Thu Apr 28 2011 16:56:42

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    <use>openr2</use>
00047  ***/
00048 
00049 #include "asterisk.h"
00050 
00051 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 307624 $")
00052 
00053 #if defined(__NetBSD__) || defined(__FreeBSD__)
00054 #include <pthread.h>
00055 #include <signal.h>
00056 #else
00057 #include <sys/signal.h>
00058 #endif
00059 #include <sys/ioctl.h>
00060 #include <math.h>
00061 #include <ctype.h>
00062 
00063 #include <dahdi/user.h>
00064 #include <dahdi/tonezone.h>
00065 
00066 #ifdef HAVE_PRI
00067 #include <libpri.h>
00068 #endif
00069 
00070 #ifdef HAVE_SS7
00071 #include <libss7.h>
00072 #endif
00073 
00074 #ifdef HAVE_OPENR2
00075 #include <openr2.h>
00076 #endif
00077 
00078 #include "asterisk/lock.h"
00079 #include "asterisk/channel.h"
00080 #include "asterisk/config.h"
00081 #include "asterisk/module.h"
00082 #include "asterisk/pbx.h"
00083 #include "asterisk/file.h"
00084 #include "asterisk/ulaw.h"
00085 #include "asterisk/alaw.h"
00086 #include "asterisk/callerid.h"
00087 #include "asterisk/adsi.h"
00088 #include "asterisk/cli.h"
00089 #include "asterisk/cdr.h"
00090 #include "asterisk/features.h"
00091 #include "asterisk/musiconhold.h"
00092 #include "asterisk/say.h"
00093 #include "asterisk/tdd.h"
00094 #include "asterisk/app.h"
00095 #include "asterisk/dsp.h"
00096 #include "asterisk/astdb.h"
00097 #include "asterisk/manager.h"
00098 #include "asterisk/causes.h"
00099 #include "asterisk/term.h"
00100 #include "asterisk/utils.h"
00101 #include "asterisk/transcap.h"
00102 #include "asterisk/stringfields.h"
00103 #include "asterisk/abstract_jb.h"
00104 #include "asterisk/smdi.h"
00105 #include "asterisk/astobj.h"
00106 #include "asterisk/event.h"
00107 #include "asterisk/devicestate.h"
00108 #include "asterisk/paths.h"
00109 
00110 /*** DOCUMENTATION
00111    <application name="DAHDISendKeypadFacility" language="en_US">
00112       <synopsis>
00113          Send digits out of band over a PRI.
00114       </synopsis>
00115       <syntax>
00116          <parameter name="digits" required="true" />
00117       </syntax>
00118       <description>
00119          <para>This application will send the given string of digits in a Keypad
00120          Facility IE over the current channel.</para>
00121       </description>
00122    </application>
00123    <application name="DAHDISendCallreroutingFacility" language="en_US">
00124       <synopsis>
00125          Send an ISDN call rerouting/deflection facility message.
00126       </synopsis>
00127       <syntax argsep=",">
00128          <parameter name="destination" required="true">
00129             <para>Destination number.</para>
00130          </parameter>
00131          <parameter name="original">
00132             <para>Original called number.</para>
00133          </parameter>
00134          <parameter name="reason">
00135             <para>Diversion reason, if not specified defaults to <literal>unknown</literal></para>
00136          </parameter>
00137       </syntax>
00138       <description>
00139          <para>This application will send an ISDN switch specific call
00140          rerouting/deflection facility message over the current channel.
00141          Supported switches depend upon the version of libpri in use.</para>
00142       </description>
00143    </application>
00144    <application name="DAHDIAcceptR2Call" language="en_US">
00145       <synopsis>
00146          Accept an R2 call if its not already accepted (you still need to answer it)
00147       </synopsis>
00148       <syntax>
00149          <parameter name="charge" required="true">
00150             <para>Yes or No.</para>
00151             <para>Whether you want to accept the call with charge or without charge.</para>
00152          </parameter>
00153       </syntax>
00154       <description>
00155          <para>This application will Accept the R2 call either with charge or no charge.</para>
00156       </description>
00157    </application>
00158  ***/
00159 
00160 #define SMDI_MD_WAIT_TIMEOUT 1500 /* 1.5 seconds */
00161 
00162 static const char *lbostr[] = {
00163 "0 db (CSU)/0-133 feet (DSX-1)",
00164 "133-266 feet (DSX-1)",
00165 "266-399 feet (DSX-1)",
00166 "399-533 feet (DSX-1)",
00167 "533-655 feet (DSX-1)",
00168 "-7.5db (CSU)",
00169 "-15db (CSU)",
00170 "-22.5db (CSU)"
00171 };
00172 
00173 /*! Global jitterbuffer configuration - by default, jb is disabled */
00174 static struct ast_jb_conf default_jbconf =
00175 {
00176    .flags = 0,
00177    .max_size = -1,
00178    .resync_threshold = -1,
00179    .impl = "",
00180    .target_extra = -1,
00181 };
00182 static struct ast_jb_conf global_jbconf;
00183 
00184 /* define this to send PRI user-user information elements */
00185 #undef SUPPORT_USERUSER
00186 
00187 /*!
00188  * \note Define ZHONE_HACK to cause us to go off hook and then back on hook when
00189  * the user hangs up to reset the state machine so ring works properly.
00190  * This is used to be able to support kewlstart by putting the zhone in
00191  * groundstart mode since their forward disconnect supervision is entirely
00192  * broken even though their documentation says it isn't and their support
00193  * is entirely unwilling to provide any assistance with their channel banks
00194  * even though their web site says they support their products for life.
00195  */
00196 /* #define ZHONE_HACK */
00197 
00198 /*! \note
00199  * Define if you want to check the hook state for an FXO (FXS signalled) interface
00200  * before dialing on it.  Certain FXO interfaces always think they're out of
00201  * service with this method however.
00202  */
00203 /* #define DAHDI_CHECK_HOOKSTATE */
00204 
00205 /*! \brief Typically, how many rings before we should send Caller*ID */
00206 #define DEFAULT_CIDRINGS 1
00207 
00208 #define CHANNEL_PSEUDO -12
00209 
00210 #define AST_LAW(p) (((p)->law == DAHDI_LAW_ALAW) ? AST_FORMAT_ALAW : AST_FORMAT_ULAW)
00211 
00212 
00213 /*! \brief Signaling types that need to use MF detection should be placed in this macro */
00214 #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))
00215 
00216 static const char tdesc[] = "DAHDI Telephony Driver"
00217 #if defined(HAVE_PRI) || defined(HAVE_SS7) || defined(HAVE_OPENR2)
00218    " w/"
00219 #endif
00220 #ifdef HAVE_PRI
00221    "PRI"
00222 #endif
00223 #ifdef HAVE_SS7
00224    #ifdef HAVE_PRI
00225    " & SS7"
00226    #else
00227    "SS7"
00228    #endif
00229 #endif
00230 #ifdef HAVE_OPENR2
00231    #if defined(HAVE_PRI) || defined(HAVE_SS7)
00232    " & MFC/R2"
00233    #else
00234    "MFC/R2"
00235    #endif
00236 #endif
00237 ;
00238 
00239 static const char config[] = "chan_dahdi.conf";
00240 
00241 #define SIG_EM    DAHDI_SIG_EM
00242 #define SIG_EMWINK   (0x0100000 | DAHDI_SIG_EM)
00243 #define SIG_FEATD (0x0200000 | DAHDI_SIG_EM)
00244 #define  SIG_FEATDMF (0x0400000 | DAHDI_SIG_EM)
00245 #define  SIG_FEATB   (0x0800000 | DAHDI_SIG_EM)
00246 #define  SIG_E911 (0x1000000 | DAHDI_SIG_EM)
00247 #define  SIG_FEATDMF_TA (0x2000000 | DAHDI_SIG_EM)
00248 #define  SIG_FGC_CAMA   (0x4000000 | DAHDI_SIG_EM)
00249 #define  SIG_FGC_CAMAMF (0x8000000 | DAHDI_SIG_EM)
00250 #define SIG_FXSLS DAHDI_SIG_FXSLS
00251 #define SIG_FXSGS DAHDI_SIG_FXSGS
00252 #define SIG_FXSKS DAHDI_SIG_FXSKS
00253 #define SIG_FXOLS DAHDI_SIG_FXOLS
00254 #define SIG_FXOGS DAHDI_SIG_FXOGS
00255 #define SIG_FXOKS DAHDI_SIG_FXOKS
00256 #define SIG_PRI      DAHDI_SIG_CLEAR
00257 #define SIG_BRI      (0x2000000 | DAHDI_SIG_CLEAR)
00258 #define SIG_BRI_PTMP (0X4000000 | DAHDI_SIG_CLEAR)
00259 #define SIG_SS7      (0x1000000 | DAHDI_SIG_CLEAR)
00260 #define SIG_MFCR2    DAHDI_SIG_CAS
00261 #define  SIG_SF      DAHDI_SIG_SF
00262 #define SIG_SFWINK   (0x0100000 | DAHDI_SIG_SF)
00263 #define SIG_SF_FEATD (0x0200000 | DAHDI_SIG_SF)
00264 #define  SIG_SF_FEATDMF (0x0400000 | DAHDI_SIG_SF)
00265 #define  SIG_SF_FEATB   (0x0800000 | DAHDI_SIG_SF)
00266 #define SIG_EM_E1 DAHDI_SIG_EM_E1
00267 #define SIG_GR303FXOKS  (0x0100000 | DAHDI_SIG_FXOKS)
00268 #define SIG_GR303FXSKS  (0x0100000 | DAHDI_SIG_FXSKS)
00269 
00270 #ifdef LOTS_OF_SPANS
00271 #define NUM_SPANS DAHDI_MAX_SPANS
00272 #else
00273 #define NUM_SPANS       32
00274 #endif
00275 #define NUM_DCHANS      4  /*!< No more than 4 d-channels */
00276 #define MAX_CHANNELS 672      /*!< No more than a DS3 per trunk group */
00277 
00278 #define CHAN_PSEUDO  -2
00279 
00280 #define DCHAN_PROVISIONED (1 << 0)
00281 #define DCHAN_NOTINALARM  (1 << 1)
00282 #define DCHAN_UP          (1 << 2)
00283 
00284 #define DCHAN_AVAILABLE (DCHAN_PROVISIONED | DCHAN_NOTINALARM | DCHAN_UP)
00285 
00286 /* Overlap dialing option types */
00287 #define DAHDI_OVERLAPDIAL_NONE 0
00288 #define DAHDI_OVERLAPDIAL_OUTGOING 1
00289 #define DAHDI_OVERLAPDIAL_INCOMING 2
00290 #define DAHDI_OVERLAPDIAL_BOTH (DAHDI_OVERLAPDIAL_INCOMING|DAHDI_OVERLAPDIAL_OUTGOING)
00291 
00292 #define CALLPROGRESS_PROGRESS    1
00293 #define CALLPROGRESS_FAX_OUTGOING   2
00294 #define CALLPROGRESS_FAX_INCOMING   4
00295 #define CALLPROGRESS_FAX      (CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING)
00296 
00297 static char defaultcic[64] = "";
00298 static char defaultozz[64] = "";
00299 
00300 static char parkinglot[AST_MAX_EXTENSION] = "";    /*!< Default parking lot for this channel */
00301 
00302 /*! Run this script when the MWI state changes on an FXO line, if mwimonitor is enabled */
00303 static char mwimonitornotify[PATH_MAX] = "";
00304 #ifndef HAVE_DAHDI_LINEREVERSE_VMWI
00305 static int  mwisend_rpas = 0;
00306 #endif
00307 
00308 static char progzone[10] = "";
00309 
00310 static int usedistinctiveringdetection = 0;
00311 static int distinctiveringaftercid = 0;
00312 
00313 static int numbufs = 4;
00314 
00315 static int mwilevel = 512;
00316 
00317 #ifdef HAVE_PRI
00318 static struct ast_channel inuse;
00319 #ifdef PRI_GETSET_TIMERS
00320 static int pritimers[PRI_MAX_TIMERS];
00321 #endif
00322 static int pridebugfd = -1;
00323 static char pridebugfilename[1024] = "";
00324 #endif
00325 
00326 /*! \brief Wait up to 16 seconds for first digit (FXO logic) */
00327 static int firstdigittimeout = 16000;
00328 
00329 /*! \brief How long to wait for following digits (FXO logic) */
00330 static int gendigittimeout = 8000;
00331 
00332 /*! \brief How long to wait for an extra digit, if there is an ambiguous match */
00333 static int matchdigittimeout = 3000;
00334 
00335 /*! \brief Protect the interface list (of dahdi_pvt's) */
00336 AST_MUTEX_DEFINE_STATIC(iflock);
00337 
00338 /* QSIG channel mapping option types */
00339 #define DAHDI_CHAN_MAPPING_PHYSICAL 0
00340 #define DAHDI_CHAN_MAPPING_LOGICAL  1
00341 
00342 
00343 static int ifcount = 0;
00344 
00345 #ifdef HAVE_PRI
00346 AST_MUTEX_DEFINE_STATIC(pridebugfdlock);
00347 #endif
00348 
00349 /*! \brief Protect the monitoring thread, so only one process can kill or start it, and not
00350    when it's doing something critical. */
00351 AST_MUTEX_DEFINE_STATIC(monlock);
00352 
00353 /*! \brief This is the thread for the monitor which checks for input on the channels
00354    which are not currently in use. */
00355 static pthread_t monitor_thread = AST_PTHREADT_NULL;
00356 static ast_cond_t ss_thread_complete;
00357 AST_MUTEX_DEFINE_STATIC(ss_thread_lock);
00358 AST_MUTEX_DEFINE_STATIC(restart_lock);
00359 static int ss_thread_count = 0;
00360 static int num_restart_pending = 0;
00361 
00362 static int restart_monitor(void);
00363 
00364 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);
00365 
00366 static int dahdi_sendtext(struct ast_channel *c, const char *text);
00367 
00368 static void mwi_event_cb(const struct ast_event *event, void *userdata)
00369 {
00370    /* This module does not handle MWI in an event-based manner.  However, it
00371     * subscribes to MWI for each mailbox that is configured so that the core
00372     * knows that we care about it.  Then, chan_dahdi will get the MWI from the
00373     * event cache instead of checking the mailbox directly. */
00374 }
00375 
00376 /*! \brief Avoid the silly dahdi_getevent which ignores a bunch of events */
00377 static inline int dahdi_get_event(int fd)
00378 {
00379    int j;
00380    if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
00381       return -1;
00382    return j;
00383 }
00384 
00385 /*! \brief Avoid the silly dahdi_waitevent which ignores a bunch of events */
00386 static inline int dahdi_wait_event(int fd)
00387 {
00388    int i, j = 0;
00389    i = DAHDI_IOMUX_SIGEVENT;
00390    if (ioctl(fd, DAHDI_IOMUX, &i) == -1)
00391       return -1;
00392    if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
00393       return -1;
00394    return j;
00395 }
00396 
00397 /*! Chunk size to read -- we use 20ms chunks to make things happy. */
00398 #define READ_SIZE 160
00399 
00400 #define MASK_AVAIL      (1 << 0) /*!< Channel available for PRI use */
00401 #define MASK_INUSE      (1 << 1) /*!< Channel currently in use */
00402 
00403 #define CALLWAITING_SILENT_SAMPLES     ((300 * 8) / READ_SIZE) /*!< 300 ms */
00404 #define CALLWAITING_REPEAT_SAMPLES     ((10000 * 8) / READ_SIZE) /*!< 10,000 ms */
00405 #define CALLWAITING_SUPPRESS_SAMPLES   ((100 * 8) / READ_SIZE) /*!< 100 ms */
00406 #define CIDCW_EXPIRE_SAMPLES        ((500 * 8) / READ_SIZE) /*!< 500 ms */
00407 #define MIN_MS_SINCE_FLASH          ((2000) )   /*!< 2000 ms */
00408 #define DEFAULT_RINGT               ((8000 * 8) / READ_SIZE) /*!< 8,000 ms */
00409 
00410 struct dahdi_pvt;
00411 
00412 /*!
00413  * \brief Configured ring timeout base.
00414  * \note Value computed from "ringtimeout" read in from chan_dahdi.conf if it exists.
00415  */
00416 static int ringt_base = DEFAULT_RINGT;
00417 
00418 #ifdef HAVE_SS7
00419 
00420 #define LINKSTATE_INALARM  (1 << 0)
00421 #define LINKSTATE_STARTING (1 << 1)
00422 #define LINKSTATE_UP    (1 << 2)
00423 #define LINKSTATE_DOWN     (1 << 3)
00424 
00425 #define SS7_NAI_DYNAMIC    -1
00426 
00427 #define LINKSET_FLAG_EXPLICITACM (1 << 0)
00428 
00429 struct dahdi_ss7 {
00430    pthread_t master;                /*!< Thread of master */
00431    ast_mutex_t lock;
00432    int fds[NUM_DCHANS];
00433    int numsigchans;
00434    int linkstate[NUM_DCHANS];
00435    int numchans;
00436    int type;
00437    enum {
00438       LINKSET_STATE_DOWN = 0,
00439       LINKSET_STATE_UP
00440    } state;
00441    char called_nai;                 /*!< Called Nature of Address Indicator */
00442    char calling_nai;                /*!< Calling Nature of Address Indicator */
00443    char internationalprefix[10];             /*!< country access code ('00' for european dialplans) */
00444    char nationalprefix[10];               /*!< area access code ('0' for european dialplans) */
00445    char subscriberprefix[20];             /*!< area access code + area code ('0'+area code for european dialplans) */
00446    char unknownprefix[20];                /*!< for unknown dialplans */
00447    struct ss7 *ss7;
00448    struct dahdi_pvt *pvts[MAX_CHANNELS];           /*!< Member channel pvt structs */
00449    int flags;                    /*!< Linkset flags */
00450 };
00451 
00452 static struct dahdi_ss7 linksets[NUM_SPANS];
00453 
00454 static int cur_ss7type = -1;
00455 static int cur_linkset = -1;
00456 static int cur_pointcode = -1;
00457 static int cur_cicbeginswith = -1;
00458 static int cur_adjpointcode = -1;
00459 static int cur_networkindicator = -1;
00460 static int cur_defaultdpc = -1;
00461 #endif /* HAVE_SS7 */
00462 
00463 #ifdef HAVE_OPENR2
00464 struct dahdi_mfcr2 {
00465    pthread_t r2master;            /*!< Thread of master */
00466    openr2_context_t *protocol_context;    /*!< OpenR2 context handle */
00467    struct dahdi_pvt *pvts[MAX_CHANNELS];     /*!< Member channel pvt structs */
00468    int numchans;                          /*!< Number of channels in this R2 block */
00469    int monitored_count;                   /*!< Number of channels being monitored */
00470 };
00471 
00472 struct dahdi_mfcr2_conf {
00473    openr2_variant_t variant;
00474    int mfback_timeout;
00475    int metering_pulse_timeout;
00476    int max_ani;
00477    int max_dnis;
00478    signed int get_ani_first:2;
00479 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
00480    signed int skip_category_request:2;
00481 #endif
00482    unsigned int call_files:1;
00483    unsigned int allow_collect_calls:1;
00484    unsigned int charge_calls:1;
00485    unsigned int accept_on_offer:1;
00486    unsigned int forced_release:1;
00487    unsigned int double_answer:1;
00488    signed int immediate_accept:2;
00489    char logdir[OR2_MAX_PATH];
00490    char r2proto_file[OR2_MAX_PATH];
00491    openr2_log_level_t loglevel;
00492    openr2_calling_party_category_t category;
00493 };
00494 
00495 /* malloc'd array of malloc'd r2links */
00496 static struct dahdi_mfcr2 **r2links;
00497 /* how many r2links have been malloc'd */
00498 static int r2links_count = 0;
00499 
00500 #endif /* HAVE_OPENR2 */
00501 
00502 #ifdef HAVE_PRI
00503 
00504 #define PVT_TO_CHANNEL(p) (((p)->prioffset) | ((p)->logicalspan << 8) | (p->pri->mastertrunkgroup ? 0x10000 : 0))
00505 #define PRI_CHANNEL(p) ((p) & 0xff)
00506 #define PRI_SPAN(p) (((p) >> 8) & 0xff)
00507 #define PRI_EXPLICIT(p) (((p) >> 16) & 0x01)
00508 
00509 /*! Call establishment life cycle level for simple comparisons. */
00510 enum dahdi_call_level {
00511    /*! Call does not exist. */
00512    DAHDI_CALL_LEVEL_IDLE,
00513    /*! Call is present but has no response yet. (SETUP) */
00514    DAHDI_CALL_LEVEL_SETUP,
00515    /*! Call is collecting digits for overlap dialing. (SETUP ACKNOWLEDGE) */
00516    DAHDI_CALL_LEVEL_OVERLAP,
00517    /*! Call routing is happening. (PROCEEDING) */
00518    DAHDI_CALL_LEVEL_PROCEEDING,
00519    /*! Called party is being alerted of the call. (ALERTING) */
00520    DAHDI_CALL_LEVEL_ALERTING,
00521    /*! Call is connected/answered. (CONNECT) */
00522    DAHDI_CALL_LEVEL_CONNECT,
00523 };
00524 
00525 struct dahdi_pri {
00526    pthread_t master;                /*!< Thread of master */
00527    ast_mutex_t lock;                /*!< Mutex */
00528    char idleext[AST_MAX_EXTENSION];          /*!< Where to idle extra calls */
00529    char idlecontext[AST_MAX_CONTEXT];           /*!< What context to use for idle */
00530    char idledial[AST_MAX_EXTENSION];            /*!< What to dial before dumping */
00531    int minunused;                   /*!< Min # of channels to keep empty */
00532    int minidle;                     /*!< Min # of "idling" calls to keep active */
00533    int nodetype;                    /*!< Node type */
00534    int switchtype;                     /*!< Type of switch to emulate */
00535    int nsf;                   /*!< Network-Specific Facilities */
00536    int dialplan;                    /*!< Dialing plan */
00537    int localdialplan;                  /*!< Local dialing plan */
00538    char internationalprefix[10];             /*!< country access code ('00' for european dialplans) */
00539    char nationalprefix[10];               /*!< area access code ('0' for european dialplans) */
00540    char localprefix[20];                  /*!< area access code + area code ('0'+area code for european dialplans) */
00541    char privateprefix[20];                /*!< for private dialplans */
00542    char unknownprefix[20];                /*!< for unknown dialplans */
00543    int dchannels[NUM_DCHANS];             /*!< What channel are the dchannels on */
00544    int trunkgroup;                     /*!< What our trunkgroup is */
00545    int mastertrunkgroup;                  /*!< What trunk group is our master */
00546    int prilogicalspan;                 /*!< Logical span number within trunk group */
00547    int numchans;                    /*!< Num of channels we represent */
00548    int overlapdial;                 /*!< In overlap dialing mode */
00549    int qsigchannelmapping;                /*!< QSIG channel mapping type */
00550    int discardremoteholdretrieval;              /*!< shall remote hold or remote retrieval notifications be discarded? */
00551    int facilityenable;                 /*!< Enable facility IEs */
00552    struct pri *dchans[NUM_DCHANS];              /*!< Actual d-channels */
00553    int dchanavail[NUM_DCHANS];               /*!< Whether each channel is available */
00554    struct pri *pri;                 /*!< Currently active D-channel */
00555    /*! \brief TRUE if to dump PRI event info (Tested but never set) */
00556    int debug;
00557    int fds[NUM_DCHANS];                /*!< FD's for d-channels */
00558    /*! \brief Value set but not used */
00559    int offset;
00560    /*! \brief Span number put into user output messages */
00561    int span;
00562    /*! \brief TRUE if span is being reset/restarted */
00563    int resetting;
00564    /*! \brief Current position during a reset (-1 if not started) */
00565    int resetpos;
00566 #ifdef HAVE_PRI_INBANDDISCONNECT
00567    unsigned int inbanddisconnect:1;          /*!< Should we support inband audio after receiving DISCONNECT? */
00568 #endif
00569    /*! TRUE if we have already whined about no D channels available. */
00570    unsigned int no_d_channels:1;
00571    time_t lastreset;                /*!< time when unused channels were last reset */
00572    long resetinterval;                 /*!< Interval (in seconds) for resetting unused channels */
00573    /*! \brief ISDN signalling type (SIG_PRI, SIG_BRI, SIG_BRI_PTMP, etc...) */
00574    int sig;
00575    struct dahdi_pvt *pvts[MAX_CHANNELS];           /*!< Member channel pvt structs */
00576    struct dahdi_pvt *crvs;                /*!< Member CRV structs */
00577    struct dahdi_pvt *crvend;                 /*!< Pointer to end of CRV structs */
00578 };
00579 
00580 
00581 static struct dahdi_pri pris[NUM_SPANS];
00582 
00583 #if 0
00584 #define DEFAULT_PRI_DEBUG (PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_STATE)
00585 #else
00586 #define DEFAULT_PRI_DEBUG 0
00587 #endif
00588 
00589 static inline void pri_rel(struct dahdi_pri *pri)
00590 {
00591    ast_mutex_unlock(&pri->lock);
00592 }
00593 
00594 #else
00595 /*! Shut up the compiler */
00596 struct dahdi_pri;
00597 #endif
00598 
00599 #define SUB_REAL  0        /*!< Active call */
00600 #define SUB_CALLWAIT 1        /*!< Call-Waiting call on hold */
00601 #define SUB_THREEWAY 2        /*!< Three-way call */
00602 
00603 /* Polarity states */
00604 #define POLARITY_IDLE   0
00605 #define POLARITY_REV    1
00606 
00607 
00608 struct distRingData {
00609    int ring[3];
00610    int range;
00611 };
00612 struct ringContextData {
00613    char contextData[AST_MAX_CONTEXT];
00614 };
00615 struct dahdi_distRings {
00616    struct distRingData ringnum[3];
00617    struct ringContextData ringContext[3];
00618 };
00619 
00620 static char *subnames[] = {
00621    "Real",
00622    "Callwait",
00623    "Threeway"
00624 };
00625 
00626 struct dahdi_subchannel {
00627    int dfd;
00628    struct ast_channel *owner;
00629    int chan;
00630    short buffer[AST_FRIENDLY_OFFSET/2 + READ_SIZE];
00631    struct ast_frame f;     /*!< One frame for each channel.  How did this ever work before? */
00632    unsigned int needringing:1;
00633    unsigned int needbusy:1;
00634    unsigned int needcongestion:1;
00635    unsigned int needcallerid:1;
00636    unsigned int needanswer:1;
00637    unsigned int needflash:1;
00638    unsigned int needhold:1;
00639    unsigned int needunhold:1;
00640    unsigned int linear:1;
00641    unsigned int inthreeway:1;
00642    struct dahdi_confinfo curconf;
00643 };
00644 
00645 #define CONF_USER_REAL     (1 << 0)
00646 #define CONF_USER_THIRDCALL   (1 << 1)
00647 
00648 #define MAX_SLAVES   4
00649 
00650 /* States for sending MWI message
00651  * First three states are required for send Ring Pulse Alert Signal
00652  */
00653 typedef enum {
00654    MWI_SEND_NULL = 0,
00655    MWI_SEND_SA,
00656    MWI_SEND_SA_WAIT,
00657    MWI_SEND_PAUSE,
00658    MWI_SEND_SPILL,
00659    MWI_SEND_CLEANUP,
00660    MWI_SEND_DONE,
00661 } mwisend_states;
00662 
00663 struct mwisend_info {
00664    struct   timeval  pause;
00665    mwisend_states    mwisend_current;
00666 };
00667 
00668 static struct dahdi_pvt {
00669    ast_mutex_t lock;             /*!< Channel private lock. */
00670    struct ast_channel *owner;       /*!< Our current active owner (if applicable) */
00671                      /*!< Up to three channels can be associated with this call */
00672 
00673    struct dahdi_subchannel sub_unused;    /*!< Just a safety precaution */
00674    struct dahdi_subchannel subs[3];       /*!< Sub-channels */
00675    struct dahdi_confinfo saveconf;        /*!< Saved conference info */
00676 
00677    struct dahdi_pvt *slaves[MAX_SLAVES];     /*!< Slave to us (follows our conferencing) */
00678    struct dahdi_pvt *master;           /*!< Master to us (we follow their conferencing) */
00679    int inconference;          /*!< If our real should be in the conference */
00680 
00681    int bufsize;                /*!< Size of the buffers */
00682    int buf_no;             /*!< Number of buffers */
00683    int buf_policy;            /*!< Buffer policy */
00684    int faxbuf_no;              /*!< Number of Fax buffers */
00685    int faxbuf_policy;          /*!< Fax buffer policy */
00686    int sig;             /*!< Signalling style */
00687    /*!
00688     * \brief Nonzero if the signaling type is sent over a radio.
00689     * \note Set to a couple of nonzero values but it is only tested like a boolean.
00690     */
00691    int radio;
00692    int outsigmod;             /*!< Outbound Signalling style (modifier) */
00693    int oprmode;               /*!< "Operator Services" mode */
00694    struct dahdi_pvt *oprpeer;          /*!< "Operator Services" peer tech_pvt ptr */
00695    /*! \brief Amount of gain to increase during caller id */
00696    float cid_rxgain;
00697    /*! \brief Rx gain set by chan_dahdi.conf */
00698    float rxgain;
00699    /*! \brief Tx gain set by chan_dahdi.conf */
00700    float txgain;
00701    int tonezone;              /*!< tone zone for this chan, or -1 for default */
00702    struct dahdi_pvt *next;          /*!< Next channel in list */
00703    struct dahdi_pvt *prev;          /*!< Prev channel in list */
00704 
00705    /* flags */
00706 
00707    /*!
00708     * \brief TRUE if ADSI (Analog Display Services Interface) available
00709     * \note Set from the "adsi" value read in from chan_dahdi.conf
00710     */
00711    unsigned int adsi:1;
00712    /*!
00713     * \brief TRUE if we can use a polarity reversal to mark when an outgoing
00714     * call is answered by the remote party.
00715     * \note Set from the "answeronpolarityswitch" value read in from chan_dahdi.conf
00716     */
00717    unsigned int answeronpolarityswitch:1;
00718    /*!
00719     * \brief TRUE if busy detection is enabled.
00720     * (Listens for the beep-beep busy pattern.)
00721     * \note Set from the "busydetect" value read in from chan_dahdi.conf
00722     */
00723    unsigned int busydetect:1;
00724    /*!
00725     * \brief TRUE if call return is enabled.
00726     * (*69, if your dialplan doesn't catch this first)
00727     * \note Set from the "callreturn" value read in from chan_dahdi.conf
00728     */
00729    unsigned int callreturn:1;
00730    /*!
00731     * \brief TRUE if busy extensions will hear the call-waiting tone
00732     * and can use hook-flash to switch between callers.
00733     * \note Can be disabled by dialing *70.
00734     * \note Initialized with the "callwaiting" value read in from chan_dahdi.conf
00735     */
00736    unsigned int callwaiting:1;
00737    /*!
00738     * \brief TRUE if send caller ID for Call Waiting
00739     * \note Set from the "callwaitingcallerid" value read in from chan_dahdi.conf
00740     */
00741    unsigned int callwaitingcallerid:1;
00742    /*!
00743     * \brief TRUE if support for call forwarding enabled.
00744     * Dial *72 to enable call forwarding.
00745     * Dial *73 to disable call forwarding.
00746     * \note Set from the "cancallforward" value read in from chan_dahdi.conf
00747     */
00748    unsigned int cancallforward:1;
00749    /*!
00750     * \brief TRUE if support for call parking is enabled.
00751     * \note Set from the "canpark" value read in from chan_dahdi.conf
00752     */
00753    unsigned int canpark:1;
00754    /*! \brief TRUE if to wait for a DTMF digit to confirm answer */
00755    unsigned int confirmanswer:1;
00756    /*!
00757     * \brief TRUE if the channel is to be destroyed on hangup.
00758     * (Used by pseudo channels.)
00759     */
00760    unsigned int destroy:1;
00761    unsigned int didtdd:1;           /*!< flag to say its done it once */
00762    /*! \brief TRUE if analog type line dialed no digits in Dial() */
00763    unsigned int dialednone:1;
00764    /*! \brief TRUE if in the process of dialing digits or sending something. */
00765    unsigned int dialing:1;
00766    /*! \brief TRUE if the transfer capability of the call is digital. */
00767    unsigned int digital:1;
00768    /*! \brief TRUE if Do-Not-Disturb is enabled. */
00769    unsigned int dnd:1;
00770    /*! \brief XXX BOOLEAN Purpose??? */
00771    unsigned int echobreak:1;
00772    /*!
00773     * \brief TRUE if echo cancellation enabled when bridged.
00774     * \note Initialized with the "echocancelwhenbridged" value read in from chan_dahdi.conf
00775     * \note Disabled if the echo canceller is not setup.
00776     */
00777    unsigned int echocanbridged:1;
00778    /*! \brief TRUE if echo cancellation is turned on. */
00779    unsigned int echocanon:1;
00780    /*! \brief TRUE if a fax tone has already been handled. */
00781    unsigned int faxhandled:1;
00782    /*! \brief TRUE if dynamic faxbuffers are configured for use, default is OFF */
00783    unsigned int usefaxbuffers:1;
00784    /*! \brief TRUE while dynamic faxbuffers are in use */
00785    unsigned int bufferoverrideinuse:1;
00786    /*! \brief TRUE if over a radio and dahdi_read() has been called. */
00787    unsigned int firstradio:1;
00788    /*!
00789     * \brief TRUE if the call will be considered "hung up" on a polarity reversal.
00790     * \note Set from the "hanguponpolarityswitch" value read in from chan_dahdi.conf
00791     */
00792    unsigned int hanguponpolarityswitch:1;
00793    /*! \brief TRUE if DTMF detection needs to be done by hardware. */
00794    unsigned int hardwaredtmf:1;
00795    /*!
00796     * \brief TRUE if the outgoing caller ID is blocked/hidden.
00797     * \note Caller ID can be disabled by dialing *67.
00798     * \note Caller ID can be enabled by dialing *82.
00799     * \note Initialized with the "hidecallerid" value read in from chan_dahdi.conf
00800     */
00801    unsigned int hidecallerid:1;
00802    /*!
00803     * \brief TRUE if hide just the name not the number for legacy PBX use.
00804     * \note Only applies to PRI channels.
00805     * \note Set from the "hidecalleridname" value read in from chan_dahdi.conf
00806     */
00807    unsigned int hidecalleridname:1;
00808    /*! \brief TRUE if DTMF detection is disabled. */
00809    unsigned int ignoredtmf:1;
00810    /*!
00811     * \brief TRUE if the channel should be answered immediately
00812     * without attempting to gather any digits.
00813     * \note Set from the "immediate" value read in from chan_dahdi.conf
00814     */
00815    unsigned int immediate:1;
00816    /*! \brief TRUE if in an alarm condition. */
00817    unsigned int inalarm:1;
00818    /*! \brief TRUE if TDD in MATE mode */
00819    unsigned int mate:1;
00820    /*! \brief TRUE if we originated the call leg. */
00821    unsigned int outgoing:1;
00822    /* unsigned int overlapdial:1;         unused and potentially confusing */
00823    /*!
00824     * \brief TRUE if busy extensions will hear the call-waiting tone
00825     * and can use hook-flash to switch between callers.
00826     * \note Set from the "callwaiting" value read in from chan_dahdi.conf
00827     */
00828    unsigned int permcallwaiting:1;
00829    /*!
00830     * \brief TRUE if the outgoing caller ID is blocked/restricted/hidden.
00831     * \note Set from the "hidecallerid" value read in from chan_dahdi.conf
00832     */
00833    unsigned int permhidecallerid:1;
00834    /*!
00835     * \brief TRUE if PRI congestion/busy indications are sent out-of-band.
00836     * \note Set from the "priindication" value read in from chan_dahdi.conf
00837     */
00838    unsigned int priindication_oob:1;
00839    /*!
00840     * \brief TRUE if PRI B channels are always exclusively selected.
00841     * \note Set from the "priexclusive" value read in from chan_dahdi.conf
00842     */
00843    unsigned int priexclusive:1;
00844    /*!
00845     * \brief TRUE if we will pulse dial.
00846     * \note Set from the "pulsedial" value read in from chan_dahdi.conf
00847     */
00848    unsigned int pulse:1;
00849    /*! \brief TRUE if a pulsed digit was detected. (Pulse dial phone detected) */
00850    unsigned int pulsedial:1;
00851    unsigned int restartpending:1;      /*!< flag to ensure counted only once for restart */
00852    /*!
00853     * \brief TRUE if caller ID is restricted.
00854     * \note Set but not used.  Should be deleted.  Redundant with permhidecallerid.
00855     * \note Set from the "restrictcid" value read in from chan_dahdi.conf
00856     */
00857    unsigned int restrictcid:1;
00858    /*!
00859     * \brief TRUE if three way calling is enabled
00860     * \note Set from the "threewaycalling" value read in from chan_dahdi.conf
00861     */
00862    unsigned int threewaycalling:1;
00863    /*!
00864     * \brief TRUE if call transfer is enabled
00865     * \note For FXS ports (either direct analog or over T1/E1):
00866     *   Support flash-hook call transfer
00867     * \note For digital ports using ISDN PRI protocols:
00868     *   Support switch-side transfer (called 2BCT, RLT or other names)
00869     * \note Set from the "transfer" value read in from chan_dahdi.conf
00870     */
00871    unsigned int transfer:1;
00872    /*!
00873     * \brief TRUE if caller ID is used on this channel.
00874     * \note PRI and SS7 spans will save caller ID from the networking peer.
00875     * \note FXS ports will generate the caller ID spill.
00876     * \note FXO ports will listen for the caller ID spill.
00877     * \note Set from the "usecallerid" value read in from chan_dahdi.conf
00878     */
00879    unsigned int use_callerid:1;
00880    /*!
00881     * \brief TRUE if we will use the calling presentation setting
00882     * from the Asterisk channel for outgoing calls.
00883     * \note Only applies to PRI and SS7 channels.
00884     * \note Set from the "usecallingpres" value read in from chan_dahdi.conf
00885     */
00886    unsigned int use_callingpres:1;
00887    /*!
00888     * \brief TRUE if distinctive rings are to be detected.
00889     * \note For FXO lines
00890     * \note Set indirectly from the "usedistinctiveringdetection" value read in from chan_dahdi.conf
00891     */
00892    unsigned int usedistinctiveringdetection:1;
00893    /*!
00894     * \brief TRUE if we should use the callerid from incoming call on dahdi transfer.
00895     * \note Set from the "useincomingcalleridondahditransfer" value read in from chan_dahdi.conf
00896     */
00897    unsigned int dahditrcallerid:1;
00898    /*!
00899     * \brief TRUE if allowed to flash-transfer to busy channels.
00900     * \note Set from the "transfertobusy" value read in from chan_dahdi.conf
00901     */
00902    unsigned int transfertobusy:1;
00903    /*!
00904     * \brief TRUE if the FXO port monitors for neon type MWI indications from the other end.
00905     * \note Set if the "mwimonitor" value read in contains "neon" from chan_dahdi.conf
00906     */
00907    unsigned int mwimonitor_neon:1;
00908    /*!
00909     * \brief TRUE if the FXO port monitors for fsk type MWI indications from the other end.
00910     * \note Set if the "mwimonitor" value read in contains "fsk" from chan_dahdi.conf
00911     */
00912    unsigned int mwimonitor_fsk:1;
00913    /*!
00914     * \brief TRUE if the FXO port monitors for rpas precursor to fsk MWI indications from the other end.
00915     * \note RPAS - Ring Pulse Alert Signal
00916     * \note Set if the "mwimonitor" value read in contains "rpas" from chan_dahdi.conf
00917     */
00918    unsigned int mwimonitor_rpas:1;
00919    /*! \brief TRUE if an MWI monitor thread is currently active */
00920    unsigned int mwimonitoractive:1;
00921    /*! \brief TRUE if a MWI message sending thread is active */
00922    unsigned int mwisendactive:1;
00923    /*!
00924     * \brief TRUE if channel is out of reset and ready
00925     * \note Set but not used.
00926     */
00927    unsigned int inservice:1;
00928    /*!
00929     * \brief TRUE if the channel is locally blocked.
00930     * \note Applies to SS7 channels.
00931     */
00932    unsigned int locallyblocked:1;
00933    /*!
00934     * \brief TRUE if the channel is remotely blocked.
00935     * \note Applies to SS7 channels.
00936     */
00937    unsigned int remotelyblocked:1;
00938    /*!
00939     * \brief TRUE if SMDI (Simplified Message Desk Interface) is enabled
00940     * \note Set from the "usesmdi" value read in from chan_dahdi.conf
00941     */
00942    unsigned int use_smdi:1;
00943 #if defined(HAVE_PRI) || defined(HAVE_SS7)
00944    /*!
00945     * \brief XXX BOOLEAN Purpose???
00946     * \note Applies to SS7 channels.
00947     */
00948    unsigned int rlt:1;
00949    /*! \brief TRUE if the call has already gone/hungup */
00950    unsigned int alreadyhungup:1;
00951    /*!
00952     * \brief TRUE if this is an idle call
00953     * \note Applies to PRI channels.
00954     */
00955    unsigned int isidlecall:1;
00956    /*! \brief TRUE if the call has seen inband-information progress through the network. */
00957    unsigned int progress:1;
00958    /*!
00959     * \brief TRUE if this channel is being reset/restarted
00960     * \note Applies to PRI channels.
00961     */
00962    unsigned int resetting:1;
00963 
00964    /*! Call establishment life cycle level for simple comparisons. */
00965    enum dahdi_call_level call_level;
00966 #endif
00967    struct mwisend_info mwisend_data;
00968    /*! \brief The serial port to listen for SMDI data on */
00969    struct ast_smdi_interface *smdi_iface;
00970 
00971    /*! \brief Distinctive Ring data */
00972    struct dahdi_distRings drings;
00973 
00974    /*!
00975     * \brief The configured context for incoming calls.
00976     * \note The "context" string read in from chan_dahdi.conf
00977     */
00978    char context[AST_MAX_CONTEXT];
00979    /*!
00980     * \brief Saved context string.
00981     */
00982    char defcontext[AST_MAX_CONTEXT];
00983    /*! \brief Extension to use in the dialplan. */
00984    char exten[AST_MAX_EXTENSION];
00985    /*!
00986     * \brief Language configured for calls.
00987     * \note The "language" string read in from chan_dahdi.conf
00988     */
00989    char language[MAX_LANGUAGE];
00990    /*!
00991     * \brief The configured music-on-hold class to use for calls.
00992     * \note The "musicclass" or "mohinterpret" or "musiconhold" string read in from chan_dahdi.conf
00993     */
00994    char mohinterpret[MAX_MUSICCLASS];
00995    /*!
00996     * \brief Suggested music-on-hold class for peer channel to use for calls.
00997     * \note The "mohsuggest" string read in from chan_dahdi.conf
00998     */
00999    char mohsuggest[MAX_MUSICCLASS];
01000    char parkinglot[AST_MAX_EXTENSION]; /*!< Parking lot for this channel */
01001 #if defined(PRI_ANI) || defined(HAVE_SS7)
01002    /*! \brief Automatic Number Identification number (Alternate PRI caller ID number) */
01003    char cid_ani[AST_MAX_EXTENSION];
01004 #endif
01005    /*! \brief Automatic Number Identification code from PRI */
01006    int cid_ani2;
01007    /*! \brief Caller ID number from an incoming call. */
01008    char cid_num[AST_MAX_EXTENSION];
01009    /*! \brief Caller ID Q.931 TON/NPI field values.  Set by PRI. Zero otherwise. */
01010    int cid_ton;
01011    /*! \brief Caller ID name from an incoming call. */
01012    char cid_name[AST_MAX_EXTENSION];
01013    /*! \brief Last Caller ID number from an incoming call. */
01014    char lastcid_num[AST_MAX_EXTENSION];
01015    /*! \brief Last Caller ID name from an incoming call. */
01016    char lastcid_name[AST_MAX_EXTENSION];
01017    char *origcid_num;            /*!< malloced original callerid */
01018    char *origcid_name;           /*!< malloced original callerid */
01019    /*! \brief Call waiting number. */
01020    char callwait_num[AST_MAX_EXTENSION];
01021    /*! \brief Call waiting name. */
01022    char callwait_name[AST_MAX_EXTENSION];
01023    /*! \brief Redirecting Directory Number Information Service (RDNIS) number */
01024    char rdnis[AST_MAX_EXTENSION];
01025    /*! \brief Dialed Number Identifier */
01026    char dnid[AST_MAX_EXTENSION];
01027    /*!
01028     * \brief Bitmapped groups this belongs to.
01029     * \note The "group" bitmapped group string read in from chan_dahdi.conf
01030     */
01031    ast_group_t group;
01032    /*! \brief Active PCM encoding format: DAHDI_LAW_ALAW or DAHDI_LAW_MULAW */
01033    int law;
01034    int confno;             /*!< Our conference */
01035    int confusers;             /*!< Who is using our conference */
01036    int propconfno;               /*!< Propagated conference number */
01037    /*!
01038     * \brief Bitmapped call groups this belongs to.
01039     * \note The "callgroup" bitmapped group string read in from chan_dahdi.conf
01040     */
01041    ast_group_t callgroup;
01042    /*!
01043     * \brief Bitmapped pickup groups this belongs to.
01044     * \note The "pickupgroup" bitmapped group string read in from chan_dahdi.conf
01045     */
01046    ast_group_t pickupgroup;
01047    /*!
01048     * \brief Channel variable list with associated values to set when a channel is created.
01049     * \note The "setvar" strings read in from chan_dahdi.conf
01050     */
01051    struct ast_variable *vars;
01052    int channel;               /*!< Channel Number or CRV */
01053    int span;               /*!< Span number */
01054    time_t guardtime;          /*!< Must wait this much time before using for new call */
01055    int cid_signalling;           /*!< CID signalling type bell202 or v23 */
01056    int cid_start;             /*!< CID start indicator, polarity or ring */
01057    int callingpres;           /*!< The value of calling presentation that we're going to use when placing a PRI call */
01058    int callwaitingrepeat;           /*!< How many samples to wait before repeating call waiting */
01059    int cidcwexpire;           /*!< When to stop waiting for CID/CW CAS response (In samples) */
01060    int cid_suppress_expire;      /*!< How many samples to suppress after a CID spill. */
01061    /*! \brief Analog caller ID waveform sample buffer */
01062    unsigned char *cidspill;
01063    /*! \brief Position in the cidspill buffer to send out next. */
01064    int cidpos;
01065    /*! \brief Length of the cidspill buffer containing samples. */
01066    int cidlen;
01067    /*! \brief Ring timeout timer?? */
01068    int ringt;
01069    /*!
01070     * \brief Ring timeout base.
01071     * \note Value computed indirectly from "ringtimeout" read in from chan_dahdi.conf
01072     */
01073    int ringt_base;
01074    /*!
01075     * \brief Number of most significant digits/characters to strip from the dialed number.
01076     * \note Feature is deprecated.  Use dialplan logic.
01077     * \note The characters are stripped before the PRI TON/NPI prefix
01078     * characters are processed.
01079     */
01080    int stripmsd;
01081    /*!
01082     * \brief TRUE if Call Waiting (CW) CPE Alert Signal (CAS) is being sent.
01083     * \note
01084     * After CAS is sent, the call waiting caller id will be sent if the phone
01085     * gives a positive reply.
01086     */
01087    int callwaitcas;
01088    /*! \brief Number of call waiting rings. */
01089    int callwaitrings;
01090    /*! \brief Echo cancel parameters. */
01091    struct {
01092       struct dahdi_echocanparams head;
01093       struct dahdi_echocanparam params[DAHDI_MAX_ECHOCANPARAMS];
01094    } echocancel;
01095    /*!
01096     * \brief Echo training time. 0 = disabled
01097     * \note Set from the "echotraining" value read in from chan_dahdi.conf
01098     */
01099    int echotraining;
01100    /*! \brief Filled with 'w'.  XXX Purpose?? */
01101    char echorest[20];
01102    /*!
01103     * \brief Number of times to see "busy" tone before hanging up.
01104     * \note Set from the "busycount" value read in from chan_dahdi.conf
01105     */
01106    int busycount;
01107    /*!
01108     * \brief Length of "busy" tone on time.
01109     * \note Set from the "busypattern" value read in from chan_dahdi.conf
01110     */
01111    int busy_tonelength;
01112    /*!
01113     * \brief Length of "busy" tone off time.
01114     * \note Set from the "busypattern" value read in from chan_dahdi.conf
01115     */
01116    int busy_quietlength;
01117    /*!
01118     * \brief Bitmapped call progress detection flags. CALLPROGRESS_xxx values.
01119     * \note Bits set from the "callprogress" and "faxdetect" values read in from chan_dahdi.conf
01120     */
01121    int callprogress;
01122    /*!
01123     * \brief Number of milliseconds to wait for dialtone.
01124     * \note Set from the "waitfordialtone" value read in from chan_dahdi.conf
01125     */
01126    int waitfordialtone;
01127    struct timeval waitingfordt;        /*!< Time we started waiting for dialtone */
01128    struct timeval flashtime;        /*!< Last flash-hook time */
01129    /*! \brief Opaque DSP configuration structure. */
01130    struct ast_dsp *dsp;
01131    //int cref;             /*!< Call reference number (Not used) */
01132    /*! \brief DAHDI dial operation command struct for ioctl() call. */
01133    struct dahdi_dialoperation dop;
01134    int whichwink;             /*!< SIG_FEATDMF_TA Which wink are we on? */
01135    /*! \brief Second part of SIG_FEATDMF_TA wink operation. */
01136    char finaldial[64];
01137    char accountcode[AST_MAX_ACCOUNT_CODE];      /*!< Account code */
01138    int amaflags;              /*!< AMA Flags */
01139    struct tdd_state *tdd;           /*!< TDD flag */
01140    /*! \brief Accumulated call forwarding number. */
01141    char call_forward[AST_MAX_EXTENSION];
01142    /*!
01143     * \brief Voice mailbox location.
01144     * \note Set from the "mailbox" string read in from chan_dahdi.conf
01145     */
01146    char mailbox[AST_MAX_EXTENSION];
01147    /*! \brief Opaque event subscription parameters for message waiting indication support. */
01148    struct ast_event_sub *mwi_event_sub;
01149    /*! \brief Delayed dialing for E911.  Overlap digits for ISDN. */
01150    char dialdest[256];
01151    /*! \brief Time the interface went on-hook. */
01152    int onhooktime;
01153    /*! \brief TRUE if the FXS port is off-hook */
01154    int fxsoffhookstate;
01155    /*! \brief -1 = unknown, 0 = no messages, 1 = new messages available */
01156    int msgstate;
01157 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
01158    struct dahdi_vmwi_info mwisend_setting;            /*!< Which VMWI methods to use */
01159    unsigned int mwisend_fsk: 1;     /*! Variable for enabling FSK MWI handling in chan_dahdi */
01160    unsigned int mwisend_rpas:1;     /*! Variable for enabling Ring Pulse Alert before MWI FSK Spill */
01161 #endif
01162    int distinctivering;          /*!< Which distinctivering to use */
01163    int cidrings;              /*!< Which ring to deliver CID on */
01164    int dtmfrelax;             /*!< whether to run in relaxed DTMF mode */
01165    /*! \brief Holding place for event injected from outside normal operation. */
01166    int fake_event;
01167    /*!
01168     * \brief Minimal time period (ms) between the answer polarity
01169     * switch and hangup polarity switch.
01170     */
01171    int polarityonanswerdelay;
01172    /*! \brief Start delay time if polarityonanswerdelay is nonzero. */
01173    struct timeval polaritydelaytv;
01174    /*!
01175     * \brief Send caller ID after this many rings.
01176     * \note Set from the "sendcalleridafter" value read in from chan_dahdi.conf
01177     */
01178    int sendcalleridafter;
01179 #ifdef HAVE_PRI
01180    /*! \brief DAHDI PRI control parameters */
01181    struct dahdi_pri *pri;
01182    /*! \brief XXX Purpose??? */
01183    struct dahdi_pvt *bearer;
01184    /*! \brief XXX Purpose??? */
01185    struct dahdi_pvt *realcall;
01186    /*! \brief Opaque libpri call control structure */
01187    q931_call *call;
01188    /*! \brief Channel number in span. */
01189    int prioffset;
01190    /*! \brief Logical span number within trunk group */
01191    int logicalspan;
01192 #endif
01193    /*! \brief Current line interface polarity. POLARITY_IDLE, POLARITY_REV */
01194    int polarity;
01195    /*! \brief DSP feature flags: DSP_FEATURE_xxx */
01196    int dsp_features;
01197 #ifdef HAVE_SS7
01198    /*! \brief SS7 control parameters */
01199    struct dahdi_ss7 *ss7;
01200    /*! \brief Opaque libss7 call control structure */
01201    struct isup_call *ss7call;
01202    char charge_number[50];
01203    char gen_add_number[50];
01204    char gen_dig_number[50];
01205    char orig_called_num[50];
01206    char redirecting_num[50];
01207    char generic_name[50];
01208    unsigned char gen_add_num_plan;
01209    unsigned char gen_add_nai;
01210    unsigned char gen_add_pres_ind;
01211    unsigned char gen_add_type;
01212    unsigned char gen_dig_type;
01213    unsigned char gen_dig_scheme;
01214    char jip_number[50];
01215    unsigned char lspi_type;
01216    unsigned char lspi_scheme;
01217    unsigned char lspi_context;
01218    char lspi_ident[50];
01219    unsigned int call_ref_ident;
01220    unsigned int call_ref_pc;
01221    unsigned char calling_party_cat;
01222    int transcap;
01223    int cic;                   /*!< CIC associated with channel */
01224    unsigned int dpc;                /*!< CIC's DPC */
01225    unsigned int loopedback:1;
01226 #endif
01227 #ifdef HAVE_OPENR2
01228    struct dahdi_mfcr2 *mfcr2;
01229    openr2_chan_t *r2chan;
01230    openr2_calling_party_category_t mfcr2_recvd_category;
01231    openr2_calling_party_category_t mfcr2_category;
01232    int mfcr2_dnis_index;
01233    int mfcr2_ani_index;
01234    int mfcr2call:1;
01235    int mfcr2_answer_pending:1;
01236    int mfcr2_charge_calls:1;
01237    int mfcr2_allow_collect_calls:1;
01238    int mfcr2_forced_release:1;
01239    int mfcr2_dnis_matched:1;
01240    int mfcr2_call_accepted:1;
01241    int mfcr2_progress:1;
01242    int mfcr2_accept_on_offer:1;
01243 #endif
01244    /*! \brief DTMF digit in progress.  0 when no digit in progress. */
01245    char begindigit;
01246    /*! \brief TRUE if confrence is muted. */
01247    int muting;
01248 } *iflist = NULL, *ifend = NULL;
01249 
01250 /*! \brief Channel configuration from chan_dahdi.conf .
01251  * This struct is used for parsing the [channels] section of chan_dahdi.conf.
01252  * Generally there is a field here for every possible configuration item.
01253  *
01254  * The state of fields is saved along the parsing and whenever a 'channel'
01255  * statement is reached, the current dahdi_chan_conf is used to configure the
01256  * channel (struct dahdi_pvt)
01257  *
01258  * \see dahdi_chan_init for the default values.
01259  */
01260 struct dahdi_chan_conf {
01261    struct dahdi_pvt chan;
01262 #ifdef HAVE_PRI
01263    struct dahdi_pri pri;
01264 #endif
01265 
01266 #ifdef HAVE_SS7
01267    struct dahdi_ss7 ss7;
01268 #endif
01269 
01270 #ifdef HAVE_OPENR2
01271    struct dahdi_mfcr2_conf mfcr2;
01272 #endif
01273    struct dahdi_params timing;
01274    int is_sig_auto; /*!< Use channel signalling from DAHDI? */
01275 
01276    /*!
01277     * \brief The serial port to listen for SMDI data on
01278     * \note Set from the "smdiport" string read in from chan_dahdi.conf
01279     */
01280    char smdi_port[SMDI_MAX_FILENAME_LEN];
01281 };
01282 
01283 /*! returns a new dahdi_chan_conf with default values (by-value) */
01284 static struct dahdi_chan_conf dahdi_chan_conf_default(void)
01285 {
01286    /* recall that if a field is not included here it is initialized
01287     * to 0 or equivalent
01288     */
01289    struct dahdi_chan_conf conf = {
01290 #ifdef HAVE_PRI
01291       .pri = {
01292          .nsf = PRI_NSF_NONE,
01293          .switchtype = PRI_SWITCH_NI2,
01294          .dialplan = PRI_UNKNOWN + 1,
01295          .localdialplan = PRI_NATIONAL_ISDN + 1,
01296          .nodetype = PRI_CPE,
01297          .qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL,
01298 
01299          .minunused = 2,
01300          .idleext = "",
01301          .idledial = "",
01302          .internationalprefix = "",
01303          .nationalprefix = "",
01304          .localprefix = "",
01305          .privateprefix = "",
01306          .unknownprefix = "",
01307          .resetinterval = -1,
01308       },
01309 #endif
01310 #ifdef HAVE_SS7
01311       .ss7 = {
01312          .called_nai = SS7_NAI_NATIONAL,
01313          .calling_nai = SS7_NAI_NATIONAL,
01314          .internationalprefix = "",
01315          .nationalprefix = "",
01316          .subscriberprefix = "",
01317          .unknownprefix = ""
01318       },
01319 #endif
01320 #ifdef HAVE_OPENR2
01321       .mfcr2 = {
01322          .variant = OR2_VAR_ITU,
01323          .mfback_timeout = -1,
01324          .metering_pulse_timeout = -1,
01325          .max_ani = 10,
01326          .max_dnis = 4,
01327          .get_ani_first = -1,
01328 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
01329          .skip_category_request = -1,
01330 #endif
01331          .call_files = 0,
01332          .allow_collect_calls = 0,
01333          .charge_calls = 1,
01334          .accept_on_offer = 1,
01335          .forced_release = 0,
01336          .double_answer = 0,
01337          .immediate_accept = -1,
01338          .logdir = "",
01339          .r2proto_file = "",
01340          .loglevel = OR2_LOG_ERROR | OR2_LOG_WARNING,
01341          .category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER
01342       },
01343 #endif
01344       .chan = {
01345          .context = "default",
01346          .cid_num = "",
01347          .cid_name = "",
01348          .mohinterpret = "default",
01349          .mohsuggest = "",
01350          .parkinglot = "",
01351          .transfertobusy = 1,
01352 
01353          .cid_signalling = CID_SIG_BELL,
01354          .cid_start = CID_START_RING,
01355          .dahditrcallerid = 0,
01356          .use_callerid = 1,
01357          .sig = -1,
01358          .outsigmod = -1,
01359 
01360          .cid_rxgain = +5.0,
01361 
01362          .tonezone = -1,
01363 
01364          .echocancel.head.tap_length = 1,
01365 
01366          .busycount = 3,
01367 
01368          .accountcode = "",
01369 
01370          .mailbox = "",
01371 
01372 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
01373          .mwisend_fsk = 1,
01374 #endif
01375          .polarityonanswerdelay = 600,
01376 
01377          .sendcalleridafter = DEFAULT_CIDRINGS,
01378 
01379          .buf_policy = DAHDI_POLICY_IMMEDIATE,
01380          .buf_no = numbufs,
01381          .usefaxbuffers = 0,
01382          .faxbuf_policy = DAHDI_POLICY_IMMEDIATE,
01383          .faxbuf_no = numbufs,
01384       },
01385       .timing = {
01386          .prewinktime = -1,
01387          .preflashtime = -1,
01388          .winktime = -1,
01389          .flashtime = -1,
01390          .starttime = -1,
01391          .rxwinktime = -1,
01392          .rxflashtime = -1,
01393          .debouncetime = -1
01394       },
01395       .is_sig_auto = 1,
01396       .smdi_port = "/dev/ttyS0",
01397    };
01398 
01399    return conf;
01400 }
01401 
01402 
01403 static struct ast_channel *dahdi_request(const char *type, int format, void *data, int *cause);
01404 static int dahdi_digit_begin(struct ast_channel *ast, char digit);
01405 static int dahdi_digit_end(struct ast_channel *ast, char digit, unsigned int duration);
01406 static int dahdi_sendtext(struct ast_channel *c, const char *text);
01407 static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout);
01408 static int dahdi_hangup(struct ast_channel *ast);
01409 static int dahdi_answer(struct ast_channel *ast);
01410 static struct ast_frame *dahdi_read(struct ast_channel *ast);
01411 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame);
01412 static struct ast_frame *dahdi_exception(struct ast_channel *ast);
01413 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen);
01414 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
01415 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen);
01416 static int dahdi_func_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len);
01417 static int dahdi_func_write(struct ast_channel *chan, const char *function, char *data, const char *value);
01418 static struct dahdi_pvt *handle_init_event(struct dahdi_pvt *i, int event);
01419 
01420 static const struct ast_channel_tech dahdi_tech = {
01421    .type = "DAHDI",
01422    .description = tdesc,
01423    .capabilities = AST_FORMAT_SLINEAR | AST_FORMAT_ULAW | AST_FORMAT_ALAW,
01424    .requester = dahdi_request,
01425    .send_digit_begin = dahdi_digit_begin,
01426    .send_digit_end = dahdi_digit_end,
01427    .send_text = dahdi_sendtext,
01428    .call = dahdi_call,
01429    .hangup = dahdi_hangup,
01430    .answer = dahdi_answer,
01431    .read = dahdi_read,
01432    .write = dahdi_write,
01433    .bridge = dahdi_bridge,
01434    .exception = dahdi_exception,
01435    .indicate = dahdi_indicate,
01436    .fixup = dahdi_fixup,
01437    .setoption = dahdi_setoption,
01438    .func_channel_read = dahdi_func_read,
01439    .func_channel_write = dahdi_func_write,
01440 };
01441 
01442 #ifdef HAVE_PRI
01443 #define GET_CHANNEL(p) ((p)->bearer ? (p)->bearer->channel : p->channel)
01444 #else
01445 #define GET_CHANNEL(p) ((p)->channel)
01446 #endif
01447 
01448 struct dahdi_pvt *round_robin[32];
01449 
01450 #if defined(HAVE_PRI)
01451 static inline int pri_grab(struct dahdi_pvt *pvt, struct dahdi_pri *pri)
01452 {
01453    int res;
01454    /* Grab the lock first */
01455    do {
01456       res = ast_mutex_trylock(&pri->lock);
01457       if (res) {
01458          DEADLOCK_AVOIDANCE(&pvt->lock);
01459       }
01460    } while (res);
01461    /* Then break the poll */
01462    if (pri->master != AST_PTHREADT_NULL)
01463       pthread_kill(pri->master, SIGURG);
01464    return 0;
01465 }
01466 #endif   /* defined(HAVE_PRI) */
01467 
01468 #if defined(HAVE_SS7)
01469 static inline void ss7_rel(struct dahdi_ss7 *ss7)
01470 {
01471    ast_mutex_unlock(&ss7->lock);
01472 }
01473 #endif   /* defined(HAVE_SS7) */
01474 
01475 #if defined(HAVE_SS7)
01476 static inline int ss7_grab(struct dahdi_pvt *pvt, struct dahdi_ss7 *pri)
01477 {
01478    int res;
01479    /* Grab the lock first */
01480    do {
01481       res = ast_mutex_trylock(&pri->lock);
01482       if (res) {
01483          DEADLOCK_AVOIDANCE(&pvt->lock);
01484       }
01485    } while (res);
01486    /* Then break the poll */
01487    if (pri->master != AST_PTHREADT_NULL)
01488       pthread_kill(pri->master, SIGURG);
01489    return 0;
01490 }
01491 #endif   /* defined(HAVE_SS7) */
01492 #define NUM_CADENCE_MAX 25
01493 static int num_cadence = 4;
01494 static int user_has_defined_cadences = 0;
01495 
01496 static struct dahdi_ring_cadence cadences[NUM_CADENCE_MAX] = {
01497    { { 125, 125, 2000, 4000 } },       /*!< Quick chirp followed by normal ring */
01498    { { 250, 250, 500, 1000, 250, 250, 500, 4000 } }, /*!< British style ring */
01499    { { 125, 125, 125, 125, 125, 4000 } }, /*!< Three short bursts */
01500    { { 1000, 500, 2500, 5000 } },   /*!< Long ring */
01501 };
01502 
01503 /*! \brief cidrings says in which pause to transmit the cid information, where the first pause
01504  * is 1, the second pause is 2 and so on.
01505  */
01506 
01507 static int cidrings[NUM_CADENCE_MAX] = {
01508    2,                            /*!< Right after first long ring */
01509    4,                            /*!< Right after long part */
01510    3,                            /*!< After third chirp */
01511    2,                            /*!< Second spell */
01512 };
01513 
01514 /* ETSI EN300 659-1 specifies the ring pulse between 200 and 300 mS */
01515 static struct dahdi_ring_cadence AS_RP_cadence = {{250, 10000}};
01516 
01517 #define ISTRUNK(p) ((p->sig == SIG_FXSLS) || (p->sig == SIG_FXSKS) || \
01518          (p->sig == SIG_FXSGS) || (p->sig == SIG_PRI))
01519 
01520 #define CANBUSYDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */)
01521 #define CANPROGRESSDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */)
01522 
01523 #define dahdi_get_index(ast, p, nullok)   _dahdi_get_index(ast, p, nullok, __PRETTY_FUNCTION__, __LINE__)
01524 static int _dahdi_get_index(struct ast_channel *ast, struct dahdi_pvt *p, int nullok, const char *fname, unsigned long line)
01525 {
01526    int res;
01527    if (p->subs[SUB_REAL].owner == ast)
01528       res = 0;
01529    else if (p->subs[SUB_CALLWAIT].owner == ast)
01530       res = 1;
01531    else if (p->subs[SUB_THREEWAY].owner == ast)
01532       res = 2;
01533    else {
01534       res = -1;
01535       if (!nullok)
01536          ast_log(LOG_WARNING,
01537             "Unable to get index for '%s' on channel %d (%s(), line %lu)\n",
01538             ast ? ast->name : "", p->channel, fname, line);
01539    }
01540    return res;
01541 }
01542 
01543 /*!
01544  * \internal
01545  * \brief Obtain the specified subchannel owner lock if the owner exists.
01546  *
01547  * \param pvt Channel private struct.
01548  * \param sub_idx Subchannel owner to lock.
01549  *
01550  * \note Assumes the pvt->lock is already obtained.
01551  *
01552  * \note
01553  * Because deadlock avoidance may have been necessary, you need to confirm
01554  * the state of things before continuing.
01555  *
01556  * \return Nothing
01557  */
01558 static void dahdi_lock_sub_owner(struct dahdi_pvt *pvt, int sub_idx)
01559 {
01560    for (;;) {
01561       if (!pvt->subs[sub_idx].owner) {
01562          /* No subchannel owner pointer */
01563          break;
01564       }
01565       if (!ast_channel_trylock(pvt->subs[sub_idx].owner)) {
01566          /* Got subchannel owner lock */
01567          break;
01568       }
01569       /* We must unlock the private to avoid the possibility of a deadlock */
01570       DEADLOCK_AVOIDANCE(&pvt->lock);
01571    }
01572 }
01573 
01574 static void wakeup_sub(struct dahdi_pvt *p, int a, struct dahdi_pri *pri)
01575 {
01576 #ifdef HAVE_PRI
01577    if (pri)
01578       ast_mutex_unlock(&pri->lock);
01579 #endif
01580    dahdi_lock_sub_owner(p, a);
01581    if (p->subs[a].owner) {
01582       ast_queue_frame(p->subs[a].owner, &ast_null_frame);
01583       ast_channel_unlock(p->subs[a].owner);
01584    }
01585 #ifdef HAVE_PRI
01586    if (pri)
01587       ast_mutex_lock(&pri->lock);
01588 #endif
01589 }
01590 
01591 static void dahdi_queue_frame(struct dahdi_pvt *p, struct ast_frame *f, void *data)
01592 {
01593 #ifdef HAVE_PRI
01594    struct dahdi_pri *pri = (struct dahdi_pri*) data;
01595 #endif
01596 #ifdef HAVE_SS7
01597    struct dahdi_ss7 *ss7 = (struct dahdi_ss7*) data;
01598 #endif
01599    /* We must unlock the PRI to avoid the possibility of a deadlock */
01600 #if defined(HAVE_PRI) || defined(HAVE_SS7)
01601    if (data) {
01602       switch (p->sig) {
01603 #ifdef HAVE_PRI
01604       case SIG_BRI:
01605       case SIG_BRI_PTMP:
01606       case SIG_PRI:
01607          ast_mutex_unlock(&pri->lock);
01608          break;
01609 #endif
01610 #ifdef HAVE_SS7
01611       case SIG_SS7:
01612          ast_mutex_unlock(&ss7->lock);
01613          break;
01614 #endif
01615       default:
01616          break;
01617       }
01618    }
01619 #endif
01620    for (;;) {
01621       if (p->owner) {
01622          if (ast_channel_trylock(p->owner)) {
01623             DEADLOCK_AVOIDANCE(&p->lock);
01624          } else {
01625             ast_queue_frame(p->owner, f);
01626             ast_channel_unlock(p->owner);
01627             break;
01628          }
01629       } else
01630          break;
01631    }
01632 #if defined(HAVE_PRI) || defined(HAVE_SS7)
01633    if (data) {
01634       switch (p->sig) {
01635 #ifdef HAVE_PRI
01636       case SIG_BRI:
01637       case SIG_BRI_PTMP:
01638       case SIG_PRI:
01639          ast_mutex_lock(&pri->lock);
01640          break;
01641 #endif
01642 #ifdef HAVE_SS7
01643       case SIG_SS7:
01644          ast_mutex_lock(&ss7->lock);
01645          break;
01646 #endif
01647       default:
01648          break;
01649       }
01650    }
01651 #endif
01652 }
01653 
01654 static struct ast_channel *dahdi_new(struct dahdi_pvt *, int, int, int, int, int);
01655 #ifdef HAVE_OPENR2
01656 
01657 static int dahdi_r2_answer(struct dahdi_pvt *p)
01658 {
01659    int res = 0;
01660    /* openr2 1.1.0 and older does not even define OR2_LIB_INTERFACE
01661    * and does not has support for openr2_chan_answer_call_with_mode
01662    *  */
01663 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
01664    const char *double_answer = pbx_builtin_getvar_helper(p->owner, "MFCR2_DOUBLE_ANSWER");
01665    int wants_double_answer = ast_true(double_answer) ? 1 : 0;
01666    if (!double_answer) {
01667       /* this still can result in double answer if the channel context
01668       * was configured that way */
01669       res = openr2_chan_answer_call(p->r2chan);
01670    } else if (wants_double_answer) {
01671       res = openr2_chan_answer_call_with_mode(p->r2chan, OR2_ANSWER_DOUBLE);
01672    } else {
01673       res = openr2_chan_answer_call_with_mode(p->r2chan, OR2_ANSWER_SIMPLE);
01674    }
01675 #else
01676    res = openr2_chan_answer_call(p->r2chan);
01677 #endif
01678    return res;
01679 }
01680 
01681 
01682 
01683 /* should be called with the ast_channel locked */
01684 static openr2_calling_party_category_t dahdi_r2_get_channel_category(struct ast_channel *c)
01685 {
01686    openr2_calling_party_category_t cat;
01687    const char *catstr = pbx_builtin_getvar_helper(c, "MFCR2_CATEGORY");
01688    struct dahdi_pvt *p = c->tech_pvt;
01689    if (ast_strlen_zero(catstr)) {
01690       ast_debug(1, "No MFC/R2 category specified for chan %s, using default %s\n",
01691             c->name, openr2_proto_get_category_string(p->mfcr2_category));
01692       return p->mfcr2_category;
01693    }
01694    if ((cat = openr2_proto_get_category(catstr)) == OR2_CALLING_PARTY_CATEGORY_UNKNOWN) {
01695       ast_log(LOG_WARNING, "Invalid category specified '%s' for chan %s, using default %s\n",
01696             catstr, c->name, openr2_proto_get_category_string(p->mfcr2_category));
01697       return p->mfcr2_category;
01698    }
01699    ast_debug(1, "Using category %s\n", catstr);
01700    return cat;
01701 }
01702 
01703 static void dahdi_r2_on_call_init(openr2_chan_t *r2chan)
01704 {
01705    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01706    ast_mutex_lock(&p->lock);
01707    if (p->mfcr2call) {
01708       ast_mutex_unlock(&p->lock);
01709       /* TODO: This can happen when some other thread just finished dahdi_request requesting this very same
01710          interface but has not yet seized the line (dahdi_call), and the far end wins and seize the line,
01711          can we avoid this somehow?, at this point when dahdi_call send the seize, it is likely that since
01712          the other end will see our seize as a forced release and drop the call, we will see an invalid
01713          pattern that will be seen and treated as protocol error. */
01714       ast_log(LOG_ERROR, "Collision of calls on chan %d detected!.\n", openr2_chan_get_number(r2chan));
01715       return;
01716    }
01717    p->mfcr2call = 1;
01718    /* better safe than sorry ... */
01719    p->cid_name[0] = '\0';
01720    p->cid_num[0] = '\0';
01721    p->rdnis[0] = '\0';
01722    p->exten[0] = '\0';
01723    p->mfcr2_ani_index = '\0';
01724    p->mfcr2_dnis_index = '\0';
01725    p->mfcr2_dnis_matched = 0;
01726    p->mfcr2_answer_pending = 0;
01727    p->mfcr2_call_accepted = 0;
01728    ast_mutex_unlock(&p->lock);
01729    ast_verbose("New MFC/R2 call detected on chan %d.\n", openr2_chan_get_number(r2chan));
01730 }
01731 
01732 static int get_alarms(struct dahdi_pvt *p);
01733 static void handle_alarms(struct dahdi_pvt *p, int alms);
01734 static void dahdi_r2_on_hardware_alarm(openr2_chan_t *r2chan, int alarm)
01735 {
01736    int res;
01737    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01738    ast_mutex_lock(&p->lock);
01739    p->inalarm = alarm ? 1 : 0;
01740    if (p->inalarm) {
01741       res = get_alarms(p);
01742       handle_alarms(p, res);
01743    } else {
01744       ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel);
01745       manager_event(EVENT_FLAG_SYSTEM, "AlarmClear", "Channel: %d\r\n", p->channel);
01746    }
01747    ast_mutex_unlock(&p->lock);
01748 }
01749 
01750 static void dahdi_r2_on_os_error(openr2_chan_t *r2chan, int errorcode)
01751 {
01752    ast_log(LOG_ERROR, "OS error on chan %d: %s\n", openr2_chan_get_number(r2chan), strerror(errorcode));
01753 }
01754 
01755 static void dahdi_r2_on_protocol_error(openr2_chan_t *r2chan, openr2_protocol_error_t reason)
01756 {
01757    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01758    ast_log(LOG_ERROR, "MFC/R2 protocol error on chan %d: %s\n", openr2_chan_get_number(r2chan), openr2_proto_get_error(reason));
01759    if (p->owner) {
01760       p->owner->hangupcause = AST_CAUSE_PROTOCOL_ERROR;
01761       p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
01762    }
01763    ast_mutex_lock(&p->lock);
01764    p->mfcr2call = 0;
01765    ast_mutex_unlock(&p->lock);
01766 }
01767 
01768 static void dahdi_r2_disconnect_call(struct dahdi_pvt *p, openr2_call_disconnect_cause_t cause)
01769 {
01770    if (openr2_chan_disconnect_call(p->r2chan, cause)) {
01771       ast_log(LOG_NOTICE, "Bad! failed to disconnect call on channel %d with reason %s, hope for the best!\n",
01772          p->channel, openr2_proto_get_disconnect_string(cause));
01773       /* force the chan to idle and release the call flag now since we will not see a clean on_call_end */
01774       openr2_chan_set_idle(p->r2chan);
01775       ast_mutex_lock(&p->lock);
01776       p->mfcr2call = 0;
01777       ast_mutex_unlock(&p->lock);
01778    }
01779 }
01780 
01781 static void dahdi_r2_on_call_offered(openr2_chan_t *r2chan, const char *ani, const char *dnis, openr2_calling_party_category_t category)
01782 {
01783    struct dahdi_pvt *p;
01784    struct ast_channel *c;
01785    ast_verbose("MFC/R2 call offered on chan %d. ANI = %s, DNIS = %s, Category = %s\n",
01786          openr2_chan_get_number(r2chan), ani ? ani : "(restricted)", dnis,
01787          openr2_proto_get_category_string(category));
01788    p = openr2_chan_get_client_data(r2chan);
01789    /* if collect calls are not allowed and this is a collect call, reject it! */
01790    if (!p->mfcr2_allow_collect_calls && category == OR2_CALLING_PARTY_CATEGORY_COLLECT_CALL) {
01791       ast_log(LOG_NOTICE, "Rejecting MFC/R2 collect call\n");
01792       dahdi_r2_disconnect_call(p, OR2_CAUSE_COLLECT_CALL_REJECTED);
01793       return;
01794    }
01795    ast_mutex_lock(&p->lock);
01796    p->mfcr2_recvd_category = category;
01797    /* if we're not supposed to use CID, clear whatever we have */
01798    if (!p->use_callerid) {
01799       ast_log(LOG_DEBUG, "No CID allowed in configuration, CID is being cleared!\n");
01800       p->cid_num[0] = 0;
01801       p->cid_name[0] = 0;
01802    }
01803    /* if we're supposed to answer immediately, clear DNIS and set 's' exten */
01804    if (p->immediate || !openr2_context_get_max_dnis(openr2_chan_get_context(r2chan))) {
01805       ast_log(LOG_DEBUG, "Setting exten => s because of immediate or 0 DNIS configured\n");
01806       p->exten[0] = 's';
01807       p->exten[1] = 0;
01808    }
01809    ast_mutex_unlock(&p->lock);
01810    if (!ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
01811       ast_log(LOG_NOTICE, "MFC/R2 call on channel %d requested non-existent extension '%s' in context '%s'. Rejecting call.\n",
01812             p->channel, p->exten, p->context);
01813       dahdi_r2_disconnect_call(p, OR2_CAUSE_UNALLOCATED_NUMBER);
01814       return;
01815    }
01816    if (!p->mfcr2_accept_on_offer) {
01817       /* The user wants us to start the PBX thread right away without accepting the call first */
01818       c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, 0);
01819       if (c) {
01820          /* Done here, don't disable reading now since we still need to generate MF tones to accept
01821             the call or reject it and detect the tone off condition of the other end, all of this
01822             will be done in the PBX thread now */
01823          return;
01824       }
01825       ast_log(LOG_WARNING, "Unable to create PBX channel in DAHDI channel %d\n", p->channel);
01826       dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER);
01827    } else if (p->mfcr2_charge_calls) {
01828       ast_log(LOG_DEBUG, "Accepting MFC/R2 call with charge on chan %d\n", p->channel);
01829       openr2_chan_accept_call(r2chan, OR2_CALL_WITH_CHARGE);
01830    } else {
01831       ast_log(LOG_DEBUG, "Accepting MFC/R2 call with no charge on chan %d\n", p->channel);
01832       openr2_chan_accept_call(r2chan, OR2_CALL_NO_CHARGE);
01833    }
01834 }
01835 
01836 static void dahdi_r2_on_call_end(openr2_chan_t *r2chan)
01837 {
01838    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01839    ast_verbose("MFC/R2 call end on channel %d\n", p->channel);
01840    ast_mutex_lock(&p->lock);
01841    p->mfcr2call = 0;
01842    ast_mutex_unlock(&p->lock);
01843 }
01844 
01845 static void dahdi_enable_ec(struct dahdi_pvt *p);
01846 static void dahdi_r2_on_call_accepted(openr2_chan_t *r2chan, openr2_call_mode_t mode)
01847 {
01848    struct dahdi_pvt *p = NULL;
01849    struct ast_channel *c = NULL;
01850    p = openr2_chan_get_client_data(r2chan);
01851    dahdi_enable_ec(p);
01852    p->mfcr2_call_accepted = 1;
01853    /* if it's an incoming call ... */
01854    if (OR2_DIR_BACKWARD == openr2_chan_get_direction(r2chan)) {
01855       ast_verbose("MFC/R2 call has been accepted on backward channel %d\n", openr2_chan_get_number(r2chan));
01856       /* If accept on offer is not set, it means at this point the PBX thread is already
01857          launched (was launched in the 'on call offered' handler) and therefore this callback
01858          is being executed already in the PBX thread rather than the monitor thread, don't launch
01859          any other thread, just disable the openr2 reading and answer the call if needed */
01860       if (!p->mfcr2_accept_on_offer) {
01861          openr2_chan_disable_read(r2chan);
01862          if (p->mfcr2_answer_pending) {
01863             ast_log(LOG_DEBUG, "Answering MFC/R2 call after accepting it on chan %d\n", openr2_chan_get_number(r2chan));
01864             dahdi_r2_answer(p);
01865          }
01866          return;
01867       }
01868       c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, 0);
01869       if (c) {
01870          /* chan_dahdi will take care of reading from now on in the PBX thread, tell the
01871             library to forget about it */
01872          openr2_chan_disable_read(r2chan);
01873          return;
01874       }
01875       ast_log(LOG_WARNING, "Unable to create PBX channel in DAHDI channel %d\n", p->channel);
01876       /* failed to create the channel, bail out and report it as an out of order line */
01877       dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER);
01878       return;
01879    }
01880    /* this is an outgoing call, no need to launch the PBX thread, most likely we're in one already */
01881    ast_verbose("MFC/R2 call has been accepted on forward channel %d\n", p->channel);
01882    p->subs[SUB_REAL].needringing = 1;
01883    p->dialing = 0;
01884    /* chan_dahdi will take care of reading from now on in the PBX thread, tell the library to forget about it */
01885    openr2_chan_disable_read(r2chan);
01886 }
01887 
01888 static void dahdi_r2_on_call_answered(openr2_chan_t *r2chan)
01889 {
01890    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01891    ast_verbose("MFC/R2 call has been answered on channel %d\n", openr2_chan_get_number(r2chan));
01892    p->subs[SUB_REAL].needanswer = 1;
01893 }
01894 
01895 static void dahdi_r2_on_call_read(openr2_chan_t *r2chan, const unsigned char *buf, int buflen)
01896 {
01897    /*ast_log(LOG_DEBUG, "Read data from dahdi channel %d\n", openr2_chan_get_number(r2chan));*/
01898 }
01899 
01900 static int dahdi_r2_cause_to_ast_cause(openr2_call_disconnect_cause_t cause)
01901 {
01902    switch (cause) {
01903    case OR2_CAUSE_BUSY_NUMBER:
01904       return AST_CAUSE_BUSY;
01905    case OR2_CAUSE_NETWORK_CONGESTION:
01906       return AST_CAUSE_CONGESTION;
01907    case OR2_CAUSE_OUT_OF_ORDER:
01908       return AST_CAUSE_DESTINATION_OUT_OF_ORDER;
01909    case OR2_CAUSE_UNALLOCATED_NUMBER:
01910       return AST_CAUSE_UNREGISTERED;
01911    case OR2_CAUSE_NO_ANSWER:
01912       return AST_CAUSE_NO_ANSWER;
01913    case OR2_CAUSE_NORMAL_CLEARING:
01914       return AST_CAUSE_NORMAL_CLEARING;
01915    case OR2_CAUSE_UNSPECIFIED:
01916    default:
01917       return AST_CAUSE_NOTDEFINED;
01918    }
01919 }
01920 
01921 static void dahdi_r2_on_call_disconnect(openr2_chan_t *r2chan, openr2_call_disconnect_cause_t cause)
01922 {
01923    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01924    ast_verbose("MFC/R2 call disconnected on channel %d\n", openr2_chan_get_number(r2chan));
01925    ast_mutex_lock(&p->lock);
01926    if (!p->owner) {
01927       ast_mutex_unlock(&p->lock);
01928       /* no owner, therefore we can't use dahdi_hangup to disconnect, do it right now */
01929       dahdi_r2_disconnect_call(p, OR2_CAUSE_NORMAL_CLEARING);
01930       return;
01931    }
01932    /* when we have an owner we don't call dahdi_r2_disconnect_call here, that will
01933       be done in dahdi_hangup */
01934    if (p->owner->_state == AST_STATE_UP) {
01935       p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
01936       ast_mutex_unlock(&p->lock);
01937    } else if (openr2_chan_get_direction(r2chan) == OR2_DIR_FORWARD) {
01938       /* being the forward side we must report what happened to the call to whoever requested it */
01939       switch (cause) {
01940       case OR2_CAUSE_BUSY_NUMBER:
01941          p->subs[SUB_REAL].needbusy = 1;
01942          break;
01943       case OR2_CAUSE_NETWORK_CONGESTION:
01944       case OR2_CAUSE_OUT_OF_ORDER:
01945       case OR2_CAUSE_UNALLOCATED_NUMBER:
01946       case OR2_CAUSE_NO_ANSWER:
01947       case OR2_CAUSE_UNSPECIFIED:
01948       case OR2_CAUSE_NORMAL_CLEARING:
01949          p->subs[SUB_REAL].needcongestion = 1;
01950          break;
01951       default:
01952          p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
01953       }
01954       ast_mutex_unlock(&p->lock);
01955    } else {
01956       ast_mutex_unlock(&p->lock);
01957       /* being the backward side and not UP yet, we only need to request hangup */
01958       /* TODO: what about doing this same thing when were AST_STATE_UP? */
01959       ast_queue_hangup_with_cause(p->owner, dahdi_r2_cause_to_ast_cause(cause));
01960    }
01961 }
01962 
01963 static void dahdi_r2_write_log(openr2_log_level_t level, char *logmessage)
01964 {
01965    switch (level) {
01966    case OR2_LOG_NOTICE:
01967       ast_verbose("%s", logmessage);
01968       break;
01969    case OR2_LOG_WARNING:
01970       ast_log(LOG_WARNING, "%s", logmessage);
01971       break;
01972    case OR2_LOG_ERROR:
01973       ast_log(LOG_ERROR, "%s", logmessage);
01974       break;
01975    case OR2_LOG_STACK_TRACE:
01976    case OR2_LOG_MF_TRACE:
01977    case OR2_LOG_CAS_TRACE:
01978    case OR2_LOG_DEBUG:
01979    case OR2_LOG_EX_DEBUG:
01980       ast_log(LOG_DEBUG, "%s", logmessage);
01981       break;
01982    default:
01983       ast_log(LOG_WARNING, "We should handle logging level %d here.\n", level);
01984       ast_log(LOG_DEBUG, "%s", logmessage);
01985       break;
01986    }
01987 }
01988 
01989 static void dahdi_r2_on_line_blocked(openr2_chan_t *r2chan)
01990 {
01991    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01992    ast_mutex_lock(&p->lock);
01993    p->remotelyblocked = 1;
01994    ast_mutex_unlock(&p->lock);
01995    ast_log(LOG_NOTICE, "Far end blocked on chan %d\n", openr2_chan_get_number(r2chan));
01996 }
01997 
01998 static void dahdi_r2_on_line_idle(openr2_chan_t *r2chan)
01999 {
02000    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
02001    ast_mutex_lock(&p->lock);
02002    p->remotelyblocked = 0;
02003    ast_mutex_unlock(&p->lock);
02004    ast_log(LOG_NOTICE, "Far end unblocked on chan %d\n", openr2_chan_get_number(r2chan));
02005 }
02006 
02007 static void dahdi_r2_on_context_log(openr2_context_t *r2context, openr2_log_level_t level, const char *fmt, va_list ap)
02008    __attribute__((format (printf, 3, 0)));
02009 static void dahdi_r2_on_context_log(openr2_context_t *r2context, openr2_log_level_t level, const char *fmt, va_list ap)
02010 {
02011 #define CONTEXT_TAG "Context - "
02012    char logmsg[256];
02013    char completemsg[sizeof(logmsg) + sizeof(CONTEXT_TAG) - 1];
02014    vsnprintf(logmsg, sizeof(logmsg), fmt, ap);
02015    snprintf(completemsg, sizeof(completemsg), CONTEXT_TAG "%s", logmsg);
02016    dahdi_r2_write_log(level, completemsg);
02017 #undef CONTEXT_TAG
02018 }
02019 
02020 static void dahdi_r2_on_chan_log(openr2_chan_t *r2chan, openr2_log_level_t level, const char *fmt, va_list ap)
02021    __attribute__((format (printf, 3, 0)));
02022 static void dahdi_r2_on_chan_log(openr2_chan_t *r2chan, openr2_log_level_t level, const char *fmt, va_list ap)
02023 {
02024 #define CHAN_TAG "Chan "
02025    char logmsg[256];
02026    char completemsg[sizeof(logmsg) + sizeof(CHAN_TAG) - 1];
02027    vsnprintf(logmsg, sizeof(logmsg), fmt, ap);
02028    snprintf(completemsg, sizeof(completemsg), CHAN_TAG "%d - %s", openr2_chan_get_number(r2chan), logmsg);
02029    dahdi_r2_write_log(level, completemsg);
02030 }
02031 
02032 static int dahdi_r2_on_dnis_digit_received(openr2_chan_t *r2chan, char digit)
02033 {
02034    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
02035    /* if 'immediate' is set, let's stop requesting DNIS */
02036    if (p->immediate) {
02037       return 0;
02038    }
02039    p->exten[p->mfcr2_dnis_index] = digit;
02040    p->rdnis[p->mfcr2_dnis_index] = digit;
02041    p->mfcr2_dnis_index++;
02042    p->exten[p->mfcr2_dnis_index] = 0;
02043    p->rdnis[p->mfcr2_dnis_index] = 0;
02044    /* if the DNIS is a match and cannot match more, stop requesting DNIS */
02045    if ((p->mfcr2_dnis_matched ||
02046        (ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num) && (p->mfcr2_dnis_matched = 1))) &&
02047        !ast_matchmore_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
02048       return 0;
02049    }
02050    /* otherwise keep going */
02051    return 1;
02052 }
02053 
02054 static void dahdi_r2_on_ani_digit_received(openr2_chan_t *r2chan, char digit)
02055 {
02056    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
02057    p->cid_num[p->mfcr2_ani_index] = digit;
02058    p->cid_name[p->mfcr2_ani_index] = digit;
02059    p->mfcr2_ani_index++;
02060    p->cid_num[p->mfcr2_ani_index] = 0;
02061    p->cid_name[p->mfcr2_ani_index] = 0;
02062 }
02063 
02064 static void dahdi_r2_on_billing_pulse_received(openr2_chan_t *r2chan)
02065 {
02066    ast_verbose("MFC/R2 billing pulse received on channel %d\n", openr2_chan_get_number(r2chan));
02067 }
02068 
02069 static openr2_event_interface_t dahdi_r2_event_iface = {
02070    .on_call_init = dahdi_r2_on_call_init,
02071    .on_call_offered = dahdi_r2_on_call_offered,
02072    .on_call_accepted = dahdi_r2_on_call_accepted,
02073    .on_call_answered = dahdi_r2_on_call_answered,
02074    .on_call_disconnect = dahdi_r2_on_call_disconnect,
02075    .on_call_end = dahdi_r2_on_call_end,
02076    .on_call_read = dahdi_r2_on_call_read,
02077    .on_hardware_alarm = dahdi_r2_on_hardware_alarm,
02078    .on_os_error = dahdi_r2_on_os_error,
02079    .on_protocol_error = dahdi_r2_on_protocol_error,
02080    .on_line_blocked = dahdi_r2_on_line_blocked,
02081    .on_line_idle = dahdi_r2_on_line_idle,
02082    /* cast seems to be needed to get rid of the annoying warning regarding format attribute  */
02083    .on_context_log = (openr2_handle_context_logging_func)dahdi_r2_on_context_log,
02084    .on_dnis_digit_received = dahdi_r2_on_dnis_digit_received,
02085    .on_ani_digit_received = dahdi_r2_on_ani_digit_received,
02086    /* so far we do nothing with billing pulses */
02087    .on_billing_pulse_received = dahdi_r2_on_billing_pulse_received
02088 };
02089 
02090 static inline int16_t dahdi_r2_alaw_to_linear(uint8_t sample)
02091 {
02092    return AST_ALAW(sample);
02093 }
02094 
02095 static inline uint8_t dahdi_r2_linear_to_alaw(int sample)
02096 {
02097    return AST_LIN2A(sample);
02098 }
02099 
02100 static openr2_transcoder_interface_t dahdi_r2_transcode_iface = {
02101    dahdi_r2_alaw_to_linear,
02102    dahdi_r2_linear_to_alaw
02103 };
02104 
02105 #endif /* HAVE_OPENR2 */
02106 
02107 static int restore_gains(struct dahdi_pvt *p);
02108 
02109 static void swap_subs(struct dahdi_pvt *p, int a, int b)
02110 {
02111    int tchan;
02112    int tinthreeway;
02113    struct ast_channel *towner;
02114 
02115    ast_debug(1, "Swapping %d and %d\n", a, b);
02116 
02117    tchan = p->subs[a].chan;
02118    towner = p->subs[a].owner;
02119    tinthreeway = p->subs[a].inthreeway;
02120 
02121    p->subs[a].chan = p->subs[b].chan;
02122    p->subs[a].owner = p->subs[b].owner;
02123    p->subs[a].inthreeway = p->subs[b].inthreeway;
02124 
02125    p->subs[b].chan = tchan;
02126    p->subs[b].owner = towner;
02127    p->subs[b].inthreeway = tinthreeway;
02128 
02129    if (p->subs[a].owner)
02130       ast_channel_set_fd(p->subs[a].owner, 0, p->subs[a].dfd);
02131    if (p->subs[b].owner)
02132       ast_channel_set_fd(p->subs[b].owner, 0, p->subs[b].dfd);
02133    wakeup_sub(p, a, NULL);
02134    wakeup_sub(p, b, NULL);
02135 }
02136 
02137 static int dahdi_open(char *fn)
02138 {
02139    int fd;
02140    int isnum;
02141    int chan = 0;
02142    int bs;
02143    int x;
02144    isnum = 1;
02145    for (x = 0; x < strlen(fn); x++) {
02146       if (!isdigit(fn[x])) {
02147          isnum = 0;
02148          break;
02149       }
02150    }
02151    if (isnum) {
02152       chan = atoi(fn);
02153       if (chan < 1) {
02154          ast_log(LOG_WARNING, "Invalid channel number '%s'\n", fn);
02155          return -1;
02156       }
02157       fn = "/dev/dahdi/channel";
02158    }
02159    fd = open(fn, O_RDWR | O_NONBLOCK);
02160    if (fd < 0) {
02161       ast_log(LOG_WARNING, "Unable to open '%s': %s\n", fn, strerror(errno));
02162       return -1;
02163    }
02164    if (chan) {
02165       if (ioctl(fd, DAHDI_SPECIFY, &chan)) {
02166          x = errno;
02167          close(fd);
02168          errno = x;
02169          ast_log(LOG_WARNING, "Unable to specify channel %d: %s\n", chan, strerror(errno));
02170          return -1;
02171       }
02172    }
02173    bs = READ_SIZE;
02174    if (ioctl(fd, DAHDI_SET_BLOCKSIZE, &bs) == -1) {
02175       ast_log(LOG_WARNING, "Unable to set blocksize '%d': %s\n", bs,  strerror(errno));
02176       x = errno;
02177       close(fd);
02178       errno = x;
02179       return -1;
02180    }
02181    return fd;
02182 }
02183 
02184 static void dahdi_close(int fd)
02185 {
02186    if (fd > 0)
02187       close(fd);
02188 }
02189 
02190 static void dahdi_close_sub(struct dahdi_pvt *chan_pvt, int sub_num)
02191 {
02192    dahdi_close(chan_pvt->subs[sub_num].dfd);
02193    chan_pvt->subs[sub_num].dfd = -1;
02194 }
02195 
02196 #if defined(HAVE_PRI)
02197 static void dahdi_close_pri_fd(struct dahdi_pri *pri, int fd_num)
02198 {
02199    dahdi_close(pri->fds[fd_num]);
02200    pri->fds[fd_num] = -1;
02201 }
02202 #endif   /* defined(HAVE_PRI) */
02203 
02204 #if defined(HAVE_SS7)
02205 static void dahdi_close_ss7_fd(struct dahdi_ss7 *ss7, int fd_num)
02206 {
02207    dahdi_close(ss7->fds[fd_num]);
02208    ss7->fds[fd_num] = -1;
02209 }
02210 #endif   /* defined(HAVE_SS7) */
02211 
02212 static int dahdi_setlinear(int dfd, int linear)
02213 {
02214    int res;
02215    res = ioctl(dfd, DAHDI_SETLINEAR, &linear);
02216    if (res)
02217       return res;
02218    return 0;
02219 }
02220 
02221 
02222 static int alloc_sub(struct dahdi_pvt *p, int x)
02223 {
02224    struct dahdi_bufferinfo bi;
02225    int res;
02226    if (p->subs[x].dfd >= 0) {
02227       ast_log(LOG_WARNING, "%s subchannel of %d already in use\n", subnames[x], p->channel);
02228       return -1;
02229    }
02230 
02231    p->subs[x].dfd = dahdi_open("/dev/dahdi/pseudo");
02232    if (p->subs[x].dfd <= -1) {
02233       ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno));
02234       return -1;
02235    }
02236 
02237    res = ioctl(p->subs[x].dfd, DAHDI_GET_BUFINFO, &bi);
02238    if (!res) {
02239       bi.txbufpolicy = p->buf_policy;
02240       bi.rxbufpolicy = p->buf_policy;
02241       bi.numbufs = p->buf_no;
02242       res = ioctl(p->subs[x].dfd, DAHDI_SET_BUFINFO, &bi);
02243       if (res < 0) {
02244          ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", x, strerror(errno));
02245       }
02246    } else
02247       ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", x, strerror(errno));
02248 
02249    if (ioctl(p->subs[x].dfd, DAHDI_CHANNO, &p->subs[x].chan) == 1) {
02250       ast_log(LOG_WARNING, "Unable to get channel number for pseudo channel on FD %d: %s\n", p->subs[x].dfd, strerror(errno));
02251       dahdi_close_sub(p, x);
02252       p->subs[x].dfd = -1;
02253       return -1;
02254    }
02255    ast_debug(1, "Allocated %s subchannel on FD %d channel %d\n", subnames[x], p->subs[x].dfd, p->subs[x].chan);
02256    return 0;
02257 }
02258 
02259 static int unalloc_sub(struct dahdi_pvt *p, int x)
02260 {
02261    if (!x) {
02262       ast_log(LOG_WARNING, "Trying to unalloc the real channel %d?!?\n", p->channel);
02263       return -1;
02264    }
02265    ast_debug(1, "Released sub %d of channel %d\n", x, p->channel);
02266    dahdi_close_sub(p, x);
02267    p->subs[x].linear = 0;
02268    p->subs[x].chan = 0;
02269    p->subs[x].owner = NULL;
02270    p->subs[x].inthreeway = 0;
02271    p->polarity = POLARITY_IDLE;
02272    memset(&p->subs[x].curconf, 0, sizeof(p->subs[x].curconf));
02273    return 0;
02274 }
02275 
02276 static int digit_to_dtmfindex(char digit)
02277 {
02278    if (isdigit(digit))
02279       return DAHDI_TONE_DTMF_BASE + (digit - '0');
02280    else if (digit >= 'A' && digit <= 'D')
02281       return DAHDI_TONE_DTMF_A + (digit - 'A');
02282    else if (digit >= 'a' && digit <= 'd')
02283       return DAHDI_TONE_DTMF_A + (digit - 'a');
02284    else if (digit == '*')
02285       return DAHDI_TONE_DTMF_s;
02286    else if (digit == '#')
02287       return DAHDI_TONE_DTMF_p;
02288    else
02289       return -1;
02290 }
02291 
02292 static int dahdi_digit_begin(struct ast_channel *chan, char digit)
02293 {
02294    struct dahdi_pvt *pvt;
02295    int idx;
02296    int dtmf = -1;
02297 
02298    pvt = chan->tech_pvt;
02299 
02300    ast_mutex_lock(&pvt->lock);
02301 
02302    idx = dahdi_get_index(chan, pvt, 0);
02303 
02304    if ((idx != SUB_REAL) || !pvt->owner)
02305       goto out;
02306 
02307 #ifdef HAVE_PRI
02308    if (((pvt->sig == SIG_PRI) || (pvt->sig == SIG_BRI) || (pvt->sig == SIG_BRI_PTMP))
02309       && chan->_state == AST_STATE_DIALING) {
02310       if (pvt->call_level < DAHDI_CALL_LEVEL_OVERLAP) {
02311          unsigned int len;
02312 
02313          len = strlen(pvt->dialdest);
02314          if (len < sizeof(pvt->dialdest) - 1) {
02315             ast_debug(1, "Queueing digit '%c' since setup_ack not yet received\n",
02316                digit);
02317             pvt->dialdest[len++] = digit;
02318             pvt->dialdest[len] = '\0';
02319          } else {
02320             ast_log(LOG_WARNING,
02321                "Span %d: Deferred digit buffer overflow for digit '%c'.\n",
02322                pvt->span, digit);
02323          }
02324          goto out;
02325       }
02326       if (pvt->call_level < DAHDI_CALL_LEVEL_PROCEEDING) {
02327          if (!pri_grab(pvt, pvt->pri)) {
02328             pri_information(pvt->pri->pri, pvt->call, digit);
02329             pri_rel(pvt->pri);
02330          } else {
02331             ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", pvt->span);
02332          }
02333          goto out;
02334       }
02335       if (pvt->call_level < DAHDI_CALL_LEVEL_CONNECT) {
02336          ast_log(LOG_WARNING,
02337             "Span %d: Digit '%c' may be ignored by peer. (Call level:%d)\n",
02338             pvt->span, digit, pvt->call_level);
02339       }
02340    }
02341 #endif
02342    if ((dtmf = digit_to_dtmfindex(digit)) == -1)
02343       goto out;
02344 
02345    if (pvt->pulse || ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &dtmf)) {
02346       int res;
02347       struct dahdi_dialoperation zo = {
02348          .op = DAHDI_DIAL_OP_APPEND,
02349       };
02350 
02351       zo.dialstr[0] = 'T';
02352       zo.dialstr[1] = digit;
02353       zo.dialstr[2] = '\0';
02354       if ((res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo)))
02355          ast_log(LOG_WARNING, "Couldn't dial digit %c: %s\n", digit, strerror(errno));
02356       else
02357          pvt->dialing = 1;
02358    } else {
02359       ast_debug(1, "Started VLDTMF digit '%c'\n", digit);
02360       pvt->dialing = 1;
02361       pvt->begindigit = digit;
02362    }
02363 
02364 out:
02365    ast_mutex_unlock(&pvt->lock);
02366 
02367    return 0;
02368 }
02369 
02370 static int dahdi_digit_end(struct ast_channel *chan, char digit, unsigned int duration)
02371 {
02372    struct dahdi_pvt *pvt;
02373    int res = 0;
02374    int idx;
02375    int x;
02376 
02377    pvt = chan->tech_pvt;
02378 
02379    ast_mutex_lock(&pvt->lock);
02380 
02381    idx = dahdi_get_index(chan, pvt, 0);
02382 
02383    if ((idx != SUB_REAL) || !pvt->owner || pvt->pulse)
02384       goto out;
02385 
02386 #ifdef HAVE_PRI
02387    /* This means that the digit was already sent via PRI signalling */
02388    if (((pvt->sig == SIG_PRI) || (pvt->sig == SIG_BRI) || (pvt->sig == SIG_BRI_PTMP))
02389          && !pvt->begindigit)
02390       goto out;
02391 #endif
02392 
02393    if (pvt->begindigit) {
02394       x = -1;
02395       ast_debug(1, "Ending VLDTMF digit '%c'\n", digit);
02396       res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &x);
02397       pvt->dialing = 0;
02398       pvt->begindigit = 0;
02399    }
02400 
02401 out:
02402    ast_mutex_unlock(&pvt->lock);
02403 
02404    return res;
02405 }
02406 
02407 static char *events[] = {
02408    "No event",
02409    "On hook",
02410    "Ring/Answered",
02411    "Wink/Flash",
02412    "Alarm",
02413    "No more alarm",
02414    "HDLC Abort",
02415    "HDLC Overrun",
02416    "HDLC Bad FCS",
02417    "Dial Complete",
02418    "Ringer On",
02419    "Ringer Off",
02420    "Hook Transition Complete",
02421    "Bits Changed",
02422    "Pulse Start",
02423    "Timer Expired",
02424    "Timer Ping",
02425    "Polarity Reversal",
02426    "Ring Begin",
02427 };
02428 
02429 static struct {
02430    int alarm;
02431    char *name;
02432 } alarms[] = {
02433    { DAHDI_ALARM_RED, "Red Alarm" },
02434    { DAHDI_ALARM_YELLOW, "Yellow Alarm" },
02435    { DAHDI_ALARM_BLUE, "Blue Alarm" },
02436    { DAHDI_ALARM_RECOVER, "Recovering" },
02437    { DAHDI_ALARM_LOOPBACK, "Loopback" },
02438    { DAHDI_ALARM_NOTOPEN, "Not Open" },
02439    { DAHDI_ALARM_NONE, "None" },
02440 };
02441 
02442 static char *alarm2str(int alm)
02443 {
02444    int x;
02445    for (x = 0; x < ARRAY_LEN(alarms); x++) {
02446       if (alarms[x].alarm & alm)
02447          return alarms[x].name;
02448    }
02449    return alm ? "Unknown Alarm" : "No Alarm";
02450 }
02451 
02452 static char *event2str(int event)
02453 {
02454    static char buf[256];
02455    if ((event < (ARRAY_LEN(events))) && (event > -1))
02456       return events[event];
02457    sprintf(buf, "Event %d", event); /* safe */
02458    return buf;
02459 }
02460 
02461 #ifdef HAVE_PRI
02462 static char *dialplan2str(int dialplan)
02463 {
02464    if (dialplan == -1 || dialplan == -2) {
02465       return("Dynamically set dialplan in ISDN");
02466    }
02467    return (pri_plan2str(dialplan));
02468 }
02469 #endif
02470 
02471 static char *dahdi_sig2str(int sig)
02472 {
02473    static char buf[256];
02474    switch (sig) {
02475    case SIG_EM:
02476       return "E & M Immediate";
02477    case SIG_EMWINK:
02478       return "E & M Wink";
02479    case SIG_EM_E1:
02480       return "E & M E1";
02481    case SIG_FEATD:
02482       return "Feature Group D (DTMF)";
02483    case SIG_FEATDMF:
02484       return "Feature Group D (MF)";
02485    case SIG_FEATDMF_TA:
02486       return "Feature Groud D (MF) Tandem Access";
02487    case SIG_FEATB:
02488       return "Feature Group B (MF)";
02489    case SIG_E911:
02490       return "E911 (MF)";
02491    case SIG_FGC_CAMA:
02492       return "FGC/CAMA (Dialpulse)";
02493    case SIG_FGC_CAMAMF:
02494       return "FGC/CAMA (MF)";
02495    case SIG_FXSLS:
02496       return "FXS Loopstart";
02497    case SIG_FXSGS:
02498       return "FXS Groundstart";
02499    case SIG_FXSKS:
02500       return "FXS Kewlstart";
02501    case SIG_FXOLS:
02502       return "FXO Loopstart";
02503    case SIG_FXOGS:
02504       return "FXO Groundstart";
02505    case SIG_FXOKS:
02506       return "FXO Kewlstart";
02507    case SIG_PRI:
02508       return "ISDN PRI";
02509    case SIG_BRI:
02510       return "ISDN BRI Point to Point";
02511    case SIG_BRI_PTMP:
02512       return "ISDN BRI Point to MultiPoint";
02513    case SIG_SS7:
02514       return "SS7";
02515    case SIG_MFCR2:
02516       return "MFC/R2";
02517    case SIG_SF:
02518       return "SF (Tone) Immediate";
02519    case SIG_SFWINK:
02520       return "SF (Tone) Wink";
02521    case SIG_SF_FEATD:
02522       return "SF (Tone) with Feature Group D (DTMF)";
02523    case SIG_SF_FEATDMF:
02524       return "SF (Tone) with Feature Group D (MF)";
02525    case SIG_SF_FEATB:
02526       return "SF (Tone) with Feature Group B (MF)";
02527    case SIG_GR303FXOKS:
02528       return "GR-303 with FXOKS";
02529    case SIG_GR303FXSKS:
02530       return "GR-303 with FXSKS";
02531    case 0:
02532       return "Pseudo";
02533    default:
02534       snprintf(buf, sizeof(buf), "Unknown signalling %d", sig);
02535       return buf;
02536    }
02537 }
02538 
02539 #define sig2str dahdi_sig2str
02540 
02541 static int conf_add(struct dahdi_pvt *p, struct dahdi_subchannel *c, int idx, int slavechannel)
02542 {
02543    /* If the conference already exists, and we're already in it
02544       don't bother doing anything */
02545    struct dahdi_confinfo zi;
02546 
02547    memset(&zi, 0, sizeof(zi));
02548    zi.chan = 0;
02549 
02550    if (slavechannel > 0) {
02551       /* If we have only one slave, do a digital mon */
02552       zi.confmode = DAHDI_CONF_DIGITALMON;
02553       zi.confno = slavechannel;
02554    } else {
02555       if (!idx) {
02556          /* Real-side and pseudo-side both participate in conference */
02557          zi.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER |
02558             DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER;
02559       } else
02560          zi.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER;
02561       zi.confno = p->confno;
02562    }
02563    if ((zi.confno == c->curconf.confno) && (zi.confmode == c->curconf.confmode))
02564       return 0;
02565    if (c->dfd < 0)
02566       return 0;
02567    if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
02568       ast_log(LOG_WARNING, "Failed to add %d to conference %d/%d: %s\n", c->dfd, zi.confmode, zi.confno, strerror(errno));
02569       return -1;
02570    }
02571    if (slavechannel < 1) {
02572       p->confno = zi.confno;
02573    }
02574    memcpy(&c->curconf, &zi, sizeof(c->curconf));
02575    ast_debug(1, "Added %d to conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
02576    return 0;
02577 }
02578 
02579 static int isourconf(struct dahdi_pvt *p, struct dahdi_subchannel *c)
02580 {
02581    /* If they're listening to our channel, they're ours */
02582    if ((p->channel == c->curconf.confno) && (c->curconf.confmode == DAHDI_CONF_DIGITALMON))
02583       return 1;
02584    /* If they're a talker on our (allocated) conference, they're ours */
02585    if ((p->confno > 0) && (p->confno == c->curconf.confno) && (c->curconf.confmode & DAHDI_CONF_TALKER))
02586       return 1;
02587    return 0;
02588 }
02589 
02590 static int conf_del(struct dahdi_pvt *p, struct dahdi_subchannel *c, int idx)
02591 {
02592    struct dahdi_confinfo zi;
02593    if (/* Can't delete if there's no dfd */
02594       (c->dfd < 0) ||
02595       /* Don't delete from the conference if it's not our conference */
02596       !isourconf(p, c)
02597       /* Don't delete if we don't think it's conferenced at all (implied) */
02598       ) return 0;
02599    memset(&zi, 0, sizeof(zi));
02600    if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
02601       ast_log(LOG_WARNING, "Failed to drop %d from conference %d/%d: %s\n", c->dfd, c->curconf.confmode, c->curconf.confno, strerror(errno));
02602       return -1;
02603    }
02604    ast_debug(1, "Removed %d from conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
02605    memcpy(&c->curconf, &zi, sizeof(c->curconf));
02606    return 0;
02607 }
02608 
02609 static int isslavenative(struct dahdi_pvt *p, struct dahdi_pvt **out)
02610 {
02611    int x;
02612    int useslavenative;
02613    struct dahdi_pvt *slave = NULL;
02614    /* Start out optimistic */
02615    useslavenative = 1;
02616    /* Update conference state in a stateless fashion */
02617    for (x = 0; x < 3; x++) {
02618       /* Any three-way calling makes slave native mode *definitely* out
02619          of the question */
02620       if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway)
02621          useslavenative = 0;
02622    }
02623    /* If we don't have any 3-way calls, check to see if we have
02624       precisely one slave */
02625    if (useslavenative) {
02626       for (x = 0; x < MAX_SLAVES; x++) {
02627          if (p->slaves[x]) {
02628             if (slave) {
02629                /* Whoops already have a slave!  No
02630                   slave native and stop right away */
02631                slave = NULL;
02632                useslavenative = 0;
02633                break;
02634             } else {
02635                /* We have one slave so far */
02636                slave = p->slaves[x];
02637             }
02638          }
02639       }
02640    }
02641    /* If no slave, slave native definitely out */
02642    if (!slave)
02643       useslavenative = 0;
02644    else if (slave->law != p->law) {
02645       useslavenative = 0;
02646       slave = NULL;
02647    }
02648    if (out)
02649       *out = slave;
02650    return useslavenative;
02651 }
02652 
02653 static int reset_conf(struct dahdi_pvt *p)
02654 {
02655    p->confno = -1;
02656    memset(&p->subs[SUB_REAL].curconf, 0, sizeof(p->subs[SUB_REAL].curconf));
02657    if (p->subs[SUB_REAL].dfd > -1) {
02658       struct dahdi_confinfo zi;
02659 
02660       memset(&zi, 0, sizeof(zi));
02661       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &zi))
02662          ast_log(LOG_WARNING, "Failed to reset conferencing on channel %d: %s\n", p->channel, strerror(errno));
02663    }
02664    return 0;
02665 }
02666 
02667 static int update_conf(struct dahdi_pvt *p)
02668 {
02669    int needconf = 0;
02670    int x;
02671    int useslavenative;
02672    struct dahdi_pvt *slave = NULL;
02673 
02674    useslavenative = isslavenative(p, &slave);
02675    /* Start with the obvious, general stuff */
02676    for (x = 0; x < 3; x++) {
02677       /* Look for three way calls */
02678       if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) {
02679          conf_add(p, &p->subs[x], x, 0);
02680          needconf++;
02681       } else {
02682          conf_del(p, &p->subs[x], x);
02683       }
02684    }
02685    /* If we have a slave, add him to our conference now. or DAX
02686       if this is slave native */
02687    for (x = 0; x < MAX_SLAVES; x++) {
02688       if (p->slaves[x]) {
02689          if (useslavenative)
02690             conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
02691          else {
02692             conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
02693             needconf++;
02694          }
02695       }
02696    }
02697    /* If we're supposed to be in there, do so now */
02698    if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
02699       if (useslavenative)
02700          conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
02701       else {
02702          conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
02703          needconf++;
02704       }
02705    }
02706    /* If we have a master, add ourselves to his conference */
02707    if (p->master) {
02708       if (isslavenative(p->master, NULL)) {
02709          conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
02710       } else {
02711          conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
02712       }
02713    }
02714    if (!needconf) {
02715       /* Nobody is left (or should be left) in our conference.
02716          Kill it. */
02717       p->confno = -1;
02718    }
02719    ast_debug(1, "Updated conferencing on %d, with %d conference users\n", p->channel, needconf);
02720    return 0;
02721 }
02722 
02723 static void dahdi_enable_ec(struct dahdi_pvt *p)
02724 {
02725    int x;
02726    int res;
02727    if (!p)
02728       return;
02729    if (p->echocanon) {
02730       ast_debug(1, "Echo cancellation already on\n");
02731       return;
02732    }
02733    if (p->digital) {
02734       ast_debug(1, "Echo cancellation isn't required on digital connection\n");
02735       return;
02736    }
02737    if (p->echocancel.head.tap_length) {
02738       if ((p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP) || (p->sig == SIG_PRI) || (p->sig == SIG_SS7)) {
02739          x = 1;
02740          res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x);
02741          if (res)
02742             ast_log(LOG_WARNING, "Unable to enable audio mode on channel %d (%s)\n", p->channel, strerror(errno));
02743       }
02744       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &p->echocancel);
02745       if (res) {
02746          ast_log(LOG_WARNING, "Unable to enable echo cancellation on channel %d (%s)\n", p->channel, strerror(errno));
02747       } else {
02748          p->echocanon = 1;
02749          ast_debug(1, "Enabled echo cancellation on channel %d\n", p->channel);
02750       }
02751    } else
02752       ast_debug(1, "No echo cancellation requested\n");
02753 }
02754 
02755 static void dahdi_train_ec(struct dahdi_pvt *p)
02756 {
02757    int x;
02758    int res;
02759 
02760    if (p && p->echocanon && p->echotraining) {
02761       x = p->echotraining;
02762       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOTRAIN, &x);
02763       if (res)
02764          ast_log(LOG_WARNING, "Unable to request echo training on channel %d: %s\n", p->channel, strerror(errno));
02765       else
02766          ast_debug(1, "Engaged echo training on channel %d\n", p->channel);
02767    } else {
02768       ast_debug(1, "No echo training requested\n");
02769    }
02770 }
02771 
02772 static void dahdi_disable_ec(struct dahdi_pvt *p)
02773 {
02774    int res;
02775 
02776    if (p->echocanon) {
02777       struct dahdi_echocanparams ecp = { .tap_length = 0 };
02778 
02779       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &ecp);
02780 
02781       if (res)
02782          ast_log(LOG_WARNING, "Unable to disable echo cancellation on channel %d: %s\n", p->channel, strerror(errno));
02783       else
02784          ast_debug(1, "Disabled echo cancellation on channel %d\n", p->channel);
02785    }
02786 
02787    p->echocanon = 0;
02788 }
02789 
02790 static void fill_txgain(struct dahdi_gains *g, float gain, int law)
02791 {
02792    int j;
02793    int k;
02794    float linear_gain = pow(10.0, gain / 20.0);
02795 
02796    switch (law) {
02797    case DAHDI_LAW_ALAW:
02798       for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
02799          if (gain) {
02800             k = (int) (((float) AST_ALAW(j)) * linear_gain);
02801             if (k > 32767) k = 32767;
02802             if (k < -32767) k = -32767;
02803             g->txgain[j] = AST_LIN2A(k);
02804          } else {
02805             g->txgain[j] = j;
02806          }
02807       }
02808       break;
02809    case DAHDI_LAW_MULAW:
02810       for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
02811          if (gain) {
02812             k = (int) (((float) AST_MULAW(j)) * linear_gain);
02813             if (k > 32767) k = 32767;
02814             if (k < -32767) k = -32767;
02815             g->txgain[j] = AST_LIN2MU(k);
02816          } else {
02817             g->txgain[j] = j;
02818          }
02819       }
02820       break;
02821    }
02822 }
02823 
02824 static void fill_rxgain(struct dahdi_gains *g, float gain, int law)
02825 {
02826    int j;
02827    int k;
02828    float linear_gain = pow(10.0, gain / 20.0);
02829 
02830    switch (law) {
02831    case DAHDI_LAW_ALAW:
02832       for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
02833          if (gain) {
02834             k = (int) (((float) AST_ALAW(j)) * linear_gain);
02835             if (k > 32767) k = 32767;
02836             if (k < -32767) k = -32767;
02837             g->rxgain[j] = AST_LIN2A(k);
02838          } else {
02839             g->rxgain[j] = j;
02840          }
02841       }
02842       break;
02843    case DAHDI_LAW_MULAW:
02844       for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
02845          if (gain) {
02846             k = (int) (((float) AST_MULAW(j)) * linear_gain);
02847             if (k > 32767) k = 32767;
02848             if (k < -32767) k = -32767;
02849             g->rxgain[j] = AST_LIN2MU(k);
02850          } else {
02851             g->rxgain[j] = j;
02852          }
02853       }
02854       break;
02855    }
02856 }
02857 
02858 static int set_actual_txgain(int fd, int chan, float gain, int law)
02859 {
02860    struct dahdi_gains g;
02861    int res;
02862 
02863    memset(&g, 0, sizeof(g));
02864    g.chan = chan;
02865    res = ioctl(fd, DAHDI_GETGAINS, &g);
02866    if (res) {
02867       ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
02868       return res;
02869    }
02870 
02871    fill_txgain(&g, gain, law);
02872 
02873    return ioctl(fd, DAHDI_SETGAINS, &g);
02874 }
02875 
02876 static int set_actual_rxgain(int fd, int chan, float gain, int law)
02877 {
02878    struct dahdi_gains g;
02879    int res;
02880 
02881    memset(&g, 0, sizeof(g));
02882    g.chan = chan;
02883    res = ioctl(fd, DAHDI_GETGAINS, &g);
02884    if (res) {
02885       ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
02886       return res;
02887    }
02888 
02889    fill_rxgain(&g, gain, law);
02890 
02891    return ioctl(fd, DAHDI_SETGAINS, &g);
02892 }
02893 
02894 static int set_actual_gain(int fd, int chan, float rxgain, float txgain, int law)
02895 {
02896    return set_actual_txgain(fd, chan, txgain, law) | set_actual_rxgain(fd, chan, rxgain, law);
02897 }
02898 
02899 static int bump_gains(struct dahdi_pvt *p)
02900 {
02901    int res;
02902 
02903    /* Bump receive gain by value stored in cid_rxgain */
02904    res = set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain + p->cid_rxgain, p->txgain, p->law);
02905    if (res) {
02906       ast_log(LOG_WARNING, "Unable to bump gain: %s\n", strerror(errno));
02907       return -1;
02908    }
02909 
02910    return 0;
02911 }
02912 
02913 static int restore_gains(struct dahdi_pvt *p)
02914 {
02915    int res;
02916 
02917    res = set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain, p->txgain, p->law);
02918    if (res) {
02919       ast_log(LOG_WARNING, "Unable to restore gains: %s\n", strerror(errno));
02920       return -1;
02921    }
02922 
02923    return 0;
02924 }
02925 
02926 static inline int dahdi_set_hook(int fd, int hs)
02927 {
02928    int x, res;
02929 
02930    x = hs;
02931    res = ioctl(fd, DAHDI_HOOK, &x);
02932 
02933    if (res < 0) {
02934       if (errno == EINPROGRESS)
02935          return 0;
02936       ast_log(LOG_WARNING, "DAHDI hook failed returned %d (trying %d): %s\n", res, hs, strerror(errno));
02937       /* will expectedly fail if phone is off hook during operation, such as during a restart */
02938    }
02939 
02940    return res;
02941 }
02942 
02943 static inline int dahdi_confmute(struct dahdi_pvt *p, int muted)
02944 {
02945    int x, y, res;
02946    x = muted;
02947    if ((p->sig == SIG_PRI) || (p->sig == SIG_SS7) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) {
02948       y = 1;
02949       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &y);
02950       if (res)
02951          ast_log(LOG_WARNING, "Unable to set audio mode on %d: %s\n", p->channel, strerror(errno));
02952    }
02953    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_CONFMUTE, &x);
02954    if (res < 0)
02955       ast_log(LOG_WARNING, "DAHDI confmute(%d) failed on channel %d: %s\n", muted, p->channel, strerror(errno));
02956    return res;
02957 }
02958 
02959 static int save_conference(struct dahdi_pvt *p)
02960 {
02961    struct dahdi_confinfo c;
02962    int res;
02963    if (p->saveconf.confmode) {
02964       ast_log(LOG_WARNING, "Can't save conference -- already in use\n");
02965       return -1;
02966    }
02967    p->saveconf.chan = 0;
02968    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &p->saveconf);
02969    if (res) {
02970       ast_log(LOG_WARNING, "Unable to get conference info: %s\n", strerror(errno));
02971       p->saveconf.confmode = 0;
02972       return -1;
02973    }
02974    memset(&c, 0, sizeof(c));
02975    c.confmode = DAHDI_CONF_NORMAL;
02976    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &c);
02977    if (res) {
02978       ast_log(LOG_WARNING, "Unable to set conference info: %s\n", strerror(errno));
02979       return -1;
02980    }
02981    ast_debug(1, "Disabled conferencing\n");
02982    return 0;
02983 }
02984 
02985 /*!
02986  * \brief Send MWI state change
02987  *
02988  * \arg mailbox_full This is the mailbox associated with the FXO line that the
02989  *      MWI state has changed on.
02990  * \arg thereornot This argument should simply be set to 1 or 0, to indicate
02991  *      whether there are messages waiting or not.
02992  *
02993  *  \return nothing
02994  *
02995  * This function does two things:
02996  *
02997  * 1) It generates an internal Asterisk event notifying any other module that
02998  *    cares about MWI that the state of a mailbox has changed.
02999  *
03000  * 2) It runs the script specified by the mwimonitornotify option to allow
03001  *    some custom handling of the state change.
03002  */
03003 static void notify_message(char *mailbox_full, int thereornot)
03004 {
03005    char s[sizeof(mwimonitornotify) + 80];
03006    struct ast_event *event;
03007    char *mailbox, *context;
03008 
03009    /* Strip off @default */
03010    context = mailbox = ast_strdupa(mailbox_full);
03011    strsep(&context, "@");
03012    if (ast_strlen_zero(context))
03013       context = "default";
03014 
03015    if (!(event = ast_event_new(AST_EVENT_MWI,
03016          AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
03017          AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
03018          AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot,
03019          AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot,
03020          AST_EVENT_IE_END))) {
03021       return;
03022    }
03023 
03024    ast_event_queue_and_cache(event);
03025 
03026    if (!ast_strlen_zero(mailbox) && !ast_strlen_zero(mwimonitornotify)) {
03027       snprintf(s, sizeof(s), "%s %s %d", mwimonitornotify, mailbox, thereornot);
03028       ast_safe_system(s);
03029    }
03030 }
03031 
03032 static int restore_conference(struct dahdi_pvt *p)
03033 {
03034    int res;
03035    if (p->saveconf.confmode) {
03036       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &p->saveconf);
03037       p->saveconf.confmode = 0;
03038       if (res) {
03039          ast_log(LOG_WARNING, "Unable to restore conference info: %s\n", strerror(errno));
03040          return -1;
03041       }
03042       ast_debug(1, "Restored conferencing\n");
03043    }
03044    return 0;
03045 }
03046 
03047 static int send_callerid(struct dahdi_pvt *p);
03048 
03049 static int send_cwcidspill(struct dahdi_pvt *p)
03050 {
03051    p->callwaitcas = 0;
03052    p->cidcwexpire = 0;
03053    p->cid_suppress_expire = 0;
03054    if (!(p->cidspill = ast_malloc(MAX_CALLERID_SIZE)))
03055       return -1;
03056    p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, p->callwait_name, p->callwait_num, AST_LAW(p));
03057    /* Make sure we account for the end */
03058    p->cidlen += READ_SIZE * 4;
03059    p->cidpos = 0;
03060    send_callerid(p);
03061    ast_verb(3, "CPE supports Call Waiting Caller*ID.  Sending '%s/%s'\n", p->callwait_name, p->callwait_num);
03062    return 0;
03063 }
03064 
03065 static int has_voicemail(struct dahdi_pvt *p)
03066 {
03067    int new_msgs;
03068    struct ast_event *event;
03069    char *mailbox, *context;
03070 
03071    mailbox = context = ast_strdupa(p->mailbox);
03072    strsep(&context, "@");
03073    if (ast_strlen_zero(context))
03074       context = "default";
03075 
03076    event = ast_event_get_cached(AST_EVENT_MWI,
03077       AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
03078       AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
03079       AST_EVENT_IE_END);
03080 
03081    if (event) {
03082       new_msgs = ast_event_get_ie_uint(event, AST_EVENT_IE_NEWMSGS);
03083       ast_event_destroy(event);
03084    } else
03085       new_msgs = ast_app_has_voicemail(p->mailbox, NULL);
03086 
03087    return new_msgs;
03088 }
03089 
03090 static int send_callerid(struct dahdi_pvt *p)
03091 {
03092    /* Assumes spill in p->cidspill, p->cidlen in length and we're p->cidpos into it */
03093    int res;
03094    /* Take out of linear mode if necessary */
03095    if (p->subs[SUB_REAL].linear) {
03096       p->subs[SUB_REAL].linear = 0;
03097       dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
03098    }
03099    while (p->cidpos < p->cidlen) {
03100       res = write(p->subs[SUB_REAL].dfd, p->cidspill + p->cidpos, p->cidlen - p->cidpos);
03101       if (res < 0) {
03102          if (errno == EAGAIN)
03103             return 0;
03104          else {
03105             ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
03106             return -1;
03107          }
03108       }
03109       if (!res)
03110          return 0;
03111       p->cidpos += res;
03112    }
03113    p->cid_suppress_expire = CALLWAITING_SUPPRESS_SAMPLES;
03114    ast_free(p->cidspill);
03115    p->cidspill = NULL;
03116    if (p->callwaitcas) {
03117       /* Wait for CID/CW to expire */
03118       p->cidcwexpire = CIDCW_EXPIRE_SAMPLES;
03119       p->cid_suppress_expire = p->cidcwexpire;
03120    } else
03121       restore_conference(p);
03122    return 0;
03123 }
03124 
03125 static int dahdi_callwait(struct ast_channel *ast)
03126 {
03127    struct dahdi_pvt *p = ast->tech_pvt;
03128    p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
03129    if (p->cidspill) {
03130       ast_log(LOG_WARNING, "Spill already exists?!?\n");
03131       ast_free(p->cidspill);
03132    }
03133 
03134    /*
03135     * SAS: Subscriber Alert Signal, 440Hz for 300ms
03136     * CAS: CPE Alert Signal, 2130Hz * 2750Hz sine waves
03137     */
03138    if (!(p->cidspill = ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE * 4)))
03139       return -1;
03140    save_conference(p);
03141    /* Silence */
03142    memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
03143    if (!p->callwaitrings && p->callwaitingcallerid) {
03144       ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
03145       p->callwaitcas = 1;
03146       p->cidlen = 2400 + 680 + READ_SIZE * 4;
03147    } else {
03148       ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
03149       p->callwaitcas = 0;
03150       p->cidlen = 2400 + READ_SIZE * 4;
03151    }
03152    p->cidpos = 0;
03153    send_callerid(p);
03154 
03155    return 0;
03156 }
03157 
03158 #if defined(HAVE_SS7)
03159 static unsigned char cid_pres2ss7pres(int cid_pres)
03160 {
03161     return (cid_pres >> 5) & 0x03;
03162 }
03163 #endif   /* defined(HAVE_SS7) */
03164 
03165 #if defined(HAVE_SS7)
03166 static unsigned char cid_pres2ss7screen(int cid_pres)
03167 {
03168    return cid_pres & 0x03;
03169 }
03170 #endif   /* defined(HAVE_SS7) */
03171 
03172 static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout)
03173 {
03174    struct dahdi_pvt *p = ast->tech_pvt;
03175    int x, res, idx,mysig;
03176    char *c, *n, *l;
03177 #ifdef HAVE_PRI
03178    char *s = NULL;
03179 #endif
03180    char dest[256]; /* must be same length as p->dialdest */
03181    ast_mutex_lock(&p->lock);
03182    ast_copy_string(dest, rdest, sizeof(dest));
03183    ast_copy_string(p->dialdest, rdest, sizeof(p->dialdest));
03184    if ((ast->_state == AST_STATE_BUSY)) {
03185       p->subs[SUB_REAL].needbusy = 1;
03186       ast_mutex_unlock(&p->lock);
03187       return 0;
03188    }
03189    if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
03190       ast_log(LOG_WARNING, "dahdi_call called on %s, neither down nor reserved\n", ast->name);
03191       ast_mutex_unlock(&p->lock);
03192       return -1;
03193    }
03194    p->waitingfordt.tv_sec = 0;
03195    p->dialednone = 0;
03196    if ((p->radio || (p->oprmode < 0)))  /* if a radio channel, up immediately */
03197    {
03198       /* Special pseudo -- automatically up */
03199       ast_setstate(ast, AST_STATE_UP);
03200       ast_mutex_unlock(&p->lock);
03201       return 0;
03202    }
03203    x = DAHDI_FLUSH_READ | DAHDI_FLUSH_WRITE;
03204    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
03205    if (res)
03206       ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", p->channel, strerror(errno));
03207    p->outgoing = 1;
03208 
03209    if (IS_DIGITAL(ast->transfercapability)){
03210       set_actual_gain(p->subs[SUB_REAL].dfd, 0, 0, 0, p->law);
03211    } else {
03212       set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain, p->txgain, p->law);
03213    }  
03214 
03215    mysig = p->sig;
03216    if (p->outsigmod > -1)
03217       mysig = p->outsigmod;
03218 
03219    switch (mysig) {
03220    case SIG_FXOLS:
03221    case SIG_FXOGS:
03222    case SIG_FXOKS:
03223       if (p->owner == ast) {
03224          /* Normal ring, on hook */
03225 
03226          /* Don't send audio while on hook, until the call is answered */
03227          p->dialing = 1;
03228          if (p->use_callerid) {
03229             /* Generate the Caller-ID spill if desired */
03230             if (p->cidspill) {
03231                ast_log(LOG_WARNING, "cidspill already exists??\n");
03232                ast_free(p->cidspill);
03233             }
03234             p->callwaitcas = 0;
03235             if ((p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) {
03236                p->cidlen = ast_callerid_generate(p->cidspill, ast->cid.cid_name, ast->cid.cid_num, AST_LAW(p));
03237                p->cidpos = 0;
03238                send_callerid(p);
03239             }
03240          }
03241          /* Choose proper cadence */
03242          if ((p->distinctivering > 0) && (p->distinctivering <= num_cadence)) {
03243             if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &cadences[p->distinctivering - 1]))
03244                ast_log(LOG_WARNING, "Unable to set distinctive ring cadence %d on '%s': %s\n", p->distinctivering, ast->name, strerror(errno));
03245             p->cidrings = cidrings[p->distinctivering - 1];
03246          } else {
03247             if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, NULL))
03248                ast_log(LOG_WARNING, "Unable to reset default ring on '%s': %s\n", ast->name, strerror(errno));
03249             p->cidrings = p->sendcalleridafter;
03250          }
03251 
03252          /* nick@dccinc.com 4/3/03 mods to allow for deferred dialing */
03253          c = strchr(dest, '/');
03254          if (c)
03255             c++;
03256          if (c && (strlen(c) < p->stripmsd)) {
03257             ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
03258             c = NULL;
03259          }
03260          if (c) {
03261             p->dop.op = DAHDI_DIAL_OP_REPLACE;
03262             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "Tw%s", c);
03263             ast_debug(1, "FXO: setup deferred dialstring: %s\n", c);
03264          } else {
03265             p->dop.dialstr[0] = '\0';
03266          }
03267          x = DAHDI_RING;
03268          if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x) && (errno != EINPROGRESS)) {
03269             ast_log(LOG_WARNING, "Unable to ring phone: %s\n", strerror(errno));
03270             ast_mutex_unlock(&p->lock);
03271             return -1;
03272          }
03273          p->dialing = 1;
03274       } else {
03275          /* Call waiting call */
03276          p->callwaitrings = 0;
03277          if (ast->cid.cid_num)
03278             ast_copy_string(p->callwait_num, ast->cid.cid_num, sizeof(p->callwait_num));
03279          else
03280             p->callwait_num[0] = '\0';
03281          if (ast->cid.cid_name)
03282             ast_copy_string(p->callwait_name, ast->cid.cid_name, sizeof(p->callwait_name));
03283          else
03284             p->callwait_name[0] = '\0';
03285          /* Call waiting tone instead */
03286          if (dahdi_callwait(ast)) {
03287             ast_mutex_unlock(&p->lock);
03288             return -1;
03289          }
03290          /* Make ring-back */
03291          if (tone_zone_play_tone(p->subs[SUB_CALLWAIT].dfd, DAHDI_TONE_RINGTONE))
03292             ast_log(LOG_WARNING, "Unable to generate call-wait ring-back on channel %s\n", ast->name);
03293       }
03294       n = ast->cid.cid_name;
03295       l = ast->cid.cid_num;
03296       if (l)
03297          ast_copy_string(p->lastcid_num, l, sizeof(p->lastcid_num));
03298       else
03299          p->lastcid_num[0] = '\0';
03300       if (n)
03301          ast_copy_string(p->lastcid_name, n, sizeof(p->lastcid_name));
03302       else
03303          p->lastcid_name[0] = '\0';
03304       ast_setstate(ast, AST_STATE_RINGING);
03305       idx = dahdi_get_index(ast, p, 0);
03306       if (idx > -1) {
03307          p->subs[idx].needringing = 1;
03308       }
03309       break;
03310    case SIG_FXSLS:
03311    case SIG_FXSGS:
03312    case SIG_FXSKS:
03313       if (p->answeronpolarityswitch || p->hanguponpolarityswitch) {
03314          ast_debug(1, "Ignore possible polarity reversal on line seizure\n");
03315          p->polaritydelaytv = ast_tvnow();
03316       }
03317       /* fall through */
03318    case SIG_EMWINK:
03319    case SIG_EM:
03320    case SIG_EM_E1:
03321    case SIG_FEATD:
03322    case SIG_FEATDMF:
03323    case SIG_E911:
03324    case SIG_FGC_CAMA:
03325    case SIG_FGC_CAMAMF:
03326    case SIG_FEATB:
03327    case SIG_SFWINK:
03328    case SIG_SF:
03329    case SIG_SF_FEATD:
03330    case SIG_SF_FEATDMF:
03331    case SIG_FEATDMF_TA:
03332    case SIG_SF_FEATB:
03333       c = strchr(dest, '/');
03334       if (c)
03335          c++;
03336       else
03337          c = "";
03338       if (strlen(c) < p->stripmsd) {
03339          ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
03340          ast_mutex_unlock(&p->lock);
03341          return -1;
03342       }
03343 #ifdef HAVE_PRI
03344       /* Start the trunk, if not GR-303 */
03345       if (!p->pri) {
03346 #endif
03347          x = DAHDI_START;
03348          res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
03349          if (res < 0) {
03350             if (errno != EINPROGRESS) {
03351                ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno));
03352                ast_mutex_unlock(&p->lock);
03353                return -1;
03354             }
03355          }
03356 #ifdef HAVE_PRI
03357       }
03358 #endif
03359       ast_debug(1, "Dialing '%s'\n", c);
03360       p->dop.op = DAHDI_DIAL_OP_REPLACE;
03361 
03362       c += p->stripmsd;
03363 
03364       switch (mysig) {
03365       case SIG_FEATD:
03366          l = ast->cid.cid_num;
03367          if (l)
03368             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T*%s*%s*", l, c);
03369          else
03370             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T**%s*", c);
03371          break;
03372       case SIG_FEATDMF:
03373          l = ast->cid.cid_num;
03374          if (l)
03375             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*00%s#*%s#", l, c);
03376          else
03377             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*02#*%s#", c);
03378          break;
03379       case SIG_FEATDMF_TA:
03380       {
03381          const char *cic, *ozz;
03382 
03383          /* If you have to go through a Tandem Access point you need to use this */
03384          ozz = pbx_builtin_getvar_helper(p->owner, "FEATDMF_OZZ");
03385          if (!ozz)
03386             ozz = defaultozz;
03387          cic = pbx_builtin_getvar_helper(p->owner, "FEATDMF_CIC");
03388          if (!cic)
03389             cic = defaultcic;
03390          if (!ozz || !cic) {
03391             ast_log(LOG_WARNING, "Unable to dial channel of type feature group D MF tandem access without CIC or OZZ set\n");
03392             ast_mutex_unlock(&p->lock);
03393             return -1;
03394          }
03395          snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s%s#", ozz, cic);
03396          snprintf(p->finaldial, sizeof(p->finaldial), "M*%s#", c);
03397          p->whichwink = 0;
03398       }
03399          break;
03400       case SIG_E911:
03401          ast_copy_string(p->dop.dialstr, "M*911#", sizeof(p->dop.dialstr));
03402          break;
03403       case SIG_FGC_CAMA:
03404          snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%s", c);
03405          break;
03406       case SIG_FGC_CAMAMF:
03407       case SIG_FEATB:
03408          snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s#", c);
03409          break;
03410       default:
03411          if (p->pulse)
03412             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%sw", c);
03413          else
03414             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%sw", c);
03415          break;
03416       }
03417 
03418       if (p->echotraining && (strlen(p->dop.dialstr) > 4)) {
03419          memset(p->echorest, 'w', sizeof(p->echorest) - 1);
03420          strcpy(p->echorest + (p->echotraining / 400) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
03421          p->echorest[sizeof(p->echorest) - 1] = '\0';
03422          p->echobreak = 1;
03423          p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
03424       } else
03425          p->echobreak = 0;
03426 
03427       /* waitfordialtone ? */
03428 #ifdef HAVE_PRI
03429       if (!p->pri) {
03430 #endif
03431          if( p->waitfordialtone && CANPROGRESSDETECT(p) && p->dsp ) {
03432             ast_log(LOG_DEBUG, "Defer dialling for %dms or dialtone\n", p->waitfordialtone);
03433             gettimeofday(&p->waitingfordt,NULL);
03434             ast_setstate(ast, AST_STATE_OFFHOOK);
03435             break;
03436          }
03437 #ifdef HAVE_PRI
03438       }
03439 #endif
03440       if (!res) {
03441          if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
03442             int saveerr = errno;
03443 
03444             x = DAHDI_ONHOOK;
03445             ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
03446             ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
03447             ast_mutex_unlock(&p->lock);
03448             return -1;
03449          }
03450       } else
03451          ast_debug(1, "Deferring dialing...\n");
03452 
03453       p->dialing = 1;
03454       if (ast_strlen_zero(c))
03455          p->dialednone = 1;
03456       ast_setstate(ast, AST_STATE_DIALING);
03457       break;
03458    case 0:
03459       /* Special pseudo -- automatically up*/
03460       ast_setstate(ast, AST_STATE_UP);
03461       break;
03462    case SIG_PRI:
03463    case SIG_BRI:
03464    case SIG_BRI_PTMP:
03465    case SIG_SS7:
03466    case SIG_MFCR2:
03467       /* We'll get it in a moment -- but use dialdest to store pre-setup_ack digits */
03468       p->dialdest[0] = '\0';
03469       p->dialing = 1;
03470       break;
03471    default:
03472       ast_debug(1, "not yet implemented\n");
03473       ast_mutex_unlock(&p->lock);
03474       return -1;
03475    }
03476 #ifdef HAVE_SS7
03477    if (p->ss7) {
03478       char ss7_called_nai;
03479       int called_nai_strip;
03480       char ss7_calling_nai;
03481       int calling_nai_strip;
03482       const char *charge_str = NULL;
03483       const char *gen_address = NULL;
03484       const char *gen_digits = NULL;
03485       const char *gen_dig_type = NULL;
03486       const char *gen_dig_scheme = NULL;
03487       const char *gen_name = NULL;
03488       const char *jip_digits = NULL;
03489       const char *lspi_ident = NULL;
03490       const char *rlt_flag = NULL;
03491       const char *call_ref_id = NULL;
03492       const char *call_ref_pc = NULL;
03493       const char *send_far = NULL;
03494 
03495       c = strchr(dest, '/');
03496       if (c) {
03497          c++;
03498       } else {
03499          c = "";
03500       }
03501       if (strlen(c) < p->stripmsd) {
03502          ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
03503          ast_mutex_unlock(&p->lock);
03504          return -1;
03505       }
03506 
03507       if (!p->hidecallerid) {
03508          l = ast->cid.cid_num;
03509       } else {
03510          l = NULL;
03511       }
03512 
03513       if (ss7_grab(p, p->ss7)) {
03514          ast_log(LOG_WARNING, "Failed to grab SS7!\n");
03515          ast_mutex_unlock(&p->lock);
03516          return -1;
03517       }
03518       p->digital = IS_DIGITAL(ast->transfercapability);
03519       p->ss7call = isup_new_call(p->ss7->ss7);
03520 
03521       if (!p->ss7call) {
03522          ss7_rel(p->ss7);
03523          ast_mutex_unlock(&p->lock);
03524          ast_log(LOG_ERROR, "Unable to allocate new SS7 call!\n");
03525          return -1;
03526       }
03527 
03528       called_nai_strip = 0;
03529       ss7_called_nai = p->ss7->called_nai;
03530       if (ss7_called_nai == SS7_NAI_DYNAMIC) { /* compute dynamically */
03531          if (strncmp(c + p->stripmsd, p->ss7->internationalprefix, strlen(p->ss7->internationalprefix)) == 0) {
03532             called_nai_strip = strlen(p->ss7->internationalprefix);
03533             ss7_called_nai = SS7_NAI_INTERNATIONAL;
03534          } else if (strncmp(c + p->stripmsd, p->ss7->nationalprefix, strlen(p->ss7->nationalprefix)) == 0) {
03535             called_nai_strip = strlen(p->ss7->nationalprefix);
03536             ss7_called_nai = SS7_NAI_NATIONAL;
03537          } else {
03538             ss7_called_nai = SS7_NAI_SUBSCRIBER;
03539          }
03540       }
03541       isup_set_called(p->ss7call, c + p->stripmsd + called_nai_strip, ss7_called_nai, p->ss7->ss7);
03542 
03543       calling_nai_strip = 0;
03544       ss7_calling_nai = p->ss7->calling_nai;
03545       if ((l != NULL) && (ss7_calling_nai == SS7_NAI_DYNAMIC)) { /* compute dynamically */
03546          if (strncmp(l, p->ss7->internationalprefix, strlen(p->ss7->internationalprefix)) == 0) {
03547             calling_nai_strip = strlen(p->ss7->internationalprefix);
03548             ss7_calling_nai = SS7_NAI_INTERNATIONAL;
03549          } else if (strncmp(l, p->ss7->nationalprefix, strlen(p->ss7->nationalprefix)) == 0) {
03550             calling_nai_strip = strlen(p->ss7->nationalprefix);
03551             ss7_calling_nai = SS7_NAI_NATIONAL;
03552          } else {
03553             ss7_calling_nai = SS7_NAI_SUBSCRIBER;
03554          }
03555       }
03556       isup_set_calling(p->ss7call, l ? (l + calling_nai_strip) : NULL, ss7_calling_nai,
03557          p->use_callingpres ? cid_pres2ss7pres(ast->cid.cid_pres) : (l ? SS7_PRESENTATION_ALLOWED : SS7_PRESENTATION_RESTRICTED),
03558          p->use_callingpres ? cid_pres2ss7screen(ast->cid.cid_pres) : SS7_SCREENING_USER_PROVIDED );
03559 
03560       isup_set_oli(p->ss7call, ast->cid.cid_ani2);
03561       isup_init_call(p->ss7->ss7, p->ss7call, p->cic, p->dpc);
03562 
03563       ast_channel_lock(ast);
03564       /* Set the charge number if it is set */
03565       charge_str = pbx_builtin_getvar_helper(ast, "SS7_CHARGE_NUMBER");
03566       if (charge_str)
03567          isup_set_charge(p->ss7call, charge_str, SS7_ANI_CALLING_PARTY_SUB_NUMBER, 0x10);
03568 
03569       gen_address = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_ADDRESS");
03570       if (gen_address)
03571          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 */
03572 
03573       gen_digits = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_DIGITS");
03574       gen_dig_type = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_DIGTYPE");
03575       gen_dig_scheme = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_DIGSCHEME");
03576       if (gen_digits)
03577          isup_set_gen_digits(p->ss7call, gen_digits, atoi(gen_dig_type), atoi(gen_dig_scheme));
03578 
03579       gen_name = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_NAME");
03580       if (gen_name)
03581          isup_set_generic_name(p->ss7call, gen_name, GEN_NAME_TYPE_CALLING_NAME, GEN_NAME_AVAIL_AVAILABLE, GEN_NAME_PRES_ALLOWED);
03582 
03583       jip_digits = pbx_builtin_getvar_helper(ast, "SS7_JIP");
03584       if (jip_digits)
03585          isup_set_jip_digits(p->ss7call, jip_digits);
03586 
03587       lspi_ident = pbx_builtin_getvar_helper(ast, "SS7_LSPI_IDENT");
03588       if (lspi_ident)
03589          isup_set_lspi(p->ss7call, lspi_ident, 0x18, 0x7, 0x00);
03590 
03591       rlt_flag = pbx_builtin_getvar_helper(ast, "SS7_RLT_ON");
03592       if ((rlt_flag) && ((strncmp("NO", rlt_flag, strlen(rlt_flag))) != 0 )) {
03593          isup_set_lspi(p->ss7call, rlt_flag, 0x18, 0x7, 0x00); /* Setting for Nortel DMS-250/500 */
03594       }
03595 
03596       call_ref_id = pbx_builtin_getvar_helper(ast, "SS7_CALLREF_IDENT");
03597       call_ref_pc = pbx_builtin_getvar_helper(ast, "SS7_CALLREF_PC");
03598       if (call_ref_id && call_ref_pc) {
03599          isup_set_callref(p->ss7call, atoi(call_ref_id),
03600                 call_ref_pc ? atoi(call_ref_pc) : 0);
03601       }
03602 
03603       send_far = pbx_builtin_getvar_helper(ast, "SS7_SEND_FAR");
03604       if ((send_far) && ((strncmp("NO", send_far, strlen(send_far))) != 0 ))
03605          (isup_far(p->ss7->ss7, p->ss7call));
03606 
03607       ast_channel_unlock(ast);
03608 
03609       p->call_level = DAHDI_CALL_LEVEL_SETUP;
03610       isup_iam(p->ss7->ss7, p->ss7call);
03611       ast_setstate(ast, AST_STATE_DIALING);
03612       ss7_rel(p->ss7);
03613    }
03614 #endif /* HAVE_SS7 */
03615 #ifdef HAVE_OPENR2
03616    if (p->mfcr2) {
03617       openr2_calling_party_category_t chancat;
03618       int callres = 0;
03619       char *c, *l;
03620 
03621       c = strchr(dest, '/');
03622       if (c) {
03623          c++;
03624       } else {
03625          c = "";
03626       }
03627       if (!p->hidecallerid) {
03628          l = ast->cid.cid_num;
03629       } else {
03630          l = NULL;
03631       }
03632       if (strlen(c) < p->stripmsd) {
03633          ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
03634          ast_mutex_unlock(&p->lock);
03635          return -1;
03636       }
03637       p->dialing = 1;
03638       ast_channel_lock(ast);
03639       chancat = dahdi_r2_get_channel_category(ast);
03640       ast_channel_unlock(ast);
03641       callres = openr2_chan_make_call(p->r2chan, l, (c + p->stripmsd), chancat);
03642       if (-1 == callres) {
03643          ast_mutex_unlock(&p->lock);
03644          ast_log(LOG_ERROR, "unable to make new MFC/R2 call!\n");
03645          return -1;
03646       }
03647       p->mfcr2_call_accepted = 0;
03648       p->mfcr2_progress = 0;
03649       ast_setstate(ast, AST_STATE_DIALING);
03650    }
03651 #endif /* HAVE_OPENR2 */
03652 #ifdef HAVE_PRI
03653    if (p->pri) {
03654       struct pri_sr *sr;
03655 #ifdef SUPPORT_USERUSER
03656       const char *useruser;
03657 #endif
03658       int pridialplan;
03659       int dp_strip;
03660       int prilocaldialplan;
03661       int ldp_strip;
03662       int exclusive;
03663       const char *rr_str;
03664       int redirect_reason;
03665 
03666       c = strchr(dest, '/');
03667       if (c) {
03668          c++;
03669       } else {
03670          c = "";
03671       }
03672 
03673       l = NULL;
03674       n = NULL;
03675       if (!p->hidecallerid) {
03676          /* If we get to the end of this loop without breaking, there's no
03677           * numeric calleridnum. This is done instead of testing for
03678           * "unknown" or the thousands of other ways that the calleridnum
03679           * could be invalid. */
03680          for (l = ast->cid.cid_num; l && *l; l++) {
03681             if (strchr("0123456789", *l)) {
03682                l = ast->cid.cid_num;
03683                break;
03684             }
03685          }
03686          if (!p->hidecalleridname) {
03687             n = ast->cid.cid_name;
03688          }
03689       }
03690 
03691       if (strlen(c) < p->stripmsd) {
03692          ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
03693          ast_mutex_unlock(&p->lock);
03694          return -1;
03695       }
03696       if (mysig != SIG_FXSKS) {
03697          p->dop.op = DAHDI_DIAL_OP_REPLACE;
03698          s = strchr(c + p->stripmsd, 'w');
03699          if (s) {
03700             if (strlen(s) > 1)
03701                snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%s", s);
03702             else
03703                p->dop.dialstr[0] = '\0';
03704             *s = '\0';
03705          } else {
03706             p->dop.dialstr[0] = '\0';
03707          }
03708       }
03709       if (pri_grab(p, p->pri)) {
03710          ast_log(LOG_WARNING, "Failed to grab PRI!\n");
03711          ast_mutex_unlock(&p->lock);
03712          return -1;
03713       }
03714       if (!(p->call = pri_new_call(p->pri->pri))) {
03715          ast_log(LOG_WARNING, "Unable to create call on channel %d\n", p->channel);
03716          pri_rel(p->pri);
03717          ast_mutex_unlock(&p->lock);
03718          return -1;
03719       }
03720       if (!(sr = pri_sr_new())) {
03721          ast_log(LOG_WARNING, "Failed to allocate setup request channel %d\n", p->channel);
03722          pri_rel(p->pri);
03723          ast_mutex_unlock(&p->lock);
03724       }
03725       if (p->bearer || (mysig == SIG_FXSKS)) {
03726          if (p->bearer) {
03727             ast_debug(1, "Oooh, I have a bearer on %d (%d:%d)\n", PVT_TO_CHANNEL(p->bearer), p->bearer->logicalspan, p->bearer->channel);
03728             p->bearer->call = p->call;
03729          } else
03730             ast_debug(1, "I'm being setup with no bearer right now...\n");
03731 
03732          pri_set_crv(p->pri->pri, p->call, p->channel, 0);
03733       }
03734       p->digital = IS_DIGITAL(ast->transfercapability);
03735 
03736       /* Should the picked channel be used exclusively? */
03737       if (p->priexclusive || p->pri->nodetype == PRI_NETWORK) {
03738          exclusive = 1;
03739       } else {
03740          exclusive = 0;
03741       }
03742 
03743       pri_sr_set_channel(sr, p->bearer ? PVT_TO_CHANNEL(p->bearer) : PVT_TO_CHANNEL(p), exclusive, 1);
03744       pri_sr_set_bearer(sr, p->digital ? PRI_TRANS_CAP_DIGITAL : ast->transfercapability,
03745          (p->digital ? -1 :
03746             ((p->law == DAHDI_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW)));
03747       if (p->pri->facilityenable)
03748          pri_facility_enable(p->pri->pri);
03749 
03750       ast_verb(3, "Requested transfer capability: 0x%.2x - %s\n", ast->transfercapability, ast_transfercapability2str(ast->transfercapability));
03751 
03752       dp_strip = 0;
03753       pridialplan = p->pri->dialplan - 1;
03754       if (pridialplan == -2 || pridialplan == -3) { /* compute dynamically */
03755          if (strncmp(c + p->stripmsd, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) {
03756             if (pridialplan == -2) {
03757                dp_strip = strlen(p->pri->internationalprefix);
03758             }
03759             pridialplan = PRI_INTERNATIONAL_ISDN;
03760          } else if (strncmp(c + p->stripmsd, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) {
03761             if (pridialplan == -2) {
03762                dp_strip = strlen(p->pri->nationalprefix);
03763             }
03764             pridialplan = PRI_NATIONAL_ISDN;
03765          } else {
03766             pridialplan = PRI_LOCAL_ISDN;
03767          }
03768       }
03769       while (c[p->stripmsd] > '9' && c[p->stripmsd] != '*' && c[p->stripmsd] != '#') {
03770          switch (c[p->stripmsd]) {
03771          case 'U':
03772             pridialplan = (PRI_TON_UNKNOWN << 4) | (pridialplan & 0xf);
03773             break;
03774          case 'I':
03775             pridialplan = (PRI_TON_INTERNATIONAL << 4) | (pridialplan & 0xf);
03776             break;
03777          case 'N':
03778             pridialplan = (PRI_TON_NATIONAL << 4) | (pridialplan & 0xf);
03779             break;
03780          case 'L':
03781             pridialplan = (PRI_TON_NET_SPECIFIC << 4) | (pridialplan & 0xf);
03782             break;
03783          case 'S':
03784             pridialplan = (PRI_TON_SUBSCRIBER << 4) | (pridialplan & 0xf);
03785             break;
03786          case 'V':
03787             pridialplan = (PRI_TON_ABBREVIATED << 4) | (pridialplan & 0xf);
03788             break;
03789          case 'R':
03790             pridialplan = (PRI_TON_RESERVED << 4) | (pridialplan & 0xf);
03791             break;
03792          case 'u':
03793             pridialplan = PRI_NPI_UNKNOWN | (pridialplan & 0xf0);
03794             break;
03795          case 'e':
03796             pridialplan = PRI_NPI_E163_E164 | (pridialplan & 0xf0);
03797             break;
03798          case 'x':
03799             pridialplan = PRI_NPI_X121 | (pridialplan & 0xf0);
03800             break;
03801          case 'f':
03802             pridialplan = PRI_NPI_F69 | (pridialplan & 0xf0);
03803             break;
03804          case 'n':
03805             pridialplan = PRI_NPI_NATIONAL | (pridialplan & 0xf0);
03806             break;
03807          case 'p':
03808             pridialplan = PRI_NPI_PRIVATE | (pridialplan & 0xf0);
03809             break;
03810          case 'r':
03811             pridialplan = PRI_NPI_RESERVED | (pridialplan & 0xf0);
03812             break;
03813          default:
03814             if (isalpha(c[p->stripmsd])) {
03815                ast_log(LOG_WARNING, "Unrecognized pridialplan %s modifier: %c\n",
03816                   c[p->stripmsd] > 'Z' ? "NPI" : "TON", c[p->stripmsd]);
03817             }
03818             break;
03819          }
03820          c++;
03821       }
03822       pri_sr_set_called(sr, c + p->stripmsd + dp_strip, pridialplan, s ? 1 : 0);
03823 
03824       ldp_strip = 0;
03825       prilocaldialplan = p->pri->localdialplan - 1;
03826       if ((l != NULL) && (prilocaldialplan == -2 || prilocaldialplan == -3)) { /* compute dynamically */
03827          if (strncmp(l, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) {
03828             if (prilocaldialplan == -2) {
03829                ldp_strip = strlen(p->pri->internationalprefix);
03830             }
03831             prilocaldialplan = PRI_INTERNATIONAL_ISDN;
03832          } else if (strncmp(l, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) {
03833             if (prilocaldialplan == -2) {
03834                ldp_strip = strlen(p->pri->nationalprefix);
03835             }
03836             prilocaldialplan = PRI_NATIONAL_ISDN;
03837          } else {
03838             prilocaldialplan = PRI_LOCAL_ISDN;
03839          }
03840       }
03841       if (l != NULL) {
03842          while (*l > '9' && *l != '*' && *l != '#') {
03843             switch (*l) {
03844             case 'U':
03845                prilocaldialplan = (PRI_TON_UNKNOWN << 4) | (prilocaldialplan & 0xf);
03846                break;
03847             case 'I':
03848                prilocaldialplan = (PRI_TON_INTERNATIONAL << 4) | (prilocaldialplan & 0xf);
03849                break;
03850             case 'N':
03851                prilocaldialplan = (PRI_TON_NATIONAL << 4) | (prilocaldialplan & 0xf);
03852                break;
03853             case 'L':
03854                prilocaldialplan = (PRI_TON_NET_SPECIFIC << 4) | (prilocaldialplan & 0xf);
03855                break;
03856             case 'S':
03857                prilocaldialplan = (PRI_TON_SUBSCRIBER << 4) | (prilocaldialplan & 0xf);
03858                break;
03859             case 'V':
03860                prilocaldialplan = (PRI_TON_ABBREVIATED << 4) | (prilocaldialplan & 0xf);
03861                break;
03862             case 'R':
03863                prilocaldialplan = (PRI_TON_RESERVED << 4) | (prilocaldialplan & 0xf);
03864                break;
03865             case 'u':
03866                prilocaldialplan = PRI_NPI_UNKNOWN | (prilocaldialplan & 0xf0);
03867                break;
03868             case 'e':
03869                prilocaldialplan = PRI_NPI_E163_E164 | (prilocaldialplan & 0xf0);
03870                break;
03871             case 'x':
03872                prilocaldialplan = PRI_NPI_X121 | (prilocaldialplan & 0xf0);
03873                break;
03874             case 'f':
03875                prilocaldialplan = PRI_NPI_F69 | (prilocaldialplan & 0xf0);
03876                break;
03877             case 'n':
03878                prilocaldialplan = PRI_NPI_NATIONAL | (prilocaldialplan & 0xf0);
03879                break;
03880             case 'p':
03881                prilocaldialplan = PRI_NPI_PRIVATE | (prilocaldialplan & 0xf0);
03882                break;
03883             case 'r':
03884                prilocaldialplan = PRI_NPI_RESERVED | (prilocaldialplan & 0xf0);
03885                break;
03886             default:
03887                if (isalpha(*l)) {
03888                   ast_log(LOG_WARNING,
03889                      "Unrecognized prilocaldialplan %s modifier: %c\n",
03890                      *l > 'Z' ? "NPI" : "TON", *l);
03891                }
03892                break;
03893             }
03894             l++;
03895          }
03896       }
03897       pri_sr_set_caller(sr, l ? (l + ldp_strip) : NULL, n, prilocaldialplan,
03898          p->use_callingpres ? ast->cid.cid_pres : (l ? PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN : PRES_NUMBER_NOT_AVAILABLE));
03899       if ((rr_str = pbx_builtin_getvar_helper(ast, "PRIREDIRECTREASON"))) {
03900          if (!strcasecmp(rr_str, "UNKNOWN"))
03901             redirect_reason = 0;
03902          else if (!strcasecmp(rr_str, "BUSY"))
03903             redirect_reason = 1;
03904          else if (!strcasecmp(rr_str, "NO_REPLY") || !strcasecmp(rr_str, "NOANSWER"))
03905          /* the NOANSWER is to match diversion-reason from chan_sip, (which never reads PRIREDIRECTREASON) */
03906             redirect_reason = 2;
03907          else if (!strcasecmp(rr_str, "UNCONDITIONAL"))
03908             redirect_reason = 15;
03909          else
03910             redirect_reason = PRI_REDIR_UNCONDITIONAL;
03911       } else
03912          redirect_reason = PRI_REDIR_UNCONDITIONAL;
03913       pri_sr_set_redirecting(sr, ast->cid.cid_rdnis, p->pri->localdialplan - 1, PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN, redirect_reason);
03914 
03915 #ifdef SUPPORT_USERUSER
03916       /* User-user info */
03917       useruser = pbx_builtin_getvar_helper(p->owner, "USERUSERINFO");
03918       if (useruser)
03919          pri_sr_set_useruser(sr, useruser);
03920 #endif
03921 
03922       if (pri_setup(p->pri->pri, p->call, sr)) {
03923          ast_log(LOG_WARNING, "Unable to setup call to %s (using %s)\n",
03924             c + p->stripmsd + dp_strip, dialplan2str(p->pri->dialplan));
03925          pri_destroycall(p->pri->pri, p->call);
03926          p->call = NULL;
03927          pri_rel(p->pri);
03928          ast_mutex_unlock(&p->lock);
03929          pri_sr_free(sr);
03930          return -1;
03931       }
03932       p->call_level = DAHDI_CALL_LEVEL_SETUP;
03933       pri_sr_free(sr);
03934       ast_setstate(ast, AST_STATE_DIALING);
03935       pri_rel(p->pri);
03936    }
03937 #endif
03938    ast_mutex_unlock(&p->lock);
03939    return 0;
03940 }
03941 
03942 static void destroy_dahdi_pvt(struct dahdi_pvt **pvt)
03943 {
03944    struct dahdi_pvt *p = *pvt;
03945    /* Remove channel from the list */
03946    if (p->prev)
03947       p->prev->next = p->next;
03948    if (p->next)
03949       p->next->prev = p->prev;
03950 
03951    ast_free(p->cidspill);
03952    if (p->use_smdi)
03953       ast_smdi_interface_unref(p->smdi_iface);
03954    if (p->mwi_event_sub)
03955       ast_event_unsubscribe(p->mwi_event_sub);
03956    if (p->vars) {
03957       ast_variables_destroy(p->vars);
03958    }
03959    ast_mutex_destroy(&p->lock);
03960    dahdi_close_sub(p, SUB_REAL);
03961    if (p->owner)
03962       p->owner->tech_pvt = NULL;
03963    free(p);
03964    *pvt = NULL;
03965 }
03966 
03967 static int destroy_channel(struct dahdi_pvt *prev, struct dahdi_pvt *cur, int now)
03968 {
03969    int owned = 0;
03970    int i = 0;
03971 
03972    if (!now) {
03973       if (cur->owner) {
03974          owned = 1;
03975       }
03976 
03977       for (i = 0; i < 3; i++) {
03978          if (cur->subs[i].owner) {
03979             owned = 1;
03980          }
03981       }
03982       if (!owned) {
03983          if (prev) {
03984             prev->next = cur->next;
03985             if (prev->next)
03986                prev->next->prev = prev;
03987             else
03988                ifend = prev;
03989          } else {
03990             iflist = cur->next;
03991             if (iflist)
03992                iflist->prev = NULL;
03993             else
03994                ifend = NULL;
03995          }
03996          destroy_dahdi_pvt(&cur);
03997       }
03998    } else {
03999       if (prev) {
04000          prev->next = cur->next;
04001          if (prev->next)
04002             prev->next->prev = prev;
04003          else
04004             ifend = prev;
04005       } else {
04006          iflist = cur->next;
04007          if (iflist)
04008             iflist->prev = NULL;
04009          else
04010             ifend = NULL;
04011       }
04012       destroy_dahdi_pvt(&cur);
04013    }
04014    return 0;
04015 }
04016 
04017 static void destroy_all_channels(void)
04018 {
04019    int x;
04020    struct dahdi_pvt *p, *pl;
04021 
04022    while (num_restart_pending) {
04023       usleep(1);
04024    }
04025 
04026    ast_mutex_lock(&iflock);
04027    /* Destroy all the interfaces and free their memory */
04028    p = iflist;
04029    while (p) {
04030       pl = p;
04031       p = p->next;
04032       x = pl->channel;
04033       /* Free associated memory */
04034       destroy_dahdi_pvt(&pl);
04035       if (option_verbose > 2)
04036          ast_verbose(VERBOSE_PREFIX_2 "Unregistered channel %d\n", x);
04037    }
04038    iflist = NULL;
04039    ifcount = 0;
04040    ast_mutex_unlock(&iflock);
04041 }
04042 
04043 #if defined(HAVE_PRI)
04044 static char *dahdi_send_keypad_facility_app = "DAHDISendKeypadFacility";
04045 
04046 static int dahdi_send_keypad_facility_exec(struct ast_channel *chan, void *data)
04047 {
04048    /* Data will be our digit string */
04049    struct dahdi_pvt *p;
04050    char *digits = (char *) data;
04051 
04052    if (ast_strlen_zero(digits)) {
04053       ast_debug(1, "No digit string sent to application!\n");
04054       return -1;
04055    }
04056 
04057    p = (struct dahdi_pvt *)chan->tech_pvt;
04058 
04059    if (!p) {
04060       ast_debug(1, "Unable to find technology private\n");
04061       return -1;
04062    }
04063 
04064    ast_mutex_lock(&p->lock);
04065 
04066    if (!p->pri || !p->call) {
04067       ast_debug(1, "Unable to find pri or call on channel!\n");
04068       ast_mutex_unlock(&p->lock);
04069       return -1;
04070    }
04071 
04072    if (!pri_grab(p, p->pri)) {
04073       pri_keypad_facility(p->pri->pri, p->call, digits);
04074       pri_rel(p->pri);
04075    } else {
04076       ast_debug(1, "Unable to grab pri to send keypad facility!\n");
04077       ast_mutex_unlock(&p->lock);
04078       return -1;
04079    }
04080 
04081    ast_mutex_unlock(&p->lock);
04082 
04083    return 0;
04084 }
04085 #endif   /* defined(HAVE_PRI) */
04086 
04087 #if defined(HAVE_PRI)
04088 #if defined(HAVE_PRI_PROG_W_CAUSE)
04089 static char *dahdi_send_callrerouting_facility_app = "DAHDISendCallreroutingFacility";
04090 
04091 static int dahdi_send_callrerouting_facility_exec(struct ast_channel *chan, void *data)
04092 {
04093    /* Data will be our digit string */
04094    struct dahdi_pvt *p;
04095    char *parse;
04096    int res = -1;
04097    AST_DECLARE_APP_ARGS(args,
04098       AST_APP_ARG(destination);
04099       AST_APP_ARG(original);
04100       AST_APP_ARG(reason);
04101    );
04102 
04103    if (ast_strlen_zero(data)) {
04104       ast_log(LOG_DEBUG, "No data sent to application!\n");
04105       return -1;
04106    }
04107 
04108    p = (struct dahdi_pvt *)chan->tech_pvt;
04109 
04110    if (!p) {
04111       ast_log(LOG_DEBUG, "Unable to find technology private\n");
04112       return -1;
04113    }
04114 
04115    parse = ast_strdupa(data);
04116    AST_STANDARD_APP_ARGS(args, parse);
04117 
04118    if (ast_strlen_zero(args.destination)) {
04119       ast_log(LOG_WARNING, "callrerouting facility requires at least destination number argument\n");
04120       return -1;
04121    }
04122 
04123    if (ast_strlen_zero(args.original)) {
04124       ast_log(LOG_WARNING, "Callrerouting Facility without original called number argument\n");
04125       args.original = NULL;
04126    }
04127 
04128    if (ast_strlen_zero(args.reason)) {
04129       ast_log(LOG_NOTICE, "Callrerouting Facility without diversion reason argument, defaulting to unknown\n");
04130       args.reason = NULL;
04131    }
04132 
04133    ast_mutex_lock(&p->lock);
04134 
04135    if (!p->pri || !p->call) {
04136       ast_log(LOG_DEBUG, "Unable to find pri or call on channel!\n");
04137       ast_mutex_unlock(&p->lock);
04138       return -1;
04139    }
04140 
04141    switch (p->sig) {
04142    case SIG_PRI:
04143       if (!pri_grab(p, p->pri)) {
04144          if (chan->_state == AST_STATE_RING) {
04145             res = pri_callrerouting_facility(p->pri->pri, p->call, args.destination, args.original, args.reason);
04146          }
04147          pri_rel(p->pri);
04148       } else {
04149          ast_log(LOG_DEBUG, "Unable to grab pri to send callrerouting facility on span %d!\n", p->span);
04150          ast_mutex_unlock(&p->lock);
04151          return -1;
04152       }
04153       break;
04154    }
04155 
04156    ast_mutex_unlock(&p->lock);
04157 
04158    return res;
04159 }
04160 #endif   /* defined(HAVE_PRI_PROG_W_CAUSE) */
04161 #endif   /* defined(HAVE_PRI) */
04162 
04163 #if defined(HAVE_PRI)
04164 static int pri_is_up(struct dahdi_pri *pri)
04165 {
04166    int x;
04167    for (x = 0; x < NUM_DCHANS; x++) {
04168       if (pri->dchanavail[x] == DCHAN_AVAILABLE)
04169          return 1;
04170    }
04171    return 0;
04172 }
04173 #endif   /* defined(HAVE_PRI) */
04174 
04175 #if defined(HAVE_PRI)
04176 static int pri_assign_bearer(struct dahdi_pvt *crv, struct dahdi_pri *pri, struct dahdi_pvt *bearer)
04177 {
04178    bearer->owner = &inuse;
04179    bearer->realcall = crv;
04180    crv->subs[SUB_REAL].dfd = bearer->subs[SUB_REAL].dfd;
04181    if (crv->subs[SUB_REAL].owner)
04182       ast_channel_set_fd(crv->subs[SUB_REAL].owner, 0, crv->subs[SUB_REAL].dfd);
04183    crv->bearer = bearer;
04184    crv->call = bearer->call;
04185    crv->pri = pri;
04186    return 0;
04187 }
04188 #endif   /* defined(HAVE_PRI) */
04189 
04190 #if defined(HAVE_PRI)
04191 static char *pri_order(int level)
04192 {
04193    switch (level) {
04194    case 0:
04195       return "Primary";
04196    case 1:
04197       return "Secondary";
04198    case 2:
04199       return "Tertiary";
04200    case 3:
04201       return "Quaternary";
04202    default:
04203       return "<Unknown>";
04204    }
04205 }
04206 #endif   /* defined(HAVE_PRI) */
04207 
04208 #if defined(HAVE_PRI)
04209 /* Returns fd of the active dchan */
04210 static int pri_active_dchan_fd(struct dahdi_pri *pri)
04211 {
04212    int x = -1;
04213 
04214    for (x = 0; x < NUM_DCHANS; x++) {
04215       if ((pri->dchans[x] == pri->pri))
04216          break;
04217    }
04218 
04219    return pri->fds[x];
04220 }
04221 #endif   /* defined(HAVE_PRI) */
04222 
04223 #if defined(HAVE_PRI)
04224 static int pri_find_dchan(struct dahdi_pri *pri)
04225 {
04226    int oldslot = -1;
04227    struct pri *old;
04228    int newslot = -1;
04229    int x;
04230    old = pri->pri;
04231    for (x = 0; x < NUM_DCHANS; x++) {
04232       if ((pri->dchanavail[x] == DCHAN_AVAILABLE) && (newslot < 0))
04233          newslot = x;
04234       if (pri->dchans[x] == old) {
04235          oldslot = x;
04236       }
04237    }
04238    if (newslot < 0) {
04239       newslot = 0;
04240       /* This is annoying to see on non persistent layer 2 connections.  Let's not complain in that case */
04241       if (pri->sig != SIG_BRI_PTMP && !pri->no_d_channels) {
04242          pri->no_d_channels = 1;
04243          ast_log(LOG_WARNING,
04244             "No D-channels available!  Using Primary channel %d as D-channel anyway!\n",
04245             pri->dchannels[newslot]);
04246       }
04247    } else {
04248       pri->no_d_channels = 0;
04249    }
04250    if (old && (oldslot != newslot))
04251       ast_log(LOG_NOTICE, "Switching from from d-channel %d to channel %d!\n",
04252          pri->dchannels[oldslot], pri->dchannels[newslot]);
04253    pri->pri = pri->dchans[newslot];
04254    return 0;
04255 }
04256 #endif   /* defined(HAVE_PRI) */
04257 
04258 #if defined(HAVE_OPENR2)
04259 static const char *dahdi_accept_r2_call_app = "DAHDIAcceptR2Call";
04260 
04261 static int dahdi_accept_r2_call_exec(struct ast_channel *chan, void *data)
04262 {
04263    /* data is whether to accept with charge or no charge */
04264    openr2_call_mode_t accept_mode;
04265    int res, timeout, maxloops;
04266    struct ast_frame *f;
04267    struct dahdi_pvt *p;
04268    char *parse;
04269    AST_DECLARE_APP_ARGS(args,
04270          AST_APP_ARG(charge);
04271    );
04272 
04273    if (ast_strlen_zero(data)) {
04274       ast_log(LOG_DEBUG, "No data sent to application!\n");
04275       return -1;
04276    }
04277 
04278    if (chan->tech != &dahdi_tech) {
04279       ast_log(LOG_DEBUG, "Only DAHDI technology accepted!\n");
04280       return -1;
04281    }
04282 
04283    p = (struct dahdi_pvt *)chan->tech_pvt;
04284    if (!p) {
04285       ast_log(LOG_DEBUG, "Unable to find technology private!\n");
04286       return -1;
04287    }
04288 
04289    parse = ast_strdupa(data);
04290    AST_STANDARD_APP_ARGS(args, parse);
04291 
04292    if (ast_strlen_zero(args.charge)) {
04293       ast_log(LOG_WARNING, "DAHDIAcceptR2Call requires 'yes' or 'no' for the charge parameter\n");
04294       return -1;
04295    }
04296 
04297    ast_mutex_lock(&p->lock);
04298    if (!p->mfcr2 || !p->mfcr2call) {
04299       ast_mutex_unlock(&p->lock);
04300       ast_log(LOG_DEBUG, "Channel %s does not seems to be an R2 active channel!\n", chan->name);
04301       return -1;
04302    }
04303 
04304    if (p->mfcr2_call_accepted) {
04305       ast_mutex_unlock(&p->lock);
04306       ast_log(LOG_DEBUG, "MFC/R2 call already accepted on channel %s!\n", chan->name);
04307       return 0;
04308    }
04309    accept_mode = ast_true(args.charge) ? OR2_CALL_WITH_CHARGE : OR2_CALL_NO_CHARGE;
04310    if (openr2_chan_accept_call(p->r2chan, accept_mode)) {
04311       ast_mutex_unlock(&p->lock);
04312       ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n");
04313       return -1;
04314    }
04315    ast_mutex_unlock(&p->lock);
04316 
04317    res = 0;
04318    timeout = 100;
04319    maxloops = 50; /* wait up to 5 seconds */
04320    /* we need to read() until the call is accepted */
04321    while (maxloops > 0) {
04322       maxloops--;
04323       if (ast_check_hangup(chan)) {
04324          break;
04325       }
04326       res = ast_waitfor(chan, timeout);
04327       if (res < 0) {
04328          ast_log(LOG_DEBUG, "ast_waitfor failed on channel %s, going out ...\n", chan->name);
04329          res = -1;
04330          break;
04331       }
04332       if (res == 0) {
04333          continue;
04334       }
04335       f = ast_read(chan);
04336       if (!f) {
04337          ast_log(LOG_DEBUG, "No frame read on channel %s, going out ...\n", chan->name);
04338          res = -1;
04339          break;
04340       }
04341       if (f->frametype == AST_FRAME_CONTROL && f->subclass == AST_CONTROL_HANGUP) {
04342          ast_log(LOG_DEBUG, "Got HANGUP frame on channel %s, going out ...\n", chan->name);
04343          ast_frfree(f);
04344          res = -1;
04345          break;
04346       }
04347       ast_frfree(f);
04348       ast_mutex_lock(&p->lock);
04349       if (p->mfcr2_call_accepted) {
04350          ast_mutex_unlock(&p->lock);
04351          ast_log(LOG_DEBUG, "Accepted MFC/R2 call!\n");
04352          break;
04353       }
04354       ast_mutex_unlock(&p->lock);
04355    }
04356    if (res == -1) {
04357       ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n");
04358    }
04359    return res;
04360 }
04361 
04362 static openr2_call_disconnect_cause_t dahdi_ast_cause_to_r2_cause(int cause)
04363 {
04364    openr2_call_disconnect_cause_t r2cause = OR2_CAUSE_NORMAL_CLEARING;
04365    switch (cause) {
04366    case AST_CAUSE_USER_BUSY:
04367    case AST_CAUSE_CALL_REJECTED:
04368    case AST_CAUSE_INTERWORKING: /* I don't know wtf is this but is used sometimes when ekiga rejects a call */
04369       r2cause = OR2_CAUSE_BUSY_NUMBER;
04370       break;
04371 
04372    case AST_CAUSE_NORMAL_CIRCUIT_CONGESTION:
04373    case AST_CAUSE_SWITCH_CONGESTION:
04374       r2cause = OR2_CAUSE_NETWORK_CONGESTION;
04375       break;
04376 
04377    case AST_CAUSE_UNALLOCATED:
04378       r2cause = OR2_CAUSE_UNALLOCATED_NUMBER;
04379       break;
04380 
04381    case AST_CAUSE_NETWORK_OUT_OF_ORDER:
04382    case AST_CAUSE_DESTINATION_OUT_OF_ORDER:
04383       r2cause = OR2_CAUSE_OUT_OF_ORDER;
04384       break;
04385 
04386    case AST_CAUSE_NO_ANSWER:
04387    case AST_CAUSE_NO_USER_RESPONSE:
04388       r2cause = OR2_CAUSE_NO_ANSWER;
04389       break;
04390 
04391    default:
04392       r2cause = OR2_CAUSE_NORMAL_CLEARING;
04393       break;
04394    }
04395    ast_log(LOG_DEBUG, "ast cause %d resulted in openr2 cause %d/%s\n",
04396          cause, r2cause, openr2_proto_get_disconnect_string(r2cause));
04397    return r2cause;
04398 }
04399 #endif
04400 
04401 static int dahdi_hangup(struct ast_channel *ast)
04402 {
04403    int res;
04404    int idx,x, law;
04405    /*static int restore_gains(struct dahdi_pvt *p);*/
04406    struct dahdi_pvt *p = ast->tech_pvt;
04407    struct dahdi_pvt *tmp = NULL;
04408    struct dahdi_pvt *prev = NULL;
04409    struct dahdi_params par;
04410 
04411    ast_debug(1, "dahdi_hangup(%s)\n", ast->name);
04412    if (!ast->tech_pvt) {
04413       ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
04414       return 0;
04415    }
04416 
04417    ast_mutex_lock(&p->lock);
04418 
04419    idx = dahdi_get_index(ast, p, 1);
04420 
04421    switch (p->sig) {
04422    case SIG_PRI:
04423    case SIG_BRI:
04424    case SIG_BRI_PTMP:
04425    case SIG_SS7:
04426       x = 1;
04427       ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
04428       /* Fall through */
04429    case SIG_MFCR2:
04430       p->cid_num[0] = '\0';
04431       p->cid_name[0] = '\0';
04432       break;
04433    default:
04434       break;
04435    }
04436 
04437    x = 0;
04438    dahdi_confmute(p, 0);
04439    p->muting = 0;
04440    restore_gains(p);
04441    if (p->origcid_num) {
04442       ast_copy_string(p->cid_num, p->origcid_num, sizeof(p->cid_num));
04443       ast_free(p->origcid_num);
04444       p->origcid_num = NULL;
04445    }
04446    if (p->origcid_name) {
04447       ast_copy_string(p->cid_name, p->origcid_name, sizeof(p->cid_name));
04448       ast_free(p->origcid_name);
04449       p->origcid_name = NULL;
04450    }
04451    if (p->dsp)
04452       ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
04453    p->exten[0] = '\0';
04454 
04455    ast_debug(1, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n",
04456       p->channel, idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
04457    p->ignoredtmf = 0;
04458 
04459    if (idx > -1) {
04460       /* Real channel, do some fixup */
04461       p->subs[idx].owner = NULL;
04462       p->subs[idx].needanswer = 0;
04463       p->subs[idx].needflash = 0;
04464       p->subs[idx].needringing = 0;
04465       p->subs[idx].needbusy = 0;
04466       p->subs[idx].needcongestion = 0;
04467       p->subs[idx].linear = 0;
04468       p->subs[idx].needcallerid = 0;
04469       p->polarity = POLARITY_IDLE;
04470       dahdi_setlinear(p->subs[idx].dfd, 0);
04471       switch (idx) {
04472       case SUB_REAL:
04473          if ((p->subs[SUB_CALLWAIT].dfd > -1) && (p->subs[SUB_THREEWAY].dfd > -1)) {
04474             ast_debug(1, "Normal call hung up with both three way call and a call waiting call in place?\n");
04475             if (p->subs[SUB_CALLWAIT].inthreeway) {
04476                /* We had flipped over to answer a callwait and now it's gone */
04477                ast_debug(1, "We were flipped over to the callwait, moving back and unowning.\n");
04478                /* Move to the call-wait, but un-own us until they flip back. */
04479                swap_subs(p, SUB_CALLWAIT, SUB_REAL);
04480                unalloc_sub(p, SUB_CALLWAIT);
04481                p->owner = NULL;
04482             } else {
04483                /* The three way hung up, but we still have a call wait */
04484                ast_debug(1, "We were in the threeway and have a callwait still.  Ditching the threeway.\n");
04485                swap_subs(p, SUB_THREEWAY, SUB_REAL);
04486                unalloc_sub(p, SUB_THREEWAY);
04487                if (p->subs[SUB_REAL].inthreeway) {
04488                   /* This was part of a three way call.  Immediately make way for
04489                      another call */
04490                   ast_debug(1, "Call was complete, setting owner to former third call\n");
04491                   p->subs[SUB_REAL].inthreeway = 0;
04492                   p->owner = p->subs[SUB_REAL].owner;
04493                } else {
04494                   /* This call hasn't been completed yet...  Set owner to NULL */
04495                   ast_debug(1, "Call was incomplete, setting owner to NULL\n");
04496                   p->owner = NULL;
04497                }
04498             }
04499          } else if (p->subs[SUB_CALLWAIT].dfd > -1) {
04500             /* Need to hold the lock for real-call, private, and call-waiting call */
04501             dahdi_lock_sub_owner(p, SUB_CALLWAIT);
04502             if (!p->subs[SUB_CALLWAIT].owner) {
04503                /* The call waiting call dissappeared. */
04504                p->owner = NULL;
04505                break;
04506             }
04507 
04508             /* Move to the call-wait and switch back to them. */
04509             swap_subs(p, SUB_CALLWAIT, SUB_REAL);
04510             unalloc_sub(p, SUB_CALLWAIT);
04511             p->owner = p->subs[SUB_REAL].owner;
04512             if (p->owner->_state != AST_STATE_UP)
04513                p->subs[SUB_REAL].needanswer = 1;
04514             if (ast_bridged_channel(p->subs[SUB_REAL].owner))
04515                ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
04516             /* Unlock the call-waiting call that we swapped to real-call. */
04517             ast_channel_unlock(p->subs[SUB_REAL].owner);
04518          } else if (p->subs[SUB_THREEWAY].dfd > -1) {
04519             swap_subs(p, SUB_THREEWAY, SUB_REAL);
04520             unalloc_sub(p, SUB_THREEWAY);
04521             if (p->subs[SUB_REAL].inthreeway) {
04522                /* This was part of a three way call.  Immediately make way for
04523                   another call */
04524                ast_debug(1, "Call was complete, setting owner to former third call\n");
04525                p->subs[SUB_REAL].inthreeway = 0;
04526                p->owner = p->subs[SUB_REAL].owner;
04527             } else {
04528                /* This call hasn't been completed yet...  Set owner to NULL */
04529                ast_debug(1, "Call was incomplete, setting owner to NULL\n");
04530                p->owner = NULL;
04531             }
04532          }
04533          break;
04534       case SUB_CALLWAIT:
04535          /* Ditch the holding callwait call, and immediately make it availabe */
04536          if (p->subs[SUB_CALLWAIT].inthreeway) {
04537             /* Need to hold the lock for call-waiting call, private, and 3-way call */
04538             dahdi_lock_sub_owner(p, SUB_THREEWAY);
04539 
04540             /* This is actually part of a three way, placed on hold.  Place the third part
04541                on music on hold now */
04542             if (p->subs[SUB_THREEWAY].owner && ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
04543                ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
04544                   S_OR(p->mohsuggest, NULL),
04545                   !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
04546             }
04547             p->subs[SUB_THREEWAY].inthreeway = 0;
04548             /* Make it the call wait now */
04549             swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
04550             unalloc_sub(p, SUB_THREEWAY);
04551             if (p->subs[SUB_CALLWAIT].owner) {
04552                /* Unlock the 3-way call that we swapped to call-waiting call. */
04553                ast_channel_unlock(p->subs[SUB_CALLWAIT].owner);
04554             }
04555          } else
04556             unalloc_sub(p, SUB_CALLWAIT);
04557          break;
04558       case SUB_THREEWAY:
04559          /* Need to hold the lock for 3-way call, private, and call-waiting call */
04560          dahdi_lock_sub_owner(p, SUB_CALLWAIT);
04561          if (p->subs[SUB_CALLWAIT].inthreeway) {
04562             /* The other party of the three way call is currently in a call-wait state.
04563                Start music on hold for them, and take the main guy out of the third call */
04564             p->subs[SUB_CALLWAIT].inthreeway = 0;
04565             if (p->subs[SUB_CALLWAIT].owner && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
04566                ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
04567                   S_OR(p->mohsuggest, NULL),
04568                   !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
04569             }
04570          }
04571          if (p->subs[SUB_CALLWAIT].owner) {
04572             ast_channel_unlock(p->subs[SUB_CALLWAIT].owner);
04573          }
04574          p->subs[SUB_REAL].inthreeway = 0;
04575          /* If this was part of a three way call index, let us make
04576             another three way call */
04577          unalloc_sub(p, SUB_THREEWAY);
04578          break;
04579       default:
04580          /*
04581           * Should never happen.
04582           * This wasn't any sort of call, so how are we an index?
04583           */
04584          ast_log(LOG_ERROR, "Index found but not any type of call?\n");
04585          break;
04586       }
04587    }
04588 
04589    if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) {
04590       p->owner = NULL;
04591       p->ringt = 0;
04592       p->distinctivering = 0;
04593       p->confirmanswer = 0;
04594       p->cidrings = 1;
04595       p->outgoing = 0;
04596       p->digital = 0;
04597       p->faxhandled = 0;
04598       p->pulsedial = 0;
04599       p->onhooktime = time(NULL);
04600 #if defined(HAVE_PRI) || defined(HAVE_SS7)
04601       p->dialing = 0;
04602       p->progress = 0;
04603       p->rlt = 0;
04604       p->call_level = DAHDI_CALL_LEVEL_IDLE;
04605 #endif
04606       if (p->dsp) {
04607          ast_dsp_free(p->dsp);
04608          p->dsp = NULL;
04609       }
04610 
04611       if (p->bufferoverrideinuse) {
04612          /* faxbuffers are in use, revert them */
04613          struct dahdi_bufferinfo bi = {
04614             .txbufpolicy = p->buf_policy,
04615             .rxbufpolicy = p->buf_policy,
04616             .bufsize = p->bufsize,
04617             .numbufs = p->buf_no
04618          };
04619          int bpres;
04620 
04621          if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
04622             ast_log(LOG_WARNING, "Channel '%s' unable to revert faxbuffer policy: %s\n", ast->name, strerror(errno));
04623          }
04624          p->bufferoverrideinuse = 0;
04625       }
04626 
04627       law = DAHDI_LAW_DEFAULT;
04628       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
04629       if (res < 0)
04630          ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
04631       /* Perform low level hangup if no owner left */
04632 #ifdef HAVE_SS7
04633       if (p->ss7) {
04634          if (p->ss7call) {
04635             if (!ss7_grab(p, p->ss7)) {
04636                if (!p->alreadyhungup) {
04637                   const char *cause = pbx_builtin_getvar_helper(ast,"SS7_CAUSE");
04638                   int icause = ast->hangupcause ? ast->hangupcause : -1;
04639 
04640                   if (cause) {
04641                      if (atoi(cause))
04642                         icause = atoi(cause);
04643                   }
04644                   isup_rel(p->ss7->ss7, p->ss7call, icause);
04645                   ss7_rel(p->ss7);
04646                   p->alreadyhungup = 1;
04647                } else
04648                   ast_log(LOG_WARNING, "Trying to hangup twice!\n");
04649             } else {
04650                ast_log(LOG_WARNING, "Unable to grab SS7 on CIC %d\n", p->cic);
04651                res = -1;
04652             }
04653          }
04654       }
04655 #endif
04656 #ifdef HAVE_OPENR2
04657       if (p->mfcr2 && p->mfcr2call && openr2_chan_get_direction(p->r2chan) != OR2_DIR_STOPPED) {
04658          ast_log(LOG_DEBUG, "disconnecting MFC/R2 call on chan %d\n", p->channel);
04659          /* If it's an incoming call, check the mfcr2_forced_release setting */
04660          if (openr2_chan_get_direction(p->r2chan) == OR2_DIR_BACKWARD && p->mfcr2_forced_release) {
04661             dahdi_r2_disconnect_call(p, OR2_CAUSE_FORCED_RELEASE);
04662          } else {
04663             const char *r2causestr = pbx_builtin_getvar_helper(ast, "MFCR2_CAUSE");
04664             int r2cause_user = r2causestr ? atoi(r2causestr) : 0;
04665             openr2_call_disconnect_cause_t r2cause = r2cause_user ? dahdi_ast_cause_to_r2_cause(r2cause_user)
04666                                                              : dahdi_ast_cause_to_r2_cause(ast->hangupcause);
04667             dahdi_r2_disconnect_call(p, r2cause);
04668          }
04669       } else if (p->mfcr2call) {
04670          ast_log(LOG_DEBUG, "Clearing call request on channel %d\n", p->channel);
04671          /* since ast_request() was called but not ast_call() we have not yet dialed
04672          and the openr2 stack will not call on_call_end callback, we need to unset
04673          the mfcr2call flag and bump the monitor count so the monitor thread can take
04674          care of this channel events from now on */
04675          p->mfcr2call = 0;
04676       }
04677 #endif
04678 #ifdef HAVE_PRI
04679       if (p->pri) {
04680 #ifdef SUPPORT_USERUSER
04681          const char *useruser = pbx_builtin_getvar_helper(ast,"USERUSERINFO");
04682 #endif
04683 
04684          /* Make sure we have a call (or REALLY have a call in the case of a PRI) */
04685          if (p->call && (!p->bearer || (p->bearer->call == p->call))) {
04686             if (!pri_grab(p, p->pri)) {
04687                if (p->alreadyhungup) {
04688                   ast_debug(1, "Already hungup...  Calling hangup once, and clearing call\n");
04689 
04690 #ifdef SUPPORT_USERUSER
04691                   pri_call_set_useruser(p->call, useruser);
04692 #endif
04693 
04694                   pri_hangup(p->pri->pri, p->call, -1);
04695                   p->call = NULL;
04696                   if (p->bearer)
04697                      p->bearer->call = NULL;
04698                } else {
04699                   const char *cause = pbx_builtin_getvar_helper(ast,"PRI_CAUSE");
04700                   int icause = ast->hangupcause ? ast->hangupcause : -1;
04701                   ast_debug(1, "Not yet hungup...  Calling hangup once with icause, and clearing call\n");
04702 
04703 #ifdef SUPPORT_USERUSER
04704                   pri_call_set_useruser(p->call, useruser);
04705 #endif
04706 
04707                   p->alreadyhungup = 1;
04708                   if (p->bearer)
04709                      p->bearer->alreadyhungup = 1;
04710                   if (cause) {
04711                      if (atoi(cause))
04712                         icause = atoi(cause);
04713                   }
04714                   pri_hangup(p->pri->pri, p->call, icause);
04715                }
04716                if (res < 0)
04717                   ast_log(LOG_WARNING, "pri_disconnect failed\n");
04718                pri_rel(p->pri);
04719             } else {
04720                ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
04721                res = -1;
04722             }
04723          } else {
04724             if (p->bearer)
04725                ast_debug(1, "Bearer call is %p, while ours is still %p\n", p->bearer->call, p->call);
04726             p->call = NULL;
04727             res = 0;
04728          }
04729       }
04730 #endif
04731       if (p->sig && ((p->sig != SIG_PRI) && (p->sig != SIG_SS7)
04732          && (p->sig != SIG_BRI)
04733          && (p->sig != SIG_BRI_PTMP))
04734          && (p->sig != SIG_MFCR2))
04735          res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
04736       if (res < 0) {
04737          ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast->name);
04738       }
04739       switch (p->sig) {
04740       case SIG_FXOGS:
04741       case SIG_FXOLS:
04742       case SIG_FXOKS:
04743          memset(&par, 0, sizeof(par));
04744          res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
04745          if (!res) {
04746 #if 0
04747             ast_debug(1, "Hanging up channel %d, offhook = %d\n", p->channel, par.rxisoffhook);
04748 #endif
04749             /* If they're off hook, try playing congestion */
04750             if ((par.rxisoffhook) && (!(p->radio || (p->oprmode < 0))))
04751                tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
04752             else
04753                tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
04754             p->fxsoffhookstate = par.rxisoffhook;
04755          }
04756          break;
04757       case SIG_FXSGS:
04758       case SIG_FXSLS:
04759       case SIG_FXSKS:
04760          /* Make sure we're not made available for at least two seconds assuming
04761             we were actually used for an inbound or outbound call. */
04762          if (ast->_state != AST_STATE_RESERVED) {
04763             time(&p->guardtime);
04764             p->guardtime += 2;
04765          }
04766          break;
04767       default:
04768          tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
04769       }
04770       ast_free(p->cidspill);
04771       p->cidspill = NULL;
04772       if (p->sig)
04773          dahdi_disable_ec(p);
04774       x = 0;
04775       ast_channel_setoption(ast,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0);
04776       ast_channel_setoption(ast,AST_OPTION_TDD,&x,sizeof(char),0);
04777       p->didtdd = 0;
04778       p->callwaitcas = 0;
04779       p->callwaiting = p->permcallwaiting;
04780       p->hidecallerid = p->permhidecallerid;
04781       p->waitingfordt.tv_sec = 0;
04782       p->dialing = 0;
04783       p->rdnis[0] = '\0';
04784       update_conf(p);
04785       reset_conf(p);
04786       /* Restore data mode */
04787       if ((p->sig == SIG_PRI) || (p->sig == SIG_SS7) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) {
04788          x = 0;
04789          ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
04790       }
04791 #ifdef HAVE_PRI
04792       if (p->bearer) {
04793          ast_debug(1, "Freeing up bearer channel %d\n", p->bearer->channel);
04794          /* Free up the bearer channel as well, and
04795             don't use its file descriptor anymore */
04796          update_conf(p->bearer);
04797          reset_conf(p->bearer);
04798          p->bearer->owner = NULL;
04799          p->bearer->realcall = NULL;
04800          p->bearer = NULL;
04801          p->subs[SUB_REAL].dfd = -1;
04802          p->pri = NULL;
04803       }
04804 #endif
04805       if (num_restart_pending == 0)
04806          restart_monitor();
04807    }
04808 
04809    p->callwaitingrepeat = 0;
04810    p->cidcwexpire = 0;
04811    p->cid_suppress_expire = 0;
04812    p->oprmode = 0;
04813    ast->tech_pvt = NULL;
04814    ast_mutex_unlock(&p->lock);
04815    ast_module_unref(ast_module_info->self);
04816    ast_verb(3, "Hungup '%s'\n", ast->name);
04817 
04818    ast_mutex_lock(&iflock);
04819 
04820    if (p->restartpending) {
04821       num_restart_pending--;
04822    }
04823 
04824    tmp = iflist;
04825    prev = NULL;
04826    if (p->destroy) {
04827       while (tmp) {
04828          if (tmp == p) {
04829             destroy_channel(prev, tmp, 0);
04830             break;
04831          } else {
04832             prev = tmp;
04833             tmp = tmp->next;
04834          }
04835       }
04836    }
04837    ast_mutex_unlock(&iflock);
04838    return 0;
04839 }
04840 
04841 static int dahdi_answer(struct ast_channel *ast)
04842 {
04843    struct dahdi_pvt *p = ast->tech_pvt;
04844    int res = 0;
04845    int idx;
04846    int oldstate = ast->_state;
04847    ast_setstate(ast, AST_STATE_UP);
04848    ast_mutex_lock(&p->lock);
04849    idx = dahdi_get_index(ast, p, 0);
04850    if (idx < 0)
04851       idx = SUB_REAL;
04852    /* nothing to do if a radio channel */
04853    if ((p->radio || (p->oprmode < 0))) {
04854       ast_mutex_unlock(&p->lock);
04855       return 0;
04856    }
04857    switch (p->sig) {
04858    case SIG_FXSLS:
04859    case SIG_FXSGS:
04860    case SIG_FXSKS:
04861       p->ringt = 0;
04862       /* Fall through */
04863    case SIG_EM:
04864    case SIG_EM_E1:
04865    case SIG_EMWINK:
04866    case SIG_FEATD:
04867    case SIG_FEATDMF:
04868    case SIG_FEATDMF_TA:
04869    case SIG_E911:
04870    case SIG_FGC_CAMA:
04871    case SIG_FGC_CAMAMF:
04872    case SIG_FEATB:
04873    case SIG_SF:
04874    case SIG_SFWINK:
04875    case SIG_SF_FEATD:
04876    case SIG_SF_FEATDMF:
04877    case SIG_SF_FEATB:
04878    case SIG_FXOLS:
04879    case SIG_FXOGS:
04880    case SIG_FXOKS:
04881       /* Pick up the line */
04882       ast_debug(1, "Took %s off hook\n", ast->name);
04883       if (p->hanguponpolarityswitch) {
04884          p->polaritydelaytv = ast_tvnow();
04885       }
04886       res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
04887       tone_zone_play_tone(p->subs[idx].dfd, -1);
04888       p->dialing = 0;
04889       if ((idx == SUB_REAL) && p->subs[SUB_THREEWAY].inthreeway) {
04890          if (oldstate == AST_STATE_RINGING) {
04891             ast_debug(1, "Finally swapping real and threeway\n");
04892             tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, -1);
04893             swap_subs(p, SUB_THREEWAY, SUB_REAL);
04894             p->owner = p->subs[SUB_REAL].owner;
04895          }
04896       }
04897       if (p->sig & __DAHDI_SIG_FXS) {
04898          dahdi_enable_ec(p);
04899          dahdi_train_ec(p);
04900       }
04901       break;
04902 #ifdef HAVE_PRI
04903    case SIG_BRI:
04904    case SIG_BRI_PTMP:
04905    case SIG_PRI:
04906       /* Send a pri acknowledge */
04907       if (!pri_grab(p, p->pri)) {
04908          if (p->call_level < DAHDI_CALL_LEVEL_CONNECT) {
04909             p->call_level = DAHDI_CALL_LEVEL_CONNECT;
04910          }
04911          p->dialing = 0;
04912          res = pri_answer(p->pri->pri, p->call, 0, !p->digital);
04913          pri_rel(p->pri);
04914       } else {
04915          ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
04916          res = -1;
04917       }
04918       break;
04919 #endif
04920 #ifdef HAVE_SS7
04921    case SIG_SS7:
04922       if (!ss7_grab(p, p->ss7)) {
04923          if (p->call_level < DAHDI_CALL_LEVEL_CONNECT) {
04924             p->call_level = DAHDI_CALL_LEVEL_CONNECT;
04925          }
04926          res = isup_anm(p->ss7->ss7, p->ss7call);
04927          ss7_rel(p->ss7);
04928       } else {
04929          ast_log(LOG_WARNING, "Unable to grab SS7 on span %d\n", p->span);
04930          res = -1;
04931       }
04932       break;
04933 #endif
04934 #ifdef HAVE_OPENR2
04935    case SIG_MFCR2:
04936       if (!p->mfcr2_call_accepted) {
04937          /* The call was not accepted on offer nor the user, so it must be accepted now before answering,
04938             openr2_chan_answer_call will be called when the callback on_call_accepted is executed */
04939          p->mfcr2_answer_pending = 1;
04940          if (p->mfcr2_charge_calls) {
04941             ast_log(LOG_DEBUG, "Accepting MFC/R2 call with charge before answering on chan %d\n", p->channel);
04942             openr2_chan_accept_call(p->r2chan, OR2_CALL_WITH_CHARGE);
04943          } else {
04944             ast_log(LOG_DEBUG, "Accepting MFC/R2 call with no charge before answering on chan %d\n", p->channel);
04945             openr2_chan_accept_call(p->r2chan, OR2_CALL_NO_CHARGE);
04946          }
04947       } else {
04948          ast_log(LOG_DEBUG, "Answering MFC/R2 call on chan %d\n", p->channel);
04949          dahdi_r2_answer(p);
04950       }
04951       break;
04952 #endif
04953    case 0:
04954       ast_mutex_unlock(&p->lock);
04955       return 0;
04956    default:
04957       ast_log(LOG_WARNING, "Don't know how to answer signalling %d (channel %d)\n", p->sig, p->channel);
04958       res = -1;
04959    }
04960    ast_mutex_unlock(&p->lock);
04961    return res;
04962 }
04963 
04964 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen)
04965 {
04966    char *cp;
04967    signed char *scp;
04968    int x;
04969    int idx;
04970    struct dahdi_pvt *p = chan->tech_pvt, *pp;
04971    struct oprmode *oprmode;
04972 
04973 
04974    /* all supported options require data */
04975    if (!data || (datalen < 1)) {
04976       errno = EINVAL;
04977       return -1;
04978    }
04979 
04980    switch (option) {
04981    case AST_OPTION_TXGAIN:
04982       scp = (signed char *) data;
04983       idx = dahdi_get_index(chan, p, 0);
04984       if (idx < 0) {
04985          ast_log(LOG_WARNING, "No index in TXGAIN?\n");
04986          return -1;
04987       }
04988       ast_debug(1, "Setting actual tx gain on %s to %f\n", chan->name, p->txgain + (float) *scp);
04989       return set_actual_txgain(p->subs[idx].dfd, 0, p->txgain + (float) *scp, p->law);
04990    case AST_OPTION_RXGAIN:
04991       scp = (signed char *) data;
04992       idx = dahdi_get_index(chan, p, 0);
04993       if (idx < 0) {
04994          ast_log(LOG_WARNING, "No index in RXGAIN?\n");
04995          return -1;
04996       }
04997       ast_debug(1, "Setting actual rx gain on %s to %f\n", chan->name, p->rxgain + (float) *scp);
04998       return set_actual_rxgain(p->subs[idx].dfd, 0, p->rxgain + (float) *scp, p->law);
04999    case AST_OPTION_TONE_VERIFY:
05000       if (!p->dsp)
05001          break;
05002       cp = (char *) data;
05003       switch (*cp) {
05004       case 1:
05005          ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",chan->name);
05006          ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | p->dtmfrelax);  /* set mute mode if desired */
05007          break;
05008       case 2:
05009          ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",chan->name);
05010          ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX | p->dtmfrelax);  /* set mute mode if desired */
05011          break;
05012       default:
05013          ast_debug(1, "Set option TONE VERIFY, mode: OFF(0) on %s\n",chan->name);
05014          ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);  /* set mute mode if desired */
05015          break;
05016       }
05017       break;
05018    case AST_OPTION_TDD:
05019       /* turn on or off TDD */
05020       cp = (char *) data;
05021       p->mate = 0;
05022       if (!*cp) { /* turn it off */
05023          ast_debug(1, "Set option TDD MODE, value: OFF(0) on %s\n",chan->name);
05024          if (p->tdd)
05025             tdd_free(p->tdd);
05026          p->tdd = 0;
05027          break;
05028       }
05029       ast_debug(1, "Set option TDD MODE, value: %s(%d) on %s\n",
05030          (*cp == 2) ? "MATE" : "ON", (int) *cp, chan->name);
05031       dahdi_disable_ec(p);
05032       /* otherwise, turn it on */
05033       if (!p->didtdd) { /* if havent done it yet */
05034          unsigned char mybuf[41000];/*! \todo XXX This is an abuse of the stack!! */
05035          unsigned char *buf;
05036          int size, res, fd, len;
05037          struct pollfd fds[1];
05038 
05039          buf = mybuf;
05040          memset(buf, 0x7f, sizeof(mybuf)); /* set to silence */
05041          ast_tdd_gen_ecdisa(buf + 16000, 16000);  /* put in tone */
05042          len = 40000;
05043          idx = dahdi_get_index(chan, p, 0);
05044          if (idx < 0) {
05045             ast_log(LOG_WARNING, "No index in TDD?\n");
05046             return -1;
05047          }
05048          fd = p->subs[idx].dfd;
05049          while (len) {
05050             if (ast_check_hangup(chan))
05051                return -1;
05052             size = len;
05053             if (size > READ_SIZE)
05054                size = READ_SIZE;
05055             fds[0].fd = fd;
05056             fds[0].events = POLLPRI | POLLOUT;
05057             fds[0].revents = 0;
05058             res = poll(fds, 1, -1);
05059             if (!res) {
05060                ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
05061                continue;
05062             }
05063             /* if got exception */
05064             if (fds[0].revents & POLLPRI)
05065                return -1;
05066             if (!(fds[0].revents & POLLOUT)) {
05067                ast_debug(1, "write fd not ready on channel %d\n", p->channel);
05068                continue;
05069             }
05070             res = write(fd, buf, size);
05071             if (res != size) {
05072                if (res == -1) return -1;
05073                ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
05074                break;
05075             }
05076             len -= size;
05077             buf += size;
05078          }
05079          p->didtdd = 1; /* set to have done it now */
05080       }
05081       if (*cp == 2) { /* Mate mode */
05082          if (p->tdd)
05083             tdd_free(p->tdd);
05084          p->tdd = 0;
05085          p->mate = 1;
05086          break;
05087       }
05088       if (!p->tdd) { /* if we dont have one yet */
05089          p->tdd = tdd_new(); /* allocate one */
05090       }
05091       break;
05092    case AST_OPTION_RELAXDTMF:  /* Relax DTMF decoding (or not) */
05093       if (!p->dsp)
05094          break;
05095       cp = (char *) data;
05096       ast_debug(1, "Set option RELAX DTMF, value: %s(%d) on %s\n",
05097          *cp ? "ON" : "OFF", (int) *cp, chan->name);
05098       ast_dsp_set_digitmode(p->dsp, ((*cp) ? DSP_DIGITMODE_RELAXDTMF : DSP_DIGITMODE_DTMF) | p->dtmfrelax);
05099       break;
05100    case AST_OPTION_AUDIO_MODE:  /* Set AUDIO mode (or not) */
05101       cp = (char *) data;
05102       if (!*cp) {
05103          ast_debug(1, "Set option AUDIO MODE, value: OFF(0) on %s\n", chan->name);
05104          x = 0;
05105          dahdi_disable_ec(p);
05106       } else {
05107          ast_debug(1, "Set option AUDIO MODE, value: ON(1) on %s\n", chan->name);
05108          x = 1;
05109       }
05110       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x) == -1)
05111          ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, x, strerror(errno));
05112       break;
05113    case AST_OPTION_OPRMODE:  /* Operator services mode */
05114       oprmode = (struct oprmode *) data;
05115       /* We don't support operator mode across technologies */
05116       if (strcasecmp(chan->tech->type, oprmode->peer->tech->type)) {
05117          ast_log(LOG_NOTICE, "Operator mode not supported on %s to %s calls.\n",
05118                chan->tech->type, oprmode->peer->tech->type);
05119          errno = EINVAL;
05120          return -1;
05121       }
05122       pp = oprmode->peer->tech_pvt;
05123       p->oprmode = pp->oprmode = 0;
05124       /* setup peers */
05125       p->oprpeer = pp;
05126       pp->oprpeer = p;
05127       /* setup modes, if any */
05128       if (oprmode->mode)
05129       {
05130          pp->oprmode = oprmode->mode;
05131          p->oprmode = -oprmode->mode;
05132       }
05133       ast_debug(1, "Set Operator Services mode, value: %d on %s/%s\n",
05134          oprmode->mode, chan->name,oprmode->peer->name);
05135       break;
05136    case AST_OPTION_ECHOCAN:
05137       cp = (char *) data;
05138       if (*cp) {
05139          ast_debug(1, "Enabling echo cancellation on %s\n", chan->name);
05140          dahdi_enable_ec(p);
05141       } else {
05142          ast_debug(1, "Disabling echo cancellation on %s\n", chan->name);
05143          dahdi_disable_ec(p);
05144       }
05145       break;
05146    }
05147    errno = 0;
05148 
05149    return 0;
05150 }
05151 
05152 static int dahdi_func_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len)
05153 {
05154    struct dahdi_pvt *p = chan->tech_pvt;
05155    int res = 0;
05156 
05157    if (!strcasecmp(data, "rxgain")) {
05158       ast_mutex_lock(&p->lock);
05159       snprintf(buf, len, "%f", p->rxgain);
05160       ast_mutex_unlock(&p->lock);
05161    } else if (!strcasecmp(data, "txgain")) {
05162       ast_mutex_lock(&p->lock);
05163       snprintf(buf, len, "%f", p->txgain);
05164       ast_mutex_unlock(&p->lock);
05165    } else {
05166       ast_copy_string(buf, "", len);
05167       res = -1;
05168    }
05169 
05170    return res;
05171 }
05172 
05173 
05174 static int parse_buffers_policy(const char *parse, int *num_buffers, int *policy)
05175 {
05176    int res;
05177    char policy_str[21] = "";
05178    
05179    if (((res = sscanf(parse, "%d,%20s", num_buffers, policy_str)) != 2) &&
05180       ((res = sscanf(parse, "%d|%20s", num_buffers, policy_str)) != 2)) {
05181       ast_log(LOG_WARNING, "Parsing buffer string '%s' failed.\n", parse);
05182       return 1;
05183    }
05184    if (*num_buffers < 0) {
05185       ast_log(LOG_WARNING, "Invalid buffer count given '%d'.\n", *num_buffers);
05186       return -1;
05187    }
05188    if (!strcasecmp(policy_str, "full")) {
05189       *policy = DAHDI_POLICY_WHEN_FULL;
05190    } else if (!strcasecmp(policy_str, "immediate")) {
05191       *policy = DAHDI_POLICY_IMMEDIATE;
05192 #ifdef DAHDI_POLICY_HALF_FULL
05193    } else if (!strcasecmp(policy_str, "half")) {
05194       *policy = DAHDI_POLICY_HALF_FULL;
05195 #endif
05196    } else {
05197       ast_log(LOG_WARNING, "Invalid policy name given '%s'.\n", policy_str);
05198       return -1;
05199    }
05200 
05201    return 0;
05202 }
05203 
05204 static int dahdi_func_write(struct ast_channel *chan, const char *function, char *data, const char *value)
05205 {
05206    struct dahdi_pvt *p = chan->tech_pvt;
05207    int res = 0;
05208 
05209    if (!strcasecmp(data, "buffers")) {
05210       int num_bufs, policy;
05211 
05212       if (!(parse_buffers_policy(value, &num_bufs, &policy))) {
05213          struct dahdi_bufferinfo bi = {
05214             .txbufpolicy = policy,
05215             .rxbufpolicy = policy,
05216             .bufsize = p->bufsize,
05217             .numbufs = num_bufs,
05218          };
05219          int bpres;
05220 
05221          if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
05222             ast_log(LOG_WARNING, "Channel '%d' unable to override buffer policy: %s\n", p->channel, strerror(errno));
05223          } else {
05224             p->bufferoverrideinuse = 1;
05225          }
05226       } else {
05227          res = -1;
05228       }
05229    } else {
05230       res = -1;
05231    }
05232 
05233    return res;
05234 }
05235 
05236 static void dahdi_unlink(struct dahdi_pvt *slave, struct dahdi_pvt *master, int needlock)
05237 {
05238    /* Unlink a specific slave or all slaves/masters from a given master */
05239    int x;
05240    int hasslaves;
05241    if (!master)
05242       return;
05243    if (needlock) {
05244       ast_mutex_lock(&master->lock);
05245       if (slave) {
05246          while (ast_mutex_trylock(&slave->lock)) {
05247             DEADLOCK_AVOIDANCE(&master->lock);
05248          }
05249       }
05250    }
05251    hasslaves = 0;
05252    for (x = 0; x < MAX_SLAVES; x++) {
05253       if (master->slaves[x]) {
05254          if (!slave || (master->slaves[x] == slave)) {
05255             /* Take slave out of the conference */
05256             ast_debug(1, "Unlinking slave %d from %d\n", master->slaves[x]->channel, master->channel);
05257             conf_del(master, &master->slaves[x]->subs[SUB_REAL], SUB_REAL);
05258             conf_del(master->slaves[x], &master->subs[SUB_REAL], SUB_REAL);
05259             master->slaves[x]->master = NULL;
05260             master->slaves[x] = NULL;
05261          } else
05262             hasslaves = 1;
05263       }
05264       if (!hasslaves)
05265          master->inconference = 0;
05266    }
05267    if (!slave) {
05268       if (master->master) {
05269          /* Take master out of the conference */
05270          conf_del(master->master, &master->subs[SUB_REAL], SUB_REAL);
05271          conf_del(master, &master->master->subs[SUB_REAL], SUB_REAL);
05272          hasslaves = 0;
05273          for (x = 0; x < MAX_SLAVES; x++) {
05274             if (master->master->slaves[x] == master)
05275                master->master->slaves[x] = NULL;
05276             else if (master->master->slaves[x])
05277                hasslaves = 1;
05278          }
05279          if (!hasslaves)
05280             master->master->inconference = 0;
05281       }
05282       master->master = NULL;
05283    }
05284    update_conf(master);
05285    if (needlock) {
05286       if (slave)
05287          ast_mutex_unlock(&slave->lock);
05288       ast_mutex_unlock(&master->lock);
05289    }
05290 }
05291 
05292 static void dahdi_link(struct dahdi_pvt *slave, struct dahdi_pvt *master) {
05293    int x;
05294    if (!slave || !master) {
05295       ast_log(LOG_WARNING, "Tried to link to/from NULL??\n");
05296       return;
05297    }
05298    for (x = 0; x < MAX_SLAVES; x++) {
05299       if (!master->slaves[x]) {
05300          master->slaves[x] = slave;
05301          break;
05302       }
05303    }
05304    if (x >= MAX_SLAVES) {
05305       ast_log(LOG_WARNING, "Replacing slave %d with new slave, %d\n", master->slaves[MAX_SLAVES - 1]->channel, slave->channel);
05306       master->slaves[MAX_SLAVES - 1] = slave;
05307    }
05308    if (slave->master)
05309       ast_log(LOG_WARNING, "Replacing master %d with new master, %d\n", slave->master->channel, master->channel);
05310    slave->master = master;
05311 
05312    ast_debug(1, "Making %d slave to master %d at %d\n", slave->channel, master->channel, x);
05313 }
05314 
05315 static void disable_dtmf_detect(struct dahdi_pvt *p)
05316 {
05317    int val;
05318 
05319    p->ignoredtmf = 1;
05320 
05321    val = 0;
05322    ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
05323 
05324    if (!p->hardwaredtmf && p->dsp) {
05325       p->dsp_features &= ~DSP_FEATURE_DIGIT_DETECT;
05326       ast_dsp_set_features(p->dsp, p->dsp_features);
05327    }
05328 }
05329 
05330 static void enable_dtmf_detect(struct dahdi_pvt *p)
05331 {
05332    int val;
05333 
05334    if (p->channel == CHAN_PSEUDO)
05335       return;
05336 
05337    p->ignoredtmf = 0;
05338 
05339    val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
05340    ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
05341 
05342    if (!p->hardwaredtmf && p->dsp) {
05343       p->dsp_features |= DSP_FEATURE_DIGIT_DETECT;
05344       ast_dsp_set_features(p->dsp, p->dsp_features);
05345    }
05346 }
05347 
05348 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)
05349 {
05350    struct ast_channel *who;
05351    struct dahdi_pvt *p0, *p1, *op0, *op1;
05352    struct dahdi_pvt *master = NULL, *slave = NULL;
05353    struct ast_frame *f;
05354    int inconf = 0;
05355    int nothingok = 1;
05356    int ofd0, ofd1;
05357    int oi0, oi1, i0 = -1, i1 = -1, t0, t1;
05358    int os0 = -1, os1 = -1;
05359    int priority = 0;
05360    struct ast_channel *oc0, *oc1;
05361    enum ast_bridge_result res;
05362 
05363 #ifdef PRI_2BCT
05364    int triedtopribridge = 0;
05365 #endif
05366 
05367    /* For now, don't attempt to native bridge if either channel needs DTMF detection.
05368       There is code below to handle it properly until DTMF is actually seen,
05369       but due to currently unresolved issues it's ignored...
05370    */
05371 
05372    if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1))
05373       return AST_BRIDGE_FAILED_NOWARN;
05374 
05375    ast_channel_lock(c0);
05376    while (ast_channel_trylock(c1)) {
05377       CHANNEL_DEADLOCK_AVOIDANCE(c0);
05378    }
05379 
05380    p0 = c0->tech_pvt;
05381    p1 = c1->tech_pvt;
05382    /* cant do pseudo-channels here */
05383    if (!p0 || (!p0->sig) || !p1 || (!p1->sig)) {
05384       ast_channel_unlock(c0);
05385       ast_channel_unlock(c1);
05386       return AST_BRIDGE_FAILED_NOWARN;
05387    }
05388 
05389    oi0 = dahdi_get_index(c0, p0, 0);
05390    oi1 = dahdi_get_index(c1, p1, 0);
05391    if ((oi0 < 0) || (oi1 < 0)) {
05392       ast_channel_unlock(c0);
05393       ast_channel_unlock(c1);
05394       return AST_BRIDGE_FAILED;
05395    }
05396 
05397    op0 = p0 = c0->tech_pvt;
05398    op1 = p1 = c1->tech_pvt;
05399    ofd0 = c0->fds[0];
05400    ofd1 = c1->fds[0];
05401    oc0 = p0->owner;
05402    oc1 = p1->owner;
05403 
05404    if (ast_mutex_trylock(&p0->lock)) {
05405       /* Don't block, due to potential for deadlock */
05406       ast_channel_unlock(c0);
05407       ast_channel_unlock(c1);
05408       ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
05409       return AST_BRIDGE_RETRY;
05410    }
05411    if (ast_mutex_trylock(&p1->lock)) {
05412       /* Don't block, due to potential for deadlock */
05413       ast_mutex_unlock(&p0->lock);
05414       ast_channel_unlock(c0);
05415       ast_channel_unlock(c1);
05416       ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
05417       return AST_BRIDGE_RETRY;
05418    }
05419 
05420    if ((p0->callwaiting && p0->callwaitingcallerid)
05421       || (p1->callwaiting && p1->callwaitingcallerid)) {
05422       /*
05423        * Call Waiting Caller ID requires DTMF detection to know if it
05424        * can send the CID spill.
05425        *
05426        * For now, don't attempt to native bridge if either channel
05427        * needs DTMF detection.  There is code below to handle it
05428        * properly until DTMF is actually seen, but due to currently
05429        * unresolved issues it's ignored...
05430        */
05431       ast_mutex_unlock(&p0->lock);
05432       ast_mutex_unlock(&p1->lock);
05433       ast_channel_unlock(c0);
05434       ast_channel_unlock(c1);
05435       return AST_BRIDGE_FAILED_NOWARN;
05436    }
05437 
05438    if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
05439       if (p0->owner && p1->owner) {
05440          /* If we don't have a call-wait in a 3-way, and we aren't in a 3-way, we can be master */
05441          if (!p0->subs[SUB_CALLWAIT].inthreeway && !p1->subs[SUB_REAL].inthreeway) {
05442             master = p0;
05443             slave = p1;
05444             inconf = 1;
05445          } else if (!p1->subs[SUB_CALLWAIT].inthreeway && !p0->subs[SUB_REAL].inthreeway) {
05446             master = p1;
05447             slave = p0;
05448             inconf = 1;
05449          } else {
05450             ast_log(LOG_WARNING, "Huh?  Both calls are callwaits or 3-ways?  That's clever...?\n");
05451             ast_log(LOG_WARNING, "p0: chan %d/%d/CW%d/3W%d, p1: chan %d/%d/CW%d/3W%d\n",
05452                p0->channel,
05453                oi0, (p0->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
05454                p0->subs[SUB_REAL].inthreeway, p0->channel,
05455                oi0, (p1->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
05456                p1->subs[SUB_REAL].inthreeway);
05457          }
05458          nothingok = 0;
05459       }
05460    } else if ((oi0 == SUB_REAL) && (oi1 == SUB_THREEWAY)) {
05461       if (p1->subs[SUB_THREEWAY].inthreeway) {
05462          master = p1;
05463          slave = p0;
05464          nothingok = 0;
05465       }
05466    } else if ((oi0 == SUB_THREEWAY) && (oi1 == SUB_REAL)) {
05467       if (p0->subs[SUB_THREEWAY].inthreeway) {
05468          master = p0;
05469          slave = p1;
05470          nothingok = 0;
05471       }
05472    } else if ((oi0 == SUB_REAL) && (oi1 == SUB_CALLWAIT)) {
05473       /* We have a real and a call wait.  If we're in a three way call, put us in it, otherwise,
05474          don't put us in anything */
05475       if (p1->subs[SUB_CALLWAIT].inthreeway) {
05476          master = p1;
05477          slave = p0;
05478          nothingok = 0;
05479       }
05480    } else if ((oi0 == SUB_CALLWAIT) && (oi1 == SUB_REAL)) {
05481       /* Same as previous */
05482       if (p0->subs[SUB_CALLWAIT].inthreeway) {
05483          master = p0;
05484          slave = p1;
05485          nothingok = 0;
05486       }
05487    }
05488    ast_debug(1, "master: %d, slave: %d, nothingok: %d\n",
05489       master ? master->channel : 0, slave ? slave->channel : 0, nothingok);
05490    if (master && slave) {
05491       /* Stop any tones, or play ringtone as appropriate.  If they're bridged
05492          in an active threeway call with a channel that is ringing, we should
05493          indicate ringing. */
05494       if ((oi1 == SUB_THREEWAY) &&
05495          p1->subs[SUB_THREEWAY].inthreeway &&
05496          p1->subs[SUB_REAL].owner &&
05497          p1->subs[SUB_REAL].inthreeway &&
05498          (p1->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
05499          ast_debug(1,
05500             "Playing ringback on %d/%d(%s) since %d/%d(%s) is in a ringing three-way\n",
05501             p0->channel, oi0, c0->name, p1->channel, oi1, c1->name);
05502          tone_zone_play_tone(p0->subs[oi0].dfd, DAHDI_TONE_RINGTONE);
05503          os1 = p1->subs[SUB_REAL].owner->_state;
05504       } else {
05505          ast_debug(1, "Stopping tones on %d/%d(%s) talking to %d/%d(%s)\n",
05506             p0->channel, oi0, c0->name, p1->channel, oi1, c1->name);
05507          tone_zone_play_tone(p0->subs[oi0].dfd, -1);
05508       }
05509       if ((oi0 == SUB_THREEWAY) &&
05510          p0->subs[SUB_THREEWAY].inthreeway &&
05511          p0->subs[SUB_REAL].owner &&
05512          p0->subs[SUB_REAL].inthreeway &&
05513          (p0->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
05514          ast_debug(1,
05515             "Playing ringback on %d/%d(%s) since %d/%d(%s) is in a ringing three-way\n",
05516             p1->channel, oi1, c1->name, p0->channel, oi0, c0->name);
05517          tone_zone_play_tone(p1->subs[oi1].dfd, DAHDI_TONE_RINGTONE);
05518          os0 = p0->subs[SUB_REAL].owner->_state;
05519       } else {
05520          ast_debug(1, "Stopping tones on %d/%d(%s) talking to %d/%d(%s)\n",
05521             p1->channel, oi1, c1->name, p0->channel, oi0, c0->name);
05522          tone_zone_play_tone(p1->subs[oi1].dfd, -1);
05523       }
05524       if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
05525          if (!p0->echocanbridged || !p1->echocanbridged) {
05526             /* Disable echo cancellation if appropriate */
05527             dahdi_disable_ec(p0);
05528             dahdi_disable_ec(p1);
05529          }
05530       }
05531       dahdi_link(slave, master);
05532       master->inconference = inconf;
05533    } else if (!nothingok)
05534       ast_log(LOG_WARNING, "Can't link %d/%s with %d/%s\n", p0->channel, subnames[oi0], p1->channel, subnames[oi1]);
05535 
05536    update_conf(p0);
05537    update_conf(p1);
05538    t0 = p0->subs[SUB_REAL].inthreeway;
05539    t1 = p1->subs[SUB_REAL].inthreeway;
05540 
05541    ast_mutex_unlock(&p0->lock);
05542    ast_mutex_unlock(&p1->lock);
05543 
05544    ast_channel_unlock(c0);
05545    ast_channel_unlock(c1);
05546 
05547    /* Native bridge failed */
05548    if ((!master || !slave) && !nothingok) {
05549       dahdi_enable_ec(p0);
05550       dahdi_enable_ec(p1);
05551       return AST_BRIDGE_FAILED;
05552    }
05553 
05554    ast_verb(3, "Native bridging %s and %s\n", c0->name, c1->name);
05555 
05556    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
05557       disable_dtmf_detect(op0);
05558 
05559    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
05560       disable_dtmf_detect(op1);
05561 
05562    for (;;) {
05563       struct ast_channel *c0_priority[2] = {c0, c1};
05564       struct ast_channel *c1_priority[2] = {c1, c0};
05565 
05566       /* Here's our main loop...  Start by locking things, looking for private parts,
05567          and then balking if anything is wrong */
05568 
05569       ast_channel_lock(c0);
05570       while (ast_channel_trylock(c1)) {
05571          CHANNEL_DEADLOCK_AVOIDANCE(c0);
05572       }
05573 
05574       p0 = c0->tech_pvt;
05575       p1 = c1->tech_pvt;
05576 
05577       if (op0 == p0)
05578          i0 = dahdi_get_index(c0, p0, 1);
05579       if (op1 == p1)
05580          i1 = dahdi_get_index(c1, p1, 1);
05581 
05582       ast_channel_unlock(c0);
05583       ast_channel_unlock(c1);
05584 
05585       if (!timeoutms ||
05586          (op0 != p0) ||
05587          (op1 != p1) ||
05588          (ofd0 != c0->fds[0]) ||
05589          (ofd1 != c1->fds[0]) ||
05590          (p0->subs[SUB_REAL].owner && (os0 > -1) && (os0 != p0->subs[SUB_REAL].owner->_state)) ||
05591          (p1->subs[SUB_REAL].owner && (os1 > -1) && (os1 != p1->subs[SUB_REAL].owner->_state)) ||
05592          (oc0 != p0->owner) ||
05593          (oc1 != p1->owner) ||
05594          (t0 != p0->subs[SUB_REAL].inthreeway) ||
05595          (t1 != p1->subs[SUB_REAL].inthreeway) ||
05596          (oi0 != i0) ||
05597          (oi1 != i1)) {
05598          ast_debug(1, "Something changed out on %d/%d to %d/%d, returning -3 to restart\n",
05599             op0->channel, oi0, op1->channel, oi1);
05600          res = AST_BRIDGE_RETRY;
05601          goto return_from_bridge;
05602       }
05603 
05604 #ifdef PRI_2BCT
05605       if (!triedtopribridge) {
05606          triedtopribridge = 1;
05607          if (p0->pri && p0->pri == p1->pri && p0->transfer && p1->transfer) {
05608             ast_mutex_lock(&p0->pri->lock);
05609             if (p0->call && p1->call) {
05610                pri_channel_bridge(p0->call, p1->call);
05611             }
05612             ast_mutex_unlock(&p0->pri->lock);
05613          }
05614       }
05615 #endif
05616 
05617       who = ast_waitfor_n(priority ? c0_priority : c1_priority, 2, &timeoutms);
05618       if (!who) {
05619          ast_debug(1, "Ooh, empty read...\n");
05620          continue;
05621       }
05622       f = ast_read(who);
05623       if (!f || (f->frametype == AST_FRAME_CONTROL)) {
05624          *fo = f;
05625          *rc = who;
05626          res = AST_BRIDGE_COMPLETE;
05627          goto return_from_bridge;
05628       }
05629       if (f->frametype == AST_FRAME_DTMF) {
05630          if ((who == c0) && p0->pulsedial) {
05631             ast_write(c1, f);
05632          } else if ((who == c1) && p1->pulsedial) {
05633             ast_write(c0, f);
05634          } else {
05635             *fo = f;
05636             *rc = who;
05637             res = AST_BRIDGE_COMPLETE;
05638             goto return_from_bridge;
05639          }
05640       }
05641       ast_frfree(f);
05642 
05643       /* Swap who gets priority */
05644       priority = !priority;
05645    }
05646 
05647 return_from_bridge:
05648    if (op0 == p0)
05649       dahdi_enable_ec(p0);
05650 
05651    if (op1 == p1)
05652       dahdi_enable_ec(p1);
05653 
05654    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
05655       enable_dtmf_detect(op0);
05656 
05657    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
05658       enable_dtmf_detect(op1);
05659 
05660    dahdi_unlink(slave, master, 1);
05661 
05662    return res;
05663 }
05664 
05665 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
05666 {
05667    struct dahdi_pvt *p = newchan->tech_pvt;
05668    int x;
05669    ast_mutex_lock(&p->lock);
05670    ast_debug(1, "New owner for channel %d is %s\n", p->channel, newchan->name);
05671    if (p->owner == oldchan) {
05672       p->owner = newchan;
05673    }
05674    for (x = 0; x < 3; x++)
05675       if (p->subs[x].owner == oldchan) {
05676          if (!x)
05677             dahdi_unlink(NULL, p, 0);
05678          p->subs[x].owner = newchan;
05679       }
05680    update_conf(p);
05681    ast_mutex_unlock(&p->lock);
05682    if (newchan->_state == AST_STATE_RINGING) {
05683       dahdi_indicate(newchan, AST_CONTROL_RINGING, NULL, 0);
05684    }
05685    return 0;
05686 }
05687 
05688 static int dahdi_ring_phone(struct dahdi_pvt *p)
05689 {
05690    int x;
05691    int res;
05692    /* Make sure our transmit state is on hook */
05693    x = 0;
05694    x = DAHDI_ONHOOK;
05695    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
05696    do {
05697       x = DAHDI_RING;
05698       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
05699       if (res) {
05700          switch (errno) {
05701          case EBUSY:
05702          case EINTR:
05703             /* Wait just in case */
05704             usleep(10000);
05705             continue;
05706          case EINPROGRESS:
05707             res = 0;
05708             break;
05709          default:
05710             ast_log(LOG_WARNING, "Couldn't ring the phone: %s\n", strerror(errno));
05711             res = 0;
05712          }
05713       }
05714    } while (res);
05715    return res;
05716 }
05717 
05718 static void *ss_thread(void *data);
05719 
05720 /*!
05721  * \internal
05722  * \brief Attempt to transfer 3-way call.
05723  *
05724  * \param p private structure.
05725  *
05726  * \note
05727  * On entry these locks are held: real-call, private, 3-way call.
05728  *
05729  * \retval 1 Transfer successful.  3-way call is unlocked and subchannel is unalloced.
05730  *         Swapped real and 3-way subchannel.
05731  * \retval 0 Transfer successful.  3-way call is unlocked and subchannel is unalloced.
05732  * \retval -1 on error.  Caller must unlock 3-way call.
05733  */
05734 static int attempt_transfer(struct dahdi_pvt *p)
05735 {
05736    /* In order to transfer, we need at least one of the channels to
05737       actually be in a call bridge.  We can't conference two applications
05738       together (but then, why would we want to?) */
05739    if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
05740       /* The three-way person we're about to transfer to could still be in MOH, so
05741          stop it now if appropriate */
05742       if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner))
05743          ast_queue_control(p->subs[SUB_THREEWAY].owner, AST_CONTROL_UNHOLD);
05744       if (p->subs[SUB_REAL].owner->_state == AST_STATE_RINGING) {
05745          /*
05746           * This may not be safe.
05747           * We currently hold the locks on the real-call, private, and 3-way call.
05748           * We could possibly avoid this here by using an ast_queue_control() instead.
05749           * However, the following ast_channel_masquerade() is going to be locking
05750           * the bridged channel again anyway.
05751           */
05752          ast_indicate(ast_bridged_channel(p->subs[SUB_REAL].owner), AST_CONTROL_RINGING);
05753       }
05754       if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RING) {
05755          tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE);
05756       }
05757        if (ast_channel_masquerade(p->subs[SUB_THREEWAY].owner, ast_bridged_channel(p->subs[SUB_REAL].owner))) {
05758          ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
05759                ast_bridged_channel(p->subs[SUB_REAL].owner)->name, p->subs[SUB_THREEWAY].owner->name);
05760          return -1;
05761       }
05762       /* Orphan the channel after releasing the lock */
05763       ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
05764       unalloc_sub(p, SUB_THREEWAY);
05765    } else if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
05766       ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
05767       if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RINGING) {
05768          /*
05769           * This may not be safe.
05770           * We currently hold the locks on the real-call, private, and 3-way call.
05771           * We could possibly avoid this here by using an ast_queue_control() instead.
05772           * However, the following ast_channel_masquerade() is going to be locking
05773           * the bridged channel again anyway.
05774           */
05775          ast_indicate(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), AST_CONTROL_RINGING);
05776       }
05777       if (p->subs[SUB_REAL].owner->_state == AST_STATE_RING) {
05778          tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
05779       }
05780       if (ast_channel_masquerade(p->subs[SUB_REAL].owner, ast_bridged_channel(p->subs[SUB_THREEWAY].owner))) {
05781          ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
05782                ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->name, p->subs[SUB_REAL].owner->name);
05783          return -1;
05784       }
05785       /* Three-way is now the REAL */
05786       swap_subs(p, SUB_THREEWAY, SUB_REAL);
05787       ast_channel_unlock(p->subs[SUB_REAL].owner);
05788       unalloc_sub(p, SUB_THREEWAY);
05789       /* Tell the caller not to hangup */
05790       return 1;
05791    } else {
05792       ast_debug(1, "Neither %s nor %s are in a bridge, nothing to transfer\n",
05793          p->subs[SUB_REAL].owner->name, p->subs[SUB_THREEWAY].owner->name);
05794       return -1;
05795    }
05796    return 0;
05797 }
05798 
05799 static int check_for_conference(struct dahdi_pvt *p)
05800 {
05801    struct dahdi_confinfo ci;
05802    /* Fine if we already have a master, etc */
05803    if (p->master || (p->confno > -1))
05804       return 0;
05805    memset(&ci, 0, sizeof(ci));
05806    if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
05807       ast_log(LOG_WARNING, "Failed to get conference info on channel %d: %s\n", p->channel, strerror(errno));
05808       return 0;
05809    }
05810    /* If we have no master and don't have a confno, then
05811       if we're in a conference, it's probably a MeetMe room or
05812       some such, so don't let us 3-way out! */
05813    if ((p->subs[SUB_REAL].curconf.confno != ci.confno) || (p->subs[SUB_REAL].curconf.confmode != ci.confmode)) {
05814       ast_verb(3, "Avoiding 3-way call when in an external conference\n");
05815       return 1;
05816    }
05817    return 0;
05818 }
05819 
05820 /*! Checks channel for alarms
05821  * \param p a channel to check for alarms.
05822  * \returns the alarms on the span to which the channel belongs, or alarms on
05823  *          the channel if no span alarms.
05824  */
05825 static int get_alarms(struct dahdi_pvt *p)
05826 {
05827    int res;
05828    struct dahdi_spaninfo zi;
05829    struct dahdi_params params;
05830 
05831    memset(&zi, 0, sizeof(zi));
05832    zi.spanno = p->span;
05833 
05834    if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SPANSTAT, &zi)) >= 0) {
05835       if (zi.alarms != DAHDI_ALARM_NONE)
05836          return zi.alarms;
05837    } else {
05838       ast_log(LOG_WARNING, "Unable to determine alarm on channel %d: %s\n", p->channel, strerror(errno));
05839       return 0;
05840    }
05841 
05842    /* No alarms on the span. Check for channel alarms. */
05843    memset(&params, 0, sizeof(params));
05844    if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &params)) >= 0)
05845       return params.chan_alarms;
05846 
05847    ast_log(LOG_WARNING, "Unable to determine alarm on channel %d\n", p->channel);
05848 
05849    return DAHDI_ALARM_NONE;
05850 }
05851 
05852 static void dahdi_handle_dtmf(struct ast_channel *ast, int idx, struct ast_frame **dest)
05853 {
05854    struct dahdi_pvt *p = ast->tech_pvt;
05855    struct ast_frame *f = *dest;
05856 
05857    ast_debug(1, "%s DTMF digit: 0x%02X '%c' on %s\n",
05858       f->frametype == AST_FRAME_DTMF_BEGIN ? "Begin" : "End",
05859       f->subclass, f->subclass, ast->name);
05860 
05861    if (p->confirmanswer) {
05862       if (f->frametype == AST_FRAME_DTMF_END) {
05863          ast_debug(1, "Confirm answer on %s!\n", ast->name);
05864          /* Upon receiving a DTMF digit, consider this an answer confirmation instead
05865             of a DTMF digit */
05866          p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05867          p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
05868          /* Reset confirmanswer so DTMF's will behave properly for the duration of the call */
05869          p->confirmanswer = 0;
05870       } else {
05871          p->subs[idx].f.frametype = AST_FRAME_NULL;
05872          p->subs[idx].f.subclass = 0;
05873       }
05874       *dest = &p->subs[idx].f;
05875    } else if (p->callwaitcas) {
05876       if (f->frametype == AST_FRAME_DTMF_END) {
05877          if ((f->subclass == 'A') || (f->subclass == 'D')) {
05878             ast_debug(1, "Got some DTMF, but it's for the CAS\n");
05879             ast_free(p->cidspill);
05880             p->cidspill = NULL;
05881             send_cwcidspill(p);
05882          }
05883          p->callwaitcas = 0;
05884       }
05885       p->subs[idx].f.frametype = AST_FRAME_NULL;
05886       p->subs[idx].f.subclass = 0;
05887       *dest = &p->subs[idx].f;
05888    } else if (f->subclass == 'f') {
05889       if (f->frametype == AST_FRAME_DTMF_END) {
05890          /* Fax tone -- Handle and return NULL */
05891          if ((p->callprogress & CALLPROGRESS_FAX) && !p->faxhandled) {
05892             /* If faxbuffers are configured, use them for the fax transmission */
05893             if (p->usefaxbuffers && !p->bufferoverrideinuse) {
05894                struct dahdi_bufferinfo bi = {
05895                   .txbufpolicy = p->faxbuf_policy,
05896                   .bufsize = p->bufsize,
05897                   .numbufs = p->faxbuf_no
05898                };
05899                int res;
05900 
05901                if ((res = ioctl(p->subs[idx].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
05902                   ast_log(LOG_WARNING, "Channel '%s' unable to set faxbuffer policy, reason: %s\n", ast->name, strerror(errno));
05903                } else {
05904                   p->bufferoverrideinuse = 1;
05905                }
05906             }
05907             p->faxhandled = 1;
05908             if (strcmp(ast->exten, "fax")) {
05909                const char *target_context = S_OR(ast->macrocontext, ast->context);
05910 
05911                /* We need to unlock 'ast' here because ast_exists_extension has the
05912                 * potential to start autoservice on the channel. Such action is prone
05913                 * to deadlock.
05914                 */
05915                ast_mutex_unlock(&p->lock);
05916                ast_channel_unlock(ast);
05917                if (ast_exists_extension(ast, target_context, "fax", 1, ast->cid.cid_num)) {
05918                   ast_channel_lock(ast);
05919                   ast_mutex_lock(&p->lock);
05920                   ast_verb(3, "Redirecting %s to fax extension\n", ast->name);
05921                   /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
05922                   pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten);
05923                   if (ast_async_goto(ast, target_context, "fax", 1))
05924                      ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context);
05925                } else {
05926                   ast_channel_lock(ast);
05927                   ast_mutex_lock(&p->lock);
05928                   ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
05929                }
05930             } else {
05931                ast_debug(1, "Already in a fax extension, not redirecting\n");
05932             }
05933          } else {
05934             ast_debug(1, "Fax already handled\n");
05935          }
05936          dahdi_confmute(p, 0);
05937       }
05938       p->subs[idx].f.frametype = AST_FRAME_NULL;
05939       p->subs[idx].f.subclass = 0;
05940       *dest = &p->subs[idx].f;
05941    }
05942 }
05943 
05944 static void handle_alarms(struct dahdi_pvt *p, int alms)
05945 {
05946    const char *alarm_str = alarm2str(alms);
05947 
05948    ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", p->channel, alarm_str);
05949    manager_event(EVENT_FLAG_SYSTEM, "Alarm",
05950       "Alarm: %s\r\n"
05951       "Channel: %d\r\n",
05952       alarm_str, p->channel);
05953 }
05954 
05955 static struct ast_frame *dahdi_handle_event(struct ast_channel *ast)
05956 {
05957    int res, x;
05958    int idx, mysig;
05959    char *c;
05960    struct dahdi_pvt *p = ast->tech_pvt;
05961    pthread_t threadid;
05962    struct ast_channel *chan;
05963    struct ast_frame *f;
05964 
05965    idx = dahdi_get_index(ast, p, 0);
05966    if (idx < 0) {
05967       return &ast_null_frame;
05968    }
05969    if (idx != SUB_REAL) {
05970       ast_log(LOG_ERROR, "We got an event on a non real sub.  Fix it!\n");
05971    }
05972 
05973    mysig = p->sig;
05974    if (p->outsigmod > -1)
05975       mysig = p->outsigmod;
05976 
05977    p->subs[idx].f.frametype = AST_FRAME_NULL;
05978    p->subs[idx].f.subclass = 0;
05979    p->subs[idx].f.datalen = 0;
05980    p->subs[idx].f.samples = 0;
05981    p->subs[idx].f.mallocd = 0;
05982    p->subs[idx].f.offset = 0;
05983    p->subs[idx].f.src = "dahdi_handle_event";
05984    p->subs[idx].f.data.ptr = NULL;
05985    f = &p->subs[idx].f;
05986 
05987    if (p->fake_event) {
05988       res = p->fake_event;
05989       p->fake_event = 0;
05990    } else
05991       res = dahdi_get_event(p->subs[idx].dfd);
05992 
05993    ast_debug(1, "Got event %s(%d) on channel %d (index %d)\n", event2str(res), res, p->channel, idx);
05994 
05995    if (res & (DAHDI_EVENT_PULSEDIGIT | DAHDI_EVENT_DTMFUP)) {
05996       p->pulsedial = (res & DAHDI_EVENT_PULSEDIGIT) ? 1 : 0;
05997       ast_debug(1, "Detected %sdigit '%c'\n", p->pulsedial ? "pulse ": "", res & 0xff);
05998 #if defined(HAVE_PRI)
05999       if (((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))
06000          && p->call_level < DAHDI_CALL_LEVEL_PROCEEDING
06001          && p->pri
06002          && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
06003          /* absorb event */
06004       } else
06005 #endif   /* defined(HAVE_PRI) */
06006       {
06007          /* Unmute conference */
06008          dahdi_confmute(p, 0);
06009          p->subs[idx].f.frametype = AST_FRAME_DTMF_END;
06010          p->subs[idx].f.subclass = res & 0xff;
06011          dahdi_handle_dtmf(ast, idx, &f);
06012       }
06013       return f;
06014    }
06015 
06016    if (res & DAHDI_EVENT_DTMFDOWN) {
06017       ast_debug(1, "DTMF Down '%c'\n", res & 0xff);
06018 #if defined(HAVE_PRI)
06019       if (((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))
06020          && p->call_level < DAHDI_CALL_LEVEL_PROCEEDING
06021          && p->pri
06022          && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
06023          /* absorb event */
06024       } else
06025 #endif   /* defined(HAVE_PRI) */
06026       {
06027          /* Mute conference */
06028          dahdi_confmute(p, 1);
06029          p->subs[idx].f.frametype = AST_FRAME_DTMF_BEGIN;
06030          p->subs[idx].f.subclass = res & 0xff;
06031          dahdi_handle_dtmf(ast, idx, &f);
06032       }
06033       return &p->subs[idx].f;
06034    }
06035 
06036    switch (res) {
06037       case DAHDI_EVENT_EC_DISABLED:
06038          ast_verb(3, "Channel %d echo canceler disabled due to CED detection\n", p->channel);
06039          p->echocanon = 0;
06040          break;
06041       case DAHDI_EVENT_BITSCHANGED:
06042 #ifdef HAVE_OPENR2
06043          if (p->sig != SIG_MFCR2) {
06044             ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig));
06045          } else {
06046             ast_log(LOG_DEBUG, "bits changed in chan %d\n", p->channel);
06047             openr2_chan_handle_cas(p->r2chan);
06048          }
06049 #else
06050          ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig));
06051 #endif
06052       case DAHDI_EVENT_PULSE_START:
06053          /* Stop tone if there's a pulse start and the PBX isn't started */
06054          if (!ast->pbx)
06055             tone_zone_play_tone(p->subs[idx].dfd, -1);
06056          break;
06057       case DAHDI_EVENT_DIALCOMPLETE:
06058 #ifdef HAVE_OPENR2
06059          if ((p->sig & SIG_MFCR2) && p->r2chan && ast->_state != AST_STATE_UP) {
06060             /* we don't need to do anything for this event for R2 signaling
06061                if the call is being setup */
06062             break;
06063          }
06064 #endif
06065          if (p->inalarm) break;
06066          if ((p->radio || (p->oprmode < 0))) break;
06067          if (ioctl(p->subs[idx].dfd,DAHDI_DIALING,&x) == -1) {
06068             ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed on %s: %s\n",ast->name, strerror(errno));
06069             return NULL;
06070          }
06071          if (!x) { /* if not still dialing in driver */
06072             dahdi_enable_ec(p);
06073             if (p->echobreak) {
06074                dahdi_train_ec(p);
06075                ast_copy_string(p->dop.dialstr, p->echorest, sizeof(p->dop.dialstr));
06076                p->dop.op = DAHDI_DIAL_OP_REPLACE;
06077                res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
06078                p->echobreak = 0;
06079             } else {
06080                p->dialing = 0;
06081                if ((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) {
06082                   /* if thru with dialing after offhook */
06083                   if (ast->_state == AST_STATE_DIALING_OFFHOOK) {
06084                      ast_setstate(ast, AST_STATE_UP);
06085                      p->subs[idx].f.frametype = AST_FRAME_CONTROL;
06086                      p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
06087                      break;
06088                   } else { /* if to state wait for offhook to dial rest */
06089                      /* we now wait for off hook */
06090                      ast_setstate(ast,AST_STATE_DIALING_OFFHOOK);
06091                   }
06092                }
06093                if (ast->_state == AST_STATE_DIALING) {
06094                   if ((p->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
06095                      ast_debug(1, "Done dialing, but waiting for progress detection before doing more...\n");
06096                   } else if (p->confirmanswer || (!p->dialednone
06097                      && ((mysig == SIG_EM) || (mysig == SIG_EM_E1)
06098                         || (mysig == SIG_EMWINK) || (mysig == SIG_FEATD)
06099                         || (mysig == SIG_FEATDMF_TA) || (mysig == SIG_FEATDMF)
06100                         || (mysig == SIG_E911) || (mysig == SIG_FGC_CAMA)
06101                         || (mysig == SIG_FGC_CAMAMF) || (mysig == SIG_FEATB)
06102                         || (mysig == SIG_SF) || (mysig == SIG_SFWINK)
06103                         || (mysig == SIG_SF_FEATD) || (mysig == SIG_SF_FEATDMF)
06104                         || (mysig == SIG_SF_FEATB)))) {
06105                      ast_setstate(ast, AST_STATE_RINGING);
06106                   } else if (!p->answeronpolarityswitch) {
06107                      ast_setstate(ast, AST_STATE_UP);
06108                      p->subs[idx].f.frametype = AST_FRAME_CONTROL;
06109                      p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
06110                      /* If aops=0 and hops=1, this is necessary */
06111                      p->polarity = POLARITY_REV;
06112                   } else {
06113                      /* Start clean, so we can catch the change to REV polarity when party answers */
06114                      p->polarity = POLARITY_IDLE;
06115                   }
06116                }
06117             }
06118          }
06119          break;
06120       case DAHDI_EVENT_ALARM:
06121 #ifdef HAVE_PRI
06122          if ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) {
06123             if (!p->pri || !p->pri->pri || (pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0)) {
06124                /* T309 is not enabled : hangup calls when alarm occurs */
06125                if (p->call) {
06126                   if (p->pri && p->pri->pri) {
06127                      if (!pri_grab(p, p->pri)) {
06128                         pri_hangup(p->pri->pri, p->call, -1);
06129                         pri_destroycall(p->pri->pri, p->call);
06130                         p->call = NULL;
06131                         pri_rel(p->pri);
06132                      } else
06133                         ast_log(LOG_WARNING, "Failed to grab PRI!\n");
06134                   } else
06135                      ast_log(LOG_WARNING, "The PRI Call has not been destroyed\n");
06136                }
06137                if (p->owner)
06138                   p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
06139             }
06140          }
06141          if (p->bearer)
06142             p->bearer->inalarm = 1;
06143          else
06144 #endif
06145          p->inalarm = 1;
06146          res = get_alarms(p);
06147          handle_alarms(p, res);
06148 #ifdef HAVE_PRI
06149          if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
06150             /* fall through intentionally */
06151          } else {
06152             break;
06153          }
06154 #endif
06155 #ifdef HAVE_SS7
06156          if (p->sig == SIG_SS7)
06157             break;
06158 #endif
06159 #ifdef HAVE_OPENR2
06160          if (p->sig == SIG_MFCR2)
06161             break;
06162 #endif
06163       case DAHDI_EVENT_ONHOOK:
06164          if (p->radio) {
06165             p->subs[idx].f.frametype = AST_FRAME_CONTROL;
06166             p->subs[idx].f.subclass = AST_CONTROL_RADIO_UNKEY;
06167             break;
06168          }
06169          if (p->oprmode < 0)
06170          {
06171             if (p->oprmode != -1) break;
06172             if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
06173             {
06174                /* Make sure it starts ringing */
06175                dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
06176                dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RING);
06177                save_conference(p->oprpeer);
06178                tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
06179             }
06180             break;
06181          }
06182          switch (p->sig) {
06183          case SIG_FXOLS:
06184          case SIG_FXOGS:
06185          case SIG_FXOKS:
06186             p->onhooktime = time(NULL);
06187             p->fxsoffhookstate = 0;
06188             p->msgstate = -1;
06189             /* Check for some special conditions regarding call waiting */
06190             if (idx == SUB_REAL) {
06191                /* The normal line was hung up */
06192                if (p->subs[SUB_CALLWAIT].owner) {
06193                   /* Need to hold the lock for real-call, private, and call-waiting call */
06194                   dahdi_lock_sub_owner(p, SUB_CALLWAIT);
06195                   if (!p->subs[SUB_CALLWAIT].owner) {
06196                      /*
06197                       * The call waiting call dissappeared.
06198                       * This is now a normal hangup.
06199                       */
06200                      dahdi_disable_ec(p);
06201                      return NULL;
06202                   }
06203 
06204                   /* There's a call waiting call, so ring the phone, but make it unowned in the mean time */
06205                   swap_subs(p, SUB_CALLWAIT, SUB_REAL);
06206                   ast_verb(3, "Channel %d still has (callwait) call, ringing phone\n", p->channel);
06207                   unalloc_sub(p, SUB_CALLWAIT);
06208 #if 0
06209                   p->subs[idx].needanswer = 0;
06210                   p->subs[idx].needringing = 0;
06211 #endif
06212                   p->callwaitingrepeat = 0;
06213                   p->cidcwexpire = 0;
06214                   p->cid_suppress_expire = 0;
06215                   p->owner = NULL;
06216                   /* Don't start streaming audio yet if the incoming call isn't up yet */
06217                   if (p->subs[SUB_REAL].owner->_state != AST_STATE_UP)
06218                      p->dialing = 1;
06219                   /* Unlock the call-waiting call that we swapped to real-call. */
06220                   ast_channel_unlock(p->subs[SUB_REAL].owner);
06221                   dahdi_ring_phone(p);
06222                } else if (p->subs[SUB_THREEWAY].owner) {
06223                   unsigned int mssinceflash;
06224 
06225                   /* Need to hold the lock for real-call, private, and 3-way call */
06226                   dahdi_lock_sub_owner(p, SUB_THREEWAY);
06227                   if (!p->subs[SUB_THREEWAY].owner) {
06228                      ast_log(LOG_NOTICE, "Whoa, threeway disappeared kinda randomly.\n");
06229                      /* Just hangup */
06230                      return NULL;
06231                   }
06232                   if (p->owner != ast) {
06233                      ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
06234                      ast_log(LOG_WARNING, "This isn't good...\n");
06235                      /* Just hangup */
06236                      return NULL;
06237                   }
06238 
06239                   mssinceflash = ast_tvdiff_ms(ast_tvnow(), p->flashtime);
06240                   ast_debug(1, "Last flash was %d ms ago\n", mssinceflash);
06241                   if (mssinceflash < MIN_MS_SINCE_FLASH) {
06242                      /* It hasn't been long enough since the last flashook.  This is probably a bounce on
06243                         hanging up.  Hangup both channels now */
06244                      ast_debug(1, "Looks like a bounced flash, hanging up both calls on %d\n", p->channel);
06245                      ast_queue_hangup_with_cause(p->subs[SUB_THREEWAY].owner, AST_CAUSE_NO_ANSWER);
06246                      p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
06247                      ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
06248                   } else if ((ast->pbx) || (ast->_state == AST_STATE_UP)) {
06249                      if (p->transfer) {
06250                         /* In any case this isn't a threeway call anymore */
06251                         p->subs[SUB_REAL].inthreeway = 0;
06252                         p->subs[SUB_THREEWAY].inthreeway = 0;
06253                         /* Only attempt transfer if the phone is ringing; why transfer to busy tone eh? */
06254                         if (!p->transfertobusy && ast->_state == AST_STATE_BUSY) {
06255                            /* Swap subs and dis-own channel */
06256                            swap_subs(p, SUB_THREEWAY, SUB_REAL);
06257                            /* Unlock the 3-way call that we swapped to real-call. */
06258                            ast_channel_unlock(p->subs[SUB_REAL].owner);
06259                            p->owner = NULL;
06260                            /* Ring the phone */
06261                            dahdi_ring_phone(p);
06262                         } else {
06263                            res = attempt_transfer(p);
06264                            if (res < 0) {
06265                               /* Transfer attempt failed. */
06266                               p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
06267                               ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
06268                            } else if (res) {
06269                               /* Don't actually hang up at this point */
06270                               break;
06271                            }
06272                         }
06273                      } else {
06274                         p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
06275                         ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
06276                      }
06277                   } else {
06278                      /* Swap subs and dis-own channel */
06279                      swap_subs(p, SUB_THREEWAY, SUB_REAL);
06280                      /* Unlock the 3-way call that we swapped to real-call. */
06281                      ast_channel_unlock(p->subs[SUB_REAL].owner);
06282                      p->owner = NULL;
06283                      /* Ring the phone */
06284                      dahdi_ring_phone(p);
06285                   }
06286                }
06287             } else {
06288                ast_log(LOG_WARNING, "Got a hangup and my index is %d?\n", idx);
06289             }
06290             /* Fall through */
06291          default:
06292             dahdi_disable_ec(p);
06293             return NULL;
06294          }
06295          break;
06296       case DAHDI_EVENT_RINGOFFHOOK:
06297          if (p->inalarm) break;
06298          if (p->oprmode < 0)
06299          {
06300             if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
06301             {
06302                /* Make sure it stops ringing */
06303                dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
06304                tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, -1);
06305                restore_conference(p->oprpeer);
06306             }
06307             break;
06308          }
06309          if (p->radio)
06310          {
06311             p->subs[idx].f.frametype = AST_FRAME_CONTROL;
06312             p->subs[idx].f.subclass = AST_CONTROL_RADIO_KEY;
06313             break;
06314          }
06315          /* for E911, its supposed to wait for offhook then dial
06316             the second half of the dial string */
06317          if (((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) && (ast->_state == AST_STATE_DIALING_OFFHOOK)) {
06318             c = strchr(p->dialdest, '/');
06319             if (c)
06320                c++;
06321             else
06322                c = p->dialdest;
06323             if (*c) snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*0%s#", c);
06324             else ast_copy_string(p->dop.dialstr,"M*2#", sizeof(p->dop.dialstr));
06325             if (strlen(p->dop.dialstr) > 4) {
06326                memset(p->echorest, 'w', sizeof(p->echorest) - 1);
06327                strcpy(p->echorest + (p->echotraining / 401) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
06328                p->echorest[sizeof(p->echorest) - 1] = '\0';
06329                p->echobreak = 1;
06330                p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
06331             } else
06332                p->echobreak = 0;
06333             if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
06334                int saveerr = errno;
06335 
06336                x = DAHDI_ONHOOK;
06337                ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
06338                ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
06339                return NULL;
06340                }
06341             p->dialing = 1;
06342             return &p->subs[idx].f;
06343          }
06344          switch (p->sig) {
06345          case SIG_FXOLS:
06346          case SIG_FXOGS:
06347          case SIG_FXOKS:
06348             p->fxsoffhookstate = 1;
06349             switch (ast->_state) {
06350             case AST_STATE_RINGING:
06351                dahdi_enable_ec(p);
06352                dahdi_train_ec(p);
06353                p->subs[idx].f.frametype = AST_FRAME_CONTROL;
06354                p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
06355                /* Make sure it stops ringing */
06356                p->subs[SUB_REAL].needringing = 0;
06357                dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
06358                ast_debug(1, "channel %d answered\n", p->channel);
06359 
06360                /* Cancel any running CallerID spill */
06361                ast_free(p->cidspill);
06362                p->cidspill = NULL;
06363                restore_conference(p);
06364 
06365                p->dialing = 0;
06366                p->callwaitcas = 0;
06367                if (p->confirmanswer) {
06368                   /* Ignore answer if "confirm answer" is enabled */
06369                   p->subs[idx].f.frametype = AST_FRAME_NULL;
06370                   p->subs[idx].f.subclass = 0;
06371                } else if (!ast_strlen_zero(p->dop.dialstr)) {
06372                   /* nick@dccinc.com 4/3/03 - fxo should be able to do deferred dialing */
06373                   res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
06374                   if (res < 0) {
06375                      ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
06376                      p->dop.dialstr[0] = '\0';
06377                      return NULL;
06378                   } else {
06379                      ast_debug(1, "Sent FXO deferred digit string: %s\n", p->dop.dialstr);
06380                      p->subs[idx].f.frametype = AST_FRAME_NULL;
06381                      p->subs[idx].f.subclass = 0;
06382                      p->dialing = 1;
06383                   }
06384                   p->dop.dialstr[0] = '\0';
06385                   ast_setstate(ast, AST_STATE_DIALING);
06386                } else
06387                   ast_setstate(ast, AST_STATE_UP);
06388                return &p->subs[idx].f;
06389             case AST_STATE_DOWN:
06390                ast_setstate(ast, AST_STATE_RING);
06391                ast->rings = 1;
06392                p->subs[idx].f.frametype = AST_FRAME_CONTROL;
06393                p->subs[idx].f.subclass = AST_CONTROL_OFFHOOK;
06394                ast_debug(1, "channel %d picked up\n", p->channel);
06395                return &p->subs[idx].f;
06396             case AST_STATE_UP:
06397                /* Make sure it stops ringing */
06398                dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
06399                /* Okay -- probably call waiting*/
06400                if (ast_bridged_channel(p->owner))
06401                   ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
06402                p->subs[idx].needunhold = 1;
06403                break;
06404             case AST_STATE_RESERVED:
06405                /* Start up dialtone */
06406                if (has_voicemail(p))
06407                   res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
06408                else
06409                   res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
06410                break;
06411             default:
06412                ast_log(LOG_WARNING, "FXO phone off hook in weird state %d??\n", ast->_state);
06413             }
06414             break;
06415          case SIG_FXSLS:
06416          case SIG_FXSGS:
06417          case SIG_FXSKS:
06418             if (ast->_state == AST_STATE_RING) {
06419                p->ringt = p->ringt_base;
06420             }
06421 
06422             /* If we get a ring then we cannot be in
06423              * reversed polarity. So we reset to idle */
06424             ast_debug(1, "Setting IDLE polarity due "
06425                "to ring. Old polarity was %d\n",
06426                p->polarity);
06427             p->polarity = POLARITY_IDLE;
06428 
06429             /* Fall through */
06430          case SIG_EM:
06431          case SIG_EM_E1:
06432          case SIG_EMWINK:
06433          case SIG_FEATD:
06434          case SIG_FEATDMF:
06435          case SIG_FEATDMF_TA:
06436          case SIG_E911:
06437          case SIG_FGC_CAMA:
06438          case SIG_FGC_CAMAMF:
06439          case SIG_FEATB:
06440          case SIG_SF:
06441          case SIG_SFWINK:
06442          case SIG_SF_FEATD:
06443          case SIG_SF_FEATDMF:
06444          case SIG_SF_FEATB:
06445             if (ast->_state == AST_STATE_PRERING)
06446                ast_setstate(ast, AST_STATE_RING);
06447             if ((ast->_state == AST_STATE_DOWN) || (ast->_state == AST_STATE_RING)) {
06448                ast_debug(1, "Ring detected\n");
06449                p->subs[idx].f.frametype = AST_FRAME_CONTROL;
06450                p->subs[idx].f.subclass = AST_CONTROL_RING;
06451             } else if (p->outgoing && ((ast->_state == AST_STATE_RINGING) || (ast->_state == AST_STATE_DIALING))) {
06452                ast_debug(1, "Line answered\n");
06453                if (p->confirmanswer) {
06454                   p->subs[idx].f.frametype = AST_FRAME_NULL;
06455                   p->subs[idx].f.subclass = 0;
06456                } else {
06457                   p->subs[idx].f.frametype = AST_FRAME_CONTROL;
06458                   p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
06459                   ast_setstate(ast, AST_STATE_UP);
06460                }
06461             } else if (ast->_state != AST_STATE_RING)
06462                ast_log(LOG_WARNING, "Ring/Off-hook in strange state %d on channel %d\n", ast->_state, p->channel);
06463             break;
06464          default:
06465             ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
06466          }
06467          break;
06468       case DAHDI_EVENT_RINGBEGIN:
06469          switch (p->sig) {
06470          case SIG_FXSLS:
06471          case SIG_FXSGS:
06472          case SIG_FXSKS:
06473             if (ast->_state == AST_STATE_RING) {
06474                p->ringt = p->ringt_base;
06475             }
06476             break;
06477          }
06478          break;
06479       case DAHDI_EVENT_RINGEROFF:
06480          if (p->inalarm) break;
06481          if ((p->radio || (p->oprmode < 0))) break;
06482          ast->rings++;
06483          if ((ast->rings > p->cidrings) && (p->cidspill)) {
06484             ast_log(LOG_WARNING, "Didn't finish Caller-ID spill.  Cancelling.\n");
06485             ast_free(p->cidspill);
06486             p->cidspill = NULL;
06487             p->callwaitcas = 0;
06488          }
06489          p->subs[idx].f.frametype = AST_FRAME_CONTROL;
06490          p->subs[idx].f.subclass = AST_CONTROL_RINGING;
06491          break;
06492       case DAHDI_EVENT_RINGERON:
06493          break;
06494       case DAHDI_EVENT_NOALARM:
06495          p->inalarm = 0;
06496 #ifdef HAVE_PRI
06497          /* Extremely unlikely but just in case */
06498          if (p->bearer)
06499             p->bearer->inalarm = 0;
06500 #endif
06501          ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel);
06502          manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
06503                         "Channel: %d\r\n", p->channel);
06504          break;
06505       case DAHDI_EVENT_WINKFLASH:
06506          if (p->inalarm) break;
06507          if (p->radio) break;
06508          if (p->oprmode < 0) break;
06509          if (p->oprmode > 1)
06510          {
06511             struct dahdi_params par;
06512 
06513             memset(&par, 0, sizeof(par));
06514             if (ioctl(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par) != -1)
06515             {
06516                if (!par.rxisoffhook)
06517                {
06518                   /* Make sure it stops ringing */
06519                   dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
06520                   dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RING);
06521                   save_conference(p);
06522                   tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
06523                }
06524             }
06525             break;
06526          }
06527          /* Remember last time we got a flash-hook */
06528          p->flashtime = ast_tvnow();
06529          switch (mysig) {
06530          case SIG_FXOLS:
06531          case SIG_FXOGS:
06532          case SIG_FXOKS:
06533             ast_debug(1, "Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n",
06534                idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
06535 
06536             /* Cancel any running CallerID spill */
06537             ast_free(p->cidspill);
06538             p->cidspill = NULL;
06539             restore_conference(p);
06540             p->callwaitcas = 0;
06541 
06542             if (idx != SUB_REAL) {
06543                ast_log(LOG_WARNING, "Got flash hook with index %d on channel %d?!?\n", idx, p->channel);
06544                goto winkflashdone;
06545             }
06546 
06547             if (p->subs[SUB_CALLWAIT].owner) {
06548                /* Need to hold the lock for real-call, private, and call-waiting call */
06549                dahdi_lock_sub_owner(p, SUB_CALLWAIT);
06550                if (!p->subs[SUB_CALLWAIT].owner) {
06551                   /*
06552                    * The call waiting call dissappeared.
06553                    * Let's just ignore this flash-hook.
06554                    */
06555                   ast_log(LOG_NOTICE, "Whoa, the call-waiting call disappeared.\n");
06556                   goto winkflashdone;
06557                }
06558 
06559                /* Swap to call-wait */
06560                swap_subs(p, SUB_REAL, SUB_CALLWAIT);
06561                tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06562                p->owner = p->subs[SUB_REAL].owner;
06563                ast_debug(1, "Making %s the new owner\n", p->owner->name);
06564                if (p->owner->_state == AST_STATE_RINGING) {
06565                   ast_setstate(p->owner, AST_STATE_UP);
06566                   p->subs[SUB_REAL].needanswer = 1;
06567                }
06568                p->callwaitingrepeat = 0;
06569                p->cidcwexpire = 0;
06570                p->cid_suppress_expire = 0;
06571 
06572                /* Start music on hold if appropriate */
06573                if (!p->subs[SUB_CALLWAIT].inthreeway && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
06574                   ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
06575                      S_OR(p->mohsuggest, NULL),
06576                      !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
06577                }
06578                p->subs[SUB_CALLWAIT].needhold = 1;
06579                if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
06580                   ast_queue_control_data(p->subs[SUB_REAL].owner, AST_CONTROL_HOLD,
06581                      S_OR(p->mohsuggest, NULL),
06582                      !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
06583                }
06584                p->subs[SUB_REAL].needunhold = 1;
06585 
06586                /* Unlock the call-waiting call that we swapped to real-call. */
06587                ast_channel_unlock(p->subs[SUB_REAL].owner);
06588             } else if (!p->subs[SUB_THREEWAY].owner) {
06589                if (!p->threewaycalling) {
06590                   /* Just send a flash if no 3-way calling */
06591                   p->subs[SUB_REAL].needflash = 1;
06592                   goto winkflashdone;
06593                } else if (!check_for_conference(p)) {
06594                   char cid_num[256];
06595                   char cid_name[256];
06596 
06597                   cid_num[0] = 0;
06598                   cid_name[0] = 0;
06599                   if (p->dahditrcallerid && p->owner) {
06600                      if (p->owner->cid.cid_num)
06601                         ast_copy_string(cid_num, p->owner->cid.cid_num, sizeof(cid_num));
06602                      if (p->owner->cid.cid_name)
06603                         ast_copy_string(cid_name, p->owner->cid.cid_name, sizeof(cid_name));
06604                   }
06605                   /* XXX This section needs much more error checking!!! XXX */
06606                   /* Start a 3-way call if feasible */
06607                   if (!((ast->pbx) ||
06608                      (ast->_state == AST_STATE_UP) ||
06609                      (ast->_state == AST_STATE_RING))) {
06610                      ast_debug(1, "Flash when call not up or ringing\n");
06611                      goto winkflashdone;
06612                   }
06613                   if (alloc_sub(p, SUB_THREEWAY)) {
06614                      ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n");
06615                      goto winkflashdone;
06616                   }
06617                   /* Make new channel */
06618                   chan = dahdi_new(p, AST_STATE_RESERVED, 0, SUB_THREEWAY, 0, 0);
06619                   if (!chan) {
06620                      ast_log(LOG_WARNING,
06621                         "Cannot allocate new call structure on channel %d\n",
06622                         p->channel);
06623                      unalloc_sub(p, SUB_THREEWAY);
06624                      goto winkflashdone;
06625                   }
06626                   if (p->dahditrcallerid) {
06627                      if (!p->origcid_num)
06628                         p->origcid_num = ast_strdup(p->cid_num);
06629                      if (!p->origcid_name)
06630                         p->origcid_name = ast_strdup(p->cid_name);
06631                      ast_copy_string(p->cid_num, cid_num, sizeof(p->cid_num));
06632                      ast_copy_string(p->cid_name, cid_name, sizeof(p->cid_name));
06633                   }
06634                   /* Swap things around between the three-way and real call */
06635                   swap_subs(p, SUB_THREEWAY, SUB_REAL);
06636                   /* Disable echo canceller for better dialing */
06637                   dahdi_disable_ec(p);
06638                   res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALRECALL);
06639                   if (res)
06640                      ast_log(LOG_WARNING, "Unable to start dial recall tone on channel %d\n", p->channel);
06641                   p->owner = chan;
06642                   if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
06643                      ast_log(LOG_WARNING, "Unable to start simple switch on channel %d\n", p->channel);
06644                      res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
06645                      dahdi_enable_ec(p);
06646                      ast_hangup(chan);
06647                   } else {
06648                      ast_verb(3, "Started three way call on channel %d\n", p->channel);
06649 
06650                      /* Start music on hold if appropriate */
06651                      if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
06652                         ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
06653                            S_OR(p->mohsuggest, NULL),
06654                            !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
06655                      }
06656                      p->subs[SUB_THREEWAY].needhold = 1;
06657                   }
06658                }
06659             } else {
06660                /* Already have a 3 way call */
06661                int orig_3way_sub;
06662 
06663                /* Need to hold the lock for real-call, private, and 3-way call */
06664                dahdi_lock_sub_owner(p, SUB_THREEWAY);
06665                if (!p->subs[SUB_THREEWAY].owner) {
06666                   /*
06667                    * The 3-way call dissappeared.
06668                    * Let's just ignore this flash-hook.
06669                    */
06670                   ast_log(LOG_NOTICE, "Whoa, the 3-way call disappeared.\n");
06671                   goto winkflashdone;
06672                }
06673                orig_3way_sub = SUB_THREEWAY;
06674 
06675                if (p->subs[SUB_THREEWAY].inthreeway) {
06676                   /* Call is already up, drop the last person */
06677                   ast_debug(1, "Got flash with three way call up, dropping last call on %d\n", p->channel);
06678                   /* If the primary call isn't answered yet, use it */
06679                   if ((p->subs[SUB_REAL].owner->_state != AST_STATE_UP) && (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_UP)) {
06680                      /* Swap back -- we're dropping the real 3-way that isn't finished yet*/
06681                      swap_subs(p, SUB_THREEWAY, SUB_REAL);
06682                      orig_3way_sub = SUB_REAL;
06683                      p->owner = p->subs[SUB_REAL].owner;
06684                   }
06685                   /* Drop the last call and stop the conference */
06686                   ast_verb(3, "Dropping three-way call on %s\n", p->subs[SUB_THREEWAY].owner->name);
06687                   p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
06688                   p->subs[SUB_REAL].inthreeway = 0;
06689                   p->subs[SUB_THREEWAY].inthreeway = 0;
06690                } else {
06691                   /* Lets see what we're up to */
06692                   if (((ast->pbx) || (ast->_state == AST_STATE_UP)) &&
06693                      (p->transfertobusy || (ast->_state != AST_STATE_BUSY))) {
06694                      ast_verb(3, "Building conference call with %s and %s\n",
06695                         p->subs[SUB_THREEWAY].owner->name,
06696                         p->subs[SUB_REAL].owner->name);
06697                      /* Put them in the threeway, and flip */
06698                      p->subs[SUB_THREEWAY].inthreeway = 1;
06699                      p->subs[SUB_REAL].inthreeway = 1;
06700                      if (ast->_state == AST_STATE_UP) {
06701                         swap_subs(p, SUB_THREEWAY, SUB_REAL);
06702                         orig_3way_sub = SUB_REAL;
06703                      }
06704                      if (ast_bridged_channel(p->subs[orig_3way_sub].owner)) {
06705                         ast_queue_control(p->subs[orig_3way_sub].owner, AST_CONTROL_UNHOLD);
06706                      }
06707                      p->subs[orig_3way_sub].needunhold = 1;
06708                      p->owner = p->subs[SUB_REAL].owner;
06709                   } else {
06710                      ast_verb(3, "Dumping incomplete call on %s\n", p->subs[SUB_THREEWAY].owner->name);
06711                      swap_subs(p, SUB_THREEWAY, SUB_REAL);
06712                      orig_3way_sub = SUB_REAL;
06713                      p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
06714                      p->owner = p->subs[SUB_REAL].owner;
06715                      if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
06716                         ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
06717                      }
06718                      p->subs[SUB_REAL].needunhold = 1;
06719                      dahdi_enable_ec(p);
06720                   }
06721                }
06722                ast_channel_unlock(p->subs[orig_3way_sub].owner);
06723             }
06724 winkflashdone:
06725             update_conf(p);
06726             break;
06727          case SIG_EM:
06728          case SIG_EM_E1:
06729          case SIG_FEATD:
06730          case SIG_SF:
06731          case SIG_SFWINK:
06732          case SIG_SF_FEATD:
06733          case SIG_FXSLS:
06734          case SIG_FXSGS:
06735             if (option_debug) {
06736                if (p->dialing)
06737                   ast_debug(1, "Ignoring wink on channel %d\n", p->channel);
06738                else
06739                   ast_debug(1, "Got wink in weird state %d on channel %d\n", ast->_state, p->channel);
06740             }
06741             break;
06742          case SIG_FEATDMF_TA:
06743             switch (p->whichwink) {
06744             case 0:
06745                ast_debug(1, "ANI2 set to '%d' and ANI is '%s'\n", p->owner->cid.cid_ani2, p->owner->cid.cid_ani);
06746                snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%d%s#", p->owner->cid.cid_ani2, p->owner->cid.cid_ani);
06747                break;
06748             case 1:
06749                ast_copy_string(p->dop.dialstr, p->finaldial, sizeof(p->dop.dialstr));
06750                break;
06751             case 2:
06752                ast_log(LOG_WARNING, "Received unexpected wink on channel of type SIG_FEATDMF_TA\n");
06753                return NULL;
06754             }
06755             p->whichwink++;
06756             /* Fall through */
06757          case SIG_FEATDMF:
06758          case SIG_E911:
06759          case SIG_FGC_CAMAMF:
06760          case SIG_FGC_CAMA:
06761          case SIG_FEATB:
06762          case SIG_SF_FEATDMF:
06763          case SIG_SF_FEATB:
06764          case SIG_EMWINK:
06765             /* FGD MF and EMWINK *Must* wait for wink */
06766             if (!ast_strlen_zero(p->dop.dialstr)) {
06767                res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
06768                if (res < 0) {
06769                   ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
06770                   p->dop.dialstr[0] = '\0';
06771                   return NULL;
06772                } else
06773                   ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
06774             }
06775             p->dop.dialstr[0] = '\0';
06776             break;
06777          default:
06778             ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
06779          }
06780          break;
06781       case DAHDI_EVENT_HOOKCOMPLETE:
06782          if (p->inalarm) break;
06783          if ((p->radio || (p->oprmode < 0))) break;
06784          if (p->waitingfordt.tv_sec) break;
06785          switch (mysig) {
06786          case SIG_FXSLS:  /* only interesting for FXS */
06787          case SIG_FXSGS:
06788          case SIG_FXSKS:
06789          case SIG_EM:
06790          case SIG_EM_E1:
06791          case SIG_EMWINK:
06792          case SIG_FEATD:
06793          case SIG_SF:
06794          case SIG_SFWINK:
06795          case SIG_SF_FEATD:
06796             if (!ast_strlen_zero(p->dop.dialstr)) {
06797                res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
06798                if (res < 0) {
06799                   ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
06800                   p->dop.dialstr[0] = '\0';
06801                   return NULL;
06802                } else
06803                   ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
06804             }
06805             p->dop.dialstr[0] = '\0';
06806             p->dop.op = DAHDI_DIAL_OP_REPLACE;
06807             break;
06808          case SIG_FEATDMF:
06809          case SIG_FEATDMF_TA:
06810          case SIG_E911:
06811          case SIG_FGC_CAMA:
06812          case SIG_FGC_CAMAMF:
06813          case SIG_FEATB:
06814          case SIG_SF_FEATDMF:
06815          case SIG_SF_FEATB:
06816             ast_debug(1, "Got hook complete in MF FGD, waiting for wink now on channel %d\n",p->channel);
06817             break;
06818          default:
06819             break;
06820          }
06821          break;
06822       case DAHDI_EVENT_POLARITY:
06823          /*
06824           * If we get a Polarity Switch event, this could be
06825           * due to line seizure, remote end connect or remote end disconnect.
06826           *
06827           * Check to see if we should change the polarity state and
06828           * mark the channel as UP or if this is an indication
06829           * of remote end disconnect.
06830           */
06831 
06832          if (p->polarityonanswerdelay > 0) {
06833             /* check if event is not too soon after OffHook or Answer */
06834             if (ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) > p->polarityonanswerdelay) {
06835                switch (ast->_state) {
06836                case AST_STATE_DIALING:       /*!< Digits (or equivalent) have been dialed */
06837                case AST_STATE_RINGING:       /*!< Remote end is ringing */
06838                   if (p->answeronpolarityswitch) {
06839                      ast_debug(1, "Answering on polarity switch! channel %d\n", p->channel);
06840                      ast_setstate(p->owner, AST_STATE_UP);
06841                      p->polarity = POLARITY_REV;
06842                      if (p->hanguponpolarityswitch) {
06843                         p->polaritydelaytv = ast_tvnow();
06844                      }
06845                   } else {
06846                      ast_debug(1, "Ignore Answer on polarity switch, channel %d\n", p->channel);
06847                   }
06848                   break;
06849 
06850                case AST_STATE_UP:         /*!< Line is up */
06851                case AST_STATE_RING:       /*!< Line is ringing */
06852                   if (p->hanguponpolarityswitch) {
06853                      ast_debug(1, "HangingUp on polarity switch! channel %d\n", p->channel);
06854                      ast_softhangup(p->owner, AST_SOFTHANGUP_EXPLICIT);
06855                      p->polarity = POLARITY_IDLE;
06856                   } else {
06857                      ast_debug(1, "Ignore Hangup on polarity switch, channel %d\n", p->channel);
06858                   }
06859                   break;
06860 
06861                case AST_STATE_DOWN:       /*!< Channel is down and available */
06862                case AST_STATE_RESERVED:      /*!< Channel is down, but reserved */
06863                case AST_STATE_OFFHOOK:       /*!< Channel is off hook */
06864                case AST_STATE_BUSY:       /*!< Line is busy */
06865                case AST_STATE_DIALING_OFFHOOK:     /*!< Digits (or equivalent) have been dialed while offhook */
06866                case AST_STATE_PRERING:       /*!< Channel has detected an incoming call and is waiting for ring */
06867                default:
06868                   if (p->answeronpolarityswitch || p->hanguponpolarityswitch) {
06869                      ast_debug(1, "Ignoring Polarity switch on channel %d, state %d\n", p->channel, ast->_state);
06870                   }
06871                }
06872 
06873             } else {
06874                /* event is too soon after OffHook or Answer */
06875                switch (ast->_state) {
06876                case AST_STATE_DIALING:       /*!< Digits (or equivalent) have been dialed */
06877                case AST_STATE_RINGING:       /*!< Remote end is ringing */
06878                   if (p->answeronpolarityswitch) {
06879                      ast_debug(1, "Polarity switch detected but NOT answering (too close to OffHook event) on channel %d, state %d\n", p->channel, ast->_state);
06880                   }
06881                   break;
06882 
06883                case AST_STATE_UP:         /*!< Line is up */
06884                case AST_STATE_RING:       /*!< Line is ringing */
06885                   if (p->hanguponpolarityswitch) {
06886                      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);
06887                   }
06888                   break;
06889 
06890                default: 
06891                   if (p->answeronpolarityswitch || p->hanguponpolarityswitch) {
06892                      ast_debug(1, "Polarity switch detected (too close to previous event) on channel %d, state %d\n", p->channel, ast->_state);
06893                   }
06894                }
06895             }
06896          }
06897 
06898          /* Added more log_debug information below to provide a better indication of what is going on */
06899          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) );
06900          break;
06901       default:
06902          ast_debug(1, "Dunno what to do with event %d on channel %d\n", res, p->channel);
06903    }
06904    return &p->subs[idx].f;
06905 }
06906 
06907 static struct ast_frame *__dahdi_exception(struct ast_channel *ast)
06908 {
06909    struct dahdi_pvt *p = ast->tech_pvt;
06910    int res;
06911    int idx;
06912    struct ast_frame *f;
06913 
06914 
06915    idx = dahdi_get_index(ast, p, 1);
06916    if (idx < 0) {
06917       idx = SUB_REAL;
06918    }
06919 
06920    p->subs[idx].f.frametype = AST_FRAME_NULL;
06921    p->subs[idx].f.datalen = 0;
06922    p->subs[idx].f.samples = 0;
06923    p->subs[idx].f.mallocd = 0;
06924    p->subs[idx].f.offset = 0;
06925    p->subs[idx].f.subclass = 0;
06926    p->subs[idx].f.delivery = ast_tv(0,0);
06927    p->subs[idx].f.src = "dahdi_exception";
06928    p->subs[idx].f.data.ptr = NULL;
06929 
06930    if ((!p->owner) && (!(p->radio || (p->oprmode < 0)))) {
06931       /* If nobody owns us, absorb the event appropriately, otherwise
06932          we loop indefinitely.  This occurs when, during call waiting, the
06933          other end hangs up our channel so that it no longer exists, but we
06934          have neither FLASH'd nor ONHOOK'd to signify our desire to
06935          change to the other channel. */
06936       if (p->fake_event) {
06937          res = p->fake_event;
06938          p->fake_event = 0;
06939       } else
06940          res = dahdi_get_event(p->subs[SUB_REAL].dfd);
06941       /* Switch to real if there is one and this isn't something really silly... */
06942       if ((res != DAHDI_EVENT_RINGEROFF) && (res != DAHDI_EVENT_RINGERON) &&
06943          (res != DAHDI_EVENT_HOOKCOMPLETE)) {
06944          ast_debug(1, "Restoring owner of channel %d on event %d\n", p->channel, res);
06945          p->owner = p->subs[SUB_REAL].owner;
06946          if (p->owner && ast != p->owner) {
06947             /*
06948              * Could this even happen?
06949              * Possible deadlock because we do not have the real-call lock.
06950              */
06951             ast_log(LOG_WARNING, "Event %s on %s is not restored owner %s\n",
06952                event2str(res), ast->name, p->owner->name);
06953          }
06954          if (p->owner && ast_bridged_channel(p->owner))
06955             ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
06956          p->subs[SUB_REAL].needunhold = 1;
06957       }
06958       switch (res) {
06959       case DAHDI_EVENT_ONHOOK:
06960          dahdi_disable_ec(p);
06961          if (p->owner) {
06962             ast_verb(3, "Channel %s still has call, ringing phone\n", p->owner->name);
06963             dahdi_ring_phone(p);
06964             p->callwaitingrepeat = 0;
06965             p->cidcwexpire = 0;
06966             p->cid_suppress_expire = 0;
06967          } else {
06968             ast_log(LOG_WARNING, "Absorbed %s, but nobody is left!?!?\n",
06969                event2str(res));
06970          }
06971          update_conf(p);
06972          break;
06973       case DAHDI_EVENT_RINGOFFHOOK:
06974          dahdi_enable_ec(p);
06975          dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
06976          if (p->owner && (p->owner->_state == AST_STATE_RINGING)) {
06977             p->subs[SUB_REAL].needanswer = 1;
06978             p->dialing = 0;
06979          }
06980          break;
06981       case DAHDI_EVENT_HOOKCOMPLETE:
06982       case DAHDI_EVENT_RINGERON:
06983       case DAHDI_EVENT_RINGEROFF:
06984          /* Do nothing */
06985          break;
06986       case DAHDI_EVENT_WINKFLASH:
06987          p->flashtime = ast_tvnow();
06988          if (p->owner) {
06989             ast_verb(3, "Channel %d flashed to other channel %s\n", p->channel, p->owner->name);
06990             if (p->owner->_state != AST_STATE_UP) {
06991                /* Answer if necessary */
06992                p->subs[SUB_REAL].needanswer = 1;
06993                ast_setstate(p->owner, AST_STATE_UP);
06994             }
06995             p->callwaitingrepeat = 0;
06996             p->cidcwexpire = 0;
06997             p->cid_suppress_expire = 0;
06998             if (ast_bridged_channel(p->owner))
06999                ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
07000             p->subs[SUB_REAL].needunhold = 1;
07001          } else {
07002             ast_log(LOG_WARNING, "Absorbed %s, but nobody is left!?!?\n",
07003                event2str(res));
07004          }
07005          update_conf(p);
07006          break;
07007       default:
07008          ast_log(LOG_WARNING, "Don't know how to absorb event %s\n", event2str(res));
07009          break;
07010       }
07011       f = &p->subs[idx].f;
07012       return f;
07013    }
07014    if (!(p->radio || (p->oprmode < 0)))
07015       ast_debug(1, "Exception on %d, channel %d\n", ast->fds[0],p->channel);
07016    /* If it's not us, return NULL immediately */
07017    if (ast != p->owner) {
07018       ast_log(LOG_WARNING, "We're %s, not %s\n", ast->name, p->owner->name);
07019       f = &p->subs[idx].f;
07020       return f;
07021    }
07022    f = dahdi_handle_event(ast);
07023    return f;
07024 }
07025 
07026 static struct ast_frame *dahdi_exception(struct ast_channel *ast)
07027 {
07028    struct dahdi_pvt *p = ast->tech_pvt;
07029    struct ast_frame *f;
07030    ast_mutex_lock(&p->lock);
07031    f = __dahdi_exception(ast);
07032    ast_mutex_unlock(&p->lock);
07033    return f;
07034 }
07035 
07036 static struct ast_frame *dahdi_read(struct ast_channel *ast)
07037 {
07038    struct dahdi_pvt *p = ast->tech_pvt;
07039    int res;
07040    int idx;
07041    void *readbuf;
07042    struct ast_frame *f;
07043 
07044    while (ast_mutex_trylock(&p->lock)) {
07045       CHANNEL_DEADLOCK_AVOIDANCE(ast);
07046    }
07047 
07048    idx = dahdi_get_index(ast, p, 0);
07049 
07050    /* Hang up if we don't really exist */
07051    if (idx < 0)   {
07052       ast_log(LOG_WARNING, "We don't exist?\n");
07053       ast_mutex_unlock(&p->lock);
07054       return NULL;
07055    }
07056 
07057    if ((p->radio || (p->oprmode < 0)) && p->inalarm) {
07058       ast_mutex_unlock(&p->lock);
07059       return NULL;
07060    }
07061 
07062    p->subs[idx].f.frametype = AST_FRAME_NULL;
07063    p->subs[idx].f.datalen = 0;
07064    p->subs[idx].f.samples = 0;
07065    p->subs[idx].f.mallocd = 0;
07066    p->subs[idx].f.offset = 0;
07067    p->subs[idx].f.subclass = 0;
07068    p->subs[idx].f.delivery = ast_tv(0,0);
07069    p->subs[idx].f.src = "dahdi_read";
07070    p->subs[idx].f.data.ptr = NULL;
07071 
07072    /* make sure it sends initial key state as first frame */
07073    if ((p->radio || (p->oprmode < 0)) && (!p->firstradio))
07074    {
07075       struct dahdi_params ps;
07076 
07077       memset(&ps, 0, sizeof(ps));
07078       ps.channo = p->channel;
07079       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
07080          ast_mutex_unlock(&p->lock);
07081          return NULL;
07082       }
07083       p->firstradio = 1;
07084       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
07085       if (ps.rxisoffhook)
07086       {
07087          p->subs[idx].f.subclass = AST_CONTROL_RADIO_KEY;
07088       }
07089       else
07090       {
07091          p->subs[idx].f.subclass = AST_CONTROL_RADIO_UNKEY;
07092       }
07093       ast_mutex_unlock(&p->lock);
07094       return &p->subs[idx].f;
07095    }
07096    if (p->ringt == 1) {
07097       ast_mutex_unlock(&p->lock);
07098       return NULL;
07099    }
07100    else if (p->ringt > 0)
07101       p->ringt--;
07102 
07103 #ifdef HAVE_OPENR2
07104    if (p->mfcr2) {
07105       openr2_chan_process_event(p->r2chan);
07106       if (OR2_DIR_FORWARD == openr2_chan_get_direction(p->r2chan)) {
07107          struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, };
07108          /* if the call is already accepted and we already delivered AST_CONTROL_RINGING
07109           * now enqueue a progress frame to bridge the media up */
07110          if (p->mfcr2_call_accepted &&
07111              !p->mfcr2_progress && 
07112              ast->_state == AST_STATE_RINGING) {
07113             ast_log(LOG_DEBUG, "Enqueuing progress frame after R2 accept in chan %d\n", p->channel);
07114             ast_queue_frame(p->owner, &f);
07115             p->mfcr2_progress = 1;
07116          }
07117       }
07118    }
07119 #endif
07120 
07121    if (p->subs[idx].needringing) {
07122       /* Send ringing frame if requested */
07123       p->subs[idx].needringing = 0;
07124       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
07125       p->subs[idx].f.subclass = AST_CONTROL_RINGING;
07126       ast_setstate(ast, AST_STATE_RINGING);
07127       ast_mutex_unlock(&p->lock);
07128       return &p->subs[idx].f;
07129    }
07130 
07131    if (p->subs[idx].needbusy) {
07132       /* Send busy frame if requested */
07133       p->subs[idx].needbusy = 0;
07134       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
07135       p->subs[idx].f.subclass = AST_CONTROL_BUSY;
07136       ast_mutex_unlock(&p->lock);
07137       return &p->subs[idx].f;
07138    }
07139 
07140    if (p->subs[idx].needcongestion) {
07141       /* Send congestion frame if requested */
07142       p->subs[idx].needcongestion = 0;
07143       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
07144       p->subs[idx].f.subclass = AST_CONTROL_CONGESTION;
07145       ast_mutex_unlock(&p->lock);
07146       return &p->subs[idx].f;
07147    }
07148 
07149    if (p->subs[idx].needcallerid && !ast->cid.cid_tns) {
07150       ast_set_callerid(ast, S_OR(p->lastcid_num, NULL),
07151                      S_OR(p->lastcid_name, NULL),
07152                      S_OR(p->lastcid_num, NULL)
07153                      );
07154       p->subs[idx].needcallerid = 0;
07155    }
07156 
07157    if (p->subs[idx].needanswer) {
07158       /* Send answer frame if requested */
07159       p->subs[idx].needanswer = 0;
07160       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
07161       p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
07162       ast_mutex_unlock(&p->lock);
07163       return &p->subs[idx].f;
07164    }
07165 #ifdef HAVE_OPENR2
07166    if (p->mfcr2 && openr2_chan_get_read_enabled(p->r2chan)) {
07167       /* openr2 took care of reading and handling any event
07168         (needanswer, needbusy etc), if we continue we will read()
07169         twice, lets just return a null frame. This should only
07170         happen when openr2 is dialing out */
07171       ast_mutex_unlock(&p->lock);
07172       return &ast_null_frame;
07173    }
07174 #endif
07175 
07176    if (p->subs[idx].needflash) {
07177       /* Send answer frame if requested */
07178       p->subs[idx].needflash = 0;
07179       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
07180       p->subs[idx].f.subclass = AST_CONTROL_FLASH;
07181       ast_mutex_unlock(&p->lock);
07182       return &p->subs[idx].f;
07183    }
07184 
07185    if (p->subs[idx].needhold) {
07186       /* Send answer frame if requested */
07187       p->subs[idx].needhold = 0;
07188       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
07189       p->subs[idx].f.subclass = AST_CONTROL_HOLD;
07190       ast_mutex_unlock(&p->lock);
07191       ast_debug(1, "Sending hold on '%s'\n", ast->name);
07192       return &p->subs[idx].f;
07193    }
07194 
07195    if (p->subs[idx].needunhold) {
07196       /* Send answer frame if requested */
07197       p->subs[idx].needunhold = 0;
07198       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
07199       p->subs[idx].f.subclass = AST_CONTROL_UNHOLD;
07200       ast_mutex_unlock(&p->lock);
07201       ast_debug(1, "Sending unhold on '%s'\n", ast->name);
07202       return &p->subs[idx].f;
07203    }
07204 
07205    if (ast->rawreadformat == AST_FORMAT_SLINEAR) {
07206       if (!p->subs[idx].linear) {
07207          p->subs[idx].linear = 1;
07208          res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
07209          if (res)
07210             ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to linear mode.\n", p->channel, idx);
07211       }
07212    } else if ((ast->rawreadformat == AST_FORMAT_ULAW) ||
07213       (ast->rawreadformat == AST_FORMAT_ALAW)) {
07214       if (p->subs[idx].linear) {
07215          p->subs[idx].linear = 0;
07216          res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
07217          if (res)
07218             ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to companded mode.\n", p->channel, idx);
07219       }
07220    } else {
07221       ast_log(LOG_WARNING, "Don't know how to read frames in format %s\n", ast_getformatname(ast->rawreadformat));
07222       ast_mutex_unlock(&p->lock);
07223       return NULL;
07224    }
07225    readbuf = ((unsigned char *)p->subs[idx].buffer) + AST_FRIENDLY_OFFSET;
07226    CHECK_BLOCKING(ast);
07227    res = read(p->subs[idx].dfd, readbuf, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
07228    ast_clear_flag(ast, AST_FLAG_BLOCKING);
07229    /* Check for hangup */
07230    if (res < 0) {
07231       f = NULL;
07232       if (res == -1) {
07233          if (errno == EAGAIN) {
07234             /* Return "NULL" frame if there is nobody there */
07235             ast_mutex_unlock(&p->lock);
07236             return &p->subs[idx].f;
07237          } else if (errno == ELAST) {
07238             f = __dahdi_exception(ast);
07239          } else
07240             ast_log(LOG_WARNING, "dahdi_rec: %s\n", strerror(errno));
07241       }
07242       ast_mutex_unlock(&p->lock);
07243       return f;
07244    }
07245    if (res != (p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE)) {
07246       ast_debug(1, "Short read (%d/%d), must be an event...\n", res, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
07247       f = __dahdi_exception(ast);
07248       ast_mutex_unlock(&p->lock);
07249       return f;
07250    }
07251    if (p->tdd) { /* if in TDD mode, see if we receive that */
07252       int c;
07253 
07254       c = tdd_feed(p->tdd,readbuf,READ_SIZE);
07255       if (c < 0) {
07256          ast_debug(1,"tdd_feed failed\n");
07257          ast_mutex_unlock(&p->lock);
07258          return NULL;
07259       }
07260       if (c) { /* if a char to return */
07261          p->subs[idx].f.subclass = 0;
07262          p->subs[idx].f.frametype = AST_FRAME_TEXT;
07263          p->subs[idx].f.mallocd = 0;
07264          p->subs[idx].f.offset = AST_FRIENDLY_OFFSET;
07265          p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET;
07266          p->subs[idx].f.datalen = 1;
07267          *((char *) p->subs[idx].f.data.ptr) = c;
07268          ast_mutex_unlock(&p->lock);
07269          return &p->subs[idx].f;
07270       }
07271    }
07272    if (idx == SUB_REAL) {
07273       /* Ensure the CW timers decrement only on a single subchannel */
07274       if (p->cidcwexpire) {
07275          if (!--p->cidcwexpire) {
07276             /* Expired CID/CW */
07277             ast_verb(3, "CPE does not support Call Waiting Caller*ID.\n");
07278             restore_conference(p);
07279          }
07280       }
07281       if (p->cid_suppress_expire) {
07282          --p->cid_suppress_expire;
07283       }
07284       if (p->callwaitingrepeat) {
07285          if (!--p->callwaitingrepeat) {
07286             /* Expired, Repeat callwaiting tone */
07287             ++p->callwaitrings;
07288             dahdi_callwait(ast);
07289          }
07290       }
07291    }
07292    if (p->subs[idx].linear) {
07293       p->subs[idx].f.datalen = READ_SIZE * 2;
07294    } else
07295       p->subs[idx].f.datalen = READ_SIZE;
07296 
07297    /* Handle CallerID Transmission */
07298    if ((p->owner == ast) && p->cidspill &&((ast->_state == AST_STATE_UP) || (ast->rings == p->cidrings))) {
07299       send_callerid(p);
07300    }
07301 
07302    p->subs[idx].f.frametype = AST_FRAME_VOICE;
07303    p->subs[idx].f.subclass = ast->rawreadformat;
07304    p->subs[idx].f.samples = READ_SIZE;
07305    p->subs[idx].f.mallocd = 0;
07306    p->subs[idx].f.offset = AST_FRIENDLY_OFFSET;
07307    p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET / sizeof(p->subs[idx].buffer[0]);
07308 #if 0
07309    ast_debug(1, "Read %d of voice on %s\n", p->subs[idx].f.datalen, ast->name);
07310 #endif
07311    if (p->dialing || /* Transmitting something */
07312       (idx && (ast->_state != AST_STATE_UP)) || /* Three-way or callwait that isn't up */
07313       ((idx == SUB_CALLWAIT) && !p->subs[SUB_CALLWAIT].inthreeway) /* Inactive and non-confed call-wait */
07314       ) {
07315       /* Whoops, we're still dialing, or in a state where we shouldn't transmit....
07316          don't send anything */
07317       p->subs[idx].f.frametype = AST_FRAME_NULL;
07318       p->subs[idx].f.subclass = 0;
07319       p->subs[idx].f.samples = 0;
07320       p->subs[idx].f.mallocd = 0;
07321       p->subs[idx].f.offset = 0;
07322       p->subs[idx].f.data.ptr = NULL;
07323       p->subs[idx].f.datalen= 0;
07324    }
07325    if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect || p->callprogress || p->waitingfordt.tv_sec) && !idx) {
07326       /* Perform busy detection etc on the dahdi line */
07327       int mute;
07328 
07329       f = ast_dsp_process(ast, p->dsp, &p->subs[idx].f);
07330 
07331       /* Check if DSP code thinks we should be muting this frame and mute the conference if so */
07332       mute = ast_dsp_was_muted(p->dsp);
07333       if (p->muting != mute) {
07334          p->muting = mute;
07335          dahdi_confmute(p, mute);
07336       }
07337 
07338       if (f) {
07339          if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_BUSY)) {
07340             if ((ast->_state == AST_STATE_UP) && !p->outgoing) {
07341                /* Treat this as a "hangup" instead of a "busy" on the assumption that
07342                   a busy */
07343                f = NULL;
07344             }
07345          } else if (f->frametype == AST_FRAME_DTMF_BEGIN
07346             || f->frametype == AST_FRAME_DTMF_END) {
07347 #ifdef HAVE_PRI
07348             if (((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))
07349                && p->call_level < DAHDI_CALL_LEVEL_PROCEEDING
07350                && p->pri
07351                && ((!p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING))
07352                   || (p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)))) {
07353                /* Don't accept in-band DTMF when in overlap dial mode */
07354                ast_debug(1, "Absorbing inband %s DTMF digit: 0x%02X '%c' on %s\n",
07355                   f->frametype == AST_FRAME_DTMF_BEGIN ? "begin" : "end",
07356                   f->subclass, f->subclass, ast->name);
07357 
07358                f->frametype = AST_FRAME_NULL;
07359                f->subclass = 0;
07360             }
07361 #endif
07362             /* DSP clears us of being pulse */
07363             p->pulsedial = 0;
07364          } else if (p->waitingfordt.tv_sec) {
07365             if (ast_tvdiff_ms(ast_tvnow(), p->waitingfordt) >= p->waitfordialtone ) {
07366                p->waitingfordt.tv_sec = 0;
07367                ast_log(LOG_WARNING, "Never saw dialtone on channel %d\n", p->channel);
07368                f=NULL;
07369             } else if (f->frametype == AST_FRAME_VOICE) {
07370                f->frametype = AST_FRAME_NULL;
07371                f->subclass = 0;
07372                if ((ast_dsp_get_tstate(p->dsp) == DSP_TONE_STATE_DIALTONE || ast_dsp_get_tstate(p->dsp) == DSP_TONE_STATE_RINGING) && ast_dsp_get_tcount(p->dsp) > 9) {
07373                   p->waitingfordt.tv_sec = 0;
07374                   p->dsp_features &= ~DSP_FEATURE_WAITDIALTONE;
07375                   ast_dsp_set_features(p->dsp, p->dsp_features);
07376                   ast_log(LOG_DEBUG, "Got 10 samples of dialtone!\n");
07377                   if (!ast_strlen_zero(p->dop.dialstr)) { /* Dial deferred digits */
07378                      res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
07379                      if (res < 0) {
07380                         ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d\n", p->channel);
07381                         p->dop.dialstr[0] = '\0';
07382                         ast_mutex_unlock(&p->lock);
07383                         return NULL;
07384                      } else {
07385                         ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", p->dop.dialstr);
07386                         p->dialing = 1;
07387                         p->dop.dialstr[0] = '\0';
07388                         p->dop.op = DAHDI_DIAL_OP_REPLACE;
07389                         ast_setstate(ast, AST_STATE_DIALING);
07390                      }
07391                   }
07392                }
07393             }
07394          }
07395       }
07396    } else
07397       f = &p->subs[idx].f;
07398 
07399    if (f) {
07400       switch (f->frametype) {
07401       case AST_FRAME_DTMF_BEGIN:
07402       case AST_FRAME_DTMF_END:
07403          dahdi_handle_dtmf(ast, idx, &f);
07404          break;
07405       case AST_FRAME_VOICE:
07406          if (p->cidspill || p->cid_suppress_expire) {
07407             /* We are/were sending a caller id spill.  Suppress any echo. */
07408             p->subs[idx].f.frametype = AST_FRAME_NULL;
07409             p->subs[idx].f.subclass = 0;
07410             p->subs[idx].f.samples = 0;
07411             p->subs[idx].f.mallocd = 0;
07412             p->subs[idx].f.offset = 0;
07413             p->subs[idx].f.data.ptr = NULL;
07414             p->subs[idx].f.datalen= 0;
07415          }
07416          break;
07417       default:
07418          break;
07419       }
07420    }
07421 
07422    /* If we have a fake_event, trigger exception to handle it */
07423    if (p->fake_event)
07424       ast_set_flag(ast, AST_FLAG_EXCEPTION);
07425 
07426    ast_mutex_unlock(&p->lock);
07427    return f;
07428 }
07429 
07430 static int my_dahdi_write(struct dahdi_pvt *p, unsigned char *buf, int len, int idx, int linear)
07431 {
07432    int sent=0;
07433    int size;
07434    int res;
07435    int fd;
07436    fd = p->subs[idx].dfd;
07437    while (len) {
07438       size = len;
07439       if (size > (linear ? READ_SIZE * 2 : READ_SIZE))
07440          size = (linear ? READ_SIZE * 2 : READ_SIZE);
07441       res = write(fd, buf, size);
07442       if (res != size) {
07443          ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
07444          return sent;
07445       }
07446       len -= size;
07447       buf += size;
07448    }
07449    return sent;
07450 }
07451 
07452 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame)
07453 {
07454    struct dahdi_pvt *p = ast->tech_pvt;
07455    int res;
07456    int idx;
07457    idx = dahdi_get_index(ast, p, 0);
07458    if (idx < 0) {
07459       ast_log(LOG_WARNING, "%s doesn't really exist?\n", ast->name);
07460       return -1;
07461    }
07462 
07463    /* Write a frame of (presumably voice) data */
07464    if (frame->frametype != AST_FRAME_VOICE) {
07465       if (frame->frametype != AST_FRAME_IMAGE)
07466          ast_log(LOG_WARNING, "Don't know what to do with frame type '%d'\n", frame->frametype);
07467       return 0;
07468    }
07469    if ((frame->subclass != AST_FORMAT_SLINEAR) &&
07470       (frame->subclass != AST_FORMAT_ULAW) &&
07471       (frame->subclass != AST_FORMAT_ALAW)) {
07472       ast_log(LOG_WARNING, "Cannot handle frames in %d format\n", frame->subclass);
07473       return -1;
07474    }
07475    if (p->dialing) {
07476       ast_debug(1, "Dropping frame since I'm still dialing on %s...\n",ast->name);
07477       return 0;
07478    }
07479    if (!p->owner) {
07480       ast_debug(1, "Dropping frame since there is no active owner on %s...\n",ast->name);
07481       return 0;
07482    }
07483    if (p->cidspill) {
07484       ast_debug(1, "Dropping frame since I've still got a callerid spill on %s...\n",
07485          ast->name);
07486       return 0;
07487    }
07488    /* Return if it's not valid data */
07489    if (!frame->data.ptr || !frame->datalen)
07490       return 0;
07491 
07492    if (frame->subclass == AST_FORMAT_SLINEAR) {
07493       if (!p->subs[idx].linear) {
07494          p->subs[idx].linear = 1;
07495          res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
07496          if (res)
07497             ast_log(LOG_WARNING, "Unable to set linear mode on channel %d\n", p->channel);
07498       }
07499       res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 1);
07500    } else {
07501       /* x-law already */
07502       if (p->subs[idx].linear) {
07503          p->subs[idx].linear = 0;
07504          res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
07505          if (res)
07506             ast_log(LOG_WARNING, "Unable to set companded mode on channel %d\n", p->channel);
07507       }
07508       res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 0);
07509    }
07510    if (res < 0) {
07511       ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
07512       return -1;
07513    }
07514    return 0;
07515 }
07516 
07517 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen)
07518 {
07519    struct dahdi_pvt *p = chan->tech_pvt;
07520    int res=-1;
07521    int idx;
07522    int func = DAHDI_FLASH;
07523    ast_mutex_lock(&p->lock);
07524    idx = dahdi_get_index(chan, p, 0);
07525    ast_debug(1, "Requested indication %d on channel %s\n", condition, chan->name);
07526 #ifdef HAVE_OPENR2
07527    if (p->mfcr2 && !p->mfcr2_call_accepted) {
07528       ast_mutex_unlock(&p->lock);
07529       /* if this is an R2 call and the call is not yet accepted, we don't want the
07530          tone indications to mess up with the MF tones */
07531       return 0;
07532    }
07533 #endif
07534    if (idx == SUB_REAL) {
07535       switch (condition) {
07536       case AST_CONTROL_BUSY:
07537 #ifdef HAVE_PRI
07538          if ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) {
07539             if (p->priindication_oob) {
07540                chan->hangupcause = AST_CAUSE_USER_BUSY;
07541                chan->_softhangup |= AST_SOFTHANGUP_DEV;
07542                res = 0;
07543                break;
07544             }
07545             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_BUSY);
07546             if (p->call_level < DAHDI_CALL_LEVEL_ALERTING && !p->outgoing) {
07547                chan->hangupcause = AST_CAUSE_USER_BUSY;
07548                p->progress = 1;/* No need to send plain PROGRESS after this. */
07549                if (p->pri && p->pri->pri) {
07550                   if (!pri_grab(p, p->pri)) {
07551 #ifdef HAVE_PRI_PROG_W_CAUSE
07552                      pri_progress_with_cause(p->pri->pri, p->call, PVT_TO_CHANNEL(p), 1, chan->hangupcause);
07553 #else
07554                      pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
07555 #endif
07556                      pri_rel(p->pri);
07557                   } else {
07558                      ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
07559                   }
07560                }
07561             }
07562             break;
07563          }
07564 #endif
07565          res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_BUSY);
07566          break;
07567       case AST_CONTROL_RINGING:
07568 #ifdef HAVE_PRI
07569          if (((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))
07570             && p->call_level < DAHDI_CALL_LEVEL_ALERTING && !p->outgoing) {
07571             p->call_level = DAHDI_CALL_LEVEL_ALERTING;
07572             if (p->pri && p->pri->pri) {
07573                if (!pri_grab(p, p->pri)) {
07574                   pri_acknowledge(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
07575                   pri_rel(p->pri);
07576                } else {
07577                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
07578                }
07579             }
07580          }
07581 #endif
07582 #ifdef HAVE_SS7
07583          if (p->sig == SIG_SS7
07584             && p->call_level < DAHDI_CALL_LEVEL_ALERTING && !p->outgoing) {
07585             p->call_level = DAHDI_CALL_LEVEL_ALERTING;
07586             if (p->ss7 && p->ss7->ss7) {
07587                ss7_grab(p, p->ss7);
07588                if ((isup_far(p->ss7->ss7, p->ss7call)) != -1)
07589                   p->rlt = 1;
07590                if (p->rlt != 1) /* No need to send CPG if call will be RELEASE */
07591                   isup_cpg(p->ss7->ss7, p->ss7call, CPG_EVENT_ALERTING);
07592                ss7_rel(p->ss7);
07593             }
07594          }
07595 #endif
07596 
07597          res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_RINGTONE);
07598 
07599          if (chan->_state != AST_STATE_UP) {
07600             if ((chan->_state != AST_STATE_RING) ||
07601                ((p->sig != SIG_FXSKS) &&
07602              (p->sig != SIG_FXSLS) &&
07603              (p->sig != SIG_FXSGS)))
07604             ast_setstate(chan, AST_STATE_RINGING);
07605          }
07606          break;
07607       case AST_CONTROL_PROCEEDING:
07608          ast_debug(1,"Received AST_CONTROL_PROCEEDING on %s\n",chan->name);
07609 #ifdef HAVE_PRI
07610          if (((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))
07611             && p->call_level < DAHDI_CALL_LEVEL_PROCEEDING && !p->outgoing) {
07612             p->call_level = DAHDI_CALL_LEVEL_PROCEEDING;
07613             if (p->pri && p->pri->pri) {
07614                if (!pri_grab(p, p->pri)) {
07615                   pri_proceeding(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
07616                   pri_rel(p->pri);
07617                } else {
07618                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
07619                }
07620             }
07621             p->dialing = 0;
07622          }
07623 #endif
07624 #ifdef HAVE_SS7
07625          if (p->sig == SIG_SS7) {
07626             /* This IF sends the FAR for an answered ALEG call */
07627             if (chan->_state == AST_STATE_UP && (p->rlt != 1)){
07628                if ((isup_far(p->ss7->ss7, p->ss7call)) != -1)
07629                   p->rlt = 1;
07630             }
07631 
07632             if (p->call_level < DAHDI_CALL_LEVEL_PROCEEDING && !p->outgoing) {
07633                p->call_level = DAHDI_CALL_LEVEL_PROCEEDING;
07634                if (p->ss7 && p->ss7->ss7) {
07635                   ss7_grab(p, p->ss7);
07636                   isup_acm(p->ss7->ss7, p->ss7call);
07637                   ss7_rel(p->ss7);
07638                }
07639             }
07640          }
07641 #endif
07642          /* don't continue in ast_indicate */
07643          res = 0;
07644          break;
07645       case AST_CONTROL_PROGRESS:
07646          ast_debug(1,"Received AST_CONTROL_PROGRESS on %s\n",chan->name);
07647 #ifdef HAVE_PRI
07648          p->digital = 0;   /* Digital-only calls isn't allows any inband progress messages */
07649          if (((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))
07650             && !p->progress && p->call_level < DAHDI_CALL_LEVEL_ALERTING
07651             && !p->outgoing) {
07652             p->progress = 1;/* No need to send plain PROGRESS again. */
07653             if (p->pri && p->pri->pri) {
07654                if (!pri_grab(p, p->pri)) {
07655 #ifdef HAVE_PRI_PROG_W_CAUSE
07656                   pri_progress_with_cause(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1, -1);  /* no cause at all */
07657 #else
07658                   pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
07659 #endif
07660                   pri_rel(p->pri);
07661                } else {
07662                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
07663                }
07664             }
07665          }
07666 #endif
07667 #ifdef HAVE_SS7
07668          if (p->sig == SIG_SS7
07669             && !p->progress && p->call_level < DAHDI_CALL_LEVEL_ALERTING
07670             && !p->outgoing) {
07671             p->progress = 1;/* No need to send inband-information progress again. */
07672             if (p->ss7 && p->ss7->ss7) {
07673                ss7_grab(p, p->ss7);
07674                isup_cpg(p->ss7->ss7, p->ss7call, CPG_EVENT_INBANDINFO);
07675                ss7_rel(p->ss7);
07676                /* enable echo canceler here on SS7 calls */
07677                dahdi_enable_ec(p);
07678             }
07679          }
07680 #endif
07681          /* don't continue in ast_indicate */
07682          res = 0;
07683          break;
07684       case AST_CONTROL_CONGESTION:
07685 #ifdef HAVE_PRI
07686          if ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) {
07687             if (p->priindication_oob) {
07688                /* There are many cause codes that generate an AST_CONTROL_CONGESTION. */
07689                switch (chan->hangupcause) {
07690                case AST_CAUSE_USER_BUSY:
07691                case AST_CAUSE_NORMAL_CLEARING:
07692                case 0:/* Cause has not been set. */
07693                   /* Supply a more appropriate cause. */
07694                   chan->hangupcause = AST_CAUSE_SWITCH_CONGESTION;
07695                   break;
07696                default:
07697                   break;
07698                }
07699                chan->_softhangup |= AST_SOFTHANGUP_DEV;
07700                res = 0;
07701                break;
07702             }
07703             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
07704             if (p->call_level < DAHDI_CALL_LEVEL_ALERTING && !p->outgoing) {
07705                /* There are many cause codes that generate an AST_CONTROL_CONGESTION. */
07706                switch (chan->hangupcause) {
07707                case AST_CAUSE_USER_BUSY:
07708                case AST_CAUSE_NORMAL_CLEARING:
07709                case 0:/* Cause has not been set. */
07710                   /* Supply a more appropriate cause. */
07711                   chan->hangupcause = AST_CAUSE_SWITCH_CONGESTION;
07712                   break;
07713                default:
07714                   break;
07715                }
07716                p->progress = 1;/* No need to send plain PROGRESS after this. */
07717                if (p->pri && p->pri->pri) {
07718                   if (!pri_grab(p, p->pri)) {
07719 #ifdef HAVE_PRI_PROG_W_CAUSE
07720                      pri_progress_with_cause(p->pri->pri, p->call, PVT_TO_CHANNEL(p), 1, chan->hangupcause);
07721 #else
07722                      pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
07723 #endif
07724                      pri_rel(p->pri);
07725                   } else {
07726                      ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
07727                   }
07728                }
07729             }
07730             break;
07731          }
07732 #endif
07733          /* There are many cause codes that generate an AST_CONTROL_CONGESTION. */
07734          switch (chan->hangupcause) {
07735          case AST_CAUSE_USER_BUSY:
07736          case AST_CAUSE_NORMAL_CLEARING:
07737          case 0:/* Cause has not been set. */
07738             /* Supply a more appropriate cause. */
07739             chan->hangupcause = AST_CAUSE_CONGESTION;
07740             break;
07741          default:
07742             break;
07743          }
07744          res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
07745          break;
07746       case AST_CONTROL_HOLD:
07747 #ifdef HAVE_PRI
07748          if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) {
07749             if (!pri_grab(p, p->pri)) {
07750                res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_HOLD);
07751                pri_rel(p->pri);
07752             } else
07753                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
07754          } else
07755 #endif
07756             ast_moh_start(chan, data, p->mohinterpret);
07757          break;
07758       case AST_CONTROL_UNHOLD:
07759 #ifdef HAVE_PRI
07760          if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) {
07761             if (!pri_grab(p, p->pri)) {
07762                res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_RETRIEVAL);
07763                pri_rel(p->pri);
07764             } else
07765                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
07766          } else
07767 #endif
07768             ast_moh_stop(chan);
07769          break;
07770       case AST_CONTROL_RADIO_KEY:
07771          if (p->radio)
07772             res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
07773          res = 0;
07774          break;
07775       case AST_CONTROL_RADIO_UNKEY:
07776          if (p->radio)
07777             res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_RINGOFF);
07778          res = 0;
07779          break;
07780       case AST_CONTROL_FLASH:
07781          /* flash hookswitch */
07782          if (ISTRUNK(p) && (p->sig != SIG_PRI)) {
07783             /* Clear out the dial buffer */
07784             p->dop.dialstr[0] = '\0';
07785             if ((ioctl(p->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
07786                ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
07787                   chan->name, strerror(errno));
07788             } else
07789                res = 0;
07790          } else
07791             res = 0;
07792          break;
07793       case AST_CONTROL_SRCUPDATE:
07794          res = 0;
07795          break;
07796       case -1:
07797          res = tone_zone_play_tone(p->subs[idx].dfd, -1);
07798          break;
07799       }
07800    } else
07801       res = 0;
07802    ast_mutex_unlock(&p->lock);
07803    return res;
07804 }
07805 
07806 static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpbx, int idx, int law, int transfercapability)
07807 {
07808    struct ast_channel *tmp;
07809    int deflaw;
07810    int res;
07811    int x,y;
07812    int features;
07813    struct ast_str *chan_name;
07814    struct ast_variable *v;
07815    struct dahdi_params ps;
07816    if (i->subs[idx].owner) {
07817       ast_log(LOG_WARNING, "Channel %d already has a %s call\n", i->channel,subnames[idx]);
07818       return NULL;
07819    }
07820    y = 1;
07821    chan_name = ast_str_alloca(32);
07822    do {
07823 #ifdef HAVE_PRI
07824       if (i->bearer || (i->pri && (i->sig == SIG_FXSKS)))
07825          ast_str_set(&chan_name, 0, "%d:%d-%d", i->pri->trunkgroup, i->channel, y);
07826       else
07827 #endif
07828       if (i->channel == CHAN_PSEUDO)
07829          ast_str_set(&chan_name, 0, "pseudo-%ld", ast_random());
07830       else
07831          ast_str_set(&chan_name, 0, "%d-%d", i->channel, y);
07832       for (x = 0; x < 3; x++) {
07833          if ((idx != x) && i->subs[x].owner && !strcasecmp(ast_str_buffer(chan_name), i->subs[x].owner->name + 6))
07834             break;
07835       }
07836       y++;
07837    } while (x < 3);
07838    tmp = ast_channel_alloc(0, state, i->cid_num, i->cid_name, i->accountcode, i->exten, i->context, i->amaflags, "DAHDI/%s", ast_str_buffer(chan_name));
07839    if (!tmp)
07840       return NULL;
07841    tmp->tech = &dahdi_tech;
07842    memset(&ps, 0, sizeof(ps));
07843    ps.channo = i->channel;
07844    res = ioctl(i->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps);
07845    if (res) {
07846       ast_log(LOG_WARNING, "Unable to get parameters, assuming MULAW: %s\n", strerror(errno));
07847       ps.curlaw = DAHDI_LAW_MULAW;
07848    }
07849    if (ps.curlaw == DAHDI_LAW_ALAW)
07850       deflaw = AST_FORMAT_ALAW;
07851    else
07852       deflaw = AST_FORMAT_ULAW;
07853    if (law) {
07854       if (law == DAHDI_LAW_ALAW)
07855          deflaw = AST_FORMAT_ALAW;
07856       else
07857          deflaw = AST_FORMAT_ULAW;
07858    }
07859    ast_channel_set_fd(tmp, 0, i->subs[idx].dfd);
07860    tmp->nativeformats = deflaw;
07861    /* Start out assuming ulaw since it's smaller :) */
07862    tmp->rawreadformat = deflaw;
07863    tmp->readformat = deflaw;
07864    tmp->rawwriteformat = deflaw;
07865    tmp->writeformat = deflaw;
07866    i->subs[idx].linear = 0;
07867    dahdi_setlinear(i->subs[idx].dfd, i->subs[idx].linear);
07868    features = 0;
07869    if (idx == SUB_REAL) {
07870       if (i->busydetect && CANBUSYDETECT(i))
07871          features |= DSP_FEATURE_BUSY_DETECT;
07872       if ((i->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(i))
07873          features |= DSP_FEATURE_CALL_PROGRESS;
07874       if ((i->waitfordialtone) && CANPROGRESSDETECT(i))
07875          features |= DSP_FEATURE_WAITDIALTONE;
07876       if ((!i->outgoing && (i->callprogress & CALLPROGRESS_FAX_INCOMING)) ||
07877          (i->outgoing && (i->callprogress & CALLPROGRESS_FAX_OUTGOING))) {
07878          features |= DSP_FEATURE_FAX_DETECT;
07879       }
07880       x = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
07881       if (ioctl(i->subs[idx].dfd, DAHDI_TONEDETECT, &x)) {
07882          i->hardwaredtmf = 0;
07883          features |= DSP_FEATURE_DIGIT_DETECT;
07884       } else if (NEED_MFDETECT(i)) {
07885          i->hardwaredtmf = 1;
07886          features |= DSP_FEATURE_DIGIT_DETECT;
07887       }
07888    }
07889    if (features) {
07890       if (i->dsp) {
07891          ast_debug(1, "Already have a dsp on %s?\n", tmp->name);
07892       } else {
07893          if (i->channel != CHAN_PSEUDO)
07894             i->dsp = ast_dsp_new();
07895          else
07896             i->dsp = NULL;
07897          if (i->dsp) {
07898             i->dsp_features = features;
07899 #if defined(HAVE_PRI) || defined(HAVE_SS7)
07900             /* We cannot do progress detection until receives PROGRESS message */
07901             if (i->outgoing && ((i->sig == SIG_PRI) || (i->sig == SIG_BRI) || (i->sig == SIG_BRI_PTMP) || (i->sig == SIG_SS7))) {
07902                /* Remember requested DSP features, don't treat
07903                   talking as ANSWER */
07904                i->dsp_features = features & ~DSP_PROGRESS_TALK;
07905                features = 0;
07906             }
07907 #endif
07908             ast_dsp_set_features(i->dsp, features);
07909             ast_dsp_set_digitmode(i->dsp, DSP_DIGITMODE_DTMF | i->dtmfrelax);
07910             if (!ast_strlen_zero(progzone))
07911                ast_dsp_set_call_progress_zone(i->dsp, progzone);
07912             if (i->busydetect && CANBUSYDETECT(i)) {
07913                ast_dsp_set_busy_count(i->dsp, i->busycount);
07914                ast_dsp_set_busy_pattern(i->dsp, i->busy_tonelength, i->busy_quietlength);
07915             }
07916          }
07917       }
07918    }
07919 
07920    if (state == AST_STATE_RING)
07921       tmp->rings = 1;
07922    tmp->tech_pvt = i;
07923    if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) {
07924       /* Only FXO signalled stuff can be picked up */
07925       tmp->callgroup = i->callgroup;
07926       tmp->pickupgroup = i->pickupgroup;
07927    }
07928    if (!ast_strlen_zero(i->parkinglot))
07929       ast_string_field_set(tmp, parkinglot, i->parkinglot);
07930    if (!ast_strlen_zero(i->language))
07931       ast_string_field_set(tmp, language, i->language);
07932    if (!i->owner)
07933       i->owner = tmp;
07934    if (!ast_strlen_zero(i->accountcode))
07935       ast_string_field_set(tmp, accountcode, i->accountcode);
07936    if (i->amaflags)
07937       tmp->amaflags = i->amaflags;
07938    i->subs[idx].owner = tmp;
07939    ast_copy_string(tmp->context, i->context, sizeof(tmp->context));
07940    ast_string_field_set(tmp, call_forward, i->call_forward);
07941    /* If we've been told "no ADSI" then enforce it */
07942    if (!i->adsi)
07943       tmp->adsicpe = AST_ADSI_UNAVAILABLE;
07944    if (!ast_strlen_zero(i->exten))
07945       ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten));
07946    if (!ast_strlen_zero(i->rdnis))
07947       tmp->cid.cid_rdnis = ast_strdup(i->rdnis);
07948    if (!ast_strlen_zero(i->dnid))
07949       tmp->cid.cid_dnid = ast_strdup(i->dnid);
07950 
07951    /* Don't use ast_set_callerid() here because it will
07952     * generate a needless NewCallerID event */
07953 #ifdef PRI_ANI
07954    if (!ast_strlen_zero(i->cid_ani))
07955       tmp->cid.cid_ani = ast_strdup(i->cid_ani);
07956    else
07957       tmp->cid.cid_ani = ast_strdup(i->cid_num);
07958 #else
07959    tmp->cid.cid_ani = ast_strdup(i->cid_num);
07960 #endif
07961    tmp->cid.cid_pres = i->callingpres;
07962    tmp->cid.cid_ton = i->cid_ton;
07963    tmp->cid.cid_ani2 = i->cid_ani2;
07964 #if defined(HAVE_PRI) || defined(HAVE_SS7)
07965    tmp->transfercapability = transfercapability;
07966    pbx_builtin_setvar_helper(tmp, "TRANSFERCAPABILITY", ast_transfercapability2str(transfercapability));
07967    if (transfercapability & AST_TRANS_CAP_DIGITAL)
07968       i->digital = 1;
07969    /* Assume calls are not idle calls unless we're told differently */
07970    i->isidlecall = 0;
07971    i->alreadyhungup = 0;
07972 #endif
07973    /* clear the fake event in case we posted one before we had ast_channel */
07974    i->fake_event = 0;
07975    /* Assure there is no confmute on this channel */
07976    dahdi_confmute(i, 0);
07977    i->muting = 0;
07978    /* Configure the new channel jb */
07979    ast_jb_configure(tmp, &global_jbconf);
07980 
07981    ast_devstate_changed_literal(ast_state_chan2dev(state), tmp->name);
07982 
07983    for (v = i->vars ; v ; v = v->next)
07984       pbx_builtin_setvar_helper(tmp, v->name, v->value);
07985 
07986    if (startpbx) {
07987 #ifdef HAVE_OPENR2
07988       if (i->mfcr2call) {
07989          pbx_builtin_setvar_helper(tmp, "MFCR2_CATEGORY", openr2_proto_get_category_string(i->mfcr2_recvd_category));
07990       }
07991 #endif
07992       if (ast_pbx_start(tmp)) {
07993          ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
07994          ast_hangup(tmp);
07995          i->owner = NULL;
07996          return NULL;
07997       }
07998    }
07999 
08000    ast_module_ref(ast_module_info->self);
08001    return tmp;
08002 }
08003 
08004 
08005 static int my_getsigstr(struct ast_channel *chan, char *str, const char *term, int ms)
08006 {
08007    char c;
08008 
08009    *str = 0; /* start with empty output buffer */
08010    for (;;)
08011    {
08012       /* Wait for the first digit (up to specified ms). */
08013       c = ast_waitfordigit(chan, ms);
08014       /* if timeout, hangup or error, return as such */
08015       if (c < 1)
08016          return c;
08017       *str++ = c;
08018       *str = 0;
08019       if (strchr(term, c))
08020          return 1;
08021    }
08022 }
08023 
08024 static int dahdi_wink(struct dahdi_pvt *p, int idx)
08025 {
08026    int j;
08027    dahdi_set_hook(p->subs[idx].dfd, DAHDI_WINK);
08028    for (;;)
08029    {
08030       /* set bits of interest */
08031       j = DAHDI_IOMUX_SIGEVENT;
08032       /* wait for some happening */
08033       if (ioctl(p->subs[idx].dfd,DAHDI_IOMUX,&j) == -1) return(-1);
08034       /* exit loop if we have it */
08035       if (j & DAHDI_IOMUX_SIGEVENT) break;
08036    }
08037    /* get the event info */
08038    if (ioctl(p->subs[idx].dfd,DAHDI_GETEVENT,&j) == -1) return(-1);
08039    return 0;
08040 }
08041 
08042 /*! \brief enable or disable the chan_dahdi Do-Not-Disturb mode for a DAHDI channel
08043  * \param dahdichan "Physical" DAHDI channel (e.g: DAHDI/5)
08044  * \param on 1 to enable, 0 to disable
08045  *
08046  * chan_dahdi has a DND (Do Not Disturb) mode for each dahdichan (physical
08047  * DAHDI channel). Use this to enable or disable it.
08048  *
08049  * \bug the use of the word "channel" for those dahdichans is really confusing.
08050  */
08051 static void dahdi_dnd(struct dahdi_pvt *dahdichan, int on)
08052 {
08053    /* Do not disturb */
08054    dahdichan->dnd = on;
08055    ast_verb(3, "%s DND on channel %d\n",
08056          on? "Enabled" : "Disabled",
08057          dahdichan->channel);
08058    manager_event(EVENT_FLAG_SYSTEM, "DNDState",
08059          "Channel: DAHDI/%d\r\n"
08060          "Status: %s\r\n", dahdichan->channel,
08061          on? "enabled" : "disabled");
08062 }
08063 
08064 static void *ss_thread(void *data)
08065 {
08066    struct ast_channel *chan = data;
08067    struct dahdi_pvt *p = chan->tech_pvt;
08068    char exten[AST_MAX_EXTENSION] = "";
08069    char exten2[AST_MAX_EXTENSION] = "";
08070    unsigned char buf[256];
08071    char dtmfcid[300];
08072    char dtmfbuf[300];
08073    struct callerid_state *cs = NULL;
08074    char *name = NULL, *number = NULL;
08075    int distMatches;
08076    int curRingData[3];
08077    int receivedRingT;
08078    int counter1;
08079    int counter;
08080    int samples = 0;
08081    struct ast_smdi_md_message *smdi_msg = NULL;
08082    int flags = 0;
08083    int i;
08084    int timeout;
08085    int getforward = 0;
08086    char *s1, *s2;
08087    int len = 0;
08088    int res;
08089    int idx;
08090 
08091    ast_mutex_lock(&ss_thread_lock);
08092    ss_thread_count++;
08093    ast_mutex_unlock(&ss_thread_lock);
08094    /* in the bizarre case where the channel has become a zombie before we
08095       even get started here, abort safely
08096    */
08097    if (!p) {
08098       ast_log(LOG_WARNING, "Channel became a zombie before simple switch could be started (%s)\n", chan->name);
08099       ast_hangup(chan);
08100       goto quit;
08101    }
08102    ast_verb(3, "Starting simple switch on '%s'\n", chan->name);
08103    idx = dahdi_get_index(chan, p, 0);
08104    if (idx < 0) {
08105       ast_hangup(chan);
08106       goto quit;
08107    }
08108    if (p->dsp)
08109       ast_dsp_digitreset(p->dsp);
08110    switch (p->sig) {
08111 #ifdef HAVE_PRI
08112    case SIG_PRI:
08113    case SIG_BRI:
08114    case SIG_BRI_PTMP:
08115       /* Now loop looking for an extension */
08116       ast_copy_string(exten, p->exten, sizeof(exten));
08117       len = strlen(exten);
08118       res = 0;
08119       while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
08120          if (len && !ast_ignore_pattern(chan->context, exten))
08121             tone_zone_play_tone(p->subs[idx].dfd, -1);
08122          else
08123             tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
08124          if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num))
08125             timeout = matchdigittimeout;
08126          else
08127             timeout = gendigittimeout;
08128          res = ast_waitfordigit(chan, timeout);
08129          if (res < 0) {
08130             ast_debug(1, "waitfordigit returned < 0...\n");
08131             ast_hangup(chan);
08132             goto quit;
08133          } else if (res) {
08134             exten[len++] = res;
08135             exten[len] = '\0';
08136          } else
08137             break;
08138       }
08139       /* if no extension was received ('unspecified') on overlap call, use the 's' extension */
08140       if (ast_strlen_zero(exten)) {
08141          ast_verb(3, "Going to extension s|1 because of empty extension received on overlap call\n");
08142          exten[0] = 's';
08143          exten[1] = '\0';
08144       }
08145       tone_zone_play_tone(p->subs[idx].dfd, -1);
08146       if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num)) {
08147          /* Start the real PBX */
08148          ast_copy_string(chan->exten, exten, sizeof(chan->exten));
08149          if (p->dsp) {
08150             ast_dsp_digitreset(p->dsp);
08151          }
08152 #if defined(ISSUE_16789)
08153          /*
08154           * Conditionaled out this code to effectively revert the Mantis
08155           * issue 16789 change.  It breaks overlap dialing through
08156           * Asterisk.  There is not enough information available at this
08157           * point to know if dialing is complete.  The
08158           * ast_exists_extension(), ast_matchmore_extension(), and
08159           * ast_canmatch_extension() calls are not adequate to detect a
08160           * dial through extension pattern of "_9!".
08161           *
08162           * Workaround is to use the dialplan Proceeding() application
08163           * early on non-dial through extensions.
08164           */
08165          if ((p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)
08166             && !ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
08167             ast_mutex_lock(&p->lock);
08168             if (p->pri->pri) {
08169                if (!pri_grab(p, p->pri)) {
08170                   if (p->call_level < DAHDI_CALL_LEVEL_PROCEEDING) {
08171                      p->call_level = DAHDI_CALL_LEVEL_PROCEEDING;
08172                   }
08173                   pri_proceeding(p->pri->pri, p->call, PVT_TO_CHANNEL(p), 0);
08174                   pri_rel(p->pri);
08175                } else {
08176                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
08177                }
08178             }
08179             ast_mutex_unlock(&p->lock);
08180          }
08181 #endif   /* defined(ISSUE_16789) */
08182 
08183          dahdi_enable_ec(p);
08184          ast_setstate(chan, AST_STATE_RING);
08185          res = ast_pbx_run(chan);
08186          if (res) {
08187             ast_log(LOG_WARNING, "PBX exited non-zero!\n");
08188          }
08189       } else {
08190          ast_debug(1, "No such possible extension '%s' in context '%s'\n", exten, chan->context);
08191          chan->hangupcause = AST_CAUSE_UNALLOCATED;
08192          ast_hangup(chan);
08193          p->exten[0] = '\0';
08194          /* Since we send release complete here, we won't get one */
08195          p->call = NULL;
08196       }
08197       goto quit;
08198       break;
08199 #endif
08200    case SIG_FEATD:
08201    case SIG_FEATDMF:
08202    case SIG_FEATDMF_TA:
08203    case SIG_E911:
08204    case SIG_FGC_CAMAMF:
08205    case SIG_FEATB:
08206    case SIG_EMWINK:
08207    case SIG_SF_FEATD:
08208    case SIG_SF_FEATDMF:
08209    case SIG_SF_FEATB:
08210    case SIG_SFWINK:
08211       if (dahdi_wink(p, idx))
08212          goto quit;
08213       /* Fall through */
08214    case SIG_EM:
08215    case SIG_EM_E1:
08216    case SIG_SF:
08217    case SIG_FGC_CAMA:
08218       res = tone_zone_play_tone(p->subs[idx].dfd, -1);
08219       if (p->dsp)
08220          ast_dsp_digitreset(p->dsp);
08221       /* set digit mode appropriately */
08222       if (p->dsp) {
08223          if (NEED_MFDETECT(p))
08224             ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
08225          else
08226             ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
08227       }
08228       memset(dtmfbuf, 0, sizeof(dtmfbuf));
08229       /* Wait for the first digit only if immediate=no */
08230       if (!p->immediate)
08231          /* Wait for the first digit (up to 5 seconds). */
08232          res = ast_waitfordigit(chan, 5000);
08233       else
08234          res = 0;
08235       if (res > 0) {
08236          /* save first char */
08237          dtmfbuf[0] = res;
08238          switch (p->sig) {
08239          case SIG_FEATD:
08240          case SIG_SF_FEATD:
08241             res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
08242             if (res > 0)
08243                res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
08244             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
08245             break;
08246          case SIG_FEATDMF_TA:
08247             res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
08248             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
08249             if (dahdi_wink(p, idx)) goto quit;
08250             dtmfbuf[0] = 0;
08251             /* Wait for the first digit (up to 5 seconds). */
08252             res = ast_waitfordigit(chan, 5000);
08253             if (res <= 0) break;
08254             dtmfbuf[0] = res;
08255             /* fall through intentionally */
08256          case SIG_FEATDMF:
08257          case SIG_E911:
08258          case SIG_FGC_CAMAMF:
08259          case SIG_SF_FEATDMF:
08260             res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
08261             /* if international caca, do it again to get real ANO */
08262             if ((p->sig == SIG_FEATDMF) && (dtmfbuf[1] != '0') && (strlen(dtmfbuf) != 14))
08263             {
08264                if (dahdi_wink(p, idx)) goto quit;
08265                dtmfbuf[0] = 0;
08266                /* Wait for the first digit (up to 5 seconds). */
08267                res = ast_waitfordigit(chan, 5000);
08268                if (res <= 0) break;
08269                dtmfbuf[0] = res;
08270                res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
08271             }
08272             if (res > 0) {
08273                /* if E911, take off hook */
08274                if (p->sig == SIG_E911)
08275                   dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
08276                res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "#", 3000);
08277             }
08278             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
08279             break;
08280          case SIG_FEATB:
08281          case SIG_SF_FEATB:
08282             res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
08283             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
08284             break;
08285          case SIG_EMWINK:
08286             /* if we received a '*', we are actually receiving Feature Group D
08287                dial syntax, so use that mode; otherwise, fall through to normal
08288                mode
08289             */
08290             if (res == '*') {
08291                res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
08292                if (res > 0)
08293                   res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
08294                if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
08295                break;
08296             }
08297          default:
08298             /* If we got the first digit, get the rest */
08299             len = 1;
08300             dtmfbuf[len] = '\0';
08301             while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
08302                if (ast_exists_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
08303                   timeout = matchdigittimeout;
08304                } else {
08305                   timeout = gendigittimeout;
08306                }
08307                res = ast_waitfordigit(chan, timeout);
08308                if (res < 0) {
08309                   ast_debug(1, "waitfordigit returned < 0...\n");
08310                   ast_hangup(chan);
08311                   goto quit;
08312                } else if (res) {
08313                   dtmfbuf[len++] = res;
08314                   dtmfbuf[len] = '\0';
08315                } else {
08316                   break;
08317                }
08318             }
08319             break;
08320          }
08321       }
08322       if (res == -1) {
08323          ast_log(LOG_WARNING, "getdtmf on channel %d: %s\n", p->channel, strerror(errno));
08324          ast_hangup(chan);
08325          goto quit;
08326       } else if (res < 0) {
08327          ast_debug(1, "Got hung up before digits finished\n");
08328          ast_hangup(chan);
08329          goto quit;
08330       }
08331 
08332       if (p->sig == SIG_FGC_CAMA) {
08333          char anibuf[100];
08334 
08335          if (ast_safe_sleep(chan,1000) == -1) {
08336             ast_hangup(chan);
08337             goto quit;
08338          }
08339          dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
08340          ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
08341          res = my_getsigstr(chan, anibuf, "#", 10000);
08342          if ((res > 0) && (strlen(anibuf) > 2)) {
08343             if (anibuf[strlen(anibuf) - 1] == '#')
08344                anibuf[strlen(anibuf) - 1] = 0;
08345             ast_set_callerid(chan, anibuf + 2, NULL, anibuf + 2);
08346          }
08347          ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
08348       }
08349 
08350       ast_copy_string(exten, dtmfbuf, sizeof(exten));
08351       if (ast_strlen_zero(exten))
08352          ast_copy_string(exten, "s", sizeof(exten));
08353       if (p->sig == SIG_FEATD || p->sig == SIG_EMWINK) {
08354          /* Look for Feature Group D on all E&M Wink and Feature Group D trunks */
08355          if (exten[0] == '*') {
08356             char *stringp=NULL;
08357             ast_copy_string(exten2, exten, sizeof(exten2));
08358             /* Parse out extension and callerid */
08359             stringp=exten2 +1;
08360             s1 = strsep(&stringp, "*");
08361             s2 = strsep(&stringp, "*");
08362             if (s2) {
08363                if (!ast_strlen_zero(p->cid_num))
08364                   ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
08365                else
08366                   ast_set_callerid(chan, s1, NULL, s1);
08367                ast_copy_string(exten, s2, sizeof(exten));
08368             } else
08369                ast_copy_string(exten, s1, sizeof(exten));
08370          } else if (p->sig == SIG_FEATD)
08371             ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d.  Assuming E&M Wink instead\n", p->channel);
08372       }
08373       if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
08374          if (exten[0] == '*') {
08375             char *stringp=NULL;
08376             ast_copy_string(exten2, exten, sizeof(exten2));
08377             /* Parse out extension and callerid */
08378             stringp=exten2 +1;
08379             s1 = strsep(&stringp, "#");
08380             s2 = strsep(&stringp, "#");
08381             if (s2) {
08382                if (!ast_strlen_zero(p->cid_num))
08383                   ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
08384                else
08385                   if (*(s1 + 2))
08386                      ast_set_callerid(chan, s1 + 2, NULL, s1 + 2);
08387                ast_copy_string(exten, s2 + 1, sizeof(exten));
08388             } else
08389                ast_copy_string(exten, s1 + 2, sizeof(exten));
08390          } else
08391             ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d.  Assuming E&M Wink instead\n", p->channel);
08392       }
08393       if ((p->sig == SIG_E911) || (p->sig == SIG_FGC_CAMAMF)) {
08394          if (exten[0] == '*') {
08395             char *stringp=NULL;
08396             ast_copy_string(exten2, exten, sizeof(exten2));
08397             /* Parse out extension and callerid */
08398             stringp=exten2 +1;
08399             s1 = strsep(&stringp, "#");
08400             s2 = strsep(&stringp, "#");
08401             if (s2 && (*(s2 + 1) == '0')) {
08402                if (*(s2 + 2))
08403                   ast_set_callerid(chan, s2 + 2, NULL, s2 + 2);
08404             }
08405             if (s1)  ast_copy_string(exten, s1, sizeof(exten));
08406             else ast_copy_string(exten, "911", sizeof(exten));
08407          } else
08408             ast_log(LOG_WARNING, "Got a non-E911/FGC CAMA input on channel %d.  Assuming E&M Wink instead\n", p->channel);
08409       }
08410       if (p->sig == SIG_FEATB) {
08411          if (exten[0] == '*') {
08412             char *stringp=NULL;
08413             ast_copy_string(exten2, exten, sizeof(exten2));
08414             /* Parse out extension and callerid */
08415             stringp=exten2 +1;
08416             s1 = strsep(&stringp, "#");
08417             ast_copy_string(exten, exten2 + 1, sizeof(exten));
08418          } else
08419             ast_log(LOG_WARNING, "Got a non-Feature Group B input on channel %d.  Assuming E&M Wink instead\n", p->channel);
08420       }
08421       if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
08422          dahdi_wink(p, idx);
08423          /* some switches require a minimum guard time between
08424             the last FGD wink and something that answers
08425             immediately. This ensures it */
08426          if (ast_safe_sleep(chan,100)) goto quit;
08427       }
08428       dahdi_enable_ec(p);
08429       if (NEED_MFDETECT(p)) {
08430          if (p->dsp) {
08431             if (!p->hardwaredtmf)
08432                ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
08433             else {
08434                ast_dsp_free(p->dsp);
08435                p->dsp = NULL;
08436             }
08437          }
08438       }
08439 
08440       if (ast_exists_extension(chan, chan->context, exten, 1, chan->cid.cid_num)) {
08441          ast_copy_string(chan->exten, exten, sizeof(chan->exten));
08442          if (p->dsp) ast_dsp_digitreset(p->dsp);
08443          res = ast_pbx_run(chan);
08444          if (res) {
08445             ast_log(LOG_WARNING, "PBX exited non-zero\n");
08446             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
08447          }
08448          goto quit;
08449       } else {
08450          ast_verb(2, "Unknown extension '%s' in context '%s' requested\n", exten, chan->context);
08451          sleep(2);
08452          res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_INFO);
08453          if (res < 0)
08454             ast_log(LOG_WARNING, "Unable to start special tone on %d\n", p->channel);
08455          else
08456             sleep(1);
08457          res = ast_streamfile(chan, "ss-noservice", chan->language);
08458          if (res >= 0)
08459             ast_waitstream(chan, "");
08460          res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
08461          ast_hangup(chan);
08462          goto quit;
08463       }
08464       break;
08465    case SIG_FXOLS:
08466    case SIG_FXOGS:
08467    case SIG_FXOKS:
08468       /* Read the first digit */
08469       timeout = firstdigittimeout;
08470       /* If starting a threeway call, never timeout on the first digit so someone
08471          can use flash-hook as a "hold" feature */
08472       if (p->subs[SUB_THREEWAY].owner)
08473          timeout = 999999;
08474       while (len < AST_MAX_EXTENSION-1) {
08475          /* Read digit unless it's supposed to be immediate, in which case the
08476             only answer is 's' */
08477          if (p->immediate)
08478             res = 's';
08479          else
08480             res = ast_waitfordigit(chan, timeout);
08481          timeout = 0;
08482          if (res < 0) {
08483             ast_debug(1, "waitfordigit returned < 0...\n");
08484             res = tone_zone_play_tone(p->subs[idx].dfd, -1);
08485             ast_hangup(chan);
08486             goto quit;
08487          } else if (res) {
08488             ast_debug(1,"waitfordigit returned '%c' (%d), timeout = %d\n", res, res, timeout);
08489             exten[len++]=res;
08490             exten[len] = '\0';
08491          }
08492          if (!ast_ignore_pattern(chan->context, exten))
08493             tone_zone_play_tone(p->subs[idx].dfd, -1);
08494          else
08495             tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
08496          if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num) && strcmp(exten, ast_parking_ext())) {
08497             if (!res || !ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
08498                if (getforward) {
08499                   /* Record this as the forwarding extension */
08500                   ast_copy_string(p->call_forward, exten, sizeof(p->call_forward));
08501                   ast_verb(3, "Setting call forward to '%s' on channel %d\n", p->call_forward, p->channel);
08502                   res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
08503                   if (res)
08504                      break;
08505                   usleep(500000);
08506                   res = tone_zone_play_tone(p->subs[idx].dfd, -1);
08507                   sleep(1);
08508                   memset(exten, 0, sizeof(exten));
08509                   res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
08510                   len = 0;
08511                   getforward = 0;
08512                } else {
08513                   res = tone_zone_play_tone(p->subs[idx].dfd, -1);
08514                   ast_copy_string(chan->exten, exten, sizeof(chan->exten));
08515                   if (!ast_strlen_zero(p->cid_num)) {
08516                      if (!p->hidecallerid)
08517                         ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
08518                      else
08519                         ast_set_callerid(chan, NULL, NULL, p->cid_num);
08520                   }
08521                   if (!ast_strlen_zero(p->cid_name)) {
08522                      if (!p->hidecallerid)
08523                         ast_set_callerid(chan, NULL, p->cid_name, NULL);
08524                   }
08525                   ast_setstate(chan, AST_STATE_RING);
08526                   dahdi_enable_ec(p);
08527                   res = ast_pbx_run(chan);
08528                   if (res) {
08529                      ast_log(LOG_WARNING, "PBX exited non-zero\n");
08530                      res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
08531                   }
08532                   goto quit;
08533                }
08534             } else {
08535                /* It's a match, but they just typed a digit, and there is an ambiguous match,
08536                   so just set the timeout to matchdigittimeout and wait some more */
08537                timeout = matchdigittimeout;
08538             }
08539          } else if (res == 0) {
08540             ast_debug(1, "not enough digits (and no ambiguous match)...\n");
08541             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
08542             dahdi_wait_event(p->subs[idx].dfd);
08543             ast_hangup(chan);
08544             goto quit;
08545          } else if (p->callwaiting && !strcmp(exten, "*70")) {
08546             ast_verb(3, "Disabling call waiting on %s\n", chan->name);
08547             /* Disable call waiting if enabled */
08548             p->callwaiting = 0;
08549             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
08550             if (res) {
08551                ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
08552                   chan->name, strerror(errno));
08553             }
08554             len = 0;
08555             ioctl(p->subs[idx].dfd,DAHDI_CONFDIAG,&len);
08556             memset(exten, 0, sizeof(exten));
08557             timeout = firstdigittimeout;
08558 
08559          } else if (!strcmp(exten,ast_pickup_ext())) {
08560             /* Scan all channels and see if there are any
08561              * ringing channels that have call groups
08562              * that equal this channels pickup group
08563              */
08564             if (idx == SUB_REAL) {
08565                /* Switch us from Third call to Call Wait */
08566                if (p->subs[SUB_THREEWAY].owner) {
08567                   /* If you make a threeway call and the *8# a call, it should actually
08568                      look like a callwait */
08569                   alloc_sub(p, SUB_CALLWAIT);
08570                   swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
08571                   unalloc_sub(p, SUB_THREEWAY);
08572                }
08573                dahdi_enable_ec(p);
08574                if (ast_pickup_call(chan)) {
08575                   ast_debug(1, "No call pickup possible...\n");
08576                   res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
08577                   dahdi_wait_event(p->subs[idx].dfd);
08578                }
08579                ast_hangup(chan);
08580                goto quit;
08581             } else {
08582                ast_log(LOG_WARNING, "Huh?  Got *8# on call not on real\n");
08583                ast_hangup(chan);
08584                goto quit;
08585             }
08586 
08587          } else if (!p->hidecallerid && !strcmp(exten, "*67")) {
08588             ast_verb(3, "Disabling Caller*ID on %s\n", chan->name);
08589             /* Disable Caller*ID if enabled */
08590             p->hidecallerid = 1;
08591             if (chan->cid.cid_num)
08592                ast_free(chan->cid.cid_num);
08593             chan->cid.cid_num = NULL;
08594             if (chan->cid.cid_name)
08595                ast_free(chan->cid.cid_name);
08596             chan->cid.cid_name = NULL;
08597             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
08598             if (res) {
08599                ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
08600                   chan->name, strerror(errno));
08601             }
08602             len = 0;
08603             memset(exten, 0, sizeof(exten));
08604             timeout = firstdigittimeout;
08605          } else if (p->callreturn && !strcmp(exten, "*69")) {
08606             res = 0;
08607             if (!ast_strlen_zero(p->lastcid_num)) {
08608                res = ast_say_digit_str(chan, p->lastcid_num, "", chan->language);
08609             }
08610             if (!res)
08611                res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
08612             break;
08613          } else if (!strcmp(exten, "*78")) {
08614             dahdi_dnd(p, 1);
08615             /* Do not disturb */
08616             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
08617             getforward = 0;
08618             memset(exten, 0, sizeof(exten));
08619             len = 0;
08620          } else if (!strcmp(exten, "*79")) {
08621             dahdi_dnd(p, 0);
08622             /* Do not disturb */
08623             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
08624             getforward = 0;
08625             memset(exten, 0, sizeof(exten));
08626             len = 0;
08627          } else if (p->cancallforward && !strcmp(exten, "*72")) {
08628             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
08629             getforward = 1;
08630             memset(exten, 0, sizeof(exten));
08631             len = 0;
08632          } else if (p->cancallforward && !strcmp(exten, "*73")) {
08633             ast_verb(3, "Cancelling call forwarding on channel %d\n", p->channel);
08634             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
08635             memset(p->call_forward, 0, sizeof(p->call_forward));
08636             getforward = 0;
08637             memset(exten, 0, sizeof(exten));
08638             len = 0;
08639          } else if ((p->transfer || p->canpark) && !strcmp(exten, ast_parking_ext()) &&
08640                   p->subs[SUB_THREEWAY].owner &&
08641                   ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
08642             /* This is a three way call, the main call being a real channel,
08643                and we're parking the first call. */
08644             ast_masq_park_call(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), chan, 0, NULL);
08645             ast_verb(3, "Parking call to '%s'\n", chan->name);
08646             break;
08647          } else if (!ast_strlen_zero(p->lastcid_num) && !strcmp(exten, "*60")) {
08648             ast_verb(3, "Blacklisting number %s\n", p->lastcid_num);
08649             res = ast_db_put("blacklist", p->lastcid_num, "1");
08650             if (!res) {
08651                res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
08652                memset(exten, 0, sizeof(exten));
08653                len = 0;
08654             }
08655          } else if (p->hidecallerid && !strcmp(exten, "*82")) {
08656             ast_verb(3, "Enabling Caller*ID on %s\n", chan->name);
08657             /* Enable Caller*ID if enabled */
08658             p->hidecallerid = 0;
08659             if (chan->cid.cid_num)
08660                ast_free(chan->cid.cid_num);
08661             chan->cid.cid_num = NULL;
08662             if (chan->cid.cid_name)
08663                ast_free(chan->cid.cid_name);
08664             chan->cid.cid_name = NULL;
08665             ast_set_callerid(chan, p->cid_num, p->cid_name, NULL);
08666             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
08667             if (res) {
08668                ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
08669                   chan->name, strerror(errno));
08670             }
08671             len = 0;
08672             memset(exten, 0, sizeof(exten));
08673             timeout = firstdigittimeout;
08674          } else if (!strcmp(exten, "*0")) {
08675             struct ast_channel *nbridge =
08676                p->subs[SUB_THREEWAY].owner;
08677             struct dahdi_pvt *pbridge = NULL;
08678             /* set up the private struct of the bridged one, if any */
08679             if (nbridge && ast_bridged_channel(nbridge))
08680                pbridge = ast_bridged_channel(nbridge)->tech_pvt;
08681             if (nbridge && pbridge &&
08682                (nbridge->tech == &dahdi_tech) &&
08683                (ast_bridged_channel(nbridge)->tech == &dahdi_tech) &&
08684                ISTRUNK(pbridge)) {
08685                int func = DAHDI_FLASH;
08686                /* Clear out the dial buffer */
08687                p->dop.dialstr[0] = '\0';
08688                /* flash hookswitch */
08689                if ((ioctl(pbridge->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
08690                   ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
08691                      nbridge->name, strerror(errno));
08692                }
08693                swap_subs(p, SUB_REAL, SUB_THREEWAY);
08694                unalloc_sub(p, SUB_THREEWAY);
08695                p->owner = p->subs[SUB_REAL].owner;
08696                if (ast_bridged_channel(p->subs[SUB_REAL].owner))
08697                   ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
08698                ast_hangup(chan);
08699                goto quit;
08700             } else {
08701                tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
08702                dahdi_wait_event(p->subs[idx].dfd);
08703                tone_zone_play_tone(p->subs[idx].dfd, -1);
08704                swap_subs(p, SUB_REAL, SUB_THREEWAY);
08705                unalloc_sub(p, SUB_THREEWAY);
08706                p->owner = p->subs[SUB_REAL].owner;
08707                ast_hangup(chan);
08708                goto quit;
08709             }
08710          } else if (!ast_canmatch_extension(chan, chan->context, exten, 1, chan->cid.cid_num) &&
08711                      ((exten[0] != '*') || (strlen(exten) > 2))) {
08712             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);
08713             break;
08714          }
08715          if (!timeout)
08716             timeout = gendigittimeout;
08717          if (len && !ast_ignore_pattern(chan->context, exten))
08718             tone_zone_play_tone(p->subs[idx].dfd, -1);
08719       }
08720       break;
08721    case SIG_FXSLS:
08722    case SIG_FXSGS:
08723    case SIG_FXSKS:
08724 #ifdef HAVE_PRI
08725       if (p->pri) {
08726          /* This is a GR-303 trunk actually.  Wait for the first ring... */
08727          struct ast_frame *f;
08728          int res;
08729          time_t start;
08730 
08731          time(&start);
08732          ast_setstate(chan, AST_STATE_RING);
08733          while (time(NULL) < start + 3) {
08734             res = ast_waitfor(chan, 1000);
08735             if (res) {
08736                f = ast_read(chan);
08737                if (!f) {
08738                   ast_log(LOG_WARNING, "Whoa, hangup while waiting for first ring!\n");
08739                   ast_hangup(chan);
08740                   goto quit;
08741                } else if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_RING)) {
08742                   res = 1;
08743                } else
08744                   res = 0;
08745                ast_frfree(f);
08746                if (res) {
08747                   ast_debug(1, "Got ring!\n");
08748                   res = 0;
08749                   break;
08750                }
08751             }
08752          }
08753       }
08754 #endif
08755       /* check for SMDI messages */
08756       if (p->use_smdi && p->smdi_iface) {
08757          smdi_msg = ast_smdi_md_message_wait(p->smdi_iface, SMDI_MD_WAIT_TIMEOUT);
08758 
08759          if (smdi_msg != NULL) {
08760             ast_copy_string(chan->exten, smdi_msg->fwd_st, sizeof(chan->exten));
08761 
08762             if (smdi_msg->type == 'B')
08763                pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "b");
08764             else if (smdi_msg->type == 'N')
08765                pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "u");
08766 
08767             ast_debug(1, "Received SMDI message on %s\n", chan->name);
08768          } else {
08769             ast_log(LOG_WARNING, "SMDI enabled but no SMDI message present\n");
08770          }
08771       }
08772 
08773       if (p->use_callerid && (p->cid_signalling == CID_SIG_SMDI && smdi_msg)) {
08774          number = smdi_msg->calling_st;
08775 
08776       /* If we want caller id, we're in a prering state due to a polarity reversal
08777        * and we're set to use a polarity reversal to trigger the start of caller id,
08778        * grab the caller id and wait for ringing to start... */
08779       } else if (p->use_callerid && (chan->_state == AST_STATE_PRERING && (p->cid_start == CID_START_POLARITY || p->cid_start == CID_START_POLARITY_IN))) {
08780          /* If set to use DTMF CID signalling, listen for DTMF */
08781          if (p->cid_signalling == CID_SIG_DTMF) {
08782             int k = 0;
08783             cs = NULL;
08784             ast_debug(1, "Receiving DTMF cid on channel %s\n", chan->name);
08785             dahdi_setlinear(p->subs[idx].dfd, 0);
08786             /*
08787              * We are the only party interested in the Rx stream since
08788              * we have not answered yet.  We don't need or even want DTMF
08789              * emulation.  The DTMF digits can come so fast that emulation
08790              * can drop some of them.
08791              */
08792             ast_set_flag(chan, AST_FLAG_END_DTMF_ONLY);
08793             res = 4000;/* This is a typical OFF time between rings. */
08794             for (;;) {
08795                struct ast_frame *f;
08796                res = ast_waitfor(chan, res);
08797                if (res <= 0) {
08798                   /*
08799                    * We do not need to restore the dahdi_setlinear()
08800                    * or AST_FLAG_END_DTMF_ONLY flag settings since we
08801                    * are hanging up the channel.
08802                    */
08803                   ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
08804                      "Exiting simple switch\n");
08805                   ast_hangup(chan);
08806                   goto quit;
08807                }
08808                f = ast_read(chan);
08809                if (!f)
08810                   break;
08811                if (f->frametype == AST_FRAME_DTMF) {
08812                   if (k < ARRAY_LEN(dtmfbuf) - 1) {
08813                      dtmfbuf[k++] = f->subclass;
08814                   }
08815                   ast_debug(1, "CID got digit '%c'\n", f->subclass);
08816                   res = 4000;/* This is a typical OFF time between rings. */
08817                }
08818                ast_frfree(f);
08819                if (chan->_state == AST_STATE_RING ||
08820                   chan->_state == AST_STATE_RINGING)
08821                   break; /* Got ring */
08822             }
08823             ast_clear_flag(chan, AST_FLAG_END_DTMF_ONLY);
08824             dtmfbuf[k] = '\0';
08825             dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
08826             /* Got cid and ring. */
08827             ast_debug(1, "CID got string '%s'\n", dtmfbuf);
08828             callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
08829             ast_debug(1, "CID is '%s', flags %d\n", dtmfcid, flags);
08830             /* If first byte is NULL, we have no cid */
08831             if (!ast_strlen_zero(dtmfcid))
08832                number = dtmfcid;
08833             else
08834                number = NULL;
08835          /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */
08836          } else if ((p->cid_signalling == CID_SIG_V23) || (p->cid_signalling == CID_SIG_V23_JP)) {
08837             cs = callerid_new(p->cid_signalling);
08838             if (cs) {
08839                samples = 0;
08840 #if 1
08841                bump_gains(p);
08842 #endif
08843                /* Take out of linear mode for Caller*ID processing */
08844                dahdi_setlinear(p->subs[idx].dfd, 0);
08845 
08846                /* First we wait and listen for the Caller*ID */
08847                for (;;) {
08848                   i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
08849                   if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
08850                      ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
08851                      callerid_free(cs);
08852                      ast_hangup(chan);
08853                      goto quit;
08854                   }
08855                   if (i & DAHDI_IOMUX_SIGEVENT) {
08856                      res = dahdi_get_event(p->subs[idx].dfd);
08857                      ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
08858                      if (res == DAHDI_EVENT_NOALARM) {
08859                         p->inalarm = 0;
08860                      }
08861 
08862                      if (p->cid_signalling == CID_SIG_V23_JP) {
08863                         if (res == DAHDI_EVENT_RINGBEGIN) {
08864                            res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
08865                            usleep(1);
08866                         }
08867                      } else {
08868                         res = 0;
08869                         break;
08870                      }
08871                   } else if (i & DAHDI_IOMUX_READ) {
08872                      res = read(p->subs[idx].dfd, buf, sizeof(buf));
08873                      if (res < 0) {
08874                         if (errno != ELAST) {
08875                            ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
08876                            callerid_free(cs);
08877                            ast_hangup(chan);
08878                            goto quit;
08879                         }
08880                         break;
08881                      }
08882                      samples += res;
08883 
08884                      if (p->cid_signalling == CID_SIG_V23_JP) {
08885                         res = callerid_feed_jp(cs, buf, res, AST_LAW(p));
08886                      } else {
08887                         res = callerid_feed(cs, buf, res, AST_LAW(p));
08888                      }
08889                      if (res < 0) {
08890                         /*
08891                          * The previous diagnostic message output likely
08892                          * explains why it failed.
08893                          */
08894                         ast_log(LOG_WARNING,
08895                            "Failed to decode CallerID on channel '%s'\n",
08896                            chan->name);
08897                         break;
08898                      } else if (res)
08899                         break;
08900                      else if (samples > (8000 * 10))
08901                         break;
08902                   }
08903                }
08904                if (res == 1) {
08905                   callerid_get(cs, &name, &number, &flags);
08906                   ast_log(LOG_NOTICE, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
08907                }
08908 
08909                if (p->cid_signalling == CID_SIG_V23_JP) {
08910                   res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
08911                   usleep(1);
08912                }
08913 
08914                /* Finished with Caller*ID, now wait for a ring to make sure there really is a call coming */
08915                res = 4000;/* This is a typical OFF time between rings. */
08916                for (;;) {
08917                   struct ast_frame *f;
08918                   res = ast_waitfor(chan, res);
08919                   if (res <= 0) {
08920                      ast_log(LOG_WARNING, "CID timed out waiting for ring. "
08921                         "Exiting simple switch\n");
08922                      ast_hangup(chan);
08923                      goto quit;
08924                   }
08925                   if (!(f = ast_read(chan))) {
08926                      ast_log(LOG_WARNING, "Hangup received waiting for ring. Exiting simple switch\n");
08927                      ast_hangup(chan);
08928                      goto quit;
08929                   }
08930                   ast_frfree(f);
08931                   if (chan->_state == AST_STATE_RING ||
08932                      chan->_state == AST_STATE_RINGING)
08933                      break; /* Got ring */
08934                }
08935 
08936                /* We must have a ring by now, so, if configured, lets try to listen for
08937                 * distinctive ringing */
08938                if (p->usedistinctiveringdetection) {
08939                   len = 0;
08940                   distMatches = 0;
08941                   /* Clear the current ring data array so we dont have old data in it. */
08942                   for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
08943                      curRingData[receivedRingT] = 0;
08944                   receivedRingT = 0;
08945                   counter = 0;
08946                   counter1 = 0;
08947                   /* Check to see if context is what it should be, if not set to be. */
08948                   if (strcmp(p->context,p->defcontext) != 0) {
08949                      ast_copy_string(p->context, p->defcontext, sizeof(p->context));
08950                      ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
08951                   }
08952 
08953                   for (;;) {
08954                      i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
08955                      if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
08956                         ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
08957                         callerid_free(cs);
08958                         ast_hangup(chan);
08959                         goto quit;
08960                      }
08961                      if (i & DAHDI_IOMUX_SIGEVENT) {
08962                         res = dahdi_get_event(p->subs[idx].dfd);
08963                         ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
08964                         if (res == DAHDI_EVENT_NOALARM) {
08965                            p->inalarm = 0;
08966                         }
08967                         res = 0;
08968                         /* Let us detect distinctive ring */
08969 
08970                         curRingData[receivedRingT] = p->ringt;
08971 
08972                         if (p->ringt < p->ringt_base/2)
08973                            break;
08974                         /* Increment the ringT counter so we can match it against
08975                            values in chan_dahdi.conf for distinctive ring */
08976                         if (++receivedRingT == ARRAY_LEN(curRingData))
08977                            break;
08978                      } else if (i & DAHDI_IOMUX_READ) {
08979                         res = read(p->subs[idx].dfd, buf, sizeof(buf));
08980                         if (res < 0) {
08981                            if (errno != ELAST) {
08982                               ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
08983                               callerid_free(cs);
08984                               ast_hangup(chan);
08985                               goto quit;
08986                            }
08987                            break;
08988                         }
08989                         if (p->ringt)
08990                            p->ringt--;
08991                         if (p->ringt == 1) {
08992                            res = -1;
08993                            break;
08994                         }
08995                      }
08996                   }
08997                      /* this only shows up if you have n of the dring patterns filled in */
08998                   ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
08999                   for (counter = 0; counter < 3; counter++) {
09000                      /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this
09001                      channel */
09002                      distMatches = 0;
09003                      for (counter1 = 0; counter1 < 3; counter1++) {
09004                         ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
09005                         if (p->drings.ringnum[counter].ring[counter1] == -1) {
09006                            ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
09007                            curRingData[counter1]);
09008                            distMatches++;
09009                         } else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
09010                               curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
09011                            ast_verb(3, "Ring pattern matched in range: %d to %d\n",
09012                            (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
09013                            (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
09014                            distMatches++;
09015                         }
09016                      }
09017 
09018                      if (distMatches == 3) {
09019                         /* The ring matches, set the context to whatever is for distinctive ring.. */
09020                         ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context));
09021                         ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context));
09022                         ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
09023                         break;
09024                      }
09025                   }
09026                }
09027                /* Restore linear mode (if appropriate) for Caller*ID processing */
09028                dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09029 #if 1
09030                restore_gains(p);
09031 #endif
09032             } else
09033                ast_log(LOG_WARNING, "Unable to get caller ID space\n");
09034          } else {
09035             ast_log(LOG_WARNING, "Channel %s in prering "
09036                "state, but I have nothing to do. "
09037                "Terminating simple switch, should be "
09038                "restarted by the actual ring.\n",
09039                chan->name);
09040             ast_hangup(chan);
09041             goto quit;
09042          }
09043       } else if (p->use_callerid && p->cid_start == CID_START_RING) {
09044          if (p->cid_signalling == CID_SIG_DTMF) {
09045             int k = 0;
09046             cs = NULL;
09047             dahdi_setlinear(p->subs[idx].dfd, 0);
09048             res = 2000;
09049             for (;;) {
09050                struct ast_frame *f;
09051                res = ast_waitfor(chan, res);
09052                if (res <= 0) {
09053                   ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
09054                      "Exiting simple switch\n");
09055                   ast_hangup(chan);
09056                   return NULL;
09057                }
09058                f = ast_read(chan);
09059                if (f->frametype == AST_FRAME_DTMF) {
09060                   dtmfbuf[k++] = f->subclass;
09061                   ast_log(LOG_DEBUG, "CID got digit '%c'\n", f->subclass);
09062                   res = 2000;
09063                }
09064                ast_frfree(f);
09065 
09066                if (p->ringt_base == p->ringt)
09067                   break;
09068             }
09069             dtmfbuf[k] = '\0';
09070             dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09071             /* Got cid and ring. */
09072             callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
09073             ast_log(LOG_DEBUG, "CID is '%s', flags %d\n",
09074                dtmfcid, flags);
09075             /* If first byte is NULL, we have no cid */
09076             if (!ast_strlen_zero(dtmfcid))
09077                number = dtmfcid;
09078             else
09079                number = NULL;
09080             /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */
09081          } else {
09082             /* FSK Bell202 callerID */
09083             cs = callerid_new(p->cid_signalling);
09084             if (cs) {
09085 #if 1
09086                bump_gains(p);
09087 #endif
09088                samples = 0;
09089                len = 0;
09090                distMatches = 0;
09091                /* Clear the current ring data array so we dont have old data in it. */
09092                for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
09093                   curRingData[receivedRingT] = 0;
09094                receivedRingT = 0;
09095                counter = 0;
09096                counter1 = 0;
09097                /* Check to see if context is what it should be, if not set to be. */
09098                if (strcmp(p->context,p->defcontext) != 0) {
09099                   ast_copy_string(p->context, p->defcontext, sizeof(p->context));
09100                   ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
09101                }
09102 
09103                /* Take out of linear mode for Caller*ID processing */
09104                dahdi_setlinear(p->subs[idx].dfd, 0);
09105                for (;;) {
09106                   i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
09107                   if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
09108                      ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
09109                      callerid_free(cs);
09110                      ast_hangup(chan);
09111                      goto quit;
09112                   }
09113                   if (i & DAHDI_IOMUX_SIGEVENT) {
09114                      res = dahdi_get_event(p->subs[idx].dfd);
09115                      ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
09116                      if (res == DAHDI_EVENT_NOALARM) {
09117                         p->inalarm = 0;
09118                      }
09119                      /* If we get a PR event, they hung up while processing calerid */
09120                      if ( res == DAHDI_EVENT_POLARITY && p->hanguponpolarityswitch && p->polarity == POLARITY_REV) {
09121                         ast_log(LOG_DEBUG, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p->channel);
09122                         p->polarity = POLARITY_IDLE;
09123                         callerid_free(cs);
09124                         ast_hangup(chan);
09125                         goto quit;
09126                      }
09127                      res = 0;
09128                      /* Let us detect callerid when the telco uses distinctive ring */
09129 
09130                      curRingData[receivedRingT] = p->ringt;
09131 
09132                      if (p->ringt < p->ringt_base/2)
09133                         break;
09134                      /* Increment the ringT counter so we can match it against
09135                         values in chan_dahdi.conf for distinctive ring */
09136                      if (++receivedRingT == ARRAY_LEN(curRingData))
09137                         break;
09138                   } else if (i & DAHDI_IOMUX_READ) {
09139                      res = read(p->subs[idx].dfd, buf, sizeof(buf));
09140                      if (res < 0) {
09141                         if (errno != ELAST) {
09142                            ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
09143                            callerid_free(cs);
09144                            ast_hangup(chan);
09145                            goto quit;
09146                         }
09147                         break;
09148                      }
09149                      if (p->ringt)
09150                         p->ringt--;
09151                      if (p->ringt == 1) {
09152                         res = -1;
09153                         break;
09154                      }
09155                      samples += res;
09156                      res = callerid_feed(cs, buf, res, AST_LAW(p));
09157                      if (res < 0) {
09158                         /*
09159                          * The previous diagnostic message output likely
09160                          * explains why it failed.
09161                          */
09162                         ast_log(LOG_WARNING,
09163                            "Failed to decode CallerID on channel '%s'\n",
09164                            chan->name);
09165                         break;
09166                      } else if (res)
09167                         break;
09168                      else if (samples > (8000 * 10))
09169                         break;
09170                   }
09171                }
09172                if (res == 1) {
09173                   callerid_get(cs, &name, &number, &flags);
09174                   ast_debug(1, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
09175                }
09176                if (distinctiveringaftercid == 1) {
09177                   /* Clear the current ring data array so we dont have old data in it. */
09178                   for (receivedRingT = 0; receivedRingT < 3; receivedRingT++) {
09179                      curRingData[receivedRingT] = 0;
09180                   }
09181                   receivedRingT = 0;
09182                   ast_verb(3, "Detecting post-CID distinctive ring\n");
09183                   for (;;) {
09184                      i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
09185                      if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
09186                         ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
09187                         callerid_free(cs);
09188                         ast_hangup(chan);
09189                         goto quit;
09190                      }
09191                      if (i & DAHDI_IOMUX_SIGEVENT) {
09192                         res = dahdi_get_event(p->subs[idx].dfd);
09193                         ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
09194                         if (res == DAHDI_EVENT_NOALARM) {
09195                            p->inalarm = 0;
09196                         }
09197                         res = 0;
09198                         /* Let us detect callerid when the telco uses distinctive ring */
09199 
09200                         curRingData[receivedRingT] = p->ringt;
09201 
09202                         if (p->ringt < p->ringt_base/2)
09203                            break;
09204                         /* Increment the ringT counter so we can match it against
09205                            values in chan_dahdi.conf for distinctive ring */
09206                         if (++receivedRingT == ARRAY_LEN(curRingData))
09207                            break;
09208                      } else if (i & DAHDI_IOMUX_READ) {
09209                         res = read(p->subs[idx].dfd, buf, sizeof(buf));
09210                         if (res < 0) {
09211                            if (errno != ELAST) {
09212                               ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
09213                               callerid_free(cs);
09214                               ast_hangup(chan);
09215                               goto quit;
09216                            }
09217                            break;
09218                         }
09219                      if (p->ringt)
09220                         p->ringt--;
09221                         if (p->ringt == 1) {
09222                            res = -1;
09223                            break;
09224                         }
09225                      }
09226                   }
09227                }
09228                if (p->usedistinctiveringdetection) {
09229                   /* this only shows up if you have n of the dring patterns filled in */
09230                   ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
09231 
09232                   for (counter = 0; counter < 3; counter++) {
09233                      /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this
09234                      channel */
09235                      /* this only shows up if you have n of the dring patterns filled in */
09236                      ast_verb(3, "Checking %d,%d,%d\n",
09237                            p->drings.ringnum[counter].ring[0],
09238                            p->drings.ringnum[counter].ring[1],
09239                            p->drings.ringnum[counter].ring[2]);
09240                      distMatches = 0;
09241                      for (counter1 = 0; counter1 < 3; counter1++) {
09242                         ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
09243                         if (p->drings.ringnum[counter].ring[counter1] == -1) {
09244                            ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
09245                            curRingData[counter1]);
09246                            distMatches++;
09247                         }
09248                         else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
09249                            curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
09250                            ast_verb(3, "Ring pattern matched in range: %d to %d\n",
09251                            (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
09252                            (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
09253                            distMatches++;
09254                         }
09255                      }
09256                      if (distMatches == 3) {
09257                         /* The ring matches, set the context to whatever is for distinctive ring.. */
09258                         ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context));
09259                         ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context));
09260                         ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
09261                         break;
09262                      }
09263                   }
09264                }
09265                /* Restore linear mode (if appropriate) for Caller*ID processing */
09266                dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09267 #if 1
09268                restore_gains(p);
09269 #endif
09270                if (res < 0) {
09271                   ast_log(LOG_WARNING, "CallerID returned with error on channel '%s'\n", chan->name);
09272                }
09273             } else
09274                ast_log(LOG_WARNING, "Unable to get caller ID space\n");
09275          }
09276       } else
09277          cs = NULL;
09278 
09279       if (number)
09280          ast_shrink_phone_number(number);
09281       ast_set_callerid(chan, number, name, number);
09282 
09283       if (smdi_msg)
09284          ASTOBJ_UNREF(smdi_msg, ast_smdi_md_message_destroy);
09285 
09286       if (cs)
09287          callerid_free(cs);
09288       /* If the CID had Message waiting payload, assume that this for MWI only and hangup the call */
09289       if (flags & CID_MSGWAITING) {
09290          ast_log(LOG_NOTICE, "MWI: Channel %d message waiting!\n", p->channel);
09291          notify_message(p->mailbox, 1);
09292          /* If generated using Ring Pulse Alert, then ring has been answered as a call and needs to be hungup */
09293          if (p->mwimonitor_rpas) {
09294             ast_hangup(chan);
09295             return NULL;
09296          }
09297       } else if (flags & CID_NOMSGWAITING) {
09298          ast_log(LOG_NOTICE, "MWI: Channel %d no message waiting!\n", p->channel);
09299          notify_message(p->mailbox, 0);
09300          /* If generated using Ring Pulse Alert, then ring has been answered as a call and needs to be hungup */
09301          if (p->mwimonitor_rpas) {
09302             ast_hangup(chan);
09303             return NULL;
09304          }
09305       }
09306 
09307       ast_setstate(chan, AST_STATE_RING);
09308       chan->rings = 1;
09309       p->ringt = p->ringt_base;
09310       res = ast_pbx_run(chan);
09311       if (res) {
09312          ast_hangup(chan);
09313          ast_log(LOG_WARNING, "PBX exited non-zero\n");
09314       }
09315       goto quit;
09316    default:
09317       ast_log(LOG_WARNING, "Don't know how to handle simple switch with signalling %s on channel %d\n", sig2str(p->sig), p->channel);
09318       res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
09319       if (res < 0)
09320             ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
09321    }
09322    res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
09323    if (res < 0)
09324          ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
09325    ast_hangup(chan);
09326 quit:
09327    ast_mutex_lock(&ss_thread_lock);
09328    ss_thread_count--;
09329    ast_cond_signal(&ss_thread_complete);
09330    ast_mutex_unlock(&ss_thread_lock);
09331    return NULL;
09332 }
09333 
09334 struct mwi_thread_data {
09335    struct dahdi_pvt *pvt;
09336    unsigned char buf[READ_SIZE];
09337    size_t len;
09338 };
09339 
09340 static int calc_energy(const unsigned char *buf, int len, int law)
09341 {
09342    int x;
09343    int sum = 0;
09344 
09345    if (!len)
09346       return 0;
09347 
09348    for (x = 0; x < len; x++)
09349       sum += abs(law == AST_FORMAT_ULAW ? AST_MULAW(buf[x]) : AST_ALAW(buf[x]));
09350 
09351    return sum / len;
09352 }
09353 
09354 static void *mwi_thread(void *data)
09355 {
09356    struct mwi_thread_data *mtd = data;
09357    struct callerid_state *cs;
09358    pthread_t threadid;
09359    int samples = 0;
09360    char *name, *number;
09361    int flags;
09362    int i, res;
09363    unsigned int spill_done = 0;
09364    int spill_result = -1;
09365 
09366    if (!(cs = callerid_new(mtd->pvt->cid_signalling))) {
09367       mtd->pvt->mwimonitoractive = 0;
09368 
09369       return NULL;
09370    }
09371 
09372    callerid_feed(cs, mtd->buf, mtd->len, AST_LAW(mtd->pvt));
09373 
09374    bump_gains(mtd->pvt);
09375 
09376    for (;;) {
09377       i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
09378       if ((res = ioctl(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_IOMUX, &i))) {
09379          ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
09380          goto quit;
09381       }
09382 
09383       if (i & DAHDI_IOMUX_SIGEVENT) {
09384          struct ast_channel *chan;
09385 
09386          /* If we get an event, screen out events that we do not act on.
09387           * Otherwise, cancel and go to the simple switch to let it deal with it.
09388           */
09389          res = dahdi_get_event(mtd->pvt->subs[SUB_REAL].dfd);
09390 
09391          switch (res) {
09392          case DAHDI_EVENT_NEONMWI_ACTIVE:
09393          case DAHDI_EVENT_NEONMWI_INACTIVE:
09394          case DAHDI_EVENT_NONE:
09395          case DAHDI_EVENT_BITSCHANGED:
09396             break;
09397          case DAHDI_EVENT_NOALARM:
09398             mtd->pvt->inalarm = 0;
09399             ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", mtd->pvt->channel);
09400             manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
09401                "Channel: %d\r\n", mtd->pvt->channel);
09402             break;
09403          case DAHDI_EVENT_ALARM:
09404             mtd->pvt->inalarm = 1;
09405             res = get_alarms(mtd->pvt);
09406             handle_alarms(mtd->pvt, res);
09407             break; /* What to do on channel alarm ???? -- fall thru intentionally?? */
09408          default:
09409             ast_log(LOG_NOTICE, "Got event %d (%s)...  Passing along to ss_thread\n", res, event2str(res));
09410             callerid_free(cs);
09411 
09412             restore_gains(mtd->pvt);
09413             mtd->pvt->ringt = mtd->pvt->ringt_base;
09414 
09415             if ((chan = dahdi_new(mtd->pvt, AST_STATE_RING, 0, SUB_REAL, 0, 0))) {
09416                if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
09417                   ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", mtd->pvt->channel);
09418                   res = tone_zone_play_tone(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
09419                   if (res < 0)
09420                      ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", mtd->pvt->channel);
09421                   ast_hangup(chan);
09422                   goto quit;
09423                }
09424                goto quit_no_clean;
09425 
09426             } else {
09427                ast_log(LOG_WARNING, "Could not create channel to handle call\n");
09428             }
09429          }
09430       } else if (i & DAHDI_IOMUX_READ) {
09431          if ((res = read(mtd->pvt->subs[SUB_REAL].dfd, mtd->buf, sizeof(mtd->buf))) < 0) {
09432             if (errno != ELAST) {
09433                ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
09434                goto quit;
09435             }
09436             break;
09437          }
09438          samples += res;
09439          if (!spill_done) {
09440             if ((spill_result = callerid_feed(cs, mtd->buf, res, AST_LAW(mtd->pvt))) < 0) {
09441                /*
09442                 * The previous diagnostic message output likely
09443                 * explains why it failed.
09444                 */
09445                ast_log(LOG_WARNING, "Failed to decode CallerID\n");
09446                break;
09447             } else if (spill_result) {
09448                spill_done = 1;
09449             }
09450          } else {
09451             /* keep reading data until the energy level drops below the threshold
09452                so we don't get another 'trigger' on the remaining carrier signal
09453             */
09454             if (calc_energy(mtd->buf, res, AST_LAW(mtd->pvt)) <= mwilevel)
09455                break;
09456          }
09457          if (samples > (8000 * 4)) /*Termination case - time to give up*/
09458             break;
09459       }
09460    }
09461 
09462    if (spill_result == 1) {
09463       callerid_get(cs, &name, &number, &flags);
09464       if (flags & CID_MSGWAITING) {
09465          ast_log(LOG_NOTICE, "mwi: Have Messages on channel %d\n", mtd->pvt->channel);
09466          notify_message(mtd->pvt->mailbox, 1);
09467       } else if (flags & CID_NOMSGWAITING) {
09468          ast_log(LOG_NOTICE, "mwi: No Messages on channel %d\n", mtd->pvt->channel);
09469          notify_message(mtd->pvt->mailbox, 0);
09470       } else {
09471          ast_log(LOG_NOTICE, "mwi: Status unknown on channel %d\n", mtd->pvt->channel);
09472       }
09473    }
09474 
09475 
09476 quit:
09477    callerid_free(cs);
09478 
09479    restore_gains(mtd->pvt);
09480 
09481 quit_no_clean:
09482    mtd->pvt->mwimonitoractive = 0;
09483 
09484    ast_free(mtd);
09485 
09486    return NULL;
09487 }
09488 
09489 /*
09490 * The following three functions (mwi_send_init, mwi_send_process_buffer,
09491 * mwi_send_process_event) work with the do_monitor thread to generate mwi spills
09492 * that are sent out via FXA port on voicemail state change.  The execution of
09493 * the mwi send is state driven and can either generate a ring pulse prior to
09494 * sending the fsk spill or simply send an fsk spill.
09495 */
09496 static int mwi_send_init(struct dahdi_pvt * pvt)
09497 {
09498    int x, res;
09499 
09500 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
09501    /* Determine how this spill is to be sent */
09502    if (pvt->mwisend_rpas) {
09503       pvt->mwisend_data.mwisend_current = MWI_SEND_SA;
09504       pvt->mwisendactive = 1;
09505    } else if (pvt->mwisend_fsk) {
09506       pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
09507       pvt->mwisendactive = 1;
09508    } else {
09509       pvt->mwisendactive = 0;
09510       return 0;
09511    }
09512 #else
09513    if (mwisend_rpas) {
09514       pvt->mwisend_data.mwisend_current = MWI_SEND_SA;
09515    } else {
09516       pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
09517    }
09518    pvt->mwisendactive = 1;
09519 #endif
09520 
09521    if (pvt->cidspill) {
09522       ast_log(LOG_WARNING, "cidspill already exists when trying to send FSK MWI\n");
09523       ast_free(pvt->cidspill);
09524       pvt->cidspill = NULL;
09525       pvt->cidpos = 0;
09526       pvt->cidlen = 0;
09527    }
09528    pvt->cidspill = ast_calloc(1, MAX_CALLERID_SIZE);
09529    if (!pvt->cidspill) {
09530       pvt->mwisendactive = 0;
09531       return -1;
09532    }
09533    x = DAHDI_FLUSH_BOTH;
09534    res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
09535    x = 3000;
09536    ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_ONHOOKTRANSFER, &x);
09537 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
09538    if (pvt->mwisend_fsk) {
09539 #endif
09540       pvt->cidlen = vmwi_generate(pvt->cidspill, has_voicemail(pvt), CID_MWI_TYPE_MDMF_FULL,
09541                         AST_LAW(pvt), pvt->cid_name, pvt->cid_num, 0);
09542       pvt->cidpos = 0;
09543 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
09544    }
09545 #endif
09546    return 0;
09547 }
09548 
09549 static int mwi_send_process_buffer(struct dahdi_pvt * pvt, int num_read)
09550 {
09551    struct timeval    now;
09552    int         res;
09553 
09554    /* sanity check to catch if this had been interrupted previously
09555    *  i.e. state says there is more to do but there is no spill allocated
09556    */
09557    if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current && !pvt->cidspill) {
09558       pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
09559    } else if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current) {
09560       /* Normal processing -- Perform mwi send action */
09561       switch ( pvt->mwisend_data.mwisend_current) {
09562       case MWI_SEND_SA:
09563          /* Send the Ring Pulse Signal Alert */
09564          res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &AS_RP_cadence);
09565          if (res) {
09566             ast_log(LOG_WARNING, "Unable to set RP-AS ring cadence: %s\n", strerror(errno));
09567             goto quit;
09568          }
09569          res = dahdi_set_hook(pvt->subs[SUB_REAL].dfd, DAHDI_RING);
09570          pvt->mwisend_data.mwisend_current = MWI_SEND_SA_WAIT;
09571          break;
09572       case MWI_SEND_SA_WAIT:  /* do nothing until I get RINGEROFF event */
09573          break;
09574       case MWI_SEND_PAUSE:  /* Wait between alert and spill - min of 500 mS*/
09575 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
09576          if (pvt->mwisend_fsk) {
09577 #endif
09578             gettimeofday(&now, NULL);
09579             if ((int)(now.tv_sec - pvt->mwisend_data.pause.tv_sec) * 1000000 + (int)now.tv_usec - (int)pvt->mwisend_data.pause.tv_usec > 500000) {
09580                pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
09581             }
09582 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
09583          } else { /* support for mwisendtype=nofsk */
09584             pvt->mwisend_data.mwisend_current = MWI_SEND_CLEANUP;
09585          }
09586 #endif
09587          break;
09588       case MWI_SEND_SPILL:
09589          /* We read some number of bytes.  Write an equal amount of data */
09590          if(0 < num_read) {
09591             if (num_read > pvt->cidlen - pvt->cidpos)
09592                num_read = pvt->cidlen - pvt->cidpos;
09593             res = write(pvt->subs[SUB_REAL].dfd, pvt->cidspill + pvt->cidpos, num_read);
09594             if (res > 0) {
09595                pvt->cidpos += res;
09596                if (pvt->cidpos >= pvt->cidlen) {
09597                   pvt->mwisend_data.mwisend_current = MWI_SEND_CLEANUP;
09598                }
09599             } else {
09600                ast_log(LOG_WARNING, "MWI FSK Send Write failed: %s\n", strerror(errno));
09601                goto quit;
09602             }
09603          }
09604          break;
09605       case MWI_SEND_CLEANUP:
09606          /* For now, do nothing */
09607          pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
09608          break;
09609       default:
09610          /* Should not get here, punt*/
09611          goto quit;
09612       }
09613    }
09614 
09615    if (MWI_SEND_DONE == pvt->mwisend_data.mwisend_current) {
09616       if (pvt->cidspill) {
09617          ast_free(pvt->cidspill);
09618          pvt->cidspill = NULL;
09619          pvt->cidpos = 0;
09620          pvt->cidlen = 0;
09621       }
09622       pvt->mwisendactive = 0;
09623    }
09624    return 0;
09625 quit:
09626    if (pvt->cidspill) {
09627       ast_free(pvt->cidspill);
09628       pvt->cidspill = NULL;
09629       pvt->cidpos = 0;
09630       pvt->cidlen = 0;
09631    }
09632    pvt->mwisendactive = 0;
09633    return -1;
09634 }
09635 
09636 static int mwi_send_process_event(struct dahdi_pvt * pvt, int event)
09637 {
09638    int handled = 0;
09639 
09640    if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current) {
09641       switch (event) {
09642       case DAHDI_EVENT_RINGEROFF:
09643          if(pvt->mwisend_data.mwisend_current == MWI_SEND_SA_WAIT) {
09644             handled = 1;
09645 
09646             if (dahdi_set_hook(pvt->subs[SUB_REAL].dfd, DAHDI_RINGOFF) ) {
09647                ast_log(LOG_WARNING, "Unable to finish RP-AS: %s mwi send aborted\n", strerror(errno));
09648                ast_free(pvt->cidspill);
09649                pvt->cidspill = NULL;
09650                pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
09651                pvt->mwisendactive = 0;
09652             } else {
09653                pvt->mwisend_data.mwisend_current = MWI_SEND_PAUSE;
09654                gettimeofday(&pvt->mwisend_data.pause, NULL);
09655             }
09656          }
09657          break;
09658       /* Going off hook, I need to punt this spill */
09659       case DAHDI_EVENT_RINGOFFHOOK:
09660          if (pvt->cidspill) {
09661             ast_free(pvt->cidspill);
09662             pvt->cidspill = NULL;
09663             pvt->cidpos = 0;
09664             pvt->cidlen = 0;
09665          }
09666          pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
09667          pvt->mwisendactive = 0;
09668          break;
09669       case DAHDI_EVENT_RINGERON:
09670       case DAHDI_EVENT_HOOKCOMPLETE:
09671          break;
09672       default:
09673          break;
09674       }
09675    }
09676    return handled;
09677 }
09678 
09679 /* destroy a DAHDI channel, identified by its number */
09680 static int dahdi_destroy_channel_bynum(int channel)
09681 {
09682    struct dahdi_pvt *tmp = NULL;
09683    struct dahdi_pvt *prev = NULL;
09684 
09685    tmp = iflist;
09686    while (tmp) {
09687       if (tmp->channel == channel) {
09688          int x = DAHDI_FLASH;
09689          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 */
09690          destroy_channel(prev, tmp, 1);
09691          ast_module_unref(ast_module_info->self);
09692          return RESULT_SUCCESS;
09693       }
09694       prev = tmp;
09695       tmp = tmp->next;
09696    }
09697    return RESULT_FAILURE;
09698 }
09699 
09700 static struct dahdi_pvt *handle_init_event(struct dahdi_pvt *i, int event)
09701 {
09702    int res;
09703    pthread_t threadid;
09704    struct ast_channel *chan;
09705 
09706    /* Handle an event on a given channel for the monitor thread. */
09707 
09708    switch (event) {
09709    case DAHDI_EVENT_NONE:
09710    case DAHDI_EVENT_BITSCHANGED:
09711       break;
09712    case DAHDI_EVENT_WINKFLASH:
09713    case DAHDI_EVENT_RINGOFFHOOK:
09714       if (i->inalarm) break;
09715       if (i->radio) break;
09716       /* Got a ring/answer.  What kind of channel are we? */
09717       switch (i->sig) {
09718       case SIG_FXOLS:
09719       case SIG_FXOGS:
09720       case SIG_FXOKS:
09721          res = dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
09722          i->fxsoffhookstate = 1;
09723          if (res && (errno == EBUSY))
09724             break;
09725 
09726          /* Cancel VMWI spill */
09727          ast_free(i->cidspill);
09728          i->cidspill = NULL;
09729          restore_conference(i);
09730 
09731          if (i->immediate) {
09732             dahdi_enable_ec(i);
09733             /* The channel is immediately up.  Start right away */
09734             res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
09735             chan = dahdi_new(i, AST_STATE_RING, 1, SUB_REAL, 0, 0);
09736             if (!chan) {
09737                ast_log(LOG_WARNING, "Unable to start PBX on channel %d\n", i->channel);
09738                res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
09739                if (res < 0)
09740                   ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
09741             }
09742          } else {
09743             /* Check for callerid, digits, etc */
09744             chan = dahdi_new(i, AST_STATE_RESERVED, 0, SUB_REAL, 0, 0);
09745             if (chan) {
09746                if (has_voicemail(i))
09747                   res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
09748                else
09749                   res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
09750                if (res < 0)
09751                   ast_log(LOG_WARNING, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i->channel);
09752                if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
09753                   ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
09754                   res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
09755                   if (res < 0)
09756                      ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
09757                   ast_hangup(chan);
09758                }
09759             } else
09760                ast_log(LOG_WARNING, "Unable to create channel\n");
09761          }
09762          break;
09763       case SIG_FXSLS:
09764       case SIG_FXSGS:
09765       case SIG_FXSKS:
09766             i->ringt = i->ringt_base;
09767             /* Fall through */
09768       case SIG_EMWINK:
09769       case SIG_FEATD:
09770       case SIG_FEATDMF:
09771       case SIG_FEATDMF_TA:
09772       case SIG_E911:
09773       case SIG_FGC_CAMA:
09774       case SIG_FGC_CAMAMF:
09775       case SIG_FEATB:
09776       case SIG_EM:
09777       case SIG_EM_E1:
09778       case SIG_SFWINK:
09779       case SIG_SF_FEATD:
09780       case SIG_SF_FEATDMF:
09781       case SIG_SF_FEATB:
09782       case SIG_SF:
09783          /* Check for callerid, digits, etc */
09784          if (i->cid_start == CID_START_POLARITY_IN) {
09785             chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, 0);
09786          } else {
09787             chan = dahdi_new(i, AST_STATE_RING, 0, SUB_REAL, 0, 0);
09788          }
09789 
09790          if (!chan) {
09791             ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
09792          } else if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
09793             ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
09794             res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
09795             if (res < 0) {
09796                ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
09797             }
09798             ast_hangup(chan);
09799          }
09800          break;
09801       default:
09802          ast_log(LOG_WARNING, "Don't know how to handle ring/answer with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
09803          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
09804          if (res < 0)
09805             ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
09806          return NULL;
09807       }
09808       break;
09809    case DAHDI_EVENT_NOALARM:
09810       i->inalarm = 0;
09811       ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", i->channel);
09812       manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
09813          "Channel: %d\r\n", i->channel);
09814       break;
09815    case DAHDI_EVENT_ALARM:
09816       i->inalarm = 1;
09817       res = get_alarms(i);
09818       handle_alarms(i, res);
09819       /* fall thru intentionally */
09820    case DAHDI_EVENT_ONHOOK:
09821       if (i->radio)
09822          break;
09823       /* Back on hook.  Hang up. */
09824       switch (i->sig) {
09825       case SIG_FXOLS:
09826       case SIG_FXOGS:
09827       case SIG_FEATD:
09828       case SIG_FEATDMF:
09829       case SIG_FEATDMF_TA:
09830       case SIG_E911:
09831       case SIG_FGC_CAMA:
09832       case SIG_FGC_CAMAMF:
09833       case SIG_FEATB:
09834       case SIG_EM:
09835       case SIG_EM_E1:
09836       case SIG_EMWINK:
09837       case SIG_SF_FEATD:
09838       case SIG_SF_FEATDMF:
09839       case SIG_SF_FEATB:
09840       case SIG_SF:
09841       case SIG_SFWINK:
09842       case SIG_FXSLS:
09843       case SIG_FXSGS:
09844       case SIG_FXSKS:
09845       case SIG_GR303FXSKS:
09846          dahdi_disable_ec(i);
09847          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
09848          dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
09849          break;
09850       case SIG_GR303FXOKS:
09851       case SIG_FXOKS:
09852          dahdi_disable_ec(i);
09853          /* Diddle the battery for the zhone */
09854 #ifdef ZHONE_HACK
09855          dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
09856          usleep(1);
09857 #endif
09858          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
09859          dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
09860          break;
09861       case SIG_PRI:
09862       case SIG_SS7:
09863       case SIG_BRI:
09864       case SIG_BRI_PTMP:
09865          dahdi_disable_ec(i);
09866          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
09867          break;
09868       default:
09869          ast_log(LOG_WARNING, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
09870          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
09871          return NULL;
09872       }
09873       if (i->sig & __DAHDI_SIG_FXO) {
09874          i->fxsoffhookstate = 0;
09875       }
09876       break;
09877    case DAHDI_EVENT_POLARITY:
09878       switch (i->sig) {
09879       case SIG_FXSLS:
09880       case SIG_FXSKS:
09881       case SIG_FXSGS:
09882          /* We have already got a PR before the channel was
09883             created, but it wasn't handled. We need polarity
09884             to be REV for remote hangup detection to work.
09885             At least in Spain */
09886          if (i->hanguponpolarityswitch)
09887             i->polarity = POLARITY_REV;
09888          if (i->cid_start == CID_START_POLARITY || i->cid_start == CID_START_POLARITY_IN) {
09889             i->polarity = POLARITY_REV;
09890             ast_verb(2, "Starting post polarity "
09891                "CID detection on channel %d\n",
09892                i->channel);
09893             chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, 0);
09894             if (!chan) {
09895                ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
09896             } else if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
09897                ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
09898             }
09899          }
09900          break;
09901       default:
09902          ast_log(LOG_WARNING, "handle_init_event detected "
09903             "polarity reversal on non-FXO (SIG_FXS) "
09904             "interface %d\n", i->channel);
09905       }
09906       break;
09907    case DAHDI_EVENT_REMOVED: /* destroy channel, will actually do so in do_monitor */
09908       ast_log(LOG_NOTICE,
09909             "Got DAHDI_EVENT_REMOVED. Destroying channel %d\n",
09910             i->channel);
09911       return i;
09912    case DAHDI_EVENT_NEONMWI_ACTIVE:
09913       if (i->mwimonitor_neon) {
09914          notify_message(i->mailbox, 1);
09915          ast_log(LOG_NOTICE, "NEON MWI set for channel %d, mailbox %s \n", i->channel, i->mailbox);
09916       }
09917       break;
09918    case DAHDI_EVENT_NEONMWI_INACTIVE:
09919       if (i->mwimonitor_neon) {
09920          notify_message(i->mailbox, 0);
09921          ast_log(LOG_NOTICE, "NEON MWI cleared for channel %d, mailbox %s\n", i->channel, i->mailbox);
09922       }
09923       break;
09924    }
09925    return NULL;
09926 }
09927 
09928 static void *do_monitor(void *data)
09929 {
09930    int count, res, res2, spoint, pollres=0;
09931    struct dahdi_pvt *i;
09932    struct dahdi_pvt *last = NULL;
09933    struct dahdi_pvt *doomed;
09934    time_t thispass = 0, lastpass = 0;
09935    int found;
09936    char buf[1024];
09937    struct pollfd *pfds=NULL;
09938    int lastalloc = -1;
09939    /* This thread monitors all the frame relay interfaces which are not yet in use
09940       (and thus do not have a separate thread) indefinitely */
09941    /* From here on out, we die whenever asked */
09942 #if 0
09943    if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) {
09944       ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n");
09945       return NULL;
09946    }
09947    ast_debug(1, "Monitor starting...\n");
09948 #endif
09949    pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
09950 
09951    for (;;) {
09952       /* Lock the interface list */
09953       ast_mutex_lock(&iflock);
09954       if (!pfds || (lastalloc != ifcount)) {
09955          if (pfds) {
09956             ast_free(pfds);
09957             pfds = NULL;
09958          }
09959          if (ifcount) {
09960             if (!(pfds = ast_calloc(1, ifcount * sizeof(*pfds)))) {
09961                ast_mutex_unlock(&iflock);
09962                return NULL;
09963             }
09964          }
09965          lastalloc = ifcount;
09966       }
09967       /* Build the stuff we're going to poll on, that is the socket of every
09968          dahdi_pvt that does not have an associated owner channel */
09969       count = 0;
09970       i = iflist;
09971       while (i) {
09972          if ((i->subs[SUB_REAL].dfd > -1) && i->sig && (!i->radio) && !(i->sig & SIG_MFCR2)) {
09973             if (!i->owner && !i->subs[SUB_REAL].owner && !i->mwimonitoractive ) {
09974                /* This needs to be watched, as it lacks an owner */
09975                pfds[count].fd = i->subs[SUB_REAL].dfd;
09976                pfds[count].events = POLLPRI;
09977                pfds[count].revents = 0;
09978                /* If we are monitoring for VMWI or sending CID, we need to
09979                   read from the channel as well */
09980                if (i->cidspill || i->mwisendactive || i->mwimonitor_fsk)
09981                   pfds[count].events |= POLLIN;
09982                count++;
09983             }
09984          }
09985          i = i->next;
09986       }
09987       /* Okay, now that we know what to do, release the interface lock */
09988       ast_mutex_unlock(&iflock);
09989 
09990       pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
09991       pthread_testcancel();
09992       /* Wait at least a second for something to happen */
09993       res = poll(pfds, count, 1000);
09994       pthread_testcancel();
09995       pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
09996 
09997       /* Okay, poll has finished.  Let's see what happened.  */
09998       if (res < 0) {
09999          if ((errno != EAGAIN) && (errno != EINTR))
10000             ast_log(LOG_WARNING, "poll return %d: %s\n", res, strerror(errno));
10001          continue;
10002       }
10003       /* Alright, lock the interface list again, and let's look and see what has
10004          happened */
10005       ast_mutex_lock(&iflock);
10006       found = 0;
10007       spoint = 0;
10008       lastpass = thispass;
10009       thispass = time(NULL);
10010       i = iflist;
10011       doomed = NULL;
10012       for (i = iflist;; i = i->next) {
10013          if (doomed) {
10014             int res;
10015             res = dahdi_destroy_channel_bynum(doomed->channel);
10016             if (!res) {
10017                ast_log(LOG_WARNING, "Couldn't find channel to destroy, hopefully another destroy operation just happened.\n");
10018             }
10019             doomed = NULL;
10020          }
10021          if (!i) {
10022             break;
10023          }
10024 
10025          if (thispass != lastpass) {
10026             if (!found && ((i == last) || ((i == iflist) && !last))) {
10027                last = i;
10028                if (last) {
10029                   /* Only allow MWI to be initiated on a quiescent fxs port */
10030                   if (!last->mwisendactive
10031                      && (last->sig & __DAHDI_SIG_FXO)
10032                      && !last->fxsoffhookstate
10033                      && !last->owner
10034                      && !ast_strlen_zero(last->mailbox)
10035                      && (thispass - last->onhooktime > 3)) {
10036                      res = has_voicemail(last);
10037                      if (last->msgstate != res) {
10038                         /* Set driver resources for signalling VMWI */
10039                         res2 = ioctl(last->subs[SUB_REAL].dfd, DAHDI_VMWI, &res);
10040                         if (res2) {
10041                            /* TODO: This message will ALWAYS be generated on some cards; any way to restrict it to those cards where it is interesting? */
10042                            ast_debug(3, "Unable to control message waiting led on channel %d: %s\n", last->channel, strerror(errno));
10043                         }
10044                         /* If enabled for FSK spill then initiate it */
10045                         if (mwi_send_init(last)) {
10046                            ast_log(LOG_WARNING, "Unable to initiate mwi send sequence on channel %d\n", last->channel);
10047                         }
10048                         last->msgstate = res;
10049                         found ++;
10050                      }
10051                   }
10052                   last = last->next;
10053                }
10054             }
10055          }
10056          if ((i->subs[SUB_REAL].dfd > -1) && i->sig) {
10057             if (i->radio && !i->owner)
10058             {
10059                res = dahdi_get_event(i->subs[SUB_REAL].dfd);
10060                if (res)
10061                {
10062                   ast_debug(1, "Monitor doohicky got event %s on radio channel %d\n", event2str(res), i->channel);
10063                   /* Don't hold iflock while handling init events */
10064                   ast_mutex_unlock(&iflock);
10065                   doomed = handle_init_event(i, res);
10066                   ast_mutex_lock(&iflock);
10067                }
10068                continue;
10069             }
10070             pollres = ast_fdisset(pfds, i->subs[SUB_REAL].dfd, count, &spoint);
10071             if (pollres & POLLIN) {
10072                if (i->owner || i->subs[SUB_REAL].owner) {
10073 #ifdef HAVE_PRI
10074                   if (!i->pri)
10075 #endif
10076                      ast_log(LOG_WARNING, "Whoa....  I'm owned but found (%d) in read...\n", i->subs[SUB_REAL].dfd);
10077                   continue;
10078                }
10079                if (!i->mwimonitor_fsk && !i->mwisendactive) {
10080                   ast_log(LOG_WARNING, "Whoa....  I'm not looking for MWI or sending MWI but am reading (%d)...\n", i->subs[SUB_REAL].dfd);
10081                   continue;
10082                }
10083                res = read(i->subs[SUB_REAL].dfd, buf, sizeof(buf));
10084                if (res > 0) {
10085                   if (i->mwimonitor_fsk) {
10086                      if (calc_energy((unsigned char *) buf, res, AST_LAW(i)) > mwilevel) {
10087                         pthread_attr_t attr;
10088                         pthread_t threadid;
10089                         struct mwi_thread_data *mtd;
10090 
10091                         pthread_attr_init(&attr);
10092                         pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
10093 
10094                         ast_log(LOG_DEBUG, "Maybe some MWI on port %d!\n", i->channel);
10095                         if ((mtd = ast_calloc(1, sizeof(*mtd)))) {
10096                            mtd->pvt = i;
10097                            memcpy(mtd->buf, buf, res);
10098                            mtd->len = res;
10099                            if (ast_pthread_create_background(&threadid, &attr, mwi_thread, mtd)) {
10100                               ast_log(LOG_WARNING, "Unable to start mwi thread on channel %d\n", i->channel);
10101                               ast_free(mtd);
10102                            }
10103                            i->mwimonitoractive = 1;
10104                         }
10105                      }
10106                   }
10107                   if (i->mwisendactive) {
10108                      mwi_send_process_buffer(i, res);
10109                   }
10110                } else {
10111                   ast_log(LOG_WARNING, "Read failed with %d: %s\n", res, strerror(errno));
10112                }
10113             }
10114             if (pollres & POLLPRI) {
10115                if (i->owner || i->subs[SUB_REAL].owner) {
10116 #ifdef HAVE_PRI
10117                   if (!i->pri)
10118 #endif
10119                      ast_log(LOG_WARNING, "Whoa....  I'm owned but found (%d)...\n", i->subs[SUB_REAL].dfd);
10120                   continue;
10121                }
10122                res = dahdi_get_event(i->subs[SUB_REAL].dfd);
10123                ast_debug(1, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel);
10124                /* Don't hold iflock while handling init events */
10125                ast_mutex_unlock(&iflock);
10126                if (0 == i->mwisendactive || 0 == mwi_send_process_event(i, res)) {
10127                   doomed = handle_init_event(i, res);
10128                }
10129                ast_mutex_lock(&iflock);
10130             }
10131          }
10132       }
10133       ast_mutex_unlock(&iflock);
10134    }
10135    /* Never reached */
10136    return NULL;
10137 
10138 }
10139 
10140 static int restart_monitor(void)
10141 {
10142    /* If we're supposed to be stopped -- stay stopped */
10143    if (monitor_thread == AST_PTHREADT_STOP)
10144       return 0;
10145    ast_mutex_lock(&monlock);
10146    if (monitor_thread == pthread_self()) {
10147       ast_mutex_unlock(&monlock);
10148       ast_log(LOG_WARNING, "Cannot kill myself\n");
10149       return -1;
10150    }
10151    if (monitor_thread != AST_PTHREADT_NULL) {
10152       /* Wake up the thread */
10153       pthread_kill(monitor_thread, SIGURG);
10154    } else {
10155       /* Start a new monitor */
10156       if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) {
10157          ast_mutex_unlock(&monlock);
10158          ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
10159          return -1;
10160       }
10161    }
10162    ast_mutex_unlock(&monlock);
10163    return 0;
10164 }
10165 
10166 #if defined(HAVE_PRI)
10167 static int pri_resolve_span(int *span, int channel, int offset, struct dahdi_spaninfo *si)
10168 {
10169    int x;
10170    int trunkgroup;
10171    /* Get appropriate trunk group if there is one */
10172    trunkgroup = pris[*span].mastertrunkgroup;
10173    if (trunkgroup) {
10174       /* Select a specific trunk group */
10175       for (x = 0; x < NUM_SPANS; x++) {
10176          if (pris[x].trunkgroup == trunkgroup) {
10177             *span = x;
10178             return 0;
10179          }
10180       }
10181       ast_log(LOG_WARNING, "Channel %d on span %d configured to use nonexistent trunk group %d\n", channel, *span, trunkgroup);
10182       *span = -1;
10183    } else {
10184       if (pris[*span].trunkgroup) {
10185          ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is trunk group %d (please use spanmap)\n", *span, pris[*span].trunkgroup);
10186          *span = -1;
10187       } else if (pris[*span].mastertrunkgroup) {
10188          ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is already part of trunk group %d\n", *span, pris[*span].mastertrunkgroup);
10189          *span = -1;
10190       } else {
10191          if (si->totalchans == 31) {
10192             /* E1 */
10193             pris[*span].dchannels[0] = 16 + offset;
10194          } else if (si->totalchans == 24) {
10195             /* T1 or J1 */
10196             pris[*span].dchannels[0] = 24 + offset;
10197          } else if (si->totalchans == 3) {
10198             /* BRI */
10199             pris[*span].dchannels[0] = 3 + offset;
10200          } else {
10201             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);
10202             *span = -1;
10203             return 0;
10204          }
10205          pris[*span].dchanavail[0] |= DCHAN_PROVISIONED;
10206          pris[*span].offset = offset;
10207          pris[*span].span = *span + 1;
10208       }
10209    }
10210    return 0;
10211 }
10212 #endif   /* defined(HAVE_PRI) */
10213 
10214 #if defined(HAVE_PRI)
10215 static int pri_create_trunkgroup(int trunkgroup, int *channels)
10216 {
10217    struct dahdi_spaninfo si;
10218    struct dahdi_params p;
10219    int fd;
10220    int span;
10221    int ospan=0;
10222    int x,y;
10223    for (x = 0; x < NUM_SPANS; x++) {
10224       if (pris[x].trunkgroup == trunkgroup) {
10225          ast_log(LOG_WARNING, "Trunk group %d already exists on span %d, Primary d-channel %d\n", trunkgroup, x + 1, pris[x].dchannels[0]);
10226          return -1;
10227       }
10228    }
10229    for (y = 0; y < NUM_DCHANS; y++) {
10230       if (!channels[y])
10231          break;
10232       memset(&si, 0, sizeof(si));
10233       memset(&p, 0, sizeof(p));
10234       fd = open("/dev/dahdi/channel", O_RDWR);
10235       if (fd < 0) {
10236          ast_log(LOG_WARNING, "Failed to open channel: %s\n", strerror(errno));
10237          return -1;
10238       }
10239       x = channels[y];
10240       if (ioctl(fd, DAHDI_SPECIFY, &x)) {
10241          ast_log(LOG_WARNING, "Failed to specify channel %d: %s\n", channels[y], strerror(errno));
10242          close(fd);
10243          return -1;
10244       }
10245       if (ioctl(fd, DAHDI_GET_PARAMS, &p)) {
10246          ast_log(LOG_WARNING, "Failed to get channel parameters for channel %d: %s\n", channels[y], strerror(errno));
10247          return -1;
10248       }
10249       if (ioctl(fd, DAHDI_SPANSTAT, &si)) {
10250          ast_log(LOG_WARNING, "Failed go get span information on channel %d (span %d): %s\n", channels[y], p.spanno, strerror(errno));
10251          close(fd);
10252          return -1;
10253       }
10254       span = p.spanno - 1;
10255       if (pris[span].trunkgroup) {
10256          ast_log(LOG_WARNING, "Span %d is already provisioned for trunk group %d\n", span + 1, pris[span].trunkgroup);
10257          close(fd);
10258          return -1;
10259       }
10260       if (pris[span].pvts[0]) {
10261          ast_log(LOG_WARNING, "Span %d is already provisioned with channels (implicit PRI maybe?)\n", span + 1);
10262          close(fd);
10263          return -1;
10264       }
10265       if (!y) {
10266          pris[span].trunkgroup = trunkgroup;
10267          pris[span].offset = channels[y] - p.chanpos;
10268          ospan = span;
10269       }
10270       pris[ospan].dchannels[y] = channels[y];
10271       pris[ospan].dchanavail[y] |= DCHAN_PROVISIONED;
10272       pris[span].span = span + 1;
10273       close(fd);
10274    }
10275    return 0;
10276 }
10277 #endif   /* defined(HAVE_PRI) */
10278 
10279 #if defined(HAVE_PRI)
10280 static int pri_create_spanmap(int span, int trunkgroup, int logicalspan)
10281 {
10282    if (pris[span].mastertrunkgroup) {
10283       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);
10284       return -1;
10285    }
10286    pris[span].mastertrunkgroup = trunkgroup;
10287    pris[span].prilogicalspan = logicalspan;
10288    return 0;
10289 }
10290 #endif   /* defined(HAVE_PRI) */
10291 
10292 #if defined(HAVE_SS7)
10293 static unsigned int parse_pointcode(const char *pcstring)
10294 {
10295    unsigned int code1, code2, code3;
10296    int numvals;
10297 
10298    numvals = sscanf(pcstring, "%30d-%30d-%30d", &code1, &code2, &code3);
10299    if (numvals == 1)
10300       return code1;
10301    if (numvals == 3)
10302       return (code1 << 16) | (code2 << 8) | code3;
10303 
10304    return 0;
10305 }
10306 #endif   /* defined(HAVE_SS7) */
10307 
10308 #if defined(HAVE_SS7)
10309 static struct dahdi_ss7 * ss7_resolve_linkset(int linkset)
10310 {
10311    if ((linkset < 0) || (linkset >= NUM_SPANS))
10312       return NULL;
10313    else
10314       return &linksets[linkset - 1];
10315 }
10316 #endif   /* defined(HAVE_SS7) */
10317 
10318 #ifdef HAVE_OPENR2
10319 static void dahdi_r2_destroy_links(void)
10320 {
10321    int i = 0;
10322    if (!r2links) {
10323       return;
10324    }
10325    for (; i < r2links_count; i++) {
10326       if (r2links[i]->r2master != AST_PTHREADT_NULL) {
10327          pthread_cancel(r2links[i]->r2master);
10328          pthread_join(r2links[i]->r2master, NULL);
10329          openr2_context_delete(r2links[i]->protocol_context);
10330       }
10331       ast_free(r2links[i]);
10332    }
10333    ast_free(r2links);
10334    r2links = NULL;
10335    r2links_count = 0;
10336 }
10337 
10338 #define R2_LINK_CAPACITY 10
10339 static struct dahdi_mfcr2 *dahdi_r2_get_link(void)
10340 {
10341    struct dahdi_mfcr2 *new_r2link = NULL;
10342    struct dahdi_mfcr2 **new_r2links = NULL;
10343    /* this function is called just when starting up and no monitor threads have been launched,
10344       no need to lock monitored_count member */
10345    if (!r2links_count || (r2links[r2links_count - 1]->monitored_count == R2_LINK_CAPACITY)) {
10346       new_r2link = ast_calloc(1, sizeof(**r2links));
10347       if (!new_r2link) {
10348          ast_log(LOG_ERROR, "Cannot allocate R2 link!\n");
10349          return NULL;
10350       }
10351       new_r2links = ast_realloc(r2links, ((r2links_count + 1) * sizeof(*r2links)));
10352       if (!new_r2links) {
10353          ast_log(LOG_ERROR, "Cannot allocate R2 link!\n");
10354          ast_free(new_r2link);
10355          return NULL;
10356       }
10357       r2links = new_r2links;
10358       new_r2link->r2master = AST_PTHREADT_NULL;
10359       r2links[r2links_count] = new_r2link;
10360       r2links_count++;
10361       ast_log(LOG_DEBUG, "Created new R2 link!\n");
10362    }
10363    return r2links[r2links_count - 1];
10364 }
10365 
10366 static int dahdi_r2_set_context(struct dahdi_mfcr2 *r2_link, const struct dahdi_chan_conf *conf)
10367 {
10368    char tmplogdir[] = "/tmp";
10369    char logdir[OR2_MAX_PATH];
10370    int threshold = 0;
10371    int snres = 0;
10372    r2_link->protocol_context = openr2_context_new(NULL, &dahdi_r2_event_iface,
10373          &dahdi_r2_transcode_iface, conf->mfcr2.variant, conf->mfcr2.max_ani,
10374          conf->mfcr2.max_dnis);
10375    if (!r2_link->protocol_context) {
10376       return -1;
10377    }
10378    openr2_context_set_log_level(r2_link->protocol_context, conf->mfcr2.loglevel);
10379    openr2_context_set_ani_first(r2_link->protocol_context, conf->mfcr2.get_ani_first);
10380 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
10381    openr2_context_set_skip_category_request(r2_link->protocol_context, conf->mfcr2.skip_category_request);
10382 #endif
10383    openr2_context_set_mf_threshold(r2_link->protocol_context, threshold);
10384    openr2_context_set_mf_back_timeout(r2_link->protocol_context, conf->mfcr2.mfback_timeout);
10385    openr2_context_set_metering_pulse_timeout(r2_link->protocol_context, conf->mfcr2.metering_pulse_timeout);
10386    openr2_context_set_double_answer(r2_link->protocol_context, conf->mfcr2.double_answer);
10387    openr2_context_set_immediate_accept(r2_link->protocol_context, conf->mfcr2.immediate_accept);
10388    if (ast_strlen_zero(conf->mfcr2.logdir)) {
10389       if (openr2_context_set_log_directory(r2_link->protocol_context, tmplogdir)) {
10390          ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir);
10391       }
10392    } else {
10393       snres = snprintf(logdir, sizeof(logdir), "%s/%s/%s", ast_config_AST_LOG_DIR, "mfcr2", conf->mfcr2.logdir);
10394       if (snres >= sizeof(logdir)) {
10395          ast_log(LOG_ERROR, "MFC/R2 logging directory truncated, using %s\n", tmplogdir);
10396          if (openr2_context_set_log_directory(r2_link->protocol_context, tmplogdir)) {
10397             ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir);
10398          }
10399       } else {
10400          if (openr2_context_set_log_directory(r2_link->protocol_context, logdir)) {
10401             ast_log(LOG_ERROR, "Failed setting MFC/R2 log directory %s\n", logdir);
10402          }
10403       }
10404    }
10405    if (!ast_strlen_zero(conf->mfcr2.r2proto_file)) {
10406       if (openr2_context_configure_from_advanced_file(r2_link->protocol_context, conf->mfcr2.r2proto_file)) {
10407          ast_log(LOG_ERROR, "Failed to configure r2context from advanced configuration file %s\n", conf->mfcr2.r2proto_file);
10408       }
10409    }
10410    r2_link->monitored_count = 0;
10411    return 0;
10412 }
10413 #endif
10414 
10415 /* converts a DAHDI sigtype to signalling as can be configured from
10416  * chan_dahdi.conf.
10417  * While both have basically the same values, this will later be the
10418  * place to add filters and sanity checks
10419  */
10420 static int sigtype_to_signalling(int sigtype)
10421 {
10422    return sigtype;
10423 }
10424 
10425 static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf, struct dahdi_pri *pri, int reloading)
10426 {
10427    /* Make a dahdi_pvt structure for this interface (or CRV if "pri" is specified) */
10428    struct dahdi_pvt *tmp = NULL, *tmp2, *prev = NULL;
10429    char fn[80];
10430    struct dahdi_bufferinfo bi;
10431 
10432    int res;
10433    int span = 0;
10434    int here = 0;
10435    int x;
10436    struct dahdi_pvt **wlist;
10437    struct dahdi_pvt **wend;
10438    struct dahdi_params p;
10439 
10440    wlist = &iflist;
10441    wend = &ifend;
10442 
10443 #ifdef HAVE_PRI
10444    if (pri) {
10445       wlist = &pri->crvs;
10446       wend = &pri->crvend;
10447    }
10448 #endif
10449 
10450    tmp2 = *wlist;
10451    prev = NULL;
10452 
10453    while (tmp2) {
10454       if (!tmp2->destroy) {
10455          if (tmp2->channel == channel) {
10456             tmp = tmp2;
10457             here = 1;
10458             break;
10459          }
10460          if (tmp2->channel > channel) {
10461             break;
10462          }
10463       }
10464       prev = tmp2;
10465       tmp2 = tmp2->next;
10466    }
10467 
10468    if (!here && reloading != 1) {
10469       if (!(tmp = ast_calloc(1, sizeof(*tmp)))) {
10470          if (tmp)
10471             free(tmp);
10472          return NULL;
10473       }
10474       ast_mutex_init(&tmp->lock);
10475       ifcount++;
10476       for (x = 0; x < 3; x++)
10477          tmp->subs[x].dfd = -1;
10478       tmp->channel = channel;
10479       tmp->priindication_oob = conf->chan.priindication_oob;
10480    }
10481 
10482    if (tmp) {
10483       int chan_sig = conf->chan.sig;
10484       if (!here) {
10485          if ((channel != CHAN_PSEUDO) && !pri) {
10486             int count = 0;
10487             snprintf(fn, sizeof(fn), "%d", channel);
10488             /* Open non-blocking */
10489             tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
10490             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 */
10491                usleep(1);
10492                tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
10493                count++;
10494             }
10495             /* Allocate a DAHDI structure */
10496             if (tmp->subs[SUB_REAL].dfd < 0) {
10497                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);
10498                destroy_dahdi_pvt(&tmp);
10499                return NULL;
10500             }
10501             memset(&p, 0, sizeof(p));
10502             res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
10503             if (res < 0) {
10504                ast_log(LOG_ERROR, "Unable to get parameters: %s\n", strerror(errno));
10505                destroy_dahdi_pvt(&tmp);
10506                return NULL;
10507             }
10508             if (conf->is_sig_auto)
10509                chan_sig = sigtype_to_signalling(p.sigtype);
10510             if (p.sigtype != (chan_sig & 0x3ffff)) {
10511                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));
10512                destroy_dahdi_pvt(&tmp);
10513                return NULL;
10514             }
10515             tmp->law = p.curlaw;
10516             tmp->span = p.spanno;
10517             span = p.spanno - 1;
10518          } else {
10519             if (channel == CHAN_PSEUDO)
10520                chan_sig = 0;
10521             else if ((chan_sig != SIG_FXOKS) && (chan_sig != SIG_FXSKS)) {
10522                ast_log(LOG_ERROR, "CRV's must use FXO/FXS Kewl Start (fxo_ks/fxs_ks) signalling only.\n");
10523                return NULL;
10524             }
10525          }
10526          tmp->outsigmod = conf->chan.outsigmod;
10527 
10528 #ifdef HAVE_SS7
10529          if (chan_sig == SIG_SS7) {
10530             struct dahdi_ss7 *ss7;
10531             int clear = 0;
10532             if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &clear)) {
10533                ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
10534                destroy_dahdi_pvt(&tmp);
10535                return NULL;
10536             }
10537 
10538             ss7 = ss7_resolve_linkset(cur_linkset);
10539             if (!ss7) {
10540                ast_log(LOG_ERROR, "Unable to find linkset %d\n", cur_linkset);
10541                destroy_dahdi_pvt(&tmp);
10542                return NULL;
10543             }
10544             if (cur_cicbeginswith < 0) {
10545                ast_log(LOG_ERROR, "Need to set cicbeginswith for the channels!\n");
10546                destroy_dahdi_pvt(&tmp);
10547                return NULL;
10548             }
10549 
10550             tmp->cic = cur_cicbeginswith++;
10551 
10552             /* DB: Add CIC's DPC information */
10553             tmp->dpc = cur_defaultdpc;
10554 
10555             tmp->ss7 = ss7;
10556             tmp->ss7call = NULL;
10557             ss7->pvts[ss7->numchans++] = tmp;
10558 
10559             ast_copy_string(ss7->internationalprefix, conf->ss7.internationalprefix, sizeof(ss7->internationalprefix));
10560             ast_copy_string(ss7->nationalprefix, conf->ss7.nationalprefix, sizeof(ss7->nationalprefix));
10561             ast_copy_string(ss7->subscriberprefix, conf->ss7.subscriberprefix, sizeof(ss7->subscriberprefix));
10562             ast_copy_string(ss7->unknownprefix, conf->ss7.unknownprefix, sizeof(ss7->unknownprefix));
10563 
10564             ss7->called_nai = conf->ss7.called_nai;
10565             ss7->calling_nai = conf->ss7.calling_nai;
10566          }
10567 #endif
10568 #ifdef HAVE_OPENR2
10569          if (chan_sig == SIG_MFCR2 && reloading != 1) {
10570             struct dahdi_mfcr2 *r2_link;
10571             r2_link = dahdi_r2_get_link();
10572             if (!r2_link) {
10573                ast_log(LOG_WARNING, "Cannot get another R2 DAHDI context!\n");
10574                destroy_dahdi_pvt(&tmp);
10575                return NULL;
10576             }
10577             if (!r2_link->protocol_context && dahdi_r2_set_context(r2_link, conf)) {
10578                ast_log(LOG_ERROR, "Cannot create OpenR2 protocol context.\n");
10579                destroy_dahdi_pvt(&tmp);
10580                return NULL;
10581             }
10582             if (r2_link->numchans == (sizeof(r2_link->pvts)/sizeof(r2_link->pvts[0]))) {
10583                ast_log(LOG_ERROR, "Cannot add more channels to this link!\n");
10584                destroy_dahdi_pvt(&tmp);
10585                return NULL;
10586             }
10587             r2_link->pvts[r2_link->numchans++] = tmp;
10588             tmp->r2chan = openr2_chan_new_from_fd(r2_link->protocol_context,
10589                                         tmp->subs[SUB_REAL].dfd,
10590                                         NULL, NULL);
10591             if (!tmp->r2chan) {
10592                openr2_liberr_t err = openr2_context_get_last_error(r2_link->protocol_context);
10593                ast_log(LOG_ERROR, "Cannot create OpenR2 channel: %s\n", openr2_context_error_string(err));
10594                destroy_dahdi_pvt(&tmp);
10595                return NULL;
10596             }
10597             tmp->mfcr2 = r2_link;
10598             if (conf->mfcr2.call_files) {
10599                openr2_chan_enable_call_files(tmp->r2chan);
10600             }
10601             openr2_chan_set_client_data(tmp->r2chan, tmp);
10602             /* cast seems to be needed to get rid of the annoying warning regarding format attribute  */
10603             openr2_chan_set_logging_func(tmp->r2chan, (openr2_logging_func_t)dahdi_r2_on_chan_log);
10604             openr2_chan_set_log_level(tmp->r2chan, conf->mfcr2.loglevel);
10605             tmp->mfcr2_category = conf->mfcr2.category;
10606             tmp->mfcr2_charge_calls = conf->mfcr2.charge_calls;
10607             tmp->mfcr2_allow_collect_calls = conf->mfcr2.allow_collect_calls;
10608             tmp->mfcr2_forced_release = conf->mfcr2.forced_release;
10609             tmp->mfcr2_accept_on_offer = conf->mfcr2.accept_on_offer;
10610             tmp->mfcr2call = 0;
10611             tmp->mfcr2_dnis_index = 0;
10612             tmp->mfcr2_ani_index = 0;
10613             r2_link->monitored_count++;
10614          }
10615 #endif
10616 #ifdef HAVE_PRI
10617          if ((chan_sig == SIG_PRI) || (chan_sig == SIG_BRI) || (chan_sig == SIG_BRI_PTMP) || (chan_sig == SIG_GR303FXOKS) || (chan_sig == SIG_GR303FXSKS)) {
10618             int offset;
10619             int myswitchtype;
10620             int matchesdchan;
10621             int x,y;
10622             offset = 0;
10623             if (((chan_sig == SIG_PRI) || (chan_sig == SIG_BRI) || (chan_sig == SIG_BRI_PTMP))
10624                   && ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &offset)) {
10625                ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
10626                destroy_dahdi_pvt(&tmp);
10627                return NULL;
10628             }
10629             if (span >= NUM_SPANS) {
10630                ast_log(LOG_ERROR, "Channel %d does not lie on a span I know of (%d)\n", channel, span);
10631                destroy_dahdi_pvt(&tmp);
10632                return NULL;
10633             } else {
10634                struct dahdi_spaninfo si;
10635                si.spanno = 0;
10636                if (ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SPANSTAT,&si) == -1) {
10637                   ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno));
10638                   destroy_dahdi_pvt(&tmp);
10639                   return NULL;
10640                }
10641                /* Store the logical span first based upon the real span */
10642                tmp->logicalspan = pris[span].prilogicalspan;
10643                pri_resolve_span(&span, channel, (channel - p.chanpos), &si);
10644                if (span < 0) {
10645                   ast_log(LOG_WARNING, "Channel %d: Unable to find locate channel/trunk group!\n", channel);
10646                   destroy_dahdi_pvt(&tmp);
10647                   return NULL;
10648                }
10649                if ((chan_sig == SIG_PRI) ||
10650                      (chan_sig == SIG_BRI) ||
10651                      (chan_sig == SIG_BRI_PTMP))
10652                   myswitchtype = conf->pri.switchtype;
10653                else
10654                   myswitchtype = PRI_SWITCH_GR303_TMC;
10655                /* Make sure this isn't a d-channel */
10656                matchesdchan=0;
10657                for (x = 0; x < NUM_SPANS; x++) {
10658                   for (y = 0; y < NUM_DCHANS; y++) {
10659                      if (pris[x].dchannels[y] == tmp->channel) {
10660                         matchesdchan = 1;
10661                         break;
10662                      }
10663                   }
10664                }
10665                offset = p.chanpos;
10666                if (!matchesdchan) {
10667                   if (pris[span].nodetype && (pris[span].nodetype != conf->pri.nodetype)) {
10668                      ast_log(LOG_ERROR, "Span %d is already a %s node\n", span + 1, pri_node2str(pris[span].nodetype));
10669                      destroy_dahdi_pvt(&tmp);
10670                      return NULL;
10671                   }
10672                   if (pris[span].switchtype && (pris[span].switchtype != myswitchtype)) {
10673                      ast_log(LOG_ERROR, "Span %d is already a %s switch\n", span + 1, pri_switch2str(pris[span].switchtype));
10674                      destroy_dahdi_pvt(&tmp);
10675                      return NULL;
10676                   }
10677                   if ((pris[span].dialplan) && (pris[span].dialplan != conf->pri.dialplan)) {
10678                      ast_log(LOG_ERROR, "Span %d is already a %s dialing plan\n", span + 1, dialplan2str(pris[span].dialplan));
10679                      destroy_dahdi_pvt(&tmp);
10680                      return NULL;
10681                   }
10682                   if (!ast_strlen_zero(pris[span].idledial) && strcmp(pris[span].idledial, conf->pri.idledial)) {
10683                      ast_log(LOG_ERROR, "Span %d already has idledial '%s'.\n", span + 1, conf->pri.idledial);
10684                      destroy_dahdi_pvt(&tmp);
10685                      return NULL;
10686                   }
10687                   if (!ast_strlen_zero(pris[span].idleext) && strcmp(pris[span].idleext, conf->pri.idleext)) {
10688                      ast_log(LOG_ERROR, "Span %d already has idleext '%s'.\n", span + 1, conf->pri.idleext);
10689                      destroy_dahdi_pvt(&tmp);
10690                      return NULL;
10691                   }
10692                   if (pris[span].minunused && (pris[span].minunused != conf->pri.minunused)) {
10693                      ast_log(LOG_ERROR, "Span %d already has minunused of %d.\n", span + 1, conf->pri.minunused);
10694                      destroy_dahdi_pvt(&tmp);
10695                      return NULL;
10696                   }
10697                   if (pris[span].minidle && (pris[span].minidle != conf->pri.minidle)) {
10698                      ast_log(LOG_ERROR, "Span %d already has minidle of %d.\n", span + 1, conf->pri.minidle);
10699                      destroy_dahdi_pvt(&tmp);
10700                      return NULL;
10701                   }
10702                   if (pris[span].numchans >= MAX_CHANNELS) {
10703                      ast_log(LOG_ERROR, "Unable to add channel %d: Too many channels in trunk group %d!\n", channel,
10704                         pris[span].trunkgroup);
10705                      destroy_dahdi_pvt(&tmp);
10706                      return NULL;
10707                   }
10708 
10709                   pris[span].sig = chan_sig;
10710                   pris[span].nodetype = conf->pri.nodetype;
10711                   pris[span].switchtype = myswitchtype;
10712                   pris[span].nsf = conf->pri.nsf;
10713                   pris[span].dialplan = conf->pri.dialplan;
10714                   pris[span].localdialplan = conf->pri.localdialplan;
10715                   pris[span].pvts[pris[span].numchans++] = tmp;
10716                   pris[span].minunused = conf->pri.minunused;
10717                   pris[span].minidle = conf->pri.minidle;
10718                   pris[span].overlapdial = conf->pri.overlapdial;
10719                   pris[span].qsigchannelmapping = conf->pri.qsigchannelmapping;
10720                   pris[span].discardremoteholdretrieval = conf->pri.discardremoteholdretrieval;
10721 #ifdef HAVE_PRI_INBANDDISCONNECT
10722                   pris[span].inbanddisconnect = conf->pri.inbanddisconnect;
10723 #endif
10724                   pris[span].facilityenable = conf->pri.facilityenable;
10725                   ast_copy_string(pris[span].idledial, conf->pri.idledial, sizeof(pris[span].idledial));
10726                   ast_copy_string(pris[span].idleext, conf->pri.idleext, sizeof(pris[span].idleext));
10727                   ast_copy_string(pris[span].internationalprefix, conf->pri.internationalprefix, sizeof(pris[span].internationalprefix));
10728                   ast_copy_string(pris[span].nationalprefix, conf->pri.nationalprefix, sizeof(pris[span].nationalprefix));
10729                   ast_copy_string(pris[span].localprefix, conf->pri.localprefix, sizeof(pris[span].localprefix));
10730                   ast_copy_string(pris[span].privateprefix, conf->pri.privateprefix, sizeof(pris[span].privateprefix));
10731                   ast_copy_string(pris[span].unknownprefix, conf->pri.unknownprefix, sizeof(pris[span].unknownprefix));
10732                   pris[span].resetinterval = conf->pri.resetinterval;
10733 
10734                   tmp->pri = &pris[span];
10735                   tmp->prioffset = offset;
10736                   tmp->call = NULL;
10737 
10738                   tmp->priexclusive = conf->chan.priexclusive;
10739                } else {
10740                   ast_log(LOG_ERROR, "Channel %d is reserved for D-channel.\n", offset);
10741                   destroy_dahdi_pvt(&tmp);
10742                   return NULL;
10743                }
10744             }
10745          } else {
10746             tmp->prioffset = 0;
10747          }
10748 #endif
10749       } else {
10750          chan_sig = tmp->sig;
10751          if (tmp->subs[SUB_REAL].dfd > -1) {
10752             memset(&p, 0, sizeof(p));
10753             res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
10754          }
10755       }
10756       /* Adjust starttime on loopstart and kewlstart trunks to reasonable values */
10757       switch (chan_sig) {
10758       case SIG_FXSKS:
10759       case SIG_FXSLS:
10760       case SIG_EM:
10761       case SIG_EM_E1:
10762       case SIG_EMWINK:
10763       case SIG_FEATD:
10764       case SIG_FEATDMF:
10765       case SIG_FEATDMF_TA:
10766       case SIG_FEATB:
10767       case SIG_E911:
10768       case SIG_SF:
10769       case SIG_SFWINK:
10770       case SIG_FGC_CAMA:
10771       case SIG_FGC_CAMAMF:
10772       case SIG_SF_FEATD:
10773       case SIG_SF_FEATDMF:
10774       case SIG_SF_FEATB:
10775          p.starttime = 250;
10776          break;
10777       }
10778 
10779       if (tmp->radio) {
10780          /* XXX Waiting to hear back from Jim if these should be adjustable XXX */
10781          p.channo = channel;
10782          p.rxwinktime = 1;
10783          p.rxflashtime = 1;
10784          p.starttime = 1;
10785          p.debouncetime = 5;
10786       }
10787       if (!tmp->radio) {
10788          p.channo = channel;
10789          /* Override timing settings based on config file */
10790          if (conf->timing.prewinktime >= 0)
10791             p.prewinktime = conf->timing.prewinktime;
10792          if (conf->timing.preflashtime >= 0)
10793             p.preflashtime = conf->timing.preflashtime;
10794          if (conf->timing.winktime >= 0)
10795             p.winktime = conf->timing.winktime;
10796          if (conf->timing.flashtime >= 0)
10797             p.flashtime = conf->timing.flashtime;
10798          if (conf->timing.starttime >= 0)
10799             p.starttime = conf->timing.starttime;
10800          if (conf->timing.rxwinktime >= 0)
10801             p.rxwinktime = conf->timing.rxwinktime;
10802          if (conf->timing.rxflashtime >= 0)
10803             p.rxflashtime = conf->timing.rxflashtime;
10804          if (conf->timing.debouncetime >= 0)
10805             p.debouncetime = conf->timing.debouncetime;
10806       }
10807 
10808       /* dont set parms on a pseudo-channel (or CRV) */
10809       if (tmp->subs[SUB_REAL].dfd >= 0)
10810       {
10811          res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_PARAMS, &p);
10812          if (res < 0) {
10813             ast_log(LOG_ERROR, "Unable to set parameters: %s\n", strerror(errno));
10814             destroy_dahdi_pvt(&tmp);
10815             return NULL;
10816          }
10817       }
10818 #if 1
10819       if (!here && (tmp->subs[SUB_REAL].dfd > -1)) {
10820          memset(&bi, 0, sizeof(bi));
10821          res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
10822          if (!res) {
10823             bi.txbufpolicy = conf->chan.buf_policy;
10824             bi.rxbufpolicy = conf->chan.buf_policy;
10825             bi.numbufs = conf->chan.buf_no;
10826             res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
10827             if (res < 0) {
10828                ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", channel, strerror(errno));
10829             }
10830          } else {
10831             ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", channel, strerror(errno));
10832          }
10833          tmp->buf_policy = conf->chan.buf_policy;
10834          tmp->buf_no = conf->chan.buf_no;
10835          tmp->usefaxbuffers = conf->chan.usefaxbuffers;
10836          tmp->faxbuf_policy = conf->chan.faxbuf_policy;
10837          tmp->faxbuf_no = conf->chan.faxbuf_no;
10838          /* This is not as gnarly as it may first appear.  If the ioctl above failed, we'd be setting
10839           * tmp->bufsize to zero which would cause subsequent faxbuffer-related ioctl calls to fail.
10840           * The reason the ioctl call above failed should to be determined before worrying about the
10841           * faxbuffer-related ioctl calls */
10842          tmp->bufsize = bi.bufsize;
10843       }
10844 #endif
10845       tmp->immediate = conf->chan.immediate;
10846       tmp->transfertobusy = conf->chan.transfertobusy;
10847       if (chan_sig & __DAHDI_SIG_FXS) {
10848          tmp->mwimonitor_fsk = conf->chan.mwimonitor_fsk;
10849          tmp->mwimonitor_neon = conf->chan.mwimonitor_neon;
10850          tmp->mwimonitor_rpas = conf->chan.mwimonitor_rpas;
10851       }
10852       tmp->sig = chan_sig;
10853       tmp->ringt_base = ringt_base;
10854       tmp->firstradio = 0;
10855       if ((chan_sig == SIG_FXOKS) || (chan_sig == SIG_FXOLS) || (chan_sig == SIG_FXOGS))
10856          tmp->permcallwaiting = conf->chan.callwaiting;
10857       else
10858          tmp->permcallwaiting = 0;
10859       /* Flag to destroy the channel must be cleared on new mkif.  Part of changes for reload to work */
10860       tmp->destroy = 0;
10861       tmp->drings = conf->chan.drings;
10862 
10863       /* 10 is a nice default. */
10864       if (tmp->drings.ringnum[0].range == 0)
10865          tmp->drings.ringnum[0].range = 10;
10866       if (tmp->drings.ringnum[1].range == 0)
10867          tmp->drings.ringnum[1].range = 10;
10868       if (tmp->drings.ringnum[2].range == 0)
10869          tmp->drings.ringnum[2].range = 10;
10870 
10871       tmp->usedistinctiveringdetection = usedistinctiveringdetection;
10872       tmp->callwaitingcallerid = conf->chan.callwaitingcallerid;
10873       tmp->threewaycalling = conf->chan.threewaycalling;
10874       tmp->adsi = conf->chan.adsi;
10875       tmp->use_smdi = conf->chan.use_smdi;
10876       tmp->permhidecallerid = conf->chan.hidecallerid;
10877       tmp->hidecalleridname = conf->chan.hidecalleridname;
10878       tmp->callreturn = conf->chan.callreturn;
10879       tmp->echocancel = conf->chan.echocancel;
10880       tmp->echotraining = conf->chan.echotraining;
10881       tmp->pulse = conf->chan.pulse;
10882       if (tmp->echocancel.head.tap_length) {
10883          tmp->echocanbridged = conf->chan.echocanbridged;
10884       } else {
10885          if (conf->chan.echocanbridged)
10886             ast_log(LOG_NOTICE, "echocancelwhenbridged requires echocancel to be enabled; ignoring\n");
10887          tmp->echocanbridged = 0;
10888       }
10889       tmp->busydetect = conf->chan.busydetect;
10890       tmp->busycount = conf->chan.busycount;
10891       tmp->busy_tonelength = conf->chan.busy_tonelength;
10892       tmp->busy_quietlength = conf->chan.busy_quietlength;
10893       tmp->callprogress = conf->chan.callprogress;
10894       tmp->waitfordialtone = conf->chan.waitfordialtone;
10895       tmp->cancallforward = conf->chan.cancallforward;
10896       tmp->dtmfrelax = conf->chan.dtmfrelax;
10897       tmp->callwaiting = tmp->permcallwaiting;
10898       tmp->hidecallerid = tmp->permhidecallerid;
10899       tmp->channel = channel;
10900       tmp->stripmsd = conf->chan.stripmsd;
10901       tmp->use_callerid = conf->chan.use_callerid;
10902       tmp->cid_signalling = conf->chan.cid_signalling;
10903       tmp->cid_start = conf->chan.cid_start;
10904       tmp->dahditrcallerid = conf->chan.dahditrcallerid;
10905       tmp->restrictcid = conf->chan.restrictcid;
10906       tmp->use_callingpres = conf->chan.use_callingpres;
10907       if (tmp->usedistinctiveringdetection) {
10908          if (!tmp->use_callerid) {
10909             ast_log(LOG_NOTICE, "Distinctive Ring detect requires 'usecallerid' be on\n");
10910             tmp->use_callerid = 1;
10911          }
10912       }
10913 
10914       if (tmp->cid_signalling == CID_SIG_SMDI) {
10915          if (!tmp->use_smdi) {
10916             ast_log(LOG_WARNING, "SMDI callerid requires SMDI to be enabled, enabling...\n");
10917             tmp->use_smdi = 1;
10918          }
10919       }
10920       if (tmp->use_smdi) {
10921          tmp->smdi_iface = ast_smdi_interface_find(conf->smdi_port);
10922          if (!(tmp->smdi_iface)) {
10923             ast_log(LOG_ERROR, "Invalid SMDI port specfied, disabling SMDI support\n");
10924             tmp->use_smdi = 0;
10925          }
10926       }
10927 
10928       ast_copy_string(tmp->accountcode, conf->chan.accountcode, sizeof(tmp->accountcode));
10929       tmp->amaflags = conf->chan.amaflags;
10930       if (!here) {
10931          tmp->confno = -1;
10932          tmp->propconfno = -1;
10933       }
10934       tmp->canpark = conf->chan.canpark;
10935       tmp->transfer = conf->chan.transfer;
10936       ast_copy_string(tmp->defcontext,conf->chan.context,sizeof(tmp->defcontext));
10937       ast_copy_string(tmp->language, conf->chan.language, sizeof(tmp->language));
10938       ast_copy_string(tmp->mohinterpret, conf->chan.mohinterpret, sizeof(tmp->mohinterpret));
10939       ast_copy_string(tmp->mohsuggest, conf->chan.mohsuggest, sizeof(tmp->mohsuggest));
10940       ast_copy_string(tmp->context, conf->chan.context, sizeof(tmp->context));
10941       ast_copy_string(tmp->parkinglot, conf->chan.parkinglot, sizeof(tmp->parkinglot));
10942       tmp->cid_ton = 0;
10943       switch (tmp->sig) {
10944       case SIG_PRI:
10945       case SIG_BRI:
10946       case SIG_BRI_PTMP:
10947       case SIG_SS7:
10948       case SIG_MFCR2:
10949          tmp->cid_num[0] = '\0';
10950          tmp->cid_name[0] = '\0';
10951          break;
10952       default:
10953          ast_copy_string(tmp->cid_num, conf->chan.cid_num, sizeof(tmp->cid_num));
10954          ast_copy_string(tmp->cid_name, conf->chan.cid_name, sizeof(tmp->cid_name));
10955          break;
10956       }
10957       ast_copy_string(tmp->mailbox, conf->chan.mailbox, sizeof(tmp->mailbox));
10958       if (channel != CHAN_PSEUDO && !ast_strlen_zero(tmp->mailbox)) {
10959          char *mailbox, *context;
10960          mailbox = context = ast_strdupa(tmp->mailbox);
10961          strsep(&context, "@");
10962          if (ast_strlen_zero(context))
10963             context = "default";
10964          tmp->mwi_event_sub = ast_event_subscribe(AST_EVENT_MWI, mwi_event_cb, NULL,
10965             AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
10966             AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
10967             AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS,
10968             AST_EVENT_IE_END);
10969       }
10970       tmp->msgstate = -1;
10971 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
10972       tmp->mwisend_setting = conf->chan.mwisend_setting;
10973       tmp->mwisend_fsk  = conf->chan.mwisend_fsk;
10974       tmp->mwisend_rpas = conf->chan.mwisend_rpas;
10975 #endif
10976       if (chan_sig & __DAHDI_SIG_FXO) {
10977          memset(&p, 0, sizeof(p));
10978          res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
10979          if (!res) {
10980             tmp->fxsoffhookstate = p.rxisoffhook;
10981          }
10982 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
10983          res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_VMWI_CONFIG, &tmp->mwisend_setting);
10984 #endif
10985       }
10986       tmp->onhooktime = time(NULL);
10987       tmp->group = conf->chan.group;
10988       tmp->callgroup = conf->chan.callgroup;
10989       tmp->pickupgroup= conf->chan.pickupgroup;
10990       if (conf->chan.vars) {
10991          struct ast_variable *v, *tmpvar;
10992                    for (v = conf->chan.vars ; v ; v = v->next) {
10993                          if ((tmpvar = ast_variable_new(v->name, v->value, v->file))) {
10994                                   tmpvar->next = tmp->vars;
10995                                    tmp->vars = tmpvar;
10996                            }
10997                   }
10998       }
10999       tmp->cid_rxgain = conf->chan.cid_rxgain;
11000       tmp->rxgain = conf->chan.rxgain;
11001       tmp->txgain = conf->chan.txgain;
11002       tmp->tonezone = conf->chan.tonezone;
11003       if (tmp->subs[SUB_REAL].dfd > -1) {
11004          set_actual_gain(tmp->subs[SUB_REAL].dfd, 0, tmp->rxgain, tmp->txgain, tmp->law);
11005          if (tmp->dsp)
11006             ast_dsp_set_digitmode(tmp->dsp, DSP_DIGITMODE_DTMF | tmp->dtmfrelax);
11007          update_conf(tmp);
11008          if (!here) {
11009             if ((chan_sig != SIG_BRI) && (chan_sig != SIG_BRI_PTMP) && (chan_sig != SIG_PRI)
11010                 && (chan_sig != SIG_SS7) && (chan_sig != SIG_MFCR2))
11011                /* Hang it up to be sure it's good */
11012                dahdi_set_hook(tmp->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
11013          }
11014          ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SETTONEZONE,&tmp->tonezone);
11015 #ifdef HAVE_PRI
11016          /* the dchannel is down so put the channel in alarm */
11017          if (tmp->pri && !pri_is_up(tmp->pri))
11018             tmp->inalarm = 1;
11019 #endif
11020          if ((res = get_alarms(tmp)) != DAHDI_ALARM_NONE) {
11021             tmp->inalarm = 1;
11022             handle_alarms(tmp, res);
11023          }
11024       }
11025 
11026       tmp->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
11027       tmp->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
11028       tmp->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
11029       tmp->sendcalleridafter = conf->chan.sendcalleridafter;
11030       if (!here) {
11031          tmp->locallyblocked = tmp->remotelyblocked = 0;
11032          if ((chan_sig == SIG_PRI) || (chan_sig == SIG_BRI) || (chan_sig == SIG_BRI_PTMP) || (chan_sig == SIG_SS7))
11033             tmp->inservice = 0;
11034          else /* We default to in service on protocols that don't have a reset */
11035             tmp->inservice = 1;
11036       }
11037    }
11038    if (tmp && !here) {
11039       /* nothing on the iflist */
11040       if (!*wlist) {
11041          *wlist = tmp;
11042          tmp->prev = NULL;
11043          tmp->next = NULL;
11044          *wend = tmp;
11045       } else {
11046          /* at least one member on the iflist */
11047          struct dahdi_pvt *working = *wlist;
11048 
11049          /* check if we maybe have to put it on the begining */
11050          if (working->channel > tmp->channel) {
11051             tmp->next = *wlist;
11052             tmp->prev = NULL;
11053             (*wlist)->prev = tmp;
11054             *wlist = tmp;
11055          } else {
11056          /* go through all the members and put the member in the right place */
11057             while (working) {
11058                /* in the middle */
11059                if (working->next) {
11060                   if (working->channel < tmp->channel && working->next->channel > tmp->channel) {
11061                      tmp->next = working->next;
11062                      tmp->prev = working;
11063                      working->next->prev = tmp;
11064                      working->next = tmp;
11065                      break;
11066                   }
11067                } else {
11068                /* the last */
11069                   if (working->channel < tmp->channel) {
11070                      working->next = tmp;
11071                      tmp->next = NULL;
11072                      tmp->prev = working;
11073                      *wend = tmp;
11074                      break;
11075                   }
11076                }
11077                working = working->next;
11078             }
11079          }
11080       }
11081    }
11082    return tmp;
11083 }
11084 
11085 static inline int available(struct dahdi_pvt *p, int channelmatch, ast_group_t groupmatch, int *busy, int *channelmatched, int *groupmatched)
11086 {
11087    int res;
11088    struct dahdi_params par;
11089 
11090    /* First, check group matching */
11091    if (groupmatch) {
11092       if ((p->group & groupmatch) != groupmatch)
11093          return 0;
11094       *groupmatched = 1;
11095    }
11096    /* Check to see if we have a channel match */
11097    if (channelmatch != -1) {
11098       if (p->channel != channelmatch)
11099          return 0;
11100       *channelmatched = 1;
11101    }
11102    /* We're at least busy at this point */
11103    if (busy) {
11104       if ((p->sig == SIG_FXOKS) || (p->sig == SIG_FXOLS) || (p->sig == SIG_FXOGS))
11105          *busy = 1;
11106    }
11107    /* If do not disturb, definitely not */
11108    if (p->dnd)
11109       return 0;
11110    /* If guard time, definitely not */
11111    if (p->guardtime && (time(NULL) < p->guardtime))
11112       return 0;
11113 
11114    if (p->locallyblocked || p->remotelyblocked)
11115       return 0;
11116 
11117    /* If no owner definitely available */
11118    if (!p->owner) {
11119 #ifdef HAVE_PRI
11120       /* Trust PRI */
11121       if (p->pri) {
11122          if (p->resetting || p->call)
11123             return 0;
11124          else
11125             return 1;
11126       }
11127 #endif
11128 #ifdef HAVE_SS7
11129       /* Trust SS7 */
11130       if (p->ss7) {
11131          if (p->ss7call)
11132             return 0;
11133          else
11134             return 1;
11135       }
11136 #endif
11137 #ifdef HAVE_OPENR2
11138       /* Trust MFC/R2 */
11139       if (p->mfcr2) {
11140          if (p->mfcr2call)
11141             return 0;
11142          else
11143             return 1;
11144       }
11145 #endif
11146 
11147       /* Trust hook state */
11148       if (p->sig && !(p->radio || (p->oprmode < 0)))
11149       {
11150          /* Check hook state */
11151          if (p->subs[SUB_REAL].dfd > -1) {
11152             memset(&par, 0, sizeof(par));
11153             res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
11154          } else {
11155             /* Assume not off hook on CVRS */
11156             res = 0;
11157             par.rxisoffhook = 0;
11158          }
11159 
11160          if (res) {
11161             ast_log(LOG_WARNING, "Unable to check hook state on channel %d: %s\n", p->channel, strerror(errno));
11162          }
11163          else if ((p->sig != SIG_FXSKS) && (p->sig != SIG_FXSGS) && (p->sig != SIG_FXSLS)) {
11164             if (par.rxisoffhook) {
11165                ast_debug(1, "Channel %d off hook, can't use\n", p->channel);
11166                /* Not available when the other end is off hook */
11167                return 0;
11168             }
11169          }
11170 #ifdef DAHDI_CHECK_HOOKSTATE
11171          } else { /* FXO channel case (SIG_FXS--) */
11172             /* Channel bank (using CAS), "onhook" does not necessarily means out of service, so return 1 */
11173             if (par.rxbits > -1)
11174                return 1;
11175             /* TDM FXO card, "onhook" means out of service (no battery on the line) */
11176             if (par.rxisoffhook)
11177                return 1;
11178             else
11179                return 0;
11180 #endif
11181       }
11182 
11183       return 1;
11184    }
11185 
11186    /* If it's not an FXO, forget about call wait */
11187    if ((p->sig != SIG_FXOKS) && (p->sig != SIG_FXOLS) && (p->sig != SIG_FXOGS))
11188       return 0;
11189 
11190    if (!p->callwaiting) {
11191       /* If they don't have call waiting enabled, then for sure they're unavailable at this point */
11192       return 0;
11193    }
11194 
11195    if (p->subs[SUB_CALLWAIT].dfd > -1) {
11196       /* If there is already a call waiting call, then we can't take a second one */
11197       return 0;
11198    }
11199 
11200    if ((p->owner->_state != AST_STATE_UP) &&
11201       ((p->owner->_state != AST_STATE_RINGING) || p->outgoing)) {
11202       /* If the current call is not up, then don't allow the call */
11203       return 0;
11204    }
11205    if ((p->subs[SUB_THREEWAY].owner) && (!p->subs[SUB_THREEWAY].inthreeway)) {
11206       /* Can't take a call wait when the three way calling hasn't been merged yet. */
11207       return 0;
11208    }
11209    /* We're cool */
11210    return 1;
11211 }
11212 
11213 /* This function can *ONLY* be used for copying pseudo (CHAN_PSEUDO) private
11214    structures; it makes no attempt to safely copy regular channel private
11215    structures that might contain reference-counted object pointers and other
11216    scary bits
11217 */
11218 static struct dahdi_pvt *duplicate_pseudo(struct dahdi_pvt *src)
11219 {
11220    struct dahdi_pvt *p;
11221    struct dahdi_bufferinfo bi;
11222    int res;
11223 
11224    if ((p = ast_malloc(sizeof(*p)))) {
11225       memcpy(p, src, sizeof(struct dahdi_pvt));
11226       ast_mutex_init(&p->lock);
11227       p->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo");
11228       if (p->subs[SUB_REAL].dfd < 0) {
11229          ast_log(LOG_ERROR, "Unable to dup channel: %s\n", strerror(errno));
11230          destroy_dahdi_pvt(&p);
11231          return NULL;
11232       }
11233       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
11234       if (!res) {
11235          bi.txbufpolicy = src->buf_policy;
11236          bi.rxbufpolicy = src->buf_policy;
11237          bi.numbufs = src->buf_no;
11238          res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
11239          if (res < 0) {
11240             ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel: %s\n", strerror(errno));
11241          }
11242       } else
11243          ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel: %s\n", strerror(errno));
11244    }
11245    p->destroy = 1;
11246    p->next = iflist;
11247    p->prev = NULL;
11248    iflist = p;
11249    if (iflist->next)
11250       iflist->next->prev = p;
11251    return p;
11252 }
11253 
11254 #if defined(HAVE_PRI)
11255 static int pri_find_empty_chan(struct dahdi_pri *pri, int backwards)
11256 {
11257    int x;
11258    if (backwards)
11259       x = pri->numchans;
11260    else
11261       x = 0;
11262    for (;;) {
11263       if (backwards && (x < 0))
11264          break;
11265       if (!backwards && (x >= pri->numchans))
11266          break;
11267       if (pri->pvts[x] && !pri->pvts[x]->inalarm && !pri->pvts[x]->owner) {
11268          ast_debug(1, "Found empty available channel %d/%d\n",
11269             pri->pvts[x]->logicalspan, pri->pvts[x]->prioffset);
11270          return x;
11271       }
11272       if (backwards)
11273          x--;
11274       else
11275          x++;
11276    }
11277    return -1;
11278 }
11279 #endif   /* defined(HAVE_PRI) */
11280 
11281 static struct ast_channel *dahdi_request(const char *type, int format, void *data, int *cause)
11282 {
11283    ast_group_t groupmatch = 0;
11284    int channelmatch = -1;
11285    int roundrobin = 0;
11286    int callwait = 0;
11287    int busy = 0;
11288    struct dahdi_pvt *p;
11289    struct ast_channel *tmp = NULL;
11290    char *dest=NULL;
11291    int x;
11292    char *s;
11293    char opt=0;
11294    int res=0, y=0;
11295    int backwards = 0;
11296 #ifdef HAVE_PRI
11297    int crv;
11298    int bearer = -1;
11299    int trunkgroup;
11300    struct dahdi_pri *pri=NULL;
11301 #endif
11302    struct dahdi_pvt *exitpvt, *start, *end;
11303    ast_mutex_t *lock;
11304    int channelmatched = 0;
11305    int groupmatched = 0;
11306 
11307    /*
11308     * data is ---v
11309     * Dial(DAHDI/pseudo[/extension])
11310     * Dial(DAHDI/<channel#>[c|r<cadance#>|d][/extension])
11311     * Dial(DAHDI/<trunk_group#>:<crv#>[c|r<cadance#>|d][/extension])
11312     * Dial(DAHDI/(g|G|r|R)<group#(0-63)>[c|r<cadance#>|d][/extension])
11313     *
11314     * g - channel group allocation search forward
11315     * G - channel group allocation search backward
11316     * r - channel group allocation round robin search forward
11317     * R - channel group allocation round robin search backward
11318     *
11319     * c - Wait for DTMF digit to confirm answer
11320     * r<cadance#> - Set distintive ring cadance number
11321     * d - Force bearer capability for ISDN/SS7 call to digital.
11322     */
11323 
11324    /* Assume we're locking the iflock */
11325    lock = &iflock;
11326    start = iflist;
11327    end = ifend;
11328    if (data) {
11329       dest = ast_strdupa((char *)data);
11330    } else {
11331       ast_log(LOG_WARNING, "Channel requested with no data\n");
11332       return NULL;
11333    }
11334    if (toupper(dest[0]) == 'G' || toupper(dest[0])=='R') {
11335       /* Retrieve the group number */
11336       char *stringp;
11337 
11338       stringp = dest + 1;
11339       s = strsep(&stringp, "/");
11340       if ((res = sscanf(s, "%30d%1c%30d", &x, &opt, &y)) < 1) {
11341          ast_log(LOG_WARNING, "Unable to determine group for data %s\n", (char *)data);
11342          return NULL;
11343       }
11344       groupmatch = ((ast_group_t) 1 << x);
11345       if (toupper(dest[0]) == 'G') {
11346          if (dest[0] == 'G') {
11347             backwards = 1;
11348             p = ifend;
11349          } else
11350             p = iflist;
11351       } else {
11352          if (dest[0] == 'R') {
11353             backwards = 1;
11354             p = round_robin[x]?round_robin[x]->prev:ifend;
11355             if (!p)
11356                p = ifend;
11357          } else {
11358             p = round_robin[x]?round_robin[x]->next:iflist;
11359             if (!p)
11360                p = iflist;
11361          }
11362          roundrobin = 1;
11363       }
11364    } else {
11365       char *stringp;
11366 
11367       stringp = dest;
11368       s = strsep(&stringp, "/");
11369       p = iflist;
11370       if (!strcasecmp(s, "pseudo")) {
11371          /* Special case for pseudo */
11372          x = CHAN_PSEUDO;
11373          channelmatch = x;
11374       }
11375 #ifdef HAVE_PRI
11376       else if ((res = sscanf(s, "%30d:%30d%1c%30d", &trunkgroup, &crv, &opt, &y)) > 1) {
11377          if ((trunkgroup < 1) || (crv < 1)) {
11378             ast_log(LOG_WARNING, "Unable to determine trunk group and CRV for data %s\n", (char *)data);
11379             return NULL;
11380          }
11381          res--;
11382          for (x = 0; x < NUM_SPANS; x++) {
11383             if (pris[x].trunkgroup == trunkgroup) {
11384                pri = pris + x;
11385                lock = &pri->lock;
11386                start = pri->crvs;
11387                end = pri->crvend;
11388                break;
11389             }
11390          }
11391          if (!pri) {
11392             ast_log(LOG_WARNING, "Unable to find trunk group %d\n", trunkgroup);
11393             return NULL;
11394          }
11395          channelmatch = crv;
11396          p = pris[x].crvs;
11397       }
11398 #endif
11399       else if ((res = sscanf(s, "%30d%1c%30d", &x, &opt, &y)) < 1) {
11400          ast_log(LOG_WARNING, "Unable to determine channel for data %s\n", (char *)data);
11401          return NULL;
11402       } else {
11403          channelmatch = x;
11404       }
11405    }
11406    /* Search for an unowned channel */
11407    ast_mutex_lock(lock);
11408    exitpvt = p;
11409    while (p && !tmp) {
11410       if (roundrobin)
11411          round_robin[x] = p;
11412 #if 0
11413       ast_verbose("name = %s, %d, %d, %llu\n",p->owner ? p->owner->name : "<none>", p->channel, channelmatch, groupmatch);
11414 #endif
11415 
11416       if (p && available(p, channelmatch, groupmatch, &busy, &channelmatched, &groupmatched)) {
11417          ast_debug(1, "Using channel %d\n", p->channel);
11418          if (p->inalarm)
11419             goto next;
11420 
11421          callwait = (p->owner != NULL);
11422 #ifdef HAVE_PRI
11423          if (pri && (p->subs[SUB_REAL].dfd < 0)) {
11424             if (p->sig != SIG_FXSKS) {
11425                /* Gotta find an actual channel to use for this
11426                   CRV if this isn't a callwait */
11427                bearer = pri_find_empty_chan(pri, 0);
11428                if (bearer < 0) {
11429                   ast_log(LOG_NOTICE, "Out of bearer channels on span %d for call to CRV %d:%d\n", pri->span, trunkgroup, crv);
11430                   p = NULL;
11431                   break;
11432                }
11433                pri_assign_bearer(p, pri, pri->pvts[bearer]);
11434             } else {
11435                if (alloc_sub(p, 0)) {
11436                   ast_log(LOG_NOTICE, "Failed to allocate place holder pseudo channel!\n");
11437                   p = NULL;
11438                   break;
11439                } else
11440                   ast_debug(1, "Allocated placeholder pseudo channel\n");
11441 
11442                p->pri = pri;
11443             }
11444          }
11445 #endif
11446 #ifdef HAVE_OPENR2
11447          if (p->mfcr2) {
11448             ast_mutex_lock(&p->lock);
11449             if (p->mfcr2call) {
11450                ast_mutex_unlock(&p->lock);
11451                ast_log(LOG_DEBUG, "Yay!, someone just beat us in the race for channel %d.\n", p->channel);
11452                goto next;
11453             }
11454             p->mfcr2call = 1;
11455             ast_mutex_unlock(&p->lock);
11456          }
11457 #endif
11458          if (p->channel == CHAN_PSEUDO) {
11459             p = duplicate_pseudo(p);
11460             if (!p) {
11461                break;
11462             }
11463          }
11464          if (p->owner) {
11465             if (alloc_sub(p, SUB_CALLWAIT)) {
11466                p = NULL;
11467                break;
11468             }
11469          }
11470          p->outgoing = 1;
11471          tmp = dahdi_new(p, AST_STATE_RESERVED, 0, p->owner ? SUB_CALLWAIT : SUB_REAL, 0, 0);
11472          if (!tmp) {
11473             p->outgoing = 0;
11474          }
11475 #ifdef HAVE_PRI
11476          if (p->bearer) {
11477             /* Log owner to bearer channel, too */
11478             p->bearer->owner = tmp;
11479          }
11480 #endif
11481          /* Make special notes */
11482          if (res > 1) {
11483             if (opt == 'c') {
11484                /* Confirm answer */
11485                p->confirmanswer = 1;
11486             } else if (opt == 'r') {
11487                /* Distinctive ring */
11488                if (res < 3)
11489                   ast_log(LOG_WARNING, "Distinctive ring missing identifier in '%s'\n", (char *)data);
11490                else
11491                   p->distinctivering = y;
11492             } else if (opt == 'd') {
11493                /* If this is an ISDN call, make it digital */
11494                p->digital = 1;
11495                if (tmp)
11496                   tmp->transfercapability = AST_TRANS_CAP_DIGITAL;
11497             } else {
11498                ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", opt, (char *)data);
11499             }
11500          }
11501          /* Note if the call is a call waiting call */
11502          if (tmp && callwait)
11503             tmp->cdrflags |= AST_CDR_CALLWAIT;
11504          break;
11505       }
11506 next:
11507       if (backwards) {
11508          p = p->prev;
11509          if (!p)
11510             p = end;
11511       } else {
11512          p = p->next;
11513          if (!p)
11514             p = start;
11515       }
11516       /* stop when you roll to the one that we started from */
11517       if (p == exitpvt)
11518          break;
11519    }
11520    ast_mutex_unlock(lock);
11521    restart_monitor();
11522    if (callwait)
11523       *cause = AST_CAUSE_BUSY;
11524    else if (!tmp) {
11525       if (channelmatched) {
11526          if (busy)
11527             *cause = AST_CAUSE_BUSY;
11528       } else if (groupmatched) {
11529          *cause = AST_CAUSE_CONGESTION;
11530       }
11531    }
11532 
11533    return tmp;
11534 }
11535 
11536 #if defined(HAVE_PRI) || defined(HAVE_SS7)
11537 static int dahdi_setlaw(int dfd, int law)
11538 {
11539    return ioctl(dfd, DAHDI_SETLAW, &law);
11540 }
11541 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
11542 
11543 #if defined(HAVE_SS7)
11544 static int ss7_find_cic(struct dahdi_ss7 *linkset, int cic, unsigned int dpc)
11545 {
11546    int i;
11547    int winner = -1;
11548    for (i = 0; i < linkset->numchans; i++) {
11549       if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && linkset->pvts[i]->cic == cic)) {
11550          winner = i;
11551          break;
11552       }
11553    }
11554    return winner;
11555 }
11556 #endif   /* defined(HAVE_SS7) */
11557 
11558 #if defined(HAVE_SS7)
11559 static void ss7_handle_cqm(struct dahdi_ss7 *linkset, int startcic, int endcic, unsigned int dpc)
11560 {
11561    unsigned char status[32];
11562    struct dahdi_pvt *p = NULL;
11563    int i, offset;
11564 
11565    for (i = 0; i < linkset->numchans; i++) {
11566       if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && ((linkset->pvts[i]->cic >= startcic) && (linkset->pvts[i]->cic <= endcic)))) {
11567          p = linkset->pvts[i];
11568          offset = p->cic - startcic;
11569          status[offset] = 0;
11570          if (p->locallyblocked)
11571             status[offset] |= (1 << 0) | (1 << 4);
11572          if (p->remotelyblocked)
11573             status[offset] |= (1 << 1) | (1 << 5);
11574          if (p->ss7call) {
11575             if (p->outgoing)
11576                status[offset] |= (1 << 3);
11577             else
11578                status[offset] |= (1 << 2);
11579          } else
11580             status[offset] |= 0x3 << 2;
11581       }
11582    }
11583 
11584    if (p)
11585       isup_cqr(linkset->ss7, startcic, endcic, dpc, status);
11586    else
11587       ast_log(LOG_WARNING, "Could not find any equipped circuits within CQM CICs\n");
11588 
11589 }
11590 #endif   /* defined(HAVE_SS7) */
11591 
11592 #if defined(HAVE_SS7)
11593 static inline void ss7_hangup_cics(struct dahdi_ss7 *linkset, int startcic, int endcic, unsigned int dpc)
11594 {
11595    int i;
11596 
11597    for (i = 0; i < linkset->numchans; i++) {
11598       if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && ((linkset->pvts[i]->cic >= startcic) && (linkset->pvts[i]->cic <= endcic)))) {
11599          ast_mutex_lock(&linkset->pvts[i]->lock);
11600          if (linkset->pvts[i]->owner)
11601             linkset->pvts[i]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11602          ast_mutex_unlock(&linkset->pvts[i]->lock);
11603       }
11604    }
11605 }
11606 #endif   /* defined(HAVE_SS7) */
11607 
11608 #if defined(HAVE_SS7)
11609 static inline void ss7_block_cics(struct dahdi_ss7 *linkset, int startcic, int endcic, unsigned int dpc, unsigned char state[], int block)
11610 {
11611    int i;
11612 
11613    for (i = 0; i < linkset->numchans; i++) {
11614       if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && ((linkset->pvts[i]->cic >= startcic) && (linkset->pvts[i]->cic <= endcic)))) {
11615          if (state) {
11616             if (state[i])
11617                linkset->pvts[i]->remotelyblocked = block;
11618          } else
11619             linkset->pvts[i]->remotelyblocked = block;
11620       }
11621    }
11622 }
11623 #endif   /* defined(HAVE_SS7) */
11624 
11625 #if defined(HAVE_SS7)
11626 static void ss7_inservice(struct dahdi_ss7 *linkset, int startcic, int endcic, unsigned int dpc)
11627 {
11628    int i;
11629 
11630    for (i = 0; i < linkset->numchans; i++) {
11631       if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && ((linkset->pvts[i]->cic >= startcic) && (linkset->pvts[i]->cic <= endcic))))
11632          linkset->pvts[i]->inservice = 1;
11633    }
11634 }
11635 #endif   /* defined(HAVE_SS7) */
11636 
11637 #if defined(HAVE_SS7)
11638 static void ss7_reset_linkset(struct dahdi_ss7 *linkset)
11639 {
11640    int i, startcic = -1, endcic, dpc;
11641 
11642    if (linkset->numchans <= 0)
11643       return;
11644 
11645    startcic = linkset->pvts[0]->cic;
11646    /* DB: CIC's DPC fix */
11647    dpc = linkset->pvts[0]->dpc;
11648 
11649    for (i = 0; i < linkset->numchans; i++) {
11650       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)) {
11651          continue;
11652       } else {
11653          endcic = linkset->pvts[i]->cic;
11654          ast_verbose("Resetting CICs %d to %d\n", startcic, endcic);
11655          isup_grs(linkset->ss7, startcic, endcic, dpc);
11656 
11657          /* DB: CIC's DPC fix */
11658          if (linkset->pvts[i+1]) {
11659             startcic = linkset->pvts[i+1]->cic;
11660             dpc = linkset->pvts[i+1]->dpc;
11661          }
11662       }
11663    }
11664 }
11665 #endif   /* defined(HAVE_SS7) */
11666 
11667 #if defined(HAVE_SS7)
11668 static void dahdi_loopback(struct dahdi_pvt *p, int enable)
11669 {
11670    if (p->loopedback != enable) {
11671       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_LOOPBACK, &enable)) {
11672          ast_log(LOG_WARNING, "Unable to set loopback on channel %d: %s\n", p->channel, strerror(errno));
11673          return;
11674       }
11675       p->loopedback = enable;
11676    }
11677 }
11678 #endif   /* defined(HAVE_SS7) */
11679 
11680 #if defined(HAVE_SS7)
11681 /* XXX: This function is assumed to be called with the private channel lock and linkset lock held */
11682 static void ss7_start_call(struct dahdi_pvt *p, struct dahdi_ss7 *linkset)
11683 {
11684    struct ss7 *ss7 = linkset->ss7;
11685    int res;
11686    int law = 1;
11687    struct ast_channel *c;
11688    char tmp[256];
11689 
11690    if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &law) == -1)
11691       ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, law, strerror(errno));
11692 
11693    if (linkset->type == SS7_ITU)
11694       law = DAHDI_LAW_ALAW;
11695    else
11696       law = DAHDI_LAW_MULAW;
11697 
11698    res = dahdi_setlaw(p->subs[SUB_REAL].dfd, law);
11699    if (res < 0)
11700       ast_log(LOG_WARNING, "Unable to set law on channel %d\n", p->channel);
11701 
11702    if (!(linkset->flags & LINKSET_FLAG_EXPLICITACM)) {
11703       p->call_level = DAHDI_CALL_LEVEL_PROCEEDING;
11704       isup_acm(ss7, p->ss7call);
11705    } else {
11706       p->call_level = DAHDI_CALL_LEVEL_SETUP;
11707    }
11708 
11709    ast_mutex_unlock(&linkset->lock);
11710    c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, law, 0);
11711    if (!c) {
11712       ast_log(LOG_WARNING, "Unable to start PBX on CIC %d\n", p->cic);
11713       /* Holding this lock is assumed entering the function */
11714       ast_mutex_lock(&linkset->lock);
11715       p->call_level = DAHDI_CALL_LEVEL_IDLE;
11716       return;
11717    } else
11718       ast_verb(3, "Accepting call to '%s' on CIC %d\n", p->exten, p->cic);
11719 
11720    dahdi_enable_ec(p);
11721 
11722    /* We only reference these variables in the context of the ss7_linkset function
11723     * when receiving either and IAM or a COT message.  Since they are only accessed
11724     * from this context, we should be safe to unlock around them */
11725 
11726    ast_mutex_unlock(&p->lock);
11727 
11728    if (!ast_strlen_zero(p->charge_number)) {
11729       pbx_builtin_setvar_helper(c, "SS7_CHARGE_NUMBER", p->charge_number);
11730       /* Clear this after we set it */
11731       p->charge_number[0] = 0;
11732    }
11733    if (!ast_strlen_zero(p->gen_add_number)) {
11734       pbx_builtin_setvar_helper(c, "SS7_GENERIC_ADDRESS", p->gen_add_number);
11735       /* Clear this after we set it */
11736       p->gen_add_number[0] = 0;
11737    }
11738    if (!ast_strlen_zero(p->jip_number)) {
11739       pbx_builtin_setvar_helper(c, "SS7_JIP", p->jip_number);
11740       /* Clear this after we set it */
11741       p->jip_number[0] = 0;
11742    }
11743    if (!ast_strlen_zero(p->gen_dig_number)) {
11744       pbx_builtin_setvar_helper(c, "SS7_GENERIC_DIGITS", p->gen_dig_number);
11745       /* Clear this after we set it */
11746       p->gen_dig_number[0] = 0;
11747    }
11748    if (!ast_strlen_zero(p->orig_called_num)) {
11749       pbx_builtin_setvar_helper(c, "SS7_ORIG_CALLED_NUM", p->orig_called_num);
11750       /* Clear this after we set it */
11751       p->orig_called_num[0] = 0;
11752    }
11753 
11754    snprintf(tmp, sizeof(tmp), "%d", p->gen_dig_type);
11755    pbx_builtin_setvar_helper(c, "SS7_GENERIC_DIGTYPE", tmp);
11756    /* Clear this after we set it */
11757    p->gen_dig_type = 0;
11758 
11759    snprintf(tmp, sizeof(tmp), "%d", p->gen_dig_scheme);
11760    pbx_builtin_setvar_helper(c, "SS7_GENERIC_DIGSCHEME", tmp);
11761    /* Clear this after we set it */
11762    p->gen_dig_scheme = 0;
11763 
11764    if (!ast_strlen_zero(p->lspi_ident)) {
11765       pbx_builtin_setvar_helper(c, "SS7_LSPI_IDENT", p->lspi_ident);
11766       /* Clear this after we set it */
11767       p->lspi_ident[0] = 0;
11768    }
11769 
11770    snprintf(tmp, sizeof(tmp), "%d", p->call_ref_ident);
11771    pbx_builtin_setvar_helper(c, "SS7_CALLREF_IDENT", tmp);
11772    /* Clear this after we set it */
11773    p->call_ref_ident = 0;
11774 
11775    snprintf(tmp, sizeof(tmp), "%d", p->call_ref_pc);
11776    pbx_builtin_setvar_helper(c, "SS7_CALLREF_PC", tmp);
11777    /* Clear this after we set it */
11778    p->call_ref_pc = 0;
11779 
11780    snprintf(tmp, sizeof(tmp), "%d", p->calling_party_cat);
11781    pbx_builtin_setvar_helper(c, "SS7_CALLING_PARTY_CATEGORY", tmp);
11782    /* Clear this after we set it */
11783    p->calling_party_cat = 0;
11784 
11785    if (!ast_strlen_zero(p->redirecting_num)) {
11786       pbx_builtin_setvar_helper(c, "SS7_REDIRECTING_NUMBER", p->redirecting_num);
11787       /* Clear this after we set it */
11788       p->redirecting_num[0] = 0;
11789    }
11790    if (!ast_strlen_zero(p->generic_name)) {
11791       pbx_builtin_setvar_helper(c, "SS7_GENERIC_NAME", p->generic_name);
11792       /* Clear this after we set it */
11793       p->generic_name[0] = 0;
11794    }
11795 
11796    ast_mutex_lock(&p->lock);
11797    ast_mutex_lock(&linkset->lock);
11798 }
11799 #endif   /* defined(HAVE_SS7) */
11800 
11801 #if defined(HAVE_SS7)
11802 static void ss7_apply_plan_to_number(char *buf, size_t size, const struct dahdi_ss7 *ss7, const char *number, const unsigned nai)
11803 {
11804    if (ast_strlen_zero(number)) { /* make sure a number exists so prefix isn't placed on an empty string */
11805       if (size) {
11806          *buf = '\0';
11807       }
11808       return;
11809    }
11810    switch (nai) {
11811    case SS7_NAI_INTERNATIONAL:
11812       snprintf(buf, size, "%s%s", ss7->internationalprefix, number);
11813       break;
11814    case SS7_NAI_NATIONAL:
11815       snprintf(buf, size, "%s%s", ss7->nationalprefix, number);
11816       break;
11817    case SS7_NAI_SUBSCRIBER:
11818       snprintf(buf, size, "%s%s", ss7->subscriberprefix, number);
11819       break;
11820    case SS7_NAI_UNKNOWN:
11821       snprintf(buf, size, "%s%s", ss7->unknownprefix, number);
11822       break;
11823    default:
11824       snprintf(buf, size, "%s", number);
11825       break;
11826    }
11827 }
11828 #endif   /* defined(HAVE_SS7) */
11829 
11830 #if defined(HAVE_SS7)
11831 static int ss7_pres_scr2cid_pres(char presentation_ind, char screening_ind)
11832 {
11833    return ((presentation_ind & 0x3) << 5) | (screening_ind & 0x3);
11834 }
11835 #endif   /* defined(HAVE_SS7) */
11836 
11837 #if defined(HAVE_SS7)
11838 static void *ss7_linkset(void *data)
11839 {
11840    int res, i;
11841    struct timeval *next = NULL, tv;
11842    struct dahdi_ss7 *linkset = (struct dahdi_ss7 *) data;
11843    struct ss7 *ss7 = linkset->ss7;
11844    ss7_event *e = NULL;
11845    struct dahdi_pvt *p;
11846    int chanpos;
11847    struct pollfd pollers[NUM_DCHANS];
11848    int cic;
11849    unsigned int dpc;
11850    int nextms = 0;
11851 
11852    ss7_start(ss7);
11853 
11854    while(1) {
11855       ast_mutex_lock(&linkset->lock);
11856       if ((next = ss7_schedule_next(ss7))) {
11857          tv = ast_tvnow();
11858          tv.tv_sec = next->tv_sec - tv.tv_sec;
11859          tv.tv_usec = next->tv_usec - tv.tv_usec;
11860          if (tv.tv_usec < 0) {
11861             tv.tv_usec += 1000000;
11862             tv.tv_sec -= 1;
11863          }
11864          if (tv.tv_sec < 0) {
11865             tv.tv_sec = 0;
11866             tv.tv_usec = 0;
11867          }
11868          nextms = tv.tv_sec * 1000;
11869          nextms += tv.tv_usec / 1000;
11870       }
11871       ast_mutex_unlock(&linkset->lock);
11872 
11873       for (i = 0; i < linkset->numsigchans; i++) {
11874          pollers[i].fd = linkset->fds[i];
11875          pollers[i].events = ss7_pollflags(ss7, linkset->fds[i]);
11876          pollers[i].revents = 0;
11877       }
11878 
11879       res = poll(pollers, linkset->numsigchans, nextms);
11880       if ((res < 0) && (errno != EINTR)) {
11881          ast_log(LOG_ERROR, "poll(%s)\n", strerror(errno));
11882       } else if (!res) {
11883          ast_mutex_lock(&linkset->lock);
11884          ss7_schedule_run(ss7);
11885          ast_mutex_unlock(&linkset->lock);
11886          continue;
11887       }
11888 
11889       ast_mutex_lock(&linkset->lock);
11890       for (i = 0; i < linkset->numsigchans; i++) {
11891          if (pollers[i].revents & POLLPRI) {
11892             int x;
11893             if (ioctl(pollers[i].fd, DAHDI_GETEVENT, &x)) {
11894                ast_log(LOG_ERROR, "Error in exception retrieval!\n");
11895             }
11896             switch (x) {
11897             case DAHDI_EVENT_OVERRUN:
11898                ast_debug(1, "Overrun detected!\n");
11899                break;
11900             case DAHDI_EVENT_BADFCS:
11901                ast_debug(1, "Bad FCS\n");
11902                break;
11903             case DAHDI_EVENT_ABORT:
11904                ast_debug(1, "HDLC Abort\n");
11905                break;
11906             case DAHDI_EVENT_ALARM:
11907                ast_log(LOG_ERROR, "Alarm on link!\n");
11908                linkset->linkstate[i] |= (LINKSTATE_DOWN | LINKSTATE_INALARM);
11909                linkset->linkstate[i] &= ~LINKSTATE_UP;
11910                ss7_link_alarm(ss7, pollers[i].fd);
11911                break;
11912             case DAHDI_EVENT_NOALARM:
11913                ast_log(LOG_ERROR, "Alarm cleared on link\n");
11914                linkset->linkstate[i] &= ~(LINKSTATE_INALARM | LINKSTATE_DOWN);
11915                linkset->linkstate[i] |= LINKSTATE_STARTING;
11916                ss7_link_noalarm(ss7, pollers[i].fd);
11917                break;
11918             default:
11919                ast_log(LOG_ERROR, "Got exception %d!\n", x);
11920                break;
11921             }
11922          }
11923 
11924          if (pollers[i].revents & POLLIN) {
11925             res = ss7_read(ss7, pollers[i].fd);
11926          }
11927 
11928          if (pollers[i].revents & POLLOUT) {
11929             res = ss7_write(ss7, pollers[i].fd);
11930             if (res < 0) {
11931                ast_debug(1, "Error in write %s\n", strerror(errno));
11932             }
11933          }
11934       }
11935 
11936       while ((e = ss7_check_event(ss7))) {
11937          switch (e->e) {
11938          case SS7_EVENT_UP:
11939             if (linkset->state != LINKSET_STATE_UP) {
11940                ast_verbose("--- SS7 Up ---\n");
11941                ss7_reset_linkset(linkset);
11942             }
11943             linkset->state = LINKSET_STATE_UP;
11944             break;
11945          case SS7_EVENT_DOWN:
11946             ast_verbose("--- SS7 Down ---\n");
11947             linkset->state = LINKSET_STATE_DOWN;
11948             for (i = 0; i < linkset->numchans; i++) {
11949                struct dahdi_pvt *p = linkset->pvts[i];
11950                if (p)
11951                   p->inalarm = 1;
11952             }
11953             break;
11954          case MTP2_LINK_UP:
11955             ast_verbose("MTP2 link up (SLC %d)\n", e->gen.data);
11956             break;
11957          case MTP2_LINK_DOWN:
11958             ast_log(LOG_WARNING, "MTP2 link down (SLC %d)\n", e->gen.data);
11959             break;
11960          case ISUP_EVENT_CPG:
11961             chanpos = ss7_find_cic(linkset, e->cpg.cic, e->cpg.opc);
11962             if (chanpos < 0) {
11963                ast_log(LOG_WARNING, "CPG on unconfigured CIC %d\n", e->cpg.cic);
11964                break;
11965             }
11966             p = linkset->pvts[chanpos];
11967             ast_mutex_lock(&p->lock);
11968             switch (e->cpg.event) {
11969             case CPG_EVENT_ALERTING:
11970                if (p->call_level < DAHDI_CALL_LEVEL_ALERTING) {
11971                   p->call_level = DAHDI_CALL_LEVEL_ALERTING;
11972                }
11973                p->subs[SUB_REAL].needringing = 1;
11974                break;
11975             case CPG_EVENT_PROGRESS:
11976             case CPG_EVENT_INBANDINFO:
11977                {
11978                   struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, };
11979                   ast_debug(1, "Queuing frame PROGRESS on CIC %d\n", p->cic);
11980                   dahdi_queue_frame(p, &f, linkset);
11981                   p->progress = 1;
11982                   p->dialing = 0;
11983                   if (p->dsp && p->dsp_features) {
11984                      ast_dsp_set_features(p->dsp, p->dsp_features);
11985                      p->dsp_features = 0;
11986                   }
11987                }
11988                break;
11989             default:
11990                ast_debug(1, "Do not handle CPG with event type 0x%x\n", e->cpg.event);
11991             }
11992 
11993             ast_mutex_unlock(&p->lock);
11994             break;
11995          case ISUP_EVENT_RSC:
11996             ast_verbose("Resetting CIC %d\n", e->rsc.cic);
11997             chanpos = ss7_find_cic(linkset, e->rsc.cic, e->rsc.opc);
11998             if (chanpos < 0) {
11999                ast_log(LOG_WARNING, "RSC on unconfigured CIC %d\n", e->rsc.cic);
12000                break;
12001             }
12002             p = linkset->pvts[chanpos];
12003             ast_mutex_lock(&p->lock);
12004             p->inservice = 1;
12005             p->remotelyblocked = 0;
12006             dpc = p->dpc;
12007             isup_set_call_dpc(e->rsc.call, dpc);
12008             if (p->ss7call)
12009                p->ss7call = NULL;
12010             if (p->owner)
12011                p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
12012             ast_mutex_unlock(&p->lock);
12013             isup_rlc(ss7, e->rsc.call);
12014             break;
12015          case ISUP_EVENT_GRS:
12016             ast_debug(1, "Got Reset for CICs %d to %d: Acknowledging\n", e->grs.startcic, e->grs.endcic);
12017             chanpos = ss7_find_cic(linkset, e->grs.startcic, e->grs.opc);
12018             if (chanpos < 0) {
12019                ast_log(LOG_WARNING, "GRS on unconfigured CIC %d\n", e->grs.startcic);
12020                break;
12021             }
12022             p = linkset->pvts[chanpos];
12023             isup_gra(ss7, e->grs.startcic, e->grs.endcic, e->grs.opc);
12024             ss7_block_cics(linkset, e->grs.startcic, e->grs.endcic, e->grs.opc, NULL, 0);
12025             ss7_hangup_cics(linkset, e->grs.startcic, e->grs.endcic, e->grs.opc);
12026             break;
12027          case ISUP_EVENT_CQM:
12028             ast_debug(1, "Got Circuit group query message from CICs %d to %d\n", e->cqm.startcic, e->cqm.endcic);
12029             ss7_handle_cqm(linkset, e->cqm.startcic, e->cqm.endcic, e->cqm.opc);
12030             break;
12031          case ISUP_EVENT_GRA:
12032             ast_verbose("Got reset acknowledgement from CIC %d to %d.\n", e->gra.startcic, e->gra.endcic);
12033             ss7_inservice(linkset, e->gra.startcic, e->gra.endcic, e->gra.opc);
12034             ss7_block_cics(linkset, e->gra.startcic, e->gra.endcic, e->gra.opc, e->gra.status, 1);
12035             break;
12036          case ISUP_EVENT_IAM:
12037             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);
12038             chanpos = ss7_find_cic(linkset, e->iam.cic, e->iam.opc);
12039             if (chanpos < 0) {
12040                ast_log(LOG_WARNING, "IAM on unconfigured CIC %d\n", e->iam.cic);
12041                isup_rel(ss7, e->iam.call, -1);
12042                break;
12043             }
12044             p = linkset->pvts[chanpos];
12045             ast_mutex_lock(&p->lock);
12046             if (p->owner) {
12047                if (p->ss7call == e->iam.call) {
12048                   ast_mutex_unlock(&p->lock);
12049                   ast_log(LOG_WARNING, "Duplicate IAM requested on CIC %d\n", e->iam.cic);
12050                   break;
12051                } else {
12052                   ast_mutex_unlock(&p->lock);
12053                   ast_log(LOG_WARNING, "Ring requested on CIC %d already in use!\n", e->iam.cic);
12054                   break;
12055                }
12056             }
12057 
12058             dpc = p->dpc;
12059             p->ss7call = e->iam.call;
12060             isup_set_call_dpc(p->ss7call, dpc);
12061 
12062             if ((p->use_callerid) && (!ast_strlen_zero(e->iam.calling_party_num))) {
12063                ss7_apply_plan_to_number(p->cid_num, sizeof(p->cid_num), linkset, e->iam.calling_party_num, e->iam.calling_nai);
12064                p->callingpres = ss7_pres_scr2cid_pres(e->iam.presentation_ind, e->iam.screening_ind);
12065             } else
12066                p->cid_num[0] = 0;
12067 
12068             if (p->immediate) {
12069                p->exten[0] = 's';
12070                p->exten[1] = '\0';
12071             } else if (!ast_strlen_zero(e->iam.called_party_num)) {
12072                char *st;
12073                ss7_apply_plan_to_number(p->exten, sizeof(p->exten), linkset, e->iam.called_party_num, e->iam.called_nai);
12074                st = strchr(p->exten, '#');
12075                if (st)
12076                   *st = '\0';
12077                } else
12078                   p->exten[0] = '\0';
12079 
12080             p->cid_ani[0] = '\0';
12081             if ((p->use_callerid) && (!ast_strlen_zero(e->iam.generic_name)))
12082                ast_copy_string(p->cid_name, e->iam.generic_name, sizeof(p->cid_name));
12083             else
12084                p->cid_name[0] = '\0';
12085 
12086             p->cid_ani2 = e->iam.oli_ani2;
12087             p->cid_ton = 0;
12088             ast_copy_string(p->charge_number, e->iam.charge_number, sizeof(p->charge_number));
12089             ast_copy_string(p->gen_add_number, e->iam.gen_add_number, sizeof(p->gen_add_number));
12090             p->gen_add_type = e->iam.gen_add_type;
12091             p->gen_add_nai = e->iam.gen_add_nai;
12092             p->gen_add_pres_ind = e->iam.gen_add_pres_ind;
12093             p->gen_add_num_plan = e->iam.gen_add_num_plan;
12094             ast_copy_string(p->gen_dig_number, e->iam.gen_dig_number, sizeof(p->gen_dig_number));
12095             p->gen_dig_type = e->iam.gen_dig_type;
12096             p->gen_dig_scheme = e->iam.gen_dig_scheme;
12097             ast_copy_string(p->jip_number, e->iam.jip_number, sizeof(p->jip_number));
12098             ast_copy_string(p->orig_called_num, e->iam.orig_called_num, sizeof(p->orig_called_num));
12099             ast_copy_string(p->redirecting_num, e->iam.redirecting_num, sizeof(p->redirecting_num));
12100             ast_copy_string(p->generic_name, e->iam.generic_name, sizeof(p->generic_name));
12101             p->calling_party_cat = e->iam.calling_party_cat;
12102 
12103             /* Set DNID */
12104             if (!ast_strlen_zero(e->iam.called_party_num))
12105                ss7_apply_plan_to_number(p->dnid, sizeof(p->dnid), linkset, e->iam.called_party_num, e->iam.called_nai);
12106 
12107             if (ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
12108 
12109                if (e->iam.cot_check_required) {
12110                   dahdi_loopback(p, 1);
12111                } else
12112                   ss7_start_call(p, linkset);
12113             } else {
12114                ast_debug(1, "Call on CIC for unconfigured extension %s\n", p->exten);
12115                p->alreadyhungup = 1;
12116                isup_rel(ss7, e->iam.call, AST_CAUSE_UNALLOCATED);
12117             }
12118             ast_mutex_unlock(&p->lock);
12119             break;
12120          case ISUP_EVENT_COT:
12121             chanpos = ss7_find_cic(linkset, e->cot.cic, e->cot.opc);
12122             if (chanpos < 0) {
12123                ast_log(LOG_WARNING, "COT on unconfigured CIC %d\n", e->cot.cic);
12124                isup_rel(ss7, e->cot.call, -1);
12125                break;
12126             }
12127             p = linkset->pvts[chanpos];
12128 
12129             ast_mutex_lock(&p->lock);
12130 
12131             if (p->loopedback) {
12132                dahdi_loopback(p, 0);
12133                ss7_start_call(p, linkset);
12134             }
12135 
12136             ast_mutex_unlock(&p->lock);
12137 
12138             break;
12139          case ISUP_EVENT_CCR:
12140             ast_debug(1, "Got CCR request on CIC %d\n", e->ccr.cic);
12141             chanpos = ss7_find_cic(linkset, e->ccr.cic, e->ccr.opc);
12142             if (chanpos < 0) {
12143                ast_log(LOG_WARNING, "CCR on unconfigured CIC %d\n", e->ccr.cic);
12144                break;
12145             }
12146 
12147             p = linkset->pvts[chanpos];
12148 
12149             ast_mutex_lock(&p->lock);
12150             dahdi_loopback(p, 1);
12151             ast_mutex_unlock(&p->lock);
12152 
12153             isup_lpa(linkset->ss7, e->ccr.cic, p->dpc);
12154             break;
12155          case ISUP_EVENT_CVT:
12156             ast_debug(1, "Got CVT request on CIC %d\n", e->cvt.cic);
12157             chanpos = ss7_find_cic(linkset, e->cvt.cic, e->cvt.opc);
12158             if (chanpos < 0) {
12159                ast_log(LOG_WARNING, "CVT on unconfigured CIC %d\n", e->cvt.cic);
12160                break;
12161             }
12162 
12163             p = linkset->pvts[chanpos];
12164 
12165             ast_mutex_lock(&p->lock);
12166             dahdi_loopback(p, 1);
12167             ast_mutex_unlock(&p->lock);
12168 
12169             isup_cvr(linkset->ss7, e->cvt.cic, p->dpc);
12170             break;
12171          case ISUP_EVENT_REL:
12172             chanpos = ss7_find_cic(linkset, e->rel.cic, e->rel.opc);
12173             if (chanpos < 0) {
12174                ast_log(LOG_WARNING, "REL on unconfigured CIC %d\n", e->rel.cic);
12175                break;
12176             }
12177             p = linkset->pvts[chanpos];
12178             ast_mutex_lock(&p->lock);
12179             if (p->owner) {
12180                p->owner->hangupcause = e->rel.cause;
12181                p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
12182             } else if (!p->restartpending)
12183                ast_log(LOG_WARNING, "REL on channel (CIC %d) without owner!\n", p->cic);
12184 
12185             /* End the loopback if we have one */
12186             dahdi_loopback(p, 0);
12187 
12188             isup_rlc(ss7, e->rel.call);
12189             p->ss7call = NULL;
12190 
12191             ast_mutex_unlock(&p->lock);
12192             break;
12193          case ISUP_EVENT_ACM:
12194             chanpos = ss7_find_cic(linkset, e->acm.cic, e->acm.opc);
12195             if (chanpos < 0) {
12196                ast_log(LOG_WARNING, "ACM on unconfigured CIC %d\n", e->acm.cic);
12197                isup_rel(ss7, e->acm.call, -1);
12198                break;
12199             } else {
12200                struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROCEEDING, };
12201 
12202                p = linkset->pvts[chanpos];
12203 
12204                ast_debug(1, "Queueing frame from SS7_EVENT_ACM on CIC %d\n", p->cic);
12205 
12206                if (e->acm.call_ref_ident > 0) {
12207                   p->rlt = 1; /* Setting it but not using it here*/
12208                }
12209 
12210                ast_mutex_lock(&p->lock);
12211                dahdi_queue_frame(p, &f, linkset);
12212                if (p->call_level < DAHDI_CALL_LEVEL_PROCEEDING) {
12213                   p->call_level = DAHDI_CALL_LEVEL_PROCEEDING;
12214                }
12215                p->dialing = 0;
12216                /* Send alerting if subscriber is free */
12217                if (e->acm.called_party_status_ind == 1) {
12218                   if (p->call_level < DAHDI_CALL_LEVEL_ALERTING) {
12219                      p->call_level = DAHDI_CALL_LEVEL_ALERTING;
12220                   }
12221                   p->subs[SUB_REAL].needringing = 1;
12222                }
12223                ast_mutex_unlock(&p->lock);
12224             }
12225             break;
12226          case ISUP_EVENT_CGB:
12227             chanpos = ss7_find_cic(linkset, e->cgb.startcic, e->cgb.opc);
12228             if (chanpos < 0) {
12229                ast_log(LOG_WARNING, "CGB on unconfigured CIC %d\n", e->cgb.startcic);
12230                break;
12231             }
12232             p = linkset->pvts[chanpos];
12233             ss7_block_cics(linkset, e->cgb.startcic, e->cgb.endcic, e->cgb.opc, e->cgb.status, 1);
12234             isup_cgba(linkset->ss7, e->cgb.startcic, e->cgb.endcic, e->cgb.opc, e->cgb.status, e->cgb.type);
12235             break;
12236          case ISUP_EVENT_CGU:
12237             chanpos = ss7_find_cic(linkset, e->cgu.startcic, e->cgu.opc);
12238             if (chanpos < 0) {
12239                ast_log(LOG_WARNING, "CGU on unconfigured CIC %d\n", e->cgu.startcic);
12240                break;
12241             }
12242             p = linkset->pvts[chanpos];
12243             ss7_block_cics(linkset, e->cgu.startcic, e->cgu.endcic, e->cgu.opc, e->cgu.status, 0);
12244             isup_cgua(linkset->ss7, e->cgu.startcic, e->cgu.endcic, e->cgu.opc, e->cgu.status, e->cgu.type);
12245             break;
12246          case ISUP_EVENT_UCIC:
12247             chanpos = ss7_find_cic(linkset, e->ucic.cic, e->ucic.opc);
12248             if (chanpos < 0) {
12249                ast_log(LOG_WARNING, "UCIC on unconfigured CIC %d\n", e->ucic.cic);
12250                break;
12251             }
12252             p = linkset->pvts[chanpos];
12253             ast_debug(1, "Unequiped Circuit Id Code on CIC %d\n", e->ucic.cic);
12254             ast_mutex_lock(&p->lock);
12255             p->remotelyblocked = 1;
12256             p->inservice = 0;
12257             ast_mutex_unlock(&p->lock);         //doesn't require a SS7 acknowledgement
12258             break;
12259          case ISUP_EVENT_BLO:
12260             chanpos = ss7_find_cic(linkset, e->blo.cic, e->blo.opc);
12261             if (chanpos < 0) {
12262                ast_log(LOG_WARNING, "BLO on unconfigured CIC %d\n", e->blo.cic);
12263                break;
12264             }
12265             p = linkset->pvts[chanpos];
12266             ast_debug(1, "Blocking CIC %d\n", e->blo.cic);
12267             ast_mutex_lock(&p->lock);
12268             p->remotelyblocked = 1;
12269             ast_mutex_unlock(&p->lock);
12270             isup_bla(linkset->ss7, e->blo.cic, p->dpc);
12271             break;
12272          case ISUP_EVENT_BLA:
12273             chanpos = ss7_find_cic(linkset, e->bla.cic, e->bla.opc);
12274             if (chanpos < 0) {
12275                ast_log(LOG_WARNING, "BLA on unconfigured CIC %d\n", e->bla.cic);
12276                break;
12277             }
12278             ast_debug(1, "Blocking CIC %d\n", e->bla.cic);
12279             p = linkset->pvts[chanpos];
12280             ast_mutex_lock(&p->lock);
12281             p->locallyblocked = 1;
12282             ast_mutex_unlock(&p->lock);
12283             break;
12284          case ISUP_EVENT_UBL:
12285             chanpos = ss7_find_cic(linkset, e->ubl.cic, e->ubl.opc);
12286             if (chanpos < 0) {
12287                ast_log(LOG_WARNING, "UBL on unconfigured CIC %d\n", e->ubl.cic);
12288                break;
12289             }
12290             p = linkset->pvts[chanpos];
12291             ast_debug(1, "Unblocking CIC %d\n", e->ubl.cic);
12292             ast_mutex_lock(&p->lock);
12293             p->remotelyblocked = 0;
12294             ast_mutex_unlock(&p->lock);
12295             isup_uba(linkset->ss7, e->ubl.cic, p->dpc);
12296             break;
12297          case ISUP_EVENT_UBA:
12298             chanpos = ss7_find_cic(linkset, e->uba.cic, e->uba.opc);
12299             if (chanpos < 0) {
12300                ast_log(LOG_WARNING, "UBA on unconfigured CIC %d\n", e->uba.cic);
12301                break;
12302             }
12303             p = linkset->pvts[chanpos];
12304             ast_debug(1, "Unblocking CIC %d\n", e->uba.cic);
12305             ast_mutex_lock(&p->lock);
12306             p->locallyblocked = 0;
12307             ast_mutex_unlock(&p->lock);
12308             break;
12309          case ISUP_EVENT_CON:
12310          case ISUP_EVENT_ANM:
12311             if (e->e == ISUP_EVENT_CON)
12312                cic = e->con.cic;
12313             else
12314                cic = e->anm.cic;
12315 
12316             chanpos = ss7_find_cic(linkset, cic, (e->e == ISUP_EVENT_ANM) ? e->anm.opc : e->con.opc);
12317             if (chanpos < 0) {
12318                ast_log(LOG_WARNING, "ANM/CON on unconfigured CIC %d\n", cic);
12319                isup_rel(ss7, (e->e == ISUP_EVENT_ANM) ? e->anm.call : e->con.call, -1);
12320                break;
12321             } else {
12322                p = linkset->pvts[chanpos];
12323                ast_mutex_lock(&p->lock);
12324                if (p->call_level < DAHDI_CALL_LEVEL_CONNECT) {
12325                   p->call_level = DAHDI_CALL_LEVEL_CONNECT;
12326                }
12327                p->subs[SUB_REAL].needanswer = 1;
12328                if (p->dsp && p->dsp_features) {
12329                   ast_dsp_set_features(p->dsp, p->dsp_features);
12330                   p->dsp_features = 0;
12331                }
12332                dahdi_enable_ec(p);
12333                ast_mutex_unlock(&p->lock);
12334             }
12335             break;
12336          case ISUP_EVENT_RLC:
12337             chanpos = ss7_find_cic(linkset, e->rlc.cic, e->rlc.opc);
12338             if (chanpos < 0) {
12339                ast_log(LOG_WARNING, "RLC on unconfigured CIC %d\n", e->rlc.cic);
12340                break;
12341             } else {
12342                p = linkset->pvts[chanpos];
12343                ast_mutex_lock(&p->lock);
12344                if (p->alreadyhungup)
12345                   p->ss7call = NULL;
12346                else
12347                   ast_log(LOG_NOTICE, "Received RLC out and we haven't sent REL.  Ignoring.\n");
12348                ast_mutex_unlock(&p->lock);
12349                }
12350                break;
12351          case ISUP_EVENT_FAA:
12352             chanpos = ss7_find_cic(linkset, e->faa.cic, e->faa.opc);
12353             if (chanpos < 0) {
12354                ast_log(LOG_WARNING, "FAA on unconfigured CIC %d\n", e->faa.cic);
12355                break;
12356             } else {
12357                p = linkset->pvts[chanpos];
12358                ast_debug(1, "FAA received on CIC %d\n", e->faa.cic);
12359                ast_mutex_lock(&p->lock);
12360                if (p->alreadyhungup){
12361                   p->ss7call = NULL;
12362                   ast_log(LOG_NOTICE, "Received FAA and we haven't sent FAR.  Ignoring.\n");
12363                }
12364                ast_mutex_unlock(&p->lock);
12365             }
12366             break;
12367          default:
12368             ast_debug(1, "Unknown event %s\n", ss7_event2str(e->e));
12369             break;
12370          }
12371       }
12372       ast_mutex_unlock(&linkset->lock);
12373    }
12374 
12375    return 0;
12376 }
12377 #endif   /* defined(HAVE_SS7) */
12378 
12379 #if defined(HAVE_SS7)
12380 static void dahdi_ss7_message(struct ss7 *ss7, char *s)
12381 {
12382 #if 0
12383    int i;
12384 
12385    for (i = 0; i < NUM_SPANS; i++)
12386       if (linksets[i].ss7 == ss7)
12387          break;
12388 
12389    ast_verbose("[%d] %s", i+1, s);
12390 #else
12391    ast_verbose("%s", s);
12392 #endif
12393 }
12394 #endif   /* defined(HAVE_SS7) */
12395 
12396 #if defined(HAVE_SS7)
12397 static void dahdi_ss7_error(struct ss7 *ss7, char *s)
12398 {
12399 #if 0
12400    int i;
12401 
12402    for (i = 0; i < NUM_SPANS; i++)
12403       if (linksets[i].ss7 == ss7)
12404          break;
12405 
12406 #else
12407    ast_log(LOG_ERROR, "%s", s);
12408 #endif
12409 }
12410 #endif   /* defined(HAVE_SS7) */
12411 
12412 #if defined(HAVE_OPENR2)
12413 static void *mfcr2_monitor(void *data)
12414 {
12415    struct dahdi_mfcr2 *mfcr2 = data;
12416    /* we should be using pthread_key_create
12417       and allocate pollers dynamically.
12418       I think do_monitor() could be leaking, since it
12419       could be cancelled at any time and is not
12420       using thread keys, why?, */
12421    struct pollfd pollers[sizeof(mfcr2->pvts)];
12422    int res = 0;
12423    int i = 0;
12424    int oldstate = 0;
12425    int quit_loop = 0;
12426    int maxsleep = 20;
12427    int was_idle = 0;
12428    int pollsize = 0;
12429    /* now that we're ready to get calls, unblock our side and
12430       get current line state */
12431    for (i = 0; i < mfcr2->numchans; i++) {
12432       openr2_chan_set_idle(mfcr2->pvts[i]->r2chan);
12433       openr2_chan_handle_cas(mfcr2->pvts[i]->r2chan);
12434    }
12435    while (1) {
12436       /* we trust here that the mfcr2 channel list will not ever change once
12437          the module is loaded */
12438       pollsize = 0;
12439       for (i = 0; i < mfcr2->numchans; i++) {
12440          pollers[i].revents = 0;
12441          pollers[i].events = 0;
12442          if (mfcr2->pvts[i]->owner) {
12443             continue;
12444          }
12445          if (!mfcr2->pvts[i]->r2chan) {
12446             ast_log(LOG_DEBUG, "Wow, no r2chan on channel %d\n", mfcr2->pvts[i]->channel);
12447             quit_loop = 1;
12448             break;
12449          }
12450          openr2_chan_enable_read(mfcr2->pvts[i]->r2chan);
12451          pollers[i].events = POLLIN | POLLPRI;
12452          pollers[i].fd = mfcr2->pvts[i]->subs[SUB_REAL].dfd;
12453          pollsize++;
12454       }
12455       if (quit_loop) {
12456          break;
12457       }
12458       if (pollsize == 0) {
12459          if (!was_idle) {
12460             ast_log(LOG_DEBUG, "Monitor thread going idle since everybody has an owner\n");
12461             was_idle = 1;
12462          }
12463          poll(NULL, 0, maxsleep);
12464          continue;
12465       }
12466       was_idle = 0;
12467       /* probably poll() is a valid cancel point, lets just be on the safe side
12468          by calling pthread_testcancel */
12469       pthread_testcancel();
12470       res = poll(pollers, mfcr2->numchans, maxsleep);
12471       pthread_testcancel();
12472       if ((res < 0) && (errno != EINTR)) {
12473          ast_log(LOG_ERROR, "going out, poll failed: %s\n", strerror(errno));
12474          break;
12475       }
12476       /* do we want to allow to cancel while processing events? */
12477       pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate);
12478       for (i = 0; i < mfcr2->numchans; i++) {
12479          if (pollers[i].revents & POLLPRI || pollers[i].revents & POLLIN) {
12480             openr2_chan_process_event(mfcr2->pvts[i]->r2chan);
12481          }
12482       }
12483       pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
12484    }
12485    ast_log(LOG_NOTICE, "Quitting MFC/R2 monitor thread\n");
12486    return 0;
12487 }
12488 #endif /* HAVE_OPENR2 */
12489 
12490 #if defined(HAVE_PRI)
12491 static struct dahdi_pvt *pri_find_crv(struct dahdi_pri *pri, int crv)
12492 {
12493    struct dahdi_pvt *p;
12494    p = pri->crvs;
12495    while (p) {
12496       if (p->channel == crv)
12497          return p;
12498       p = p->next;
12499    }
12500    return NULL;
12501 }
12502 #endif   /* defined(HAVE_PRI) */
12503 
12504 #if defined(HAVE_PRI)
12505 /*!
12506  * \internal
12507  * \brief Obtain the DAHDI owner channel lock if the owner exists.
12508  * \since 1.8
12509  *
12510  * \param pri DAHDI PRI control structure.
12511  * \param chanpos Channel position in the span.
12512  *
12513  * \note Assumes the pri->lock is already obtained.
12514  * \note Assumes the pri->pvts[chanpos]->lock is already obtained.
12515  *
12516  * \return Nothing
12517  */
12518 static void sig_pri_lock_owner(struct dahdi_pri *pri, int chanpos)
12519 {
12520    for (;;) {
12521       if (!pri->pvts[chanpos]->owner) {
12522          /* There is no owner lock to get. */
12523          break;
12524       }
12525       if (!ast_channel_trylock(pri->pvts[chanpos]->owner)) {
12526          /* We got the lock */
12527          break;
12528       }
12529       /* We must unlock the PRI to avoid the possibility of a deadlock */
12530       ast_mutex_unlock(&pri->lock);
12531       DEADLOCK_AVOIDANCE(&pri->pvts[chanpos]->lock);
12532       ast_mutex_lock(&pri->lock);
12533    }
12534 }
12535 #endif   /* defined(HAVE_PRI) */
12536 
12537 #if defined(HAVE_PRI)
12538 /*!
12539  * \internal
12540  * \brief Find the private structure for the libpri call.
12541  *
12542  * \param pri Span controller structure.
12543  * \param channel LibPRI encoded channel ID.
12544  *
12545  * \note Assumes the pri->lock is already obtained.
12546  *
12547  * \retval array-index into private pointer array on success.
12548  * \retval -1 on error.
12549  */
12550 static int pri_find_principle(struct dahdi_pri *pri, int channel)
12551 {
12552    int x;
12553    int span = PRI_SPAN(channel);
12554    int spanfd;
12555    struct dahdi_params param;
12556    int principle = -1;
12557    int explicit = PRI_EXPLICIT(channel);
12558    channel = PRI_CHANNEL(channel);
12559 
12560    if (!explicit) {
12561       spanfd = pri_active_dchan_fd(pri);
12562       memset(&param, 0, sizeof(param));
12563       if (ioctl(spanfd, DAHDI_GET_PARAMS, &param))
12564          return -1;
12565       span = pris[param.spanno - 1].prilogicalspan;
12566    }
12567 
12568    for (x = 0; x < pri->numchans; x++) {
12569       if (pri->pvts[x] && (pri->pvts[x]->prioffset == channel) && (pri->pvts[x]->logicalspan == span)) {
12570          principle = x;
12571          break;
12572       }
12573    }
12574 
12575    return principle;
12576 }
12577 #endif   /* defined(HAVE_PRI) */
12578 
12579 #if defined(HAVE_PRI)
12580 /*!
12581  * \internal
12582  * \brief Fixup the private structure associated with the libpri call.
12583  *
12584  * \param pri Span controller structure.
12585  * \param principle Array-index into private array to move call to if not already there.
12586  * \param c LibPRI opaque call pointer to find if need to move call.
12587  *
12588  * \note Assumes the pri->lock is already obtained.
12589  *
12590  * \retval principle on success.
12591  * \retval -1 on error.
12592  */
12593 static int pri_fixup_principle(struct dahdi_pri *pri, int principle, q931_call *c)
12594 {
12595    int x;
12596    struct dahdi_pvt *crv;
12597    if (!c) {
12598       if (principle < 0)
12599          return -1;
12600       return principle;
12601    }
12602    if ((principle > -1) &&
12603       (principle < pri->numchans) &&
12604       (pri->pvts[principle]) &&
12605       (pri->pvts[principle]->call == c))
12606       return principle;
12607    /* First, check for other bearers */
12608    for (x = 0; x < pri->numchans; x++) {
12609       if (!pri->pvts[x])
12610          continue;
12611       if (pri->pvts[x]->call == c) {
12612          /* Found our call */
12613          if (principle != x) {
12614             struct dahdi_pvt *new = pri->pvts[principle], *old = pri->pvts[x];
12615 
12616             /* Get locks to safely move to the new private structure. */
12617             ast_mutex_lock(&old->lock);
12618             sig_pri_lock_owner(pri, x);
12619             ast_mutex_lock(&new->lock);
12620 
12621             ast_verb(3, "Moving call (%s) from channel %d to %d.\n",
12622                old->owner ? old->owner->name : "",
12623                old->channel, new->channel);
12624             if (new->owner) {
12625                ast_log(LOG_WARNING,
12626                   "Can't move call (%s) from channel %d to %d.  It is already in use.\n",
12627                   old->owner ? old->owner->name : "",
12628                   old->channel, new->channel);
12629                ast_mutex_unlock(&new->lock);
12630                if (old->owner) {
12631                   ast_channel_unlock(old->owner);
12632                }
12633                ast_mutex_unlock(&old->lock);
12634                return -1;
12635             }
12636 
12637             /* Fix it all up now */
12638             new->owner = old->owner;
12639             old->owner = NULL;
12640             if (new->owner) {
12641                ast_string_field_build(new->owner, name,
12642                   "DAHDI/%d:%d-%d", pri->trunkgroup,
12643                   new->channel, 1);
12644                new->owner->tech_pvt = new;
12645                ast_channel_set_fd(new->owner, 0, new->subs[SUB_REAL].dfd);
12646                new->subs[SUB_REAL].owner = old->subs[SUB_REAL].owner;
12647                old->subs[SUB_REAL].owner = NULL;
12648             } else
12649                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);
12650             new->call = old->call;
12651             old->call = NULL;
12652 
12653             /* Copy any DSP that may be present */
12654             new->dsp = old->dsp;
12655             new->dsp_features = old->dsp_features;
12656             old->dsp = NULL;
12657             old->dsp_features = 0;
12658 
12659             /* Transfer flags from the old channel. */
12660             new->alreadyhungup = old->alreadyhungup;
12661             new->isidlecall = old->isidlecall;
12662             new->progress = old->progress;
12663             new->outgoing = old->outgoing;
12664             new->digital = old->digital;
12665             old->alreadyhungup = 0;
12666             old->isidlecall = 0;
12667             old->progress = 0;
12668             old->outgoing = 0;
12669             old->digital = 0;
12670 
12671             /* More stuff to transfer to the new channel. */
12672             new->call_level = old->call_level;
12673             old->call_level = DAHDI_CALL_LEVEL_IDLE;
12674  
12675             ast_mutex_unlock(&old->lock);
12676             if (new->owner) {
12677                ast_channel_unlock(new->owner);
12678             }
12679             ast_mutex_unlock(&new->lock);
12680          }
12681          return principle;
12682       }
12683    }
12684    /* Now check for a CRV with no bearer */
12685    crv = pri->crvs;
12686    while (crv) {
12687       if (crv->call == c) {
12688          /* This is our match...  Perform some basic checks */
12689          if (crv->bearer)
12690             ast_log(LOG_WARNING, "Trying to fix up call which already has a bearer which isn't the one we think it is\n");
12691          else if (pri->pvts[principle]->owner)
12692             ast_log(LOG_WARNING, "Tring to fix up a call to a bearer which already has an owner!\n");
12693          else {
12694             /* Looks good.  Drop the pseudo channel now, clear up the assignment, and
12695                wakeup the potential sleeper */
12696             dahdi_close_sub(crv, SUB_REAL);
12697             pri->pvts[principle]->call = crv->call;
12698             pri_assign_bearer(crv, pri, pri->pvts[principle]);
12699             ast_debug(1, "Assigning bearer %d/%d to CRV %d:%d\n",
12700                pri->pvts[principle]->logicalspan, pri->pvts[principle]->prioffset,
12701                pri->trunkgroup, crv->channel);
12702             wakeup_sub(crv, SUB_REAL, pri);
12703          }
12704          return principle;
12705       }
12706       crv = crv->next;
12707    }
12708    ast_log(LOG_WARNING, "Call specified, but not found?\n");
12709    return -1;
12710 }
12711 #endif   /* defined(HAVE_PRI) */
12712 
12713 #if defined(HAVE_PRI)
12714 static void *do_idle_thread(void *vchan)
12715 {
12716    struct ast_channel *chan = vchan;
12717    struct dahdi_pvt *pvt = chan->tech_pvt;
12718    struct ast_frame *f;
12719    char ex[80];
12720    /* Wait up to 30 seconds for an answer */
12721    int newms, ms = 30000;
12722    ast_verb(3, "Initiating idle call on channel %s\n", chan->name);
12723    snprintf(ex, sizeof(ex), "%d/%s", pvt->channel, pvt->pri->idledial);
12724    if (ast_call(chan, ex, 0)) {
12725       ast_log(LOG_WARNING, "Idle dial failed on '%s' to '%s'\n", chan->name, ex);
12726       ast_hangup(chan);
12727       return NULL;
12728    }
12729    while ((newms = ast_waitfor(chan, ms)) > 0) {
12730       f = ast_read(chan);
12731       if (!f) {
12732          /* Got hangup */
12733          break;
12734       }
12735       if (f->frametype == AST_FRAME_CONTROL) {
12736          switch (f->subclass) {
12737          case AST_CONTROL_ANSWER:
12738             /* Launch the PBX */
12739             ast_copy_string(chan->exten, pvt->pri->idleext, sizeof(chan->exten));
12740             ast_copy_string(chan->context, pvt->pri->idlecontext, sizeof(chan->context));
12741             chan->priority = 1;
12742             ast_verb(4, "Idle channel '%s' answered, sending to %s@%s\n", chan->name, chan->exten, chan->context);
12743             ast_pbx_run(chan);
12744             /* It's already hungup, return immediately */
12745             return NULL;
12746          case AST_CONTROL_BUSY:
12747             ast_verb(4, "Idle channel '%s' busy, waiting...\n", chan->name);
12748             break;
12749          case AST_CONTROL_CONGESTION:
12750             ast_verb(4, "Idle channel '%s' congested, waiting...\n", chan->name);
12751             break;
12752          };
12753       }
12754       ast_frfree(f);
12755       ms = newms;
12756    }
12757    /* Hangup the channel since nothing happend */
12758    ast_hangup(chan);
12759    return NULL;
12760 }
12761 #endif   /* defined(HAVE_PRI) */
12762 
12763 #if defined(HAVE_PRI)
12764 #ifndef PRI_RESTART
12765 #error "Upgrade your libpri"
12766 #endif
12767 static void dahdi_pri_message(struct pri *pri, char *s)
12768 {
12769    int x, y;
12770    int dchan = -1, span = -1;
12771    int dchancount = 0;
12772 
12773    if (pri) {
12774       for (x = 0; x < NUM_SPANS; x++) {
12775          for (y = 0; y < NUM_DCHANS; y++) {
12776             if (pris[x].dchans[y])
12777                dchancount++;
12778 
12779             if (pris[x].dchans[y] == pri)
12780                dchan = y;
12781          }
12782          if (dchan >= 0) {
12783             span = x;
12784             break;
12785          }
12786          dchancount = 0;
12787       }
12788       if (dchancount > 1 && (span > -1))
12789          ast_verbose("[Span %d D-Channel %d]%s", span, dchan, s);
12790       else
12791          ast_verbose("%s", s);
12792    } else
12793       ast_verbose("%s", s);
12794 
12795    ast_mutex_lock(&pridebugfdlock);
12796 
12797    if (pridebugfd >= 0) {
12798       if (write(pridebugfd, s, strlen(s)) < 0) {
12799          ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
12800       }
12801    }
12802 
12803    ast_mutex_unlock(&pridebugfdlock);
12804 }
12805 #endif   /* defined(HAVE_PRI) */
12806 
12807 #if defined(HAVE_PRI)
12808 static void dahdi_pri_error(struct pri *pri, char *s)
12809 {
12810    int x, y;
12811    int dchan = -1, span = -1;
12812    int dchancount = 0;
12813 
12814    if (pri) {
12815       for (x = 0; x < NUM_SPANS; x++) {
12816          for (y = 0; y < NUM_DCHANS; y++) {
12817             if (pris[x].dchans[y])
12818                dchancount++;
12819 
12820             if (pris[x].dchans[y] == pri)
12821                dchan = y;
12822          }
12823          if (dchan >= 0) {
12824             span = x;
12825             break;
12826          }
12827          dchancount = 0;
12828       }
12829       if ((dchancount > 1) && (span > -1))
12830          ast_log(LOG_ERROR, "[Span %d D-Channel %d] PRI: %s", span, dchan, s);
12831       else
12832          ast_log(LOG_ERROR, "%s", s);
12833    } else
12834       ast_log(LOG_ERROR, "%s", s);
12835 
12836    ast_mutex_lock(&pridebugfdlock);
12837 
12838    if (pridebugfd >= 0) {
12839       if (write(pridebugfd, s, strlen(s)) < 0) {
12840          ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
12841       }
12842    }
12843 
12844    ast_mutex_unlock(&pridebugfdlock);
12845 }
12846 #endif   /* defined(HAVE_PRI) */
12847 
12848 #if defined(HAVE_PRI)
12849 static int pri_check_restart(struct dahdi_pri *pri)
12850 {
12851    do {
12852       pri->resetpos++;
12853    } while ((pri->resetpos < pri->numchans) &&
12854       (!pri->pvts[pri->resetpos] ||
12855       pri->pvts[pri->resetpos]->call ||
12856       pri->pvts[pri->resetpos]->resetting));
12857    if (pri->resetpos < pri->numchans) {
12858       /* Mark the channel as resetting and restart it */
12859       pri->pvts[pri->resetpos]->resetting = 1;
12860       pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[pri->resetpos]));
12861    } else {
12862       pri->resetting = 0;
12863       time(&pri->lastreset);
12864    }
12865    return 0;
12866 }
12867 #endif   /* defined(HAVE_PRI) */
12868 
12869 #if defined(HAVE_PRI)
12870 static int pri_hangup_all(struct dahdi_pvt *p, struct dahdi_pri *pri)
12871 {
12872    int x;
12873    int redo;
12874    ast_mutex_unlock(&pri->lock);
12875    ast_mutex_lock(&p->lock);
12876    do {
12877       redo = 0;
12878       for (x = 0; x < 3; x++) {
12879          while (p->subs[x].owner && ast_channel_trylock(p->subs[x].owner)) {
12880             redo++;
12881             DEADLOCK_AVOIDANCE(&p->lock);
12882          }
12883          if (p->subs[x].owner) {
12884             ast_queue_hangup_with_cause(p->subs[x].owner, AST_CAUSE_PRE_EMPTED);
12885             ast_channel_unlock(p->subs[x].owner);
12886          }
12887       }
12888    } while (redo);
12889    ast_mutex_unlock(&p->lock);
12890    ast_mutex_lock(&pri->lock);
12891    return 0;
12892 }
12893 #endif   /* defined(HAVE_PRI) */
12894 
12895 #if defined(HAVE_PRI)
12896 static char * redirectingreason2str(int redirectingreason)
12897 {
12898    switch (redirectingreason) {
12899    case 0:
12900       return "UNKNOWN";
12901    case 1:
12902       return "BUSY";
12903    case 2:
12904       return "NO_REPLY";
12905    case 0xF:
12906       return "UNCONDITIONAL";
12907    default:
12908       return "NOREDIRECT";
12909    }
12910 }
12911 #endif   /* defined(HAVE_PRI) */
12912 
12913 #if defined(HAVE_PRI)
12914 static void apply_plan_to_number(char *buf, size_t size, const struct dahdi_pri *pri, const char *number, const int plan)
12915 {
12916    if (pri->dialplan == -2) { /* autodetect the TON but leave the number untouched */
12917       snprintf(buf, size, "%s", number);
12918       return;
12919    }
12920    if (ast_strlen_zero(number)) { /* make sure a number exists so prefix isn't placed on an empty string */
12921       if (size) {
12922          *buf = '\0';
12923       }
12924       return;
12925    }
12926    switch (plan) {
12927    case PRI_INTERNATIONAL_ISDN:     /* Q.931 dialplan == 0x11 international dialplan => prepend international prefix digits */
12928       snprintf(buf, size, "%s%s", pri->internationalprefix, number);
12929       break;
12930    case PRI_NATIONAL_ISDN:       /* Q.931 dialplan == 0x21 national dialplan => prepend national prefix digits */
12931       snprintf(buf, size, "%s%s", pri->nationalprefix, number);
12932       break;
12933    case PRI_LOCAL_ISDN:       /* Q.931 dialplan == 0x41 local dialplan => prepend local prefix digits */
12934       snprintf(buf, size, "%s%s", pri->localprefix, number);
12935       break;
12936    case PRI_PRIVATE:       /* Q.931 dialplan == 0x49 private dialplan => prepend private prefix digits */
12937       snprintf(buf, size, "%s%s", pri->privateprefix, number);
12938       break;
12939    case PRI_UNKNOWN:       /* Q.931 dialplan == 0x00 unknown dialplan => prepend unknown prefix digits */
12940       snprintf(buf, size, "%s%s", pri->unknownprefix, number);
12941       break;
12942    default:          /* other Q.931 dialplan => don't twiddle with callingnum */
12943       snprintf(buf, size, "%s", number);
12944       break;
12945    }
12946 }
12947 #endif   /* defined(HAVE_PRI) */
12948 
12949 #if defined(HAVE_PRI)
12950 static void *pri_dchannel(void *vpri)
12951 {
12952    struct dahdi_pri *pri = vpri;
12953    pri_event *e;
12954    struct pollfd fds[NUM_DCHANS];
12955    int res;
12956    int chanpos = 0;
12957    int x;
12958    int haveidles;
12959    int activeidles;
12960    int nextidle = -1;
12961    struct ast_channel *c;
12962    struct timeval tv, lowest, *next;
12963    struct timeval lastidle = ast_tvnow();
12964    int doidling=0;
12965    char *cc;
12966    char idlen[80];
12967    struct ast_channel *idle;
12968    pthread_t p;
12969    time_t t;
12970    int i, which=-1;
12971    int numdchans;
12972    int cause=0;
12973    struct dahdi_pvt *crv;
12974    pthread_t threadid;
12975    char ani2str[6];
12976    char plancallingnum[256];
12977    char plancallingani[256];
12978    char calledtonstr[10];
12979 
12980    pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
12981 
12982    gettimeofday(&lastidle, NULL);
12983    if (!ast_strlen_zero(pri->idledial) && !ast_strlen_zero(pri->idleext)) {
12984       /* Need to do idle dialing, check to be sure though */
12985       cc = strchr(pri->idleext, '@');
12986       if (cc) {
12987          *cc = '\0';
12988          cc++;
12989          ast_copy_string(pri->idlecontext, cc, sizeof(pri->idlecontext));
12990 #if 0
12991          /* Extensions may not be loaded yet */
12992          if (!ast_exists_extension(NULL, pri->idlecontext, pri->idleext, 1, NULL))
12993             ast_log(LOG_WARNING, "Extension '%s @ %s' does not exist\n", pri->idleext, pri->idlecontext);
12994          else
12995 #endif
12996             doidling = 1;
12997       } else
12998          ast_log(LOG_WARNING, "Idle dial string '%s' lacks '@context'\n", pri->idleext);
12999    }
13000    for (;;) {
13001       for (i = 0; i < NUM_DCHANS; i++) {
13002          if (!pri->dchannels[i])
13003             break;
13004          fds[i].fd = pri->fds[i];
13005          fds[i].events = POLLIN | POLLPRI;
13006          fds[i].revents = 0;
13007       }
13008       numdchans = i;
13009       time(&t);
13010       ast_mutex_lock(&pri->lock);
13011       if ((pri->switchtype != PRI_SWITCH_GR303_TMC) && (pri->sig != SIG_BRI_PTMP) && (pri->resetinterval > 0)) {
13012          if (pri->resetting && pri_is_up(pri)) {
13013             if (pri->resetpos < 0)
13014                pri_check_restart(pri);
13015          } else {
13016             if (!pri->resetting  && (t - pri->lastreset) >= pri->resetinterval) {
13017                pri->resetting = 1;
13018                pri->resetpos = -1;
13019             }
13020          }
13021       }
13022       /* Look for any idle channels if appropriate */
13023       if (doidling && pri_is_up(pri)) {
13024          nextidle = -1;
13025          haveidles = 0;
13026          activeidles = 0;
13027          for (x = pri->numchans; x >= 0; x--) {
13028             if (pri->pvts[x] && !pri->pvts[x]->owner &&
13029                !pri->pvts[x]->call) {
13030                if (haveidles < pri->minunused) {
13031                   haveidles++;
13032                } else if (!pri->pvts[x]->resetting) {
13033                   nextidle = x;
13034                   break;
13035                }
13036             } else if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall)
13037                activeidles++;
13038          }
13039          if (nextidle > -1) {
13040             if (ast_tvdiff_ms(ast_tvnow(), lastidle) > 1000) {
13041                /* Don't create a new idle call more than once per second */
13042                snprintf(idlen, sizeof(idlen), "%d/%s", pri->pvts[nextidle]->channel, pri->idledial);
13043                idle = dahdi_request("DAHDI", AST_FORMAT_ULAW, idlen, &cause);
13044                if (idle) {
13045                   pri->pvts[nextidle]->isidlecall = 1;
13046                   if (ast_pthread_create_background(&p, NULL, do_idle_thread, idle)) {
13047                      ast_log(LOG_WARNING, "Unable to start new thread for idle channel '%s'\n", idle->name);
13048                      dahdi_hangup(idle);
13049                   }
13050                } else
13051                   ast_log(LOG_WARNING, "Unable to request channel 'DAHDI/%s' for idle call\n", idlen);
13052                lastidle = ast_tvnow();
13053             }
13054          } else if ((haveidles < pri->minunused) &&
13055             (activeidles > pri->minidle)) {
13056             /* Mark something for hangup if there is something
13057                that can be hungup */
13058             for (x = pri->numchans; x >= 0; x--) {
13059                /* find a candidate channel */
13060                if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall) {
13061                   pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
13062                   haveidles++;
13063                   /* Stop if we have enough idle channels or
13064                     can't spare any more active idle ones */
13065                   if ((haveidles >= pri->minunused) ||
13066                      (activeidles <= pri->minidle))
13067                      break;
13068                }
13069             }
13070          }
13071       }
13072       /* Start with reasonable max */
13073       lowest = ast_tv(60, 0);
13074       for (i = 0; i < NUM_DCHANS; i++) {
13075          /* Find lowest available d-channel */
13076          if (!pri->dchannels[i])
13077             break;
13078          if ((next = pri_schedule_next(pri->dchans[i]))) {
13079             /* We need relative time here */
13080             tv = ast_tvsub(*next, ast_tvnow());
13081             if (tv.tv_sec < 0) {
13082                tv = ast_tv(0,0);
13083             }
13084             if (doidling || pri->resetting) {
13085                if (tv.tv_sec > 1) {
13086                   tv = ast_tv(1, 0);
13087                }
13088             } else {
13089                if (tv.tv_sec > 60) {
13090                   tv = ast_tv(60, 0);
13091                }
13092             }
13093          } else if (doidling || pri->resetting) {
13094             /* Make sure we stop at least once per second if we're
13095                monitoring idle channels */
13096             tv = ast_tv(1,0);
13097          } else {
13098             /* Don't poll for more than 60 seconds */
13099             tv = ast_tv(60, 0);
13100          }
13101          if (!i || ast_tvcmp(tv, lowest) < 0) {
13102             lowest = tv;
13103          }
13104       }
13105       ast_mutex_unlock(&pri->lock);
13106 
13107       pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
13108       pthread_testcancel();
13109       e = NULL;
13110       res = poll(fds, numdchans, lowest.tv_sec * 1000 + lowest.tv_usec / 1000);
13111       pthread_testcancel();
13112       pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
13113 
13114       ast_mutex_lock(&pri->lock);
13115       if (!res) {
13116          for (which = 0; which < NUM_DCHANS; which++) {
13117             if (!pri->dchans[which])
13118                break;
13119             /* Just a timeout, run the scheduler */
13120             e = pri_schedule_run(pri->dchans[which]);
13121             if (e)
13122                break;
13123          }
13124       } else if (res > -1) {
13125          for (which = 0; which < NUM_DCHANS; which++) {
13126             if (!pri->dchans[which])
13127                break;
13128             if (fds[which].revents & POLLPRI) {
13129                /* Check for an event */
13130                x = 0;
13131                res = ioctl(pri->fds[which], DAHDI_GETEVENT, &x);
13132                if (x) {
13133                   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);
13134                   manager_event(EVENT_FLAG_SYSTEM, "PRIEvent",
13135                      "PRIEvent: %s\r\n"
13136                      "PRIEventCode: %d\r\n"
13137                      "D-channel: %s\r\n"
13138                      "Span: %d\r\n",
13139                      event2str(x),
13140                      x,
13141                      pri_order(which),
13142                      pri->span
13143                      );
13144                }
13145                /* Keep track of alarm state */
13146                if (x == DAHDI_EVENT_ALARM) {
13147                   pri->dchanavail[which] &= ~(DCHAN_NOTINALARM | DCHAN_UP);
13148                   pri_find_dchan(pri);
13149                } else if (x == DAHDI_EVENT_NOALARM) {
13150                   pri->dchanavail[which] |= DCHAN_NOTINALARM;
13151                   pri_restart(pri->dchans[which]);
13152                }
13153 
13154                ast_debug(1, "Got event %s (%d) on D-channel for span %d\n", event2str(x), x, pri->span);
13155             } else if (fds[which].revents & POLLIN) {
13156                e = pri_check_event(pri->dchans[which]);
13157             }
13158             if (e)
13159                break;
13160          }
13161       } else if (errno != EINTR)
13162          ast_log(LOG_WARNING, "pri_event returned error %d (%s)\n", errno, strerror(errno));
13163 
13164       if (e) {
13165          if (pri->debug)
13166             pri_dump_event(pri->dchans[which], e);
13167 
13168          if (e->e != PRI_EVENT_DCHAN_DOWN) {
13169             if (!(pri->dchanavail[which] & DCHAN_UP)) {
13170                ast_verb(2, "%s D-Channel on span %d up\n", pri_order(which), pri->span);
13171             }
13172             pri->dchanavail[which] |= DCHAN_UP;
13173          } else if (pri->sig != SIG_BRI_PTMP) {
13174             if (pri->dchanavail[which] & DCHAN_UP) {
13175                ast_verb(2, "%s D-Channel on span %d down\n", pri_order(which), pri->span);
13176             }
13177             pri->dchanavail[which] &= ~DCHAN_UP;
13178          }
13179 
13180          if ((e->e != PRI_EVENT_DCHAN_UP) && (e->e != PRI_EVENT_DCHAN_DOWN) && (pri->pri != pri->dchans[which]))
13181             /* Must be an NFAS group that has the secondary dchan active */
13182             pri->pri = pri->dchans[which];
13183 
13184          switch (e->e) {
13185          case PRI_EVENT_DCHAN_UP:
13186             pri->no_d_channels = 0;
13187             if (!pri->pri) pri_find_dchan(pri);
13188 
13189             /* Note presense of D-channel */
13190             time(&pri->lastreset);
13191 
13192             /* Restart in 5 seconds */
13193             if (pri->resetinterval > -1) {
13194                pri->lastreset -= pri->resetinterval;
13195                pri->lastreset += 5;
13196             }
13197             pri->resetting = 0;
13198             /* Take the channels from inalarm condition */
13199             for (i = 0; i < pri->numchans; i++)
13200                if (pri->pvts[i]) {
13201                   pri->pvts[i]->inalarm = 0;
13202                }
13203             break;
13204          case PRI_EVENT_DCHAN_DOWN:
13205             pri_find_dchan(pri);
13206             if (!pri_is_up(pri)) {
13207                pri->resetting = 0;
13208                /* Hangup active channels and put them in alarm mode */
13209                for (i = 0; i < pri->numchans; i++) {
13210                   struct dahdi_pvt *p = pri->pvts[i];
13211                   if (p) {
13212                      if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
13213                         /* T309 is not enabled : hangup calls when alarm occurs */
13214                         if (p->call) {
13215                            if (p->pri && p->pri->pri) {
13216                               pri_hangup(p->pri->pri, p->call, -1);
13217                               pri_destroycall(p->pri->pri, p->call);
13218                               p->call = NULL;
13219                            } else
13220                               ast_log(LOG_WARNING, "The PRI Call have not been destroyed\n");
13221                         }
13222                         if (p->realcall) {
13223                            pri_hangup_all(p->realcall, pri);
13224                         } else if (p->owner)
13225                            p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
13226                      }
13227                      /* For PTMP connections with non persistent layer 2 we want
13228                       * to *not* declare inalarm unless there actually is an alarm */
13229                      if (p->sig != SIG_BRI_PTMP) {
13230                         p->inalarm = 1;
13231                      }
13232                   }
13233                }
13234             }
13235             break;
13236          case PRI_EVENT_RESTART:
13237             if (e->restart.channel > -1) {
13238                chanpos = pri_find_principle(pri, e->restart.channel);
13239                if (chanpos < 0)
13240                   ast_log(LOG_WARNING, "Restart requested on odd/unavailable channel number %d/%d on span %d\n",
13241                      PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span);
13242                else {
13243                   ast_verb(3, "B-channel %d/%d restarted on span %d\n",
13244                         PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span);
13245                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
13246                   if (pri->pvts[chanpos]->call) {
13247                      pri_destroycall(pri->pri, pri->pvts[chanpos]->call);
13248                      pri->pvts[chanpos]->call = NULL;
13249                   }
13250                   /* Force soft hangup if appropriate */
13251                   if (pri->pvts[chanpos]->realcall)
13252                      pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
13253                   else if (pri->pvts[chanpos]->owner)
13254                      pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
13255                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13256                }
13257             } else {
13258                ast_verb(3, "Restart on requested on entire span %d\n", pri->span);
13259                for (x = 0; x < pri->numchans; x++)
13260                   if (pri->pvts[x]) {
13261                      ast_mutex_lock(&pri->pvts[x]->lock);
13262                      if (pri->pvts[x]->call) {
13263                         pri_destroycall(pri->pri, pri->pvts[x]->call);
13264                         pri->pvts[x]->call = NULL;
13265                      }
13266                      if (pri->pvts[x]->realcall)
13267                         pri_hangup_all(pri->pvts[x]->realcall, pri);
13268                      else if (pri->pvts[x]->owner)
13269                         pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
13270                      ast_mutex_unlock(&pri->pvts[x]->lock);
13271                   }
13272             }
13273             break;
13274          case PRI_EVENT_KEYPAD_DIGIT:
13275             chanpos = pri_find_principle(pri, e->digit.channel);
13276             if (chanpos < 0) {
13277                ast_log(LOG_WARNING, "KEYPAD_DIGITs received on unconfigured channel %d/%d span %d\n",
13278                   PRI_SPAN(e->digit.channel), PRI_CHANNEL(e->digit.channel), pri->span);
13279             } else {
13280                chanpos = pri_fixup_principle(pri, chanpos, e->digit.call);
13281                if (chanpos > -1) {
13282                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
13283                   /* queue DTMF frame if the PBX for this call was already started (we're forwarding KEYPAD_DIGITs further on */
13284                   if ((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && pri->pvts[chanpos]->call==e->digit.call && pri->pvts[chanpos]->owner) {
13285                      /* how to do that */
13286                      int digitlen = strlen(e->digit.digits);
13287                      char digit;
13288                      int i;
13289                      for (i = 0; i < digitlen; i++) {
13290                         digit = e->digit.digits[i];
13291                         {
13292                            struct ast_frame f = { AST_FRAME_DTMF, digit, };
13293                            dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
13294                         }
13295                      }
13296                   }
13297                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13298                }
13299             }
13300             break;
13301 
13302          case PRI_EVENT_INFO_RECEIVED:
13303             chanpos = pri_find_principle(pri, e->ring.channel);
13304             if (chanpos < 0) {
13305                ast_log(LOG_WARNING, "INFO received on unconfigured channel %d/%d span %d\n",
13306                   PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
13307             } else {
13308                chanpos = pri_fixup_principle(pri, chanpos, e->ring.call);
13309                if (chanpos > -1) {
13310                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
13311                   /* queue DTMF frame if the PBX for this call was already started (we're forwarding INFORMATION further on */
13312                   if ((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && pri->pvts[chanpos]->call==e->ring.call && pri->pvts[chanpos]->owner) {
13313                      /* how to do that */
13314                      int digitlen = strlen(e->ring.callednum);
13315                      char digit;
13316                      int i;
13317                      for (i = 0; i < digitlen; i++) {
13318                         digit = e->ring.callednum[i];
13319                         {
13320                            struct ast_frame f = { AST_FRAME_DTMF, digit, };
13321                            dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
13322                         }
13323                      }
13324                   }
13325                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13326                }
13327             }
13328             break;
13329          case PRI_EVENT_RING:
13330             crv = NULL;
13331             if (e->ring.channel == -1)
13332                chanpos = pri_find_empty_chan(pri, 1);
13333             else
13334                chanpos = pri_find_principle(pri, e->ring.channel);
13335             /* if no channel specified find one empty */
13336             if (chanpos < 0) {
13337                ast_log(LOG_WARNING, "Ring requested on unconfigured channel %d/%d span %d\n",
13338                   PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
13339             } else {
13340                ast_mutex_lock(&pri->pvts[chanpos]->lock);
13341                if (pri->pvts[chanpos]->owner) {
13342                   if (pri->pvts[chanpos]->call == e->ring.call) {
13343                      ast_log(LOG_WARNING, "Duplicate setup requested on channel %d/%d already in use on span %d\n",
13344                         PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
13345                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13346                      break;
13347                   } else {
13348                      /* This is where we handle initial glare */
13349                      ast_debug(1, "Ring requested on channel %d/%d already in use or previously requested on span %d.  Attempting to renegotiate channel.\n",
13350                      PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
13351                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13352                      chanpos = -1;
13353                   }
13354                }
13355                if (chanpos > -1)
13356                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13357             }
13358             if ((chanpos < 0) && (e->ring.flexible))
13359                chanpos = pri_find_empty_chan(pri, 1);
13360             if (chanpos > -1) {
13361                ast_mutex_lock(&pri->pvts[chanpos]->lock);
13362                if (pri->switchtype == PRI_SWITCH_GR303_TMC) {
13363                   /* Should be safe to lock CRV AFAIK while bearer is still locked */
13364                   crv = pri_find_crv(pri, pri_get_crv(pri->pri, e->ring.call, NULL));
13365                   if (crv)
13366                      ast_mutex_lock(&crv->lock);
13367                   if (!crv || crv->owner) {
13368                      pri->pvts[chanpos]->call = NULL;
13369                      if (crv) {
13370                         if (crv->owner)
13371                            crv->owner->_softhangup |= AST_SOFTHANGUP_DEV;
13372                         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);
13373                      } else
13374                         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);
13375                      pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_INVALID_CALL_REFERENCE);
13376                      if (crv)
13377                         ast_mutex_unlock(&crv->lock);
13378                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13379                      break;
13380                   }
13381                }
13382                pri->pvts[chanpos]->call = e->ring.call;
13383                apply_plan_to_number(plancallingnum, sizeof(plancallingnum), pri, e->ring.callingnum, e->ring.callingplan);
13384                if (pri->pvts[chanpos]->use_callerid) {
13385                   ast_shrink_phone_number(plancallingnum);
13386                   ast_copy_string(pri->pvts[chanpos]->cid_num, plancallingnum, sizeof(pri->pvts[chanpos]->cid_num));
13387 #ifdef PRI_ANI
13388                   if (!ast_strlen_zero(e->ring.callingani)) {
13389                      apply_plan_to_number(plancallingani, sizeof(plancallingani), pri, e->ring.callingani, e->ring.callingplanani);
13390                      ast_shrink_phone_number(plancallingani);
13391                      ast_copy_string(pri->pvts[chanpos]->cid_ani, plancallingani, sizeof(pri->pvts[chanpos]->cid_ani));
13392                   } else {
13393                      pri->pvts[chanpos]->cid_ani[0] = '\0';
13394                   }
13395 #endif
13396                   ast_copy_string(pri->pvts[chanpos]->cid_name, e->ring.callingname, sizeof(pri->pvts[chanpos]->cid_name));
13397                   pri->pvts[chanpos]->cid_ton = e->ring.callingplan; /* this is the callingplan (TON/NPI), e->ring.callingplan>>4 would be the TON */
13398                } else {
13399                   pri->pvts[chanpos]->cid_num[0] = '\0';
13400                   pri->pvts[chanpos]->cid_ani[0] = '\0';
13401                   pri->pvts[chanpos]->cid_name[0] = '\0';
13402                   pri->pvts[chanpos]->cid_ton = 0;
13403                }
13404                apply_plan_to_number(pri->pvts[chanpos]->rdnis, sizeof(pri->pvts[chanpos]->rdnis), pri,
13405                   e->ring.redirectingnum, e->ring.callingplanrdnis);
13406 
13407                /* Set DNID on all incoming calls -- even immediate */
13408                ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid));
13409 
13410                /* If immediate=yes go to s|1 */
13411                if (pri->pvts[chanpos]->immediate) {
13412                   ast_verb(3, "Going to extension s|1 because of immediate=yes\n");
13413                   pri->pvts[chanpos]->exten[0] = 's';
13414                   pri->pvts[chanpos]->exten[1] = '\0';
13415                }
13416                /* Get called number */
13417                else if (!ast_strlen_zero(e->ring.callednum)) {
13418                   ast_copy_string(pri->pvts[chanpos]->exten, e->ring.callednum, sizeof(pri->pvts[chanpos]->exten));
13419                } else if (pri->overlapdial)
13420                   pri->pvts[chanpos]->exten[0] = '\0';
13421                else {
13422                   /* Some PRI circuits are set up to send _no_ digits.  Handle them as 's'. */
13423                   pri->pvts[chanpos]->exten[0] = 's';
13424                   pri->pvts[chanpos]->exten[1] = '\0';
13425                }
13426                /* No number yet, but received "sending complete"? */
13427                if (e->ring.complete && (ast_strlen_zero(e->ring.callednum))) {
13428                   ast_verb(3, "Going to extension s|1 because of Complete received\n");
13429                   pri->pvts[chanpos]->exten[0] = 's';
13430                   pri->pvts[chanpos]->exten[1] = '\0';
13431                }
13432 
13433                /* Make sure extension exists (or in overlap dial mode, can exist) */
13434                if (((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && ast_canmatch_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) ||
13435                   ast_exists_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) {
13436                   /* Setup law */
13437                   int law;
13438                   if (pri->switchtype != PRI_SWITCH_GR303_TMC) {
13439                      /* Set to audio mode at this point */
13440                      law = 1;
13441                      if (ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &law) == -1)
13442                         ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", pri->pvts[chanpos]->channel, law, strerror(errno));
13443                   }
13444                   if (e->ring.layer1 == PRI_LAYER_1_ALAW)
13445                      law = DAHDI_LAW_ALAW;
13446                   else
13447                      law = DAHDI_LAW_MULAW;
13448                   res = dahdi_setlaw(pri->pvts[chanpos]->subs[SUB_REAL].dfd, law);
13449                   if (res < 0)
13450                      ast_log(LOG_WARNING, "Unable to set law on channel %d\n", pri->pvts[chanpos]->channel);
13451                   res = set_actual_gain(pri->pvts[chanpos]->subs[SUB_REAL].dfd, 0, pri->pvts[chanpos]->rxgain, pri->pvts[chanpos]->txgain, law);
13452                   if (res < 0)
13453                      ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", pri->pvts[chanpos]->channel);
13454                   if (e->ring.complete || !(pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
13455                      /* Just announce proceeding */
13456                      pri->pvts[chanpos]->call_level = DAHDI_CALL_LEVEL_PROCEEDING;
13457                      pri_proceeding(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 0);
13458                   } else if (pri->switchtype == PRI_SWITCH_GR303_TMC) {
13459                      pri->pvts[chanpos]->call_level = DAHDI_CALL_LEVEL_CONNECT;
13460                      pri_answer(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
13461                   } else {
13462                      pri->pvts[chanpos]->call_level = DAHDI_CALL_LEVEL_OVERLAP;
13463                      pri_need_more_info(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
13464                   }
13465                   /* Get the use_callingpres state */
13466                   pri->pvts[chanpos]->callingpres = e->ring.callingpres;
13467 
13468                   /* Start PBX */
13469                   if (!e->ring.complete
13470                      && (pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)
13471                      && ast_matchmore_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) {
13472                      /*
13473                       * Release the PRI lock while we create the channel
13474                       * so other threads can send D channel messages.
13475                       */
13476                      ast_mutex_unlock(&pri->lock);
13477                      if (crv) {
13478                         /* Set bearer and such */
13479                         pri_assign_bearer(crv, pri, pri->pvts[chanpos]);
13480                         c = dahdi_new(crv, AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype);
13481                         pri->pvts[chanpos]->owner = &inuse;
13482                         ast_debug(1, "Started up crv %d:%d on bearer channel %d\n", pri->trunkgroup, crv->channel, crv->bearer->channel);
13483                      } else {
13484                         c = dahdi_new(pri->pvts[chanpos], AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype);
13485                      }
13486                      ast_mutex_lock(&pri->lock);
13487                      if (c) {
13488                         if (!ast_strlen_zero(e->ring.callingsubaddr)) {
13489                            pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr);
13490                         }
13491                         if (e->ring.ani2 >= 0) {
13492                            snprintf(ani2str, sizeof(ani2str), "%d", e->ring.ani2);
13493                            pbx_builtin_setvar_helper(c, "ANI2", ani2str);
13494                            pri->pvts[chanpos]->cid_ani2 = e->ring.ani2;
13495                         }
13496 
13497 #ifdef SUPPORT_USERUSER
13498                         if (!ast_strlen_zero(e->ring.useruserinfo)) {
13499                            pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo);
13500                         }
13501 #endif
13502 
13503                         snprintf(calledtonstr, sizeof(calledtonstr), "%d", e->ring.calledplan);
13504                         pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr);
13505                         if (e->ring.redirectingreason >= 0)
13506                            pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason));
13507 
13508                         if (!pri->pvts[chanpos]->digital) {
13509                            /*
13510                             * Call has a channel.
13511                             * Indicate that we are providing dialtone.
13512                             */
13513                            pri->pvts[chanpos]->progress = 1;/* No need to send plain PROGRESS again. */
13514 #ifdef HAVE_PRI_PROG_W_CAUSE
13515                            pri_progress_with_cause(pri->pri, e->ring.call,
13516                               PVT_TO_CHANNEL(pri->pvts[chanpos]), 1, -1);/* no cause at all */
13517 #else
13518                            pri_progress(pri->pri, e->ring.call,
13519                               PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
13520 #endif
13521                         }
13522                      }
13523                      if (c && !ast_pthread_create_detached(&threadid, NULL, ss_thread, c)) {
13524                         ast_verb(3, "Accepting overlap call from '%s' to '%s' on channel %d/%d, span %d\n",
13525                            plancallingnum, S_OR(pri->pvts[chanpos]->exten, "<unspecified>"),
13526                            pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
13527                      } else {
13528                         ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n",
13529                            pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
13530                         if (c)
13531                            ast_hangup(c);
13532                         else {
13533                            pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION);
13534                            pri->pvts[chanpos]->call = NULL;
13535                         }
13536                      }
13537                   } else {
13538                      /*
13539                       * Release the PRI lock while we create the channel
13540                       * so other threads can send D channel messages.
13541                       */
13542                      ast_mutex_unlock(&pri->lock);
13543                      c = dahdi_new(pri->pvts[chanpos], AST_STATE_RING, 0, SUB_REAL, law, e->ring.ctype);
13544                      ast_mutex_lock(&pri->lock);
13545                      if (c) {
13546                         /*
13547                          * It is reasonably safe to set the following
13548                          * channel variables while the PRI and DAHDI private
13549                          * structures are locked.  The PBX has not been
13550                          * started yet and it is unlikely that any other task
13551                          * will do anything with the channel we have just
13552                          * created.
13553                          */
13554                         if (!ast_strlen_zero(e->ring.callingsubaddr)) {
13555                            pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr);
13556                         }
13557                         if (e->ring.ani2 >= 0) {
13558                            snprintf(ani2str, sizeof(ani2str), "%d", e->ring.ani2);
13559                            pbx_builtin_setvar_helper(c, "ANI2", ani2str);
13560                            pri->pvts[chanpos]->cid_ani2 = e->ring.ani2;
13561                         }
13562 
13563 #ifdef SUPPORT_USERUSER
13564                         if (!ast_strlen_zero(e->ring.useruserinfo)) {
13565                            pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo);
13566                         }
13567 #endif
13568 
13569                         if (e->ring.redirectingreason >= 0)
13570                            pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason));
13571 
13572                         snprintf(calledtonstr, sizeof(calledtonstr), "%d", e->ring.calledplan);
13573                         pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr);
13574                      }
13575                      if (c && !ast_pbx_start(c)) {
13576                         ast_verb(3, "Accepting call from '%s' to '%s' on channel %d/%d, span %d\n",
13577                            plancallingnum, pri->pvts[chanpos]->exten,
13578                            pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
13579 
13580                         dahdi_enable_ec(pri->pvts[chanpos]);
13581                      } else {
13582                         ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n",
13583                            pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
13584                         if (c) {
13585                            ast_hangup(c);
13586                         } else {
13587                            pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION);
13588                            pri->pvts[chanpos]->call = NULL;
13589                         }
13590                      }
13591                   }
13592                } else {
13593                   ast_verb(3, "Extension '%s' in context '%s' from '%s' does not exist.  Rejecting call on channel %d/%d, span %d\n",
13594                      pri->pvts[chanpos]->exten, pri->pvts[chanpos]->context, pri->pvts[chanpos]->cid_num, pri->pvts[chanpos]->logicalspan,
13595                      pri->pvts[chanpos]->prioffset, pri->span);
13596                   pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_UNALLOCATED);
13597                   pri->pvts[chanpos]->call = NULL;
13598                   pri->pvts[chanpos]->exten[0] = '\0';
13599                }
13600                if (crv)
13601                   ast_mutex_unlock(&crv->lock);
13602                ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13603             } else {
13604                if (e->ring.flexible)
13605                   pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION);
13606                else
13607                   pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_REQUESTED_CHAN_UNAVAIL);
13608             }
13609             break;
13610          case PRI_EVENT_RINGING:
13611             chanpos = pri_find_principle(pri, e->ringing.channel);
13612             if (chanpos < 0) {
13613                ast_log(LOG_WARNING, "Ringing requested on unconfigured channel %d/%d span %d\n",
13614                   PRI_SPAN(e->ringing.channel), PRI_CHANNEL(e->ringing.channel), pri->span);
13615             } else {
13616                chanpos = pri_fixup_principle(pri, chanpos, e->ringing.call);
13617                if (chanpos < 0) {
13618                   ast_log(LOG_WARNING, "Ringing requested on channel %d/%d not in use on span %d\n",
13619                      PRI_SPAN(e->ringing.channel), PRI_CHANNEL(e->ringing.channel), pri->span);
13620                } else {
13621                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
13622                   if (ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) {
13623                      dahdi_enable_ec(pri->pvts[chanpos]);
13624                      pri->pvts[chanpos]->subs[SUB_REAL].needringing = 1;
13625                      if (pri->pvts[chanpos]->call_level < DAHDI_CALL_LEVEL_ALERTING) {
13626                         pri->pvts[chanpos]->call_level = DAHDI_CALL_LEVEL_ALERTING;
13627                      }
13628                   } else
13629                      ast_debug(1, "Deferring ringing notification because of extra digits to dial...\n");
13630 
13631                   if (
13632 #ifdef PRI_PROGRESS_MASK
13633                      e->ringing.progressmask & PRI_PROG_INBAND_AVAILABLE
13634 #else
13635                      e->ringing.progress == 8
13636 #endif
13637                      ) {
13638                      /* Now we can do call progress detection */
13639                      if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
13640                         /* RINGING detection isn't required because we got ALERTING signal */
13641                         ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features & ~DSP_PROGRESS_RINGING);
13642                         pri->pvts[chanpos]->dsp_features = 0;
13643                      }
13644                   }
13645 
13646 #ifdef SUPPORT_USERUSER
13647                   if (!ast_strlen_zero(e->ringing.useruserinfo)) {
13648                      struct ast_channel *owner = pri->pvts[chanpos]->owner;
13649                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13650                      pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->ringing.useruserinfo);
13651                      ast_mutex_lock(&pri->pvts[chanpos]->lock);
13652                   }
13653 #endif
13654 
13655                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13656                }
13657             }
13658             break;
13659          case PRI_EVENT_PROGRESS:
13660             /* Get chan value if e->e is not PRI_EVNT_RINGING */
13661             chanpos = pri_find_principle(pri, e->proceeding.channel);
13662             if (chanpos > -1) {
13663                if ((!pri->pvts[chanpos]->progress)
13664 #ifdef PRI_PROGRESS_MASK
13665                   || (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE)
13666 #else
13667                   || (e->proceeding.progress == 8)
13668 #endif
13669                   ) {
13670                   struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, };
13671 
13672                   if (e->proceeding.cause > -1) {
13673                      ast_verb(3, "PROGRESS with cause code %d received\n", e->proceeding.cause);
13674 
13675                      /* Work around broken, out of spec USER_BUSY cause in a progress message */
13676                      if (e->proceeding.cause == AST_CAUSE_USER_BUSY) {
13677                         if (pri->pvts[chanpos]->owner) {
13678                            ast_verb(3, "PROGRESS with 'user busy' received, signalling AST_CONTROL_BUSY instead of AST_CONTROL_PROGRESS\n");
13679 
13680                            pri->pvts[chanpos]->owner->hangupcause = e->proceeding.cause;
13681                            f.subclass = AST_CONTROL_BUSY;
13682                         }
13683                      }
13684                   }
13685 
13686                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
13687                   ast_debug(1, "Queuing frame from PRI_EVENT_PROGRESS on channel %d/%d span %d\n",
13688                      pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span);
13689                   dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
13690                   if (
13691 #ifdef PRI_PROGRESS_MASK
13692                      e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE
13693 #else
13694                      e->proceeding.progress == 8
13695 #endif
13696                      ) {
13697                      /* Now we can do call progress detection */
13698                      if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
13699                         ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
13700                         pri->pvts[chanpos]->dsp_features = 0;
13701                      }
13702                      /* Bring voice path up */
13703                      f.subclass = AST_CONTROL_PROGRESS;
13704                      dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
13705                   }
13706                   pri->pvts[chanpos]->progress = 1;
13707                   pri->pvts[chanpos]->dialing = 0;
13708                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13709                }
13710             }
13711             break;
13712          case PRI_EVENT_PROCEEDING:
13713             chanpos = pri_find_principle(pri, e->proceeding.channel);
13714             if (chanpos > -1) {
13715                ast_mutex_lock(&pri->pvts[chanpos]->lock);
13716                if (pri->pvts[chanpos]->call_level < DAHDI_CALL_LEVEL_PROCEEDING) {
13717                   struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROCEEDING, };
13718 
13719                   pri->pvts[chanpos]->call_level = DAHDI_CALL_LEVEL_PROCEEDING;
13720                   ast_debug(1, "Queuing frame from PRI_EVENT_PROCEEDING on channel %d/%d span %d\n",
13721                      pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span);
13722                   dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
13723                   if (
13724 #ifdef PRI_PROGRESS_MASK
13725                      e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE
13726 #else
13727                      e->proceeding.progress == 8
13728 #endif
13729                      ) {
13730                      /* Now we can do call progress detection */
13731                      if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
13732                         ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
13733                         pri->pvts[chanpos]->dsp_features = 0;
13734                      }
13735                      /* Bring voice path up */
13736                      f.subclass = AST_CONTROL_PROGRESS;
13737                      dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
13738                   }
13739                   pri->pvts[chanpos]->dialing = 0;
13740                }
13741                ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13742             }
13743             break;
13744          case PRI_EVENT_FACNAME:
13745             chanpos = pri_find_principle(pri, e->facname.channel);
13746             if (chanpos < 0) {
13747                ast_log(LOG_WARNING, "Facility Name requested on unconfigured channel %d/%d span %d\n",
13748                   PRI_SPAN(e->facname.channel), PRI_CHANNEL(e->facname.channel), pri->span);
13749             } else {
13750                chanpos = pri_fixup_principle(pri, chanpos, e->facname.call);
13751                if (chanpos < 0) {
13752                   ast_log(LOG_WARNING, "Facility Name requested on channel %d/%d not in use on span %d\n",
13753                      PRI_SPAN(e->facname.channel), PRI_CHANNEL(e->facname.channel), pri->span);
13754                } else if (pri->pvts[chanpos]->use_callerid) {
13755                   /* Re-use *69 field for PRI */
13756                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
13757                   ast_copy_string(pri->pvts[chanpos]->lastcid_num, e->facname.callingnum, sizeof(pri->pvts[chanpos]->lastcid_num));
13758                   ast_copy_string(pri->pvts[chanpos]->lastcid_name, e->facname.callingname, sizeof(pri->pvts[chanpos]->lastcid_name));
13759                   pri->pvts[chanpos]->subs[SUB_REAL].needcallerid = 1;
13760                   dahdi_enable_ec(pri->pvts[chanpos]);
13761                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13762                }
13763             }
13764             break;
13765          case PRI_EVENT_ANSWER:
13766             chanpos = pri_find_principle(pri, e->answer.channel);
13767             if (chanpos < 0) {
13768                ast_log(LOG_WARNING, "Answer on unconfigured channel %d/%d span %d\n",
13769                   PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span);
13770             } else {
13771                chanpos = pri_fixup_principle(pri, chanpos, e->answer.call);
13772                if (chanpos < 0) {
13773                   ast_log(LOG_WARNING, "Answer requested on channel %d/%d not in use on span %d\n",
13774                      PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span);
13775                } else {
13776                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
13777                   /* Now we can do call progress detection */
13778 
13779                   /* We changed this so it turns on the DSP no matter what... progress or no progress.
13780                    * By this time, we need DTMF detection and other features that were previously disabled
13781                    * -- Matt F */
13782                   if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
13783                      ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
13784                      pri->pvts[chanpos]->dsp_features = 0;
13785                   }
13786                   if (pri->pvts[chanpos]->realcall && (pri->pvts[chanpos]->realcall->sig == SIG_FXSKS)) {
13787                      ast_debug(1, "Starting up GR-303 trunk now that we got CONNECT...\n");
13788                      x = DAHDI_START;
13789                      res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
13790                      if (res < 0) {
13791                         if (errno != EINPROGRESS) {
13792                            ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno));
13793                         }
13794                      }
13795                   } else if (!ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) {
13796                      pri->pvts[chanpos]->dialing = 1;
13797                      /* Send any "w" waited stuff */
13798                      res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_DIAL, &pri->pvts[chanpos]->dop);
13799                      if (res < 0) {
13800                         ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", pri->pvts[chanpos]->channel, strerror(errno));
13801                         pri->pvts[chanpos]->dop.dialstr[0] = '\0';
13802                      } else
13803                         ast_debug(1, "Sent deferred digit string: %s\n", pri->pvts[chanpos]->dop.dialstr);
13804 
13805                      pri->pvts[chanpos]->dop.dialstr[0] = '\0';
13806                   } else if (pri->pvts[chanpos]->confirmanswer) {
13807                      ast_debug(1, "Waiting on answer confirmation on channel %d!\n", pri->pvts[chanpos]->channel);
13808                   } else {
13809                      pri->pvts[chanpos]->dialing = 0;
13810                      if (pri->pvts[chanpos]->call_level < DAHDI_CALL_LEVEL_CONNECT) {
13811                         pri->pvts[chanpos]->call_level = DAHDI_CALL_LEVEL_CONNECT;
13812                      }
13813                      pri->pvts[chanpos]->subs[SUB_REAL].needanswer =1;
13814                      /* Enable echo cancellation if it's not on already */
13815                      dahdi_enable_ec(pri->pvts[chanpos]);
13816                   }
13817 
13818 #ifdef SUPPORT_USERUSER
13819                   if (!ast_strlen_zero(e->answer.useruserinfo)) {
13820                      struct ast_channel *owner = pri->pvts[chanpos]->owner;
13821                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13822                      pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->answer.useruserinfo);
13823                      ast_mutex_lock(&pri->pvts[chanpos]->lock);
13824                   }
13825 #endif
13826 
13827                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13828                }
13829             }
13830             break;
13831          case PRI_EVENT_HANGUP:
13832             chanpos = pri_find_principle(pri, e->hangup.channel);
13833             if (chanpos < 0) {
13834                ast_log(LOG_WARNING, "Hangup requested on unconfigured channel %d/%d span %d\n",
13835                   PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
13836             } else {
13837                chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
13838                if (chanpos > -1) {
13839                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
13840                   if (!pri->pvts[chanpos]->alreadyhungup) {
13841                      /* we're calling here dahdi_hangup so once we get there we need to clear p->call after calling pri_hangup */
13842                      pri->pvts[chanpos]->alreadyhungup = 1;
13843                      if (pri->pvts[chanpos]->realcall)
13844                         pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
13845                      else if (pri->pvts[chanpos]->owner) {
13846                         /* Queue a BUSY instead of a hangup if our cause is appropriate */
13847                         pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
13848                         switch (pri->pvts[chanpos]->owner->_state) {
13849                         case AST_STATE_BUSY:
13850                         case AST_STATE_UP:
13851                            pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
13852                            break;
13853                         default:
13854                            if (!pri->pvts[chanpos]->outgoing) {
13855                               /*
13856                                * The incoming call leg hung up before getting
13857                                * connected so just hangup the call.
13858                                */
13859                               pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
13860                               break;
13861                            }
13862                            switch (e->hangup.cause) {
13863                            case PRI_CAUSE_USER_BUSY:
13864                               pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1;
13865                               break;
13866                            case PRI_CAUSE_CALL_REJECTED:
13867                            case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
13868                            case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
13869                            case PRI_CAUSE_SWITCH_CONGESTION:
13870                            case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
13871                            case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
13872                               pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1;
13873                               break;
13874                            default:
13875                               pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
13876                            }
13877                            break;
13878                         }
13879                      }
13880                      ast_verb(3, "Channel %d/%d, span %d got hangup, cause %d\n",
13881                            pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, e->hangup.cause);
13882                   } else {
13883                      pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
13884                      pri->pvts[chanpos]->call = NULL;
13885                   }
13886                   if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) {
13887                      ast_verb(3, "Forcing restart of channel %d/%d on span %d since channel reported in use\n",
13888                            PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
13889                      pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
13890                      pri->pvts[chanpos]->resetting = 1;
13891                   }
13892                   if (e->hangup.aoc_units > -1)
13893                      ast_verb(3, "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
13894                            pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
13895 
13896 #ifdef SUPPORT_USERUSER
13897                   if (pri->pvts[chanpos]->owner && !ast_strlen_zero(e->hangup.useruserinfo)) {
13898                      struct ast_channel *owner = pri->pvts[chanpos]->owner;
13899                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13900                      pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
13901                      ast_mutex_lock(&pri->pvts[chanpos]->lock);
13902                   }
13903 #endif
13904 
13905                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13906                } else {
13907                   ast_log(LOG_WARNING, "Hangup on bad channel %d/%d on span %d\n",
13908                      PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
13909                }
13910             }
13911             break;
13912 #ifndef PRI_EVENT_HANGUP_REQ
13913 #error please update libpri
13914 #endif
13915          case PRI_EVENT_HANGUP_REQ:
13916             chanpos = pri_find_principle(pri, e->hangup.channel);
13917             if (chanpos < 0) {
13918                ast_log(LOG_WARNING, "Hangup REQ requested on unconfigured channel %d/%d span %d\n",
13919                   PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
13920             } else {
13921                chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
13922                if (chanpos > -1) {
13923                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
13924                   if (pri->pvts[chanpos]->realcall)
13925                      pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
13926                   else if (pri->pvts[chanpos]->owner) {
13927                      pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
13928                      switch (pri->pvts[chanpos]->owner->_state) {
13929                      case AST_STATE_BUSY:
13930                      case AST_STATE_UP:
13931                         pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
13932                         break;
13933                      default:
13934                         if (!pri->pvts[chanpos]->outgoing) {
13935                            /*
13936                             * The incoming call leg hung up before getting
13937                             * connected so just hangup the call.
13938                             */
13939                            pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
13940                            break;
13941                         }
13942                         switch (e->hangup.cause) {
13943                         case PRI_CAUSE_USER_BUSY:
13944                            pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1;
13945                            break;
13946                         case PRI_CAUSE_CALL_REJECTED:
13947                         case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
13948                         case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
13949                         case PRI_CAUSE_SWITCH_CONGESTION:
13950                         case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
13951                         case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
13952                            pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1;
13953                            break;
13954                         default:
13955                            pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
13956                            break;
13957                         }
13958                         break;
13959                      }
13960                      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);
13961                      if (e->hangup.aoc_units > -1)
13962                         ast_verb(3, "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
13963                               pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
13964                   } else {
13965                      pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
13966                      pri->pvts[chanpos]->call = NULL;
13967                   }
13968                   if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) {
13969                      ast_verb(3, "Forcing restart of channel %d/%d span %d since channel reported in use\n",
13970                            PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
13971                      pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
13972                      pri->pvts[chanpos]->resetting = 1;
13973                   }
13974 
13975 #ifdef SUPPORT_USERUSER
13976                   if (!ast_strlen_zero(e->hangup.useruserinfo)) {
13977                      struct ast_channel *owner = pri->pvts[chanpos]->owner;
13978                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13979                      pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
13980                      ast_mutex_lock(&pri->pvts[chanpos]->lock);
13981                   }
13982 #endif
13983 
13984                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13985                } else {
13986                   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);
13987                }
13988             }
13989             break;
13990          case PRI_EVENT_HANGUP_ACK:
13991             chanpos = pri_find_principle(pri, e->hangup.channel);
13992             if (chanpos < 0) {
13993                ast_log(LOG_WARNING, "Hangup ACK requested on unconfigured channel number %d/%d span %d\n",
13994                   PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
13995             } else {
13996                chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
13997                if (chanpos > -1) {
13998                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
13999                   pri->pvts[chanpos]->call = NULL;
14000                   pri->pvts[chanpos]->resetting = 0;
14001                   if (pri->pvts[chanpos]->owner) {
14002                      ast_verb(3, "Channel %d/%d, span %d got hangup ACK\n", PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
14003                   }
14004 
14005 #ifdef SUPPORT_USERUSER
14006                   if (!ast_strlen_zero(e->hangup.useruserinfo)) {
14007                      struct ast_channel *owner = pri->pvts[chanpos]->owner;
14008                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
14009                      pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
14010                      ast_mutex_lock(&pri->pvts[chanpos]->lock);
14011                   }
14012 #endif
14013 
14014                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
14015                }
14016             }
14017             break;
14018          case PRI_EVENT_CONFIG_ERR:
14019             ast_log(LOG_WARNING, "PRI Error on span %d: %s\n", pri->span, e->err.err);
14020             break;
14021          case PRI_EVENT_RESTART_ACK:
14022             chanpos = pri_find_principle(pri, e->restartack.channel);
14023             if (chanpos < 0) {
14024                /* Sometime switches (e.g. I421 / British Telecom) don't give us the
14025                   channel number, so we have to figure it out...  This must be why
14026                   everybody resets exactly a channel at a time. */
14027                for (x = 0; x < pri->numchans; x++) {
14028                   if (pri->pvts[x] && pri->pvts[x]->resetting) {
14029                      chanpos = x;
14030                      ast_mutex_lock(&pri->pvts[chanpos]->lock);
14031                      ast_debug(1, "Assuming restart ack is really for channel %d/%d span %d\n", pri->pvts[chanpos]->logicalspan,
14032                         pri->pvts[chanpos]->prioffset, pri->span);
14033                      if (pri->pvts[chanpos]->realcall)
14034                         pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
14035                      else if (pri->pvts[chanpos]->owner) {
14036                         ast_log(LOG_WARNING, "Got restart ack on channel %d/%d with owner on span %d\n", pri->pvts[chanpos]->logicalspan,
14037                            pri->pvts[chanpos]->prioffset, pri->span);
14038                         pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
14039                      }
14040                      pri->pvts[chanpos]->resetting = 0;
14041                      ast_verb(3, "B-channel %d/%d successfully restarted on span %d\n", pri->pvts[chanpos]->logicalspan,
14042                            pri->pvts[chanpos]->prioffset, pri->span);
14043                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
14044                      if (pri->resetting)
14045                         pri_check_restart(pri);
14046                      break;
14047                   }
14048                }
14049                if (chanpos < 0) {
14050                   ast_log(LOG_WARNING, "Restart ACK requested on strange channel %d/%d span %d\n",
14051                      PRI_SPAN(e->restartack.channel), PRI_CHANNEL(e->restartack.channel), pri->span);
14052                }
14053             } else {
14054                if (pri->pvts[chanpos]) {
14055                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
14056                   if (pri->pvts[chanpos]->realcall)
14057                      pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
14058                   else if (pri->pvts[chanpos]->owner) {
14059                      ast_log(LOG_WARNING, "Got restart ack on channel %d/%d span %d with owner\n",
14060                         PRI_SPAN(e->restartack.channel), PRI_CHANNEL(e->restartack.channel), pri->span);
14061                      pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
14062                   }
14063                   pri->pvts[chanpos]->resetting = 0;
14064                   pri->pvts[chanpos]->inservice = 1;
14065                   ast_verb(3, "B-channel %d/%d successfully restarted on span %d\n", pri->pvts[chanpos]->logicalspan,
14066                            pri->pvts[chanpos]->prioffset, pri->span);
14067                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
14068                   if (pri->resetting)
14069                      pri_check_restart(pri);
14070                }
14071             }
14072             break;
14073          case PRI_EVENT_SETUP_ACK:
14074             chanpos = pri_find_principle(pri, e->setup_ack.channel);
14075             if (chanpos < 0) {
14076                ast_log(LOG_WARNING, "Received SETUP_ACKNOWLEDGE on unconfigured channel %d/%d span %d\n",
14077                   PRI_SPAN(e->setup_ack.channel), PRI_CHANNEL(e->setup_ack.channel), pri->span);
14078             } else {
14079                chanpos = pri_fixup_principle(pri, chanpos, e->setup_ack.call);
14080                if (chanpos > -1) {
14081                   unsigned int len;
14082 
14083                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
14084                   if (pri->pvts[chanpos]->call_level < DAHDI_CALL_LEVEL_OVERLAP) {
14085                      pri->pvts[chanpos]->call_level = DAHDI_CALL_LEVEL_OVERLAP;
14086                   }
14087 
14088                   /* Send any queued digits */
14089                   len = strlen(pri->pvts[chanpos]->dialdest);
14090                   for (x = 0; x < len; ++x) {
14091                      ast_debug(1, "Sending pending digit '%c'\n", pri->pvts[chanpos]->dialdest[x]);
14092                      pri_information(pri->pri, pri->pvts[chanpos]->call,
14093                         pri->pvts[chanpos]->dialdest[x]);
14094                   }
14095 
14096                   if (!pri->pvts[chanpos]->progress
14097                      && (pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)
14098                      && !pri->pvts[chanpos]->digital) {
14099                      /*
14100                       * Call has a channel.
14101                       * Indicate for overlap dialing that dialtone may be present.
14102                       */
14103                      struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, };
14104                      dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
14105                      pri->pvts[chanpos]->progress = 1;/* Claim to have seen inband-information */
14106                      pri->pvts[chanpos]->dialing = 0;
14107                      if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
14108                         ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
14109                         pri->pvts[chanpos]->dsp_features = 0;
14110                      }
14111                   }
14112                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
14113                } else
14114                   ast_log(LOG_WARNING, "Unable to move channel %d!\n", e->setup_ack.channel);
14115             }
14116             break;
14117          case PRI_EVENT_NOTIFY:
14118             chanpos = pri_find_principle(pri, e->notify.channel);
14119             if (chanpos < 0) {
14120                ast_log(LOG_WARNING, "Received NOTIFY on unconfigured channel %d/%d span %d\n",
14121                   PRI_SPAN(e->notify.channel), PRI_CHANNEL(e->notify.channel), pri->span);
14122             } else if (!pri->discardremoteholdretrieval) {
14123                struct ast_frame f = { AST_FRAME_CONTROL, };
14124                ast_mutex_lock(&pri->pvts[chanpos]->lock);
14125                switch (e->notify.info) {
14126                case PRI_NOTIFY_REMOTE_HOLD:
14127                   f.subclass = AST_CONTROL_HOLD;
14128                   dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
14129                   break;
14130                case PRI_NOTIFY_REMOTE_RETRIEVAL:
14131                   f.subclass = AST_CONTROL_UNHOLD;
14132                   dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
14133                   break;
14134                }
14135                ast_mutex_unlock(&pri->pvts[chanpos]->lock);
14136             }
14137             break;
14138          default:
14139             ast_debug(1, "Event: %d\n", e->e);
14140          }
14141       }
14142       ast_mutex_unlock(&pri->lock);
14143    }
14144    /* Never reached */
14145    return NULL;
14146 }
14147 #endif   /* defined(HAVE_PRI) */
14148 
14149 #if defined(HAVE_PRI)
14150 static int start_pri(struct dahdi_pri *pri)
14151 {
14152    int res, x;
14153    struct dahdi_params p;
14154    struct dahdi_bufferinfo bi;
14155    struct dahdi_spaninfo si;
14156    int i;
14157 
14158    for (i = 0; i < NUM_DCHANS; i++) {
14159       if (!pri->dchannels[i])
14160          break;
14161       pri->fds[i] = open("/dev/dahdi/channel", O_RDWR);
14162       x = pri->dchannels[i];
14163       if ((pri->fds[i] < 0) || (ioctl(pri->fds[i],DAHDI_SPECIFY,&x) == -1)) {
14164          ast_log(LOG_ERROR, "Unable to open D-channel %d (%s)\n", x, strerror(errno));
14165          return -1;
14166       }
14167       memset(&p, 0, sizeof(p));
14168       res = ioctl(pri->fds[i], DAHDI_GET_PARAMS, &p);
14169       if (res) {
14170          dahdi_close_pri_fd(pri, i);
14171          ast_log(LOG_ERROR, "Unable to get parameters for D-channel %d (%s)\n", x, strerror(errno));
14172          return -1;
14173       }
14174       if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC)) {
14175          dahdi_close_pri_fd(pri, i);
14176          ast_log(LOG_ERROR, "D-channel %d is not in HDLC/FCS mode.\n", x);
14177          return -1;
14178       }
14179       memset(&si, 0, sizeof(si));
14180       res = ioctl(pri->fds[i], DAHDI_SPANSTAT, &si);
14181       if (res) {
14182          dahdi_close_pri_fd(pri, i);
14183          ast_log(LOG_ERROR, "Unable to get span state for D-channel %d (%s)\n", x, strerror(errno));
14184       }
14185       if (!si.alarms)
14186          pri->dchanavail[i] |= DCHAN_NOTINALARM;
14187       else
14188          pri->dchanavail[i] &= ~DCHAN_NOTINALARM;
14189       memset(&bi, 0, sizeof(bi));
14190       bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
14191       bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
14192       bi.numbufs = 32;
14193       bi.bufsize = 1024;
14194       if (ioctl(pri->fds[i], DAHDI_SET_BUFINFO, &bi)) {
14195          ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", x, strerror(errno));
14196          dahdi_close_pri_fd(pri, i);
14197          return -1;
14198       }
14199       switch (pri->sig) {
14200       case SIG_BRI:
14201          pri->dchans[i] = pri_new_bri(pri->fds[i], 1, pri->nodetype, pri->switchtype);
14202          break;
14203       case SIG_BRI_PTMP:
14204          pri->dchans[i] = pri_new_bri(pri->fds[i], 0, pri->nodetype, pri->switchtype);
14205          break;
14206       default:
14207          pri->dchans[i] = pri_new(pri->fds[i], pri->nodetype, pri->switchtype);
14208          break;
14209       }
14210       /* Force overlap dial if we're doing GR-303! */
14211       if (pri->switchtype == PRI_SWITCH_GR303_TMC)
14212          pri->overlapdial |= DAHDI_OVERLAPDIAL_BOTH;
14213       pri_set_overlapdial(pri->dchans[i],(pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)?1:0);
14214 #ifdef HAVE_PRI_PROG_W_CAUSE
14215       pri_set_chan_mapping_logical(pri->dchans[i], pri->qsigchannelmapping == DAHDI_CHAN_MAPPING_LOGICAL);
14216 #endif
14217 #ifdef HAVE_PRI_INBANDDISCONNECT
14218       pri_set_inbanddisconnect(pri->dchans[i], pri->inbanddisconnect);
14219 #endif
14220       /* Enslave to master if appropriate */
14221       if (i)
14222          pri_enslave(pri->dchans[0], pri->dchans[i]);
14223       if (!pri->dchans[i]) {
14224          dahdi_close_pri_fd(pri, i);
14225          ast_log(LOG_ERROR, "Unable to create PRI structure\n");
14226          return -1;
14227       }
14228       pri_set_debug(pri->dchans[i], DEFAULT_PRI_DEBUG);
14229       pri_set_nsf(pri->dchans[i], pri->nsf);
14230 #ifdef PRI_GETSET_TIMERS
14231       for (x = 0; x < PRI_MAX_TIMERS; x++) {
14232          if (pritimers[x] != 0)
14233             pri_set_timer(pri->dchans[i], x, pritimers[x]);
14234       }
14235 #endif
14236    }
14237    /* Assume primary is the one we use */
14238    pri->pri = pri->dchans[0];
14239    pri->resetpos = -1;
14240    if (ast_pthread_create_background(&pri->master, NULL, pri_dchannel, pri)) {
14241       for (i = 0; i < NUM_DCHANS; i++) {
14242          if (!pri->dchannels[i])
14243             break;
14244          dahdi_close_pri_fd(pri, i);
14245       }
14246       ast_log(LOG_ERROR, "Unable to spawn D-channel: %s\n", strerror(errno));
14247       return -1;
14248    }
14249    return 0;
14250 }
14251 #endif   /* defined(HAVE_PRI) */
14252 
14253 #if defined(HAVE_PRI)
14254 static char *complete_span_helper(const char *line, const char *word, int pos, int state, int rpos)
14255 {
14256    int which, span;
14257    char *ret = NULL;
14258 
14259    if (pos != rpos)
14260       return ret;
14261 
14262    for (which = span = 0; span < NUM_SPANS; span++) {
14263       if (pris[span].pri && ++which > state) {
14264          if (asprintf(&ret, "%d", span + 1) < 0) { /* user indexes start from 1 */
14265             ast_log(LOG_WARNING, "asprintf() failed: %s\n", strerror(errno));
14266          }
14267          break;
14268       }
14269    }
14270    return ret;
14271 }
14272 #endif   /* defined(HAVE_PRI) */
14273 
14274 #if defined(HAVE_PRI)
14275 static char *complete_span_4(const char *line, const char *word, int pos, int state)
14276 {
14277    return complete_span_helper(line,word,pos,state,3);
14278 }
14279 #endif   /* defined(HAVE_PRI) */
14280 
14281 #if defined(HAVE_PRI)
14282 static char *handle_pri_set_debug_file(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14283 {
14284    int myfd;
14285    switch (cmd) {
14286    case CLI_INIT:
14287       e->command = "pri set debug file";
14288       e->usage = "Usage: pri set debug file [output-file]\n"
14289          "       Sends PRI debug output to the specified output file\n";
14290       return NULL;
14291    case CLI_GENERATE:
14292       return NULL;
14293    }
14294    if (a->argc < 5)
14295       return CLI_SHOWUSAGE;
14296 
14297    if (ast_strlen_zero(a->argv[4]))
14298       return CLI_SHOWUSAGE;
14299 
14300    myfd = open(a->argv[4], O_CREAT|O_WRONLY, AST_FILE_MODE);
14301    if (myfd < 0) {
14302       ast_cli(a->fd, "Unable to open '%s' for writing\n", a->argv[4]);
14303       return CLI_SUCCESS;
14304    }
14305 
14306    ast_mutex_lock(&pridebugfdlock);
14307 
14308    if (pridebugfd >= 0)
14309       close(pridebugfd);
14310 
14311    pridebugfd = myfd;
14312    ast_copy_string(pridebugfilename,a->argv[4],sizeof(pridebugfilename));
14313    ast_mutex_unlock(&pridebugfdlock);
14314    ast_cli(a->fd, "PRI debug output will be sent to '%s'\n", a->argv[4]);
14315    return CLI_SUCCESS;
14316 }
14317 #endif   /* defined(HAVE_PRI) */
14318 
14319 #if defined(HAVE_PRI)
14320 static char *handle_pri_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14321 {
14322    int span;
14323    int x;
14324    int level = 0;
14325    switch (cmd) {
14326    case CLI_INIT:
14327       e->command = "pri set debug {on|off|0|1|2} span";
14328       e->usage =
14329          "Usage: pri set debug {<level>|on|off} span <span>\n"
14330          "       Enables debugging on a given PRI span\n";
14331       return NULL;
14332    case CLI_GENERATE:
14333       return complete_span_4(a->line, a->word, a->pos, a->n);
14334    }
14335    if (a->argc < 6) {
14336       return CLI_SHOWUSAGE;
14337    }
14338 
14339    if (!strcasecmp(a->argv[3], "on")) {
14340       level = 1;
14341    } else if (!strcasecmp(a->argv[3], "off")) {
14342       level = 0;
14343    } else {
14344       level = atoi(a->argv[3]);
14345    }
14346    span = atoi(a->argv[5]);
14347    if ((span < 1) || (span > NUM_SPANS)) {
14348       ast_cli(a->fd, "Invalid span %s.  Should be a number %d to %d\n", a->argv[5], 1, NUM_SPANS);
14349       return CLI_SUCCESS;
14350    }
14351    if (!pris[span-1].pri) {
14352       ast_cli(a->fd, "No PRI running on span %d\n", span);
14353       return CLI_SUCCESS;
14354    }
14355    for (x = 0; x < NUM_DCHANS; x++) {
14356       if (pris[span-1].dchans[x]) {
14357          if (level == 1) {
14358             pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU |
14359                PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE |
14360                PRI_DEBUG_Q921_STATE);
14361             ast_cli(a->fd, "Enabled debugging on span %d\n", span);
14362          } else if (level == 0) {
14363             pri_set_debug(pris[span-1].dchans[x], 0);
14364             //close the file if it's set
14365             ast_mutex_lock(&pridebugfdlock);
14366             close(pridebugfd);
14367             pridebugfd = -1;
14368             ast_cli(a->fd, "PRI debug output to file disabled\n");
14369             ast_mutex_unlock(&pridebugfdlock);
14370          } else {
14371             pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU |
14372                PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE |
14373                PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_STATE);
14374             ast_cli(a->fd, "Enabled debugging on span %d\n", span);
14375          }
14376       }
14377    }
14378    return CLI_SUCCESS;
14379 }
14380 #endif   /* defined(HAVE_PRI) */
14381 
14382 #if defined(HAVE_PRI)
14383 static void build_status(char *s, size_t len, int status, int active)
14384 {
14385    if (!s || len < 1) {
14386       return;
14387    }
14388    s[0] = '\0';
14389    if (status & DCHAN_PROVISIONED)
14390       strncat(s, "Provisioned, ", len - strlen(s) - 1);
14391    if (!(status & DCHAN_NOTINALARM))
14392       strncat(s, "In Alarm, ", len - strlen(s) - 1);
14393    if (status & DCHAN_UP)
14394       strncat(s, "Up", len - strlen(s) - 1);
14395    else
14396       strncat(s, "Down", len - strlen(s) - 1);
14397    if (active)
14398       strncat(s, ", Active", len - strlen(s) - 1);
14399    else
14400       strncat(s, ", Standby", len - strlen(s) - 1);
14401    s[len - 1] = '\0';
14402 }
14403 #endif   /* defined(HAVE_PRI) */
14404 
14405 #if defined(HAVE_PRI)
14406 static char *handle_pri_show_spans(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14407 {
14408    int span;
14409    int x;
14410    char status[256];
14411 
14412    switch (cmd) {
14413    case CLI_INIT:
14414       e->command = "pri show spans";
14415       e->usage =
14416          "Usage: pri show spans\n"
14417          "       Displays PRI Information\n";
14418       return NULL;
14419    case CLI_GENERATE:
14420       return NULL;
14421    }
14422 
14423    if (a->argc != 3)
14424       return CLI_SHOWUSAGE;
14425 
14426    for (span = 0; span < NUM_SPANS; span++) {
14427       if (pris[span].pri) {
14428          for (x = 0; x < NUM_DCHANS; x++) {
14429             if (pris[span].dchannels[x]) {
14430                build_status(status, sizeof(status), pris[span].dchanavail[x], pris[span].dchans[x] == pris[span].pri);
14431                ast_cli(a->fd, "PRI span %d/%d: %s\n", span + 1, x, status);
14432             }
14433          }
14434       }
14435    }
14436    return CLI_SUCCESS;
14437 }
14438 #endif   /* defined(HAVE_PRI) */
14439 
14440 #if defined(HAVE_PRI)
14441 static char *handle_pri_show_span(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14442 {
14443    int span;
14444    int x;
14445    char status[256];
14446    switch (cmd) {
14447    case CLI_INIT:
14448       e->command = "pri show span";
14449       e->usage =
14450          "Usage: pri show span <span>\n"
14451          "       Displays PRI Information on a given PRI span\n";
14452       return NULL;
14453    case CLI_GENERATE:
14454       return complete_span_4(a->line, a->word, a->pos, a->n);
14455    }
14456 
14457    if (a->argc < 4)
14458       return CLI_SHOWUSAGE;
14459    span = atoi(a->argv[3]);
14460    if ((span < 1) || (span > NUM_SPANS)) {
14461       ast_cli(a->fd, "Invalid span '%s'.  Should be a number from %d to %d\n", a->argv[3], 1, NUM_SPANS);
14462       return CLI_SUCCESS;
14463    }
14464    if (!pris[span-1].pri) {
14465       ast_cli(a->fd, "No PRI running on span %d\n", span);
14466       return CLI_SUCCESS;
14467    }
14468    for (x = 0; x < NUM_DCHANS; x++) {
14469       if (pris[span-1].dchannels[x]) {
14470 #ifdef PRI_DUMP_INFO_STR
14471          char *info_str = NULL;
14472 #endif
14473          ast_cli(a->fd, "%s D-channel: %d\n", pri_order(x), pris[span-1].dchannels[x]);
14474          build_status(status, sizeof(status), pris[span-1].dchanavail[x], pris[span-1].dchans[x] == pris[span-1].pri);
14475          ast_cli(a->fd, "Status: %s\n", status);
14476          ast_mutex_lock(&pris[span - 1].lock);
14477 #ifdef PRI_DUMP_INFO_STR
14478          info_str = pri_dump_info_str(pris[span-1].pri);
14479          if (info_str) {
14480             ast_cli(a->fd, "%s", info_str);
14481             ast_free(info_str);
14482          }
14483 #else
14484          pri_dump_info(pris[span-1].pri);
14485 #endif
14486          ast_mutex_unlock(&pris[span - 1].lock);
14487          ast_cli(a->fd, "Overlap Recv: %s\n\n", (pris[span-1].overlapdial & DAHDI_OVERLAPDIAL_INCOMING)?"Yes":"No");
14488       }
14489    }
14490    return CLI_SUCCESS;
14491 }
14492 #endif   /* defined(HAVE_PRI) */
14493 
14494 #if defined(HAVE_PRI)
14495 static char *handle_pri_show_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14496 {
14497    int x;
14498    int span;
14499    int count=0;
14500    int debug=0;
14501 
14502    switch (cmd) {
14503    case CLI_INIT:
14504       e->command = "pri show debug";
14505       e->usage =
14506          "Usage: pri show debug\n"
14507          "  Show the debug state of pri spans\n";
14508       return NULL;
14509    case CLI_GENERATE:
14510       return NULL;
14511    }
14512 
14513    for (span = 0; span < NUM_SPANS; span++) {
14514       if (pris[span].pri) {
14515          for (x = 0; x < NUM_DCHANS; x++) {
14516             debug = 0;
14517             if (pris[span].dchans[x]) {
14518                debug = pri_get_debug(pris[span].dchans[x]);
14519                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" );
14520                count++;
14521             }
14522          }
14523       }
14524 
14525    }
14526    ast_mutex_lock(&pridebugfdlock);
14527    if (pridebugfd >= 0)
14528       ast_cli(a->fd, "Logging PRI debug to file %s\n", pridebugfilename);
14529    ast_mutex_unlock(&pridebugfdlock);
14530 
14531    if (!count)
14532       ast_cli(a->fd, "No debug set or no PRI running\n");
14533    return CLI_SUCCESS;
14534 }
14535 #endif   /* defined(HAVE_PRI) */
14536 
14537 #if defined(HAVE_PRI)
14538 static char *handle_pri_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14539 {
14540    switch (cmd) {
14541    case CLI_INIT:
14542       e->command = "pri show version";
14543       e->usage =
14544          "Usage: pri show version\n"
14545          "Show libpri version information\n";
14546       return NULL;
14547    case CLI_GENERATE:
14548       return NULL;
14549    }
14550 
14551    ast_cli(a->fd, "libpri version: %s\n", pri_get_version());
14552 
14553    return CLI_SUCCESS;
14554 }
14555 #endif   /* defined(HAVE_PRI) */
14556 
14557 #if defined(HAVE_PRI)
14558 static struct ast_cli_entry dahdi_pri_cli[] = {
14559    AST_CLI_DEFINE(handle_pri_debug, "Enables PRI debugging on a span"),
14560    AST_CLI_DEFINE(handle_pri_show_spans, "Displays PRI Information"),
14561    AST_CLI_DEFINE(handle_pri_show_span, "Displays PRI Information"),
14562    AST_CLI_DEFINE(handle_pri_show_debug, "Displays current PRI debug settings"),
14563    AST_CLI_DEFINE(handle_pri_set_debug_file, "Sends PRI debug output to the specified file"),
14564    AST_CLI_DEFINE(handle_pri_version, "Displays libpri version"),
14565 };
14566 #endif   /* defined(HAVE_PRI) */
14567 
14568 #ifdef HAVE_OPENR2
14569 
14570 static char *handle_mfcr2_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14571 {
14572    switch (cmd) {
14573    case CLI_INIT:
14574       e->command = "mfcr2 show version";
14575       e->usage =
14576          "Usage: mfcr2 show version\n"
14577          "       Shows the version of the OpenR2 library being used.\n";
14578       return NULL;
14579    case CLI_GENERATE:
14580       return NULL;
14581    }
14582    ast_cli(a->fd, "OpenR2 version: %s, revision: %s\n", openr2_get_version(), openr2_get_revision());
14583    return CLI_SUCCESS;
14584 }
14585 
14586 static char *handle_mfcr2_show_variants(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14587 {
14588 #define FORMAT "%4s %40s\n"
14589    int i = 0;
14590    int numvariants = 0;
14591    const openr2_variant_entry_t *variants;
14592    switch (cmd) {
14593    case CLI_INIT:
14594       e->command = "mfcr2 show variants";
14595       e->usage =
14596          "Usage: mfcr2 show variants\n"
14597          "       Shows the list of MFC/R2 variants supported.\n";
14598       return NULL;
14599    case CLI_GENERATE:
14600       return NULL;
14601    }
14602    if (!(variants = openr2_proto_get_variant_list(&numvariants))) {
14603       ast_cli(a->fd, "Failed to get list of variants.\n");
14604       return CLI_FAILURE;
14605    }
14606    ast_cli(a->fd, FORMAT, "Variant Code", "Country");
14607    for (i = 0; i < numvariants; i++) {
14608       ast_cli(a->fd, FORMAT, variants[i].name, variants[i].country);
14609    }
14610    return CLI_SUCCESS;
14611 #undef FORMAT
14612 }
14613 
14614 static char *handle_mfcr2_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14615 {
14616 #define FORMAT "%4s %-7.7s %-7.7s %-8.8s %-9.9s %-16.16s %-8.8s %-8.8s\n"
14617    int filtertype = 0;
14618    int targetnum = 0;
14619    char channo[5];
14620    char anino[5];
14621    char dnisno[5];
14622    struct dahdi_pvt *p;
14623    openr2_context_t *r2context;
14624    openr2_variant_t r2variant;
14625    switch (cmd) {
14626    case CLI_INIT:
14627       e->command = "mfcr2 show channels [group|context]";
14628       e->usage =
14629          "Usage: mfcr2 show channels [group <group> | context <context>]\n"
14630          "       Shows the DAHDI channels configured with MFC/R2 signaling.\n";
14631       return NULL;
14632    case CLI_GENERATE:
14633       return NULL;
14634    }
14635    if (!((a->argc == 3) || (a->argc == 5))) {
14636       return CLI_SHOWUSAGE;
14637    }
14638    if (a->argc == 5) {
14639       if (!strcasecmp(a->argv[3], "group")) {
14640          targetnum = atoi(a->argv[4]);
14641          if ((targetnum < 0) || (targetnum > 63))
14642             return CLI_SHOWUSAGE;
14643          targetnum = 1 << targetnum;
14644          filtertype = 1;
14645       } else if (!strcasecmp(a->argv[3], "context")) {
14646          filtertype = 2;
14647       } else {
14648          return CLI_SHOWUSAGE;
14649       }
14650    }
14651    ast_cli(a->fd, FORMAT, "Chan", "Variant", "Max ANI", "Max DNIS", "ANI First", "Immediate Accept", "Tx CAS", "Rx CAS");
14652    ast_mutex_lock(&iflock);
14653    p = iflist;
14654    for (p = iflist; p; p = p->next) {
14655       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14656          continue;
14657       }
14658       if (filtertype) {
14659          switch(filtertype) {
14660          case 1: /* mfcr2 show channels group <group> */
14661             if (p->group != targetnum) {
14662                continue;
14663             }
14664             break;
14665          case 2: /* mfcr2 show channels context <context> */
14666             if (strcasecmp(p->context, a->argv[4])) {
14667                continue;
14668             }
14669             break;
14670          default:
14671             ;
14672          }
14673       }
14674       r2context = openr2_chan_get_context(p->r2chan);
14675       r2variant = openr2_context_get_variant(r2context);
14676       snprintf(channo, sizeof(channo), "%d", p->channel);
14677       snprintf(anino, sizeof(anino), "%d", openr2_context_get_max_ani(r2context));
14678       snprintf(dnisno, sizeof(dnisno), "%d", openr2_context_get_max_dnis(r2context));
14679       ast_cli(a->fd, FORMAT, channo, openr2_proto_get_variant_string(r2variant),
14680             anino, dnisno, openr2_context_get_ani_first(r2context) ? "Yes" : "No",
14681             openr2_context_get_immediate_accept(r2context) ? "Yes" : "No",
14682             openr2_chan_get_tx_cas_string(p->r2chan), openr2_chan_get_rx_cas_string(p->r2chan));
14683    }
14684    ast_mutex_unlock(&iflock);
14685    return CLI_SUCCESS;
14686 #undef FORMAT
14687 }
14688 
14689 static char *handle_mfcr2_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14690 {
14691    struct dahdi_pvt *p = NULL;
14692    int channo = 0;
14693    char *toklevel = NULL;
14694    char *saveptr = NULL;
14695    char *logval = NULL;
14696    openr2_log_level_t loglevel = OR2_LOG_NOTHING;
14697    openr2_log_level_t tmplevel = OR2_LOG_NOTHING;
14698    switch (cmd) {
14699    case CLI_INIT:
14700       e->command = "mfcr2 set debug";
14701       e->usage =
14702          "Usage: mfcr2 set debug <loglevel> <channel>\n"
14703          "       Set a new logging level for the specified channel.\n"
14704          "       If no channel is specified the logging level will be applied to all channels.\n";
14705       return NULL;
14706    case CLI_GENERATE:
14707       return NULL;
14708    }
14709    if (a->argc < 4) {
14710       return CLI_SHOWUSAGE;
14711    }
14712    channo = (a->argc == 5) ? atoi(a->argv[4]) : -1;
14713    logval = ast_strdupa(a->argv[3]);
14714    toklevel = strtok_r(logval, ",", &saveptr);
14715    if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
14716       ast_cli(a->fd, "Invalid MFC/R2 logging level '%s'.\n", a->argv[3]);
14717       return CLI_FAILURE;
14718    } else if (OR2_LOG_NOTHING == tmplevel) {
14719       loglevel = tmplevel;
14720    } else {
14721       loglevel |= tmplevel;
14722       while ((toklevel = strtok_r(NULL, ",", &saveptr))) {
14723          if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
14724             ast_cli(a->fd, "Ignoring invalid logging level: '%s'.\n", toklevel);
14725             continue;
14726          }
14727          loglevel |= tmplevel;
14728       }
14729    }
14730    ast_mutex_lock(&iflock);
14731    for (p = iflist; p; p = p->next) {
14732       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14733          continue;
14734       }
14735       if ((channo != -1) && (p->channel != channo )) {
14736          continue;
14737       }
14738       openr2_chan_set_log_level(p->r2chan, loglevel);
14739       if (channo != -1) {
14740          ast_cli(a->fd, "MFC/R2 debugging set to '%s' for channel %d.\n", a->argv[3], p->channel);
14741          break;
14742       }
14743    }
14744    if ((channo != -1) && !p) {
14745       ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
14746    }
14747    if (channo == -1) {
14748       ast_cli(a->fd, "MFC/R2 debugging set to '%s' for all channels.\n", a->argv[3]);
14749    }
14750    ast_mutex_unlock(&iflock);
14751    return CLI_SUCCESS;
14752 }
14753 
14754 static char *handle_mfcr2_call_files(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14755 {
14756    struct dahdi_pvt *p = NULL;
14757    int channo = 0;
14758    switch (cmd) {
14759    case CLI_INIT:
14760       e->command = "mfcr2 call files [on|off]";
14761       e->usage =
14762          "Usage: mfcr2 call files [on|off] <channel>\n"
14763          "       Enable call files creation on the specified channel.\n"
14764          "       If no channel is specified call files creation policy will be applied to all channels.\n";
14765       return NULL;
14766    case CLI_GENERATE:
14767       return NULL;
14768    }
14769    if (a->argc < 4) {
14770       return CLI_SHOWUSAGE;
14771    }
14772    channo = (a->argc == 5) ? atoi(a->argv[4]) : -1;
14773    ast_mutex_lock(&iflock);
14774    for (p = iflist; p; p = p->next) {
14775       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14776          continue;
14777       }
14778       if ((channo != -1) && (p->channel != channo )) {
14779          continue;
14780       }
14781       if (ast_true(a->argv[3])) {
14782          openr2_chan_enable_call_files(p->r2chan);
14783       } else {
14784          openr2_chan_disable_call_files(p->r2chan);
14785       }
14786       if (channo != -1) {
14787          if (ast_true(a->argv[3])) {
14788             ast_cli(a->fd, "MFC/R2 call files enabled for channel %d.\n", p->channel);
14789          } else {
14790             ast_cli(a->fd, "MFC/R2 call files disabled for channel %d.\n", p->channel);
14791          }
14792          break;
14793       }
14794    }
14795    if ((channo != -1) && !p) {
14796       ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
14797    }
14798    if (channo == -1) {
14799       if (ast_true(a->argv[3])) {
14800          ast_cli(a->fd, "MFC/R2 Call files enabled for all channels.\n");
14801       } else {
14802          ast_cli(a->fd, "MFC/R2 Call files disabled for all channels.\n");
14803       }
14804    }
14805    ast_mutex_unlock(&iflock);
14806    return CLI_SUCCESS;
14807 }
14808 
14809 static char *handle_mfcr2_set_idle(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14810 {
14811    struct dahdi_pvt *p = NULL;
14812    int channo = 0;
14813    switch (cmd) {
14814    case CLI_INIT:
14815       e->command = "mfcr2 set idle";
14816       e->usage =
14817          "Usage: mfcr2 set idle <channel>\n"
14818          "       DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n"
14819          "       Force the given channel into IDLE state.\n"
14820          "       If no channel is specified, all channels will be set to IDLE.\n";
14821       return NULL;
14822    case CLI_GENERATE:
14823       return NULL;
14824    }
14825    channo = (a->argc == 4) ? atoi(a->argv[3]) : -1;
14826    ast_mutex_lock(&iflock);
14827    for (p = iflist; p; p = p->next) {
14828       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14829          continue;
14830       }
14831       if ((channo != -1) && (p->channel != channo )) {
14832          continue;
14833       }
14834       openr2_chan_set_idle(p->r2chan);
14835       ast_mutex_lock(&p->lock);
14836       p->locallyblocked = 0;
14837       p->mfcr2call = 0;
14838       ast_mutex_unlock(&p->lock);
14839       if (channo != -1) {
14840          break;
14841       }
14842    }
14843    if ((channo != -1) && !p) {
14844       ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
14845    }
14846    ast_mutex_unlock(&iflock);
14847    return CLI_SUCCESS;
14848 }
14849 
14850 static char *handle_mfcr2_set_blocked(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14851 {
14852    struct dahdi_pvt *p = NULL;
14853    int channo = 0;
14854    switch (cmd) {
14855    case CLI_INIT:
14856       e->command = "mfcr2 set blocked";
14857       e->usage =
14858          "Usage: mfcr2 set blocked <channel>\n"
14859          "       DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n"
14860          "       Force the given channel into BLOCKED state.\n"
14861          "       If no channel is specified, all channels will be set to BLOCKED.\n";
14862       return NULL;
14863    case CLI_GENERATE:
14864       return NULL;
14865    }
14866    channo = (a->argc == 4) ? atoi(a->argv[3]) : -1;
14867    ast_mutex_lock(&iflock);
14868    for (p = iflist; p; p = p->next) {
14869       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14870          continue;
14871       }
14872       if ((channo != -1) && (p->channel != channo )) {
14873          continue;
14874       }
14875       openr2_chan_set_blocked(p->r2chan);
14876       ast_mutex_lock(&p->lock);
14877       p->locallyblocked = 1;
14878       ast_mutex_unlock(&p->lock);
14879       if (channo != -1) {
14880          break;
14881       }
14882    }
14883    if ((channo != -1) && !p) {
14884       ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
14885    }
14886    ast_mutex_unlock(&iflock);
14887    return CLI_SUCCESS;
14888 }
14889 
14890 static struct ast_cli_entry dahdi_mfcr2_cli[] = {
14891    AST_CLI_DEFINE(handle_mfcr2_version, "Show OpenR2 library version"),
14892    AST_CLI_DEFINE(handle_mfcr2_show_variants, "Show supported MFC/R2 variants"),
14893    AST_CLI_DEFINE(handle_mfcr2_show_channels, "Show MFC/R2 channels"),
14894    AST_CLI_DEFINE(handle_mfcr2_set_debug, "Set MFC/R2 channel logging level"),
14895    AST_CLI_DEFINE(handle_mfcr2_call_files, "Enable/Disable MFC/R2 call files"),
14896    AST_CLI_DEFINE(handle_mfcr2_set_idle, "Reset MFC/R2 channel forcing it to IDLE"),
14897    AST_CLI_DEFINE(handle_mfcr2_set_blocked, "Reset MFC/R2 channel forcing it to BLOCKED"),
14898 };
14899 
14900 #endif /* HAVE_OPENR2 */
14901 
14902 static char *dahdi_destroy_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14903 {
14904    int channel;
14905    int ret;
14906    switch (cmd) {
14907    case CLI_INIT:
14908       e->command = "dahdi destroy channel";
14909       e->usage =
14910          "Usage: dahdi destroy channel <chan num>\n"
14911          "  DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.  Immediately removes a given channel, whether it is in use or not\n";
14912       return NULL;
14913    case CLI_GENERATE:
14914       return NULL;
14915    }
14916    if (a->argc != 4)
14917       return CLI_SHOWUSAGE;
14918 
14919    channel = atoi(a->argv[3]);
14920    ret = dahdi_destroy_channel_bynum(channel);
14921    return ( RESULT_SUCCESS == ret ) ? CLI_SUCCESS : CLI_FAILURE;
14922 }
14923 
14924 static void dahdi_softhangup_all(void)
14925 {
14926    struct dahdi_pvt *p;
14927 retry:
14928    ast_mutex_lock(&iflock);
14929    for (p = iflist; p; p = p->next) {
14930       ast_mutex_lock(&p->lock);
14931       if (p->owner && !p->restartpending) {
14932          if (ast_channel_trylock(p->owner)) {
14933             if (option_debug > 2)
14934                ast_verbose("Avoiding deadlock\n");
14935             /* Avoid deadlock since you're not supposed to lock iflock or pvt before a channel */
14936             ast_mutex_unlock(&p->lock);
14937             ast_mutex_unlock(&iflock);
14938             goto retry;
14939          }
14940          if (option_debug > 2)
14941             ast_verbose("Softhanging up on %s\n", p->owner->name);
14942          ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_EXPLICIT);
14943          p->restartpending = 1;
14944          num_restart_pending++;
14945          ast_channel_unlock(p->owner);
14946       }
14947       ast_mutex_unlock(&p->lock);
14948    }
14949    ast_mutex_unlock(&iflock);
14950 }
14951 
14952 static int setup_dahdi(int reload);
14953 static int dahdi_restart(void)
14954 {
14955 #if defined(HAVE_PRI) || defined(HAVE_SS7)
14956    int i, j;
14957 #endif
14958    int cancel_code;
14959    struct dahdi_pvt *p;
14960 
14961    ast_mutex_lock(&restart_lock);
14962    ast_verb(1, "Destroying channels and reloading DAHDI configuration.\n");
14963    dahdi_softhangup_all();
14964    ast_verb(4, "Initial softhangup of all DAHDI channels complete.\n");
14965 #ifdef HAVE_OPENR2
14966    dahdi_r2_destroy_links();
14967 #endif
14968 
14969 #if defined(HAVE_PRI)
14970    for (i = 0; i < NUM_SPANS; i++) {
14971       if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL)) {
14972          cancel_code = pthread_cancel(pris[i].master);
14973          pthread_kill(pris[i].master, SIGURG);
14974          ast_debug(4, "Waiting to join thread of span %d with pid=%p, cancel_code=%d\n", i, (void *) pris[i].master, cancel_code);
14975          pthread_join(pris[i].master, NULL);
14976          ast_debug(4, "Joined thread of span %d\n", i);
14977       }
14978    }
14979 #endif
14980 
14981 #if defined(HAVE_SS7)
14982    for (i = 0; i < NUM_SPANS; i++) {
14983       if (linksets[i].master && (linksets[i].master != AST_PTHREADT_NULL)) {
14984          cancel_code = pthread_cancel(linksets[i].master);
14985          pthread_kill(linksets[i].master, SIGURG);
14986          ast_debug(4, "Waiting to join thread of span %d with pid=%p, cancel_code=%d\n", i, (void *) linksets[i].master, cancel_code);
14987          pthread_join(linksets[i].master, NULL);
14988          ast_debug(4, "Joined thread of span %d\n", i);
14989       }
14990    }
14991 #endif
14992 
14993    ast_mutex_lock(&monlock);
14994    if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
14995       cancel_code = pthread_cancel(monitor_thread);
14996       pthread_kill(monitor_thread, SIGURG);
14997       ast_debug(4, "Waiting to join monitor thread with pid=%p, cancel_code=%d\n", (void *) monitor_thread, cancel_code);
14998       pthread_join(monitor_thread, NULL);
14999       ast_debug(4, "Joined monitor thread\n");
15000    }
15001    monitor_thread = AST_PTHREADT_NULL; /* prepare to restart thread in setup_dahdi once channels are reconfigured */
15002 
15003    ast_mutex_lock(&ss_thread_lock);
15004    while (ss_thread_count > 0) { /* let ss_threads finish and run dahdi_hangup before dahvi_pvts are destroyed */
15005       int x = DAHDI_FLASH;
15006       ast_debug(3, "Waiting on %d ss_thread(s) to finish\n", ss_thread_count);
15007 
15008       for (p = iflist; p; p = p->next) {
15009          if (p->owner)
15010             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 */
15011          }
15012          ast_cond_wait(&ss_thread_complete, &ss_thread_lock);
15013       }
15014 
15015    /* ensure any created channels before monitor threads were stopped are hungup */
15016    dahdi_softhangup_all();
15017    ast_verb(4, "Final softhangup of all DAHDI channels complete.\n");
15018    destroy_all_channels();
15019    ast_debug(1, "Channels destroyed. Now re-reading config. %d active channels remaining.\n", ast_active_channels());
15020 
15021    ast_mutex_unlock(&monlock);
15022 
15023 #ifdef HAVE_PRI
15024    for (i = 0; i < NUM_SPANS; i++) {
15025       for (j = 0; j < NUM_DCHANS; j++)
15026          dahdi_close_pri_fd(&(pris[i]), j);
15027    }
15028 
15029    memset(pris, 0, sizeof(pris));
15030    for (i = 0; i < NUM_SPANS; i++) {
15031       ast_mutex_init(&pris[i].lock);
15032       pris[i].offset = -1;
15033       pris[i].master = AST_PTHREADT_NULL;
15034       for (j = 0; j < NUM_DCHANS; j++)
15035          pris[i].fds[j] = -1;
15036       }
15037    pri_set_error(dahdi_pri_error);
15038    pri_set_message(dahdi_pri_message);
15039 #endif
15040 #ifdef HAVE_SS7
15041    for (i = 0; i < NUM_SPANS; i++) {
15042       for (j = 0; j < NUM_DCHANS; j++)
15043          dahdi_close_ss7_fd(&(linksets[i]), j);
15044    }
15045 
15046    memset(linksets, 0, sizeof(linksets));
15047    for (i = 0; i < NUM_SPANS; i++) {
15048       ast_mutex_init(&linksets[i].lock);
15049       linksets[i].master = AST_PTHREADT_NULL;
15050       for (j = 0; j < NUM_DCHANS; j++)
15051          linksets[i].fds[j] = -1;
15052    }
15053    ss7_set_error(dahdi_ss7_error);
15054    ss7_set_message(dahdi_ss7_message);
15055 #endif
15056 
15057    if (setup_dahdi(2) != 0) {
15058       ast_log(LOG_WARNING, "Reload channels from dahdi config failed!\n");
15059       ast_mutex_unlock(&ss_thread_lock);
15060       return 1;
15061    }
15062    ast_mutex_unlock(&ss_thread_lock);
15063    ast_mutex_unlock(&restart_lock);
15064    return 0;
15065 }
15066 
15067 static char *dahdi_restart_cmd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15068 {
15069    switch (cmd) {
15070    case CLI_INIT:
15071       e->command = "dahdi restart";
15072       e->usage =
15073          "Usage: dahdi restart\n"
15074          "  Restarts the DAHDI channels: destroys them all and then\n"
15075          "  re-reads them from chan_dahdi.conf.\n"
15076          "  Note that this will STOP any running CALL on DAHDI channels.\n"
15077          "";
15078       return NULL;
15079    case CLI_GENERATE:
15080       return NULL;
15081    }
15082    if (a->argc != 2)
15083       return CLI_SHOWUSAGE;
15084 
15085    if (dahdi_restart() != 0)
15086       return CLI_FAILURE;
15087    return CLI_SUCCESS;
15088 }
15089 
15090 static int action_dahdirestart(struct mansession *s, const struct message *m)
15091 {
15092    if (dahdi_restart() != 0) {
15093       astman_send_error(s, m, "Failed rereading DAHDI configuration");
15094       return 1;
15095    }
15096    astman_send_ack(s, m, "DAHDIRestart: Success");
15097    return 0;
15098 }
15099 
15100 static char *dahdi_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15101 {
15102 #define FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
15103 #define FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
15104    unsigned int targetnum = 0;
15105    int filtertype = 0;
15106    struct dahdi_pvt *tmp = NULL;
15107    char tmps[20] = "";
15108    char statestr[20] = "";
15109    char blockstr[20] = "";
15110    ast_mutex_t *lock;
15111    struct dahdi_pvt *start;
15112 #ifdef HAVE_PRI
15113    int trunkgroup;
15114    struct dahdi_pri *pri = NULL;
15115    int x;
15116 #endif
15117    switch (cmd) {
15118    case CLI_INIT:
15119       e->command = "dahdi show channels [trunkgroup|group|context]";
15120       e->usage =
15121          "Usage: dahdi show channels [ trunkgroup <trunkgroup> | group <group> | context <context> ]\n"
15122          "  Shows a list of available channels with optional filtering\n"
15123          "  <group> must be a number between 0 and 63\n";
15124       return NULL;
15125    case CLI_GENERATE:
15126       return NULL;
15127    }
15128 
15129    lock = &iflock;
15130    start = iflist;
15131 
15132    /* syntax: dahdi show channels [ group <group> | context <context> | trunkgroup <trunkgroup> ] */
15133 
15134    if (!((a->argc == 3) || (a->argc == 5)))
15135       return CLI_SHOWUSAGE;
15136 
15137    if (a->argc == 5) {
15138 #ifdef HAVE_PRI
15139       if (!strcasecmp(a->argv[3], "trunkgroup")) {
15140          /* this option requires no special handling, so leave filtertype to zero */
15141          if ((trunkgroup = atoi(a->argv[4])) < 1)
15142             return CLI_SHOWUSAGE;
15143          for (x = 0; x < NUM_SPANS; x++) {
15144             if (pris[x].trunkgroup == trunkgroup) {
15145                pri = pris + x;
15146                break;
15147             }
15148          }
15149          if (pri) {
15150             start = pri->crvs;
15151             lock = &pri->lock;
15152          } else {
15153             ast_cli(a->fd, "No such trunk group %d\n", trunkgroup);
15154             return CLI_FAILURE;
15155          }
15156       } else
15157 #endif
15158       if (!strcasecmp(a->argv[3], "group")) {
15159          targetnum = atoi(a->argv[4]);
15160          if ((targetnum < 0) || (targetnum > 63))
15161             return CLI_SHOWUSAGE;
15162          targetnum = 1 << targetnum;
15163          filtertype = 1;
15164       } else if (!strcasecmp(a->argv[3], "context")) {
15165          filtertype = 2;
15166       }
15167    }
15168 
15169    ast_mutex_lock(lock);
15170 #ifdef HAVE_PRI
15171    ast_cli(a->fd, FORMAT2, pri ? "CRV" : "Chan", "Extension", "Context", "Language", "MOH Interpret", "Blocked", "State");
15172 #else
15173    ast_cli(a->fd, FORMAT2, "Chan", "Extension", "Context", "Language", "MOH Interpret", "Blocked", "State");
15174 #endif
15175 
15176    tmp = start;
15177    while (tmp) {
15178       if (filtertype) {
15179          switch(filtertype) {
15180          case 1: /* dahdi show channels group <group> */
15181             if (!(tmp->group & targetnum)) {
15182                tmp = tmp->next;
15183                continue;
15184             }
15185             break;
15186          case 2: /* dahdi show channels context <context> */
15187             if (strcasecmp(tmp->context, a->argv[4])) {
15188                tmp = tmp->next;
15189                continue;
15190             }
15191             break;
15192          default:
15193             ;
15194          }
15195       }
15196       if (tmp->channel > 0) {
15197          snprintf(tmps, sizeof(tmps), "%d", tmp->channel);
15198       } else
15199          ast_copy_string(tmps, "pseudo", sizeof(tmps));
15200 
15201       if (tmp->locallyblocked)
15202          blockstr[0] = 'L';
15203       else
15204          blockstr[0] = ' ';
15205 
15206       if (tmp->remotelyblocked)
15207          blockstr[1] = 'R';
15208       else
15209          blockstr[1] = ' ';
15210 
15211       blockstr[2] = '\0';
15212 
15213       snprintf(statestr, sizeof(statestr), "%s", "In Service");
15214 
15215       ast_cli(a->fd, FORMAT, tmps, tmp->exten, tmp->context, tmp->language, tmp->mohinterpret, blockstr, statestr);
15216       tmp = tmp->next;
15217    }
15218    ast_mutex_unlock(lock);
15219    return CLI_SUCCESS;
15220 #undef FORMAT
15221 #undef FORMAT2
15222 }
15223 
15224 static char *dahdi_show_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15225 {
15226    int channel;
15227    struct dahdi_pvt *tmp = NULL;
15228    struct dahdi_confinfo ci;
15229    struct dahdi_params ps;
15230    int x;
15231    ast_mutex_t *lock;
15232    struct dahdi_pvt *start;
15233 #ifdef HAVE_PRI
15234    char *c;
15235    int trunkgroup;
15236    struct dahdi_pri *pri=NULL;
15237 #endif
15238    switch (cmd) {
15239    case CLI_INIT:
15240       e->command = "dahdi show channel";
15241       e->usage =
15242          "Usage: dahdi show channel <chan num>\n"
15243          "  Detailed information about a given channel\n";
15244       return NULL;
15245    case CLI_GENERATE:
15246       return NULL;
15247    }
15248 
15249    lock = &iflock;
15250    start = iflist;
15251 
15252    if (a->argc != 4)
15253       return CLI_SHOWUSAGE;
15254 #ifdef HAVE_PRI
15255    if ((c = strchr(a->argv[3], ':'))) {
15256       if (sscanf(a->argv[3], "%30d:%30d", &trunkgroup, &channel) != 2)
15257          return CLI_SHOWUSAGE;
15258       if ((trunkgroup < 1) || (channel < 1))
15259          return CLI_SHOWUSAGE;
15260       for (x = 0; x < NUM_SPANS; x++) {
15261          if (pris[x].trunkgroup == trunkgroup) {
15262             pri = pris + x;
15263             break;
15264          }
15265       }
15266       if (pri) {
15267          start = pri->crvs;
15268          lock = &pri->lock;
15269       } else {
15270          ast_cli(a->fd, "No such trunk group %d\n", trunkgroup);
15271          return CLI_FAILURE;
15272       }
15273    } else
15274 #endif
15275       channel = atoi(a->argv[3]);
15276 
15277    ast_mutex_lock(lock);
15278    tmp = start;
15279    while (tmp) {
15280       if (tmp->channel == channel) {
15281 #ifdef HAVE_PRI
15282          if (pri)
15283             ast_cli(a->fd, "Trunk/CRV: %d/%d\n", trunkgroup, tmp->channel);
15284          else
15285 #endif
15286          ast_cli(a->fd, "Channel: %d\n", tmp->channel);
15287          ast_cli(a->fd, "File Descriptor: %d\n", tmp->subs[SUB_REAL].dfd);
15288          ast_cli(a->fd, "Span: %d\n", tmp->span);
15289          ast_cli(a->fd, "Extension: %s\n", tmp->exten);
15290          ast_cli(a->fd, "Dialing: %s\n", tmp->dialing ? "yes" : "no");
15291          ast_cli(a->fd, "Context: %s\n", tmp->context);
15292          ast_cli(a->fd, "Caller ID: %s\n", tmp->cid_num);
15293          ast_cli(a->fd, "Calling TON: %d\n", tmp->cid_ton);
15294          ast_cli(a->fd, "Caller ID name: %s\n", tmp->cid_name);
15295          ast_cli(a->fd, "Mailbox: %s\n", S_OR(tmp->mailbox, "none"));
15296          if (tmp->vars) {
15297             struct ast_variable *v;
15298             ast_cli(a->fd, "Variables:\n");
15299             for (v = tmp->vars ; v ; v = v->next)
15300                ast_cli(a->fd, "       %s = %s\n", v->name, v->value);
15301          }
15302          ast_cli(a->fd, "Destroy: %d\n", tmp->destroy);
15303          ast_cli(a->fd, "InAlarm: %d\n", tmp->inalarm);
15304          ast_cli(a->fd, "Signalling Type: %s\n", sig2str(tmp->sig));
15305          ast_cli(a->fd, "Radio: %d\n", tmp->radio);
15306          ast_cli(a->fd, "Owner: %s\n", tmp->owner ? tmp->owner->name : "<None>");
15307          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)" : "");
15308          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)" : "");
15309          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)" : "");
15310          ast_cli(a->fd, "Confno: %d\n", tmp->confno);
15311          ast_cli(a->fd, "Propagated Conference: %d\n", tmp->propconfno);
15312          ast_cli(a->fd, "Real in conference: %d\n", tmp->inconference);
15313          ast_cli(a->fd, "DSP: %s\n", tmp->dsp ? "yes" : "no");
15314          ast_cli(a->fd, "Busy Detection: %s\n", tmp->busydetect ? "yes" : "no");
15315          if (tmp->busydetect) {
15316 #if defined(BUSYDETECT_TONEONLY)
15317             ast_cli(a->fd, "    Busy Detector Helper: BUSYDETECT_TONEONLY\n");
15318 #elif defined(BUSYDETECT_COMPARE_TONE_AND_SILENCE)
15319             ast_cli(a->fd, "    Busy Detector Helper: BUSYDETECT_COMPARE_TONE_AND_SILENCE\n");
15320 #endif
15321 #ifdef BUSYDETECT_DEBUG
15322             ast_cli(a->fd, "    Busy Detector Debug: Enabled\n");
15323 #endif
15324             ast_cli(a->fd, "    Busy Count: %d\n", tmp->busycount);
15325             ast_cli(a->fd, "    Busy Pattern: %d,%d\n", tmp->busy_tonelength, tmp->busy_quietlength);
15326          }
15327          ast_cli(a->fd, "TDD: %s\n", tmp->tdd ? "yes" : "no");
15328          ast_cli(a->fd, "Relax DTMF: %s\n", tmp->dtmfrelax ? "yes" : "no");
15329          ast_cli(a->fd, "Dialing/CallwaitCAS: %d/%d\n", tmp->dialing, tmp->callwaitcas);
15330          ast_cli(a->fd, "Default law: %s\n", tmp->law == DAHDI_LAW_MULAW ? "ulaw" : tmp->law == DAHDI_LAW_ALAW ? "alaw" : "unknown");
15331          ast_cli(a->fd, "Fax Handled: %s\n", tmp->faxhandled ? "yes" : "no");
15332          ast_cli(a->fd, "Pulse phone: %s\n", tmp->pulsedial ? "yes" : "no");
15333          ast_cli(a->fd, "DND: %s\n", tmp->dnd ? "yes" : "no");
15334          ast_cli(a->fd, "Echo Cancellation:\n");
15335 
15336          if (tmp->echocancel.head.tap_length) {
15337             ast_cli(a->fd, "\t%d taps\n", tmp->echocancel.head.tap_length);
15338             for (x = 0; x < tmp->echocancel.head.param_count; x++) {
15339                ast_cli(a->fd, "\t\t%s: %ud\n", tmp->echocancel.params[x].name, tmp->echocancel.params[x].value);
15340             }
15341             ast_cli(a->fd, "\t%scurrently %s\n", tmp->echocanbridged ? "" : "(unless TDM bridged) ", tmp->echocanon ? "ON" : "OFF");
15342          } else {
15343             ast_cli(a->fd, "\tnone\n");
15344          }
15345          ast_cli(a->fd, "Wait for dialtone: %dms\n", tmp->waitfordialtone);
15346          if (tmp->master)
15347             ast_cli(a->fd, "Master Channel: %d\n", tmp->master->channel);
15348          for (x = 0; x < MAX_SLAVES; x++) {
15349             if (tmp->slaves[x])
15350                ast_cli(a->fd, "Slave Channel: %d\n", tmp->slaves[x]->channel);
15351          }
15352 #ifdef HAVE_OPENR2
15353          if (tmp->mfcr2) {
15354             char calldir[OR2_MAX_PATH];
15355             openr2_context_t *r2context = openr2_chan_get_context(tmp->r2chan);
15356             openr2_variant_t r2variant = openr2_context_get_variant(r2context);
15357             ast_cli(a->fd, "MFC/R2 MF State: %s\n", openr2_chan_get_mf_state_string(tmp->r2chan));
15358             ast_cli(a->fd, "MFC/R2 MF Group: %s\n", openr2_chan_get_mf_group_string(tmp->r2chan));
15359             ast_cli(a->fd, "MFC/R2 State: %s\n", openr2_chan_get_r2_state_string(tmp->r2chan));
15360             ast_cli(a->fd, "MFC/R2 Call State: %s\n", openr2_chan_get_call_state_string(tmp->r2chan));
15361             ast_cli(a->fd, "MFC/R2 Call Files Enabled: %s\n", openr2_chan_get_call_files_enabled(tmp->r2chan) ? "Yes" : "No");
15362             ast_cli(a->fd, "MFC/R2 Variant: %s\n", openr2_proto_get_variant_string(r2variant));
15363             ast_cli(a->fd, "MFC/R2 Max ANI: %d\n", openr2_context_get_max_ani(r2context));
15364             ast_cli(a->fd, "MFC/R2 Max DNIS: %d\n", openr2_context_get_max_dnis(r2context));
15365             ast_cli(a->fd, "MFC/R2 Get ANI First: %s\n", openr2_context_get_ani_first(r2context) ? "Yes" : "No");
15366 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
15367             ast_cli(a->fd, "MFC/R2 Skip Category Request: %s\n", openr2_context_get_skip_category_request(r2context) ? "Yes" : "No");
15368 #endif
15369             ast_cli(a->fd, "MFC/R2 Immediate Accept: %s\n", openr2_context_get_immediate_accept(r2context) ? "Yes" : "No");
15370             ast_cli(a->fd, "MFC/R2 Accept on Offer: %s\n", tmp->mfcr2_accept_on_offer ? "Yes" : "No");
15371             ast_cli(a->fd, "MFC/R2 Charge Calls: %s\n", tmp->mfcr2_charge_calls ? "Yes" : "No");
15372             ast_cli(a->fd, "MFC/R2 Allow Collect Calls: %s\n", tmp->mfcr2_allow_collect_calls ? "Yes" : "No");
15373             ast_cli(a->fd, "MFC/R2 Forced Release: %s\n", tmp->mfcr2_forced_release ? "Yes" : "No");
15374             ast_cli(a->fd, "MFC/R2 MF Back Timeout: %dms\n", openr2_context_get_mf_back_timeout(r2context));
15375             ast_cli(a->fd, "MFC/R2 R2 Metering Pulse Timeout: %dms\n", openr2_context_get_metering_pulse_timeout(r2context));
15376             ast_cli(a->fd, "MFC/R2 Rx CAS: %s\n", openr2_chan_get_rx_cas_string(tmp->r2chan));
15377             ast_cli(a->fd, "MFC/R2 Tx CAS: %s\n", openr2_chan_get_tx_cas_string(tmp->r2chan));
15378             ast_cli(a->fd, "MFC/R2 MF Tx Signal: %d\n", openr2_chan_get_tx_mf_signal(tmp->r2chan));
15379             ast_cli(a->fd, "MFC/R2 MF Rx Signal: %d\n", openr2_chan_get_rx_mf_signal(tmp->r2chan));
15380             ast_cli(a->fd, "MFC/R2 Call Files Directory: %s\n", openr2_context_get_log_directory(r2context, calldir, sizeof(calldir)));
15381          }
15382 #endif
15383 #ifdef HAVE_SS7
15384          if (tmp->ss7) {
15385             ast_cli(a->fd, "CIC: %d\n", tmp->cic);
15386          }
15387 #endif
15388 #ifdef HAVE_PRI
15389          if (tmp->pri) {
15390             ast_cli(a->fd, "PRI Flags: ");
15391             if (tmp->resetting)
15392                ast_cli(a->fd, "Resetting ");
15393             if (tmp->call)
15394                ast_cli(a->fd, "Call ");
15395             if (tmp->bearer)
15396                ast_cli(a->fd, "Bearer ");
15397             ast_cli(a->fd, "\n");
15398             if (tmp->logicalspan)
15399                ast_cli(a->fd, "PRI Logical Span: %d\n", tmp->logicalspan);
15400             else
15401                ast_cli(a->fd, "PRI Logical Span: Implicit\n");
15402          }
15403 #endif
15404          memset(&ci, 0, sizeof(ci));
15405          ps.channo = tmp->channel;
15406          if (tmp->subs[SUB_REAL].dfd > -1) {
15407             memset(&ci, 0, sizeof(ci));
15408             if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
15409                ast_cli(a->fd, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci.confno, ci.confmode);
15410             }
15411             if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONFMUTE, &x)) {
15412                ast_cli(a->fd, "Actual Confmute: %s\n", x ? "Yes" : "No");
15413             }
15414             memset(&ps, 0, sizeof(ps));
15415             if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
15416                ast_log(LOG_WARNING, "Failed to get parameters on channel %d: %s\n", tmp->channel, strerror(errno));
15417             } else {
15418                ast_cli(a->fd, "Hookstate (FXS only): %s\n", ps.rxisoffhook ? "Offhook" : "Onhook");
15419             }
15420          }
15421          ast_mutex_unlock(lock);
15422          return CLI_SUCCESS;
15423       }
15424       tmp = tmp->next;
15425    }
15426 
15427    ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15428    ast_mutex_unlock(lock);
15429    return CLI_FAILURE;
15430 }
15431 
15432 static char *handle_dahdi_show_cadences(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15433 {
15434    int i, j;
15435    switch (cmd) {
15436    case CLI_INIT:
15437       e->command = "dahdi show cadences";
15438       e->usage =
15439          "Usage: dahdi show cadences\n"
15440          "       Shows all cadences currently defined\n";
15441       return NULL;
15442    case CLI_GENERATE:
15443       return NULL;
15444    }
15445    for (i = 0; i < num_cadence; i++) {
15446       char output[1024];
15447       char tmp[16], tmp2[64];
15448       snprintf(tmp, sizeof(tmp), "r%d: ", i + 1);
15449       term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output));
15450 
15451       for (j = 0; j < 16; j++) {
15452          if (cadences[i].ringcadence[j] == 0)
15453             break;
15454          snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]);
15455          if (cidrings[i] * 2 - 1 == j)
15456             term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1);
15457          else
15458             term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1);
15459          if (j != 0)
15460             strncat(output, ",", sizeof(output) - strlen(output) - 1);
15461          strncat(output, tmp2, sizeof(output) - strlen(output) - 1);
15462       }
15463       ast_cli(a->fd,"%s\n",output);
15464    }
15465    return CLI_SUCCESS;
15466 }
15467 
15468 /* Based on irqmiss.c */
15469 static char *dahdi_show_status(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15470 {
15471    #define FORMAT "%-40.40s %-7.7s %-6d %-6d %-6d %-3.3s %-4.4s %-8.8s %s\n"
15472    #define FORMAT2 "%-40.40s %-7.7s %-6.6s %-6.6s %-6.6s %-3.3s %-4.4s %-8.8s %s\n"
15473    int span;
15474    int res;
15475    char alarmstr[50];
15476 
15477    int ctl;
15478    struct dahdi_spaninfo s;
15479 
15480    switch (cmd) {
15481    case CLI_INIT:
15482       e->command = "dahdi show status";
15483       e->usage =
15484          "Usage: dahdi show status\n"
15485          "       Shows a list of DAHDI cards with status\n";
15486       return NULL;
15487    case CLI_GENERATE:
15488       return NULL;
15489    }
15490    ctl = open("/dev/dahdi/ctl", O_RDWR);
15491    if (ctl < 0) {
15492       ast_cli(a->fd, "No DAHDI found. Unable to open /dev/dahdi/ctl: %s\n", strerror(errno));
15493       return CLI_FAILURE;
15494    }
15495    ast_cli(a->fd, FORMAT2, "Description", "Alarms", "IRQ", "bpviol", "CRC4", "Framing", "Coding", "Options", "LBO");
15496 
15497    for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
15498       s.spanno = span;
15499       res = ioctl(ctl, DAHDI_SPANSTAT, &s);
15500       if (res) {
15501          continue;
15502       }
15503       alarmstr[0] = '\0';
15504       if (s.alarms > 0) {
15505          if (s.alarms & DAHDI_ALARM_BLUE)
15506             strcat(alarmstr, "BLU/");
15507          if (s.alarms & DAHDI_ALARM_YELLOW)
15508             strcat(alarmstr, "YEL/");
15509          if (s.alarms & DAHDI_ALARM_RED)
15510             strcat(alarmstr, "RED/");
15511          if (s.alarms & DAHDI_ALARM_LOOPBACK)
15512             strcat(alarmstr, "LB/");
15513          if (s.alarms & DAHDI_ALARM_RECOVER)
15514             strcat(alarmstr, "REC/");
15515          if (s.alarms & DAHDI_ALARM_NOTOPEN)
15516             strcat(alarmstr, "NOP/");
15517          if (!strlen(alarmstr))
15518             strcat(alarmstr, "UUU/");
15519          if (strlen(alarmstr)) {
15520             /* Strip trailing / */
15521             alarmstr[strlen(alarmstr) - 1] = '\0';
15522          }
15523       } else {
15524          if (s.numchans)
15525             strcpy(alarmstr, "OK");
15526          else
15527             strcpy(alarmstr, "UNCONFIGURED");
15528       }
15529 
15530       ast_cli(a->fd, FORMAT, s.desc, alarmstr, s.irqmisses, s.bpvcount, s.crc4count,
15531          s.lineconfig & DAHDI_CONFIG_D4 ? "D4" :
15532          s.lineconfig & DAHDI_CONFIG_ESF ? "ESF" :
15533          s.lineconfig & DAHDI_CONFIG_CCS ? "CCS" :
15534          "CAS",
15535          s.lineconfig & DAHDI_CONFIG_B8ZS ? "B8ZS" :
15536          s.lineconfig & DAHDI_CONFIG_HDB3 ? "HDB3" :
15537          s.lineconfig & DAHDI_CONFIG_AMI ? "AMI" :
15538          "Unk",
15539          s.lineconfig & DAHDI_CONFIG_CRC4 ?
15540             s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" :
15541             s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "YEL" : "",
15542          lbostr[s.lbo]
15543          );
15544    }
15545    close(ctl);
15546 
15547    return CLI_SUCCESS;
15548 #undef FORMAT
15549 #undef FORMAT2
15550 }
15551 
15552 static char *dahdi_show_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15553 {
15554    int pseudo_fd = -1;
15555    struct dahdi_versioninfo vi;
15556 
15557    switch (cmd) {
15558    case CLI_INIT:
15559       e->command = "dahdi show version";
15560       e->usage =
15561          "Usage: dahdi show version\n"
15562          "       Shows the DAHDI version in use\n";
15563       return NULL;
15564    case CLI_GENERATE:
15565       return NULL;
15566    }
15567    if ((pseudo_fd = open("/dev/dahdi/ctl", O_RDONLY)) < 0) {
15568       ast_cli(a->fd, "Failed to open control file to get version.\n");
15569       return CLI_SUCCESS;
15570    }
15571 
15572    strcpy(vi.version, "Unknown");
15573    strcpy(vi.echo_canceller, "Unknown");
15574 
15575    if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi))
15576       ast_cli(a->fd, "Failed to get DAHDI version: %s\n", strerror(errno));
15577    else
15578       ast_cli(a->fd, "DAHDI Version: %s Echo Canceller: %s\n", vi.version, vi.echo_canceller);
15579 
15580    close(pseudo_fd);
15581 
15582    return CLI_SUCCESS;
15583 }
15584 
15585 static char *dahdi_set_hwgain(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15586 {
15587    int channel;
15588    int gain;
15589    int tx;
15590    struct dahdi_hwgain hwgain;
15591    struct dahdi_pvt *tmp = NULL;
15592 
15593    switch (cmd) {
15594    case CLI_INIT:
15595       e->command = "dahdi set hwgain";
15596       e->usage =
15597          "Usage: dahdi set hwgain <rx|tx> <chan#> <gain>\n"
15598          "  Sets the hardware gain on a a given channel, overriding the\n"
15599          "   value provided at module loadtime, whether the channel is in\n"
15600          "   use or not.  Changes take effect immediately.\n"
15601          "   <rx|tx> which direction do you want to change (relative to our module)\n"
15602          "   <chan num> is the channel number relative to the device\n"
15603          "   <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
15604       return NULL;
15605    case CLI_GENERATE:
15606       return NULL;
15607    }
15608 
15609    if (a->argc != 6)
15610       return CLI_SHOWUSAGE;
15611 
15612    if (!strcasecmp("rx", a->argv[3]))
15613       tx = 0; /* rx */
15614    else if (!strcasecmp("tx", a->argv[3]))
15615       tx = 1; /* tx */
15616    else
15617       return CLI_SHOWUSAGE;
15618 
15619    channel = atoi(a->argv[4]);
15620    gain = atof(a->argv[5])*10.0;
15621 
15622    ast_mutex_lock(&iflock);
15623 
15624    for (tmp = iflist; tmp; tmp = tmp->next) {
15625 
15626       if (tmp->channel != channel)
15627          continue;
15628 
15629       if (tmp->subs[SUB_REAL].dfd == -1)
15630          break;
15631 
15632       hwgain.newgain = gain;
15633       hwgain.tx = tx;
15634       if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_HWGAIN, &hwgain) < 0) {
15635          ast_cli(a->fd, "Unable to set the hardware gain for channel %d: %s\n", channel, strerror(errno));
15636          ast_mutex_unlock(&iflock);
15637          return CLI_FAILURE;
15638       }
15639       ast_cli(a->fd, "hardware %s gain set to %d (%.1f dB) on channel %d\n",
15640          tx ? "tx" : "rx", gain, (float)gain/10.0, channel);
15641       break;
15642    }
15643 
15644    ast_mutex_unlock(&iflock);
15645 
15646    if (tmp)
15647       return CLI_SUCCESS;
15648 
15649    ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15650    return CLI_FAILURE;
15651 
15652 }
15653 
15654 static char *dahdi_set_swgain(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15655 {
15656    int channel;
15657    float gain;
15658    int tx;
15659    int res;
15660    ast_mutex_t *lock;
15661    struct dahdi_pvt *tmp = NULL;
15662 
15663    switch (cmd) {
15664    case CLI_INIT:
15665       e->command = "dahdi set swgain";
15666       e->usage =
15667          "Usage: dahdi set swgain <rx|tx> <chan#> <gain>\n"
15668          "  Sets the software gain on a a given channel, overriding the\n"
15669          "   value provided at module loadtime, whether the channel is in\n"
15670          "   use or not.  Changes take effect immediately.\n"
15671          "   <rx|tx> which direction do you want to change (relative to our module)\n"
15672          "   <chan num> is the channel number relative to the device\n"
15673          "   <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
15674       return NULL;
15675    case CLI_GENERATE:
15676       return NULL;
15677    }
15678 
15679    lock = &iflock;
15680 
15681    if (a->argc != 6)
15682       return CLI_SHOWUSAGE;
15683 
15684    if (!strcasecmp("rx", a->argv[3]))
15685       tx = 0; /* rx */
15686    else if (!strcasecmp("tx", a->argv[3]))
15687       tx = 1; /* tx */
15688    else
15689       return CLI_SHOWUSAGE;
15690 
15691    channel = atoi(a->argv[4]);
15692    gain = atof(a->argv[5]);
15693 
15694    ast_mutex_lock(lock);
15695    for (tmp = iflist; tmp; tmp = tmp->next) {
15696 
15697       if (tmp->channel != channel)
15698          continue;
15699 
15700       if (tmp->subs[SUB_REAL].dfd == -1)
15701          break;
15702 
15703       if (tx)
15704          res = set_actual_txgain(tmp->subs[SUB_REAL].dfd, channel, gain, tmp->law);
15705       else
15706          res = set_actual_rxgain(tmp->subs[SUB_REAL].dfd, channel, gain, tmp->law);
15707 
15708       if (res) {
15709          ast_cli(a->fd, "Unable to set the software gain for channel %d\n", channel);
15710          ast_mutex_unlock(lock);
15711          return CLI_FAILURE;
15712       }
15713 
15714       ast_cli(a->fd, "software %s gain set to %.1f on channel %d\n",
15715          tx ? "tx" : "rx", gain, channel);
15716       break;
15717    }
15718    ast_mutex_unlock(lock);
15719 
15720    if (tmp)
15721       return CLI_SUCCESS;
15722 
15723    ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15724    return CLI_FAILURE;
15725 
15726 }
15727 
15728 static char *dahdi_set_dnd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15729 {
15730    int channel;
15731    int on;
15732    struct dahdi_pvt *dahdi_chan = NULL;
15733 
15734    switch (cmd) {
15735    case CLI_INIT:
15736       e->command = "dahdi set dnd";
15737       e->usage =
15738          "Usage: dahdi set dnd <chan#> <on|off>\n"
15739          "  Sets/resets DND (Do Not Disturb) mode on a channel.\n"
15740          "  Changes take effect immediately.\n"
15741          "  <chan num> is the channel number\n"
15742          "  <on|off> Enable or disable DND mode?\n"
15743          ;
15744       return NULL;
15745    case CLI_GENERATE:
15746       return NULL;
15747    }
15748 
15749    if (a->argc != 5)
15750       return CLI_SHOWUSAGE;
15751 
15752    if ((channel = atoi(a->argv[3])) <= 0) {
15753       ast_cli(a->fd, "Expected channel number, got '%s'\n", a->argv[3]);
15754       return CLI_SHOWUSAGE;
15755    }
15756 
15757    if (ast_true(a->argv[4]))
15758       on = 1;
15759    else if (ast_false(a->argv[4]))
15760       on = 0;
15761    else {
15762       ast_cli(a->fd, "Expected 'on' or 'off', got '%s'\n", a->argv[4]);
15763       return CLI_SHOWUSAGE;
15764    }
15765 
15766    ast_mutex_lock(&iflock);
15767    for (dahdi_chan = iflist; dahdi_chan; dahdi_chan = dahdi_chan->next) {
15768       if (dahdi_chan->channel != channel)
15769          continue;
15770 
15771       /* Found the channel. Actually set it */
15772       dahdi_dnd(dahdi_chan, on);
15773       break;
15774    }
15775    ast_mutex_unlock(&iflock);
15776 
15777    if (!dahdi_chan) {
15778       ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15779       return CLI_FAILURE;
15780    }
15781 
15782    return CLI_SUCCESS;
15783 }
15784 
15785 static struct ast_cli_entry dahdi_cli[] = {
15786    AST_CLI_DEFINE(handle_dahdi_show_cadences, "List cadences"),
15787    AST_CLI_DEFINE(dahdi_show_channels, "Show active DAHDI channels"),
15788    AST_CLI_DEFINE(dahdi_show_channel, "Show information on a channel"),
15789    AST_CLI_DEFINE(dahdi_destroy_channel, "Destroy a channel"),
15790    AST_CLI_DEFINE(dahdi_restart_cmd, "Fully restart DAHDI channels"),
15791    AST_CLI_DEFINE(dahdi_show_status, "Show all DAHDI cards status"),
15792    AST_CLI_DEFINE(dahdi_show_version, "Show the DAHDI version in use"),
15793    AST_CLI_DEFINE(dahdi_set_hwgain, "Set hardware gain on a channel"),
15794    AST_CLI_DEFINE(dahdi_set_swgain, "Set software gain on a channel"),
15795    AST_CLI_DEFINE(dahdi_set_dnd, "Sets/resets DND (Do Not Disturb) mode on a channel"),
15796 };
15797 
15798 #define TRANSFER  0
15799 #define HANGUP    1
15800 
15801 static int dahdi_fake_event(struct dahdi_pvt *p, int mode)
15802 {
15803    if (p) {
15804       switch (mode) {
15805          case TRANSFER:
15806             p->fake_event = DAHDI_EVENT_WINKFLASH;
15807             break;
15808          case HANGUP:
15809             p->fake_event = DAHDI_EVENT_ONHOOK;
15810             break;
15811          default:
15812             ast_log(LOG_WARNING, "I don't know how to handle transfer event with this: %d on channel %s\n",mode, p->owner->name);
15813       }
15814    }
15815    return 0;
15816 }
15817 static struct dahdi_pvt *find_channel(int channel)
15818 {
15819    struct dahdi_pvt *p = iflist;
15820    while (p) {
15821       if (p->channel == channel) {
15822          break;
15823       }
15824       p = p->next;
15825    }
15826    return p;
15827 }
15828 
15829 static int action_dahdidndon(struct mansession *s, const struct message *m)
15830 {
15831    struct dahdi_pvt *p = NULL;
15832    const char *channel = astman_get_header(m, "DAHDIChannel");
15833 
15834    if (ast_strlen_zero(channel)) {
15835       astman_send_error(s, m, "No channel specified");
15836       return 0;
15837    }
15838    p = find_channel(atoi(channel));
15839    if (!p) {
15840       astman_send_error(s, m, "No such channel");
15841       return 0;
15842    }
15843    p->dnd = 1;
15844    astman_send_ack(s, m, "DND Enabled");
15845    return 0;
15846 }
15847 
15848 static int action_dahdidndoff(struct mansession *s, const struct message *m)
15849 {
15850    struct dahdi_pvt *p = NULL;
15851    const char *channel = astman_get_header(m, "DAHDIChannel");
15852 
15853    if (ast_strlen_zero(channel)) {
15854       astman_send_error(s, m, "No channel specified");
15855       return 0;
15856    }
15857    p = find_channel(atoi(channel));
15858    if (!p) {
15859       astman_send_error(s, m, "No such channel");
15860       return 0;
15861    }
15862    p->dnd = 0;
15863    astman_send_ack(s, m, "DND Disabled");
15864    return 0;
15865 }
15866 
15867 static int action_transfer(struct mansession *s, const struct message *m)
15868 {
15869    struct dahdi_pvt *p = NULL;
15870    const char *channel = astman_get_header(m, "DAHDIChannel");
15871 
15872    if (ast_strlen_zero(channel)) {
15873       astman_send_error(s, m, "No channel specified");
15874       return 0;
15875    }
15876    p = find_channel(atoi(channel));
15877    if (!p) {
15878       astman_send_error(s, m, "No such channel");
15879       return 0;
15880    }
15881    dahdi_fake_event(p,TRANSFER);
15882    astman_send_ack(s, m, "DAHDITransfer");
15883    return 0;
15884 }
15885 
15886 static int action_transferhangup(struct mansession *s, const struct message *m)
15887 {
15888    struct dahdi_pvt *p = NULL;
15889    const char *channel = astman_get_header(m, "DAHDIChannel");
15890 
15891    if (ast_strlen_zero(channel)) {
15892       astman_send_error(s, m, "No channel specified");
15893       return 0;
15894    }
15895    p = find_channel(atoi(channel));
15896    if (!p) {
15897       astman_send_error(s, m, "No such channel");
15898       return 0;
15899    }
15900    dahdi_fake_event(p,HANGUP);
15901    astman_send_ack(s, m, "DAHDIHangup");
15902    return 0;
15903 }
15904 
15905 static int action_dahdidialoffhook(struct mansession *s, const struct message *m)
15906 {
15907    struct dahdi_pvt *p = NULL;
15908    const char *channel = astman_get_header(m, "DAHDIChannel");
15909    const char *number = astman_get_header(m, "Number");
15910    int i;
15911 
15912    if (ast_strlen_zero(channel)) {
15913       astman_send_error(s, m, "No channel specified");
15914       return 0;
15915    }
15916    if (ast_strlen_zero(number)) {
15917       astman_send_error(s, m, "No number specified");
15918       return 0;
15919    }
15920    p = find_channel(atoi(channel));
15921    if (!p) {
15922       astman_send_error(s, m, "No such channel");
15923       return 0;
15924    }
15925    if (!p->owner) {
15926       astman_send_error(s, m, "Channel does not have it's owner");
15927       return 0;
15928    }
15929    for (i = 0; i < strlen(number); i++) {
15930       struct ast_frame f = { AST_FRAME_DTMF, number[i] };
15931       dahdi_queue_frame(p, &f, NULL);
15932    }
15933    astman_send_ack(s, m, "DAHDIDialOffhook");
15934    return 0;
15935 }
15936 
15937 static int action_dahdishowchannels(struct mansession *s, const struct message *m)
15938 {
15939    struct dahdi_pvt *tmp = NULL;
15940    const char *id = astman_get_header(m, "ActionID");
15941    const char *dahdichannel = astman_get_header(m, "DAHDIChannel");
15942    char idText[256] = "";
15943    int channels = 0;
15944    int dahdichanquery = -1;
15945    if (!ast_strlen_zero(dahdichannel)) {
15946       dahdichanquery = atoi(dahdichannel);
15947    }
15948 
15949    astman_send_ack(s, m, "DAHDI channel status will follow");
15950    if (!ast_strlen_zero(id))
15951       snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
15952 
15953    ast_mutex_lock(&iflock);
15954 
15955    tmp = iflist;
15956    while (tmp) {
15957       if (tmp->channel > 0) {
15958          int alm = get_alarms(tmp);
15959 
15960          /* If a specific channel is queried for, only deliver status for that channel */
15961          if (dahdichanquery > 0 && tmp->channel != dahdichanquery)
15962             continue;
15963 
15964          channels++;
15965          if (tmp->owner) {
15966             /* Add data if we have a current call */
15967             astman_append(s,
15968                "Event: DAHDIShowChannels\r\n"
15969                "DAHDIChannel: %d\r\n"
15970                "Channel: %s\r\n"
15971                "Uniqueid: %s\r\n"
15972                "AccountCode: %s\r\n"
15973                "Signalling: %s\r\n"
15974                "SignallingCode: %d\r\n"
15975                "Context: %s\r\n"
15976                "DND: %s\r\n"
15977                "Alarm: %s\r\n"
15978                "%s"
15979                "\r\n",
15980                tmp->channel,
15981                tmp->owner->name,
15982                tmp->owner->uniqueid,
15983                tmp->owner->accountcode,
15984                sig2str(tmp->sig),
15985                tmp->sig,
15986                tmp->context,
15987                tmp->dnd ? "Enabled" : "Disabled",
15988                alarm2str(alm), idText);
15989          } else {
15990             astman_append(s,
15991                "Event: DAHDIShowChannels\r\n"
15992                "DAHDIChannel: %d\r\n"
15993                "Signalling: %s\r\n"
15994                "SignallingCode: %d\r\n"
15995                "Context: %s\r\n"
15996                "DND: %s\r\n"
15997                "Alarm: %s\r\n"
15998                "%s"
15999                "\r\n",
16000                tmp->channel, sig2str(tmp->sig), tmp->sig,
16001                tmp->context,
16002                tmp->dnd ? "Enabled" : "Disabled",
16003                alarm2str(alm), idText);
16004          }
16005       }
16006 
16007       tmp = tmp->next;
16008    }
16009 
16010    ast_mutex_unlock(&iflock);
16011 
16012    astman_append(s,
16013       "Event: DAHDIShowChannelsComplete\r\n"
16014       "%s"
16015       "Items: %d\r\n"
16016       "\r\n",
16017       idText,
16018       channels);
16019    return 0;
16020 }
16021 
16022 #if defined(HAVE_SS7)
16023 static int linkset_addsigchan(int sigchan)
16024 {
16025    struct dahdi_ss7 *link;
16026    int res;
16027    int curfd;
16028    struct dahdi_params p;
16029    struct dahdi_bufferinfo bi;
16030    struct dahdi_spaninfo si;
16031 
16032 
16033    link = ss7_resolve_linkset(cur_linkset);
16034    if (!link) {
16035       ast_log(LOG_ERROR, "Invalid linkset number.  Must be between 1 and %d\n", NUM_SPANS + 1);
16036       return -1;
16037    }
16038 
16039    if (cur_ss7type < 0) {
16040       ast_log(LOG_ERROR, "Unspecified or invalid ss7type\n");
16041       return -1;
16042    }
16043 
16044    if (!link->ss7)
16045       link->ss7 = ss7_new(cur_ss7type);
16046 
16047    if (!link->ss7) {
16048       ast_log(LOG_ERROR, "Can't create new SS7!\n");
16049       return -1;
16050    }
16051 
16052    link->type = cur_ss7type;
16053 
16054    if (cur_pointcode < 0) {
16055       ast_log(LOG_ERROR, "Unspecified pointcode!\n");
16056       return -1;
16057    } else
16058       ss7_set_pc(link->ss7, cur_pointcode);
16059 
16060    if (sigchan < 0) {
16061       ast_log(LOG_ERROR, "Invalid sigchan!\n");
16062       return -1;
16063    } else {
16064       if (link->numsigchans >= NUM_DCHANS) {
16065          ast_log(LOG_ERROR, "Too many sigchans on linkset %d\n", cur_linkset);
16066          return -1;
16067       }
16068       curfd = link->numsigchans;
16069 
16070       link->fds[curfd] = open("/dev/dahdi/channel", O_RDWR, 0600);
16071       if ((link->fds[curfd] < 0) || (ioctl(link->fds[curfd],DAHDI_SPECIFY,&sigchan) == -1)) {
16072          ast_log(LOG_ERROR, "Unable to open SS7 sigchan %d (%s)\n", sigchan, strerror(errno));
16073          return -1;
16074       }
16075       memset(&p, 0, sizeof(p));
16076       res = ioctl(link->fds[curfd], DAHDI_GET_PARAMS, &p);
16077       if (res) {
16078          dahdi_close_ss7_fd(link, curfd);
16079          ast_log(LOG_ERROR, "Unable to get parameters for sigchan %d (%s)\n", sigchan, strerror(errno));
16080          return -1;
16081       }
16082       if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC) && (p.sigtype != DAHDI_SIG_MTP2)) {
16083          dahdi_close_ss7_fd(link, curfd);
16084          ast_log(LOG_ERROR, "sigchan %d is not in HDLC/FCS mode.\n", sigchan);
16085          return -1;
16086       }
16087 
16088       memset(&bi, 0, sizeof(bi));
16089       bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
16090       bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
16091       bi.numbufs = 32;
16092       bi.bufsize = 512;
16093 
16094       if (ioctl(link->fds[curfd], DAHDI_SET_BUFINFO, &bi)) {
16095          ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", sigchan, strerror(errno));
16096          dahdi_close_ss7_fd(link, curfd);
16097          return -1;
16098       }
16099 
16100       if (p.sigtype == DAHDI_SIG_MTP2)
16101          ss7_add_link(link->ss7, SS7_TRANSPORT_DAHDIMTP2, link->fds[curfd]);
16102       else
16103          ss7_add_link(link->ss7, SS7_TRANSPORT_DAHDIDCHAN, link->fds[curfd]);
16104 
16105       link->numsigchans++;
16106 
16107       memset(&si, 0, sizeof(si));
16108       res = ioctl(link->fds[curfd], DAHDI_SPANSTAT, &si);
16109       if (res) {
16110          dahdi_close_ss7_fd(link, curfd);
16111          ast_log(LOG_ERROR, "Unable to get span state for sigchan %d (%s)\n", sigchan, strerror(errno));
16112       }
16113 
16114       if (!si.alarms) {
16115          link->linkstate[curfd] = LINKSTATE_DOWN;
16116          ss7_link_noalarm(link->ss7, link->fds[curfd]);
16117       } else {
16118          link->linkstate[curfd] = LINKSTATE_DOWN | LINKSTATE_INALARM;
16119          ss7_link_alarm(link->ss7, link->fds[curfd]);
16120       }
16121    }
16122 
16123    if (cur_adjpointcode < 0) {
16124       ast_log(LOG_ERROR, "Unspecified adjpointcode!\n");
16125       return -1;
16126    } else {
16127       ss7_set_adjpc(link->ss7, link->fds[curfd], cur_adjpointcode);
16128    }
16129 
16130    if (cur_defaultdpc < 0) {
16131       ast_log(LOG_ERROR, "Unspecified defaultdpc!\n");
16132       return -1;
16133    }
16134 
16135    if (cur_networkindicator < 0) {
16136       ast_log(LOG_ERROR, "Invalid networkindicator!\n");
16137       return -1;
16138    } else
16139       ss7_set_network_ind(link->ss7, cur_networkindicator);
16140 
16141    return 0;
16142 }
16143 #endif   /* defined(HAVE_SS7) */
16144 
16145 #if defined(HAVE_SS7)
16146 static char *handle_ss7_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16147 {
16148    int span;
16149    switch (cmd) {
16150    case CLI_INIT:
16151       e->command = "ss7 set debug {on|off} linkset";
16152       e->usage =
16153          "Usage: ss7 set debug {on|off} linkset <linkset>\n"
16154          "       Enables debugging on a given SS7 linkset\n";
16155       return NULL;
16156    case CLI_GENERATE:
16157       return NULL;
16158    }
16159    if (a->argc < 6)
16160       return CLI_SHOWUSAGE;
16161    span = atoi(a->argv[5]);
16162    if ((span < 1) || (span > NUM_SPANS)) {
16163       ast_cli(a->fd, "Invalid linkset %s.  Should be a number from %d to %d\n", a->argv[5], 1, NUM_SPANS);
16164       return CLI_SUCCESS;
16165    }
16166    if (!linksets[span-1].ss7) {
16167       ast_cli(a->fd, "No SS7 running on linkset %d\n", span);
16168       return CLI_SUCCESS;
16169    }
16170    if (linksets[span-1].ss7) {
16171       if (!strcasecmp(a->argv[3], "on")) {
16172          ss7_set_debug(linksets[span-1].ss7, SS7_DEBUG_MTP2 | SS7_DEBUG_MTP3 | SS7_DEBUG_ISUP);
16173          ast_cli(a->fd, "Enabled debugging on linkset %d\n", span);
16174       } else {
16175          ss7_set_debug(linksets[span-1].ss7, 0);
16176          ast_cli(a->fd, "Disabled debugging on linkset %d\n", span);
16177       }
16178    }
16179 
16180    return CLI_SUCCESS;
16181 }
16182 #endif   /* defined(HAVE_SS7) */
16183 
16184 #if defined(HAVE_SS7)
16185 static char *handle_ss7_block_cic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16186 {
16187    int linkset, cic;
16188    int blocked = -1, i;
16189    switch (cmd) {
16190    case CLI_INIT:
16191       e->command = "ss7 block cic";
16192       e->usage =
16193          "Usage: ss7 block cic <linkset> <CIC>\n"
16194          "       Sends a remote blocking request for the given CIC on the specified linkset\n";
16195       return NULL;
16196    case CLI_GENERATE:
16197       return NULL;
16198    }
16199    if (a->argc == 5)
16200       linkset = atoi(a->argv[3]);
16201    else
16202       return CLI_SHOWUSAGE;
16203 
16204    if ((linkset < 1) || (linkset > NUM_SPANS)) {
16205       ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16206       return CLI_SUCCESS;
16207    }
16208 
16209    if (!linksets[linkset-1].ss7) {
16210       ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16211       return CLI_SUCCESS;
16212    }
16213 
16214    cic = atoi(a->argv[4]);
16215 
16216    if (cic < 1) {
16217       ast_cli(a->fd, "Invalid CIC specified!\n");
16218       return CLI_SUCCESS;
16219    }
16220 
16221    for (i = 0; i < linksets[linkset-1].numchans; i++) {
16222       if (linksets[linkset-1].pvts[i]->cic == cic) {
16223          blocked = linksets[linkset-1].pvts[i]->locallyblocked;
16224          if (!blocked) {
16225             ast_mutex_lock(&linksets[linkset-1].lock);
16226             isup_blo(linksets[linkset-1].ss7, cic, linksets[linkset-1].pvts[i]->dpc);
16227             ast_mutex_unlock(&linksets[linkset-1].lock);
16228          }
16229       }
16230    }
16231 
16232    if (blocked < 0) {
16233       ast_cli(a->fd, "Invalid CIC specified!\n");
16234       return CLI_SUCCESS;
16235    }
16236 
16237    if (!blocked)
16238       ast_cli(a->fd, "Sent blocking request for linkset %d on CIC %d\n", linkset, cic);
16239    else
16240       ast_cli(a->fd, "CIC %d already locally blocked\n", cic);
16241 
16242    /* Break poll on the linkset so it sends our messages */
16243    pthread_kill(linksets[linkset-1].master, SIGURG);
16244 
16245    return CLI_SUCCESS;
16246 }
16247 #endif   /* defined(HAVE_SS7) */
16248 
16249 #if defined(HAVE_SS7)
16250 static char *handle_ss7_block_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16251 {
16252    int linkset;
16253    int i;
16254    switch (cmd) {
16255    case CLI_INIT:
16256       e->command = "ss7 block linkset";
16257       e->usage =
16258          "Usage: ss7 block linkset <linkset number>\n"
16259          "       Sends a remote blocking request for all CICs on the given linkset\n";
16260       return NULL;
16261    case CLI_GENERATE:
16262       return NULL;
16263    }
16264    if (a->argc == 4)
16265       linkset = atoi(a->argv[3]);
16266    else
16267       return CLI_SHOWUSAGE;
16268 
16269    if ((linkset < 1) || (linkset > NUM_SPANS)) {
16270       ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16271       return CLI_SUCCESS;
16272    }
16273 
16274    if (!linksets[linkset-1].ss7) {
16275       ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16276       return CLI_SUCCESS;
16277    }
16278 
16279    for (i = 0; i < linksets[linkset-1].numchans; i++) {
16280       ast_cli(a->fd, "Sending remote blocking request on CIC %d\n", linksets[linkset-1].pvts[i]->cic);
16281       ast_mutex_lock(&linksets[linkset-1].lock);
16282       isup_blo(linksets[linkset-1].ss7, linksets[linkset-1].pvts[i]->cic, linksets[linkset-1].pvts[i]->dpc);
16283       ast_mutex_unlock(&linksets[linkset-1].lock);
16284    }
16285 
16286    /* Break poll on the linkset so it sends our messages */
16287    pthread_kill(linksets[linkset-1].master, SIGURG);
16288 
16289    return CLI_SUCCESS;
16290 }
16291 #endif   /* defined(HAVE_SS7) */
16292 
16293 #if defined(HAVE_SS7)
16294 static char *handle_ss7_unblock_cic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16295 {
16296    int linkset, cic;
16297    int i, blocked = -1;
16298    switch (cmd) {
16299    case CLI_INIT:
16300       e->command = "ss7 unblock cic";
16301       e->usage =
16302          "Usage: ss7 unblock cic <linkset> <CIC>\n"
16303          "       Sends a remote unblocking request for the given CIC on the specified linkset\n";
16304       return NULL;
16305    case CLI_GENERATE:
16306       return NULL;
16307    }
16308 
16309    if (a->argc == 5)
16310       linkset = atoi(a->argv[3]);
16311    else
16312       return CLI_SHOWUSAGE;
16313 
16314    if ((linkset < 1) || (linkset > NUM_SPANS)) {
16315       ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16316       return CLI_SUCCESS;
16317    }
16318 
16319    if (!linksets[linkset-1].ss7) {
16320       ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16321       return CLI_SUCCESS;
16322    }
16323 
16324    cic = atoi(a->argv[4]);
16325 
16326    if (cic < 1) {
16327       ast_cli(a->fd, "Invalid CIC specified!\n");
16328       return CLI_SUCCESS;
16329    }
16330 
16331    for (i = 0; i < linksets[linkset-1].numchans; i++) {
16332       if (linksets[linkset-1].pvts[i]->cic == cic) {
16333          blocked = linksets[linkset-1].pvts[i]->locallyblocked;
16334          if (blocked) {
16335             ast_mutex_lock(&linksets[linkset-1].lock);
16336             isup_ubl(linksets[linkset-1].ss7, cic, linksets[linkset-1].pvts[i]->dpc);
16337             ast_mutex_unlock(&linksets[linkset-1].lock);
16338          }
16339       }
16340    }
16341 
16342    if (blocked > 0)
16343       ast_cli(a->fd, "Sent unblocking request for linkset %d on CIC %d\n", linkset, cic);
16344 
16345    /* Break poll on the linkset so it sends our messages */
16346    pthread_kill(linksets[linkset-1].master, SIGURG);
16347 
16348    return CLI_SUCCESS;
16349 }
16350 #endif   /* defined(HAVE_SS7) */
16351 
16352 #if defined(HAVE_SS7)
16353 static char *handle_ss7_unblock_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16354 {
16355    int linkset;
16356    int i;
16357    switch (cmd) {
16358    case CLI_INIT:
16359       e->command = "ss7 unblock linkset";
16360       e->usage =
16361          "Usage: ss7 unblock linkset <linkset number>\n"
16362          "       Sends a remote unblocking request for all CICs on the specified linkset\n";
16363       return NULL;
16364    case CLI_GENERATE:
16365       return NULL;
16366    }
16367 
16368    if (a->argc == 4)
16369       linkset = atoi(a->argv[3]);
16370    else
16371       return CLI_SHOWUSAGE;
16372 
16373    if ((linkset < 1) || (linkset > NUM_SPANS)) {
16374       ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16375       return CLI_SUCCESS;
16376    }
16377 
16378    if (!linksets[linkset-1].ss7) {
16379       ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16380       return CLI_SUCCESS;
16381    }
16382 
16383    for (i = 0; i < linksets[linkset-1].numchans; i++) {
16384       ast_cli(a->fd, "Sending remote unblock request on CIC %d\n", linksets[linkset-1].pvts[i]->cic);
16385       ast_mutex_lock(&linksets[linkset-1].lock);
16386       isup_ubl(linksets[linkset-1].ss7, linksets[linkset-1].pvts[i]->cic, linksets[linkset-1].pvts[i]->dpc);
16387       ast_mutex_unlock(&linksets[linkset-1].lock);
16388    }
16389 
16390    /* Break poll on the linkset so it sends our messages */
16391    pthread_kill(linksets[linkset-1].master, SIGURG);
16392 
16393    return CLI_SUCCESS;
16394 }
16395 #endif   /* defined(HAVE_SS7) */
16396 
16397 #if defined(HAVE_SS7)
16398 static char *handle_ss7_show_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16399 {
16400    int linkset;
16401    struct dahdi_ss7 *ss7;
16402    switch (cmd) {
16403    case CLI_INIT:
16404       e->command = "ss7 show linkset";
16405       e->usage =
16406          "Usage: ss7 show linkset <span>\n"
16407          "       Shows the status of an SS7 linkset.\n";
16408       return NULL;
16409    case CLI_GENERATE:
16410       return NULL;
16411    }
16412 
16413    if (a->argc < 4)
16414       return CLI_SHOWUSAGE;
16415    linkset = atoi(a->argv[3]);
16416    if ((linkset < 1) || (linkset > NUM_SPANS)) {
16417       ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16418       return CLI_SUCCESS;
16419    }
16420    if (!linksets[linkset-1].ss7) {
16421       ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16422       return CLI_SUCCESS;
16423    }
16424    if (linksets[linkset-1].ss7)
16425       ss7 = &linksets[linkset-1];
16426 
16427    ast_cli(a->fd, "SS7 linkset %d status: %s\n", linkset, (ss7->state == LINKSET_STATE_UP) ? "Up" : "Down");
16428 
16429    return CLI_SUCCESS;
16430 }
16431 #endif   /* defined(HAVE_SS7) */
16432 
16433 #if defined(HAVE_SS7)
16434 static char *handle_ss7_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16435 {
16436    switch (cmd) {
16437    case CLI_INIT:
16438       e->command = "ss7 show version";
16439       e->usage =
16440          "Usage: ss7 show version\n"
16441          "  Show the libss7 version\n";
16442       return NULL;
16443    case CLI_GENERATE:
16444       return NULL;
16445    }
16446 
16447    ast_cli(a->fd, "libss7 version: %s\n", ss7_get_version());
16448 
16449    return CLI_SUCCESS;
16450 }
16451 #endif   /* defined(HAVE_SS7) */
16452 
16453 #if defined(HAVE_SS7)
16454 static struct ast_cli_entry dahdi_ss7_cli[] = {
16455    AST_CLI_DEFINE(handle_ss7_debug, "Enables SS7 debugging on a linkset"),
16456    AST_CLI_DEFINE(handle_ss7_block_cic, "Blocks the given CIC"),
16457    AST_CLI_DEFINE(handle_ss7_unblock_cic, "Unblocks the given CIC"),
16458    AST_CLI_DEFINE(handle_ss7_block_linkset, "Blocks all CICs on a linkset"),
16459    AST_CLI_DEFINE(handle_ss7_unblock_linkset, "Unblocks all CICs on a linkset"),
16460    AST_CLI_DEFINE(handle_ss7_show_linkset, "Shows the status of a linkset"),
16461    AST_CLI_DEFINE(handle_ss7_version, "Displays libss7 version"),
16462 };
16463 #endif   /* defined(HAVE_SS7) */
16464 
16465 static int __unload_module(void)
16466 {
16467    struct dahdi_pvt *p;
16468 #if defined(HAVE_PRI) || defined(HAVE_SS7)
16469    int i, j;
16470 #endif
16471 
16472 #ifdef HAVE_PRI
16473    for (i = 0; i < NUM_SPANS; i++) {
16474       if (pris[i].master != AST_PTHREADT_NULL)
16475          pthread_cancel(pris[i].master);
16476    }
16477    ast_cli_unregister_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
16478    ast_unregister_application(dahdi_send_keypad_facility_app);
16479 #ifdef HAVE_PRI_PROG_W_CAUSE
16480    ast_unregister_application(dahdi_send_callrerouting_facility_app);
16481 #endif
16482 #endif
16483 #if defined(HAVE_SS7)
16484    for (i = 0; i < NUM_SPANS; i++) {
16485       if (linksets[i].master != AST_PTHREADT_NULL)
16486          pthread_cancel(linksets[i].master);
16487       }
16488    ast_cli_unregister_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
16489 #endif
16490 #if defined(HAVE_OPENR2)
16491    dahdi_r2_destroy_links();
16492    ast_cli_unregister_multiple(dahdi_mfcr2_cli, ARRAY_LEN(dahdi_mfcr2_cli));
16493    ast_unregister_application(dahdi_accept_r2_call_app);
16494 #endif
16495 
16496    ast_cli_unregister_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli));
16497    ast_manager_unregister( "DAHDIDialOffhook" );
16498    ast_manager_unregister( "DAHDIHangup" );
16499    ast_manager_unregister( "DAHDITransfer" );
16500    ast_manager_unregister( "DAHDIDNDoff" );
16501    ast_manager_unregister( "DAHDIDNDon" );
16502    ast_manager_unregister("DAHDIShowChannels");
16503    ast_manager_unregister("DAHDIRestart");
16504    ast_channel_unregister(&dahdi_tech);
16505    ast_mutex_lock(&iflock);
16506    /* Hangup all interfaces if they have an owner */
16507    p = iflist;
16508    while (p) {
16509       if (p->owner)
16510          ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
16511       p = p->next;
16512    }
16513    ast_mutex_unlock(&iflock);
16514    ast_mutex_lock(&monlock);
16515    if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
16516       pthread_cancel(monitor_thread);
16517       pthread_kill(monitor_thread, SIGURG);
16518       pthread_join(monitor_thread, NULL);
16519    }
16520    monitor_thread = AST_PTHREADT_STOP;
16521    ast_mutex_unlock(&monlock);
16522 
16523    destroy_all_channels();
16524 
16525 #if defined(HAVE_PRI)
16526    for (i = 0; i < NUM_SPANS; i++) {
16527       if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL))
16528          pthread_join(pris[i].master, NULL);
16529       for (j = 0; j < NUM_DCHANS; j++) {
16530          dahdi_close_pri_fd(&(pris[i]), j);
16531       }
16532    }
16533 #endif
16534 
16535 #if defined(HAVE_SS7)
16536    for (i = 0; i < NUM_SPANS; i++) {
16537       if (linksets[i].master && (linksets[i].master != AST_PTHREADT_NULL))
16538          pthread_join(linksets[i].master, NULL);
16539       for (j = 0; j < NUM_DCHANS; j++) {
16540          dahdi_close_ss7_fd(&(linksets[i]), j);
16541       }
16542    }
16543 #endif
16544    ast_cond_destroy(&ss_thread_complete);
16545    return 0;
16546 }
16547 
16548 static int unload_module(void)
16549 {
16550 #if defined(HAVE_PRI) || defined(HAVE_SS7)
16551    int y;
16552 #endif
16553 #ifdef HAVE_PRI
16554    for (y = 0; y < NUM_SPANS; y++)
16555       ast_mutex_destroy(&pris[y].lock);
16556 #endif
16557 #ifdef HAVE_SS7
16558    for (y = 0; y < NUM_SPANS; y++)
16559       ast_mutex_destroy(&linksets[y].lock);
16560 #endif /* HAVE_SS7 */
16561    return __unload_module();
16562 }
16563 
16564 static int build_channels(struct dahdi_chan_conf *conf, int iscrv, const char *value, int reload, int lineno, int *found_pseudo)
16565 {
16566    char *c, *chan;
16567    int x, start, finish;
16568    struct dahdi_pvt *tmp;
16569 #ifdef HAVE_PRI
16570    struct dahdi_pri *pri;
16571    int trunkgroup, y;
16572 #endif
16573 
16574    if ((reload == 0) && (conf->chan.sig < 0) && !conf->is_sig_auto) {
16575       ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n");
16576       return -1;
16577    }
16578 
16579    c = ast_strdupa(value);
16580 
16581 #ifdef HAVE_PRI
16582    pri = NULL;
16583    if (iscrv) {
16584       if (sscanf(c, "%30d:%n", &trunkgroup, &y) != 1) {
16585          ast_log(LOG_WARNING, "CRV must begin with trunkgroup followed by a colon at line %d.\n", lineno);
16586          return -1;
16587       }
16588       if (trunkgroup < 1) {
16589          ast_log(LOG_WARNING, "CRV trunk group must be a positive number at line %d.\n", lineno);
16590          return -1;
16591       }
16592       c += y;
16593       for (y = 0; y < NUM_SPANS; y++) {
16594          if (pris[y].trunkgroup == trunkgroup) {
16595             pri = pris + y;
16596             break;
16597          }
16598       }
16599       if (!pri) {
16600          ast_log(LOG_WARNING, "No such trunk group %d at CRV declaration at line %d.\n", trunkgroup, lineno);
16601          return -1;
16602       }
16603    }
16604 #endif
16605 
16606    while ((chan = strsep(&c, ","))) {
16607       if (sscanf(chan, "%30d-%30d", &start, &finish) == 2) {
16608          /* Range */
16609       } else if (sscanf(chan, "%30d", &start)) {
16610          /* Just one */
16611          finish = start;
16612       } else if (!strcasecmp(chan, "pseudo")) {
16613          finish = start = CHAN_PSEUDO;
16614          if (found_pseudo)
16615             *found_pseudo = 1;
16616       } else {
16617          ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan);
16618          return -1;
16619       }
16620       if (finish < start) {
16621          ast_log(LOG_WARNING, "Sillyness: %d < %d\n", start, finish);
16622          x = finish;
16623          finish = start;
16624          start = x;
16625       }
16626 
16627       for (x = start; x <= finish; x++) {
16628 #ifdef HAVE_PRI
16629          tmp = mkintf(x, conf, pri, reload);
16630 #else
16631          tmp = mkintf(x, conf, NULL, reload);
16632 #endif
16633 
16634          if (tmp) {
16635 #ifdef HAVE_PRI
16636             if (pri)
16637                ast_verb(3, "%s CRV %d:%d, %s signalling\n", reload ? "Reconfigured" : "Registered", trunkgroup, x, sig2str(tmp->sig));
16638             else
16639 #endif
16640                ast_verb(3, "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", x, sig2str(tmp->sig));
16641          } else {
16642             ast_log(LOG_ERROR, "Unable to %s channel '%s'\n",
16643                (reload == 1) ? "reconfigure" : "register", value);
16644             return -1;
16645          }
16646       }
16647    }
16648 
16649    return 0;
16650 }
16651 
16652 /** The length of the parameters list of 'dahdichan'.
16653  * \todo Move definition of MAX_CHANLIST_LEN to a proper place. */
16654 #define MAX_CHANLIST_LEN 80
16655 
16656 static void process_echocancel(struct dahdi_chan_conf *confp, const char *data, unsigned int line)
16657 {
16658    char *parse = ast_strdupa(data);
16659    char *params[DAHDI_MAX_ECHOCANPARAMS + 1];
16660    unsigned int param_count;
16661    unsigned int x;
16662 
16663    if (!(param_count = ast_app_separate_args(parse, ',', params, ARRAY_LEN(params))))
16664       return;
16665 
16666    memset(&confp->chan.echocancel, 0, sizeof(confp->chan.echocancel));
16667 
16668    /* first parameter is tap length, process it here */
16669 
16670    x = ast_strlen_zero(params[0]) ? 0 : atoi(params[0]);
16671 
16672    if ((x == 32) || (x == 64) || (x == 128) || (x == 256) || (x == 512) || (x == 1024))
16673       confp->chan.echocancel.head.tap_length = x;
16674    else if ((confp->chan.echocancel.head.tap_length = ast_true(params[0])))
16675       confp->chan.echocancel.head.tap_length = 128;
16676 
16677    /* now process any remaining parameters */
16678 
16679    for (x = 1; x < param_count; x++) {
16680       struct {
16681          char *name;
16682          char *value;
16683       } param;
16684 
16685       if (ast_app_separate_args(params[x], '=', (char **) &param, 2) < 1) {
16686          ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, params[x]);
16687          continue;
16688       }
16689 
16690       if (ast_strlen_zero(param.name) || (strlen(param.name) > sizeof(confp->chan.echocancel.params[0].name)-1)) {
16691          ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, param.name);
16692          continue;
16693       }
16694 
16695       strcpy(confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].name, param.name);
16696 
16697       if (param.value) {
16698          if (sscanf(param.value, "%30d", &confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].value) != 1) {
16699             ast_log(LOG_WARNING, "Invalid echocancel parameter value supplied at line %d: '%s'\n", line, param.value);
16700             continue;
16701          }
16702       }
16703       confp->chan.echocancel.head.param_count++;
16704    }
16705 }
16706 
16707 /*! process_dahdi() - ignore keyword 'channel' and similar */
16708 #define PROC_DAHDI_OPT_NOCHAN  (1 << 0)
16709 /*! process_dahdi() - No warnings on non-existing cofiguration keywords */
16710 #define PROC_DAHDI_OPT_NOWARN  (1 << 1)
16711 
16712 static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct ast_variable *v, int reload, int options)
16713 {
16714    struct dahdi_pvt *tmp;
16715    int y;
16716    int found_pseudo = 0;
16717    char dahdichan[MAX_CHANLIST_LEN] = {};
16718 
16719    for (; v; v = v->next) {
16720       if (!ast_jb_read_conf(&global_jbconf, v->name, v->value))
16721          continue;
16722 
16723       /* must have parkinglot in confp before build_channels is called */
16724       if (!strcasecmp(v->name, "parkinglot")) {
16725          ast_copy_string(confp->chan.parkinglot, v->value, sizeof(confp->chan.parkinglot));
16726       }
16727 
16728       /* Create the interface list */
16729       if (!strcasecmp(v->name, "channel")
16730 #ifdef HAVE_PRI
16731          || !strcasecmp(v->name, "crv")
16732 #endif
16733          ) {
16734          int iscrv;
16735          if (options & PROC_DAHDI_OPT_NOCHAN) {
16736             ast_log(LOG_WARNING, "Channel '%s' ignored.\n", v->value);
16737             continue;
16738          }
16739          iscrv = !strcasecmp(v->name, "crv");
16740          if (build_channels(confp, iscrv, v->value, reload, v->lineno, &found_pseudo))
16741                return -1;
16742          ast_log(LOG_DEBUG, "Channel '%s' configured.\n", v->value);
16743       } else if (!strcasecmp(v->name, "buffers")) {
16744          if (parse_buffers_policy(v->value, &confp->chan.buf_no, &confp->chan.buf_policy)) {
16745             ast_log(LOG_WARNING, "Using default buffer policy.\n");
16746             confp->chan.buf_no = numbufs;
16747             confp->chan.buf_policy = DAHDI_POLICY_IMMEDIATE;
16748          }
16749       } else if (!strcasecmp(v->name, "faxbuffers")) {
16750          if (!parse_buffers_policy(v->value, &confp->chan.faxbuf_no, &confp->chan.faxbuf_policy)) {
16751             confp->chan.usefaxbuffers = 1;
16752          }
16753       } else if (!strcasecmp(v->name, "dahdichan")) {
16754          ast_copy_string(dahdichan, v->value, sizeof(dahdichan));
16755       } else if (!strcasecmp(v->name, "usedistinctiveringdetection")) {
16756          usedistinctiveringdetection = ast_true(v->value);
16757       } else if (!strcasecmp(v->name, "distinctiveringaftercid")) {
16758          distinctiveringaftercid = ast_true(v->value);
16759       } else if (!strcasecmp(v->name, "dring1context")) {
16760          ast_copy_string(confp->chan.drings.ringContext[0].contextData,v->value,sizeof(confp->chan.drings.ringContext[0].contextData));
16761       } else if (!strcasecmp(v->name, "dring2context")) {
16762          ast_copy_string(confp->chan.drings.ringContext[1].contextData,v->value,sizeof(confp->chan.drings.ringContext[1].contextData));
16763       } else if (!strcasecmp(v->name, "dring3context")) {
16764          ast_copy_string(confp->chan.drings.ringContext[2].contextData,v->value,sizeof(confp->chan.drings.ringContext[2].contextData));
16765       } else if (!strcasecmp(v->name, "dring1range")) {
16766          confp->chan.drings.ringnum[0].range = atoi(v->value);
16767       } else if (!strcasecmp(v->name, "dring2range")) {
16768          confp->chan.drings.ringnum[1].range = atoi(v->value);
16769       } else if (!strcasecmp(v->name, "dring3range")) {
16770          confp->chan.drings.ringnum[2].range = atoi(v->value);
16771       } else if (!strcasecmp(v->name, "dring1")) {
16772          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]);
16773       } else if (!strcasecmp(v->name, "dring2")) {
16774          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]);
16775       } else if (!strcasecmp(v->name, "dring3")) {
16776          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]);
16777       } else if (!strcasecmp(v->name, "usecallerid")) {
16778          confp->chan.use_callerid = ast_true(v->value);
16779       } else if (!strcasecmp(v->name, "cidsignalling")) {
16780          if (!strcasecmp(v->value, "bell"))
16781             confp->chan.cid_signalling = CID_SIG_BELL;
16782          else if (!strcasecmp(v->value, "v23"))
16783             confp->chan.cid_signalling = CID_SIG_V23;
16784          else if (!strcasecmp(v->value, "dtmf"))
16785             confp->chan.cid_signalling = CID_SIG_DTMF;
16786          else if (!strcasecmp(v->value, "smdi"))
16787             confp->chan.cid_signalling = CID_SIG_SMDI;
16788          else if (!strcasecmp(v->value, "v23_jp"))
16789             confp->chan.cid_signalling = CID_SIG_V23_JP;
16790          else if (ast_true(v->value))
16791             confp->chan.cid_signalling = CID_SIG_BELL;
16792       } else if (!strcasecmp(v->name, "cidstart")) {
16793          if (!strcasecmp(v->value, "ring"))
16794             confp->chan.cid_start = CID_START_RING;
16795          else if (!strcasecmp(v->value, "polarity_in"))
16796             confp->chan.cid_start = CID_START_POLARITY_IN;
16797          else if (!strcasecmp(v->value, "polarity"))
16798             confp->chan.cid_start = CID_START_POLARITY;
16799          else if (ast_true(v->value))
16800             confp->chan.cid_start = CID_START_RING;
16801       } else if (!strcasecmp(v->name, "threewaycalling")) {
16802          confp->chan.threewaycalling = ast_true(v->value);
16803       } else if (!strcasecmp(v->name, "cancallforward")) {
16804          confp->chan.cancallforward = ast_true(v->value);
16805       } else if (!strcasecmp(v->name, "relaxdtmf")) {
16806          if (ast_true(v->value))
16807             confp->chan.dtmfrelax = DSP_DIGITMODE_RELAXDTMF;
16808          else
16809             confp->chan.dtmfrelax = 0;
16810       } else if (!strcasecmp(v->name, "mailbox")) {
16811          ast_copy_string(confp->chan.mailbox, v->value, sizeof(confp->chan.mailbox));
16812       } else if (!strcasecmp(v->name, "hasvoicemail")) {
16813          if (ast_true(v->value) && ast_strlen_zero(confp->chan.mailbox)) {
16814             ast_copy_string(confp->chan.mailbox, cat, sizeof(confp->chan.mailbox));
16815          }
16816       } else if (!strcasecmp(v->name, "adsi")) {
16817          confp->chan.adsi = ast_true(v->value);
16818       } else if (!strcasecmp(v->name, "usesmdi")) {
16819          confp->chan.use_smdi = ast_true(v->value);
16820       } else if (!strcasecmp(v->name, "smdiport")) {
16821          ast_copy_string(confp->smdi_port, v->value, sizeof(confp->smdi_port));
16822       } else if (!strcasecmp(v->name, "transfer")) {
16823          confp->chan.transfer = ast_true(v->value);
16824       } else if (!strcasecmp(v->name, "canpark")) {
16825          confp->chan.canpark = ast_true(v->value);
16826       } else if (!strcasecmp(v->name, "echocancelwhenbridged")) {
16827          confp->chan.echocanbridged = ast_true(v->value);
16828       } else if (!strcasecmp(v->name, "busydetect")) {
16829          confp->chan.busydetect = ast_true(v->value);
16830       } else if (!strcasecmp(v->name, "busycount")) {
16831          confp->chan.busycount = atoi(v->value);
16832       } else if (!strcasecmp(v->name, "busypattern")) {
16833          if (sscanf(v->value, "%30d,%30d", &confp->chan.busy_tonelength, &confp->chan.busy_quietlength) != 2) {
16834             ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength,quietlength at line %d.\n", v->lineno);
16835          }
16836       } else if (!strcasecmp(v->name, "callprogress")) {
16837          confp->chan.callprogress &= ~CALLPROGRESS_PROGRESS;
16838          if (ast_true(v->value))
16839             confp->chan.callprogress |= CALLPROGRESS_PROGRESS;
16840       } else if (!strcasecmp(v->name, "waitfordialtone")) {
16841          confp->chan.waitfordialtone = atoi(v->value);
16842       } else if (!strcasecmp(v->name, "faxdetect")) {
16843          confp->chan.callprogress &= ~CALLPROGRESS_FAX;
16844          if (!strcasecmp(v->value, "incoming")) {
16845             confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING;
16846          } else if (!strcasecmp(v->value, "outgoing")) {
16847             confp->chan.callprogress |= CALLPROGRESS_FAX_OUTGOING;
16848          } else if (!strcasecmp(v->value, "both") || ast_true(v->value))
16849             confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING;
16850       } else if (!strcasecmp(v->name, "echocancel")) {
16851          process_echocancel(confp, v->value, v->lineno);
16852       } else if (!strcasecmp(v->name, "echotraining")) {
16853          if (sscanf(v->value, "%30d", &y) == 1) {
16854             if ((y < 10) || (y > 4000)) {
16855                ast_log(LOG_WARNING, "Echo training time must be within the range of 10 to 4000 ms at line %d.\n", v->lineno);
16856             } else {
16857                confp->chan.echotraining = y;
16858             }
16859          } else if (ast_true(v->value)) {
16860             confp->chan.echotraining = 400;
16861          } else
16862             confp->chan.echotraining = 0;
16863       } else if (!strcasecmp(v->name, "hidecallerid")) {
16864          confp->chan.hidecallerid = ast_true(v->value);
16865       } else if (!strcasecmp(v->name, "hidecalleridname")) {
16866          confp->chan.hidecalleridname = ast_true(v->value);
16867       } else if (!strcasecmp(v->name, "pulsedial")) {
16868          confp->chan.pulse = ast_true(v->value);
16869       } else if (!strcasecmp(v->name, "callreturn")) {
16870          confp->chan.callreturn = ast_true(v->value);
16871       } else if (!strcasecmp(v->name, "callwaiting")) {
16872          confp->chan.callwaiting = ast_true(v->value);
16873       } else if (!strcasecmp(v->name, "callwaitingcallerid")) {
16874          confp->chan.callwaitingcallerid = ast_true(v->value);
16875       } else if (!strcasecmp(v->name, "context")) {
16876          ast_copy_string(confp->chan.context, v->value, sizeof(confp->chan.context));
16877       } else if (!strcasecmp(v->name, "language")) {
16878          ast_copy_string(confp->chan.language, v->value, sizeof(confp->chan.language));
16879       } else if (!strcasecmp(v->name, "progzone")) {
16880          ast_copy_string(progzone, v->value, sizeof(progzone));
16881       } else if (!strcasecmp(v->name, "mohinterpret")
16882          ||!strcasecmp(v->name, "musiconhold") || !strcasecmp(v->name, "musicclass")) {
16883          ast_copy_string(confp->chan.mohinterpret, v->value, sizeof(confp->chan.mohinterpret));
16884       } else if (!strcasecmp(v->name, "mohsuggest")) {
16885          ast_copy_string(confp->chan.mohsuggest, v->value, sizeof(confp->chan.mohsuggest));
16886       } else if (!strcasecmp(v->name, "parkinglot")) {
16887          ast_copy_string(parkinglot, v->value, sizeof(parkinglot));
16888       } else if (!strcasecmp(v->name, "stripmsd")) {
16889          ast_log(LOG_NOTICE, "Configuration option \"%s\" has been deprecated. Please use dialplan instead\n", v->name);
16890          confp->chan.stripmsd = atoi(v->value);
16891       } else if (!strcasecmp(v->name, "jitterbuffers")) {
16892          numbufs = atoi(v->value);
16893       } else if (!strcasecmp(v->name, "group")) {
16894          confp->chan.group = ast_get_group(v->value);
16895       } else if (!strcasecmp(v->name, "callgroup")) {
16896          if (!strcasecmp(v->value, "none"))
16897             confp->chan.callgroup = 0;
16898          else
16899             confp->chan.callgroup = ast_get_group(v->value);
16900       } else if (!strcasecmp(v->name, "pickupgroup")) {
16901          if (!strcasecmp(v->value, "none"))
16902             confp->chan.pickupgroup = 0;
16903          else
16904             confp->chan.pickupgroup = ast_get_group(v->value);
16905       } else if (!strcasecmp(v->name, "setvar")) {
16906          char *varname = ast_strdupa(v->value), *varval = NULL;
16907          struct ast_variable *tmpvar;
16908          if (varname && (varval = strchr(varname, '='))) {
16909             *varval++ = '\0';
16910             if ((tmpvar = ast_variable_new(varname, varval, ""))) {
16911                tmpvar->next = confp->chan.vars;
16912                confp->chan.vars = tmpvar;
16913             }
16914          }
16915       } else if (!strcasecmp(v->name, "immediate")) {
16916          confp->chan.immediate = ast_true(v->value);
16917       } else if (!strcasecmp(v->name, "transfertobusy")) {
16918          confp->chan.transfertobusy = ast_true(v->value);
16919       } else if (!strcasecmp(v->name, "mwimonitor")) {
16920          confp->chan.mwimonitor_neon = 0;
16921          confp->chan.mwimonitor_fsk = 0;
16922          confp->chan.mwimonitor_rpas = 0;
16923          if (strcasestr(v->value, "fsk")) {
16924             confp->chan.mwimonitor_fsk = 1;
16925          }
16926          if (strcasestr(v->value, "rpas")) {
16927             confp->chan.mwimonitor_rpas = 1;
16928          }
16929          if (strcasestr(v->value, "neon")) {
16930             confp->chan.mwimonitor_neon = 1;
16931          }
16932          /* If set to true or yes, assume that simple fsk is desired */
16933          if (ast_true(v->value)) {
16934             confp->chan.mwimonitor_fsk = 1;
16935          }
16936       } else if (!strcasecmp(v->name, "cid_rxgain")) {
16937          if (sscanf(v->value, "%30f", &confp->chan.cid_rxgain) != 1) {
16938             ast_log(LOG_WARNING, "Invalid cid_rxgain: %s at line %d.\n", v->value, v->lineno);
16939          }
16940       } else if (!strcasecmp(v->name, "rxgain")) {
16941          if (sscanf(v->value, "%30f", &confp->chan.rxgain) != 1) {
16942             ast_log(LOG_WARNING, "Invalid rxgain: %s at line %d.\n", v->value, v->lineno);
16943          }
16944       } else if (!strcasecmp(v->name, "txgain")) {
16945          if (sscanf(v->value, "%30f", &confp->chan.txgain) != 1) {
16946             ast_log(LOG_WARNING, "Invalid txgain: %s at line %d.\n", v->value, v->lineno);
16947          }
16948       } else if (!strcasecmp(v->name, "tonezone")) {
16949          if (sscanf(v->value, "%30d", &confp->chan.tonezone) != 1) {
16950             ast_log(LOG_WARNING, "Invalid tonezone: %s at line %d.\n", v->value, v->lineno);
16951          }
16952       } else if (!strcasecmp(v->name, "callerid")) {
16953          if (!strcasecmp(v->value, "asreceived")) {
16954             confp->chan.cid_num[0] = '\0';
16955             confp->chan.cid_name[0] = '\0';
16956          } else {
16957             ast_callerid_split(v->value, confp->chan.cid_name, sizeof(confp->chan.cid_name), confp->chan.cid_num, sizeof(confp->chan.cid_num));
16958          }
16959       } else if (!strcasecmp(v->name, "fullname")) {
16960          ast_copy_string(confp->chan.cid_name, v->value, sizeof(confp->chan.cid_name));
16961       } else if (!strcasecmp(v->name, "cid_number")) {
16962          ast_copy_string(confp->chan.cid_num, v->value, sizeof(confp->chan.cid_num));
16963       } else if (!strcasecmp(v->name, "useincomingcalleridondahditransfer")) {
16964          confp->chan.dahditrcallerid = ast_true(v->value);
16965       } else if (!strcasecmp(v->name, "restrictcid")) {
16966          confp->chan.restrictcid = ast_true(v->value);
16967       } else if (!strcasecmp(v->name, "usecallingpres")) {
16968          confp->chan.use_callingpres = ast_true(v->value);
16969       } else if (!strcasecmp(v->name, "accountcode")) {
16970          ast_copy_string(confp->chan.accountcode, v->value, sizeof(confp->chan.accountcode));
16971       } else if (!strcasecmp(v->name, "amaflags")) {
16972          y = ast_cdr_amaflags2int(v->value);
16973          if (y < 0)
16974             ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d.\n", v->value, v->lineno);
16975          else
16976             confp->chan.amaflags = y;
16977       } else if (!strcasecmp(v->name, "polarityonanswerdelay")) {
16978          confp->chan.polarityonanswerdelay = atoi(v->value);
16979       } else if (!strcasecmp(v->name, "answeronpolarityswitch")) {
16980          confp->chan.answeronpolarityswitch = ast_true(v->value);
16981       } else if (!strcasecmp(v->name, "hanguponpolarityswitch")) {
16982          confp->chan.hanguponpolarityswitch = ast_true(v->value);
16983       } else if (!strcasecmp(v->name, "sendcalleridafter")) {
16984          confp->chan.sendcalleridafter = atoi(v->value);
16985       } else if (!strcasecmp(v->name, "mwimonitornotify")) {
16986          ast_copy_string(mwimonitornotify, v->value, sizeof(mwimonitornotify));
16987       } else if (!strcasecmp(v->name, "mwisendtype")) {
16988 #ifndef HAVE_DAHDI_LINEREVERSE_VMWI  /* backward compatibility for older dahdi VMWI implementation */
16989          if (!strcasecmp(v->value, "rpas")) { /* Ring Pulse Alert Signal */
16990             mwisend_rpas = 1;
16991          } else {
16992             mwisend_rpas = 0;
16993          }
16994 #else
16995          /* Default is fsk, to turn it off you must specify nofsk */
16996          memset(&confp->chan.mwisend_setting, 0, sizeof(confp->chan.mwisend_setting));
16997          if (strcasestr(v->value, "nofsk")) {      /* NoFSK */
16998             confp->chan.mwisend_fsk = 0;
16999          } else {             /* Default FSK */
17000             confp->chan.mwisend_fsk = 1;
17001          }
17002          if (strcasestr(v->value, "rpas")) {       /* Ring Pulse Alert Signal, normally followed by FSK */
17003             confp->chan.mwisend_rpas = 1;
17004          } else {
17005             confp->chan.mwisend_rpas = 0;
17006          }
17007          if (strcasestr(v->value, "lrev")) {       /* Line Reversal */
17008             confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_LREV;
17009          }
17010          if (strcasestr(v->value, "hvdc")) {       /* HV 90VDC */
17011             confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_HVDC;
17012          }
17013          if ( (strcasestr(v->value, "neon")) || (strcasestr(v->value, "hvac")) ){   /* 90V DC pulses */
17014             confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_HVAC;
17015          }
17016 #endif
17017       } else if (reload != 1) {
17018           if (!strcasecmp(v->name, "signalling") || !strcasecmp(v->name, "signaling")) {
17019             int orig_radio = confp->chan.radio;
17020             int orig_outsigmod = confp->chan.outsigmod;
17021             int orig_auto = confp->is_sig_auto;
17022 
17023             confp->chan.radio = 0;
17024             confp->chan.outsigmod = -1;
17025             confp->is_sig_auto = 0;
17026             if (!strcasecmp(v->value, "em")) {
17027                confp->chan.sig = SIG_EM;
17028             } else if (!strcasecmp(v->value, "em_e1")) {
17029                confp->chan.sig = SIG_EM_E1;
17030             } else if (!strcasecmp(v->value, "em_w")) {
17031                confp->chan.sig = SIG_EMWINK;
17032             } else if (!strcasecmp(v->value, "fxs_ls")) {
17033                confp->chan.sig = SIG_FXSLS;
17034             } else if (!strcasecmp(v->value, "fxs_gs")) {
17035                confp->chan.sig = SIG_FXSGS;
17036             } else if (!strcasecmp(v->value, "fxs_ks")) {
17037                confp->chan.sig = SIG_FXSKS;
17038             } else if (!strcasecmp(v->value, "fxo_ls")) {
17039                confp->chan.sig = SIG_FXOLS;
17040             } else if (!strcasecmp(v->value, "fxo_gs")) {
17041                confp->chan.sig = SIG_FXOGS;
17042             } else if (!strcasecmp(v->value, "fxo_ks")) {
17043                confp->chan.sig = SIG_FXOKS;
17044             } else if (!strcasecmp(v->value, "fxs_rx")) {
17045                confp->chan.sig = SIG_FXSKS;
17046                confp->chan.radio = 1;
17047             } else if (!strcasecmp(v->value, "fxo_rx")) {
17048                confp->chan.sig = SIG_FXOLS;
17049                confp->chan.radio = 1;
17050             } else if (!strcasecmp(v->value, "fxs_tx")) {
17051                confp->chan.sig = SIG_FXSLS;
17052                confp->chan.radio = 1;
17053             } else if (!strcasecmp(v->value, "fxo_tx")) {
17054                confp->chan.sig = SIG_FXOGS;
17055                confp->chan.radio = 1;
17056             } else if (!strcasecmp(v->value, "em_rx")) {
17057                confp->chan.sig = SIG_EM;
17058                confp->chan.radio = 1;
17059             } else if (!strcasecmp(v->value, "em_tx")) {
17060                confp->chan.sig = SIG_EM;
17061                confp->chan.radio = 1;
17062             } else if (!strcasecmp(v->value, "em_rxtx")) {
17063                confp->chan.sig = SIG_EM;
17064                confp->chan.radio = 2;
17065             } else if (!strcasecmp(v->value, "em_txrx")) {
17066                confp->chan.sig = SIG_EM;
17067                confp->chan.radio = 2;
17068             } else if (!strcasecmp(v->value, "sf")) {
17069                confp->chan.sig = SIG_SF;
17070             } else if (!strcasecmp(v->value, "sf_w")) {
17071                confp->chan.sig = SIG_SFWINK;
17072             } else if (!strcasecmp(v->value, "sf_featd")) {
17073                confp->chan.sig = SIG_FEATD;
17074             } else if (!strcasecmp(v->value, "sf_featdmf")) {
17075                confp->chan.sig = SIG_FEATDMF;
17076             } else if (!strcasecmp(v->value, "sf_featb")) {
17077                confp->chan.sig = SIG_SF_FEATB;
17078             } else if (!strcasecmp(v->value, "sf")) {
17079                confp->chan.sig = SIG_SF;
17080             } else if (!strcasecmp(v->value, "sf_rx")) {
17081                confp->chan.sig = SIG_SF;
17082                confp->chan.radio = 1;
17083             } else if (!strcasecmp(v->value, "sf_tx")) {
17084                confp->chan.sig = SIG_SF;
17085                confp->chan.radio = 1;
17086             } else if (!strcasecmp(v->value, "sf_rxtx")) {
17087                confp->chan.sig = SIG_SF;
17088                confp->chan.radio = 2;
17089             } else if (!strcasecmp(v->value, "sf_txrx")) {
17090                confp->chan.sig = SIG_SF;
17091                confp->chan.radio = 2;
17092             } else if (!strcasecmp(v->value, "featd")) {
17093                confp->chan.sig = SIG_FEATD;
17094             } else if (!strcasecmp(v->value, "featdmf")) {
17095                confp->chan.sig = SIG_FEATDMF;
17096             } else if (!strcasecmp(v->value, "featdmf_ta")) {
17097                confp->chan.sig = SIG_FEATDMF_TA;
17098             } else if (!strcasecmp(v->value, "e911")) {
17099                confp->chan.sig = SIG_E911;
17100             } else if (!strcasecmp(v->value, "fgccama")) {
17101                confp->chan.sig = SIG_FGC_CAMA;
17102             } else if (!strcasecmp(v->value, "fgccamamf")) {
17103                confp->chan.sig = SIG_FGC_CAMAMF;
17104             } else if (!strcasecmp(v->value, "featb")) {
17105                confp->chan.sig = SIG_FEATB;
17106 #ifdef HAVE_PRI
17107             } else if (!strcasecmp(v->value, "pri_net")) {
17108                confp->chan.sig = SIG_PRI;
17109                confp->pri.nodetype = PRI_NETWORK;
17110             } else if (!strcasecmp(v->value, "pri_cpe")) {
17111                confp->chan.sig = SIG_PRI;
17112                confp->pri.nodetype = PRI_CPE;
17113             } else if (!strcasecmp(v->value, "bri_cpe")) {
17114                confp->chan.sig = SIG_BRI;
17115                confp->pri.nodetype = PRI_CPE;
17116             } else if (!strcasecmp(v->value, "bri_net")) {
17117                confp->chan.sig = SIG_BRI;
17118                confp->pri.nodetype = PRI_NETWORK;
17119             } else if (!strcasecmp(v->value, "bri_cpe_ptmp")) {
17120                confp->chan.sig = SIG_BRI_PTMP;
17121                confp->pri.nodetype = PRI_CPE;
17122             } else if (!strcasecmp(v->value, "bri_net_ptmp")) {
17123                ast_log(LOG_WARNING, "How cool would it be if someone implemented this mode!  For now, sucks for you. (line %d)\n", v->lineno);
17124             } else if (!strcasecmp(v->value, "gr303fxoks_net")) {
17125                confp->chan.sig = SIG_GR303FXOKS;
17126                confp->pri.nodetype = PRI_NETWORK;
17127             } else if (!strcasecmp(v->value, "gr303fxsks_cpe")) {
17128                confp->chan.sig = SIG_GR303FXSKS;
17129                confp->pri.nodetype = PRI_CPE;
17130 #endif
17131 #ifdef HAVE_SS7
17132             } else if (!strcasecmp(v->value, "ss7")) {
17133                confp->chan.sig = SIG_SS7;
17134 #endif
17135 #ifdef HAVE_OPENR2
17136             } else if (!strcasecmp(v->value, "mfcr2")) {
17137                confp->chan.sig = SIG_MFCR2;
17138 #endif
17139             } else if (!strcasecmp(v->value, "auto")) {
17140                confp->is_sig_auto = 1;
17141             } else {
17142                confp->chan.outsigmod = orig_outsigmod;
17143                confp->chan.radio = orig_radio;
17144                confp->is_sig_auto = orig_auto;
17145                ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
17146             }
17147           } else if (!strcasecmp(v->name, "outsignalling") || !strcasecmp(v->name, "outsignaling")) {
17148             if (!strcasecmp(v->value, "em")) {
17149                confp->chan.outsigmod = SIG_EM;
17150             } else if (!strcasecmp(v->value, "em_e1")) {
17151                confp->chan.outsigmod = SIG_EM_E1;
17152             } else if (!strcasecmp(v->value, "em_w")) {
17153                confp->chan.outsigmod = SIG_EMWINK;
17154             } else if (!strcasecmp(v->value, "sf")) {
17155                confp->chan.outsigmod = SIG_SF;
17156             } else if (!strcasecmp(v->value, "sf_w")) {
17157                confp->chan.outsigmod = SIG_SFWINK;
17158             } else if (!strcasecmp(v->value, "sf_featd")) {
17159                confp->chan.outsigmod = SIG_FEATD;
17160             } else if (!strcasecmp(v->value, "sf_featdmf")) {
17161                confp->chan.outsigmod = SIG_FEATDMF;
17162             } else if (!strcasecmp(v->value, "sf_featb")) {
17163                confp->chan.outsigmod = SIG_SF_FEATB;
17164             } else if (!strcasecmp(v->value, "sf")) {
17165                confp->chan.outsigmod = SIG_SF;
17166             } else if (!strcasecmp(v->value, "featd")) {
17167                confp->chan.outsigmod = SIG_FEATD;
17168             } else if (!strcasecmp(v->value, "featdmf")) {
17169                confp->chan.outsigmod = SIG_FEATDMF;
17170             } else if (!strcasecmp(v->value, "featdmf_ta")) {
17171                confp->chan.outsigmod = SIG_FEATDMF_TA;
17172             } else if (!strcasecmp(v->value, "e911")) {
17173                confp->chan.outsigmod = SIG_E911;
17174             } else if (!strcasecmp(v->value, "fgccama")) {
17175                confp->chan.outsigmod = SIG_FGC_CAMA;
17176             } else if (!strcasecmp(v->value, "fgccamamf")) {
17177                confp->chan.outsigmod = SIG_FGC_CAMAMF;
17178             } else if (!strcasecmp(v->value, "featb")) {
17179                confp->chan.outsigmod = SIG_FEATB;
17180             } else {
17181                ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
17182             }
17183 #ifdef HAVE_PRI
17184          } else if (!strcasecmp(v->name, "pridialplan")) {
17185             if (!strcasecmp(v->value, "national")) {
17186                confp->pri.dialplan = PRI_NATIONAL_ISDN + 1;
17187             } else if (!strcasecmp(v->value, "unknown")) {
17188                confp->pri.dialplan = PRI_UNKNOWN + 1;
17189             } else if (!strcasecmp(v->value, "private")) {
17190                confp->pri.dialplan = PRI_PRIVATE + 1;
17191             } else if (!strcasecmp(v->value, "international")) {
17192                confp->pri.dialplan = PRI_INTERNATIONAL_ISDN + 1;
17193             } else if (!strcasecmp(v->value, "local")) {
17194                confp->pri.dialplan = PRI_LOCAL_ISDN + 1;
17195             } else if (!strcasecmp(v->value, "dynamic")) {
17196                confp->pri.dialplan = -1;
17197             } else if (!strcasecmp(v->value, "redundant")) {
17198                confp->pri.dialplan = -2;
17199             } else {
17200                ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno);
17201             }
17202          } else if (!strcasecmp(v->name, "prilocaldialplan")) {
17203             if (!strcasecmp(v->value, "national")) {
17204                confp->pri.localdialplan = PRI_NATIONAL_ISDN + 1;
17205             } else if (!strcasecmp(v->value, "unknown")) {
17206                confp->pri.localdialplan = PRI_UNKNOWN + 1;
17207             } else if (!strcasecmp(v->value, "private")) {
17208                confp->pri.localdialplan = PRI_PRIVATE + 1;
17209             } else if (!strcasecmp(v->value, "international")) {
17210                confp->pri.localdialplan = PRI_INTERNATIONAL_ISDN + 1;
17211             } else if (!strcasecmp(v->value, "local")) {
17212                confp->pri.localdialplan = PRI_LOCAL_ISDN + 1;
17213             } else if (!strcasecmp(v->value, "dynamic")) {
17214                confp->pri.localdialplan = -1;
17215             } else if (!strcasecmp(v->value, "redundant")) {
17216                confp->pri.localdialplan = -2;
17217             } else {
17218                ast_log(LOG_WARNING, "Unknown PRI localdialplan '%s' at line %d.\n", v->value, v->lineno);
17219             }
17220          } else if (!strcasecmp(v->name, "switchtype")) {
17221             if (!strcasecmp(v->value, "national"))
17222                confp->pri.switchtype = PRI_SWITCH_NI2;
17223             else if (!strcasecmp(v->value, "ni1"))
17224                confp->pri.switchtype = PRI_SWITCH_NI1;
17225             else if (!strcasecmp(v->value, "dms100"))
17226                confp->pri.switchtype = PRI_SWITCH_DMS100;
17227             else if (!strcasecmp(v->value, "4ess"))
17228                confp->pri.switchtype = PRI_SWITCH_ATT4ESS;
17229             else if (!strcasecmp(v->value, "5ess"))
17230                confp->pri.switchtype = PRI_SWITCH_LUCENT5E;
17231             else if (!strcasecmp(v->value, "euroisdn"))
17232                confp->pri.switchtype = PRI_SWITCH_EUROISDN_E1;
17233             else if (!strcasecmp(v->value, "qsig"))
17234                confp->pri.switchtype = PRI_SWITCH_QSIG;
17235             else {
17236                ast_log(LOG_ERROR, "Unknown switchtype '%s' at line %d.\n", v->value, v->lineno);
17237                return -1;
17238             }
17239          } else if (!strcasecmp(v->name, "nsf")) {
17240             if (!strcasecmp(v->value, "sdn"))
17241                confp->pri.nsf = PRI_NSF_SDN;
17242             else if (!strcasecmp(v->value, "megacom"))
17243                confp->pri.nsf = PRI_NSF_MEGACOM;
17244             else if (!strcasecmp(v->value, "tollfreemegacom"))
17245                confp->pri.nsf = PRI_NSF_TOLL_FREE_MEGACOM;
17246             else if (!strcasecmp(v->value, "accunet"))
17247                confp->pri.nsf = PRI_NSF_ACCUNET;
17248             else if (!strcasecmp(v->value, "none"))
17249                confp->pri.nsf = PRI_NSF_NONE;
17250             else {
17251                ast_log(LOG_WARNING, "Unknown network-specific facility '%s' at line %d.\n", v->value, v->lineno);
17252                confp->pri.nsf = PRI_NSF_NONE;
17253             }
17254          } else if (!strcasecmp(v->name, "priindication")) {
17255             if (!strcasecmp(v->value, "outofband"))
17256                confp->chan.priindication_oob = 1;
17257             else if (!strcasecmp(v->value, "inband"))
17258                confp->chan.priindication_oob = 0;
17259             else
17260                ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d.\n",
17261                   v->value, v->lineno);
17262          } else if (!strcasecmp(v->name, "priexclusive")) {
17263             confp->chan.priexclusive = ast_true(v->value);
17264          } else if (!strcasecmp(v->name, "internationalprefix")) {
17265             ast_copy_string(confp->pri.internationalprefix, v->value, sizeof(confp->pri.internationalprefix));
17266          } else if (!strcasecmp(v->name, "nationalprefix")) {
17267             ast_copy_string(confp->pri.nationalprefix, v->value, sizeof(confp->pri.nationalprefix));
17268          } else if (!strcasecmp(v->name, "localprefix")) {
17269             ast_copy_string(confp->pri.localprefix, v->value, sizeof(confp->pri.localprefix));
17270          } else if (!strcasecmp(v->name, "privateprefix")) {
17271             ast_copy_string(confp->pri.privateprefix, v->value, sizeof(confp->pri.privateprefix));
17272          } else if (!strcasecmp(v->name, "unknownprefix")) {
17273             ast_copy_string(confp->pri.unknownprefix, v->value, sizeof(confp->pri.unknownprefix));
17274          } else if (!strcasecmp(v->name, "resetinterval")) {
17275             if (!strcasecmp(v->value, "never"))
17276                confp->pri.resetinterval = -1;
17277             else if (atoi(v->value) >= 60)
17278                confp->pri.resetinterval = atoi(v->value);
17279             else
17280                ast_log(LOG_WARNING, "'%s' is not a valid reset interval, should be >= 60 seconds or 'never' at line %d.\n",
17281                   v->value, v->lineno);
17282          } else if (!strcasecmp(v->name, "minunused")) {
17283             confp->pri.minunused = atoi(v->value);
17284          } else if (!strcasecmp(v->name, "minidle")) {
17285             confp->pri.minidle = atoi(v->value);
17286          } else if (!strcasecmp(v->name, "idleext")) {
17287             ast_copy_string(confp->pri.idleext, v->value, sizeof(confp->pri.idleext));
17288          } else if (!strcasecmp(v->name, "idledial")) {
17289             ast_copy_string(confp->pri.idledial, v->value, sizeof(confp->pri.idledial));
17290          } else if (!strcasecmp(v->name, "overlapdial")) {
17291             if (ast_true(v->value)) {
17292                confp->pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
17293             } else if (!strcasecmp(v->value, "incoming")) {
17294                confp->pri.overlapdial = DAHDI_OVERLAPDIAL_INCOMING;
17295             } else if (!strcasecmp(v->value, "outgoing")) {
17296                confp->pri.overlapdial = DAHDI_OVERLAPDIAL_OUTGOING;
17297             } else if (!strcasecmp(v->value, "both") || ast_true(v->value)) {
17298                confp->pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
17299             } else {
17300                confp->pri.overlapdial = DAHDI_OVERLAPDIAL_NONE;
17301             }
17302 #ifdef HAVE_PRI_PROG_W_CAUSE
17303          } else if (!strcasecmp(v->name, "qsigchannelmapping")) {
17304             if (!strcasecmp(v->value, "logical")) {
17305                confp->pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_LOGICAL;
17306             } else if (!strcasecmp(v->value, "physical")) {
17307                confp->pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL;
17308             } else {
17309                confp->pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL;
17310             }
17311 #endif
17312          } else if (!strcasecmp(v->name, "discardremoteholdretrieval")) {
17313             confp->pri.discardremoteholdretrieval = ast_true(v->value);
17314 #ifdef HAVE_PRI_INBANDDISCONNECT
17315          } else if (!strcasecmp(v->name, "inbanddisconnect")) {
17316             confp->pri.inbanddisconnect = ast_true(v->value);
17317 #endif
17318          } else if (!strcasecmp(v->name, "pritimer")) {
17319 #ifdef PRI_GETSET_TIMERS
17320             char tmp[20];
17321             char *timerc;
17322             char *c;
17323             int timer;
17324             int timeridx;
17325 
17326             ast_copy_string(tmp, v->value, sizeof(tmp));
17327             c = tmp;
17328             timerc = strsep(&c, ",");
17329             if (!ast_strlen_zero(timerc) && !ast_strlen_zero(c)) {
17330                timeridx = pri_timer2idx(timerc);
17331                timer = atoi(c);
17332                if (timeridx < 0 || PRI_MAX_TIMERS <= timeridx) {
17333                   ast_log(LOG_WARNING,
17334                      "'%s' is not a valid ISDN timer at line %d.\n", timerc,
17335                      v->lineno);
17336                } else if (!timer) {
17337                   ast_log(LOG_WARNING,
17338                      "'%s' is not a valid value for ISDN timer '%s' at line %d.\n",
17339                      c, timerc, v->lineno);
17340                } else {
17341                   pritimers[timeridx] = timer;
17342                }
17343             } else {
17344                ast_log(LOG_WARNING,
17345                   "'%s' is not a valid ISDN timer configuration string at line %d.\n",
17346                   v->value, v->lineno);
17347             }
17348 
17349          } else if (!strcasecmp(v->name, "facilityenable")) {
17350             confp->pri.facilityenable = ast_true(v->value);
17351 #endif /* PRI_GETSET_TIMERS */
17352 #endif /* HAVE_PRI */
17353 #ifdef HAVE_SS7
17354          } else if (!strcasecmp(v->name, "ss7type")) {
17355             if (!strcasecmp(v->value, "itu")) {
17356                cur_ss7type = SS7_ITU;
17357             } else if (!strcasecmp(v->value, "ansi")) {
17358                cur_ss7type = SS7_ANSI;
17359             } else
17360                ast_log(LOG_WARNING, "'%s' is an unknown ss7 switch type at line %d.!\n", v->value, v->lineno);
17361          } else if (!strcasecmp(v->name, "linkset")) {
17362             cur_linkset = atoi(v->value);
17363          } else if (!strcasecmp(v->name, "pointcode")) {
17364             cur_pointcode = parse_pointcode(v->value);
17365          } else if (!strcasecmp(v->name, "adjpointcode")) {
17366             cur_adjpointcode = parse_pointcode(v->value);
17367          } else if (!strcasecmp(v->name, "defaultdpc")) {
17368             cur_defaultdpc = parse_pointcode(v->value);
17369          } else if (!strcasecmp(v->name, "cicbeginswith")) {
17370             cur_cicbeginswith = atoi(v->value);
17371          } else if (!strcasecmp(v->name, "networkindicator")) {
17372             if (!strcasecmp(v->value, "national"))
17373                cur_networkindicator = SS7_NI_NAT;
17374             else if (!strcasecmp(v->value, "national_spare"))
17375                cur_networkindicator = SS7_NI_NAT_SPARE;
17376             else if (!strcasecmp(v->value, "international"))
17377                cur_networkindicator = SS7_NI_INT;
17378             else if (!strcasecmp(v->value, "international_spare"))
17379                cur_networkindicator = SS7_NI_INT_SPARE;
17380             else
17381                cur_networkindicator = -1;
17382          } else if (!strcasecmp(v->name, "ss7_internationalprefix")) {
17383             ast_copy_string(confp->ss7.internationalprefix, v->value, sizeof(confp->ss7.internationalprefix));
17384          } else if (!strcasecmp(v->name, "ss7_nationalprefix")) {
17385             ast_copy_string(confp->ss7.nationalprefix, v->value, sizeof(confp->ss7.nationalprefix));
17386          } else if (!strcasecmp(v->name, "ss7_subscriberprefix")) {
17387             ast_copy_string(confp->ss7.subscriberprefix, v->value, sizeof(confp->ss7.subscriberprefix));
17388          } else if (!strcasecmp(v->name, "ss7_unknownprefix")) {
17389             ast_copy_string(confp->ss7.unknownprefix, v->value, sizeof(confp->ss7.unknownprefix));
17390          } else if (!strcasecmp(v->name, "ss7_called_nai")) {
17391             if (!strcasecmp(v->value, "national")) {
17392                confp->ss7.called_nai = SS7_NAI_NATIONAL;
17393             } else if (!strcasecmp(v->value, "international")) {
17394                confp->ss7.called_nai = SS7_NAI_INTERNATIONAL;
17395             } else if (!strcasecmp(v->value, "subscriber")) {
17396                confp->ss7.called_nai = SS7_NAI_SUBSCRIBER;
17397             } else if (!strcasecmp(v->value, "unknown")) {
17398                confp->ss7.called_nai = SS7_NAI_UNKNOWN;
17399             } else if (!strcasecmp(v->value, "dynamic")) {
17400                confp->ss7.called_nai = SS7_NAI_DYNAMIC;
17401             } else {
17402                ast_log(LOG_WARNING, "Unknown SS7 called_nai '%s' at line %d.\n", v->value, v->lineno);
17403             }
17404          } else if (!strcasecmp(v->name, "ss7_calling_nai")) {
17405             if (!strcasecmp(v->value, "national")) {
17406                confp->ss7.calling_nai = SS7_NAI_NATIONAL;
17407             } else if (!strcasecmp(v->value, "international")) {
17408                confp->ss7.calling_nai = SS7_NAI_INTERNATIONAL;
17409             } else if (!strcasecmp(v->value, "subscriber")) {
17410                confp->ss7.calling_nai = SS7_NAI_SUBSCRIBER;
17411             } else if (!strcasecmp(v->value, "unknown")) {
17412                confp->ss7.calling_nai = SS7_NAI_UNKNOWN;
17413             } else if (!strcasecmp(v->value, "dynamic")) {
17414                confp->ss7.calling_nai = SS7_NAI_DYNAMIC;
17415             } else {
17416                ast_log(LOG_WARNING, "Unknown SS7 calling_nai '%s' at line %d.\n", v->value, v->lineno);
17417             }
17418          } else if (!strcasecmp(v->name, "sigchan")) {
17419             int sigchan, res;
17420             sigchan = atoi(v->value);
17421             res = linkset_addsigchan(sigchan);
17422             if (res < 0)
17423                return -1;
17424 
17425          } else if (!strcasecmp(v->name, "ss7_explicitacm")) {
17426             struct dahdi_ss7 *link;
17427             link = ss7_resolve_linkset(cur_linkset);
17428             if (!link) {
17429                ast_log(LOG_ERROR, "Invalid linkset number.  Must be between 1 and %d\n", NUM_SPANS + 1);
17430                return -1;
17431             }
17432             if (ast_true(v->value))
17433                link->flags |= LINKSET_FLAG_EXPLICITACM;
17434 #endif /* HAVE_SS7 */
17435 #ifdef HAVE_OPENR2
17436          } else if (!strcasecmp(v->name, "mfcr2_advanced_protocol_file")) {
17437             ast_copy_string(confp->mfcr2.r2proto_file, v->value, sizeof(confp->mfcr2.r2proto_file));
17438             ast_log(LOG_WARNING, "MFC/R2 Protocol file '%s' will be used, you only should use this if you *REALLY KNOW WHAT YOU ARE DOING*.\n", confp->mfcr2.r2proto_file);
17439          } else if (!strcasecmp(v->name, "mfcr2_logdir")) {
17440             ast_copy_string(confp->mfcr2.logdir, v->value, sizeof(confp->mfcr2.logdir));
17441          } else if (!strcasecmp(v->name, "mfcr2_variant")) {
17442             confp->mfcr2.variant = openr2_proto_get_variant(v->value);
17443             if (OR2_VAR_UNKNOWN == confp->mfcr2.variant) {
17444                ast_log(LOG_WARNING, "Unknown MFC/R2 variant '%s' at line %d, defaulting to ITU.\n", v->value, v->lineno);
17445                confp->mfcr2.variant = OR2_VAR_ITU;
17446             }
17447          } else if (!strcasecmp(v->name, "mfcr2_mfback_timeout")) {
17448             confp->mfcr2.mfback_timeout = atoi(v->value);
17449             if (!confp->mfcr2.mfback_timeout) {
17450                ast_log(LOG_WARNING, "MF timeout of 0? hum, I will protect you from your ignorance. Setting default.\n");
17451                confp->mfcr2.mfback_timeout = -1;
17452             } else if (confp->mfcr2.mfback_timeout > 0 && confp->mfcr2.mfback_timeout < 500) {
17453                ast_log(LOG_WARNING, "MF timeout less than 500ms is not recommended, you have been warned!\n");
17454             }
17455          } else if (!strcasecmp(v->name, "mfcr2_metering_pulse_timeout")) {
17456             confp->mfcr2.metering_pulse_timeout = atoi(v->value);
17457             if (confp->mfcr2.metering_pulse_timeout > 500) {
17458                ast_log(LOG_WARNING, "Metering pulse timeout greater than 500ms is not recommended, you have been warned!\n");
17459             }
17460          } else if (!strcasecmp(v->name, "mfcr2_get_ani_first")) {
17461             confp->mfcr2.get_ani_first = ast_true(v->value) ? 1 : 0;
17462          } else if (!strcasecmp(v->name, "mfcr2_double_answer")) {
17463             confp->mfcr2.double_answer = ast_true(v->value) ? 1 : 0;
17464          } else if (!strcasecmp(v->name, "mfcr2_charge_calls")) {
17465             confp->mfcr2.charge_calls = ast_true(v->value) ? 1 : 0;
17466          } else if (!strcasecmp(v->name, "mfcr2_accept_on_offer")) {
17467             confp->mfcr2.accept_on_offer = ast_true(v->value) ? 1 : 0;
17468          } else if (!strcasecmp(v->name, "mfcr2_allow_collect_calls")) {
17469             confp->mfcr2.allow_collect_calls = ast_true(v->value) ? 1 : 0;
17470          } else if (!strcasecmp(v->name, "mfcr2_forced_release")) {
17471             confp->mfcr2.forced_release = ast_true(v->value) ? 1 : 0;
17472          } else if (!strcasecmp(v->name, "mfcr2_immediate_accept")) {
17473             confp->mfcr2.immediate_accept = ast_true(v->value) ? 1 : 0;
17474 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
17475          } else if (!strcasecmp(v->name, "mfcr2_skip_category")) {
17476             confp->mfcr2.skip_category_request = ast_true(v->value) ? 1 : 0;
17477 #endif
17478          } else if (!strcasecmp(v->name, "mfcr2_call_files")) {
17479             confp->mfcr2.call_files = ast_true(v->value) ? 1 : 0;
17480          } else if (!strcasecmp(v->name, "mfcr2_max_ani")) {
17481             confp->mfcr2.max_ani = atoi(v->value);
17482             if (confp->mfcr2.max_ani >= AST_MAX_EXTENSION){
17483                confp->mfcr2.max_ani = AST_MAX_EXTENSION - 1;
17484             }
17485          } else if (!strcasecmp(v->name, "mfcr2_max_dnis")) {
17486             confp->mfcr2.max_dnis = atoi(v->value);
17487             if (confp->mfcr2.max_dnis >= AST_MAX_EXTENSION){
17488                confp->mfcr2.max_dnis = AST_MAX_EXTENSION - 1;
17489             }
17490          } else if (!strcasecmp(v->name, "mfcr2_category")) {
17491             confp->mfcr2.category = openr2_proto_get_category(v->value);
17492             if (OR2_CALLING_PARTY_CATEGORY_UNKNOWN == confp->mfcr2.category) {
17493                confp->mfcr2.category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER;
17494                ast_log(LOG_WARNING, "Invalid MFC/R2 caller category '%s' at line %d. Using national subscriber as default.\n",
17495                      v->value, v->lineno);
17496             }
17497          } else if (!strcasecmp(v->name, "mfcr2_logging")) {
17498             openr2_log_level_t tmplevel;
17499             char *clevel;
17500             char *logval = ast_strdupa(v->value);
17501             while (logval) {
17502                clevel = strsep(&logval,",");
17503                if (-1 == (tmplevel = openr2_log_get_level(clevel))) {
17504                   ast_log(LOG_WARNING, "Ignoring invalid logging level: '%s' at line %d.\n", clevel, v->lineno);
17505                   continue;
17506                }
17507                confp->mfcr2.loglevel |= tmplevel;
17508             }
17509 #endif /* HAVE_OPENR2 */
17510          } else if (!strcasecmp(v->name, "cadence")) {
17511             /* setup to scan our argument */
17512             int element_count, c[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
17513             int i;
17514             struct dahdi_ring_cadence new_cadence;
17515             int cid_location = -1;
17516             int firstcadencepos = 0;
17517             char original_args[80];
17518             int cadence_is_ok = 1;
17519 
17520             ast_copy_string(original_args, v->value, sizeof(original_args));
17521             /* 16 cadences allowed (8 pairs) */
17522             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]);
17523 
17524             /* Cadence must be even (on/off) */
17525             if (element_count % 2 == 1) {
17526                ast_log(LOG_ERROR, "Must be a silence duration for each ring duration: %s at line %d.\n", original_args, v->lineno);
17527                cadence_is_ok = 0;
17528             }
17529 
17530             /* Ring cadences cannot be negative */
17531             for (i = 0; i < element_count; i++) {
17532                if (c[i] == 0) {
17533                   ast_log(LOG_ERROR, "Ring or silence duration cannot be zero: %s at line %d.\n", original_args, v->lineno);
17534                   cadence_is_ok = 0;
17535                   break;
17536                } else if (c[i] < 0) {
17537                   if (i % 2 == 1) {
17538                      /* Silence duration, negative possibly okay */
17539                      if (cid_location == -1) {
17540                         cid_location = i;
17541                         c[i] *= -1;
17542                      } else {
17543                         ast_log(LOG_ERROR, "CID location specified twice: %s at line %d.\n", original_args, v->lineno);
17544                         cadence_is_ok = 0;
17545                         break;
17546                      }
17547                   } else {
17548                      if (firstcadencepos == 0) {
17549                         firstcadencepos = i; /* only recorded to avoid duplicate specification */
17550                                  /* duration will be passed negative to the DAHDI driver */
17551                      } else {
17552                          ast_log(LOG_ERROR, "First cadence position specified twice: %s at line %d.\n", original_args, v->lineno);
17553                         cadence_is_ok = 0;
17554                         break;
17555                      }
17556                   }
17557                }
17558             }
17559 
17560             /* Substitute our scanned cadence */
17561             for (i = 0; i < 16; i++) {
17562                new_cadence.ringcadence[i] = c[i];
17563             }
17564 
17565             if (cadence_is_ok) {
17566                /* ---we scanned it without getting annoyed; now some sanity checks--- */
17567                if (element_count < 2) {
17568                   ast_log(LOG_ERROR, "Minimum cadence is ring,pause: %s at line %d.\n", original_args, v->lineno);
17569                } else {
17570                   if (cid_location == -1) {
17571                      /* user didn't say; default to first pause */
17572                      cid_location = 1;
17573                   } else {
17574                      /* convert element_index to cidrings value */
17575                      cid_location = (cid_location + 1) / 2;
17576                   }
17577                   /* ---we like their cadence; try to install it--- */
17578                   if (!user_has_defined_cadences++)
17579                      /* this is the first user-defined cadence; clear the default user cadences */
17580                      num_cadence = 0;
17581                   if ((num_cadence+1) >= NUM_CADENCE_MAX)
17582                      ast_log(LOG_ERROR, "Already %d cadences; can't add another: %s at line %d.\n", NUM_CADENCE_MAX, original_args, v->lineno);
17583                   else {
17584                      cadences[num_cadence] = new_cadence;
17585                      cidrings[num_cadence++] = cid_location;
17586                      ast_verb(3, "cadence 'r%d' added: %s\n",num_cadence,original_args);
17587                   }
17588                }
17589             }
17590          } else if (!strcasecmp(v->name, "ringtimeout")) {
17591             ringt_base = (atoi(v->value) * 8) / READ_SIZE;
17592          } else if (!strcasecmp(v->name, "prewink")) {
17593             confp->timing.prewinktime = atoi(v->value);
17594          } else if (!strcasecmp(v->name, "preflash")) {
17595             confp->timing.preflashtime = atoi(v->value);
17596          } else if (!strcasecmp(v->name, "wink")) {
17597             confp->timing.winktime = atoi(v->value);
17598          } else if (!strcasecmp(v->name, "flash")) {
17599             confp->timing.flashtime = atoi(v->value);
17600          } else if (!strcasecmp(v->name, "start")) {
17601             confp->timing.starttime = atoi(v->value);
17602          } else if (!strcasecmp(v->name, "rxwink")) {
17603             confp->timing.rxwinktime = atoi(v->value);
17604          } else if (!strcasecmp(v->name, "rxflash")) {
17605             confp->timing.rxflashtime = atoi(v->value);
17606          } else if (!strcasecmp(v->name, "debounce")) {
17607             confp->timing.debouncetime = atoi(v->value);
17608          } else if (!strcasecmp(v->name, "toneduration")) {
17609             int toneduration;
17610             int ctlfd;
17611             int res;
17612             struct dahdi_dialparams dps;
17613 
17614             ctlfd = open("/dev/dahdi/ctl", O_RDWR);
17615             if (ctlfd == -1) {
17616                ast_log(LOG_ERROR, "Unable to open /dev/dahdi/ctl to set toneduration at line %d.\n", v->lineno);
17617                return -1;
17618             }
17619 
17620             toneduration = atoi(v->value);
17621             if (toneduration > -1) {
17622                memset(&dps, 0, sizeof(dps));
17623 
17624                dps.dtmf_tonelen = dps.mfv1_tonelen = toneduration;
17625                res = ioctl(ctlfd, DAHDI_SET_DIALPARAMS, &dps);
17626                if (res < 0) {
17627                   ast_log(LOG_ERROR, "Invalid tone duration: %d ms at line %d: %s\n", toneduration, v->lineno, strerror(errno));
17628                   close(ctlfd);
17629                   return -1;
17630                }
17631             }
17632             close(ctlfd);
17633          } else if (!strcasecmp(v->name, "defaultcic")) {
17634             ast_copy_string(defaultcic, v->value, sizeof(defaultcic));
17635          } else if (!strcasecmp(v->name, "defaultozz")) {
17636             ast_copy_string(defaultozz, v->value, sizeof(defaultozz));
17637          } else if (!strcasecmp(v->name, "mwilevel")) {
17638             mwilevel = atoi(v->value);
17639          }
17640       } else if (!(options & PROC_DAHDI_OPT_NOWARN) )
17641          ast_log(LOG_WARNING, "Ignoring any changes to '%s' (on reload) at line %d.\n", v->name, v->lineno);
17642    }
17643    if (dahdichan[0]) {
17644       /* The user has set 'dahdichan' */
17645       /*< \todo pass proper line number instead of 0 */
17646       if (build_channels(confp, 0, dahdichan, reload, 0, &found_pseudo)) {
17647          return -1;
17648       }
17649    }
17650    /*< \todo why check for the pseudo in the per-channel section.
17651     * Any actual use for manual setup of the pseudo channel? */
17652    if (!found_pseudo && reload != 1) {
17653       /* use the default configuration for a channel, so
17654          that any settings from real configured channels
17655          don't "leak" into the pseudo channel config
17656       */
17657       struct dahdi_chan_conf conf = dahdi_chan_conf_default();
17658 
17659       tmp = mkintf(CHAN_PSEUDO, &conf, NULL, reload);
17660 
17661       if (tmp) {
17662          ast_verb(3, "Automatically generated pseudo channel\n");
17663       } else {
17664          ast_log(LOG_WARNING, "Unable to register pseudo channel!\n");
17665       }
17666    }
17667    return 0;
17668 }
17669 
17670 static int setup_dahdi(int reload)
17671 {
17672    struct ast_config *cfg, *ucfg;
17673    struct ast_variable *v;
17674    struct dahdi_chan_conf base_conf = dahdi_chan_conf_default();
17675    struct dahdi_chan_conf conf;
17676    struct ast_flags config_flags = { reload == 1 ? CONFIG_FLAG_FILEUNCHANGED : 0 };
17677    const char *cat;
17678    int res;
17679 
17680 #ifdef HAVE_PRI
17681    char *c;
17682    int spanno;
17683    int i;
17684    int logicalspan;
17685    int trunkgroup;
17686    int dchannels[NUM_DCHANS];
17687 #endif
17688 
17689    cfg = ast_config_load(config, config_flags);
17690 
17691    /* Error if we have no config file */
17692    if (!cfg) {
17693       ast_log(LOG_ERROR, "Unable to load config %s\n", config);
17694       return 0;
17695    } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
17696       ucfg = ast_config_load("users.conf", config_flags);
17697       if (ucfg == CONFIG_STATUS_FILEUNCHANGED) {
17698          return 0;
17699       } else if (ucfg == CONFIG_STATUS_FILEINVALID) {
17700          ast_log(LOG_ERROR, "File users.conf cannot be parsed.  Aborting.\n");
17701          return 0;
17702       }
17703       ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
17704       if ((cfg = ast_config_load(config, config_flags)) == CONFIG_STATUS_FILEINVALID) {
17705          ast_log(LOG_ERROR, "File %s cannot be parsed.  Aborting.\n", config);
17706          ast_config_destroy(ucfg);
17707          return 0;
17708       }
17709    } else if (cfg == CONFIG_STATUS_FILEINVALID) {
17710       ast_log(LOG_ERROR, "File %s cannot be parsed.  Aborting.\n", config);
17711       return 0;
17712    } else {
17713       ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
17714       if ((ucfg = ast_config_load("users.conf", config_flags)) == CONFIG_STATUS_FILEINVALID) {
17715          ast_log(LOG_ERROR, "File users.conf cannot be parsed.  Aborting.\n");
17716          ast_config_destroy(cfg);
17717          return 0;
17718       }
17719    }
17720 
17721    /* It's a little silly to lock it, but we mind as well just to be sure */
17722    ast_mutex_lock(&iflock);
17723 #ifdef HAVE_PRI
17724    if (reload != 1) {
17725       /* Process trunkgroups first */
17726       v = ast_variable_browse(cfg, "trunkgroups");
17727       while (v) {
17728          if (!strcasecmp(v->name, "trunkgroup")) {
17729             trunkgroup = atoi(v->value);
17730             if (trunkgroup > 0) {
17731                if ((c = strchr(v->value, ','))) {
17732                   i = 0;
17733                   memset(dchannels, 0, sizeof(dchannels));
17734                   while (c && (i < NUM_DCHANS)) {
17735                      dchannels[i] = atoi(c + 1);
17736                      if (dchannels[i] < 0) {
17737                         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);
17738                      } else
17739                         i++;
17740                      c = strchr(c + 1, ',');
17741                   }
17742                   if (i) {
17743                      if (pri_create_trunkgroup(trunkgroup, dchannels)) {
17744                         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);
17745                   } else
17746                         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");
17747                   } else
17748                      ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
17749                } else
17750                   ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
17751             } else
17752                ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of chan_dahdi.conf\n", v->lineno);
17753          } else if (!strcasecmp(v->name, "spanmap")) {
17754             spanno = atoi(v->value);
17755             if (spanno > 0) {
17756                if ((c = strchr(v->value, ','))) {
17757                   trunkgroup = atoi(c + 1);
17758                   if (trunkgroup > 0) {
17759                      if ((c = strchr(c + 1, ',')))
17760                         logicalspan = atoi(c + 1);
17761                      else
17762                         logicalspan = 0;
17763                      if (logicalspan >= 0) {
17764                         if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) {
17765                            ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
17766                      } else
17767                            ast_verb(2, "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
17768                      } else
17769                         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);
17770                   } else
17771                      ast_log(LOG_WARNING, "Trunk group must be a postive number at line %d of chan_dahdi.conf\n", v->lineno);
17772                } else
17773                   ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of chan_dahdi.conf\n", v->lineno);
17774             } else
17775                ast_log(LOG_WARNING, "Span number must be a postive integer at line %d of chan_dahdi.conf\n", v->lineno);
17776          } else {
17777             ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name);
17778          }
17779          v = v->next;
17780       }
17781    }
17782 #endif
17783 
17784    /* Copy the default jb config over global_jbconf */
17785    memcpy(&global_jbconf, &default_jbconf, sizeof(global_jbconf));
17786 
17787    mwimonitornotify[0] = '\0';
17788 
17789    v = ast_variable_browse(cfg, "channels");
17790    if ((res = process_dahdi(&base_conf, "", v, reload, 0))) {
17791       ast_mutex_unlock(&iflock);
17792       ast_config_destroy(cfg);
17793       if (ucfg) {
17794          ast_config_destroy(ucfg);
17795       }
17796       return res;
17797    }
17798 
17799    /* Now get configuration from all normal sections in chan_dahdi.conf: */
17800    for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) {
17801       /* [channels] and [trunkgroups] are used. Let's also reserve
17802        * [globals] and [general] for future use
17803        */
17804       if (!strcasecmp(cat, "general") ||
17805          !strcasecmp(cat, "trunkgroups") ||
17806          !strcasecmp(cat, "globals") ||
17807          !strcasecmp(cat, "channels")) {
17808          continue;
17809       }
17810 
17811       memcpy(&conf, &base_conf, sizeof(conf));
17812 
17813       if ((res = process_dahdi(&conf, cat, ast_variable_browse(cfg, cat), reload, PROC_DAHDI_OPT_NOCHAN))) {
17814          ast_mutex_unlock(&iflock);
17815          ast_config_destroy(cfg);
17816          if (ucfg) {
17817             ast_config_destroy(ucfg);
17818          }
17819          return res;
17820       }
17821    }
17822 
17823    ast_config_destroy(cfg);
17824 
17825    if (ucfg) {
17826       const char *chans;
17827 
17828       /* Reset conf back to defaults, so values from chan_dahdi.conf don't leak in. */
17829       base_conf = dahdi_chan_conf_default();
17830       process_dahdi(&base_conf, "", ast_variable_browse(ucfg, "general"), 1, 0);
17831 
17832       for (cat = ast_category_browse(ucfg, NULL); cat ; cat = ast_category_browse(ucfg, cat)) {
17833          if (!strcasecmp(cat, "general")) {
17834             continue;
17835          }
17836 
17837          chans = ast_variable_retrieve(ucfg, cat, "dahdichan");
17838 
17839          if (ast_strlen_zero(chans)) {
17840             continue;
17841          }
17842 
17843          memcpy(&conf, &base_conf, sizeof(conf));
17844 
17845          if ((res = process_dahdi(&conf, cat, ast_variable_browse(ucfg, cat), reload, PROC_DAHDI_OPT_NOCHAN | PROC_DAHDI_OPT_NOWARN))) {
17846             ast_config_destroy(ucfg);
17847             ast_mutex_unlock(&iflock);
17848             return res;
17849          }
17850       }
17851       ast_config_destroy(ucfg);
17852    }
17853    ast_mutex_unlock(&iflock);
17854 
17855 #ifdef HAVE_PRI
17856    if (reload != 1) {
17857       int x;
17858       for (x = 0; x < NUM_SPANS; x++) {
17859          if (pris[x].pvts[0]) {
17860             if (start_pri(pris + x)) {
17861                ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1);
17862                return -1;
17863             } else
17864                ast_verb(2, "Starting D-Channel on span %d\n", x + 1);
17865          }
17866       }
17867    }
17868 #endif
17869 #ifdef HAVE_SS7
17870    if (reload != 1) {
17871       int x;
17872       for (x = 0; x < NUM_SPANS; x++) {
17873          if (linksets[x].ss7) {
17874             if (ast_pthread_create(&linksets[x].master, NULL, ss7_linkset, &linksets[x])) {
17875                ast_log(LOG_ERROR, "Unable to start SS7 linkset on span %d\n", x + 1);
17876                return -1;
17877             } else
17878                ast_verb(2, "Starting SS7 linkset on span %d\n", x + 1);
17879          }
17880       }
17881    }
17882 #endif
17883 #ifdef HAVE_OPENR2
17884    if (reload != 1) {
17885       int x;
17886       for (x = 0; x < r2links_count; x++) {
17887          if (ast_pthread_create(&r2links[x]->r2master, NULL, mfcr2_monitor, r2links[x])) {
17888             ast_log(LOG_ERROR, "Unable to start R2 monitor on channel group %d\n", x + 1);
17889             return -1;
17890          } else {
17891             ast_verb(2, "Starting R2 monitor on channel group %d\n", x + 1);
17892          }
17893       }
17894    }
17895 #endif
17896    /* And start the monitor for the first time */
17897    restart_monitor();
17898    return 0;
17899 }
17900 
17901 static int load_module(void)
17902 {
17903    int res;
17904 #if defined(HAVE_PRI) || defined(HAVE_SS7)
17905    int y, i;
17906 #endif
17907 
17908 #ifdef HAVE_PRI
17909    memset(pris, 0, sizeof(pris));
17910    for (y = 0; y < NUM_SPANS; y++) {
17911       ast_mutex_init(&pris[y].lock);
17912       pris[y].offset = -1;
17913       pris[y].master = AST_PTHREADT_NULL;
17914       for (i = 0; i < NUM_DCHANS; i++)
17915          pris[y].fds[i] = -1;
17916    }
17917    pri_set_error(dahdi_pri_error);
17918    pri_set_message(dahdi_pri_message);
17919    ast_register_application_xml(dahdi_send_keypad_facility_app, dahdi_send_keypad_facility_exec);
17920 #ifdef HAVE_PRI_PROG_W_CAUSE
17921    ast_register_application_xml(dahdi_send_callrerouting_facility_app, dahdi_send_callrerouting_facility_exec);
17922 #endif
17923 #endif
17924 #ifdef HAVE_SS7
17925    memset(linksets, 0, sizeof(linksets));
17926    for (y = 0; y < NUM_SPANS; y++) {
17927       ast_mutex_init(&linksets[y].lock);
17928       linksets[y].master = AST_PTHREADT_NULL;
17929       for (i = 0; i < NUM_DCHANS; i++)
17930          linksets[y].fds[i] = -1;
17931    }
17932    ss7_set_error(dahdi_ss7_error);
17933    ss7_set_message(dahdi_ss7_message);
17934 #endif /* HAVE_SS7 */
17935    res = setup_dahdi(0);
17936    /* Make sure we can register our DAHDI channel type */
17937    if (res)
17938       return AST_MODULE_LOAD_DECLINE;
17939    if (ast_channel_register(&dahdi_tech)) {
17940       ast_log(LOG_ERROR, "Unable to register channel class 'DAHDI'\n");
17941       __unload_module();
17942       return AST_MODULE_LOAD_FAILURE;
17943    }
17944 #ifdef HAVE_PRI
17945    ast_string_field_init(&inuse, 16);
17946    ast_string_field_set(&inuse, name, "GR-303InUse");
17947    ast_cli_register_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
17948 #endif
17949 #ifdef HAVE_SS7
17950    ast_cli_register_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
17951 #endif
17952 #ifdef HAVE_OPENR2
17953    ast_cli_register_multiple(dahdi_mfcr2_cli, sizeof(dahdi_mfcr2_cli)/sizeof(dahdi_mfcr2_cli[0]));
17954    ast_register_application_xml(dahdi_accept_r2_call_app, dahdi_accept_r2_call_exec);
17955 #endif
17956 
17957    ast_cli_register_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli));
17958 
17959    memset(round_robin, 0, sizeof(round_robin));
17960    ast_manager_register( "DAHDITransfer", 0, action_transfer, "Transfer DAHDI Channel" );
17961    ast_manager_register( "DAHDIHangup", 0, action_transferhangup, "Hangup DAHDI Channel" );
17962    ast_manager_register( "DAHDIDialOffhook", 0, action_dahdidialoffhook, "Dial over DAHDI channel while offhook" );
17963    ast_manager_register( "DAHDIDNDon", 0, action_dahdidndon, "Toggle DAHDI channel Do Not Disturb status ON" );
17964    ast_manager_register( "DAHDIDNDoff", 0, action_dahdidndoff, "Toggle DAHDI channel Do Not Disturb status OFF" );
17965    ast_manager_register("DAHDIShowChannels", 0, action_dahdishowchannels, "Show status DAHDI channels");
17966    ast_manager_register("DAHDIRestart", 0, action_dahdirestart, "Fully Restart DAHDI channels (terminates calls)");
17967 
17968    ast_cond_init(&ss_thread_complete, NULL);
17969 
17970    return res;
17971 }
17972 
17973 static int dahdi_sendtext(struct ast_channel *c, const char *text)
17974 {
17975 #define  END_SILENCE_LEN 400
17976 #define  HEADER_MS 50
17977 #define  TRAILER_MS 5
17978 #define  HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8)
17979 #define  ASCII_BYTES_PER_CHAR 80
17980 
17981    unsigned char *buf,*mybuf;
17982    struct dahdi_pvt *p = c->tech_pvt;
17983    struct pollfd fds[1];
17984    int size,res,fd,len,x;
17985    int bytes=0;
17986    /* Initial carrier (imaginary) */
17987    float cr = 1.0;
17988    float ci = 0.0;
17989    float scont = 0.0;
17990    int idx;
17991 
17992    idx = dahdi_get_index(c, p, 0);
17993    if (idx < 0) {
17994       ast_log(LOG_WARNING, "Huh?  I don't exist?\n");
17995       return -1;
17996    }
17997    if (!text[0]) return(0); /* if nothing to send, dont */
17998    if ((!p->tdd) && (!p->mate)) return(0);  /* if not in TDD mode, just return */
17999    if (p->mate)
18000       buf = ast_malloc(((strlen(text) + 1) * ASCII_BYTES_PER_CHAR) + END_SILENCE_LEN + HEADER_LEN);
18001    else
18002       buf = ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN);
18003    if (!buf)
18004       return -1;
18005    mybuf = buf;
18006    if (p->mate) {
18007       int codec = AST_LAW(p);
18008       for (x = 0; x < HEADER_MS; x++) {   /* 50 ms of Mark */
18009          PUT_CLID_MARKMS;
18010       }
18011       /* Put actual message */
18012       for (x = 0; text[x]; x++) {
18013          PUT_CLID(text[x]);
18014       }
18015       for (x = 0; x < TRAILER_MS; x++) {  /* 5 ms of Mark */
18016          PUT_CLID_MARKMS;
18017       }
18018       len = bytes;
18019       buf = mybuf;
18020    } else {
18021       len = tdd_generate(p->tdd, buf, text);
18022       if (len < 1) {
18023          ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text));
18024          ast_free(mybuf);
18025          return -1;
18026       }
18027    }
18028    memset(buf + len, 0x7f, END_SILENCE_LEN);
18029    len += END_SILENCE_LEN;
18030    fd = p->subs[idx].dfd;
18031    while (len) {
18032       if (ast_check_hangup(c)) {
18033          ast_free(mybuf);
18034          return -1;
18035       }
18036       size = len;
18037       if (size > READ_SIZE)
18038          size = READ_SIZE;
18039       fds[0].fd = fd;
18040       fds[0].events = POLLOUT | POLLPRI;
18041       fds[0].revents = 0;
18042       res = poll(fds, 1, -1);
18043       if (!res) {
18044          ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
18045          continue;
18046       }
18047       /* if got exception */
18048       if (fds[0].revents & POLLPRI) {
18049          ast_free(mybuf);
18050          return -1;
18051       }
18052       if (!(fds[0].revents & POLLOUT)) {
18053          ast_debug(1, "write fd not ready on channel %d\n", p->channel);
18054          continue;
18055       }
18056       res = write(fd, buf, size);
18057       if (res != size) {
18058          if (res == -1) {
18059             ast_free(mybuf);
18060             return -1;
18061          }
18062          ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
18063          break;
18064       }
18065       len -= size;
18066       buf += size;
18067    }
18068    ast_free(mybuf);
18069    return(0);
18070 }
18071 
18072 
18073 static int reload(void)
18074 {
18075    int res = 0;
18076 
18077    res = setup_dahdi(1);
18078    if (res) {
18079       ast_log(LOG_WARNING, "Reload of chan_dahdi.so is unsuccessful!\n");
18080       return -1;
18081    }
18082    return 0;
18083 }
18084 
18085 /* This is a workaround so that menuselect displays a proper description
18086  * AST_MODULE_INFO(, , "DAHDI Telephony"
18087  */
18088 
18089 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, tdesc,
18090    .load = load_module,
18091    .unload = unload_module,
18092    .reload = reload,
18093    );