Fri Jul 15 2011 11:57:24

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: 313435 $")
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  * Define to make always pick a channel if allowed.  Useful for
00189  * testing channel shifting.
00190  */
00191 //#define ALWAYS_PICK_CHANNEL 1
00192 
00193 /*!
00194  * Define to force a RESTART on a channel that returns a cause
00195  * code of PRI_CAUSE_REQUESTED_CHAN_UNAVAIL(44).  If the cause
00196  * is because of a stuck channel on the peer and the channel is
00197  * always the next channel we pick for an outgoing call then
00198  * this can help.
00199  */
00200 #define FORCE_RESTART_UNAVAIL_CHANS    1
00201 
00202 /*!
00203  * \note Define ZHONE_HACK to cause us to go off hook and then back on hook when
00204  * the user hangs up to reset the state machine so ring works properly.
00205  * This is used to be able to support kewlstart by putting the zhone in
00206  * groundstart mode since their forward disconnect supervision is entirely
00207  * broken even though their documentation says it isn't and their support
00208  * is entirely unwilling to provide any assistance with their channel banks
00209  * even though their web site says they support their products for life.
00210  */
00211 /* #define ZHONE_HACK */
00212 
00213 /*! \note
00214  * Define if you want to check the hook state for an FXO (FXS signalled) interface
00215  * before dialing on it.  Certain FXO interfaces always think they're out of
00216  * service with this method however.
00217  */
00218 /* #define DAHDI_CHECK_HOOKSTATE */
00219 
00220 /*! \brief Typically, how many rings before we should send Caller*ID */
00221 #define DEFAULT_CIDRINGS 1
00222 
00223 #define AST_LAW(p) (((p)->law == DAHDI_LAW_ALAW) ? AST_FORMAT_ALAW : AST_FORMAT_ULAW)
00224 
00225 
00226 /*! \brief Signaling types that need to use MF detection should be placed in this macro */
00227 #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))
00228 
00229 static const char tdesc[] = "DAHDI Telephony Driver"
00230 #if defined(HAVE_PRI) || defined(HAVE_SS7) || defined(HAVE_OPENR2)
00231    " w/"
00232 #endif
00233 #ifdef HAVE_PRI
00234    "PRI"
00235 #endif
00236 #ifdef HAVE_SS7
00237    #ifdef HAVE_PRI
00238    " & SS7"
00239    #else
00240    "SS7"
00241    #endif
00242 #endif
00243 #ifdef HAVE_OPENR2
00244    #if defined(HAVE_PRI) || defined(HAVE_SS7)
00245    " & MFC/R2"
00246    #else
00247    "MFC/R2"
00248    #endif
00249 #endif
00250 ;
00251 
00252 static const char config[] = "chan_dahdi.conf";
00253 
00254 #define SIG_EM    DAHDI_SIG_EM
00255 #define SIG_EMWINK   (0x0100000 | DAHDI_SIG_EM)
00256 #define SIG_FEATD (0x0200000 | DAHDI_SIG_EM)
00257 #define  SIG_FEATDMF (0x0400000 | DAHDI_SIG_EM)
00258 #define  SIG_FEATB   (0x0800000 | DAHDI_SIG_EM)
00259 #define  SIG_E911 (0x1000000 | DAHDI_SIG_EM)
00260 #define  SIG_FEATDMF_TA (0x2000000 | DAHDI_SIG_EM)
00261 #define  SIG_FGC_CAMA   (0x4000000 | DAHDI_SIG_EM)
00262 #define  SIG_FGC_CAMAMF (0x8000000 | DAHDI_SIG_EM)
00263 #define SIG_FXSLS DAHDI_SIG_FXSLS
00264 #define SIG_FXSGS DAHDI_SIG_FXSGS
00265 #define SIG_FXSKS DAHDI_SIG_FXSKS
00266 #define SIG_FXOLS DAHDI_SIG_FXOLS
00267 #define SIG_FXOGS DAHDI_SIG_FXOGS
00268 #define SIG_FXOKS DAHDI_SIG_FXOKS
00269 #define SIG_PRI      DAHDI_SIG_CLEAR
00270 #define SIG_BRI      (0x2000000 | DAHDI_SIG_CLEAR)
00271 #define SIG_BRI_PTMP (0X4000000 | DAHDI_SIG_CLEAR)
00272 #define SIG_SS7      (0x1000000 | DAHDI_SIG_CLEAR)
00273 #define SIG_MFCR2    DAHDI_SIG_CAS
00274 #define  SIG_SF      DAHDI_SIG_SF
00275 #define SIG_SFWINK   (0x0100000 | DAHDI_SIG_SF)
00276 #define SIG_SF_FEATD (0x0200000 | DAHDI_SIG_SF)
00277 #define  SIG_SF_FEATDMF (0x0400000 | DAHDI_SIG_SF)
00278 #define  SIG_SF_FEATB   (0x0800000 | DAHDI_SIG_SF)
00279 #define SIG_EM_E1 DAHDI_SIG_EM_E1
00280 #define SIG_GR303FXOKS  (0x0100000 | DAHDI_SIG_FXOKS)
00281 #define SIG_GR303FXSKS  (0x0100000 | DAHDI_SIG_FXSKS)
00282 
00283 #ifdef LOTS_OF_SPANS
00284 #define NUM_SPANS DAHDI_MAX_SPANS
00285 #else
00286 #define NUM_SPANS       32
00287 #endif
00288 #define NUM_DCHANS      4  /*!< No more than 4 d-channels */
00289 #define MAX_CHANNELS 672      /*!< No more than a DS3 per trunk group */
00290 
00291 #define CHAN_PSEUDO  -2
00292 
00293 #define DCHAN_PROVISIONED (1 << 0)
00294 #define DCHAN_NOTINALARM  (1 << 1)
00295 #define DCHAN_UP          (1 << 2)
00296 
00297 #define DCHAN_AVAILABLE (DCHAN_PROVISIONED | DCHAN_NOTINALARM | DCHAN_UP)
00298 
00299 /* Overlap dialing option types */
00300 #define DAHDI_OVERLAPDIAL_NONE 0
00301 #define DAHDI_OVERLAPDIAL_OUTGOING 1
00302 #define DAHDI_OVERLAPDIAL_INCOMING 2
00303 #define DAHDI_OVERLAPDIAL_BOTH (DAHDI_OVERLAPDIAL_INCOMING|DAHDI_OVERLAPDIAL_OUTGOING)
00304 
00305 #define CALLPROGRESS_PROGRESS    1
00306 #define CALLPROGRESS_FAX_OUTGOING   2
00307 #define CALLPROGRESS_FAX_INCOMING   4
00308 #define CALLPROGRESS_FAX      (CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING)
00309 
00310 static char defaultcic[64] = "";
00311 static char defaultozz[64] = "";
00312 
00313 static char parkinglot[AST_MAX_EXTENSION] = "";    /*!< Default parking lot for this channel */
00314 
00315 /*! Run this script when the MWI state changes on an FXO line, if mwimonitor is enabled */
00316 static char mwimonitornotify[PATH_MAX] = "";
00317 #ifndef HAVE_DAHDI_LINEREVERSE_VMWI
00318 static int  mwisend_rpas = 0;
00319 #endif
00320 
00321 static char progzone[10] = "";
00322 
00323 static int usedistinctiveringdetection = 0;
00324 static int distinctiveringaftercid = 0;
00325 
00326 static int numbufs = 4;
00327 
00328 static int mwilevel = 512;
00329 
00330 #ifdef HAVE_PRI
00331 static struct ast_channel inuse;
00332 #ifdef PRI_GETSET_TIMERS
00333 static int pritimers[PRI_MAX_TIMERS];
00334 #endif
00335 static int pridebugfd = -1;
00336 static char pridebugfilename[1024] = "";
00337 #endif
00338 
00339 /*! \brief Wait up to 16 seconds for first digit (FXO logic) */
00340 static int firstdigittimeout = 16000;
00341 
00342 /*! \brief How long to wait for following digits (FXO logic) */
00343 static int gendigittimeout = 8000;
00344 
00345 /*! \brief How long to wait for an extra digit, if there is an ambiguous match */
00346 static int matchdigittimeout = 3000;
00347 
00348 /*! \brief Protect the interface list (of dahdi_pvt's) */
00349 AST_MUTEX_DEFINE_STATIC(iflock);
00350 
00351 /* QSIG channel mapping option types */
00352 #define DAHDI_CHAN_MAPPING_PHYSICAL 0
00353 #define DAHDI_CHAN_MAPPING_LOGICAL  1
00354 
00355 
00356 static int ifcount = 0;
00357 
00358 #ifdef HAVE_PRI
00359 AST_MUTEX_DEFINE_STATIC(pridebugfdlock);
00360 #endif
00361 
00362 /*! \brief Protect the monitoring thread, so only one process can kill or start it, and not
00363    when it's doing something critical. */
00364 AST_MUTEX_DEFINE_STATIC(monlock);
00365 
00366 /*! \brief This is the thread for the monitor which checks for input on the channels
00367    which are not currently in use. */
00368 static pthread_t monitor_thread = AST_PTHREADT_NULL;
00369 static ast_cond_t ss_thread_complete;
00370 AST_MUTEX_DEFINE_STATIC(ss_thread_lock);
00371 AST_MUTEX_DEFINE_STATIC(restart_lock);
00372 static int ss_thread_count = 0;
00373 static int num_restart_pending = 0;
00374 
00375 static int restart_monitor(void);
00376 
00377 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);
00378 
00379 static int dahdi_sendtext(struct ast_channel *c, const char *text);
00380 
00381 #define SIG_PRI_LIB_HANDLE_CASES \
00382    SIG_PRI:                \
00383    case SIG_BRI:              \
00384    case SIG_BRI_PTMP
00385 
00386 static void mwi_event_cb(const struct ast_event *event, void *userdata)
00387 {
00388    /* This module does not handle MWI in an event-based manner.  However, it
00389     * subscribes to MWI for each mailbox that is configured so that the core
00390     * knows that we care about it.  Then, chan_dahdi will get the MWI from the
00391     * event cache instead of checking the mailbox directly. */
00392 }
00393 
00394 /*! \brief Avoid the silly dahdi_getevent which ignores a bunch of events */
00395 static inline int dahdi_get_event(int fd)
00396 {
00397    int j;
00398    if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
00399       return -1;
00400    return j;
00401 }
00402 
00403 /*! \brief Avoid the silly dahdi_waitevent which ignores a bunch of events */
00404 static inline int dahdi_wait_event(int fd)
00405 {
00406    int i, j = 0;
00407    i = DAHDI_IOMUX_SIGEVENT;
00408    if (ioctl(fd, DAHDI_IOMUX, &i) == -1)
00409       return -1;
00410    if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
00411       return -1;
00412    return j;
00413 }
00414 
00415 /*! Chunk size to read -- we use 20ms chunks to make things happy. */
00416 #define READ_SIZE 160
00417 
00418 #define MASK_AVAIL      (1 << 0) /*!< Channel available for PRI use */
00419 #define MASK_INUSE      (1 << 1) /*!< Channel currently in use */
00420 
00421 #define CALLWAITING_SILENT_SAMPLES     ((300 * 8) / READ_SIZE) /*!< 300 ms */
00422 #define CALLWAITING_REPEAT_SAMPLES     ((10000 * 8) / READ_SIZE) /*!< 10,000 ms */
00423 #define CALLWAITING_SUPPRESS_SAMPLES   ((100 * 8) / READ_SIZE) /*!< 100 ms */
00424 #define CIDCW_EXPIRE_SAMPLES        ((500 * 8) / READ_SIZE) /*!< 500 ms */
00425 #define MIN_MS_SINCE_FLASH          ((2000) )   /*!< 2000 ms */
00426 #define DEFAULT_RINGT               ((8000 * 8) / READ_SIZE) /*!< 8,000 ms */
00427 
00428 struct dahdi_pvt;
00429 
00430 /*!
00431  * \brief Configured ring timeout base.
00432  * \note Value computed from "ringtimeout" read in from chan_dahdi.conf if it exists.
00433  */
00434 static int ringt_base = DEFAULT_RINGT;
00435 
00436 #ifdef HAVE_SS7
00437 
00438 #define LINKSTATE_INALARM  (1 << 0)
00439 #define LINKSTATE_STARTING (1 << 1)
00440 #define LINKSTATE_UP    (1 << 2)
00441 #define LINKSTATE_DOWN     (1 << 3)
00442 
00443 #define SS7_NAI_DYNAMIC    -1
00444 
00445 #define LINKSET_FLAG_EXPLICITACM (1 << 0)
00446 
00447 struct dahdi_ss7 {
00448    pthread_t master;                /*!< Thread of master */
00449    ast_mutex_t lock;
00450    int fds[NUM_DCHANS];
00451    int numsigchans;
00452    int linkstate[NUM_DCHANS];
00453    int numchans;
00454    int type;
00455    enum {
00456       LINKSET_STATE_DOWN = 0,
00457       LINKSET_STATE_UP
00458    } state;
00459    char called_nai;                 /*!< Called Nature of Address Indicator */
00460    char calling_nai;                /*!< Calling Nature of Address Indicator */
00461    char internationalprefix[10];             /*!< country access code ('00' for european dialplans) */
00462    char nationalprefix[10];               /*!< area access code ('0' for european dialplans) */
00463    char subscriberprefix[20];             /*!< area access code + area code ('0'+area code for european dialplans) */
00464    char unknownprefix[20];                /*!< for unknown dialplans */
00465    struct ss7 *ss7;
00466    struct dahdi_pvt *pvts[MAX_CHANNELS];           /*!< Member channel pvt structs */
00467    int flags;                    /*!< Linkset flags */
00468 };
00469 
00470 static struct dahdi_ss7 linksets[NUM_SPANS];
00471 
00472 static int cur_ss7type = -1;
00473 static int cur_linkset = -1;
00474 static int cur_pointcode = -1;
00475 static int cur_cicbeginswith = -1;
00476 static int cur_adjpointcode = -1;
00477 static int cur_networkindicator = -1;
00478 static int cur_defaultdpc = -1;
00479 #endif /* HAVE_SS7 */
00480 
00481 #ifdef HAVE_OPENR2
00482 struct dahdi_mfcr2 {
00483    pthread_t r2master;            /*!< Thread of master */
00484    openr2_context_t *protocol_context;    /*!< OpenR2 context handle */
00485    struct dahdi_pvt *pvts[MAX_CHANNELS];     /*!< Member channel pvt structs */
00486    int numchans;                          /*!< Number of channels in this R2 block */
00487    int monitored_count;                   /*!< Number of channels being monitored */
00488 };
00489 
00490 struct dahdi_mfcr2_conf {
00491    openr2_variant_t variant;
00492    int mfback_timeout;
00493    int metering_pulse_timeout;
00494    int max_ani;
00495    int max_dnis;
00496    signed int get_ani_first:2;
00497 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
00498    signed int skip_category_request:2;
00499 #endif
00500    unsigned int call_files:1;
00501    unsigned int allow_collect_calls:1;
00502    unsigned int charge_calls:1;
00503    unsigned int accept_on_offer:1;
00504    unsigned int forced_release:1;
00505    unsigned int double_answer:1;
00506    signed int immediate_accept:2;
00507    char logdir[OR2_MAX_PATH];
00508    char r2proto_file[OR2_MAX_PATH];
00509    openr2_log_level_t loglevel;
00510    openr2_calling_party_category_t category;
00511 };
00512 
00513 /* malloc'd array of malloc'd r2links */
00514 static struct dahdi_mfcr2 **r2links;
00515 /* how many r2links have been malloc'd */
00516 static int r2links_count = 0;
00517 
00518 #endif /* HAVE_OPENR2 */
00519 
00520 #ifdef HAVE_PRI
00521 
00522 #define PVT_TO_CHANNEL(p) (((p)->prioffset) | ((p)->logicalspan << 8) | (p->pri->mastertrunkgroup ? 0x10000 : 0))
00523 #define PRI_CHANNEL(p) ((p) & 0xff)
00524 #define PRI_SPAN(p) (((p) >> 8) & 0xff)
00525 #define PRI_EXPLICIT(p) (((p) >> 16) & 0x01)
00526 
00527 /*! Call establishment life cycle level for simple comparisons. */
00528 enum dahdi_call_level {
00529    /*! Call does not exist. */
00530    DAHDI_CALL_LEVEL_IDLE,
00531    /*! Call is present but has no response yet. (SETUP) */
00532    DAHDI_CALL_LEVEL_SETUP,
00533    /*! Call is collecting digits for overlap dialing. (SETUP ACKNOWLEDGE) */
00534    DAHDI_CALL_LEVEL_OVERLAP,
00535    /*! Call routing is happening. (PROCEEDING) */
00536    DAHDI_CALL_LEVEL_PROCEEDING,
00537    /*! Called party is being alerted of the call. (ALERTING) */
00538    DAHDI_CALL_LEVEL_ALERTING,
00539    /*! Call is connected/answered. (CONNECT) */
00540    DAHDI_CALL_LEVEL_CONNECT,
00541 };
00542 
00543 struct dahdi_pri {
00544    pthread_t master;                /*!< Thread of master */
00545    ast_mutex_t lock;                /*!< Mutex */
00546    char idleext[AST_MAX_EXTENSION];          /*!< Where to idle extra calls */
00547    char idlecontext[AST_MAX_CONTEXT];           /*!< What context to use for idle */
00548    char idledial[AST_MAX_EXTENSION];            /*!< What to dial before dumping */
00549    int minunused;                   /*!< Min # of channels to keep empty */
00550    int minidle;                     /*!< Min # of "idling" calls to keep active */
00551    int nodetype;                    /*!< Node type */
00552    int switchtype;                     /*!< Type of switch to emulate */
00553    int nsf;                   /*!< Network-Specific Facilities */
00554    int dialplan;                    /*!< Dialing plan */
00555    int localdialplan;                  /*!< Local dialing plan */
00556    char internationalprefix[10];             /*!< country access code ('00' for european dialplans) */
00557    char nationalprefix[10];               /*!< area access code ('0' for european dialplans) */
00558    char localprefix[20];                  /*!< area access code + area code ('0'+area code for european dialplans) */
00559    char privateprefix[20];                /*!< for private dialplans */
00560    char unknownprefix[20];                /*!< for unknown dialplans */
00561    int dchannels[NUM_DCHANS];             /*!< What channel are the dchannels on */
00562    int trunkgroup;                     /*!< What our trunkgroup is */
00563    int mastertrunkgroup;                  /*!< What trunk group is our master */
00564    int prilogicalspan;                 /*!< Logical span number within trunk group */
00565    int numchans;                    /*!< Num of channels we represent */
00566    int overlapdial;                 /*!< In overlap dialing mode */
00567    int qsigchannelmapping;                /*!< QSIG channel mapping type */
00568    int discardremoteholdretrieval;              /*!< shall remote hold or remote retrieval notifications be discarded? */
00569    int facilityenable;                 /*!< Enable facility IEs */
00570    struct pri *dchans[NUM_DCHANS];              /*!< Actual d-channels */
00571    int dchanavail[NUM_DCHANS];               /*!< Whether each channel is available */
00572    struct pri *pri;                 /*!< Currently active D-channel */
00573    /*! \brief TRUE if to dump PRI event info (Tested but never set) */
00574    int debug;
00575    int fds[NUM_DCHANS];                /*!< FD's for d-channels */
00576    /*! \brief Value set but not used */
00577    int offset;
00578    /*! \brief Span number put into user output messages */
00579    int span;
00580    /*! \brief TRUE if span is being reset/restarted */
00581    int resetting;
00582    /*! \brief Current position during a reset (-1 if not started) */
00583    int resetpos;
00584 #ifdef HAVE_PRI_INBANDDISCONNECT
00585    unsigned int inbanddisconnect:1;          /*!< Should we support inband audio after receiving DISCONNECT? */
00586 #endif
00587    /*! TRUE if we have already whined about no D channels available. */
00588    unsigned int no_d_channels:1;
00589    time_t lastreset;                /*!< time when unused channels were last reset */
00590    long resetinterval;                 /*!< Interval (in seconds) for resetting unused channels */
00591    /*! \brief ISDN signalling type (SIG_PRI, SIG_BRI, SIG_BRI_PTMP, etc...) */
00592    int sig;
00593    struct dahdi_pvt *pvts[MAX_CHANNELS];           /*!< Member channel pvt structs */
00594    struct dahdi_pvt *crvs;                /*!< Member CRV structs */
00595    struct dahdi_pvt *crvend;                 /*!< Pointer to end of CRV structs */
00596 };
00597 
00598 
00599 static struct dahdi_pri pris[NUM_SPANS];
00600 
00601 #if 0
00602 #define DEFAULT_PRI_DEBUG (PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_STATE)
00603 #else
00604 #define DEFAULT_PRI_DEBUG 0
00605 #endif
00606 
00607 static inline void pri_rel(struct dahdi_pri *pri)
00608 {
00609    ast_mutex_unlock(&pri->lock);
00610 }
00611 
00612 #else
00613 /*! Shut up the compiler */
00614 struct dahdi_pri;
00615 #endif
00616 
00617 #define SUB_REAL  0        /*!< Active call */
00618 #define SUB_CALLWAIT 1        /*!< Call-Waiting call on hold */
00619 #define SUB_THREEWAY 2        /*!< Three-way call */
00620 
00621 /* Polarity states */
00622 #define POLARITY_IDLE   0
00623 #define POLARITY_REV    1
00624 
00625 
00626 struct distRingData {
00627    int ring[3];
00628    int range;
00629 };
00630 struct ringContextData {
00631    char contextData[AST_MAX_CONTEXT];
00632 };
00633 struct dahdi_distRings {
00634    struct distRingData ringnum[3];
00635    struct ringContextData ringContext[3];
00636 };
00637 
00638 static char *subnames[] = {
00639    "Real",
00640    "Callwait",
00641    "Threeway"
00642 };
00643 
00644 struct dahdi_subchannel {
00645    int dfd;
00646    struct ast_channel *owner;
00647    int chan;
00648    short buffer[AST_FRIENDLY_OFFSET/2 + READ_SIZE];
00649    struct ast_frame f;     /*!< One frame for each channel.  How did this ever work before? */
00650    unsigned int needringing:1;
00651    unsigned int needbusy:1;
00652    unsigned int needcongestion:1;
00653    unsigned int needcallerid:1;
00654    unsigned int needanswer:1;
00655    unsigned int needflash:1;
00656    unsigned int needhold:1;
00657    unsigned int needunhold:1;
00658    unsigned int linear:1;
00659    unsigned int inthreeway:1;
00660    struct dahdi_confinfo curconf;
00661 };
00662 
00663 #define CONF_USER_REAL     (1 << 0)
00664 #define CONF_USER_THIRDCALL   (1 << 1)
00665 
00666 #define MAX_SLAVES   4
00667 
00668 /* States for sending MWI message
00669  * First three states are required for send Ring Pulse Alert Signal
00670  */
00671 typedef enum {
00672    MWI_SEND_NULL = 0,
00673    MWI_SEND_SA,
00674    MWI_SEND_SA_WAIT,
00675    MWI_SEND_PAUSE,
00676    MWI_SEND_SPILL,
00677    MWI_SEND_CLEANUP,
00678    MWI_SEND_DONE,
00679 } mwisend_states;
00680 
00681 struct mwisend_info {
00682    struct   timeval  pause;
00683    mwisend_states    mwisend_current;
00684 };
00685 
00686 static struct dahdi_pvt {
00687    ast_mutex_t lock;             /*!< Channel private lock. */
00688    struct ast_channel *owner;       /*!< Our current active owner (if applicable) */
00689                      /*!< Up to three channels can be associated with this call */
00690 
00691    struct dahdi_subchannel sub_unused;    /*!< Just a safety precaution */
00692    struct dahdi_subchannel subs[3];       /*!< Sub-channels */
00693    struct dahdi_confinfo saveconf;        /*!< Saved conference info */
00694 
00695    struct dahdi_pvt *slaves[MAX_SLAVES];     /*!< Slave to us (follows our conferencing) */
00696    struct dahdi_pvt *master;           /*!< Master to us (we follow their conferencing) */
00697    int inconference;          /*!< If our real should be in the conference */
00698 
00699    int bufsize;                /*!< Size of the buffers */
00700    int buf_no;             /*!< Number of buffers */
00701    int buf_policy;            /*!< Buffer policy */
00702    int faxbuf_no;              /*!< Number of Fax buffers */
00703    int faxbuf_policy;          /*!< Fax buffer policy */
00704    int sig;             /*!< Signalling style */
00705    /*!
00706     * \brief Nonzero if the signaling type is sent over a radio.
00707     * \note Set to a couple of nonzero values but it is only tested like a boolean.
00708     */
00709    int radio;
00710    int outsigmod;             /*!< Outbound Signalling style (modifier) */
00711    int oprmode;               /*!< "Operator Services" mode */
00712    struct dahdi_pvt *oprpeer;          /*!< "Operator Services" peer tech_pvt ptr */
00713    /*! \brief Amount of gain to increase during caller id */
00714    float cid_rxgain;
00715    /*! \brief Rx gain set by chan_dahdi.conf */
00716    float rxgain;
00717    /*! \brief Tx gain set by chan_dahdi.conf */
00718    float txgain;
00719    int tonezone;              /*!< tone zone for this chan, or -1 for default */
00720    struct dahdi_pvt *next;          /*!< Next channel in list */
00721    struct dahdi_pvt *prev;          /*!< Prev channel in list */
00722 
00723    /* flags */
00724 
00725    /*!
00726     * \brief TRUE if ADSI (Analog Display Services Interface) available
00727     * \note Set from the "adsi" value read in from chan_dahdi.conf
00728     */
00729    unsigned int adsi:1;
00730    /*!
00731     * \brief TRUE if we can use a polarity reversal to mark when an outgoing
00732     * call is answered by the remote party.
00733     * \note Set from the "answeronpolarityswitch" value read in from chan_dahdi.conf
00734     */
00735    unsigned int answeronpolarityswitch:1;
00736    /*!
00737     * \brief TRUE if busy detection is enabled.
00738     * (Listens for the beep-beep busy pattern.)
00739     * \note Set from the "busydetect" value read in from chan_dahdi.conf
00740     */
00741    unsigned int busydetect:1;
00742    /*!
00743     * \brief TRUE if call return is enabled.
00744     * (*69, if your dialplan doesn't catch this first)
00745     * \note Set from the "callreturn" value read in from chan_dahdi.conf
00746     */
00747    unsigned int callreturn:1;
00748    /*!
00749     * \brief TRUE if busy extensions will hear the call-waiting tone
00750     * and can use hook-flash to switch between callers.
00751     * \note Can be disabled by dialing *70.
00752     * \note Initialized with the "callwaiting" value read in from chan_dahdi.conf
00753     */
00754    unsigned int callwaiting:1;
00755    /*!
00756     * \brief TRUE if send caller ID for Call Waiting
00757     * \note Set from the "callwaitingcallerid" value read in from chan_dahdi.conf
00758     */
00759    unsigned int callwaitingcallerid:1;
00760    /*!
00761     * \brief TRUE if support for call forwarding enabled.
00762     * Dial *72 to enable call forwarding.
00763     * Dial *73 to disable call forwarding.
00764     * \note Set from the "cancallforward" value read in from chan_dahdi.conf
00765     */
00766    unsigned int cancallforward:1;
00767    /*!
00768     * \brief TRUE if support for call parking is enabled.
00769     * \note Set from the "canpark" value read in from chan_dahdi.conf
00770     */
00771    unsigned int canpark:1;
00772    /*! \brief TRUE if to wait for a DTMF digit to confirm answer */
00773    unsigned int confirmanswer:1;
00774    /*!
00775     * \brief TRUE if the channel is to be destroyed on hangup.
00776     * (Used by pseudo channels.)
00777     */
00778    unsigned int destroy:1;
00779    unsigned int didtdd:1;           /*!< flag to say its done it once */
00780    /*! \brief TRUE if analog type line dialed no digits in Dial() */
00781    unsigned int dialednone:1;
00782    /*! \brief TRUE if in the process of dialing digits or sending something. */
00783    unsigned int dialing:1;
00784    /*! \brief TRUE if the transfer capability of the call is digital. */
00785    unsigned int digital:1;
00786    /*! \brief TRUE if Do-Not-Disturb is enabled. */
00787    unsigned int dnd:1;
00788    /*! \brief XXX BOOLEAN Purpose??? */
00789    unsigned int echobreak:1;
00790    /*!
00791     * \brief TRUE if echo cancellation enabled when bridged.
00792     * \note Initialized with the "echocancelwhenbridged" value read in from chan_dahdi.conf
00793     * \note Disabled if the echo canceller is not setup.
00794     */
00795    unsigned int echocanbridged:1;
00796    /*! \brief TRUE if echo cancellation is turned on. */
00797    unsigned int echocanon:1;
00798    /*! \brief TRUE if a fax tone has already been handled. */
00799    unsigned int faxhandled:1;
00800    /*! \brief TRUE if dynamic faxbuffers are configured for use, default is OFF */
00801    unsigned int usefaxbuffers:1;
00802    /*! \brief TRUE while dynamic faxbuffers are in use */
00803    unsigned int bufferoverrideinuse:1;
00804    /*! \brief TRUE if over a radio and dahdi_read() has been called. */
00805    unsigned int firstradio:1;
00806    /*!
00807     * \brief TRUE if the call will be considered "hung up" on a polarity reversal.
00808     * \note Set from the "hanguponpolarityswitch" value read in from chan_dahdi.conf
00809     */
00810    unsigned int hanguponpolarityswitch:1;
00811    /*! \brief TRUE if DTMF detection needs to be done by hardware. */
00812    unsigned int hardwaredtmf:1;
00813    /*!
00814     * \brief TRUE if the outgoing caller ID is blocked/hidden.
00815     * \note Caller ID can be disabled by dialing *67.
00816     * \note Caller ID can be enabled by dialing *82.
00817     * \note Initialized with the "hidecallerid" value read in from chan_dahdi.conf
00818     */
00819    unsigned int hidecallerid:1;
00820    /*!
00821     * \brief TRUE if hide just the name not the number for legacy PBX use.
00822     * \note Only applies to PRI channels.
00823     * \note Set from the "hidecalleridname" value read in from chan_dahdi.conf
00824     */
00825    unsigned int hidecalleridname:1;
00826    /*! \brief TRUE if DTMF detection is disabled. */
00827    unsigned int ignoredtmf:1;
00828    /*!
00829     * \brief TRUE if the channel should be answered immediately
00830     * without attempting to gather any digits.
00831     * \note Set from the "immediate" value read in from chan_dahdi.conf
00832     */
00833    unsigned int immediate:1;
00834    /*! \brief TRUE if in an alarm condition. */
00835    unsigned int inalarm:1;
00836    /*! \brief TRUE if TDD in MATE mode */
00837    unsigned int mate:1;
00838 #if defined(HAVE_PRI)
00839    /*!
00840     * \brief TRUE when this channel is allocated.
00841     *
00842     * \details
00843     * Needed to hold an outgoing channel allocation before the
00844     * owner pointer is created.
00845     *
00846     * \note This is one of several items to check to see if a
00847     * channel is available for use.
00848     */
00849    unsigned int allocated:1;
00850 #endif   /* defined(HAVE_PRI) */
00851    /*! \brief TRUE if we originated the call leg. */
00852    unsigned int outgoing:1;
00853    /* unsigned int overlapdial:1;         unused and potentially confusing */
00854    /*!
00855     * \brief TRUE if busy extensions will hear the call-waiting tone
00856     * and can use hook-flash to switch between callers.
00857     * \note Set from the "callwaiting" value read in from chan_dahdi.conf
00858     */
00859    unsigned int permcallwaiting:1;
00860    /*!
00861     * \brief TRUE if the outgoing caller ID is blocked/restricted/hidden.
00862     * \note Set from the "hidecallerid" value read in from chan_dahdi.conf
00863     */
00864    unsigned int permhidecallerid:1;
00865    /*!
00866     * \brief TRUE if PRI congestion/busy indications are sent out-of-band.
00867     * \note Set from the "priindication" value read in from chan_dahdi.conf
00868     */
00869    unsigned int priindication_oob:1;
00870    /*!
00871     * \brief TRUE if PRI B channels are always exclusively selected.
00872     * \note Set from the "priexclusive" value read in from chan_dahdi.conf
00873     */
00874    unsigned int priexclusive:1;
00875    /*!
00876     * \brief TRUE if we will pulse dial.
00877     * \note Set from the "pulsedial" value read in from chan_dahdi.conf
00878     */
00879    unsigned int pulse:1;
00880    /*! \brief TRUE if a pulsed digit was detected. (Pulse dial phone detected) */
00881    unsigned int pulsedial:1;
00882    unsigned int restartpending:1;      /*!< flag to ensure counted only once for restart */
00883    /*!
00884     * \brief TRUE if caller ID is restricted.
00885     * \note Set but not used.  Should be deleted.  Redundant with permhidecallerid.
00886     * \note Set from the "restrictcid" value read in from chan_dahdi.conf
00887     */
00888    unsigned int restrictcid:1;
00889    /*!
00890     * \brief TRUE if three way calling is enabled
00891     * \note Set from the "threewaycalling" value read in from chan_dahdi.conf
00892     */
00893    unsigned int threewaycalling:1;
00894    /*!
00895     * \brief TRUE if call transfer is enabled
00896     * \note For FXS ports (either direct analog or over T1/E1):
00897     *   Support flash-hook call transfer
00898     * \note For digital ports using ISDN PRI protocols:
00899     *   Support switch-side transfer (called 2BCT, RLT or other names)
00900     * \note Set from the "transfer" value read in from chan_dahdi.conf
00901     */
00902    unsigned int transfer:1;
00903    /*!
00904     * \brief TRUE if caller ID is used on this channel.
00905     * \note PRI and SS7 spans will save caller ID from the networking peer.
00906     * \note FXS ports will generate the caller ID spill.
00907     * \note FXO ports will listen for the caller ID spill.
00908     * \note Set from the "usecallerid" value read in from chan_dahdi.conf
00909     */
00910    unsigned int use_callerid:1;
00911    /*!
00912     * \brief TRUE if we will use the calling presentation setting
00913     * from the Asterisk channel for outgoing calls.
00914     * \note Only applies to PRI and SS7 channels.
00915     * \note Set from the "usecallingpres" value read in from chan_dahdi.conf
00916     */
00917    unsigned int use_callingpres:1;
00918    /*!
00919     * \brief TRUE if distinctive rings are to be detected.
00920     * \note For FXO lines
00921     * \note Set indirectly from the "usedistinctiveringdetection" value read in from chan_dahdi.conf
00922     */
00923    unsigned int usedistinctiveringdetection:1;
00924    /*!
00925     * \brief TRUE if we should use the callerid from incoming call on dahdi transfer.
00926     * \note Set from the "useincomingcalleridondahditransfer" value read in from chan_dahdi.conf
00927     */
00928    unsigned int dahditrcallerid:1;
00929    /*!
00930     * \brief TRUE if allowed to flash-transfer to busy channels.
00931     * \note Set from the "transfertobusy" value read in from chan_dahdi.conf
00932     */
00933    unsigned int transfertobusy:1;
00934    /*!
00935     * \brief TRUE if the FXO port monitors for neon type MWI indications from the other end.
00936     * \note Set if the "mwimonitor" value read in contains "neon" from chan_dahdi.conf
00937     */
00938    unsigned int mwimonitor_neon:1;
00939    /*!
00940     * \brief TRUE if the FXO port monitors for fsk type MWI indications from the other end.
00941     * \note Set if the "mwimonitor" value read in contains "fsk" from chan_dahdi.conf
00942     */
00943    unsigned int mwimonitor_fsk:1;
00944    /*!
00945     * \brief TRUE if the FXO port monitors for rpas precursor to fsk MWI indications from the other end.
00946     * \note RPAS - Ring Pulse Alert Signal
00947     * \note Set if the "mwimonitor" value read in contains "rpas" from chan_dahdi.conf
00948     */
00949    unsigned int mwimonitor_rpas:1;
00950    /*! \brief TRUE if an MWI monitor thread is currently active */
00951    unsigned int mwimonitoractive:1;
00952    /*! \brief TRUE if a MWI message sending thread is active */
00953    unsigned int mwisendactive:1;
00954    /*!
00955     * \brief TRUE if channel is out of reset and ready
00956     * \note Set but not used.
00957     */
00958    unsigned int inservice:1;
00959    /*!
00960     * \brief TRUE if the channel is locally blocked.
00961     * \note Applies to SS7 channels.
00962     */
00963    unsigned int locallyblocked:1;
00964    /*!
00965     * \brief TRUE if the channel is remotely blocked.
00966     * \note Applies to SS7 channels.
00967     */
00968    unsigned int remotelyblocked:1;
00969    /*!
00970     * \brief TRUE if SMDI (Simplified Message Desk Interface) is enabled
00971     * \note Set from the "usesmdi" value read in from chan_dahdi.conf
00972     */
00973    unsigned int use_smdi:1;
00974 #if defined(HAVE_PRI) || defined(HAVE_SS7)
00975    /*!
00976     * \brief XXX BOOLEAN Purpose???
00977     * \note Applies to SS7 channels.
00978     */
00979    unsigned int rlt:1;
00980    /*! \brief TRUE if the call has already gone/hungup */
00981    unsigned int alreadyhungup:1;
00982    /*!
00983     * \brief TRUE if this is an idle call
00984     * \note Applies to PRI channels.
00985     */
00986    unsigned int isidlecall:1;
00987    /*! \brief TRUE if the call has seen inband-information progress through the network. */
00988    unsigned int progress:1;
00989    /*!
00990     * \brief TRUE if this channel is being reset/restarted
00991     * \note Applies to PRI channels.
00992     */
00993    unsigned int resetting:1;
00994 
00995    /*! Call establishment life cycle level for simple comparisons. */
00996    enum dahdi_call_level call_level;
00997 #endif
00998    struct mwisend_info mwisend_data;
00999    /*! \brief The serial port to listen for SMDI data on */
01000    struct ast_smdi_interface *smdi_iface;
01001 
01002    /*! \brief Distinctive Ring data */
01003    struct dahdi_distRings drings;
01004 
01005    /*!
01006     * \brief The configured context for incoming calls.
01007     * \note The "context" string read in from chan_dahdi.conf
01008     */
01009    char context[AST_MAX_CONTEXT];
01010    /*!
01011     * \brief Saved context string.
01012     */
01013    char defcontext[AST_MAX_CONTEXT];
01014    /*! \brief Extension to use in the dialplan. */
01015    char exten[AST_MAX_EXTENSION];
01016    /*!
01017     * \brief Language configured for calls.
01018     * \note The "language" string read in from chan_dahdi.conf
01019     */
01020    char language[MAX_LANGUAGE];
01021    /*!
01022     * \brief The configured music-on-hold class to use for calls.
01023     * \note The "musicclass" or "mohinterpret" or "musiconhold" string read in from chan_dahdi.conf
01024     */
01025    char mohinterpret[MAX_MUSICCLASS];
01026    /*!
01027     * \brief Suggested music-on-hold class for peer channel to use for calls.
01028     * \note The "mohsuggest" string read in from chan_dahdi.conf
01029     */
01030    char mohsuggest[MAX_MUSICCLASS];
01031    char parkinglot[AST_MAX_EXTENSION]; /*!< Parking lot for this channel */
01032 #if defined(PRI_ANI) || defined(HAVE_SS7)
01033    /*! \brief Automatic Number Identification number (Alternate PRI caller ID number) */
01034    char cid_ani[AST_MAX_EXTENSION];
01035 #endif
01036    /*! \brief Automatic Number Identification code from PRI */
01037    int cid_ani2;
01038    /*! \brief Caller ID number from an incoming call. */
01039    char cid_num[AST_MAX_EXTENSION];
01040    /*! \brief Caller ID Q.931 TON/NPI field values.  Set by PRI. Zero otherwise. */
01041    int cid_ton;
01042    /*! \brief Caller ID name from an incoming call. */
01043    char cid_name[AST_MAX_EXTENSION];
01044    /*! \brief Last Caller ID number from an incoming call. */
01045    char lastcid_num[AST_MAX_EXTENSION];
01046    /*! \brief Last Caller ID name from an incoming call. */
01047    char lastcid_name[AST_MAX_EXTENSION];
01048    char *origcid_num;            /*!< malloced original callerid */
01049    char *origcid_name;           /*!< malloced original callerid */
01050    /*! \brief Call waiting number. */
01051    char callwait_num[AST_MAX_EXTENSION];
01052    /*! \brief Call waiting name. */
01053    char callwait_name[AST_MAX_EXTENSION];
01054    /*! \brief Redirecting Directory Number Information Service (RDNIS) number */
01055    char rdnis[AST_MAX_EXTENSION];
01056    /*! \brief Dialed Number Identifier */
01057    char dnid[AST_MAX_EXTENSION];
01058    /*!
01059     * \brief Bitmapped groups this belongs to.
01060     * \note The "group" bitmapped group string read in from chan_dahdi.conf
01061     */
01062    ast_group_t group;
01063    /*! \brief Active PCM encoding format: DAHDI_LAW_ALAW or DAHDI_LAW_MULAW */
01064    int law;
01065    int confno;             /*!< Our conference */
01066    int confusers;             /*!< Who is using our conference */
01067    int propconfno;               /*!< Propagated conference number */
01068    /*!
01069     * \brief Bitmapped call groups this belongs to.
01070     * \note The "callgroup" bitmapped group string read in from chan_dahdi.conf
01071     */
01072    ast_group_t callgroup;
01073    /*!
01074     * \brief Bitmapped pickup groups this belongs to.
01075     * \note The "pickupgroup" bitmapped group string read in from chan_dahdi.conf
01076     */
01077    ast_group_t pickupgroup;
01078    /*!
01079     * \brief Channel variable list with associated values to set when a channel is created.
01080     * \note The "setvar" strings read in from chan_dahdi.conf
01081     */
01082    struct ast_variable *vars;
01083    int channel;               /*!< Channel Number or CRV */
01084    int span;               /*!< Span number */
01085    time_t guardtime;          /*!< Must wait this much time before using for new call */
01086    int cid_signalling;           /*!< CID signalling type bell202 or v23 */
01087    int cid_start;             /*!< CID start indicator, polarity or ring */
01088    int callingpres;           /*!< The value of calling presentation that we're going to use when placing a PRI call */
01089    int callwaitingrepeat;           /*!< How many samples to wait before repeating call waiting */
01090    int cidcwexpire;           /*!< When to stop waiting for CID/CW CAS response (In samples) */
01091    int cid_suppress_expire;      /*!< How many samples to suppress after a CID spill. */
01092    /*! \brief Analog caller ID waveform sample buffer */
01093    unsigned char *cidspill;
01094    /*! \brief Position in the cidspill buffer to send out next. */
01095    int cidpos;
01096    /*! \brief Length of the cidspill buffer containing samples. */
01097    int cidlen;
01098    /*! \brief Ring timeout timer?? */
01099    int ringt;
01100    /*!
01101     * \brief Ring timeout base.
01102     * \note Value computed indirectly from "ringtimeout" read in from chan_dahdi.conf
01103     */
01104    int ringt_base;
01105    /*!
01106     * \brief Number of most significant digits/characters to strip from the dialed number.
01107     * \note Feature is deprecated.  Use dialplan logic.
01108     * \note The characters are stripped before the PRI TON/NPI prefix
01109     * characters are processed.
01110     */
01111    int stripmsd;
01112    /*!
01113     * \brief TRUE if Call Waiting (CW) CPE Alert Signal (CAS) is being sent.
01114     * \note
01115     * After CAS is sent, the call waiting caller id will be sent if the phone
01116     * gives a positive reply.
01117     */
01118    int callwaitcas;
01119    /*! \brief Number of call waiting rings. */
01120    int callwaitrings;
01121    /*! \brief Echo cancel parameters. */
01122    struct {
01123       struct dahdi_echocanparams head;
01124       struct dahdi_echocanparam params[DAHDI_MAX_ECHOCANPARAMS];
01125    } echocancel;
01126    /*!
01127     * \brief Echo training time. 0 = disabled
01128     * \note Set from the "echotraining" value read in from chan_dahdi.conf
01129     */
01130    int echotraining;
01131    /*! \brief Filled with 'w'.  XXX Purpose?? */
01132    char echorest[20];
01133    /*!
01134     * \brief Number of times to see "busy" tone before hanging up.
01135     * \note Set from the "busycount" value read in from chan_dahdi.conf
01136     */
01137    int busycount;
01138    /*!
01139     * \brief Length of "busy" tone on time.
01140     * \note Set from the "busypattern" value read in from chan_dahdi.conf
01141     */
01142    int busy_tonelength;
01143    /*!
01144     * \brief Length of "busy" tone off time.
01145     * \note Set from the "busypattern" value read in from chan_dahdi.conf
01146     */
01147    int busy_quietlength;
01148    /*!
01149     * \brief Bitmapped call progress detection flags. CALLPROGRESS_xxx values.
01150     * \note Bits set from the "callprogress" and "faxdetect" values read in from chan_dahdi.conf
01151     */
01152    int callprogress;
01153    /*!
01154     * \brief Number of milliseconds to wait for dialtone.
01155     * \note Set from the "waitfordialtone" value read in from chan_dahdi.conf
01156     */
01157    int waitfordialtone;
01158    struct timeval waitingfordt;        /*!< Time we started waiting for dialtone */
01159    struct timeval flashtime;        /*!< Last flash-hook time */
01160    /*! \brief Opaque DSP configuration structure. */
01161    struct ast_dsp *dsp;
01162    //int cref;             /*!< Call reference number (Not used) */
01163    /*! \brief DAHDI dial operation command struct for ioctl() call. */
01164    struct dahdi_dialoperation dop;
01165    int whichwink;             /*!< SIG_FEATDMF_TA Which wink are we on? */
01166    /*! \brief Second part of SIG_FEATDMF_TA wink operation. */
01167    char finaldial[64];
01168    char accountcode[AST_MAX_ACCOUNT_CODE];      /*!< Account code */
01169    int amaflags;              /*!< AMA Flags */
01170    struct tdd_state *tdd;           /*!< TDD flag */
01171    /*! \brief Accumulated call forwarding number. */
01172    char call_forward[AST_MAX_EXTENSION];
01173    /*!
01174     * \brief Voice mailbox location.
01175     * \note Set from the "mailbox" string read in from chan_dahdi.conf
01176     */
01177    char mailbox[AST_MAX_EXTENSION];
01178    /*! \brief Opaque event subscription parameters for message waiting indication support. */
01179    struct ast_event_sub *mwi_event_sub;
01180    /*! \brief Delayed dialing for E911.  Overlap digits for ISDN. */
01181    char dialdest[256];
01182    /*! \brief Time the interface went on-hook. */
01183    int onhooktime;
01184    /*! \brief TRUE if the FXS port is off-hook */
01185    int fxsoffhookstate;
01186    /*! \brief -1 = unknown, 0 = no messages, 1 = new messages available */
01187    int msgstate;
01188 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
01189    struct dahdi_vmwi_info mwisend_setting;            /*!< Which VMWI methods to use */
01190    unsigned int mwisend_fsk: 1;     /*! Variable for enabling FSK MWI handling in chan_dahdi */
01191    unsigned int mwisend_rpas:1;     /*! Variable for enabling Ring Pulse Alert before MWI FSK Spill */
01192 #endif
01193    int distinctivering;          /*!< Which distinctivering to use */
01194    int cidrings;              /*!< Which ring to deliver CID on */
01195    int dtmfrelax;             /*!< whether to run in relaxed DTMF mode */
01196    /*! \brief Holding place for event injected from outside normal operation. */
01197    int fake_event;
01198    /*!
01199     * \brief Minimal time period (ms) between the answer polarity
01200     * switch and hangup polarity switch.
01201     */
01202    int polarityonanswerdelay;
01203    /*! \brief Start delay time if polarityonanswerdelay is nonzero. */
01204    struct timeval polaritydelaytv;
01205    /*!
01206     * \brief Send caller ID after this many rings.
01207     * \note Set from the "sendcalleridafter" value read in from chan_dahdi.conf
01208     */
01209    int sendcalleridafter;
01210 #ifdef HAVE_PRI
01211    /*! \brief DAHDI PRI control parameters */
01212    struct dahdi_pri *pri;
01213    /*! \brief XXX Purpose??? */
01214    struct dahdi_pvt *bearer;
01215    /*! \brief XXX Purpose??? */
01216    struct dahdi_pvt *realcall;
01217    /*! \brief Opaque libpri call control structure */
01218    q931_call *call;
01219    /*! \brief Channel number in span. */
01220    int prioffset;
01221    /*! \brief Logical span number within trunk group */
01222    int logicalspan;
01223 #endif
01224    /*! \brief Current line interface polarity. POLARITY_IDLE, POLARITY_REV */
01225    int polarity;
01226    /*! \brief DSP feature flags: DSP_FEATURE_xxx */
01227    int dsp_features;
01228 #ifdef HAVE_SS7
01229    /*! \brief SS7 control parameters */
01230    struct dahdi_ss7 *ss7;
01231    /*! \brief Opaque libss7 call control structure */
01232    struct isup_call *ss7call;
01233    char charge_number[50];
01234    char gen_add_number[50];
01235    char gen_dig_number[50];
01236    char orig_called_num[50];
01237    char redirecting_num[50];
01238    char generic_name[50];
01239    unsigned char gen_add_num_plan;
01240    unsigned char gen_add_nai;
01241    unsigned char gen_add_pres_ind;
01242    unsigned char gen_add_type;
01243    unsigned char gen_dig_type;
01244    unsigned char gen_dig_scheme;
01245    char jip_number[50];
01246    unsigned char lspi_type;
01247    unsigned char lspi_scheme;
01248    unsigned char lspi_context;
01249    char lspi_ident[50];
01250    unsigned int call_ref_ident;
01251    unsigned int call_ref_pc;
01252    unsigned char calling_party_cat;
01253    int transcap;
01254    int cic;                   /*!< CIC associated with channel */
01255    unsigned int dpc;                /*!< CIC's DPC */
01256    unsigned int loopedback:1;
01257 #endif
01258 #ifdef HAVE_OPENR2
01259    struct dahdi_mfcr2 *mfcr2;
01260    openr2_chan_t *r2chan;
01261    openr2_calling_party_category_t mfcr2_recvd_category;
01262    openr2_calling_party_category_t mfcr2_category;
01263    int mfcr2_dnis_index;
01264    int mfcr2_ani_index;
01265    int mfcr2call:1;
01266    int mfcr2_answer_pending:1;
01267    int mfcr2_charge_calls:1;
01268    int mfcr2_allow_collect_calls:1;
01269    int mfcr2_forced_release:1;
01270    int mfcr2_dnis_matched:1;
01271    int mfcr2_call_accepted:1;
01272    int mfcr2_progress:1;
01273    int mfcr2_accept_on_offer:1;
01274 #endif
01275    /*! \brief DTMF digit in progress.  0 when no digit in progress. */
01276    char begindigit;
01277    /*! \brief TRUE if confrence is muted. */
01278    int muting;
01279 } *iflist = NULL, *ifend = NULL;
01280 
01281 /*! \brief Channel configuration from chan_dahdi.conf .
01282  * This struct is used for parsing the [channels] section of chan_dahdi.conf.
01283  * Generally there is a field here for every possible configuration item.
01284  *
01285  * The state of fields is saved along the parsing and whenever a 'channel'
01286  * statement is reached, the current dahdi_chan_conf is used to configure the
01287  * channel (struct dahdi_pvt)
01288  *
01289  * \see dahdi_chan_init for the default values.
01290  */
01291 struct dahdi_chan_conf {
01292    struct dahdi_pvt chan;
01293 #ifdef HAVE_PRI
01294    struct dahdi_pri pri;
01295 #endif
01296 
01297 #ifdef HAVE_SS7
01298    struct dahdi_ss7 ss7;
01299 #endif
01300 
01301 #ifdef HAVE_OPENR2
01302    struct dahdi_mfcr2_conf mfcr2;
01303 #endif
01304    struct dahdi_params timing;
01305    int is_sig_auto; /*!< Use channel signalling from DAHDI? */
01306 
01307    /*!
01308     * \brief The serial port to listen for SMDI data on
01309     * \note Set from the "smdiport" string read in from chan_dahdi.conf
01310     */
01311    char smdi_port[SMDI_MAX_FILENAME_LEN];
01312 };
01313 
01314 /*! returns a new dahdi_chan_conf with default values (by-value) */
01315 static struct dahdi_chan_conf dahdi_chan_conf_default(void)
01316 {
01317    /* recall that if a field is not included here it is initialized
01318     * to 0 or equivalent
01319     */
01320    struct dahdi_chan_conf conf = {
01321 #ifdef HAVE_PRI
01322       .pri = {
01323          .nsf = PRI_NSF_NONE,
01324          .switchtype = PRI_SWITCH_NI2,
01325          .dialplan = PRI_UNKNOWN + 1,
01326          .localdialplan = PRI_NATIONAL_ISDN + 1,
01327          .nodetype = PRI_CPE,
01328          .qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL,
01329 
01330          .minunused = 2,
01331          .idleext = "",
01332          .idledial = "",
01333          .internationalprefix = "",
01334          .nationalprefix = "",
01335          .localprefix = "",
01336          .privateprefix = "",
01337          .unknownprefix = "",
01338          .resetinterval = -1,
01339       },
01340 #endif
01341 #ifdef HAVE_SS7
01342       .ss7 = {
01343          .called_nai = SS7_NAI_NATIONAL,
01344          .calling_nai = SS7_NAI_NATIONAL,
01345          .internationalprefix = "",
01346          .nationalprefix = "",
01347          .subscriberprefix = "",
01348          .unknownprefix = ""
01349       },
01350 #endif
01351 #ifdef HAVE_OPENR2
01352       .mfcr2 = {
01353          .variant = OR2_VAR_ITU,
01354          .mfback_timeout = -1,
01355          .metering_pulse_timeout = -1,
01356          .max_ani = 10,
01357          .max_dnis = 4,
01358          .get_ani_first = -1,
01359 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
01360          .skip_category_request = -1,
01361 #endif
01362          .call_files = 0,
01363          .allow_collect_calls = 0,
01364          .charge_calls = 1,
01365          .accept_on_offer = 1,
01366          .forced_release = 0,
01367          .double_answer = 0,
01368          .immediate_accept = -1,
01369          .logdir = "",
01370          .r2proto_file = "",
01371          .loglevel = OR2_LOG_ERROR | OR2_LOG_WARNING,
01372          .category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER
01373       },
01374 #endif
01375       .chan = {
01376          .context = "default",
01377          .cid_num = "",
01378          .cid_name = "",
01379          .mohinterpret = "default",
01380          .mohsuggest = "",
01381          .parkinglot = "",
01382          .transfertobusy = 1,
01383 
01384          .cid_signalling = CID_SIG_BELL,
01385          .cid_start = CID_START_RING,
01386          .dahditrcallerid = 0,
01387          .use_callerid = 1,
01388          .sig = -1,
01389          .outsigmod = -1,
01390 
01391          .cid_rxgain = +5.0,
01392 
01393          .tonezone = -1,
01394 
01395          .echocancel.head.tap_length = 1,
01396 
01397          .busycount = 3,
01398 
01399          .accountcode = "",
01400 
01401          .mailbox = "",
01402 
01403 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
01404          .mwisend_fsk = 1,
01405 #endif
01406          .polarityonanswerdelay = 600,
01407 
01408          .sendcalleridafter = DEFAULT_CIDRINGS,
01409 
01410          .buf_policy = DAHDI_POLICY_IMMEDIATE,
01411          .buf_no = numbufs,
01412          .usefaxbuffers = 0,
01413          .faxbuf_policy = DAHDI_POLICY_IMMEDIATE,
01414          .faxbuf_no = numbufs,
01415       },
01416       .timing = {
01417          .prewinktime = -1,
01418          .preflashtime = -1,
01419          .winktime = -1,
01420          .flashtime = -1,
01421          .starttime = -1,
01422          .rxwinktime = -1,
01423          .rxflashtime = -1,
01424          .debouncetime = -1
01425       },
01426       .is_sig_auto = 1,
01427       .smdi_port = "/dev/ttyS0",
01428    };
01429 
01430    return conf;
01431 }
01432 
01433 
01434 static struct ast_channel *dahdi_request(const char *type, int format, void *data, int *cause);
01435 static int dahdi_digit_begin(struct ast_channel *ast, char digit);
01436 static int dahdi_digit_end(struct ast_channel *ast, char digit, unsigned int duration);
01437 static int dahdi_sendtext(struct ast_channel *c, const char *text);
01438 static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout);
01439 static int dahdi_hangup(struct ast_channel *ast);
01440 static int dahdi_answer(struct ast_channel *ast);
01441 static struct ast_frame *dahdi_read(struct ast_channel *ast);
01442 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame);
01443 static struct ast_frame *dahdi_exception(struct ast_channel *ast);
01444 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen);
01445 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
01446 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen);
01447 static int dahdi_func_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len);
01448 static int dahdi_func_write(struct ast_channel *chan, const char *function, char *data, const char *value);
01449 static struct dahdi_pvt *handle_init_event(struct dahdi_pvt *i, int event);
01450 
01451 static const struct ast_channel_tech dahdi_tech = {
01452    .type = "DAHDI",
01453    .description = tdesc,
01454    .capabilities = AST_FORMAT_SLINEAR | AST_FORMAT_ULAW | AST_FORMAT_ALAW,
01455    .requester = dahdi_request,
01456    .send_digit_begin = dahdi_digit_begin,
01457    .send_digit_end = dahdi_digit_end,
01458    .send_text = dahdi_sendtext,
01459    .call = dahdi_call,
01460    .hangup = dahdi_hangup,
01461    .answer = dahdi_answer,
01462    .read = dahdi_read,
01463    .write = dahdi_write,
01464    .bridge = dahdi_bridge,
01465    .exception = dahdi_exception,
01466    .indicate = dahdi_indicate,
01467    .fixup = dahdi_fixup,
01468    .setoption = dahdi_setoption,
01469    .func_channel_read = dahdi_func_read,
01470    .func_channel_write = dahdi_func_write,
01471 };
01472 
01473 #ifdef HAVE_PRI
01474 #define GET_CHANNEL(p) ((p)->bearer ? (p)->bearer->channel : p->channel)
01475 #else
01476 #define GET_CHANNEL(p) ((p)->channel)
01477 #endif
01478 
01479 struct dahdi_pvt *round_robin[32];
01480 
01481 #if defined(HAVE_PRI)
01482 static inline int pri_grab(struct dahdi_pvt *pvt, struct dahdi_pri *pri)
01483 {
01484    int res;
01485    /* Grab the lock first */
01486    do {
01487       res = ast_mutex_trylock(&pri->lock);
01488       if (res) {
01489          DEADLOCK_AVOIDANCE(&pvt->lock);
01490       }
01491    } while (res);
01492    /* Then break the poll */
01493    if (pri->master != AST_PTHREADT_NULL)
01494       pthread_kill(pri->master, SIGURG);
01495    return 0;
01496 }
01497 #endif   /* defined(HAVE_PRI) */
01498 
01499 #if defined(HAVE_SS7)
01500 static inline void ss7_rel(struct dahdi_ss7 *ss7)
01501 {
01502    ast_mutex_unlock(&ss7->lock);
01503 }
01504 #endif   /* defined(HAVE_SS7) */
01505 
01506 #if defined(HAVE_SS7)
01507 static inline int ss7_grab(struct dahdi_pvt *pvt, struct dahdi_ss7 *pri)
01508 {
01509    int res;
01510    /* Grab the lock first */
01511    do {
01512       res = ast_mutex_trylock(&pri->lock);
01513       if (res) {
01514          DEADLOCK_AVOIDANCE(&pvt->lock);
01515       }
01516    } while (res);
01517    /* Then break the poll */
01518    if (pri->master != AST_PTHREADT_NULL)
01519       pthread_kill(pri->master, SIGURG);
01520    return 0;
01521 }
01522 #endif   /* defined(HAVE_SS7) */
01523 #define NUM_CADENCE_MAX 25
01524 static int num_cadence = 4;
01525 static int user_has_defined_cadences = 0;
01526 
01527 static struct dahdi_ring_cadence cadences[NUM_CADENCE_MAX] = {
01528    { { 125, 125, 2000, 4000 } },       /*!< Quick chirp followed by normal ring */
01529    { { 250, 250, 500, 1000, 250, 250, 500, 4000 } }, /*!< British style ring */
01530    { { 125, 125, 125, 125, 125, 4000 } }, /*!< Three short bursts */
01531    { { 1000, 500, 2500, 5000 } },   /*!< Long ring */
01532 };
01533 
01534 /*! \brief cidrings says in which pause to transmit the cid information, where the first pause
01535  * is 1, the second pause is 2 and so on.
01536  */
01537 
01538 static int cidrings[NUM_CADENCE_MAX] = {
01539    2,                            /*!< Right after first long ring */
01540    4,                            /*!< Right after long part */
01541    3,                            /*!< After third chirp */
01542    2,                            /*!< Second spell */
01543 };
01544 
01545 /* ETSI EN300 659-1 specifies the ring pulse between 200 and 300 mS */
01546 static struct dahdi_ring_cadence AS_RP_cadence = {{250, 10000}};
01547 
01548 #define ISTRUNK(p) ((p->sig == SIG_FXSLS) || (p->sig == SIG_FXSKS) || \
01549          (p->sig == SIG_FXSGS) || (p->sig == SIG_PRI))
01550 
01551 #define CANBUSYDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */)
01552 #define CANPROGRESSDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */)
01553 
01554 #define dahdi_get_index(ast, p, nullok)   _dahdi_get_index(ast, p, nullok, __PRETTY_FUNCTION__, __LINE__)
01555 static int _dahdi_get_index(struct ast_channel *ast, struct dahdi_pvt *p, int nullok, const char *fname, unsigned long line)
01556 {
01557    int res;
01558    if (p->subs[SUB_REAL].owner == ast)
01559       res = 0;
01560    else if (p->subs[SUB_CALLWAIT].owner == ast)
01561       res = 1;
01562    else if (p->subs[SUB_THREEWAY].owner == ast)
01563       res = 2;
01564    else {
01565       res = -1;
01566       if (!nullok)
01567          ast_log(LOG_WARNING,
01568             "Unable to get index for '%s' on channel %d (%s(), line %lu)\n",
01569             ast ? ast->name : "", p->channel, fname, line);
01570    }
01571    return res;
01572 }
01573 
01574 /*!
01575  * \internal
01576  * \brief Obtain the specified subchannel owner lock if the owner exists.
01577  *
01578  * \param pvt Channel private struct.
01579  * \param sub_idx Subchannel owner to lock.
01580  *
01581  * \note Assumes the pvt->lock is already obtained.
01582  *
01583  * \note
01584  * Because deadlock avoidance may have been necessary, you need to confirm
01585  * the state of things before continuing.
01586  *
01587  * \return Nothing
01588  */
01589 static void dahdi_lock_sub_owner(struct dahdi_pvt *pvt, int sub_idx)
01590 {
01591    for (;;) {
01592       if (!pvt->subs[sub_idx].owner) {
01593          /* No subchannel owner pointer */
01594          break;
01595       }
01596       if (!ast_channel_trylock(pvt->subs[sub_idx].owner)) {
01597          /* Got subchannel owner lock */
01598          break;
01599       }
01600       /* We must unlock the private to avoid the possibility of a deadlock */
01601       DEADLOCK_AVOIDANCE(&pvt->lock);
01602    }
01603 }
01604 
01605 static void wakeup_sub(struct dahdi_pvt *p, int a, struct dahdi_pri *pri)
01606 {
01607 #ifdef HAVE_PRI
01608    if (pri)
01609       ast_mutex_unlock(&pri->lock);
01610 #endif
01611    dahdi_lock_sub_owner(p, a);
01612    if (p->subs[a].owner) {
01613       ast_queue_frame(p->subs[a].owner, &ast_null_frame);
01614       ast_channel_unlock(p->subs[a].owner);
01615    }
01616 #ifdef HAVE_PRI
01617    if (pri)
01618       ast_mutex_lock(&pri->lock);
01619 #endif
01620 }
01621 
01622 static void dahdi_queue_frame(struct dahdi_pvt *p, struct ast_frame *f, void *data)
01623 {
01624 #ifdef HAVE_PRI
01625    struct dahdi_pri *pri = (struct dahdi_pri*) data;
01626 #endif
01627 #ifdef HAVE_SS7
01628    struct dahdi_ss7 *ss7 = (struct dahdi_ss7*) data;
01629 #endif
01630    /* We must unlock the PRI to avoid the possibility of a deadlock */
01631 #if defined(HAVE_PRI) || defined(HAVE_SS7)
01632    if (data) {
01633       switch (p->sig) {
01634 #ifdef HAVE_PRI
01635       case SIG_BRI:
01636       case SIG_BRI_PTMP:
01637       case SIG_PRI:
01638          ast_mutex_unlock(&pri->lock);
01639          break;
01640 #endif
01641 #ifdef HAVE_SS7
01642       case SIG_SS7:
01643          ast_mutex_unlock(&ss7->lock);
01644          break;
01645 #endif
01646       default:
01647          break;
01648       }
01649    }
01650 #endif
01651    for (;;) {
01652       if (p->owner) {
01653          if (ast_channel_trylock(p->owner)) {
01654             DEADLOCK_AVOIDANCE(&p->lock);
01655          } else {
01656             ast_queue_frame(p->owner, f);
01657             ast_channel_unlock(p->owner);
01658             break;
01659          }
01660       } else
01661          break;
01662    }
01663 #if defined(HAVE_PRI) || defined(HAVE_SS7)
01664    if (data) {
01665       switch (p->sig) {
01666 #ifdef HAVE_PRI
01667       case SIG_BRI:
01668       case SIG_BRI_PTMP:
01669       case SIG_PRI:
01670          ast_mutex_lock(&pri->lock);
01671          break;
01672 #endif
01673 #ifdef HAVE_SS7
01674       case SIG_SS7:
01675          ast_mutex_lock(&ss7->lock);
01676          break;
01677 #endif
01678       default:
01679          break;
01680       }
01681    }
01682 #endif
01683 }
01684 
01685 static struct ast_channel *dahdi_new(struct dahdi_pvt *, int, int, int, int, int);
01686 #ifdef HAVE_OPENR2
01687 
01688 static int dahdi_r2_answer(struct dahdi_pvt *p)
01689 {
01690    int res = 0;
01691    /* openr2 1.1.0 and older does not even define OR2_LIB_INTERFACE
01692    * and does not has support for openr2_chan_answer_call_with_mode
01693    *  */
01694 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
01695    const char *double_answer = pbx_builtin_getvar_helper(p->owner, "MFCR2_DOUBLE_ANSWER");
01696    int wants_double_answer = ast_true(double_answer) ? 1 : 0;
01697    if (!double_answer) {
01698       /* this still can result in double answer if the channel context
01699       * was configured that way */
01700       res = openr2_chan_answer_call(p->r2chan);
01701    } else if (wants_double_answer) {
01702       res = openr2_chan_answer_call_with_mode(p->r2chan, OR2_ANSWER_DOUBLE);
01703    } else {
01704       res = openr2_chan_answer_call_with_mode(p->r2chan, OR2_ANSWER_SIMPLE);
01705    }
01706 #else
01707    res = openr2_chan_answer_call(p->r2chan);
01708 #endif
01709    return res;
01710 }
01711 
01712 
01713 
01714 /* should be called with the ast_channel locked */
01715 static openr2_calling_party_category_t dahdi_r2_get_channel_category(struct ast_channel *c)
01716 {
01717    openr2_calling_party_category_t cat;
01718    const char *catstr = pbx_builtin_getvar_helper(c, "MFCR2_CATEGORY");
01719    struct dahdi_pvt *p = c->tech_pvt;
01720    if (ast_strlen_zero(catstr)) {
01721       ast_debug(1, "No MFC/R2 category specified for chan %s, using default %s\n",
01722             c->name, openr2_proto_get_category_string(p->mfcr2_category));
01723       return p->mfcr2_category;
01724    }
01725    if ((cat = openr2_proto_get_category(catstr)) == OR2_CALLING_PARTY_CATEGORY_UNKNOWN) {
01726       ast_log(LOG_WARNING, "Invalid category specified '%s' for chan %s, using default %s\n",
01727             catstr, c->name, openr2_proto_get_category_string(p->mfcr2_category));
01728       return p->mfcr2_category;
01729    }
01730    ast_debug(1, "Using category %s\n", catstr);
01731    return cat;
01732 }
01733 
01734 static void dahdi_r2_on_call_init(openr2_chan_t *r2chan)
01735 {
01736    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01737    ast_mutex_lock(&p->lock);
01738    if (p->mfcr2call) {
01739       ast_mutex_unlock(&p->lock);
01740       /* TODO: This can happen when some other thread just finished dahdi_request requesting this very same
01741          interface but has not yet seized the line (dahdi_call), and the far end wins and seize the line,
01742          can we avoid this somehow?, at this point when dahdi_call send the seize, it is likely that since
01743          the other end will see our seize as a forced release and drop the call, we will see an invalid
01744          pattern that will be seen and treated as protocol error. */
01745       ast_log(LOG_ERROR, "Collision of calls on chan %d detected!.\n", openr2_chan_get_number(r2chan));
01746       return;
01747    }
01748    p->mfcr2call = 1;
01749    /* better safe than sorry ... */
01750    p->cid_name[0] = '\0';
01751    p->cid_num[0] = '\0';
01752    p->rdnis[0] = '\0';
01753    p->exten[0] = '\0';
01754    p->mfcr2_ani_index = '\0';
01755    p->mfcr2_dnis_index = '\0';
01756    p->mfcr2_dnis_matched = 0;
01757    p->mfcr2_answer_pending = 0;
01758    p->mfcr2_call_accepted = 0;
01759    ast_mutex_unlock(&p->lock);
01760    ast_verbose("New MFC/R2 call detected on chan %d.\n", openr2_chan_get_number(r2chan));
01761 }
01762 
01763 static int get_alarms(struct dahdi_pvt *p);
01764 static void handle_alarms(struct dahdi_pvt *p, int alms);
01765 static void dahdi_r2_on_hardware_alarm(openr2_chan_t *r2chan, int alarm)
01766 {
01767    int res;
01768    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01769    ast_mutex_lock(&p->lock);
01770    p->inalarm = alarm ? 1 : 0;
01771    if (p->inalarm) {
01772       res = get_alarms(p);
01773       handle_alarms(p, res);
01774    } else {
01775       ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel);
01776       manager_event(EVENT_FLAG_SYSTEM, "AlarmClear", "Channel: %d\r\n", p->channel);
01777    }
01778    ast_mutex_unlock(&p->lock);
01779 }
01780 
01781 static void dahdi_r2_on_os_error(openr2_chan_t *r2chan, int errorcode)
01782 {
01783    ast_log(LOG_ERROR, "OS error on chan %d: %s\n", openr2_chan_get_number(r2chan), strerror(errorcode));
01784 }
01785 
01786 static void dahdi_r2_on_protocol_error(openr2_chan_t *r2chan, openr2_protocol_error_t reason)
01787 {
01788    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01789    ast_log(LOG_ERROR, "MFC/R2 protocol error on chan %d: %s\n", openr2_chan_get_number(r2chan), openr2_proto_get_error(reason));
01790    if (p->owner) {
01791       p->owner->hangupcause = AST_CAUSE_PROTOCOL_ERROR;
01792       p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
01793    }
01794    ast_mutex_lock(&p->lock);
01795    p->mfcr2call = 0;
01796    ast_mutex_unlock(&p->lock);
01797 }
01798 
01799 static void dahdi_r2_disconnect_call(struct dahdi_pvt *p, openr2_call_disconnect_cause_t cause)
01800 {
01801    if (openr2_chan_disconnect_call(p->r2chan, cause)) {
01802       ast_log(LOG_NOTICE, "Bad! failed to disconnect call on channel %d with reason %s, hope for the best!\n",
01803          p->channel, openr2_proto_get_disconnect_string(cause));
01804       /* force the chan to idle and release the call flag now since we will not see a clean on_call_end */
01805       openr2_chan_set_idle(p->r2chan);
01806       ast_mutex_lock(&p->lock);
01807       p->mfcr2call = 0;
01808       ast_mutex_unlock(&p->lock);
01809    }
01810 }
01811 
01812 static void dahdi_r2_on_call_offered(openr2_chan_t *r2chan, const char *ani, const char *dnis, openr2_calling_party_category_t category)
01813 {
01814    struct dahdi_pvt *p;
01815    struct ast_channel *c;
01816    ast_verbose("MFC/R2 call offered on chan %d. ANI = %s, DNIS = %s, Category = %s\n",
01817          openr2_chan_get_number(r2chan), ani ? ani : "(restricted)", dnis,
01818          openr2_proto_get_category_string(category));
01819    p = openr2_chan_get_client_data(r2chan);
01820    /* if collect calls are not allowed and this is a collect call, reject it! */
01821    if (!p->mfcr2_allow_collect_calls && category == OR2_CALLING_PARTY_CATEGORY_COLLECT_CALL) {
01822       ast_log(LOG_NOTICE, "Rejecting MFC/R2 collect call\n");
01823       dahdi_r2_disconnect_call(p, OR2_CAUSE_COLLECT_CALL_REJECTED);
01824       return;
01825    }
01826    ast_mutex_lock(&p->lock);
01827    p->mfcr2_recvd_category = category;
01828    /* if we're not supposed to use CID, clear whatever we have */
01829    if (!p->use_callerid) {
01830       ast_log(LOG_DEBUG, "No CID allowed in configuration, CID is being cleared!\n");
01831       p->cid_num[0] = 0;
01832       p->cid_name[0] = 0;
01833    }
01834    /* if we're supposed to answer immediately, clear DNIS and set 's' exten */
01835    if (p->immediate || !openr2_context_get_max_dnis(openr2_chan_get_context(r2chan))) {
01836       ast_log(LOG_DEBUG, "Setting exten => s because of immediate or 0 DNIS configured\n");
01837       p->exten[0] = 's';
01838       p->exten[1] = 0;
01839    }
01840    ast_mutex_unlock(&p->lock);
01841    if (!ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
01842       ast_log(LOG_NOTICE, "MFC/R2 call on channel %d requested non-existent extension '%s' in context '%s'. Rejecting call.\n",
01843             p->channel, p->exten, p->context);
01844       dahdi_r2_disconnect_call(p, OR2_CAUSE_UNALLOCATED_NUMBER);
01845       return;
01846    }
01847    if (!p->mfcr2_accept_on_offer) {
01848       /* The user wants us to start the PBX thread right away without accepting the call first */
01849       c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, 0);
01850       if (c) {
01851          /* Done here, don't disable reading now since we still need to generate MF tones to accept
01852             the call or reject it and detect the tone off condition of the other end, all of this
01853             will be done in the PBX thread now */
01854          return;
01855       }
01856       ast_log(LOG_WARNING, "Unable to create PBX channel in DAHDI channel %d\n", p->channel);
01857       dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER);
01858    } else if (p->mfcr2_charge_calls) {
01859       ast_log(LOG_DEBUG, "Accepting MFC/R2 call with charge on chan %d\n", p->channel);
01860       openr2_chan_accept_call(r2chan, OR2_CALL_WITH_CHARGE);
01861    } else {
01862       ast_log(LOG_DEBUG, "Accepting MFC/R2 call with no charge on chan %d\n", p->channel);
01863       openr2_chan_accept_call(r2chan, OR2_CALL_NO_CHARGE);
01864    }
01865 }
01866 
01867 static void dahdi_r2_on_call_end(openr2_chan_t *r2chan)
01868 {
01869    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01870    ast_verbose("MFC/R2 call end on channel %d\n", p->channel);
01871    ast_mutex_lock(&p->lock);
01872    p->mfcr2call = 0;
01873    ast_mutex_unlock(&p->lock);
01874 }
01875 
01876 static void dahdi_enable_ec(struct dahdi_pvt *p);
01877 static void dahdi_r2_on_call_accepted(openr2_chan_t *r2chan, openr2_call_mode_t mode)
01878 {
01879    struct dahdi_pvt *p = NULL;
01880    struct ast_channel *c = NULL;
01881    p = openr2_chan_get_client_data(r2chan);
01882    dahdi_enable_ec(p);
01883    p->mfcr2_call_accepted = 1;
01884    /* if it's an incoming call ... */
01885    if (OR2_DIR_BACKWARD == openr2_chan_get_direction(r2chan)) {
01886       ast_verbose("MFC/R2 call has been accepted on backward channel %d\n", openr2_chan_get_number(r2chan));
01887       /* If accept on offer is not set, it means at this point the PBX thread is already
01888          launched (was launched in the 'on call offered' handler) and therefore this callback
01889          is being executed already in the PBX thread rather than the monitor thread, don't launch
01890          any other thread, just disable the openr2 reading and answer the call if needed */
01891       if (!p->mfcr2_accept_on_offer) {
01892          openr2_chan_disable_read(r2chan);
01893          if (p->mfcr2_answer_pending) {
01894             ast_log(LOG_DEBUG, "Answering MFC/R2 call after accepting it on chan %d\n", openr2_chan_get_number(r2chan));
01895             dahdi_r2_answer(p);
01896          }
01897          return;
01898       }
01899       c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, 0);
01900       if (c) {
01901          /* chan_dahdi will take care of reading from now on in the PBX thread, tell the
01902             library to forget about it */
01903          openr2_chan_disable_read(r2chan);
01904          return;
01905       }
01906       ast_log(LOG_WARNING, "Unable to create PBX channel in DAHDI channel %d\n", p->channel);
01907       /* failed to create the channel, bail out and report it as an out of order line */
01908       dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER);
01909       return;
01910    }
01911    /* this is an outgoing call, no need to launch the PBX thread, most likely we're in one already */
01912    ast_verbose("MFC/R2 call has been accepted on forward channel %d\n", p->channel);
01913    p->subs[SUB_REAL].needringing = 1;
01914    p->dialing = 0;
01915    /* chan_dahdi will take care of reading from now on in the PBX thread, tell the library to forget about it */
01916    openr2_chan_disable_read(r2chan);
01917 }
01918 
01919 static void dahdi_r2_on_call_answered(openr2_chan_t *r2chan)
01920 {
01921    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01922    ast_verbose("MFC/R2 call has been answered on channel %d\n", openr2_chan_get_number(r2chan));
01923    p->subs[SUB_REAL].needanswer = 1;
01924 }
01925 
01926 static void dahdi_r2_on_call_read(openr2_chan_t *r2chan, const unsigned char *buf, int buflen)
01927 {
01928    /*ast_log(LOG_DEBUG, "Read data from dahdi channel %d\n", openr2_chan_get_number(r2chan));*/
01929 }
01930 
01931 static int dahdi_r2_cause_to_ast_cause(openr2_call_disconnect_cause_t cause)
01932 {
01933    switch (cause) {
01934    case OR2_CAUSE_BUSY_NUMBER:
01935       return AST_CAUSE_BUSY;
01936    case OR2_CAUSE_NETWORK_CONGESTION:
01937       return AST_CAUSE_CONGESTION;
01938    case OR2_CAUSE_OUT_OF_ORDER:
01939       return AST_CAUSE_DESTINATION_OUT_OF_ORDER;
01940    case OR2_CAUSE_UNALLOCATED_NUMBER:
01941       return AST_CAUSE_UNREGISTERED;
01942    case OR2_CAUSE_NO_ANSWER:
01943       return AST_CAUSE_NO_ANSWER;
01944    case OR2_CAUSE_NORMAL_CLEARING:
01945       return AST_CAUSE_NORMAL_CLEARING;
01946    case OR2_CAUSE_UNSPECIFIED:
01947    default:
01948       return AST_CAUSE_NOTDEFINED;
01949    }
01950 }
01951 
01952 static void dahdi_r2_on_call_disconnect(openr2_chan_t *r2chan, openr2_call_disconnect_cause_t cause)
01953 {
01954    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01955    ast_verbose("MFC/R2 call disconnected on channel %d\n", openr2_chan_get_number(r2chan));
01956    ast_mutex_lock(&p->lock);
01957    if (!p->owner) {
01958       ast_mutex_unlock(&p->lock);
01959       /* no owner, therefore we can't use dahdi_hangup to disconnect, do it right now */
01960       dahdi_r2_disconnect_call(p, OR2_CAUSE_NORMAL_CLEARING);
01961       return;
01962    }
01963    /* when we have an owner we don't call dahdi_r2_disconnect_call here, that will
01964       be done in dahdi_hangup */
01965    if (p->owner->_state == AST_STATE_UP) {
01966       p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
01967       ast_mutex_unlock(&p->lock);
01968    } else if (openr2_chan_get_direction(r2chan) == OR2_DIR_FORWARD) {
01969       /* being the forward side we must report what happened to the call to whoever requested it */
01970       switch (cause) {
01971       case OR2_CAUSE_BUSY_NUMBER:
01972          p->subs[SUB_REAL].needbusy = 1;
01973          break;
01974       case OR2_CAUSE_NETWORK_CONGESTION:
01975       case OR2_CAUSE_OUT_OF_ORDER:
01976       case OR2_CAUSE_UNALLOCATED_NUMBER:
01977       case OR2_CAUSE_NO_ANSWER:
01978       case OR2_CAUSE_UNSPECIFIED:
01979       case OR2_CAUSE_NORMAL_CLEARING:
01980          p->subs[SUB_REAL].needcongestion = 1;
01981          break;
01982       default:
01983          p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
01984       }
01985       ast_mutex_unlock(&p->lock);
01986    } else {
01987       ast_mutex_unlock(&p->lock);
01988       /* being the backward side and not UP yet, we only need to request hangup */
01989       /* TODO: what about doing this same thing when were AST_STATE_UP? */
01990       ast_queue_hangup_with_cause(p->owner, dahdi_r2_cause_to_ast_cause(cause));
01991    }
01992 }
01993 
01994 static void dahdi_r2_write_log(openr2_log_level_t level, char *logmessage)
01995 {
01996    switch (level) {
01997    case OR2_LOG_NOTICE:
01998       ast_verbose("%s", logmessage);
01999       break;
02000    case OR2_LOG_WARNING:
02001       ast_log(LOG_WARNING, "%s", logmessage);
02002       break;
02003    case OR2_LOG_ERROR:
02004       ast_log(LOG_ERROR, "%s", logmessage);
02005       break;
02006    case OR2_LOG_STACK_TRACE:
02007    case OR2_LOG_MF_TRACE:
02008    case OR2_LOG_CAS_TRACE:
02009    case OR2_LOG_DEBUG:
02010    case OR2_LOG_EX_DEBUG:
02011       ast_log(LOG_DEBUG, "%s", logmessage);
02012       break;
02013    default:
02014       ast_log(LOG_WARNING, "We should handle logging level %d here.\n", level);
02015       ast_log(LOG_DEBUG, "%s", logmessage);
02016       break;
02017    }
02018 }
02019 
02020 static void dahdi_r2_on_line_blocked(openr2_chan_t *r2chan)
02021 {
02022    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
02023    ast_mutex_lock(&p->lock);
02024    p->remotelyblocked = 1;
02025    ast_mutex_unlock(&p->lock);
02026    ast_log(LOG_NOTICE, "Far end blocked on chan %d\n", openr2_chan_get_number(r2chan));
02027 }
02028 
02029 static void dahdi_r2_on_line_idle(openr2_chan_t *r2chan)
02030 {
02031    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
02032    ast_mutex_lock(&p->lock);
02033    p->remotelyblocked = 0;
02034    ast_mutex_unlock(&p->lock);
02035    ast_log(LOG_NOTICE, "Far end unblocked on chan %d\n", openr2_chan_get_number(r2chan));
02036 }
02037 
02038 static void dahdi_r2_on_context_log(openr2_context_t *r2context, openr2_log_level_t level, const char *fmt, va_list ap)
02039    __attribute__((format (printf, 3, 0)));
02040 static void dahdi_r2_on_context_log(openr2_context_t *r2context, openr2_log_level_t level, const char *fmt, va_list ap)
02041 {
02042 #define CONTEXT_TAG "Context - "
02043    char logmsg[256];
02044    char completemsg[sizeof(logmsg) + sizeof(CONTEXT_TAG) - 1];
02045    vsnprintf(logmsg, sizeof(logmsg), fmt, ap);
02046    snprintf(completemsg, sizeof(completemsg), CONTEXT_TAG "%s", logmsg);
02047    dahdi_r2_write_log(level, completemsg);
02048 #undef CONTEXT_TAG
02049 }
02050 
02051 static void dahdi_r2_on_chan_log(openr2_chan_t *r2chan, openr2_log_level_t level, const char *fmt, va_list ap)
02052    __attribute__((format (printf, 3, 0)));
02053 static void dahdi_r2_on_chan_log(openr2_chan_t *r2chan, openr2_log_level_t level, const char *fmt, va_list ap)
02054 {
02055 #define CHAN_TAG "Chan "
02056    char logmsg[256];
02057    char completemsg[sizeof(logmsg) + sizeof(CHAN_TAG) - 1];
02058    vsnprintf(logmsg, sizeof(logmsg), fmt, ap);
02059    snprintf(completemsg, sizeof(completemsg), CHAN_TAG "%d - %s", openr2_chan_get_number(r2chan), logmsg);
02060    dahdi_r2_write_log(level, completemsg);
02061 }
02062 
02063 static int dahdi_r2_on_dnis_digit_received(openr2_chan_t *r2chan, char digit)
02064 {
02065    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
02066    /* if 'immediate' is set, let's stop requesting DNIS */
02067    if (p->immediate) {
02068       return 0;
02069    }
02070    p->exten[p->mfcr2_dnis_index] = digit;
02071    p->rdnis[p->mfcr2_dnis_index] = digit;
02072    p->mfcr2_dnis_index++;
02073    p->exten[p->mfcr2_dnis_index] = 0;
02074    p->rdnis[p->mfcr2_dnis_index] = 0;
02075    /* if the DNIS is a match and cannot match more, stop requesting DNIS */
02076    if ((p->mfcr2_dnis_matched ||
02077        (ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num) && (p->mfcr2_dnis_matched = 1))) &&
02078        !ast_matchmore_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
02079       return 0;
02080    }
02081    /* otherwise keep going */
02082    return 1;
02083 }
02084 
02085 static void dahdi_r2_on_ani_digit_received(openr2_chan_t *r2chan, char digit)
02086 {
02087    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
02088    p->cid_num[p->mfcr2_ani_index] = digit;
02089    p->cid_name[p->mfcr2_ani_index] = digit;
02090    p->mfcr2_ani_index++;
02091    p->cid_num[p->mfcr2_ani_index] = 0;
02092    p->cid_name[p->mfcr2_ani_index] = 0;
02093 }
02094 
02095 static void dahdi_r2_on_billing_pulse_received(openr2_chan_t *r2chan)
02096 {
02097    ast_verbose("MFC/R2 billing pulse received on channel %d\n", openr2_chan_get_number(r2chan));
02098 }
02099 
02100 static openr2_event_interface_t dahdi_r2_event_iface = {
02101    .on_call_init = dahdi_r2_on_call_init,
02102    .on_call_offered = dahdi_r2_on_call_offered,
02103    .on_call_accepted = dahdi_r2_on_call_accepted,
02104    .on_call_answered = dahdi_r2_on_call_answered,
02105    .on_call_disconnect = dahdi_r2_on_call_disconnect,
02106    .on_call_end = dahdi_r2_on_call_end,
02107    .on_call_read = dahdi_r2_on_call_read,
02108    .on_hardware_alarm = dahdi_r2_on_hardware_alarm,
02109    .on_os_error = dahdi_r2_on_os_error,
02110    .on_protocol_error = dahdi_r2_on_protocol_error,
02111    .on_line_blocked = dahdi_r2_on_line_blocked,
02112    .on_line_idle = dahdi_r2_on_line_idle,
02113    /* cast seems to be needed to get rid of the annoying warning regarding format attribute  */
02114    .on_context_log = (openr2_handle_context_logging_func)dahdi_r2_on_context_log,
02115    .on_dnis_digit_received = dahdi_r2_on_dnis_digit_received,
02116    .on_ani_digit_received = dahdi_r2_on_ani_digit_received,
02117    /* so far we do nothing with billing pulses */
02118    .on_billing_pulse_received = dahdi_r2_on_billing_pulse_received
02119 };
02120 
02121 static inline int16_t dahdi_r2_alaw_to_linear(uint8_t sample)
02122 {
02123    return AST_ALAW(sample);
02124 }
02125 
02126 static inline uint8_t dahdi_r2_linear_to_alaw(int sample)
02127 {
02128    return AST_LIN2A(sample);
02129 }
02130 
02131 static openr2_transcoder_interface_t dahdi_r2_transcode_iface = {
02132    dahdi_r2_alaw_to_linear,
02133    dahdi_r2_linear_to_alaw
02134 };
02135 
02136 #endif /* HAVE_OPENR2 */
02137 
02138 static int restore_gains(struct dahdi_pvt *p);
02139 
02140 static void swap_subs(struct dahdi_pvt *p, int a, int b)
02141 {
02142    int tchan;
02143    int tinthreeway;
02144    struct ast_channel *towner;
02145 
02146    ast_debug(1, "Swapping %d and %d\n", a, b);
02147 
02148    tchan = p->subs[a].chan;
02149    towner = p->subs[a].owner;
02150    tinthreeway = p->subs[a].inthreeway;
02151 
02152    p->subs[a].chan = p->subs[b].chan;
02153    p->subs[a].owner = p->subs[b].owner;
02154    p->subs[a].inthreeway = p->subs[b].inthreeway;
02155 
02156    p->subs[b].chan = tchan;
02157    p->subs[b].owner = towner;
02158    p->subs[b].inthreeway = tinthreeway;
02159 
02160    if (p->subs[a].owner)
02161       ast_channel_set_fd(p->subs[a].owner, 0, p->subs[a].dfd);
02162    if (p->subs[b].owner)
02163       ast_channel_set_fd(p->subs[b].owner, 0, p->subs[b].dfd);
02164    wakeup_sub(p, a, NULL);
02165    wakeup_sub(p, b, NULL);
02166 }
02167 
02168 static int dahdi_open(char *fn)
02169 {
02170    int fd;
02171    int isnum;
02172    int chan = 0;
02173    int bs;
02174    int x;
02175    isnum = 1;
02176    for (x = 0; x < strlen(fn); x++) {
02177       if (!isdigit(fn[x])) {
02178          isnum = 0;
02179          break;
02180       }
02181    }
02182    if (isnum) {
02183       chan = atoi(fn);
02184       if (chan < 1) {
02185          ast_log(LOG_WARNING, "Invalid channel number '%s'\n", fn);
02186          return -1;
02187       }
02188       fn = "/dev/dahdi/channel";
02189    }
02190    fd = open(fn, O_RDWR | O_NONBLOCK);
02191    if (fd < 0) {
02192       ast_log(LOG_WARNING, "Unable to open '%s': %s\n", fn, strerror(errno));
02193       return -1;
02194    }
02195    if (chan) {
02196       if (ioctl(fd, DAHDI_SPECIFY, &chan)) {
02197          x = errno;
02198          close(fd);
02199          errno = x;
02200          ast_log(LOG_WARNING, "Unable to specify channel %d: %s\n", chan, strerror(errno));
02201          return -1;
02202       }
02203    }
02204    bs = READ_SIZE;
02205    if (ioctl(fd, DAHDI_SET_BLOCKSIZE, &bs) == -1) {
02206       ast_log(LOG_WARNING, "Unable to set blocksize '%d': %s\n", bs,  strerror(errno));
02207       x = errno;
02208       close(fd);
02209       errno = x;
02210       return -1;
02211    }
02212    return fd;
02213 }
02214 
02215 static void dahdi_close(int fd)
02216 {
02217    if (fd > 0)
02218       close(fd);
02219 }
02220 
02221 static void dahdi_close_sub(struct dahdi_pvt *chan_pvt, int sub_num)
02222 {
02223    dahdi_close(chan_pvt->subs[sub_num].dfd);
02224    chan_pvt->subs[sub_num].dfd = -1;
02225 }
02226 
02227 #if defined(HAVE_PRI)
02228 static void dahdi_close_pri_fd(struct dahdi_pri *pri, int fd_num)
02229 {
02230    dahdi_close(pri->fds[fd_num]);
02231    pri->fds[fd_num] = -1;
02232 }
02233 #endif   /* defined(HAVE_PRI) */
02234 
02235 #if defined(HAVE_SS7)
02236 static void dahdi_close_ss7_fd(struct dahdi_ss7 *ss7, int fd_num)
02237 {
02238    dahdi_close(ss7->fds[fd_num]);
02239    ss7->fds[fd_num] = -1;
02240 }
02241 #endif   /* defined(HAVE_SS7) */
02242 
02243 static int dahdi_setlinear(int dfd, int linear)
02244 {
02245    int res;
02246    res = ioctl(dfd, DAHDI_SETLINEAR, &linear);
02247    if (res)
02248       return res;
02249    return 0;
02250 }
02251 
02252 
02253 static int alloc_sub(struct dahdi_pvt *p, int x)
02254 {
02255    struct dahdi_bufferinfo bi;
02256    int res;
02257    if (p->subs[x].dfd >= 0) {
02258       ast_log(LOG_WARNING, "%s subchannel of %d already in use\n", subnames[x], p->channel);
02259       return -1;
02260    }
02261 
02262    p->subs[x].dfd = dahdi_open("/dev/dahdi/pseudo");
02263    if (p->subs[x].dfd <= -1) {
02264       ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno));
02265       return -1;
02266    }
02267 
02268    res = ioctl(p->subs[x].dfd, DAHDI_GET_BUFINFO, &bi);
02269    if (!res) {
02270       bi.txbufpolicy = p->buf_policy;
02271       bi.rxbufpolicy = p->buf_policy;
02272       bi.numbufs = p->buf_no;
02273       res = ioctl(p->subs[x].dfd, DAHDI_SET_BUFINFO, &bi);
02274       if (res < 0) {
02275          ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", x, strerror(errno));
02276       }
02277    } else
02278       ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", x, strerror(errno));
02279 
02280    if (ioctl(p->subs[x].dfd, DAHDI_CHANNO, &p->subs[x].chan) == 1) {
02281       ast_log(LOG_WARNING, "Unable to get channel number for pseudo channel on FD %d: %s\n", p->subs[x].dfd, strerror(errno));
02282       dahdi_close_sub(p, x);
02283       p->subs[x].dfd = -1;
02284       return -1;
02285    }
02286    ast_debug(1, "Allocated %s subchannel on FD %d channel %d\n", subnames[x], p->subs[x].dfd, p->subs[x].chan);
02287    return 0;
02288 }
02289 
02290 static int unalloc_sub(struct dahdi_pvt *p, int x)
02291 {
02292    if (!x) {
02293       ast_log(LOG_WARNING, "Trying to unalloc the real channel %d?!?\n", p->channel);
02294       return -1;
02295    }
02296    ast_debug(1, "Released sub %d of channel %d\n", x, p->channel);
02297    dahdi_close_sub(p, x);
02298    p->subs[x].linear = 0;
02299    p->subs[x].chan = 0;
02300    p->subs[x].owner = NULL;
02301    p->subs[x].inthreeway = 0;
02302    p->polarity = POLARITY_IDLE;
02303    memset(&p->subs[x].curconf, 0, sizeof(p->subs[x].curconf));
02304    return 0;
02305 }
02306 
02307 static int digit_to_dtmfindex(char digit)
02308 {
02309    if (isdigit(digit))
02310       return DAHDI_TONE_DTMF_BASE + (digit - '0');
02311    else if (digit >= 'A' && digit <= 'D')
02312       return DAHDI_TONE_DTMF_A + (digit - 'A');
02313    else if (digit >= 'a' && digit <= 'd')
02314       return DAHDI_TONE_DTMF_A + (digit - 'a');
02315    else if (digit == '*')
02316       return DAHDI_TONE_DTMF_s;
02317    else if (digit == '#')
02318       return DAHDI_TONE_DTMF_p;
02319    else
02320       return -1;
02321 }
02322 
02323 static int dahdi_digit_begin(struct ast_channel *chan, char digit)
02324 {
02325    struct dahdi_pvt *pvt;
02326    int idx;
02327    int dtmf = -1;
02328 
02329    pvt = chan->tech_pvt;
02330 
02331    ast_mutex_lock(&pvt->lock);
02332 
02333    idx = dahdi_get_index(chan, pvt, 0);
02334 
02335    if ((idx != SUB_REAL) || !pvt->owner)
02336       goto out;
02337 
02338 #ifdef HAVE_PRI
02339    if (((pvt->sig == SIG_PRI) || (pvt->sig == SIG_BRI) || (pvt->sig == SIG_BRI_PTMP))
02340       && chan->_state == AST_STATE_DIALING) {
02341       if (pvt->call_level < DAHDI_CALL_LEVEL_OVERLAP) {
02342          unsigned int len;
02343 
02344          len = strlen(pvt->dialdest);
02345          if (len < sizeof(pvt->dialdest) - 1) {
02346             ast_debug(1, "Queueing digit '%c' since setup_ack not yet received\n",
02347                digit);
02348             pvt->dialdest[len++] = digit;
02349             pvt->dialdest[len] = '\0';
02350          } else {
02351             ast_log(LOG_WARNING,
02352                "Span %d: Deferred digit buffer overflow for digit '%c'.\n",
02353                pvt->span, digit);
02354          }
02355          goto out;
02356       }
02357       if (pvt->call_level < DAHDI_CALL_LEVEL_PROCEEDING) {
02358          if (!pri_grab(pvt, pvt->pri)) {
02359             pri_information(pvt->pri->pri, pvt->call, digit);
02360             pri_rel(pvt->pri);
02361          } else {
02362             ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", pvt->span);
02363          }
02364          goto out;
02365       }
02366       if (pvt->call_level < DAHDI_CALL_LEVEL_CONNECT) {
02367          ast_log(LOG_WARNING,
02368             "Span %d: Digit '%c' may be ignored by peer. (Call level:%d)\n",
02369             pvt->span, digit, pvt->call_level);
02370       }
02371    }
02372 #endif
02373    if ((dtmf = digit_to_dtmfindex(digit)) == -1)
02374       goto out;
02375 
02376    if (pvt->pulse || ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &dtmf)) {
02377       int res;
02378       struct dahdi_dialoperation zo = {
02379          .op = DAHDI_DIAL_OP_APPEND,
02380       };
02381 
02382       zo.dialstr[0] = 'T';
02383       zo.dialstr[1] = digit;
02384       zo.dialstr[2] = '\0';
02385       if ((res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo)))
02386          ast_log(LOG_WARNING, "Couldn't dial digit %c: %s\n", digit, strerror(errno));
02387       else
02388          pvt->dialing = 1;
02389    } else {
02390       ast_debug(1, "Started VLDTMF digit '%c'\n", digit);
02391       pvt->dialing = 1;
02392       pvt->begindigit = digit;
02393    }
02394 
02395 out:
02396    ast_mutex_unlock(&pvt->lock);
02397 
02398    return 0;
02399 }
02400 
02401 static int dahdi_digit_end(struct ast_channel *chan, char digit, unsigned int duration)
02402 {
02403    struct dahdi_pvt *pvt;
02404    int res = 0;
02405    int idx;
02406    int x;
02407 
02408    pvt = chan->tech_pvt;
02409 
02410    ast_mutex_lock(&pvt->lock);
02411 
02412    idx = dahdi_get_index(chan, pvt, 0);
02413 
02414    if ((idx != SUB_REAL) || !pvt->owner || pvt->pulse)
02415       goto out;
02416 
02417 #ifdef HAVE_PRI
02418    /* This means that the digit was already sent via PRI signalling */
02419    if (((pvt->sig == SIG_PRI) || (pvt->sig == SIG_BRI) || (pvt->sig == SIG_BRI_PTMP))
02420          && !pvt->begindigit)
02421       goto out;
02422 #endif
02423 
02424    if (pvt->begindigit) {
02425       x = -1;
02426       ast_debug(1, "Ending VLDTMF digit '%c'\n", digit);
02427       res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &x);
02428       pvt->dialing = 0;
02429       pvt->begindigit = 0;
02430    }
02431 
02432 out:
02433    ast_mutex_unlock(&pvt->lock);
02434 
02435    return res;
02436 }
02437 
02438 static char *events[] = {
02439    "No event",
02440    "On hook",
02441    "Ring/Answered",
02442    "Wink/Flash",
02443    "Alarm",
02444    "No more alarm",
02445    "HDLC Abort",
02446    "HDLC Overrun",
02447    "HDLC Bad FCS",
02448    "Dial Complete",
02449    "Ringer On",
02450    "Ringer Off",
02451    "Hook Transition Complete",
02452    "Bits Changed",
02453    "Pulse Start",
02454    "Timer Expired",
02455    "Timer Ping",
02456    "Polarity Reversal",
02457    "Ring Begin",
02458 };
02459 
02460 static struct {
02461    int alarm;
02462    char *name;
02463 } alarms[] = {
02464    { DAHDI_ALARM_RED, "Red Alarm" },
02465    { DAHDI_ALARM_YELLOW, "Yellow Alarm" },
02466    { DAHDI_ALARM_BLUE, "Blue Alarm" },
02467    { DAHDI_ALARM_RECOVER, "Recovering" },
02468    { DAHDI_ALARM_LOOPBACK, "Loopback" },
02469    { DAHDI_ALARM_NOTOPEN, "Not Open" },
02470    { DAHDI_ALARM_NONE, "None" },
02471 };
02472 
02473 static char *alarm2str(int alm)
02474 {
02475    int x;
02476    for (x = 0; x < ARRAY_LEN(alarms); x++) {
02477       if (alarms[x].alarm & alm)
02478          return alarms[x].name;
02479    }
02480    return alm ? "Unknown Alarm" : "No Alarm";
02481 }
02482 
02483 static char *event2str(int event)
02484 {
02485    static char buf[256];
02486    if ((event < (ARRAY_LEN(events))) && (event > -1))
02487       return events[event];
02488    sprintf(buf, "Event %d", event); /* safe */
02489    return buf;
02490 }
02491 
02492 #ifdef HAVE_PRI
02493 static char *dialplan2str(int dialplan)
02494 {
02495    if (dialplan == -1 || dialplan == -2) {
02496       return("Dynamically set dialplan in ISDN");
02497    }
02498    return (pri_plan2str(dialplan));
02499 }
02500 #endif
02501 
02502 static char *dahdi_sig2str(int sig)
02503 {
02504    static char buf[256];
02505    switch (sig) {
02506    case SIG_EM:
02507       return "E & M Immediate";
02508    case SIG_EMWINK:
02509       return "E & M Wink";
02510    case SIG_EM_E1:
02511       return "E & M E1";
02512    case SIG_FEATD:
02513       return "Feature Group D (DTMF)";
02514    case SIG_FEATDMF:
02515       return "Feature Group D (MF)";
02516    case SIG_FEATDMF_TA:
02517       return "Feature Groud D (MF) Tandem Access";
02518    case SIG_FEATB:
02519       return "Feature Group B (MF)";
02520    case SIG_E911:
02521       return "E911 (MF)";
02522    case SIG_FGC_CAMA:
02523       return "FGC/CAMA (Dialpulse)";
02524    case SIG_FGC_CAMAMF:
02525       return "FGC/CAMA (MF)";
02526    case SIG_FXSLS:
02527       return "FXS Loopstart";
02528    case SIG_FXSGS:
02529       return "FXS Groundstart";
02530    case SIG_FXSKS:
02531       return "FXS Kewlstart";
02532    case SIG_FXOLS:
02533       return "FXO Loopstart";
02534    case SIG_FXOGS:
02535       return "FXO Groundstart";
02536    case SIG_FXOKS:
02537       return "FXO Kewlstart";
02538    case SIG_PRI:
02539       return "ISDN PRI";
02540    case SIG_BRI:
02541       return "ISDN BRI Point to Point";
02542    case SIG_BRI_PTMP:
02543       return "ISDN BRI Point to MultiPoint";
02544    case SIG_SS7:
02545       return "SS7";
02546    case SIG_MFCR2:
02547       return "MFC/R2";
02548    case SIG_SF:
02549       return "SF (Tone) Immediate";
02550    case SIG_SFWINK:
02551       return "SF (Tone) Wink";
02552    case SIG_SF_FEATD:
02553       return "SF (Tone) with Feature Group D (DTMF)";
02554    case SIG_SF_FEATDMF:
02555       return "SF (Tone) with Feature Group D (MF)";
02556    case SIG_SF_FEATB:
02557       return "SF (Tone) with Feature Group B (MF)";
02558    case SIG_GR303FXOKS:
02559       return "GR-303 with FXOKS";
02560    case SIG_GR303FXSKS:
02561       return "GR-303 with FXSKS";
02562    case 0:
02563       return "Pseudo";
02564    default:
02565       snprintf(buf, sizeof(buf), "Unknown signalling %d", sig);
02566       return buf;
02567    }
02568 }
02569 
02570 #define sig2str dahdi_sig2str
02571 
02572 static int conf_add(struct dahdi_pvt *p, struct dahdi_subchannel *c, int idx, int slavechannel)
02573 {
02574    /* If the conference already exists, and we're already in it
02575       don't bother doing anything */
02576    struct dahdi_confinfo zi;
02577 
02578    memset(&zi, 0, sizeof(zi));
02579    zi.chan = 0;
02580 
02581    if (slavechannel > 0) {
02582       /* If we have only one slave, do a digital mon */
02583       zi.confmode = DAHDI_CONF_DIGITALMON;
02584       zi.confno = slavechannel;
02585    } else {
02586       if (!idx) {
02587          /* Real-side and pseudo-side both participate in conference */
02588          zi.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER |
02589             DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER;
02590       } else
02591          zi.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER;
02592       zi.confno = p->confno;
02593    }
02594    if ((zi.confno == c->curconf.confno) && (zi.confmode == c->curconf.confmode))
02595       return 0;
02596    if (c->dfd < 0)
02597       return 0;
02598    if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
02599       ast_log(LOG_WARNING, "Failed to add %d to conference %d/%d: %s\n", c->dfd, zi.confmode, zi.confno, strerror(errno));
02600       return -1;
02601    }
02602    if (slavechannel < 1) {
02603       p->confno = zi.confno;
02604    }
02605    memcpy(&c->curconf, &zi, sizeof(c->curconf));
02606    ast_debug(1, "Added %d to conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
02607    return 0;
02608 }
02609 
02610 static int isourconf(struct dahdi_pvt *p, struct dahdi_subchannel *c)
02611 {
02612    /* If they're listening to our channel, they're ours */
02613    if ((p->channel == c->curconf.confno) && (c->curconf.confmode == DAHDI_CONF_DIGITALMON))
02614       return 1;
02615    /* If they're a talker on our (allocated) conference, they're ours */
02616    if ((p->confno > 0) && (p->confno == c->curconf.confno) && (c->curconf.confmode & DAHDI_CONF_TALKER))
02617       return 1;
02618    return 0;
02619 }
02620 
02621 static int conf_del(struct dahdi_pvt *p, struct dahdi_subchannel *c, int idx)
02622 {
02623    struct dahdi_confinfo zi;
02624    if (/* Can't delete if there's no dfd */
02625       (c->dfd < 0) ||
02626       /* Don't delete from the conference if it's not our conference */
02627       !isourconf(p, c)
02628       /* Don't delete if we don't think it's conferenced at all (implied) */
02629       ) return 0;
02630    memset(&zi, 0, sizeof(zi));
02631    if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
02632       ast_log(LOG_WARNING, "Failed to drop %d from conference %d/%d: %s\n", c->dfd, c->curconf.confmode, c->curconf.confno, strerror(errno));
02633       return -1;
02634    }
02635    ast_debug(1, "Removed %d from conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
02636    memcpy(&c->curconf, &zi, sizeof(c->curconf));
02637    return 0;
02638 }
02639 
02640 static int isslavenative(struct dahdi_pvt *p, struct dahdi_pvt **out)
02641 {
02642    int x;
02643    int useslavenative;
02644    struct dahdi_pvt *slave = NULL;
02645    /* Start out optimistic */
02646    useslavenative = 1;
02647    /* Update conference state in a stateless fashion */
02648    for (x = 0; x < 3; x++) {
02649       /* Any three-way calling makes slave native mode *definitely* out
02650          of the question */
02651       if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway)
02652          useslavenative = 0;
02653    }
02654    /* If we don't have any 3-way calls, check to see if we have
02655       precisely one slave */
02656    if (useslavenative) {
02657       for (x = 0; x < MAX_SLAVES; x++) {
02658          if (p->slaves[x]) {
02659             if (slave) {
02660                /* Whoops already have a slave!  No
02661                   slave native and stop right away */
02662                slave = NULL;
02663                useslavenative = 0;
02664                break;
02665             } else {
02666                /* We have one slave so far */
02667                slave = p->slaves[x];
02668             }
02669          }
02670       }
02671    }
02672    /* If no slave, slave native definitely out */
02673    if (!slave)
02674       useslavenative = 0;
02675    else if (slave->law != p->law) {
02676       useslavenative = 0;
02677       slave = NULL;
02678    }
02679    if (out)
02680       *out = slave;
02681    return useslavenative;
02682 }
02683 
02684 static int reset_conf(struct dahdi_pvt *p)
02685 {
02686    p->confno = -1;
02687    memset(&p->subs[SUB_REAL].curconf, 0, sizeof(p->subs[SUB_REAL].curconf));
02688    if (p->subs[SUB_REAL].dfd > -1) {
02689       struct dahdi_confinfo zi;
02690 
02691       memset(&zi, 0, sizeof(zi));
02692       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &zi))
02693          ast_log(LOG_WARNING, "Failed to reset conferencing on channel %d: %s\n", p->channel, strerror(errno));
02694    }
02695    return 0;
02696 }
02697 
02698 static int update_conf(struct dahdi_pvt *p)
02699 {
02700    int needconf = 0;
02701    int x;
02702    int useslavenative;
02703    struct dahdi_pvt *slave = NULL;
02704 
02705    useslavenative = isslavenative(p, &slave);
02706    /* Start with the obvious, general stuff */
02707    for (x = 0; x < 3; x++) {
02708       /* Look for three way calls */
02709       if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) {
02710          conf_add(p, &p->subs[x], x, 0);
02711          needconf++;
02712       } else {
02713          conf_del(p, &p->subs[x], x);
02714       }
02715    }
02716    /* If we have a slave, add him to our conference now. or DAX
02717       if this is slave native */
02718    for (x = 0; x < MAX_SLAVES; x++) {
02719       if (p->slaves[x]) {
02720          if (useslavenative)
02721             conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
02722          else {
02723             conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
02724             needconf++;
02725          }
02726       }
02727    }
02728    /* If we're supposed to be in there, do so now */
02729    if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
02730       if (useslavenative)
02731          conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
02732       else {
02733          conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
02734          needconf++;
02735       }
02736    }
02737    /* If we have a master, add ourselves to his conference */
02738    if (p->master) {
02739       if (isslavenative(p->master, NULL)) {
02740          conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
02741       } else {
02742          conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
02743       }
02744    }
02745    if (!needconf) {
02746       /* Nobody is left (or should be left) in our conference.
02747          Kill it. */
02748       p->confno = -1;
02749    }
02750    ast_debug(1, "Updated conferencing on %d, with %d conference users\n", p->channel, needconf);
02751    return 0;
02752 }
02753 
02754 static void dahdi_enable_ec(struct dahdi_pvt *p)
02755 {
02756    int x;
02757    int res;
02758    if (!p)
02759       return;
02760    if (p->echocanon) {
02761       ast_debug(1, "Echo cancellation already on\n");
02762       return;
02763    }
02764    if (p->digital) {
02765       ast_debug(1, "Echo cancellation isn't required on digital connection\n");
02766       return;
02767    }
02768    if (p->echocancel.head.tap_length) {
02769       if ((p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP) || (p->sig == SIG_PRI) || (p->sig == SIG_SS7)) {
02770          x = 1;
02771          res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x);
02772          if (res)
02773             ast_log(LOG_WARNING, "Unable to enable audio mode on channel %d (%s)\n", p->channel, strerror(errno));
02774       }
02775       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &p->echocancel);
02776       if (res) {
02777          ast_log(LOG_WARNING, "Unable to enable echo cancellation on channel %d (%s)\n", p->channel, strerror(errno));
02778       } else {
02779          p->echocanon = 1;
02780          ast_debug(1, "Enabled echo cancellation on channel %d\n", p->channel);
02781       }
02782    } else
02783       ast_debug(1, "No echo cancellation requested\n");
02784 }
02785 
02786 static void dahdi_train_ec(struct dahdi_pvt *p)
02787 {
02788    int x;
02789    int res;
02790 
02791    if (p && p->echocanon && p->echotraining) {
02792       x = p->echotraining;
02793       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOTRAIN, &x);
02794       if (res)
02795          ast_log(LOG_WARNING, "Unable to request echo training on channel %d: %s\n", p->channel, strerror(errno));
02796       else
02797          ast_debug(1, "Engaged echo training on channel %d\n", p->channel);
02798    } else {
02799       ast_debug(1, "No echo training requested\n");
02800    }
02801 }
02802 
02803 static void dahdi_disable_ec(struct dahdi_pvt *p)
02804 {
02805    int res;
02806 
02807    if (p->echocanon) {
02808       struct dahdi_echocanparams ecp = { .tap_length = 0 };
02809 
02810       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &ecp);
02811 
02812       if (res)
02813          ast_log(LOG_WARNING, "Unable to disable echo cancellation on channel %d: %s\n", p->channel, strerror(errno));
02814       else
02815          ast_debug(1, "Disabled echo cancellation on channel %d\n", p->channel);
02816    }
02817 
02818    p->echocanon = 0;
02819 }
02820 
02821 static void fill_txgain(struct dahdi_gains *g, float gain, int law)
02822 {
02823    int j;
02824    int k;
02825    float linear_gain = pow(10.0, gain / 20.0);
02826 
02827    switch (law) {
02828    case DAHDI_LAW_ALAW:
02829       for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
02830          if (gain) {
02831             k = (int) (((float) AST_ALAW(j)) * linear_gain);
02832             if (k > 32767) k = 32767;
02833             if (k < -32767) k = -32767;
02834             g->txgain[j] = AST_LIN2A(k);
02835          } else {
02836             g->txgain[j] = j;
02837          }
02838       }
02839       break;
02840    case DAHDI_LAW_MULAW:
02841       for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
02842          if (gain) {
02843             k = (int) (((float) AST_MULAW(j)) * linear_gain);
02844             if (k > 32767) k = 32767;
02845             if (k < -32767) k = -32767;
02846             g->txgain[j] = AST_LIN2MU(k);
02847          } else {
02848             g->txgain[j] = j;
02849          }
02850       }
02851       break;
02852    }
02853 }
02854 
02855 static void fill_rxgain(struct dahdi_gains *g, float gain, int law)
02856 {
02857    int j;
02858    int k;
02859    float linear_gain = pow(10.0, gain / 20.0);
02860 
02861    switch (law) {
02862    case DAHDI_LAW_ALAW:
02863       for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
02864          if (gain) {
02865             k = (int) (((float) AST_ALAW(j)) * linear_gain);
02866             if (k > 32767) k = 32767;
02867             if (k < -32767) k = -32767;
02868             g->rxgain[j] = AST_LIN2A(k);
02869          } else {
02870             g->rxgain[j] = j;
02871          }
02872       }
02873       break;
02874    case DAHDI_LAW_MULAW:
02875       for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
02876          if (gain) {
02877             k = (int) (((float) AST_MULAW(j)) * linear_gain);
02878             if (k > 32767) k = 32767;
02879             if (k < -32767) k = -32767;
02880             g->rxgain[j] = AST_LIN2MU(k);
02881          } else {
02882             g->rxgain[j] = j;
02883          }
02884       }
02885       break;
02886    }
02887 }
02888 
02889 static int set_actual_txgain(int fd, int chan, float gain, int law)
02890 {
02891    struct dahdi_gains g;
02892    int res;
02893 
02894    memset(&g, 0, sizeof(g));
02895    g.chan = chan;
02896    res = ioctl(fd, DAHDI_GETGAINS, &g);
02897    if (res) {
02898       ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
02899       return res;
02900    }
02901 
02902    fill_txgain(&g, gain, law);
02903 
02904    return ioctl(fd, DAHDI_SETGAINS, &g);
02905 }
02906 
02907 static int set_actual_rxgain(int fd, int chan, float gain, int law)
02908 {
02909    struct dahdi_gains g;
02910    int res;
02911 
02912    memset(&g, 0, sizeof(g));
02913    g.chan = chan;
02914    res = ioctl(fd, DAHDI_GETGAINS, &g);
02915    if (res) {
02916       ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
02917       return res;
02918    }
02919 
02920    fill_rxgain(&g, gain, law);
02921 
02922    return ioctl(fd, DAHDI_SETGAINS, &g);
02923 }
02924 
02925 static int set_actual_gain(int fd, int chan, float rxgain, float txgain, int law)
02926 {
02927    return set_actual_txgain(fd, chan, txgain, law) | set_actual_rxgain(fd, chan, rxgain, law);
02928 }
02929 
02930 static int bump_gains(struct dahdi_pvt *p)
02931 {
02932    int res;
02933 
02934    /* Bump receive gain by value stored in cid_rxgain */
02935    res = set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain + p->cid_rxgain, p->txgain, p->law);
02936    if (res) {
02937       ast_log(LOG_WARNING, "Unable to bump gain: %s\n", strerror(errno));
02938       return -1;
02939    }
02940 
02941    return 0;
02942 }
02943 
02944 static int restore_gains(struct dahdi_pvt *p)
02945 {
02946    int res;
02947 
02948    res = set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain, p->txgain, p->law);
02949    if (res) {
02950       ast_log(LOG_WARNING, "Unable to restore gains: %s\n", strerror(errno));
02951       return -1;
02952    }
02953 
02954    return 0;
02955 }
02956 
02957 static inline int dahdi_set_hook(int fd, int hs)
02958 {
02959    int x, res;
02960 
02961    x = hs;
02962    res = ioctl(fd, DAHDI_HOOK, &x);
02963 
02964    if (res < 0) {
02965       if (errno == EINPROGRESS)
02966          return 0;
02967       ast_log(LOG_WARNING, "DAHDI hook failed returned %d (trying %d): %s\n", res, hs, strerror(errno));
02968       /* will expectedly fail if phone is off hook during operation, such as during a restart */
02969    }
02970 
02971    return res;
02972 }
02973 
02974 static inline int dahdi_confmute(struct dahdi_pvt *p, int muted)
02975 {
02976    int x, y, res;
02977    x = muted;
02978    if ((p->sig == SIG_PRI) || (p->sig == SIG_SS7) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) {
02979       y = 1;
02980       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &y);
02981       if (res)
02982          ast_log(LOG_WARNING, "Unable to set audio mode on %d: %s\n", p->channel, strerror(errno));
02983    }
02984    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_CONFMUTE, &x);
02985    if (res < 0)
02986       ast_log(LOG_WARNING, "DAHDI confmute(%d) failed on channel %d: %s\n", muted, p->channel, strerror(errno));
02987    return res;
02988 }
02989 
02990 static int save_conference(struct dahdi_pvt *p)
02991 {
02992    struct dahdi_confinfo c;
02993    int res;
02994    if (p->saveconf.confmode) {
02995       ast_log(LOG_WARNING, "Can't save conference -- already in use\n");
02996       return -1;
02997    }
02998    p->saveconf.chan = 0;
02999    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &p->saveconf);
03000    if (res) {
03001       ast_log(LOG_WARNING, "Unable to get conference info: %s\n", strerror(errno));
03002       p->saveconf.confmode = 0;
03003       return -1;
03004    }
03005    memset(&c, 0, sizeof(c));
03006    c.confmode = DAHDI_CONF_NORMAL;
03007    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &c);
03008    if (res) {
03009       ast_log(LOG_WARNING, "Unable to set conference info: %s\n", strerror(errno));
03010       return -1;
03011    }
03012    ast_debug(1, "Disabled conferencing\n");
03013    return 0;
03014 }
03015 
03016 /*!
03017  * \brief Send MWI state change
03018  *
03019  * \arg mailbox_full This is the mailbox associated with the FXO line that the
03020  *      MWI state has changed on.
03021  * \arg thereornot This argument should simply be set to 1 or 0, to indicate
03022  *      whether there are messages waiting or not.
03023  *
03024  *  \return nothing
03025  *
03026  * This function does two things:
03027  *
03028  * 1) It generates an internal Asterisk event notifying any other module that
03029  *    cares about MWI that the state of a mailbox has changed.
03030  *
03031  * 2) It runs the script specified by the mwimonitornotify option to allow
03032  *    some custom handling of the state change.
03033  */
03034 static void notify_message(char *mailbox_full, int thereornot)
03035 {
03036    char s[sizeof(mwimonitornotify) + 80];
03037    struct ast_event *event;
03038    char *mailbox, *context;
03039 
03040    /* Strip off @default */
03041    context = mailbox = ast_strdupa(mailbox_full);
03042    strsep(&context, "@");
03043    if (ast_strlen_zero(context))
03044       context = "default";
03045 
03046    if (!(event = ast_event_new(AST_EVENT_MWI,
03047          AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
03048          AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
03049          AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot,
03050          AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot,
03051          AST_EVENT_IE_END))) {
03052       return;
03053    }
03054 
03055    ast_event_queue_and_cache(event);
03056 
03057    if (!ast_strlen_zero(mailbox) && !ast_strlen_zero(mwimonitornotify)) {
03058       snprintf(s, sizeof(s), "%s %s %d", mwimonitornotify, mailbox, thereornot);
03059       ast_safe_system(s);
03060    }
03061 }
03062 
03063 static int restore_conference(struct dahdi_pvt *p)
03064 {
03065    int res;
03066    if (p->saveconf.confmode) {
03067       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &p->saveconf);
03068       p->saveconf.confmode = 0;
03069       if (res) {
03070          ast_log(LOG_WARNING, "Unable to restore conference info: %s\n", strerror(errno));
03071          return -1;
03072       }
03073       ast_debug(1, "Restored conferencing\n");
03074    }
03075    return 0;
03076 }
03077 
03078 static int send_callerid(struct dahdi_pvt *p);
03079 
03080 static int send_cwcidspill(struct dahdi_pvt *p)
03081 {
03082    p->callwaitcas = 0;
03083    p->cidcwexpire = 0;
03084    p->cid_suppress_expire = 0;
03085    if (!(p->cidspill = ast_malloc(MAX_CALLERID_SIZE)))
03086       return -1;
03087    p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, p->callwait_name, p->callwait_num, AST_LAW(p));
03088    /* Make sure we account for the end */
03089    p->cidlen += READ_SIZE * 4;
03090    p->cidpos = 0;
03091    send_callerid(p);
03092    ast_verb(3, "CPE supports Call Waiting Caller*ID.  Sending '%s/%s'\n", p->callwait_name, p->callwait_num);
03093    return 0;
03094 }
03095 
03096 static int has_voicemail(struct dahdi_pvt *p)
03097 {
03098    int new_msgs;
03099    struct ast_event *event;
03100    char *mailbox, *context;
03101 
03102    mailbox = context = ast_strdupa(p->mailbox);
03103    strsep(&context, "@");
03104    if (ast_strlen_zero(context))
03105       context = "default";
03106 
03107    event = ast_event_get_cached(AST_EVENT_MWI,
03108       AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
03109       AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
03110       AST_EVENT_IE_END);
03111 
03112    if (event) {
03113       new_msgs = ast_event_get_ie_uint(event, AST_EVENT_IE_NEWMSGS);
03114       ast_event_destroy(event);
03115    } else
03116       new_msgs = ast_app_has_voicemail(p->mailbox, NULL);
03117 
03118    return new_msgs;
03119 }
03120 
03121 static int send_callerid(struct dahdi_pvt *p)
03122 {
03123    /* Assumes spill in p->cidspill, p->cidlen in length and we're p->cidpos into it */
03124    int res;
03125    /* Take out of linear mode if necessary */
03126    if (p->subs[SUB_REAL].linear) {
03127       p->subs[SUB_REAL].linear = 0;
03128       dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
03129    }
03130    while (p->cidpos < p->cidlen) {
03131       res = write(p->subs[SUB_REAL].dfd, p->cidspill + p->cidpos, p->cidlen - p->cidpos);
03132       if (res < 0) {
03133          if (errno == EAGAIN)
03134             return 0;
03135          else {
03136             ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
03137             return -1;
03138          }
03139       }
03140       if (!res)
03141          return 0;
03142       p->cidpos += res;
03143    }
03144    p->cid_suppress_expire = CALLWAITING_SUPPRESS_SAMPLES;
03145    ast_free(p->cidspill);
03146    p->cidspill = NULL;
03147    if (p->callwaitcas) {
03148       /* Wait for CID/CW to expire */
03149       p->cidcwexpire = CIDCW_EXPIRE_SAMPLES;
03150       p->cid_suppress_expire = p->cidcwexpire;
03151    } else
03152       restore_conference(p);
03153    return 0;
03154 }
03155 
03156 static int dahdi_callwait(struct ast_channel *ast)
03157 {
03158    struct dahdi_pvt *p = ast->tech_pvt;
03159    p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
03160    if (p->cidspill) {
03161       ast_log(LOG_WARNING, "Spill already exists?!?\n");
03162       ast_free(p->cidspill);
03163    }
03164 
03165    /*
03166     * SAS: Subscriber Alert Signal, 440Hz for 300ms
03167     * CAS: CPE Alert Signal, 2130Hz * 2750Hz sine waves
03168     */
03169    if (!(p->cidspill = ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE * 4)))
03170       return -1;
03171    save_conference(p);
03172    /* Silence */
03173    memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
03174    if (!p->callwaitrings && p->callwaitingcallerid) {
03175       ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
03176       p->callwaitcas = 1;
03177       p->cidlen = 2400 + 680 + READ_SIZE * 4;
03178    } else {
03179       ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
03180       p->callwaitcas = 0;
03181       p->cidlen = 2400 + READ_SIZE * 4;
03182    }
03183    p->cidpos = 0;
03184    send_callerid(p);
03185 
03186    return 0;
03187 }
03188 
03189 #if defined(HAVE_SS7)
03190 static unsigned char cid_pres2ss7pres(int cid_pres)
03191 {
03192     return (cid_pres >> 5) & 0x03;
03193 }
03194 #endif   /* defined(HAVE_SS7) */
03195 
03196 #if defined(HAVE_SS7)
03197 static unsigned char cid_pres2ss7screen(int cid_pres)
03198 {
03199    return cid_pres & 0x03;
03200 }
03201 #endif   /* defined(HAVE_SS7) */
03202 
03203 static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout)
03204 {
03205    struct dahdi_pvt *p = ast->tech_pvt;
03206    int x, res, idx,mysig;
03207    char *c, *n, *l;
03208 #ifdef HAVE_PRI
03209    char *s = NULL;
03210 #endif
03211    char dest[256]; /* must be same length as p->dialdest */
03212    ast_mutex_lock(&p->lock);
03213    ast_copy_string(dest, rdest, sizeof(dest));
03214    ast_copy_string(p->dialdest, rdest, sizeof(p->dialdest));
03215    if ((ast->_state == AST_STATE_BUSY)) {
03216       p->subs[SUB_REAL].needbusy = 1;
03217       ast_mutex_unlock(&p->lock);
03218       return 0;
03219    }
03220    if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
03221       ast_log(LOG_WARNING, "dahdi_call called on %s, neither down nor reserved\n", ast->name);
03222       ast_mutex_unlock(&p->lock);
03223       return -1;
03224    }
03225    p->waitingfordt.tv_sec = 0;
03226    p->dialednone = 0;
03227    if ((p->radio || (p->oprmode < 0)))  /* if a radio channel, up immediately */
03228    {
03229       /* Special pseudo -- automatically up */
03230       ast_setstate(ast, AST_STATE_UP);
03231       ast_mutex_unlock(&p->lock);
03232       return 0;
03233    }
03234    x = DAHDI_FLUSH_READ | DAHDI_FLUSH_WRITE;
03235    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
03236    if (res)
03237       ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", p->channel, strerror(errno));
03238    p->outgoing = 1;
03239 
03240    if (IS_DIGITAL(ast->transfercapability)){
03241       set_actual_gain(p->subs[SUB_REAL].dfd, 0, 0, 0, p->law);
03242    } else {
03243       set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain, p->txgain, p->law);
03244    }  
03245 
03246    mysig = p->sig;
03247    if (p->outsigmod > -1)
03248       mysig = p->outsigmod;
03249 
03250    switch (mysig) {
03251    case SIG_FXOLS:
03252    case SIG_FXOGS:
03253    case SIG_FXOKS:
03254       if (p->owner == ast) {
03255          /* Normal ring, on hook */
03256 
03257          /* Don't send audio while on hook, until the call is answered */
03258          p->dialing = 1;
03259          if (p->use_callerid) {
03260             /* Generate the Caller-ID spill if desired */
03261             if (p->cidspill) {
03262                ast_log(LOG_WARNING, "cidspill already exists??\n");
03263                ast_free(p->cidspill);
03264             }
03265             p->callwaitcas = 0;
03266             if ((p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) {
03267                p->cidlen = ast_callerid_generate(p->cidspill, ast->cid.cid_name, ast->cid.cid_num, AST_LAW(p));
03268                p->cidpos = 0;
03269                send_callerid(p);
03270             }
03271          }
03272          /* Choose proper cadence */
03273          if ((p->distinctivering > 0) && (p->distinctivering <= num_cadence)) {
03274             if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &cadences[p->distinctivering - 1]))
03275                ast_log(LOG_WARNING, "Unable to set distinctive ring cadence %d on '%s': %s\n", p->distinctivering, ast->name, strerror(errno));
03276             p->cidrings = cidrings[p->distinctivering - 1];
03277          } else {
03278             if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, NULL))
03279                ast_log(LOG_WARNING, "Unable to reset default ring on '%s': %s\n", ast->name, strerror(errno));
03280             p->cidrings = p->sendcalleridafter;
03281          }
03282 
03283          /* nick@dccinc.com 4/3/03 mods to allow for deferred dialing */
03284          c = strchr(dest, '/');
03285          if (c)
03286             c++;
03287          if (c && (strlen(c) < p->stripmsd)) {
03288             ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
03289             c = NULL;
03290          }
03291          if (c) {
03292             p->dop.op = DAHDI_DIAL_OP_REPLACE;
03293             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "Tw%s", c);
03294             ast_debug(1, "FXO: setup deferred dialstring: %s\n", c);
03295          } else {
03296             p->dop.dialstr[0] = '\0';
03297          }
03298          x = DAHDI_RING;
03299          if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x) && (errno != EINPROGRESS)) {
03300             ast_log(LOG_WARNING, "Unable to ring phone: %s\n", strerror(errno));
03301             ast_mutex_unlock(&p->lock);
03302             return -1;
03303          }
03304          p->dialing = 1;
03305       } else {
03306          /* Call waiting call */
03307          p->callwaitrings = 0;
03308          if (ast->cid.cid_num)
03309             ast_copy_string(p->callwait_num, ast->cid.cid_num, sizeof(p->callwait_num));
03310          else
03311             p->callwait_num[0] = '\0';
03312          if (ast->cid.cid_name)
03313             ast_copy_string(p->callwait_name, ast->cid.cid_name, sizeof(p->callwait_name));
03314          else
03315             p->callwait_name[0] = '\0';
03316          /* Call waiting tone instead */
03317          if (dahdi_callwait(ast)) {
03318             ast_mutex_unlock(&p->lock);
03319             return -1;
03320          }
03321          /* Make ring-back */
03322          if (tone_zone_play_tone(p->subs[SUB_CALLWAIT].dfd, DAHDI_TONE_RINGTONE))
03323             ast_log(LOG_WARNING, "Unable to generate call-wait ring-back on channel %s\n", ast->name);
03324       }
03325       n = ast->cid.cid_name;
03326       l = ast->cid.cid_num;
03327       if (l)
03328          ast_copy_string(p->lastcid_num, l, sizeof(p->lastcid_num));
03329       else
03330          p->lastcid_num[0] = '\0';
03331       if (n)
03332          ast_copy_string(p->lastcid_name, n, sizeof(p->lastcid_name));
03333       else
03334          p->lastcid_name[0] = '\0';
03335       ast_setstate(ast, AST_STATE_RINGING);
03336       idx = dahdi_get_index(ast, p, 0);
03337       if (idx > -1) {
03338          p->subs[idx].needringing = 1;
03339       }
03340       break;
03341    case SIG_FXSLS:
03342    case SIG_FXSGS:
03343    case SIG_FXSKS:
03344       if (p->answeronpolarityswitch || p->hanguponpolarityswitch) {
03345          ast_debug(1, "Ignore possible polarity reversal on line seizure\n");
03346          p->polaritydelaytv = ast_tvnow();
03347       }
03348       /* fall through */
03349    case SIG_EMWINK:
03350    case SIG_EM:
03351    case SIG_EM_E1:
03352    case SIG_FEATD:
03353    case SIG_FEATDMF:
03354    case SIG_E911:
03355    case SIG_FGC_CAMA:
03356    case SIG_FGC_CAMAMF:
03357    case SIG_FEATB:
03358    case SIG_SFWINK:
03359    case SIG_SF:
03360    case SIG_SF_FEATD:
03361    case SIG_SF_FEATDMF:
03362    case SIG_FEATDMF_TA:
03363    case SIG_SF_FEATB:
03364       c = strchr(dest, '/');
03365       if (c)
03366          c++;
03367       else
03368          c = "";
03369       if (strlen(c) < p->stripmsd) {
03370          ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
03371          ast_mutex_unlock(&p->lock);
03372          return -1;
03373       }
03374 #ifdef HAVE_PRI
03375       /* Start the trunk, if not GR-303 */
03376       if (!p->pri) {
03377 #endif
03378          x = DAHDI_START;
03379          res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
03380          if (res < 0) {
03381             if (errno != EINPROGRESS) {
03382                ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno));
03383                ast_mutex_unlock(&p->lock);
03384                return -1;
03385             }
03386          }
03387 #ifdef HAVE_PRI
03388       }
03389 #endif
03390       ast_debug(1, "Dialing '%s'\n", c);
03391       p->dop.op = DAHDI_DIAL_OP_REPLACE;
03392 
03393       c += p->stripmsd;
03394 
03395       switch (mysig) {
03396       case SIG_FEATD:
03397          l = ast->cid.cid_num;
03398          if (l)
03399             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T*%s*%s*", l, c);
03400          else
03401             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T**%s*", c);
03402          break;
03403       case SIG_FEATDMF:
03404          l = ast->cid.cid_num;
03405          if (l)
03406             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*00%s#*%s#", l, c);
03407          else
03408             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*02#*%s#", c);
03409          break;
03410       case SIG_FEATDMF_TA:
03411       {
03412          const char *cic, *ozz;
03413 
03414          /* If you have to go through a Tandem Access point you need to use this */
03415          ozz = pbx_builtin_getvar_helper(p->owner, "FEATDMF_OZZ");
03416          if (!ozz)
03417             ozz = defaultozz;
03418          cic = pbx_builtin_getvar_helper(p->owner, "FEATDMF_CIC");
03419          if (!cic)
03420             cic = defaultcic;
03421          if (!ozz || !cic) {
03422             ast_log(LOG_WARNING, "Unable to dial channel of type feature group D MF tandem access without CIC or OZZ set\n");
03423             ast_mutex_unlock(&p->lock);
03424             return -1;
03425          }
03426          snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s%s#", ozz, cic);
03427          snprintf(p->finaldial, sizeof(p->finaldial), "M*%s#", c);
03428          p->whichwink = 0;
03429       }
03430          break;
03431       case SIG_E911:
03432          ast_copy_string(p->dop.dialstr, "M*911#", sizeof(p->dop.dialstr));
03433          break;
03434       case SIG_FGC_CAMA:
03435          snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%s", c);
03436          break;
03437       case SIG_FGC_CAMAMF:
03438       case SIG_FEATB:
03439          snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s#", c);
03440          break;
03441       default:
03442          if (p->pulse)
03443             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%sw", c);
03444          else
03445             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%sw", c);
03446          break;
03447       }
03448 
03449       if (p->echotraining && (strlen(p->dop.dialstr) > 4)) {
03450          memset(p->echorest, 'w', sizeof(p->echorest) - 1);
03451          strcpy(p->echorest + (p->echotraining / 400) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
03452          p->echorest[sizeof(p->echorest) - 1] = '\0';
03453          p->echobreak = 1;
03454          p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
03455       } else
03456          p->echobreak = 0;
03457 
03458       /* waitfordialtone ? */
03459 #ifdef HAVE_PRI
03460       if (!p->pri) {
03461 #endif
03462          if( p->waitfordialtone && CANPROGRESSDETECT(p) && p->dsp ) {
03463             ast_log(LOG_DEBUG, "Defer dialling for %dms or dialtone\n", p->waitfordialtone);
03464             gettimeofday(&p->waitingfordt,NULL);
03465             ast_setstate(ast, AST_STATE_OFFHOOK);
03466             break;
03467          }
03468 #ifdef HAVE_PRI
03469       }
03470 #endif
03471       if (!res) {
03472          if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
03473             int saveerr = errno;
03474 
03475             x = DAHDI_ONHOOK;
03476             ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
03477             ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
03478             ast_mutex_unlock(&p->lock);
03479             return -1;
03480          }
03481       } else
03482          ast_debug(1, "Deferring dialing...\n");
03483 
03484       p->dialing = 1;
03485       if (ast_strlen_zero(c))
03486          p->dialednone = 1;
03487       ast_setstate(ast, AST_STATE_DIALING);
03488       break;
03489    case 0:
03490       /* Special pseudo -- automatically up*/
03491       ast_setstate(ast, AST_STATE_UP);
03492       break;
03493    case SIG_PRI:
03494    case SIG_BRI:
03495    case SIG_BRI_PTMP:
03496    case SIG_SS7:
03497    case SIG_MFCR2:
03498       /* We'll get it in a moment -- but use dialdest to store pre-setup_ack digits */
03499       p->dialdest[0] = '\0';
03500       p->dialing = 1;
03501       break;
03502    default:
03503       ast_debug(1, "not yet implemented\n");
03504       ast_mutex_unlock(&p->lock);
03505       return -1;
03506    }
03507 #ifdef HAVE_SS7
03508    if (p->ss7) {
03509       char ss7_called_nai;
03510       int called_nai_strip;
03511       char ss7_calling_nai;
03512       int calling_nai_strip;
03513       const char *charge_str = NULL;
03514       const char *gen_address = NULL;
03515       const char *gen_digits = NULL;
03516       const char *gen_dig_type = NULL;
03517       const char *gen_dig_scheme = NULL;
03518       const char *gen_name = NULL;
03519       const char *jip_digits = NULL;
03520       const char *lspi_ident = NULL;
03521       const char *rlt_flag = NULL;
03522       const char *call_ref_id = NULL;
03523       const char *call_ref_pc = NULL;
03524       const char *send_far = NULL;
03525 
03526       c = strchr(dest, '/');
03527       if (c) {
03528          c++;
03529       } else {
03530          c = "";
03531       }
03532       if (strlen(c) < p->stripmsd) {
03533          ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
03534          ast_mutex_unlock(&p->lock);
03535          return -1;
03536       }
03537 
03538       if (!p->hidecallerid) {
03539          l = ast->cid.cid_num;
03540       } else {
03541          l = NULL;
03542       }
03543 
03544       if (ss7_grab(p, p->ss7)) {
03545          ast_log(LOG_WARNING, "Failed to grab SS7!\n");
03546          ast_mutex_unlock(&p->lock);
03547          return -1;
03548       }
03549       p->digital = IS_DIGITAL(ast->transfercapability);
03550       p->ss7call = isup_new_call(p->ss7->ss7);
03551 
03552       if (!p->ss7call) {
03553          ss7_rel(p->ss7);
03554          ast_mutex_unlock(&p->lock);
03555          ast_log(LOG_ERROR, "Unable to allocate new SS7 call!\n");
03556          return -1;
03557       }
03558 
03559       called_nai_strip = 0;
03560       ss7_called_nai = p->ss7->called_nai;
03561       if (ss7_called_nai == SS7_NAI_DYNAMIC) { /* compute dynamically */
03562          if (strncmp(c + p->stripmsd, p->ss7->internationalprefix, strlen(p->ss7->internationalprefix)) == 0) {
03563             called_nai_strip = strlen(p->ss7->internationalprefix);
03564             ss7_called_nai = SS7_NAI_INTERNATIONAL;
03565          } else if (strncmp(c + p->stripmsd, p->ss7->nationalprefix, strlen(p->ss7->nationalprefix)) == 0) {
03566             called_nai_strip = strlen(p->ss7->nationalprefix);
03567             ss7_called_nai = SS7_NAI_NATIONAL;
03568          } else {
03569             ss7_called_nai = SS7_NAI_SUBSCRIBER;
03570          }
03571       }
03572       isup_set_called(p->ss7call, c + p->stripmsd + called_nai_strip, ss7_called_nai, p->ss7->ss7);
03573 
03574       calling_nai_strip = 0;
03575       ss7_calling_nai = p->ss7->calling_nai;
03576       if ((l != NULL) && (ss7_calling_nai == SS7_NAI_DYNAMIC)) { /* compute dynamically */
03577          if (strncmp(l, p->ss7->internationalprefix, strlen(p->ss7->internationalprefix)) == 0) {
03578             calling_nai_strip = strlen(p->ss7->internationalprefix);
03579             ss7_calling_nai = SS7_NAI_INTERNATIONAL;
03580          } else if (strncmp(l, p->ss7->nationalprefix, strlen(p->ss7->nationalprefix)) == 0) {
03581             calling_nai_strip = strlen(p->ss7->nationalprefix);
03582             ss7_calling_nai = SS7_NAI_NATIONAL;
03583          } else {
03584             ss7_calling_nai = SS7_NAI_SUBSCRIBER;
03585          }
03586       }
03587       isup_set_calling(p->ss7call, l ? (l + calling_nai_strip) : NULL, ss7_calling_nai,
03588          p->use_callingpres ? cid_pres2ss7pres(ast->cid.cid_pres) : (l ? SS7_PRESENTATION_ALLOWED : SS7_PRESENTATION_RESTRICTED),
03589          p->use_callingpres ? cid_pres2ss7screen(ast->cid.cid_pres) : SS7_SCREENING_USER_PROVIDED );
03590 
03591       isup_set_oli(p->ss7call, ast->cid.cid_ani2);
03592       isup_init_call(p->ss7->ss7, p->ss7call, p->cic, p->dpc);
03593 
03594       ast_channel_lock(ast);
03595       /* Set the charge number if it is set */
03596       charge_str = pbx_builtin_getvar_helper(ast, "SS7_CHARGE_NUMBER");
03597       if (charge_str)
03598          isup_set_charge(p->ss7call, charge_str, SS7_ANI_CALLING_PARTY_SUB_NUMBER, 0x10);
03599 
03600       gen_address = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_ADDRESS");
03601       if (gen_address)
03602          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 */
03603 
03604       gen_digits = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_DIGITS");
03605       gen_dig_type = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_DIGTYPE");
03606       gen_dig_scheme = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_DIGSCHEME");
03607       if (gen_digits)
03608          isup_set_gen_digits(p->ss7call, gen_digits, atoi(gen_dig_type), atoi(gen_dig_scheme));
03609 
03610       gen_name = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_NAME");
03611       if (gen_name)
03612          isup_set_generic_name(p->ss7call, gen_name, GEN_NAME_TYPE_CALLING_NAME, GEN_NAME_AVAIL_AVAILABLE, GEN_NAME_PRES_ALLOWED);
03613 
03614       jip_digits = pbx_builtin_getvar_helper(ast, "SS7_JIP");
03615       if (jip_digits)
03616          isup_set_jip_digits(p->ss7call, jip_digits);
03617 
03618       lspi_ident = pbx_builtin_getvar_helper(ast, "SS7_LSPI_IDENT");
03619       if (lspi_ident)
03620          isup_set_lspi(p->ss7call, lspi_ident, 0x18, 0x7, 0x00);
03621 
03622       rlt_flag = pbx_builtin_getvar_helper(ast, "SS7_RLT_ON");
03623       if ((rlt_flag) && ((strncmp("NO", rlt_flag, strlen(rlt_flag))) != 0 )) {
03624          isup_set_lspi(p->ss7call, rlt_flag, 0x18, 0x7, 0x00); /* Setting for Nortel DMS-250/500 */
03625       }
03626 
03627       call_ref_id = pbx_builtin_getvar_helper(ast, "SS7_CALLREF_IDENT");
03628       call_ref_pc = pbx_builtin_getvar_helper(ast, "SS7_CALLREF_PC");
03629       if (call_ref_id && call_ref_pc) {
03630          isup_set_callref(p->ss7call, atoi(call_ref_id),
03631                 call_ref_pc ? atoi(call_ref_pc) : 0);
03632       }
03633 
03634       send_far = pbx_builtin_getvar_helper(ast, "SS7_SEND_FAR");
03635       if ((send_far) && ((strncmp("NO", send_far, strlen(send_far))) != 0 ))
03636          (isup_far(p->ss7->ss7, p->ss7call));
03637 
03638       ast_channel_unlock(ast);
03639 
03640       p->call_level = DAHDI_CALL_LEVEL_SETUP;
03641       isup_iam(p->ss7->ss7, p->ss7call);
03642       ast_setstate(ast, AST_STATE_DIALING);
03643       ss7_rel(p->ss7);
03644    }
03645 #endif /* HAVE_SS7 */
03646 #ifdef HAVE_OPENR2
03647    if (p->mfcr2) {
03648       openr2_calling_party_category_t chancat;
03649       int callres = 0;
03650       char *c, *l;
03651 
03652       c = strchr(dest, '/');
03653       if (c) {
03654          c++;
03655       } else {
03656          c = "";
03657       }
03658       if (!p->hidecallerid) {
03659          l = ast->cid.cid_num;
03660       } else {
03661          l = NULL;
03662       }
03663       if (strlen(c) < p->stripmsd) {
03664          ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
03665          ast_mutex_unlock(&p->lock);
03666          return -1;
03667       }
03668       p->dialing = 1;
03669       ast_channel_lock(ast);
03670       chancat = dahdi_r2_get_channel_category(ast);
03671       ast_channel_unlock(ast);
03672       callres = openr2_chan_make_call(p->r2chan, l, (c + p->stripmsd), chancat);
03673       if (-1 == callres) {
03674          ast_mutex_unlock(&p->lock);
03675          ast_log(LOG_ERROR, "unable to make new MFC/R2 call!\n");
03676          return -1;
03677       }
03678       p->mfcr2_call_accepted = 0;
03679       p->mfcr2_progress = 0;
03680       ast_setstate(ast, AST_STATE_DIALING);
03681    }
03682 #endif /* HAVE_OPENR2 */
03683 #ifdef HAVE_PRI
03684    if (p->pri) {
03685       struct pri_sr *sr;
03686 #ifdef SUPPORT_USERUSER
03687       const char *useruser;
03688 #endif
03689       int pridialplan;
03690       int dp_strip;
03691       int prilocaldialplan;
03692       int ldp_strip;
03693       int exclusive;
03694       const char *rr_str;
03695       int redirect_reason;
03696 
03697       c = strchr(dest, '/');
03698       if (c) {
03699          c++;
03700       } else {
03701          c = "";
03702       }
03703 
03704       l = NULL;
03705       n = NULL;
03706       if (!p->hidecallerid) {
03707          /* If we get to the end of this loop without breaking, there's no
03708           * numeric calleridnum. This is done instead of testing for
03709           * "unknown" or the thousands of other ways that the calleridnum
03710           * could be invalid. */
03711          for (l = ast->cid.cid_num; l && *l; l++) {
03712             if (strchr("0123456789", *l)) {
03713                l = ast->cid.cid_num;
03714                break;
03715             }
03716          }
03717          if (!p->hidecalleridname) {
03718             n = ast->cid.cid_name;
03719          }
03720       }
03721 
03722       if (strlen(c) < p->stripmsd) {
03723          ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
03724          ast_mutex_unlock(&p->lock);
03725          return -1;
03726       }
03727       if (mysig != SIG_FXSKS) {
03728          p->dop.op = DAHDI_DIAL_OP_REPLACE;
03729          s = strchr(c + p->stripmsd, 'w');
03730          if (s) {
03731             if (strlen(s) > 1)
03732                snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%s", s);
03733             else
03734                p->dop.dialstr[0] = '\0';
03735             *s = '\0';
03736          } else {
03737             p->dop.dialstr[0] = '\0';
03738          }
03739       }
03740       if (pri_grab(p, p->pri)) {
03741          ast_log(LOG_WARNING, "Failed to grab PRI!\n");
03742          ast_mutex_unlock(&p->lock);
03743          return -1;
03744       }
03745       if (!(p->call = pri_new_call(p->pri->pri))) {
03746          ast_log(LOG_WARNING, "Unable to create call on channel %d\n", p->channel);
03747          pri_rel(p->pri);
03748          ast_mutex_unlock(&p->lock);
03749          return -1;
03750       }
03751       if (!(sr = pri_sr_new())) {
03752          ast_log(LOG_WARNING, "Failed to allocate setup request channel %d\n", p->channel);
03753          pri_destroycall(p->pri->pri, p->call);
03754          p->call = NULL;
03755          pri_rel(p->pri);
03756          ast_mutex_unlock(&p->lock);
03757          return -1;
03758       }
03759       if (p->bearer || (mysig == SIG_FXSKS)) {
03760          if (p->bearer) {
03761             ast_debug(1, "Oooh, I have a bearer on %d (%d:%d)\n", PVT_TO_CHANNEL(p->bearer), p->bearer->logicalspan, p->bearer->channel);
03762             p->bearer->call = p->call;
03763          } else
03764             ast_debug(1, "I'm being setup with no bearer right now...\n");
03765 
03766          pri_set_crv(p->pri->pri, p->call, p->channel, 0);
03767       }
03768       p->digital = IS_DIGITAL(ast->transfercapability);
03769 
03770       /* Should the picked channel be used exclusively? */
03771       if (p->priexclusive || p->pri->nodetype == PRI_NETWORK) {
03772          exclusive = 1;
03773       } else {
03774          exclusive = 0;
03775       }
03776 
03777       pri_sr_set_channel(sr, p->bearer ? PVT_TO_CHANNEL(p->bearer) : PVT_TO_CHANNEL(p), exclusive, 1);
03778       pri_sr_set_bearer(sr, p->digital ? PRI_TRANS_CAP_DIGITAL : ast->transfercapability,
03779          (p->digital ? -1 :
03780             ((p->law == DAHDI_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW)));
03781       if (p->pri->facilityenable)
03782          pri_facility_enable(p->pri->pri);
03783 
03784       ast_verb(3, "Requested transfer capability: 0x%.2x - %s\n", ast->transfercapability, ast_transfercapability2str(ast->transfercapability));
03785 
03786       dp_strip = 0;
03787       pridialplan = p->pri->dialplan - 1;
03788       if (pridialplan == -2 || pridialplan == -3) { /* compute dynamically */
03789          if (strncmp(c + p->stripmsd, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) {
03790             if (pridialplan == -2) {
03791                dp_strip = strlen(p->pri->internationalprefix);
03792             }
03793             pridialplan = PRI_INTERNATIONAL_ISDN;
03794          } else if (strncmp(c + p->stripmsd, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) {
03795             if (pridialplan == -2) {
03796                dp_strip = strlen(p->pri->nationalprefix);
03797             }
03798             pridialplan = PRI_NATIONAL_ISDN;
03799          } else {
03800             pridialplan = PRI_LOCAL_ISDN;
03801          }
03802       }
03803       while (c[p->stripmsd] > '9' && c[p->stripmsd] != '*' && c[p->stripmsd] != '#') {
03804          switch (c[p->stripmsd]) {
03805          case 'U':
03806             pridialplan = (PRI_TON_UNKNOWN << 4) | (pridialplan & 0xf);
03807             break;
03808          case 'I':
03809             pridialplan = (PRI_TON_INTERNATIONAL << 4) | (pridialplan & 0xf);
03810             break;
03811          case 'N':
03812             pridialplan = (PRI_TON_NATIONAL << 4) | (pridialplan & 0xf);
03813             break;
03814          case 'L':
03815             pridialplan = (PRI_TON_NET_SPECIFIC << 4) | (pridialplan & 0xf);
03816             break;
03817          case 'S':
03818             pridialplan = (PRI_TON_SUBSCRIBER << 4) | (pridialplan & 0xf);
03819             break;
03820          case 'V':
03821             pridialplan = (PRI_TON_ABBREVIATED << 4) | (pridialplan & 0xf);
03822             break;
03823          case 'R':
03824             pridialplan = (PRI_TON_RESERVED << 4) | (pridialplan & 0xf);
03825             break;
03826          case 'u':
03827             pridialplan = PRI_NPI_UNKNOWN | (pridialplan & 0xf0);
03828             break;
03829          case 'e':
03830             pridialplan = PRI_NPI_E163_E164 | (pridialplan & 0xf0);
03831             break;
03832          case 'x':
03833             pridialplan = PRI_NPI_X121 | (pridialplan & 0xf0);
03834             break;
03835          case 'f':
03836             pridialplan = PRI_NPI_F69 | (pridialplan & 0xf0);
03837             break;
03838          case 'n':
03839             pridialplan = PRI_NPI_NATIONAL | (pridialplan & 0xf0);
03840             break;
03841          case 'p':
03842             pridialplan = PRI_NPI_PRIVATE | (pridialplan & 0xf0);
03843             break;
03844          case 'r':
03845             pridialplan = PRI_NPI_RESERVED | (pridialplan & 0xf0);
03846             break;
03847          default:
03848             if (isalpha(c[p->stripmsd])) {
03849                ast_log(LOG_WARNING, "Unrecognized pridialplan %s modifier: %c\n",
03850                   c[p->stripmsd] > 'Z' ? "NPI" : "TON", c[p->stripmsd]);
03851             }
03852             break;
03853          }
03854          c++;
03855       }
03856       pri_sr_set_called(sr, c + p->stripmsd + dp_strip, pridialplan, s ? 1 : 0);
03857 
03858       ldp_strip = 0;
03859       prilocaldialplan = p->pri->localdialplan - 1;
03860       if ((l != NULL) && (prilocaldialplan == -2 || prilocaldialplan == -3)) { /* compute dynamically */
03861          if (strncmp(l, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) {
03862             if (prilocaldialplan == -2) {
03863                ldp_strip = strlen(p->pri->internationalprefix);
03864             }
03865             prilocaldialplan = PRI_INTERNATIONAL_ISDN;
03866          } else if (strncmp(l, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) {
03867             if (prilocaldialplan == -2) {
03868                ldp_strip = strlen(p->pri->nationalprefix);
03869             }
03870             prilocaldialplan = PRI_NATIONAL_ISDN;
03871          } else {
03872             prilocaldialplan = PRI_LOCAL_ISDN;
03873          }
03874       }
03875       if (l != NULL) {
03876          while (*l > '9' && *l != '*' && *l != '#') {
03877             switch (*l) {
03878             case 'U':
03879                prilocaldialplan = (PRI_TON_UNKNOWN << 4) | (prilocaldialplan & 0xf);
03880                break;
03881             case 'I':
03882                prilocaldialplan = (PRI_TON_INTERNATIONAL << 4) | (prilocaldialplan & 0xf);
03883                break;
03884             case 'N':
03885                prilocaldialplan = (PRI_TON_NATIONAL << 4) | (prilocaldialplan & 0xf);
03886                break;
03887             case 'L':
03888                prilocaldialplan = (PRI_TON_NET_SPECIFIC << 4) | (prilocaldialplan & 0xf);
03889                break;
03890             case 'S':
03891                prilocaldialplan = (PRI_TON_SUBSCRIBER << 4) | (prilocaldialplan & 0xf);
03892                break;
03893             case 'V':
03894                prilocaldialplan = (PRI_TON_ABBREVIATED << 4) | (prilocaldialplan & 0xf);
03895                break;
03896             case 'R':
03897                prilocaldialplan = (PRI_TON_RESERVED << 4) | (prilocaldialplan & 0xf);
03898                break;
03899             case 'u':
03900                prilocaldialplan = PRI_NPI_UNKNOWN | (prilocaldialplan & 0xf0);
03901                break;
03902             case 'e':
03903                prilocaldialplan = PRI_NPI_E163_E164 | (prilocaldialplan & 0xf0);
03904                break;
03905             case 'x':
03906                prilocaldialplan = PRI_NPI_X121 | (prilocaldialplan & 0xf0);
03907                break;
03908             case 'f':
03909                prilocaldialplan = PRI_NPI_F69 | (prilocaldialplan & 0xf0);
03910                break;
03911             case 'n':
03912                prilocaldialplan = PRI_NPI_NATIONAL | (prilocaldialplan & 0xf0);
03913                break;
03914             case 'p':
03915                prilocaldialplan = PRI_NPI_PRIVATE | (prilocaldialplan & 0xf0);
03916                break;
03917             case 'r':
03918                prilocaldialplan = PRI_NPI_RESERVED | (prilocaldialplan & 0xf0);
03919                break;
03920             default:
03921                if (isalpha(*l)) {
03922                   ast_log(LOG_WARNING,
03923                      "Unrecognized prilocaldialplan %s modifier: %c\n",
03924                      *l > 'Z' ? "NPI" : "TON", *l);
03925                }
03926                break;
03927             }
03928             l++;
03929          }
03930       }
03931       pri_sr_set_caller(sr, l ? (l + ldp_strip) : NULL, n, prilocaldialplan,
03932          p->use_callingpres ? ast->cid.cid_pres : (l ? PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN : PRES_NUMBER_NOT_AVAILABLE));
03933       if ((rr_str = pbx_builtin_getvar_helper(ast, "PRIREDIRECTREASON"))) {
03934          if (!strcasecmp(rr_str, "UNKNOWN"))
03935             redirect_reason = 0;
03936          else if (!strcasecmp(rr_str, "BUSY"))
03937             redirect_reason = 1;
03938          else if (!strcasecmp(rr_str, "NO_REPLY") || !strcasecmp(rr_str, "NOANSWER"))
03939          /* the NOANSWER is to match diversion-reason from chan_sip, (which never reads PRIREDIRECTREASON) */
03940             redirect_reason = 2;
03941          else if (!strcasecmp(rr_str, "UNCONDITIONAL"))
03942             redirect_reason = 15;
03943          else
03944             redirect_reason = PRI_REDIR_UNCONDITIONAL;
03945       } else
03946          redirect_reason = PRI_REDIR_UNCONDITIONAL;
03947       pri_sr_set_redirecting(sr, ast->cid.cid_rdnis, p->pri->localdialplan - 1, PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN, redirect_reason);
03948 
03949 #ifdef SUPPORT_USERUSER
03950       /* User-user info */
03951       useruser = pbx_builtin_getvar_helper(p->owner, "USERUSERINFO");
03952       if (useruser)
03953          pri_sr_set_useruser(sr, useruser);
03954 #endif
03955 
03956       if (pri_setup(p->pri->pri, p->call, sr)) {
03957          ast_log(LOG_WARNING, "Unable to setup call to %s (using %s)\n",
03958             c + p->stripmsd + dp_strip, dialplan2str(p->pri->dialplan));
03959          pri_destroycall(p->pri->pri, p->call);
03960          p->call = NULL;
03961          pri_rel(p->pri);
03962          ast_mutex_unlock(&p->lock);
03963          pri_sr_free(sr);
03964          return -1;
03965       }
03966       p->call_level = DAHDI_CALL_LEVEL_SETUP;
03967       pri_sr_free(sr);
03968       ast_setstate(ast, AST_STATE_DIALING);
03969       pri_rel(p->pri);
03970    }
03971 #endif
03972    ast_mutex_unlock(&p->lock);
03973    return 0;
03974 }
03975 
03976 static void destroy_dahdi_pvt(struct dahdi_pvt **pvt)
03977 {
03978    struct dahdi_pvt *p = *pvt;
03979    /* Remove channel from the list */
03980    if (p->prev)
03981       p->prev->next = p->next;
03982    if (p->next)
03983       p->next->prev = p->prev;
03984 
03985    ast_free(p->cidspill);
03986    if (p->use_smdi)
03987       ast_smdi_interface_unref(p->smdi_iface);
03988    if (p->mwi_event_sub)
03989       ast_event_unsubscribe(p->mwi_event_sub);
03990    if (p->vars) {
03991       ast_variables_destroy(p->vars);
03992    }
03993    ast_mutex_destroy(&p->lock);
03994    dahdi_close_sub(p, SUB_REAL);
03995    if (p->owner)
03996       p->owner->tech_pvt = NULL;
03997    free(p);
03998    *pvt = NULL;
03999 }
04000 
04001 static int destroy_channel(struct dahdi_pvt *prev, struct dahdi_pvt *cur, int now)
04002 {
04003    int owned = 0;
04004    int i = 0;
04005 
04006    if (!now) {
04007       if (cur->owner) {
04008          owned = 1;
04009       }
04010 
04011       for (i = 0; i < 3; i++) {
04012          if (cur->subs[i].owner) {
04013             owned = 1;
04014          }
04015       }
04016       if (!owned) {
04017          if (prev) {
04018             prev->next = cur->next;
04019             if (prev->next)
04020                prev->next->prev = prev;
04021             else
04022                ifend = prev;
04023          } else {
04024             iflist = cur->next;
04025             if (iflist)
04026                iflist->prev = NULL;
04027             else
04028                ifend = NULL;
04029          }
04030          destroy_dahdi_pvt(&cur);
04031       }
04032    } else {
04033       if (prev) {
04034          prev->next = cur->next;
04035          if (prev->next)
04036             prev->next->prev = prev;
04037          else
04038             ifend = prev;
04039       } else {
04040          iflist = cur->next;
04041          if (iflist)
04042             iflist->prev = NULL;
04043          else
04044             ifend = NULL;
04045       }
04046       destroy_dahdi_pvt(&cur);
04047    }
04048    return 0;
04049 }
04050 
04051 static void destroy_all_channels(void)
04052 {
04053    int x;
04054    struct dahdi_pvt *p, *pl;
04055 
04056    while (num_restart_pending) {
04057       usleep(1);
04058    }
04059 
04060    ast_mutex_lock(&iflock);
04061    /* Destroy all the interfaces and free their memory */
04062    p = iflist;
04063    while (p) {
04064       pl = p;
04065       p = p->next;
04066       x = pl->channel;
04067       /* Free associated memory */
04068       destroy_dahdi_pvt(&pl);
04069       if (option_verbose > 2)
04070          ast_verbose(VERBOSE_PREFIX_2 "Unregistered channel %d\n", x);
04071    }
04072    iflist = NULL;
04073    ifcount = 0;
04074    ast_mutex_unlock(&iflock);
04075 }
04076 
04077 #if defined(HAVE_PRI)
04078 static char *dahdi_send_keypad_facility_app = "DAHDISendKeypadFacility";
04079 
04080 static int dahdi_send_keypad_facility_exec(struct ast_channel *chan, void *data)
04081 {
04082    /* Data will be our digit string */
04083    struct dahdi_pvt *p;
04084    char *digits = (char *) data;
04085 
04086    if (ast_strlen_zero(digits)) {
04087       ast_debug(1, "No digit string sent to application!\n");
04088       return -1;
04089    }
04090 
04091    p = (struct dahdi_pvt *)chan->tech_pvt;
04092 
04093    if (!p) {
04094       ast_debug(1, "Unable to find technology private\n");
04095       return -1;
04096    }
04097 
04098    ast_mutex_lock(&p->lock);
04099 
04100    if (!p->pri || !p->call) {
04101       ast_debug(1, "Unable to find pri or call on channel!\n");
04102       ast_mutex_unlock(&p->lock);
04103       return -1;
04104    }
04105 
04106    if (!pri_grab(p, p->pri)) {
04107       pri_keypad_facility(p->pri->pri, p->call, digits);
04108       pri_rel(p->pri);
04109    } else {
04110       ast_debug(1, "Unable to grab pri to send keypad facility!\n");
04111       ast_mutex_unlock(&p->lock);
04112       return -1;
04113    }
04114 
04115    ast_mutex_unlock(&p->lock);
04116 
04117    return 0;
04118 }
04119 #endif   /* defined(HAVE_PRI) */
04120 
04121 #if defined(HAVE_PRI)
04122 #if defined(HAVE_PRI_PROG_W_CAUSE)
04123 static char *dahdi_send_callrerouting_facility_app = "DAHDISendCallreroutingFacility";
04124 
04125 static int dahdi_send_callrerouting_facility_exec(struct ast_channel *chan, void *data)
04126 {
04127    /* Data will be our digit string */
04128    struct dahdi_pvt *p;
04129    char *parse;
04130    int res = -1;
04131    AST_DECLARE_APP_ARGS(args,
04132       AST_APP_ARG(destination);
04133       AST_APP_ARG(original);
04134       AST_APP_ARG(reason);
04135    );
04136 
04137    if (ast_strlen_zero(data)) {
04138       ast_log(LOG_DEBUG, "No data sent to application!\n");
04139       return -1;
04140    }
04141 
04142    p = (struct dahdi_pvt *)chan->tech_pvt;
04143 
04144    if (!p) {
04145       ast_log(LOG_DEBUG, "Unable to find technology private\n");
04146       return -1;
04147    }
04148 
04149    parse = ast_strdupa(data);
04150    AST_STANDARD_APP_ARGS(args, parse);
04151 
04152    if (ast_strlen_zero(args.destination)) {
04153       ast_log(LOG_WARNING, "callrerouting facility requires at least destination number argument\n");
04154       return -1;
04155    }
04156 
04157    if (ast_strlen_zero(args.original)) {
04158       ast_log(LOG_WARNING, "Callrerouting Facility without original called number argument\n");
04159       args.original = NULL;
04160    }
04161 
04162    if (ast_strlen_zero(args.reason)) {
04163       ast_log(LOG_NOTICE, "Callrerouting Facility without diversion reason argument, defaulting to unknown\n");
04164       args.reason = NULL;
04165    }
04166 
04167    ast_mutex_lock(&p->lock);
04168 
04169    if (!p->pri || !p->call) {
04170       ast_log(LOG_DEBUG, "Unable to find pri or call on channel!\n");
04171       ast_mutex_unlock(&p->lock);
04172       return -1;
04173    }
04174 
04175    switch (p->sig) {
04176    case SIG_PRI:
04177       if (!pri_grab(p, p->pri)) {
04178          if (chan->_state == AST_STATE_RING) {
04179             res = pri_callrerouting_facility(p->pri->pri, p->call, args.destination, args.original, args.reason);
04180          }
04181          pri_rel(p->pri);
04182       } else {
04183          ast_log(LOG_DEBUG, "Unable to grab pri to send callrerouting facility on span %d!\n", p->span);
04184          ast_mutex_unlock(&p->lock);
04185          return -1;
04186       }
04187       break;
04188    }
04189 
04190    ast_mutex_unlock(&p->lock);
04191 
04192    return res;
04193 }
04194 #endif   /* defined(HAVE_PRI_PROG_W_CAUSE) */
04195 #endif   /* defined(HAVE_PRI) */
04196 
04197 #if defined(HAVE_PRI)
04198 static int pri_is_up(struct dahdi_pri *pri)
04199 {
04200    int x;
04201    for (x = 0; x < NUM_DCHANS; x++) {
04202       if (pri->dchanavail[x] == DCHAN_AVAILABLE)
04203          return 1;
04204    }
04205    return 0;
04206 }
04207 #endif   /* defined(HAVE_PRI) */
04208 
04209 #if defined(HAVE_PRI)
04210 static int pri_assign_bearer(struct dahdi_pvt *crv, struct dahdi_pri *pri, struct dahdi_pvt *bearer)
04211 {
04212    bearer->owner = &inuse;
04213    bearer->realcall = crv;
04214    crv->subs[SUB_REAL].dfd = bearer->subs[SUB_REAL].dfd;
04215    if (crv->subs[SUB_REAL].owner)
04216       ast_channel_set_fd(crv->subs[SUB_REAL].owner, 0, crv->subs[SUB_REAL].dfd);
04217    crv->bearer = bearer;
04218    crv->call = bearer->call;
04219    crv->pri = pri;
04220    return 0;
04221 }
04222 #endif   /* defined(HAVE_PRI) */
04223 
04224 #if defined(HAVE_PRI)
04225 static char *pri_order(int level)
04226 {
04227    switch (level) {
04228    case 0:
04229       return "Primary";
04230    case 1:
04231       return "Secondary";
04232    case 2:
04233       return "Tertiary";
04234    case 3:
04235       return "Quaternary";
04236    default:
04237       return "<Unknown>";
04238    }
04239 }
04240 #endif   /* defined(HAVE_PRI) */
04241 
04242 #if defined(HAVE_PRI)
04243 /* Returns fd of the active dchan */
04244 static int pri_active_dchan_fd(struct dahdi_pri *pri)
04245 {
04246    int x = -1;
04247 
04248    for (x = 0; x < NUM_DCHANS; x++) {
04249       if ((pri->dchans[x] == pri->pri))
04250          break;
04251    }
04252 
04253    return pri->fds[x];
04254 }
04255 #endif   /* defined(HAVE_PRI) */
04256 
04257 #if defined(HAVE_PRI)
04258 static int pri_find_dchan(struct dahdi_pri *pri)
04259 {
04260    int oldslot = -1;
04261    struct pri *old;
04262    int newslot = -1;
04263    int x;
04264    old = pri->pri;
04265    for (x = 0; x < NUM_DCHANS; x++) {
04266       if ((pri->dchanavail[x] == DCHAN_AVAILABLE) && (newslot < 0))
04267          newslot = x;
04268       if (pri->dchans[x] == old) {
04269          oldslot = x;
04270       }
04271    }
04272    if (newslot < 0) {
04273       newslot = 0;
04274       /* This is annoying to see on non persistent layer 2 connections.  Let's not complain in that case */
04275       if (pri->sig != SIG_BRI_PTMP && !pri->no_d_channels) {
04276          pri->no_d_channels = 1;
04277          ast_log(LOG_WARNING,
04278             "No D-channels available!  Using Primary channel %d as D-channel anyway!\n",
04279             pri->dchannels[newslot]);
04280       }
04281    } else {
04282       pri->no_d_channels = 0;
04283    }
04284    if (old && (oldslot != newslot))
04285       ast_log(LOG_NOTICE, "Switching from from d-channel %d to channel %d!\n",
04286          pri->dchannels[oldslot], pri->dchannels[newslot]);
04287    pri->pri = pri->dchans[newslot];
04288    return 0;
04289 }
04290 #endif   /* defined(HAVE_PRI) */
04291 
04292 #if defined(HAVE_OPENR2)
04293 static const char *dahdi_accept_r2_call_app = "DAHDIAcceptR2Call";
04294 
04295 static int dahdi_accept_r2_call_exec(struct ast_channel *chan, void *data)
04296 {
04297    /* data is whether to accept with charge or no charge */
04298    openr2_call_mode_t accept_mode;
04299    int res, timeout, maxloops;
04300    struct ast_frame *f;
04301    struct dahdi_pvt *p;
04302    char *parse;
04303    AST_DECLARE_APP_ARGS(args,
04304          AST_APP_ARG(charge);
04305    );
04306 
04307    if (ast_strlen_zero(data)) {
04308       ast_log(LOG_DEBUG, "No data sent to application!\n");
04309       return -1;
04310    }
04311 
04312    if (chan->tech != &dahdi_tech) {
04313       ast_log(LOG_DEBUG, "Only DAHDI technology accepted!\n");
04314       return -1;
04315    }
04316 
04317    p = (struct dahdi_pvt *)chan->tech_pvt;
04318    if (!p) {
04319       ast_log(LOG_DEBUG, "Unable to find technology private!\n");
04320       return -1;
04321    }
04322 
04323    parse = ast_strdupa(data);
04324    AST_STANDARD_APP_ARGS(args, parse);
04325 
04326    if (ast_strlen_zero(args.charge)) {
04327       ast_log(LOG_WARNING, "DAHDIAcceptR2Call requires 'yes' or 'no' for the charge parameter\n");
04328       return -1;
04329    }
04330 
04331    ast_mutex_lock(&p->lock);
04332    if (!p->mfcr2 || !p->mfcr2call) {
04333       ast_mutex_unlock(&p->lock);
04334       ast_log(LOG_DEBUG, "Channel %s does not seems to be an R2 active channel!\n", chan->name);
04335       return -1;
04336    }
04337 
04338    if (p->mfcr2_call_accepted) {
04339       ast_mutex_unlock(&p->lock);
04340       ast_log(LOG_DEBUG, "MFC/R2 call already accepted on channel %s!\n", chan->name);
04341       return 0;
04342    }
04343    accept_mode = ast_true(args.charge) ? OR2_CALL_WITH_CHARGE : OR2_CALL_NO_CHARGE;
04344    if (openr2_chan_accept_call(p->r2chan, accept_mode)) {
04345       ast_mutex_unlock(&p->lock);
04346       ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n");
04347       return -1;
04348    }
04349    ast_mutex_unlock(&p->lock);
04350 
04351    res = 0;
04352    timeout = 100;
04353    maxloops = 50; /* wait up to 5 seconds */
04354    /* we need to read() until the call is accepted */
04355    while (maxloops > 0) {
04356       maxloops--;
04357       if (ast_check_hangup(chan)) {
04358          break;
04359       }
04360       res = ast_waitfor(chan, timeout);
04361       if (res < 0) {
04362          ast_log(LOG_DEBUG, "ast_waitfor failed on channel %s, going out ...\n", chan->name);
04363          res = -1;
04364          break;
04365       }
04366       if (res == 0) {
04367          continue;
04368       }
04369       f = ast_read(chan);
04370       if (!f) {
04371          ast_log(LOG_DEBUG, "No frame read on channel %s, going out ...\n", chan->name);
04372          res = -1;
04373          break;
04374       }
04375       if (f->frametype == AST_FRAME_CONTROL && f->subclass == AST_CONTROL_HANGUP) {
04376          ast_log(LOG_DEBUG, "Got HANGUP frame on channel %s, going out ...\n", chan->name);
04377          ast_frfree(f);
04378          res = -1;
04379          break;
04380       }
04381       ast_frfree(f);
04382       ast_mutex_lock(&p->lock);
04383       if (p->mfcr2_call_accepted) {
04384          ast_mutex_unlock(&p->lock);
04385          ast_log(LOG_DEBUG, "Accepted MFC/R2 call!\n");
04386          break;
04387       }
04388       ast_mutex_unlock(&p->lock);
04389    }
04390    if (res == -1) {
04391       ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n");
04392    }
04393    return res;
04394 }
04395 
04396 static openr2_call_disconnect_cause_t dahdi_ast_cause_to_r2_cause(int cause)
04397 {
04398    openr2_call_disconnect_cause_t r2cause = OR2_CAUSE_NORMAL_CLEARING;
04399    switch (cause) {
04400    case AST_CAUSE_USER_BUSY:
04401    case AST_CAUSE_CALL_REJECTED:
04402    case AST_CAUSE_INTERWORKING: /* I don't know wtf is this but is used sometimes when ekiga rejects a call */
04403       r2cause = OR2_CAUSE_BUSY_NUMBER;
04404       break;
04405 
04406    case AST_CAUSE_NORMAL_CIRCUIT_CONGESTION:
04407    case AST_CAUSE_SWITCH_CONGESTION:
04408       r2cause = OR2_CAUSE_NETWORK_CONGESTION;
04409       break;
04410 
04411    case AST_CAUSE_UNALLOCATED:
04412       r2cause = OR2_CAUSE_UNALLOCATED_NUMBER;
04413       break;
04414 
04415    case AST_CAUSE_NETWORK_OUT_OF_ORDER:
04416    case AST_CAUSE_DESTINATION_OUT_OF_ORDER:
04417       r2cause = OR2_CAUSE_OUT_OF_ORDER;
04418       break;
04419 
04420    case AST_CAUSE_NO_ANSWER:
04421    case AST_CAUSE_NO_USER_RESPONSE:
04422       r2cause = OR2_CAUSE_NO_ANSWER;
04423       break;
04424 
04425    default:
04426       r2cause = OR2_CAUSE_NORMAL_CLEARING;
04427       break;
04428    }
04429    ast_log(LOG_DEBUG, "ast cause %d resulted in openr2 cause %d/%s\n",
04430          cause, r2cause, openr2_proto_get_disconnect_string(r2cause));
04431    return r2cause;
04432 }
04433 #endif
04434 
04435 static int dahdi_hangup(struct ast_channel *ast)
04436 {
04437    int res;
04438    int idx,x, law;
04439    /*static int restore_gains(struct dahdi_pvt *p);*/
04440    struct dahdi_pvt *p = ast->tech_pvt;
04441    struct dahdi_pvt *tmp = NULL;
04442    struct dahdi_pvt *prev = NULL;
04443    struct dahdi_params par;
04444 
04445    ast_debug(1, "dahdi_hangup(%s)\n", ast->name);
04446    if (!ast->tech_pvt) {
04447       ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
04448       return 0;
04449    }
04450 
04451    ast_mutex_lock(&p->lock);
04452 
04453    idx = dahdi_get_index(ast, p, 1);
04454 
04455    switch (p->sig) {
04456    case SIG_PRI:
04457    case SIG_BRI:
04458    case SIG_BRI_PTMP:
04459    case SIG_SS7:
04460       x = 1;
04461       ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
04462       /* Fall through */
04463    case SIG_MFCR2:
04464       p->cid_num[0] = '\0';
04465       p->cid_name[0] = '\0';
04466       break;
04467    default:
04468       break;
04469    }
04470 
04471    x = 0;
04472    dahdi_confmute(p, 0);
04473    p->muting = 0;
04474    restore_gains(p);
04475    if (p->origcid_num) {
04476       ast_copy_string(p->cid_num, p->origcid_num, sizeof(p->cid_num));
04477       ast_free(p->origcid_num);
04478       p->origcid_num = NULL;
04479    }
04480    if (p->origcid_name) {
04481       ast_copy_string(p->cid_name, p->origcid_name, sizeof(p->cid_name));
04482       ast_free(p->origcid_name);
04483       p->origcid_name = NULL;
04484    }
04485    if (p->dsp)
04486       ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
04487    p->exten[0] = '\0';
04488 
04489    ast_debug(1, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n",
04490       p->channel, idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
04491    p->ignoredtmf = 0;
04492 
04493    if (idx > -1) {
04494       /* Real channel, do some fixup */
04495       p->subs[idx].owner = NULL;
04496       p->subs[idx].needanswer = 0;
04497       p->subs[idx].needflash = 0;
04498       p->subs[idx].needringing = 0;
04499       p->subs[idx].needbusy = 0;
04500       p->subs[idx].needcongestion = 0;
04501       p->subs[idx].linear = 0;
04502       p->subs[idx].needcallerid = 0;
04503       p->polarity = POLARITY_IDLE;
04504       dahdi_setlinear(p->subs[idx].dfd, 0);
04505       switch (idx) {
04506       case SUB_REAL:
04507          if ((p->subs[SUB_CALLWAIT].dfd > -1) && (p->subs[SUB_THREEWAY].dfd > -1)) {
04508             ast_debug(1, "Normal call hung up with both three way call and a call waiting call in place?\n");
04509             if (p->subs[SUB_CALLWAIT].inthreeway) {
04510                /* We had flipped over to answer a callwait and now it's gone */
04511                ast_debug(1, "We were flipped over to the callwait, moving back and unowning.\n");
04512                /* Move to the call-wait, but un-own us until they flip back. */
04513                swap_subs(p, SUB_CALLWAIT, SUB_REAL);
04514                unalloc_sub(p, SUB_CALLWAIT);
04515                p->owner = NULL;
04516             } else {
04517                /* The three way hung up, but we still have a call wait */
04518                ast_debug(1, "We were in the threeway and have a callwait still.  Ditching the threeway.\n");
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          } else if (p->subs[SUB_CALLWAIT].dfd > -1) {
04534             /* Need to hold the lock for real-call, private, and call-waiting call */
04535             dahdi_lock_sub_owner(p, SUB_CALLWAIT);
04536             if (!p->subs[SUB_CALLWAIT].owner) {
04537                /* The call waiting call dissappeared. */
04538                p->owner = NULL;
04539                break;
04540             }
04541 
04542             /* Move to the call-wait and switch back to them. */
04543             swap_subs(p, SUB_CALLWAIT, SUB_REAL);
04544             unalloc_sub(p, SUB_CALLWAIT);
04545             p->owner = p->subs[SUB_REAL].owner;
04546             if (p->owner->_state != AST_STATE_UP)
04547                p->subs[SUB_REAL].needanswer = 1;
04548             if (ast_bridged_channel(p->subs[SUB_REAL].owner))
04549                ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
04550             /* Unlock the call-waiting call that we swapped to real-call. */
04551             ast_channel_unlock(p->subs[SUB_REAL].owner);
04552          } else if (p->subs[SUB_THREEWAY].dfd > -1) {
04553             swap_subs(p, SUB_THREEWAY, SUB_REAL);
04554             unalloc_sub(p, SUB_THREEWAY);
04555             if (p->subs[SUB_REAL].inthreeway) {
04556                /* This was part of a three way call.  Immediately make way for
04557                   another call */
04558                ast_debug(1, "Call was complete, setting owner to former third call\n");
04559                p->subs[SUB_REAL].inthreeway = 0;
04560                p->owner = p->subs[SUB_REAL].owner;
04561             } else {
04562                /* This call hasn't been completed yet...  Set owner to NULL */
04563                ast_debug(1, "Call was incomplete, setting owner to NULL\n");
04564                p->owner = NULL;
04565             }
04566          }
04567          break;
04568       case SUB_CALLWAIT:
04569          /* Ditch the holding callwait call, and immediately make it availabe */
04570          if (p->subs[SUB_CALLWAIT].inthreeway) {
04571             /* Need to hold the lock for call-waiting call, private, and 3-way call */
04572             dahdi_lock_sub_owner(p, SUB_THREEWAY);
04573 
04574             /* This is actually part of a three way, placed on hold.  Place the third part
04575                on music on hold now */
04576             if (p->subs[SUB_THREEWAY].owner && ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
04577                ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
04578                   S_OR(p->mohsuggest, NULL),
04579                   !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
04580             }
04581             p->subs[SUB_THREEWAY].inthreeway = 0;
04582             /* Make it the call wait now */
04583             swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
04584             unalloc_sub(p, SUB_THREEWAY);
04585             if (p->subs[SUB_CALLWAIT].owner) {
04586                /* Unlock the 3-way call that we swapped to call-waiting call. */
04587                ast_channel_unlock(p->subs[SUB_CALLWAIT].owner);
04588             }
04589          } else
04590             unalloc_sub(p, SUB_CALLWAIT);
04591          break;
04592       case SUB_THREEWAY:
04593          /* Need to hold the lock for 3-way call, private, and call-waiting call */
04594          dahdi_lock_sub_owner(p, SUB_CALLWAIT);
04595          if (p->subs[SUB_CALLWAIT].inthreeway) {
04596             /* The other party of the three way call is currently in a call-wait state.
04597                Start music on hold for them, and take the main guy out of the third call */
04598             p->subs[SUB_CALLWAIT].inthreeway = 0;
04599             if (p->subs[SUB_CALLWAIT].owner && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
04600                ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
04601                   S_OR(p->mohsuggest, NULL),
04602                   !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
04603             }
04604          }
04605          if (p->subs[SUB_CALLWAIT].owner) {
04606             ast_channel_unlock(p->subs[SUB_CALLWAIT].owner);
04607          }
04608          p->subs[SUB_REAL].inthreeway = 0;
04609          /* If this was part of a three way call index, let us make
04610             another three way call */
04611          unalloc_sub(p, SUB_THREEWAY);
04612          break;
04613       default:
04614          /*
04615           * Should never happen.
04616           * This wasn't any sort of call, so how are we an index?
04617           */
04618          ast_log(LOG_ERROR, "Index found but not any type of call?\n");
04619          break;
04620       }
04621    }
04622 
04623    if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) {
04624       p->ringt = 0;
04625       p->distinctivering = 0;
04626       p->confirmanswer = 0;
04627       p->cidrings = 1;
04628       p->outgoing = 0;
04629       p->digital = 0;
04630       p->faxhandled = 0;
04631       p->pulsedial = 0;
04632       p->onhooktime = time(NULL);
04633 #if defined(HAVE_PRI) || defined(HAVE_SS7)
04634       p->dialing = 0;
04635       p->progress = 0;
04636       p->rlt = 0;
04637       p->call_level = DAHDI_CALL_LEVEL_IDLE;
04638 #endif
04639       if (p->dsp) {
04640          ast_dsp_free(p->dsp);
04641          p->dsp = NULL;
04642       }
04643 
04644       if (p->bufferoverrideinuse) {
04645          /* faxbuffers are in use, revert them */
04646          struct dahdi_bufferinfo bi = {
04647             .txbufpolicy = p->buf_policy,
04648             .rxbufpolicy = p->buf_policy,
04649             .bufsize = p->bufsize,
04650             .numbufs = p->buf_no
04651          };
04652          int bpres;
04653 
04654          if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
04655             ast_log(LOG_WARNING, "Channel '%s' unable to revert faxbuffer policy: %s\n", ast->name, strerror(errno));
04656          }
04657          p->bufferoverrideinuse = 0;
04658       }
04659 
04660       law = DAHDI_LAW_DEFAULT;
04661       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
04662       if (res < 0)
04663          ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
04664       /* Perform low level hangup if no owner left */
04665 #ifdef HAVE_SS7
04666       if (p->ss7) {
04667          if (p->ss7call) {
04668             if (!ss7_grab(p, p->ss7)) {
04669                if (!p->alreadyhungup) {
04670                   const char *cause = pbx_builtin_getvar_helper(ast,"SS7_CAUSE");
04671                   int icause = ast->hangupcause ? ast->hangupcause : -1;
04672 
04673                   if (cause) {
04674                      if (atoi(cause))
04675                         icause = atoi(cause);
04676                   }
04677                   isup_rel(p->ss7->ss7, p->ss7call, icause);
04678                   ss7_rel(p->ss7);
04679                   p->alreadyhungup = 1;
04680                } else
04681                   ast_log(LOG_WARNING, "Trying to hangup twice!\n");
04682             } else {
04683                ast_log(LOG_WARNING, "Unable to grab SS7 on CIC %d\n", p->cic);
04684                res = -1;
04685             }
04686          }
04687       }
04688 #endif
04689 #ifdef HAVE_OPENR2
04690       if (p->mfcr2 && p->mfcr2call && openr2_chan_get_direction(p->r2chan) != OR2_DIR_STOPPED) {
04691          ast_log(LOG_DEBUG, "disconnecting MFC/R2 call on chan %d\n", p->channel);
04692          /* If it's an incoming call, check the mfcr2_forced_release setting */
04693          if (openr2_chan_get_direction(p->r2chan) == OR2_DIR_BACKWARD && p->mfcr2_forced_release) {
04694             dahdi_r2_disconnect_call(p, OR2_CAUSE_FORCED_RELEASE);
04695          } else {
04696             const char *r2causestr = pbx_builtin_getvar_helper(ast, "MFCR2_CAUSE");
04697             int r2cause_user = r2causestr ? atoi(r2causestr) : 0;
04698             openr2_call_disconnect_cause_t r2cause = r2cause_user ? dahdi_ast_cause_to_r2_cause(r2cause_user)
04699                                                              : dahdi_ast_cause_to_r2_cause(ast->hangupcause);
04700             dahdi_r2_disconnect_call(p, r2cause);
04701          }
04702       } else if (p->mfcr2call) {
04703          ast_log(LOG_DEBUG, "Clearing call request on channel %d\n", p->channel);
04704          /* since ast_request() was called but not ast_call() we have not yet dialed
04705          and the openr2 stack will not call on_call_end callback, we need to unset
04706          the mfcr2call flag and bump the monitor count so the monitor thread can take
04707          care of this channel events from now on */
04708          p->mfcr2call = 0;
04709       }
04710 #endif
04711 #if defined(HAVE_PRI)
04712       if (p->pri) {
04713 #ifdef SUPPORT_USERUSER
04714          const char *useruser = pbx_builtin_getvar_helper(ast,"USERUSERINFO");
04715 #endif
04716 
04717          /* Make sure we have a call (or REALLY have a call in the case of a PRI) */
04718          pri_grab(p, p->pri);
04719          if (p->call && (!p->bearer || (p->bearer->call == p->call))) {
04720             if (p->alreadyhungup) {
04721                ast_debug(1, "Already hungup...  Calling hangup once, and clearing call\n");
04722 
04723 #ifdef SUPPORT_USERUSER
04724                pri_call_set_useruser(p->call, useruser);
04725 #endif
04726 
04727                pri_hangup(p->pri->pri, p->call, -1);
04728                p->call = NULL;
04729                if (p->bearer)
04730                   p->bearer->call = NULL;
04731             } else {
04732                const char *cause = pbx_builtin_getvar_helper(ast,"PRI_CAUSE");
04733                int icause = ast->hangupcause ? ast->hangupcause : -1;
04734                ast_debug(1, "Not yet hungup...  Calling hangup once with icause, and clearing call\n");
04735 
04736 #ifdef SUPPORT_USERUSER
04737                pri_call_set_useruser(p->call, useruser);
04738 #endif
04739 
04740                p->alreadyhungup = 1;
04741                if (p->bearer)
04742                   p->bearer->alreadyhungup = 1;
04743                if (cause) {
04744                   if (atoi(cause))
04745                      icause = atoi(cause);
04746                }
04747                pri_hangup(p->pri->pri, p->call, icause);
04748             }
04749          } else {
04750             if (p->bearer)
04751                ast_debug(1, "Bearer call is %p, while ours is still %p\n", p->bearer->call, p->call);
04752             p->call = NULL;
04753          }
04754          p->allocated = 0;
04755          p->owner = NULL;
04756          pri_rel(p->pri);
04757          res = 0;
04758       } else
04759 #endif   /* defined(HAVE_PRI) */
04760       {
04761          p->owner = NULL;
04762       }
04763       if (p->sig && ((p->sig != SIG_PRI) && (p->sig != SIG_SS7)
04764          && (p->sig != SIG_BRI)
04765          && (p->sig != SIG_BRI_PTMP))
04766          && (p->sig != SIG_MFCR2))
04767          res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
04768       if (res < 0) {
04769          ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast->name);
04770       }
04771       switch (p->sig) {
04772       case SIG_FXOGS:
04773       case SIG_FXOLS:
04774       case SIG_FXOKS:
04775          memset(&par, 0, sizeof(par));
04776          res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
04777          if (!res) {
04778 #if 0
04779             ast_debug(1, "Hanging up channel %d, offhook = %d\n", p->channel, par.rxisoffhook);
04780 #endif
04781             /* If they're off hook, try playing congestion */
04782             if ((par.rxisoffhook) && (!(p->radio || (p->oprmode < 0))))
04783                tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
04784             else
04785                tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
04786             p->fxsoffhookstate = par.rxisoffhook;
04787          }
04788          break;
04789       case SIG_FXSGS:
04790       case SIG_FXSLS:
04791       case SIG_FXSKS:
04792          /* Make sure we're not made available for at least two seconds assuming
04793             we were actually used for an inbound or outbound call. */
04794          if (ast->_state != AST_STATE_RESERVED) {
04795             time(&p->guardtime);
04796             p->guardtime += 2;
04797          }
04798          break;
04799       default:
04800          tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
04801       }
04802       ast_free(p->cidspill);
04803       p->cidspill = NULL;
04804       if (p->sig)
04805          dahdi_disable_ec(p);
04806       x = 0;
04807       ast_channel_setoption(ast,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0);
04808       ast_channel_setoption(ast,AST_OPTION_TDD,&x,sizeof(char),0);
04809       p->didtdd = 0;
04810       p->callwaitcas = 0;
04811       p->callwaiting = p->permcallwaiting;
04812       p->hidecallerid = p->permhidecallerid;
04813       p->waitingfordt.tv_sec = 0;
04814       p->dialing = 0;
04815       p->rdnis[0] = '\0';
04816       update_conf(p);
04817       reset_conf(p);
04818       /* Restore data mode */
04819       if ((p->sig == SIG_PRI) || (p->sig == SIG_SS7) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) {
04820          x = 0;
04821          ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
04822       }
04823 #ifdef HAVE_PRI
04824       if (p->bearer) {
04825          ast_debug(1, "Freeing up bearer channel %d\n", p->bearer->channel);
04826          /* Free up the bearer channel as well, and
04827             don't use its file descriptor anymore */
04828          update_conf(p->bearer);
04829          reset_conf(p->bearer);
04830          p->bearer->owner = NULL;
04831          p->bearer->realcall = NULL;
04832          p->bearer = NULL;
04833          p->subs[SUB_REAL].dfd = -1;
04834          p->pri = NULL;
04835       }
04836 #endif
04837       if (num_restart_pending == 0)
04838          restart_monitor();
04839    }
04840 
04841    p->callwaitingrepeat = 0;
04842    p->cidcwexpire = 0;
04843    p->cid_suppress_expire = 0;
04844    p->oprmode = 0;
04845    ast->tech_pvt = NULL;
04846    ast_mutex_unlock(&p->lock);
04847    ast_verb(3, "Hungup '%s'\n", ast->name);
04848 
04849    ast_mutex_lock(&iflock);
04850    if (p->restartpending) {
04851       num_restart_pending--;
04852    }
04853 
04854    tmp = iflist;
04855    prev = NULL;
04856    if (p->destroy) {
04857       while (tmp) {
04858          if (tmp == p) {
04859             destroy_channel(prev, tmp, 0);
04860             break;
04861          } else {
04862             prev = tmp;
04863             tmp = tmp->next;
04864          }
04865       }
04866    }
04867    ast_mutex_unlock(&iflock);
04868 
04869    ast_module_unref(ast_module_info->self);
04870    return 0;
04871 }
04872 
04873 static int dahdi_answer(struct ast_channel *ast)
04874 {
04875    struct dahdi_pvt *p = ast->tech_pvt;
04876    int res = 0;
04877    int idx;
04878    int oldstate = ast->_state;
04879    ast_setstate(ast, AST_STATE_UP);
04880    ast_mutex_lock(&p->lock);
04881    idx = dahdi_get_index(ast, p, 0);
04882    if (idx < 0)
04883       idx = SUB_REAL;
04884    /* nothing to do if a radio channel */
04885    if ((p->radio || (p->oprmode < 0))) {
04886       ast_mutex_unlock(&p->lock);
04887       return 0;
04888    }
04889    switch (p->sig) {
04890    case SIG_FXSLS:
04891    case SIG_FXSGS:
04892    case SIG_FXSKS:
04893       p->ringt = 0;
04894       /* Fall through */
04895    case SIG_EM:
04896    case SIG_EM_E1:
04897    case SIG_EMWINK:
04898    case SIG_FEATD:
04899    case SIG_FEATDMF:
04900    case SIG_FEATDMF_TA:
04901    case SIG_E911:
04902    case SIG_FGC_CAMA:
04903    case SIG_FGC_CAMAMF:
04904    case SIG_FEATB:
04905    case SIG_SF:
04906    case SIG_SFWINK:
04907    case SIG_SF_FEATD:
04908    case SIG_SF_FEATDMF:
04909    case SIG_SF_FEATB:
04910    case SIG_FXOLS:
04911    case SIG_FXOGS:
04912    case SIG_FXOKS:
04913       /* Pick up the line */
04914       ast_debug(1, "Took %s off hook\n", ast->name);
04915       if (p->hanguponpolarityswitch) {
04916          p->polaritydelaytv = ast_tvnow();
04917       }
04918       res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
04919       tone_zone_play_tone(p->subs[idx].dfd, -1);
04920       p->dialing = 0;
04921       if ((idx == SUB_REAL) && p->subs[SUB_THREEWAY].inthreeway) {
04922          if (oldstate == AST_STATE_RINGING) {
04923             ast_debug(1, "Finally swapping real and threeway\n");
04924             tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, -1);
04925             swap_subs(p, SUB_THREEWAY, SUB_REAL);
04926             p->owner = p->subs[SUB_REAL].owner;
04927          }
04928       }
04929       if (p->sig & __DAHDI_SIG_FXS) {
04930          dahdi_enable_ec(p);
04931          dahdi_train_ec(p);
04932       }
04933       break;
04934 #ifdef HAVE_PRI
04935    case SIG_BRI:
04936    case SIG_BRI_PTMP:
04937    case SIG_PRI:
04938       /* Send a pri acknowledge */
04939       if (!pri_grab(p, p->pri)) {
04940          if (p->call_level < DAHDI_CALL_LEVEL_CONNECT) {
04941             p->call_level = DAHDI_CALL_LEVEL_CONNECT;
04942          }
04943          p->dialing = 0;
04944          res = pri_answer(p->pri->pri, p->call, 0, !p->digital);
04945          pri_rel(p->pri);
04946       } else {
04947          ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
04948          res = -1;
04949       }
04950       break;
04951 #endif
04952 #ifdef HAVE_SS7
04953    case SIG_SS7:
04954       if (!ss7_grab(p, p->ss7)) {
04955          if (p->call_level < DAHDI_CALL_LEVEL_CONNECT) {
04956             p->call_level = DAHDI_CALL_LEVEL_CONNECT;
04957          }
04958          res = isup_anm(p->ss7->ss7, p->ss7call);
04959          ss7_rel(p->ss7);
04960       } else {
04961          ast_log(LOG_WARNING, "Unable to grab SS7 on span %d\n", p->span);
04962          res = -1;
04963       }
04964       break;
04965 #endif
04966 #ifdef HAVE_OPENR2
04967    case SIG_MFCR2:
04968       if (!p->mfcr2_call_accepted) {
04969          /* The call was not accepted on offer nor the user, so it must be accepted now before answering,
04970             openr2_chan_answer_call will be called when the callback on_call_accepted is executed */
04971          p->mfcr2_answer_pending = 1;
04972          if (p->mfcr2_charge_calls) {
04973             ast_log(LOG_DEBUG, "Accepting MFC/R2 call with charge before answering on chan %d\n", p->channel);
04974             openr2_chan_accept_call(p->r2chan, OR2_CALL_WITH_CHARGE);
04975          } else {
04976             ast_log(LOG_DEBUG, "Accepting MFC/R2 call with no charge before answering on chan %d\n", p->channel);
04977             openr2_chan_accept_call(p->r2chan, OR2_CALL_NO_CHARGE);
04978          }
04979       } else {
04980          ast_log(LOG_DEBUG, "Answering MFC/R2 call on chan %d\n", p->channel);
04981          dahdi_r2_answer(p);
04982       }
04983       break;
04984 #endif
04985    case 0:
04986       ast_mutex_unlock(&p->lock);
04987       return 0;
04988    default:
04989       ast_log(LOG_WARNING, "Don't know how to answer signalling %d (channel %d)\n", p->sig, p->channel);
04990       res = -1;
04991    }
04992    ast_mutex_unlock(&p->lock);
04993    return res;
04994 }
04995 
04996 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen)
04997 {
04998    char *cp;
04999    signed char *scp;
05000    int x;
05001    int idx;
05002    struct dahdi_pvt *p = chan->tech_pvt, *pp;
05003    struct oprmode *oprmode;
05004 
05005 
05006    /* all supported options require data */
05007    if (!data || (datalen < 1)) {
05008       errno = EINVAL;
05009       return -1;
05010    }
05011 
05012    switch (option) {
05013    case AST_OPTION_TXGAIN:
05014       scp = (signed char *) data;
05015       idx = dahdi_get_index(chan, p, 0);
05016       if (idx < 0) {
05017          ast_log(LOG_WARNING, "No index in TXGAIN?\n");
05018          return -1;
05019       }
05020       ast_debug(1, "Setting actual tx gain on %s to %f\n", chan->name, p->txgain + (float) *scp);
05021       return set_actual_txgain(p->subs[idx].dfd, 0, p->txgain + (float) *scp, p->law);
05022    case AST_OPTION_RXGAIN:
05023       scp = (signed char *) data;
05024       idx = dahdi_get_index(chan, p, 0);
05025       if (idx < 0) {
05026          ast_log(LOG_WARNING, "No index in RXGAIN?\n");
05027          return -1;
05028       }
05029       ast_debug(1, "Setting actual rx gain on %s to %f\n", chan->name, p->rxgain + (float) *scp);
05030       return set_actual_rxgain(p->subs[idx].dfd, 0, p->rxgain + (float) *scp, p->law);
05031    case AST_OPTION_TONE_VERIFY:
05032       if (!p->dsp)
05033          break;
05034       cp = (char *) data;
05035       switch (*cp) {
05036       case 1:
05037          ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",chan->name);
05038          ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | p->dtmfrelax);  /* set mute mode if desired */
05039          break;
05040       case 2:
05041          ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",chan->name);
05042          ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX | p->dtmfrelax);  /* set mute mode if desired */
05043          break;
05044       default:
05045          ast_debug(1, "Set option TONE VERIFY, mode: OFF(0) on %s\n",chan->name);
05046          ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);  /* set mute mode if desired */
05047          break;
05048       }
05049       break;
05050    case AST_OPTION_TDD:
05051       /* turn on or off TDD */
05052       cp = (char *) data;
05053       p->mate = 0;
05054       if (!*cp) { /* turn it off */
05055          ast_debug(1, "Set option TDD MODE, value: OFF(0) on %s\n",chan->name);
05056          if (p->tdd)
05057             tdd_free(p->tdd);
05058          p->tdd = 0;
05059          break;
05060       }
05061       ast_debug(1, "Set option TDD MODE, value: %s(%d) on %s\n",
05062          (*cp == 2) ? "MATE" : "ON", (int) *cp, chan->name);
05063       dahdi_disable_ec(p);
05064       /* otherwise, turn it on */
05065       if (!p->didtdd) { /* if havent done it yet */
05066          unsigned char mybuf[41000];/*! \todo XXX This is an abuse of the stack!! */
05067          unsigned char *buf;
05068          int size, res, fd, len;
05069          struct pollfd fds[1];
05070 
05071          buf = mybuf;
05072          memset(buf, 0x7f, sizeof(mybuf)); /* set to silence */
05073          ast_tdd_gen_ecdisa(buf + 16000, 16000);  /* put in tone */
05074          len = 40000;
05075          idx = dahdi_get_index(chan, p, 0);
05076          if (idx < 0) {
05077             ast_log(LOG_WARNING, "No index in TDD?\n");
05078             return -1;
05079          }
05080          fd = p->subs[idx].dfd;
05081          while (len) {
05082             if (ast_check_hangup(chan))
05083                return -1;
05084             size = len;
05085             if (size > READ_SIZE)
05086                size = READ_SIZE;
05087             fds[0].fd = fd;
05088             fds[0].events = POLLPRI | POLLOUT;
05089             fds[0].revents = 0;
05090             res = poll(fds, 1, -1);
05091             if (!res) {
05092                ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
05093                continue;
05094             }
05095             /* if got exception */
05096             if (fds[0].revents & POLLPRI)
05097                return -1;
05098             if (!(fds[0].revents & POLLOUT)) {
05099                ast_debug(1, "write fd not ready on channel %d\n", p->channel);
05100                continue;
05101             }
05102             res = write(fd, buf, size);
05103             if (res != size) {
05104                if (res == -1) return -1;
05105                ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
05106                break;
05107             }
05108             len -= size;
05109             buf += size;
05110          }
05111          p->didtdd = 1; /* set to have done it now */
05112       }
05113       if (*cp == 2) { /* Mate mode */
05114          if (p->tdd)
05115             tdd_free(p->tdd);
05116          p->tdd = 0;
05117          p->mate = 1;
05118          break;
05119       }
05120       if (!p->tdd) { /* if we dont have one yet */
05121          p->tdd = tdd_new(); /* allocate one */
05122       }
05123       break;
05124    case AST_OPTION_RELAXDTMF:  /* Relax DTMF decoding (or not) */
05125       if (!p->dsp)
05126          break;
05127       cp = (char *) data;
05128       ast_debug(1, "Set option RELAX DTMF, value: %s(%d) on %s\n",
05129          *cp ? "ON" : "OFF", (int) *cp, chan->name);
05130       ast_dsp_set_digitmode(p->dsp, ((*cp) ? DSP_DIGITMODE_RELAXDTMF : DSP_DIGITMODE_DTMF) | p->dtmfrelax);
05131       break;
05132    case AST_OPTION_AUDIO_MODE:  /* Set AUDIO mode (or not) */
05133       cp = (char *) data;
05134       if (!*cp) {
05135          ast_debug(1, "Set option AUDIO MODE, value: OFF(0) on %s\n", chan->name);
05136          x = 0;
05137          dahdi_disable_ec(p);
05138       } else {
05139          ast_debug(1, "Set option AUDIO MODE, value: ON(1) on %s\n", chan->name);
05140          x = 1;
05141       }
05142       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x) == -1)
05143          ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, x, strerror(errno));
05144       break;
05145    case AST_OPTION_OPRMODE:  /* Operator services mode */
05146       oprmode = (struct oprmode *) data;
05147       /* We don't support operator mode across technologies */
05148       if (strcasecmp(chan->tech->type, oprmode->peer->tech->type)) {
05149          ast_log(LOG_NOTICE, "Operator mode not supported on %s to %s calls.\n",
05150                chan->tech->type, oprmode->peer->tech->type);
05151          errno = EINVAL;
05152          return -1;
05153       }
05154       pp = oprmode->peer->tech_pvt;
05155       p->oprmode = pp->oprmode = 0;
05156       /* setup peers */
05157       p->oprpeer = pp;
05158       pp->oprpeer = p;
05159       /* setup modes, if any */
05160       if (oprmode->mode)
05161       {
05162          pp->oprmode = oprmode->mode;
05163          p->oprmode = -oprmode->mode;
05164       }
05165       ast_debug(1, "Set Operator Services mode, value: %d on %s/%s\n",
05166          oprmode->mode, chan->name,oprmode->peer->name);
05167       break;
05168    case AST_OPTION_ECHOCAN:
05169       cp = (char *) data;
05170       if (*cp) {
05171          ast_debug(1, "Enabling echo cancellation on %s\n", chan->name);
05172          dahdi_enable_ec(p);
05173       } else {
05174          ast_debug(1, "Disabling echo cancellation on %s\n", chan->name);
05175          dahdi_disable_ec(p);
05176       }
05177       break;
05178    }
05179    errno = 0;
05180 
05181    return 0;
05182 }
05183 
05184 static int dahdi_func_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len)
05185 {
05186    struct dahdi_pvt *p = chan->tech_pvt;
05187    int res = 0;
05188 
05189    if (!strcasecmp(data, "rxgain")) {
05190       ast_mutex_lock(&p->lock);
05191       snprintf(buf, len, "%f", p->rxgain);
05192       ast_mutex_unlock(&p->lock);
05193    } else if (!strcasecmp(data, "txgain")) {
05194       ast_mutex_lock(&p->lock);
05195       snprintf(buf, len, "%f", p->txgain);
05196       ast_mutex_unlock(&p->lock);
05197    } else {
05198       ast_copy_string(buf, "", len);
05199       res = -1;
05200    }
05201 
05202    return res;
05203 }
05204 
05205 
05206 static int parse_buffers_policy(const char *parse, int *num_buffers, int *policy)
05207 {
05208    int res;
05209    char policy_str[21] = "";
05210    
05211    if (((res = sscanf(parse, "%d,%20s", num_buffers, policy_str)) != 2) &&
05212       ((res = sscanf(parse, "%d|%20s", num_buffers, policy_str)) != 2)) {
05213       ast_log(LOG_WARNING, "Parsing buffer string '%s' failed.\n", parse);
05214       return 1;
05215    }
05216    if (*num_buffers < 0) {
05217       ast_log(LOG_WARNING, "Invalid buffer count given '%d'.\n", *num_buffers);
05218       return -1;
05219    }
05220    if (!strcasecmp(policy_str, "full")) {
05221       *policy = DAHDI_POLICY_WHEN_FULL;
05222    } else if (!strcasecmp(policy_str, "immediate")) {
05223       *policy = DAHDI_POLICY_IMMEDIATE;
05224 #ifdef DAHDI_POLICY_HALF_FULL
05225    } else if (!strcasecmp(policy_str, "half")) {
05226       *policy = DAHDI_POLICY_HALF_FULL;
05227 #endif
05228    } else {
05229       ast_log(LOG_WARNING, "Invalid policy name given '%s'.\n", policy_str);
05230       return -1;
05231    }
05232 
05233    return 0;
05234 }
05235 
05236 static int dahdi_func_write(struct ast_channel *chan, const char *function, char *data, const char *value)
05237 {
05238    struct dahdi_pvt *p = chan->tech_pvt;
05239    int res = 0;
05240 
05241    if (!strcasecmp(data, "buffers")) {
05242       int num_bufs, policy;
05243 
05244       if (!(parse_buffers_policy(value, &num_bufs, &policy))) {
05245          struct dahdi_bufferinfo bi = {
05246             .txbufpolicy = policy,
05247             .rxbufpolicy = policy,
05248             .bufsize = p->bufsize,
05249             .numbufs = num_bufs,
05250          };
05251          int bpres;
05252 
05253          if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
05254             ast_log(LOG_WARNING, "Channel '%d' unable to override buffer policy: %s\n", p->channel, strerror(errno));
05255          } else {
05256             p->bufferoverrideinuse = 1;
05257          }
05258       } else {
05259          res = -1;
05260       }
05261    } else {
05262       res = -1;
05263    }
05264 
05265    return res;
05266 }
05267 
05268 static void dahdi_unlink(struct dahdi_pvt *slave, struct dahdi_pvt *master, int needlock)
05269 {
05270    /* Unlink a specific slave or all slaves/masters from a given master */
05271    int x;
05272    int hasslaves;
05273    if (!master)
05274       return;
05275    if (needlock) {
05276       ast_mutex_lock(&master->lock);
05277       if (slave) {
05278          while (ast_mutex_trylock(&slave->lock)) {
05279             DEADLOCK_AVOIDANCE(&master->lock);
05280          }
05281       }
05282    }
05283    hasslaves = 0;
05284    for (x = 0; x < MAX_SLAVES; x++) {
05285       if (master->slaves[x]) {
05286          if (!slave || (master->slaves[x] == slave)) {
05287             /* Take slave out of the conference */
05288             ast_debug(1, "Unlinking slave %d from %d\n", master->slaves[x]->channel, master->channel);
05289             conf_del(master, &master->slaves[x]->subs[SUB_REAL], SUB_REAL);
05290             conf_del(master->slaves[x], &master->subs[SUB_REAL], SUB_REAL);
05291             master->slaves[x]->master = NULL;
05292             master->slaves[x] = NULL;
05293          } else
05294             hasslaves = 1;
05295       }
05296       if (!hasslaves)
05297          master->inconference = 0;
05298    }
05299    if (!slave) {
05300       if (master->master) {
05301          /* Take master out of the conference */
05302          conf_del(master->master, &master->subs[SUB_REAL], SUB_REAL);
05303          conf_del(master, &master->master->subs[SUB_REAL], SUB_REAL);
05304          hasslaves = 0;
05305          for (x = 0; x < MAX_SLAVES; x++) {
05306             if (master->master->slaves[x] == master)
05307                master->master->slaves[x] = NULL;
05308             else if (master->master->slaves[x])
05309                hasslaves = 1;
05310          }
05311          if (!hasslaves)
05312             master->master->inconference = 0;
05313       }
05314       master->master = NULL;
05315    }
05316    update_conf(master);
05317    if (needlock) {
05318       if (slave)
05319          ast_mutex_unlock(&slave->lock);
05320       ast_mutex_unlock(&master->lock);
05321    }
05322 }
05323 
05324 static void dahdi_link(struct dahdi_pvt *slave, struct dahdi_pvt *master) {
05325    int x;
05326    if (!slave || !master) {
05327       ast_log(LOG_WARNING, "Tried to link to/from NULL??\n");
05328       return;
05329    }
05330    for (x = 0; x < MAX_SLAVES; x++) {
05331       if (!master->slaves[x]) {
05332          master->slaves[x] = slave;
05333          break;
05334       }
05335    }
05336    if (x >= MAX_SLAVES) {
05337       ast_log(LOG_WARNING, "Replacing slave %d with new slave, %d\n", master->slaves[MAX_SLAVES - 1]->channel, slave->channel);
05338       master->slaves[MAX_SLAVES - 1] = slave;
05339    }
05340    if (slave->master)
05341       ast_log(LOG_WARNING, "Replacing master %d with new master, %d\n", slave->master->channel, master->channel);
05342    slave->master = master;
05343 
05344    ast_debug(1, "Making %d slave to master %d at %d\n", slave->channel, master->channel, x);
05345 }
05346 
05347 static void disable_dtmf_detect(struct dahdi_pvt *p)
05348 {
05349    int val;
05350 
05351    p->ignoredtmf = 1;
05352 
05353    val = 0;
05354    ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
05355 
05356    if (!p->hardwaredtmf && p->dsp) {
05357       p->dsp_features &= ~DSP_FEATURE_DIGIT_DETECT;
05358       ast_dsp_set_features(p->dsp, p->dsp_features);
05359    }
05360 }
05361 
05362 static void enable_dtmf_detect(struct dahdi_pvt *p)
05363 {
05364    int val;
05365 
05366    if (p->channel == CHAN_PSEUDO)
05367       return;
05368 
05369    p->ignoredtmf = 0;
05370 
05371    val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
05372    ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
05373 
05374    if (!p->hardwaredtmf && p->dsp) {
05375       p->dsp_features |= DSP_FEATURE_DIGIT_DETECT;
05376       ast_dsp_set_features(p->dsp, p->dsp_features);
05377    }
05378 }
05379 
05380 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)
05381 {
05382    struct ast_channel *who;
05383    struct dahdi_pvt *p0, *p1, *op0, *op1;
05384    struct dahdi_pvt *master = NULL, *slave = NULL;
05385    struct ast_frame *f;
05386    int inconf = 0;
05387    int nothingok = 1;
05388    int ofd0, ofd1;
05389    int oi0, oi1, i0 = -1, i1 = -1, t0, t1;
05390    int os0 = -1, os1 = -1;
05391    int priority = 0;
05392    struct ast_channel *oc0, *oc1;
05393    enum ast_bridge_result res;
05394 
05395 #ifdef PRI_2BCT
05396    int triedtopribridge = 0;
05397 #endif
05398 
05399    /* For now, don't attempt to native bridge if either channel needs DTMF detection.
05400       There is code below to handle it properly until DTMF is actually seen,
05401       but due to currently unresolved issues it's ignored...
05402    */
05403 
05404    if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1))
05405       return AST_BRIDGE_FAILED_NOWARN;
05406 
05407    ast_channel_lock(c0);
05408    while (ast_channel_trylock(c1)) {
05409       CHANNEL_DEADLOCK_AVOIDANCE(c0);
05410    }
05411 
05412    p0 = c0->tech_pvt;
05413    p1 = c1->tech_pvt;
05414    /* cant do pseudo-channels here */
05415    if (!p0 || (!p0->sig) || !p1 || (!p1->sig)) {
05416       ast_channel_unlock(c0);
05417       ast_channel_unlock(c1);
05418       return AST_BRIDGE_FAILED_NOWARN;
05419    }
05420 
05421    oi0 = dahdi_get_index(c0, p0, 0);
05422    oi1 = dahdi_get_index(c1, p1, 0);
05423    if ((oi0 < 0) || (oi1 < 0)) {
05424       ast_channel_unlock(c0);
05425       ast_channel_unlock(c1);
05426       return AST_BRIDGE_FAILED;
05427    }
05428 
05429    op0 = p0 = c0->tech_pvt;
05430    op1 = p1 = c1->tech_pvt;
05431    ofd0 = c0->fds[0];
05432    ofd1 = c1->fds[0];
05433    oc0 = p0->owner;
05434    oc1 = p1->owner;
05435 
05436    if (ast_mutex_trylock(&p0->lock)) {
05437       /* Don't block, due to potential for deadlock */
05438       ast_channel_unlock(c0);
05439       ast_channel_unlock(c1);
05440       ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
05441       return AST_BRIDGE_RETRY;
05442    }
05443    if (ast_mutex_trylock(&p1->lock)) {
05444       /* Don't block, due to potential for deadlock */
05445       ast_mutex_unlock(&p0->lock);
05446       ast_channel_unlock(c0);
05447       ast_channel_unlock(c1);
05448       ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
05449       return AST_BRIDGE_RETRY;
05450    }
05451 
05452    if ((p0->callwaiting && p0->callwaitingcallerid)
05453       || (p1->callwaiting && p1->callwaitingcallerid)) {
05454       /*
05455        * Call Waiting Caller ID requires DTMF detection to know if it
05456        * can send the CID spill.
05457        *
05458        * For now, don't attempt to native bridge if either channel
05459        * needs DTMF detection.  There is code below to handle it
05460        * properly until DTMF is actually seen, but due to currently
05461        * unresolved issues it's ignored...
05462        */
05463       ast_mutex_unlock(&p0->lock);
05464       ast_mutex_unlock(&p1->lock);
05465       ast_channel_unlock(c0);
05466       ast_channel_unlock(c1);
05467       return AST_BRIDGE_FAILED_NOWARN;
05468    }
05469 
05470    if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
05471       if (p0->owner && p1->owner) {
05472          /* If we don't have a call-wait in a 3-way, and we aren't in a 3-way, we can be master */
05473          if (!p0->subs[SUB_CALLWAIT].inthreeway && !p1->subs[SUB_REAL].inthreeway) {
05474             master = p0;
05475             slave = p1;
05476             inconf = 1;
05477          } else if (!p1->subs[SUB_CALLWAIT].inthreeway && !p0->subs[SUB_REAL].inthreeway) {
05478             master = p1;
05479             slave = p0;
05480             inconf = 1;
05481          } else {
05482             ast_log(LOG_WARNING, "Huh?  Both calls are callwaits or 3-ways?  That's clever...?\n");
05483             ast_log(LOG_WARNING, "p0: chan %d/%d/CW%d/3W%d, p1: chan %d/%d/CW%d/3W%d\n",
05484                p0->channel,
05485                oi0, (p0->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
05486                p0->subs[SUB_REAL].inthreeway, p0->channel,
05487                oi0, (p1->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
05488                p1->subs[SUB_REAL].inthreeway);
05489          }
05490          nothingok = 0;
05491       }
05492    } else if ((oi0 == SUB_REAL) && (oi1 == SUB_THREEWAY)) {
05493       if (p1->subs[SUB_THREEWAY].inthreeway) {
05494          master = p1;
05495          slave = p0;
05496          nothingok = 0;
05497       }
05498    } else if ((oi0 == SUB_THREEWAY) && (oi1 == SUB_REAL)) {
05499       if (p0->subs[SUB_THREEWAY].inthreeway) {
05500          master = p0;
05501          slave = p1;
05502          nothingok = 0;
05503       }
05504    } else if ((oi0 == SUB_REAL) && (oi1 == SUB_CALLWAIT)) {
05505       /* We have a real and a call wait.  If we're in a three way call, put us in it, otherwise,
05506          don't put us in anything */
05507       if (p1->subs[SUB_CALLWAIT].inthreeway) {
05508          master = p1;
05509          slave = p0;
05510          nothingok = 0;
05511       }
05512    } else if ((oi0 == SUB_CALLWAIT) && (oi1 == SUB_REAL)) {
05513       /* Same as previous */
05514       if (p0->subs[SUB_CALLWAIT].inthreeway) {
05515          master = p0;
05516          slave = p1;
05517          nothingok = 0;
05518       }
05519    }
05520    ast_debug(1, "master: %d, slave: %d, nothingok: %d\n",
05521       master ? master->channel : 0, slave ? slave->channel : 0, nothingok);
05522    if (master && slave) {
05523       /* Stop any tones, or play ringtone as appropriate.  If they're bridged
05524          in an active threeway call with a channel that is ringing, we should
05525          indicate ringing. */
05526       if ((oi1 == SUB_THREEWAY) &&
05527          p1->subs[SUB_THREEWAY].inthreeway &&
05528          p1->subs[SUB_REAL].owner &&
05529          p1->subs[SUB_REAL].inthreeway &&
05530          (p1->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
05531          ast_debug(1,
05532             "Playing ringback on %d/%d(%s) since %d/%d(%s) is in a ringing three-way\n",
05533             p0->channel, oi0, c0->name, p1->channel, oi1, c1->name);
05534          tone_zone_play_tone(p0->subs[oi0].dfd, DAHDI_TONE_RINGTONE);
05535          os1 = p1->subs[SUB_REAL].owner->_state;
05536       } else {
05537          ast_debug(1, "Stopping tones on %d/%d(%s) talking to %d/%d(%s)\n",
05538             p0->channel, oi0, c0->name, p1->channel, oi1, c1->name);
05539          tone_zone_play_tone(p0->subs[oi0].dfd, -1);
05540       }
05541       if ((oi0 == SUB_THREEWAY) &&
05542          p0->subs[SUB_THREEWAY].inthreeway &&
05543          p0->subs[SUB_REAL].owner &&
05544          p0->subs[SUB_REAL].inthreeway &&
05545          (p0->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
05546          ast_debug(1,
05547             "Playing ringback on %d/%d(%s) since %d/%d(%s) is in a ringing three-way\n",
05548             p1->channel, oi1, c1->name, p0->channel, oi0, c0->name);
05549          tone_zone_play_tone(p1->subs[oi1].dfd, DAHDI_TONE_RINGTONE);
05550          os0 = p0->subs[SUB_REAL].owner->_state;
05551       } else {
05552          ast_debug(1, "Stopping tones on %d/%d(%s) talking to %d/%d(%s)\n",
05553             p1->channel, oi1, c1->name, p0->channel, oi0, c0->name);
05554          tone_zone_play_tone(p1->subs[oi1].dfd, -1);
05555       }
05556       if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
05557          if (!p0->echocanbridged || !p1->echocanbridged) {
05558             /* Disable echo cancellation if appropriate */
05559             dahdi_disable_ec(p0);
05560             dahdi_disable_ec(p1);
05561          }
05562       }
05563       dahdi_link(slave, master);
05564       master->inconference = inconf;
05565    } else if (!nothingok)
05566       ast_log(LOG_WARNING, "Can't link %d/%s with %d/%s\n", p0->channel, subnames[oi0], p1->channel, subnames[oi1]);
05567 
05568    update_conf(p0);
05569    update_conf(p1);
05570    t0 = p0->subs[SUB_REAL].inthreeway;
05571    t1 = p1->subs[SUB_REAL].inthreeway;
05572 
05573    ast_mutex_unlock(&p0->lock);
05574    ast_mutex_unlock(&p1->lock);
05575 
05576    ast_channel_unlock(c0);
05577    ast_channel_unlock(c1);
05578 
05579    /* Native bridge failed */
05580    if ((!master || !slave) && !nothingok) {
05581       dahdi_enable_ec(p0);
05582       dahdi_enable_ec(p1);
05583       return AST_BRIDGE_FAILED;
05584    }
05585 
05586    ast_verb(3, "Native bridging %s and %s\n", c0->name, c1->name);
05587 
05588    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
05589       disable_dtmf_detect(op0);
05590 
05591    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
05592       disable_dtmf_detect(op1);
05593 
05594    for (;;) {
05595       struct ast_channel *c0_priority[2] = {c0, c1};
05596       struct ast_channel *c1_priority[2] = {c1, c0};
05597 
05598       /* Here's our main loop...  Start by locking things, looking for private parts,
05599          and then balking if anything is wrong */
05600 
05601       ast_channel_lock(c0);
05602       while (ast_channel_trylock(c1)) {
05603          CHANNEL_DEADLOCK_AVOIDANCE(c0);
05604       }
05605 
05606       p0 = c0->tech_pvt;
05607       p1 = c1->tech_pvt;
05608 
05609       if (op0 == p0)
05610          i0 = dahdi_get_index(c0, p0, 1);
05611       if (op1 == p1)
05612          i1 = dahdi_get_index(c1, p1, 1);
05613 
05614       ast_channel_unlock(c0);
05615       ast_channel_unlock(c1);
05616 
05617       if (!timeoutms ||
05618          (op0 != p0) ||
05619          (op1 != p1) ||
05620          (ofd0 != c0->fds[0]) ||
05621          (ofd1 != c1->fds[0]) ||
05622          (p0->subs[SUB_REAL].owner && (os0 > -1) && (os0 != p0->subs[SUB_REAL].owner->_state)) ||
05623          (p1->subs[SUB_REAL].owner && (os1 > -1) && (os1 != p1->subs[SUB_REAL].owner->_state)) ||
05624          (oc0 != p0->owner) ||
05625          (oc1 != p1->owner) ||
05626          (t0 != p0->subs[SUB_REAL].inthreeway) ||
05627          (t1 != p1->subs[SUB_REAL].inthreeway) ||
05628          (oi0 != i0) ||
05629          (oi1 != i1)) {
05630          ast_debug(1, "Something changed out on %d/%d to %d/%d, returning -3 to restart\n",
05631             op0->channel, oi0, op1->channel, oi1);
05632          res = AST_BRIDGE_RETRY;
05633          goto return_from_bridge;
05634       }
05635 
05636 #ifdef PRI_2BCT
05637       if (!triedtopribridge) {
05638          triedtopribridge = 1;
05639          if (p0->pri && p0->pri == p1->pri && p0->transfer && p1->transfer) {
05640             ast_mutex_lock(&p0->pri->lock);
05641             if (p0->call && p1->call) {
05642                pri_channel_bridge(p0->call, p1->call);
05643             }
05644             ast_mutex_unlock(&p0->pri->lock);
05645          }
05646       }
05647 #endif
05648 
05649       who = ast_waitfor_n(priority ? c0_priority : c1_priority, 2, &timeoutms);
05650       if (!who) {
05651          ast_debug(1, "Ooh, empty read...\n");
05652          continue;
05653       }
05654       f = ast_read(who);
05655       if (!f || (f->frametype == AST_FRAME_CONTROL)) {
05656          *fo = f;
05657          *rc = who;
05658          res = AST_BRIDGE_COMPLETE;
05659          goto return_from_bridge;
05660       }
05661       if (f->frametype == AST_FRAME_DTMF) {
05662          if ((who == c0) && p0->pulsedial) {
05663             ast_write(c1, f);
05664          } else if ((who == c1) && p1->pulsedial) {
05665             ast_write(c0, f);
05666          } else {
05667             *fo = f;
05668             *rc = who;
05669             res = AST_BRIDGE_COMPLETE;
05670             goto return_from_bridge;
05671          }
05672       }
05673       ast_frfree(f);
05674 
05675       /* Swap who gets priority */
05676       priority = !priority;
05677    }
05678 
05679 return_from_bridge:
05680    if (op0 == p0)
05681       dahdi_enable_ec(p0);
05682 
05683    if (op1 == p1)
05684       dahdi_enable_ec(p1);
05685 
05686    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
05687       enable_dtmf_detect(op0);
05688 
05689    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
05690       enable_dtmf_detect(op1);
05691 
05692    dahdi_unlink(slave, master, 1);
05693 
05694    return res;
05695 }
05696 
05697 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
05698 {
05699    struct dahdi_pvt *p = newchan->tech_pvt;
05700    int x;
05701    ast_mutex_lock(&p->lock);
05702    ast_debug(1, "New owner for channel %d is %s\n", p->channel, newchan->name);
05703    if (p->owner == oldchan) {
05704       p->owner = newchan;
05705    }
05706    for (x = 0; x < 3; x++)
05707       if (p->subs[x].owner == oldchan) {
05708          if (!x)
05709             dahdi_unlink(NULL, p, 0);
05710          p->subs[x].owner = newchan;
05711       }
05712    update_conf(p);
05713    ast_mutex_unlock(&p->lock);
05714    if (newchan->_state == AST_STATE_RINGING) {
05715       dahdi_indicate(newchan, AST_CONTROL_RINGING, NULL, 0);
05716    }
05717    return 0;
05718 }
05719 
05720 static int dahdi_ring_phone(struct dahdi_pvt *p)
05721 {
05722    int x;
05723    int res;
05724    /* Make sure our transmit state is on hook */
05725    x = 0;
05726    x = DAHDI_ONHOOK;
05727    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
05728    do {
05729       x = DAHDI_RING;
05730       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
05731       if (res) {
05732          switch (errno) {
05733          case EBUSY:
05734          case EINTR:
05735             /* Wait just in case */
05736             usleep(10000);
05737             continue;
05738          case EINPROGRESS:
05739             res = 0;
05740             break;
05741          default:
05742             ast_log(LOG_WARNING, "Couldn't ring the phone: %s\n", strerror(errno));
05743             res = 0;
05744          }
05745       }
05746    } while (res);
05747    return res;
05748 }
05749 
05750 static void *ss_thread(void *data);
05751 
05752 /*!
05753  * \internal
05754  * \brief Attempt to transfer 3-way call.
05755  *
05756  * \param p private structure.
05757  *
05758  * \note
05759  * On entry these locks are held: real-call, private, 3-way call.
05760  *
05761  * \retval 1 Transfer successful.  3-way call is unlocked and subchannel is unalloced.
05762  *         Swapped real and 3-way subchannel.
05763  * \retval 0 Transfer successful.  3-way call is unlocked and subchannel is unalloced.
05764  * \retval -1 on error.  Caller must unlock 3-way call.
05765  */
05766 static int attempt_transfer(struct dahdi_pvt *p)
05767 {
05768    /* In order to transfer, we need at least one of the channels to
05769       actually be in a call bridge.  We can't conference two applications
05770       together (but then, why would we want to?) */
05771    if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
05772       /* The three-way person we're about to transfer to could still be in MOH, so
05773          stop it now if appropriate */
05774       if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner))
05775          ast_queue_control(p->subs[SUB_THREEWAY].owner, AST_CONTROL_UNHOLD);
05776       if (p->subs[SUB_REAL].owner->_state == AST_STATE_RINGING) {
05777          /*
05778           * This may not be safe.
05779           * We currently hold the locks on the real-call, private, and 3-way call.
05780           * We could possibly avoid this here by using an ast_queue_control() instead.
05781           * However, the following ast_channel_masquerade() is going to be locking
05782           * the bridged channel again anyway.
05783           */
05784          ast_indicate(ast_bridged_channel(p->subs[SUB_REAL].owner), AST_CONTROL_RINGING);
05785       }
05786       if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RING) {
05787          tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE);
05788       }
05789        if (ast_channel_masquerade(p->subs[SUB_THREEWAY].owner, ast_bridged_channel(p->subs[SUB_REAL].owner))) {
05790          ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
05791                ast_bridged_channel(p->subs[SUB_REAL].owner)->name, p->subs[SUB_THREEWAY].owner->name);
05792          return -1;
05793       }
05794       /* Orphan the channel after releasing the lock */
05795       ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
05796       unalloc_sub(p, SUB_THREEWAY);
05797    } else if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
05798       ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
05799       if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RINGING) {
05800          /*
05801           * This may not be safe.
05802           * We currently hold the locks on the real-call, private, and 3-way call.
05803           * We could possibly avoid this here by using an ast_queue_control() instead.
05804           * However, the following ast_channel_masquerade() is going to be locking
05805           * the bridged channel again anyway.
05806           */
05807          ast_indicate(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), AST_CONTROL_RINGING);
05808       }
05809       if (p->subs[SUB_REAL].owner->_state == AST_STATE_RING) {
05810          tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
05811       }
05812       if (ast_channel_masquerade(p->subs[SUB_REAL].owner, ast_bridged_channel(p->subs[SUB_THREEWAY].owner))) {
05813          ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
05814                ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->name, p->subs[SUB_REAL].owner->name);
05815          return -1;
05816       }
05817       /* Three-way is now the REAL */
05818       swap_subs(p, SUB_THREEWAY, SUB_REAL);
05819       ast_channel_unlock(p->subs[SUB_REAL].owner);
05820       unalloc_sub(p, SUB_THREEWAY);
05821       /* Tell the caller not to hangup */
05822       return 1;
05823    } else {
05824       ast_debug(1, "Neither %s nor %s are in a bridge, nothing to transfer\n",
05825          p->subs[SUB_REAL].owner->name, p->subs[SUB_THREEWAY].owner->name);
05826       return -1;
05827    }
05828    return 0;
05829 }
05830 
05831 static int check_for_conference(struct dahdi_pvt *p)
05832 {
05833    struct dahdi_confinfo ci;
05834    /* Fine if we already have a master, etc */
05835    if (p->master || (p->confno > -1))
05836       return 0;
05837    memset(&ci, 0, sizeof(ci));
05838    if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
05839       ast_log(LOG_WARNING, "Failed to get conference info on channel %d: %s\n", p->channel, strerror(errno));
05840       return 0;
05841    }
05842    /* If we have no master and don't have a confno, then
05843       if we're in a conference, it's probably a MeetMe room or
05844       some such, so don't let us 3-way out! */
05845    if ((p->subs[SUB_REAL].curconf.confno != ci.confno) || (p->subs[SUB_REAL].curconf.confmode != ci.confmode)) {
05846       ast_verb(3, "Avoiding 3-way call when in an external conference\n");
05847       return 1;
05848    }
05849    return 0;
05850 }
05851 
05852 /*! Checks channel for alarms
05853  * \param p a channel to check for alarms.
05854  * \returns the alarms on the span to which the channel belongs, or alarms on
05855  *          the channel if no span alarms.
05856  */
05857 static int get_alarms(struct dahdi_pvt *p)
05858 {
05859    int res;
05860    struct dahdi_spaninfo zi;
05861    struct dahdi_params params;
05862 
05863    memset(&zi, 0, sizeof(zi));
05864    zi.spanno = p->span;
05865 
05866    if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SPANSTAT, &zi)) >= 0) {
05867       if (zi.alarms != DAHDI_ALARM_NONE)
05868          return zi.alarms;
05869    } else {
05870       ast_log(LOG_WARNING, "Unable to determine alarm on channel %d: %s\n", p->channel, strerror(errno));
05871       return 0;
05872    }
05873 
05874    /* No alarms on the span. Check for channel alarms. */
05875    memset(&params, 0, sizeof(params));
05876    if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &params)) >= 0)
05877       return params.chan_alarms;
05878 
05879    ast_log(LOG_WARNING, "Unable to determine alarm on channel %d\n", p->channel);
05880 
05881    return DAHDI_ALARM_NONE;
05882 }
05883 
05884 static void dahdi_handle_dtmf(struct ast_channel *ast, int idx, struct ast_frame **dest)
05885 {
05886    struct dahdi_pvt *p = ast->tech_pvt;
05887    struct ast_frame *f = *dest;
05888 
05889    ast_debug(1, "%s DTMF digit: 0x%02X '%c' on %s\n",
05890       f->frametype == AST_FRAME_DTMF_BEGIN ? "Begin" : "End",
05891       f->subclass, f->subclass, ast->name);
05892 
05893    if (p->confirmanswer) {
05894       if (f->frametype == AST_FRAME_DTMF_END) {
05895          ast_debug(1, "Confirm answer on %s!\n", ast->name);
05896          /* Upon receiving a DTMF digit, consider this an answer confirmation instead
05897             of a DTMF digit */
05898          p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05899          p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
05900          /* Reset confirmanswer so DTMF's will behave properly for the duration of the call */
05901          p->confirmanswer = 0;
05902       } else {
05903          p->subs[idx].f.frametype = AST_FRAME_NULL;
05904          p->subs[idx].f.subclass = 0;
05905       }
05906       *dest = &p->subs[idx].f;
05907    } else if (p->callwaitcas) {
05908       if (f->frametype == AST_FRAME_DTMF_END) {
05909          if ((f->subclass == 'A') || (f->subclass == 'D')) {
05910             ast_debug(1, "Got some DTMF, but it's for the CAS\n");
05911             ast_free(p->cidspill);
05912             p->cidspill = NULL;
05913             send_cwcidspill(p);
05914          }
05915          p->callwaitcas = 0;
05916       }
05917       p->subs[idx].f.frametype = AST_FRAME_NULL;
05918       p->subs[idx].f.subclass = 0;
05919       *dest = &p->subs[idx].f;
05920    } else if (f->subclass == 'f') {
05921       if (f->frametype == AST_FRAME_DTMF_END) {
05922          /* Fax tone -- Handle and return NULL */
05923          if ((p->callprogress & CALLPROGRESS_FAX) && !p->faxhandled) {
05924             /* If faxbuffers are configured, use them for the fax transmission */
05925             if (p->usefaxbuffers && !p->bufferoverrideinuse) {
05926                struct dahdi_bufferinfo bi = {
05927                   .txbufpolicy = p->faxbuf_policy,
05928                   .bufsize = p->bufsize,
05929                   .numbufs = p->faxbuf_no
05930                };
05931                int res;
05932 
05933                if ((res = ioctl(p->subs[idx].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
05934                   ast_log(LOG_WARNING, "Channel '%s' unable to set faxbuffer policy, reason: %s\n", ast->name, strerror(errno));
05935                } else {
05936                   p->bufferoverrideinuse = 1;
05937                }
05938             }
05939             p->faxhandled = 1;
05940             if (strcmp(ast->exten, "fax")) {
05941                const char *target_context = S_OR(ast->macrocontext, ast->context);
05942 
05943                /* We need to unlock 'ast' here because ast_exists_extension has the
05944                 * potential to start autoservice on the channel. Such action is prone
05945                 * to deadlock.
05946                 */
05947                ast_mutex_unlock(&p->lock);
05948                ast_channel_unlock(ast);
05949                if (ast_exists_extension(ast, target_context, "fax", 1, ast->cid.cid_num)) {
05950                   ast_channel_lock(ast);
05951                   ast_mutex_lock(&p->lock);
05952                   ast_verb(3, "Redirecting %s to fax extension\n", ast->name);
05953                   /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
05954                   pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten);
05955                   if (ast_async_goto(ast, target_context, "fax", 1))
05956                      ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context);
05957                } else {
05958                   ast_channel_lock(ast);
05959                   ast_mutex_lock(&p->lock);
05960                   ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
05961                }
05962             } else {
05963                ast_debug(1, "Already in a fax extension, not redirecting\n");
05964             }
05965          } else {
05966             ast_debug(1, "Fax already handled\n");
05967          }
05968          dahdi_confmute(p, 0);
05969       }
05970       p->subs[idx].f.frametype = AST_FRAME_NULL;
05971       p->subs[idx].f.subclass = 0;
05972       *dest = &p->subs[idx].f;
05973    }
05974 }
05975 
05976 static void handle_alarms(struct dahdi_pvt *p, int alms)
05977 {
05978    const char *alarm_str = alarm2str(alms);
05979 
05980    ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", p->channel, alarm_str);
05981    manager_event(EVENT_FLAG_SYSTEM, "Alarm",
05982       "Alarm: %s\r\n"
05983       "Channel: %d\r\n",
05984       alarm_str, p->channel);
05985 }
05986 
05987 static struct ast_frame *dahdi_handle_event(struct ast_channel *ast)
05988 {
05989    int res, x;
05990    int idx, mysig;
05991    char *c;
05992    struct dahdi_pvt *p = ast->tech_pvt;
05993    pthread_t threadid;
05994    struct ast_channel *chan;
05995    struct ast_frame *f;
05996 
05997    idx = dahdi_get_index(ast, p, 0);
05998    if (idx < 0) {
05999       return &ast_null_frame;
06000    }
06001    if (idx != SUB_REAL) {
06002       ast_log(LOG_ERROR, "We got an event on a non real sub.  Fix it!\n");
06003    }
06004 
06005    mysig = p->sig;
06006    if (p->outsigmod > -1)
06007       mysig = p->outsigmod;
06008 
06009    p->subs[idx].f.frametype = AST_FRAME_NULL;
06010    p->subs[idx].f.subclass = 0;
06011    p->subs[idx].f.datalen = 0;
06012    p->subs[idx].f.samples = 0;
06013    p->subs[idx].f.mallocd = 0;
06014    p->subs[idx].f.offset = 0;
06015    p->subs[idx].f.src = "dahdi_handle_event";
06016    p->subs[idx].f.data.ptr = NULL;
06017    f = &p->subs[idx].f;
06018 
06019    if (p->fake_event) {
06020       res = p->fake_event;
06021       p->fake_event = 0;
06022    } else
06023       res = dahdi_get_event(p->subs[idx].dfd);
06024 
06025    ast_debug(1, "Got event %s(%d) on channel %d (index %d)\n", event2str(res), res, p->channel, idx);
06026 
06027    if (res & (DAHDI_EVENT_PULSEDIGIT | DAHDI_EVENT_DTMFUP)) {
06028       p->pulsedial = (res & DAHDI_EVENT_PULSEDIGIT) ? 1 : 0;
06029       ast_debug(1, "Detected %sdigit '%c'\n", p->pulsedial ? "pulse ": "", res & 0xff);
06030 #if defined(HAVE_PRI)
06031       if (((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))
06032          && p->call_level < DAHDI_CALL_LEVEL_PROCEEDING
06033          && p->pri
06034          && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
06035          /* absorb event */
06036       } else
06037 #endif   /* defined(HAVE_PRI) */
06038       {
06039          /* Unmute conference */
06040          dahdi_confmute(p, 0);
06041          p->subs[idx].f.frametype = AST_FRAME_DTMF_END;
06042          p->subs[idx].f.subclass = res & 0xff;
06043          dahdi_handle_dtmf(ast, idx, &f);
06044       }
06045       return f;
06046    }
06047 
06048    if (res & DAHDI_EVENT_DTMFDOWN) {
06049       ast_debug(1, "DTMF Down '%c'\n", res & 0xff);
06050 #if defined(HAVE_PRI)
06051       if (((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))
06052          && p->call_level < DAHDI_CALL_LEVEL_PROCEEDING
06053          && p->pri
06054          && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
06055          /* absorb event */
06056       } else
06057 #endif   /* defined(HAVE_PRI) */
06058       {
06059          /* Mute conference */
06060          dahdi_confmute(p, 1);
06061          p->subs[idx].f.frametype = AST_FRAME_DTMF_BEGIN;
06062          p->subs[idx].f.subclass = res & 0xff;
06063          dahdi_handle_dtmf(ast, idx, &f);
06064       }
06065       return &p->subs[idx].f;
06066    }
06067 
06068    switch (res) {
06069       case DAHDI_EVENT_EC_DISABLED:
06070          ast_verb(3, "Channel %d echo canceler disabled due to CED detection\n", p->channel);
06071          p->echocanon = 0;
06072          break;
06073       case DAHDI_EVENT_BITSCHANGED:
06074 #ifdef HAVE_OPENR2
06075          if (p->sig != SIG_MFCR2) {
06076             ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig));
06077          } else {
06078             ast_log(LOG_DEBUG, "bits changed in chan %d\n", p->channel);
06079             openr2_chan_handle_cas(p->r2chan);
06080          }
06081 #else
06082          ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig));
06083 #endif
06084       case DAHDI_EVENT_PULSE_START:
06085          /* Stop tone if there's a pulse start and the PBX isn't started */
06086          if (!ast->pbx)
06087             tone_zone_play_tone(p->subs[idx].dfd, -1);
06088          break;
06089       case DAHDI_EVENT_DIALCOMPLETE:
06090 #ifdef HAVE_OPENR2
06091          if ((p->sig & SIG_MFCR2) && p->r2chan && ast->_state != AST_STATE_UP) {
06092             /* we don't need to do anything for this event for R2 signaling
06093                if the call is being setup */
06094             break;
06095          }
06096 #endif
06097          if (p->inalarm) break;
06098          if ((p->radio || (p->oprmode < 0))) break;
06099          if (ioctl(p->subs[idx].dfd,DAHDI_DIALING,&x) == -1) {
06100             ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed on %s: %s\n",ast->name, strerror(errno));
06101             return NULL;
06102          }
06103          if (!x) { /* if not still dialing in driver */
06104             dahdi_enable_ec(p);
06105             if (p->echobreak) {
06106                dahdi_train_ec(p);
06107                ast_copy_string(p->dop.dialstr, p->echorest, sizeof(p->dop.dialstr));
06108                p->dop.op = DAHDI_DIAL_OP_REPLACE;
06109                res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
06110                p->echobreak = 0;
06111             } else {
06112                p->dialing = 0;
06113                if ((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) {
06114                   /* if thru with dialing after offhook */
06115                   if (ast->_state == AST_STATE_DIALING_OFFHOOK) {
06116                      ast_setstate(ast, AST_STATE_UP);
06117                      p->subs[idx].f.frametype = AST_FRAME_CONTROL;
06118                      p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
06119                      break;
06120                   } else { /* if to state wait for offhook to dial rest */
06121                      /* we now wait for off hook */
06122                      ast_setstate(ast,AST_STATE_DIALING_OFFHOOK);
06123                   }
06124                }
06125                if (ast->_state == AST_STATE_DIALING) {
06126                   if ((p->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
06127                      ast_debug(1, "Done dialing, but waiting for progress detection before doing more...\n");
06128                   } else if (p->confirmanswer || (!p->dialednone
06129                      && ((mysig == SIG_EM) || (mysig == SIG_EM_E1)
06130                         || (mysig == SIG_EMWINK) || (mysig == SIG_FEATD)
06131                         || (mysig == SIG_FEATDMF_TA) || (mysig == SIG_FEATDMF)
06132                         || (mysig == SIG_E911) || (mysig == SIG_FGC_CAMA)
06133                         || (mysig == SIG_FGC_CAMAMF) || (mysig == SIG_FEATB)
06134                         || (mysig == SIG_SF) || (mysig == SIG_SFWINK)
06135                         || (mysig == SIG_SF_FEATD) || (mysig == SIG_SF_FEATDMF)
06136                         || (mysig == SIG_SF_FEATB)))) {
06137                      ast_setstate(ast, AST_STATE_RINGING);
06138                   } else if (!p->answeronpolarityswitch) {
06139                      ast_setstate(ast, AST_STATE_UP);
06140                      p->subs[idx].f.frametype = AST_FRAME_CONTROL;
06141                      p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
06142                      /* If aops=0 and hops=1, this is necessary */
06143                      p->polarity = POLARITY_REV;
06144                   } else {
06145                      /* Start clean, so we can catch the change to REV polarity when party answers */
06146                      p->polarity = POLARITY_IDLE;
06147                   }
06148                }
06149             }
06150          }
06151          break;
06152       case DAHDI_EVENT_ALARM:
06153 #ifdef HAVE_PRI
06154          if ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) {
06155             if (!p->pri || !p->pri->pri || (pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0)) {
06156                /* T309 is not enabled : destroy calls when alarm occurs */
06157                if (p->call) {
06158                   if (p->pri && p->pri->pri) {
06159                      pri_grab(p, p->pri);
06160                      pri_destroycall(p->pri->pri, p->call);
06161                      p->call = NULL;
06162                      pri_rel(p->pri);
06163                   } else
06164                      ast_log(LOG_WARNING, "The PRI Call has not been destroyed\n");
06165                }
06166                if (p->owner)
06167                   p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
06168             }
06169          }
06170          if (p->bearer) {
06171             p->bearer->inalarm = 1;
06172             p->bearer->resetting = 0;
06173          } else
06174 #endif
06175          {
06176             p->inalarm = 1;
06177 #if defined(HAVE_PRI)
06178             p->resetting = 0;
06179 #endif   /* defined(HAVE_PRI) */
06180          }
06181          res = get_alarms(p);
06182          handle_alarms(p, res);
06183 #ifdef HAVE_PRI
06184          if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
06185             /* fall through intentionally */
06186          } else {
06187             break;
06188          }
06189 #endif
06190 #ifdef HAVE_SS7
06191          if (p->sig == SIG_SS7)
06192             break;
06193 #endif
06194 #ifdef HAVE_OPENR2
06195          if (p->sig == SIG_MFCR2)
06196             break;
06197 #endif
06198       case DAHDI_EVENT_ONHOOK:
06199          if (p->radio) {
06200             p->subs[idx].f.frametype = AST_FRAME_CONTROL;
06201             p->subs[idx].f.subclass = AST_CONTROL_RADIO_UNKEY;
06202             break;
06203          }
06204          if (p->oprmode < 0)
06205          {
06206             if (p->oprmode != -1) break;
06207             if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
06208             {
06209                /* Make sure it starts ringing */
06210                dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
06211                dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RING);
06212                save_conference(p->oprpeer);
06213                tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
06214             }
06215             break;
06216          }
06217          switch (p->sig) {
06218          case SIG_FXOLS:
06219          case SIG_FXOGS:
06220          case SIG_FXOKS:
06221             p->onhooktime = time(NULL);
06222             p->fxsoffhookstate = 0;
06223             p->msgstate = -1;
06224             /* Check for some special conditions regarding call waiting */
06225             if (idx == SUB_REAL) {
06226                /* The normal line was hung up */
06227                if (p->subs[SUB_CALLWAIT].owner) {
06228                   /* Need to hold the lock for real-call, private, and call-waiting call */
06229                   dahdi_lock_sub_owner(p, SUB_CALLWAIT);
06230                   if (!p->subs[SUB_CALLWAIT].owner) {
06231                      /*
06232                       * The call waiting call dissappeared.
06233                       * This is now a normal hangup.
06234                       */
06235                      dahdi_disable_ec(p);
06236                      return NULL;
06237                   }
06238 
06239                   /* There's a call waiting call, so ring the phone, but make it unowned in the mean time */
06240                   swap_subs(p, SUB_CALLWAIT, SUB_REAL);
06241                   ast_verb(3, "Channel %d still has (callwait) call, ringing phone\n", p->channel);
06242                   unalloc_sub(p, SUB_CALLWAIT);
06243 #if 0
06244                   p->subs[idx].needanswer = 0;
06245                   p->subs[idx].needringing = 0;
06246 #endif
06247                   p->callwaitingrepeat = 0;
06248                   p->cidcwexpire = 0;
06249                   p->cid_suppress_expire = 0;
06250                   p->owner = NULL;
06251                   /* Don't start streaming audio yet if the incoming call isn't up yet */
06252                   if (p->subs[SUB_REAL].owner->_state != AST_STATE_UP)
06253                      p->dialing = 1;
06254                   /* Unlock the call-waiting call that we swapped to real-call. */
06255                   ast_channel_unlock(p->subs[SUB_REAL].owner);
06256                   dahdi_ring_phone(p);
06257                } else if (p->subs[SUB_THREEWAY].owner) {
06258                   unsigned int mssinceflash;
06259 
06260                   /* Need to hold the lock for real-call, private, and 3-way call */
06261                   dahdi_lock_sub_owner(p, SUB_THREEWAY);
06262                   if (!p->subs[SUB_THREEWAY].owner) {
06263                      ast_log(LOG_NOTICE, "Whoa, threeway disappeared kinda randomly.\n");
06264                      /* Just hangup */
06265                      return NULL;
06266                   }
06267                   if (p->owner != ast) {
06268                      ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
06269                      ast_log(LOG_WARNING, "This isn't good...\n");
06270                      /* Just hangup */
06271                      return NULL;
06272                   }
06273 
06274                   mssinceflash = ast_tvdiff_ms(ast_tvnow(), p->flashtime);
06275                   ast_debug(1, "Last flash was %d ms ago\n", mssinceflash);
06276                   if (mssinceflash < MIN_MS_SINCE_FLASH) {
06277                      /* It hasn't been long enough since the last flashook.  This is probably a bounce on
06278                         hanging up.  Hangup both channels now */
06279                      ast_debug(1, "Looks like a bounced flash, hanging up both calls on %d\n", p->channel);
06280                      ast_queue_hangup_with_cause(p->subs[SUB_THREEWAY].owner, AST_CAUSE_NO_ANSWER);
06281                      p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
06282                      ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
06283                   } else if ((ast->pbx) || (ast->_state == AST_STATE_UP)) {
06284                      if (p->transfer) {
06285                         /* In any case this isn't a threeway call anymore */
06286                         p->subs[SUB_REAL].inthreeway = 0;
06287                         p->subs[SUB_THREEWAY].inthreeway = 0;
06288                         /* Only attempt transfer if the phone is ringing; why transfer to busy tone eh? */
06289                         if (!p->transfertobusy && ast->_state == AST_STATE_BUSY) {
06290                            /* Swap subs and dis-own channel */
06291                            swap_subs(p, SUB_THREEWAY, SUB_REAL);
06292                            /* Unlock the 3-way call that we swapped to real-call. */
06293                            ast_channel_unlock(p->subs[SUB_REAL].owner);
06294                            p->owner = NULL;
06295                            /* Ring the phone */
06296                            dahdi_ring_phone(p);
06297                         } else {
06298                            res = attempt_transfer(p);
06299                            if (res < 0) {
06300                               /* Transfer attempt failed. */
06301                               p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
06302                               ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
06303                            } else if (res) {
06304                               /* Don't actually hang up at this point */
06305                               break;
06306                            }
06307                         }
06308                      } else {
06309                         p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
06310                         ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
06311                      }
06312                   } else {
06313                      /* Swap subs and dis-own channel */
06314                      swap_subs(p, SUB_THREEWAY, SUB_REAL);
06315                      /* Unlock the 3-way call that we swapped to real-call. */
06316                      ast_channel_unlock(p->subs[SUB_REAL].owner);
06317                      p->owner = NULL;
06318                      /* Ring the phone */
06319                      dahdi_ring_phone(p);
06320                   }
06321                }
06322             } else {
06323                ast_log(LOG_WARNING, "Got a hangup and my index is %d?\n", idx);
06324             }
06325             /* Fall through */
06326          default:
06327             dahdi_disable_ec(p);
06328             return NULL;
06329          }
06330          break;
06331       case DAHDI_EVENT_RINGOFFHOOK:
06332          if (p->inalarm) break;
06333          if (p->oprmode < 0)
06334          {
06335             if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
06336             {
06337                /* Make sure it stops ringing */
06338                dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
06339                tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, -1);
06340                restore_conference(p->oprpeer);
06341             }
06342             break;
06343          }
06344          if (p->radio)
06345          {
06346             p->subs[idx].f.frametype = AST_FRAME_CONTROL;
06347             p->subs[idx].f.subclass = AST_CONTROL_RADIO_KEY;
06348             break;
06349          }
06350          /* for E911, its supposed to wait for offhook then dial
06351             the second half of the dial string */
06352          if (((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) && (ast->_state == AST_STATE_DIALING_OFFHOOK)) {
06353             c = strchr(p->dialdest, '/');
06354             if (c)
06355                c++;
06356             else
06357                c = p->dialdest;
06358             if (*c) snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*0%s#", c);
06359             else ast_copy_string(p->dop.dialstr,"M*2#", sizeof(p->dop.dialstr));
06360             if (strlen(p->dop.dialstr) > 4) {
06361                memset(p->echorest, 'w', sizeof(p->echorest) - 1);
06362                strcpy(p->echorest + (p->echotraining / 401) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
06363                p->echorest[sizeof(p->echorest) - 1] = '\0';
06364                p->echobreak = 1;
06365                p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
06366             } else
06367                p->echobreak = 0;
06368             if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
06369                int saveerr = errno;
06370 
06371                x = DAHDI_ONHOOK;
06372                ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
06373                ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
06374                return NULL;
06375                }
06376             p->dialing = 1;
06377             return &p->subs[idx].f;
06378          }
06379          switch (p->sig) {
06380          case SIG_FXOLS:
06381          case SIG_FXOGS:
06382          case SIG_FXOKS:
06383             p->fxsoffhookstate = 1;
06384             switch (ast->_state) {
06385             case AST_STATE_RINGING:
06386                dahdi_enable_ec(p);
06387                dahdi_train_ec(p);
06388                p->subs[idx].f.frametype = AST_FRAME_CONTROL;
06389                p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
06390                /* Make sure it stops ringing */
06391                p->subs[SUB_REAL].needringing = 0;
06392                dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
06393                ast_debug(1, "channel %d answered\n", p->channel);
06394 
06395                /* Cancel any running CallerID spill */
06396                ast_free(p->cidspill);
06397                p->cidspill = NULL;
06398                restore_conference(p);
06399 
06400                p->dialing = 0;
06401                p->callwaitcas = 0;
06402                if (p->confirmanswer) {
06403                   /* Ignore answer if "confirm answer" is enabled */
06404                   p->subs[idx].f.frametype = AST_FRAME_NULL;
06405                   p->subs[idx].f.subclass = 0;
06406                } else if (!ast_strlen_zero(p->dop.dialstr)) {
06407                   /* nick@dccinc.com 4/3/03 - fxo should be able to do deferred dialing */
06408                   res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
06409                   if (res < 0) {
06410                      ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
06411                      p->dop.dialstr[0] = '\0';
06412                      return NULL;
06413                   } else {
06414                      ast_debug(1, "Sent FXO deferred digit string: %s\n", p->dop.dialstr);
06415                      p->subs[idx].f.frametype = AST_FRAME_NULL;
06416                      p->subs[idx].f.subclass = 0;
06417                      p->dialing = 1;
06418                   }
06419                   p->dop.dialstr[0] = '\0';
06420                   ast_setstate(ast, AST_STATE_DIALING);
06421                } else
06422                   ast_setstate(ast, AST_STATE_UP);
06423                return &p->subs[idx].f;
06424             case AST_STATE_DOWN:
06425                ast_setstate(ast, AST_STATE_RING);
06426                ast->rings = 1;
06427                p->subs[idx].f.frametype = AST_FRAME_CONTROL;
06428                p->subs[idx].f.subclass = AST_CONTROL_OFFHOOK;
06429                ast_debug(1, "channel %d picked up\n", p->channel);
06430                return &p->subs[idx].f;
06431             case AST_STATE_UP:
06432                /* Make sure it stops ringing */
06433                dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
06434                /* Okay -- probably call waiting*/
06435                if (ast_bridged_channel(p->owner))
06436                   ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
06437                p->subs[idx].needunhold = 1;
06438                break;
06439             case AST_STATE_RESERVED:
06440                /* Start up dialtone */
06441                if (has_voicemail(p))
06442                   res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
06443                else
06444                   res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
06445                break;
06446             default:
06447                ast_log(LOG_WARNING, "FXO phone off hook in weird state %d??\n", ast->_state);
06448             }
06449             break;
06450          case SIG_FXSLS:
06451          case SIG_FXSGS:
06452          case SIG_FXSKS:
06453             if (ast->_state == AST_STATE_RING) {
06454                p->ringt = p->ringt_base;
06455             }
06456 
06457             /* If we get a ring then we cannot be in
06458              * reversed polarity. So we reset to idle */
06459             ast_debug(1, "Setting IDLE polarity due "
06460                "to ring. Old polarity was %d\n",
06461                p->polarity);
06462             p->polarity = POLARITY_IDLE;
06463 
06464             /* Fall through */
06465          case SIG_EM:
06466          case SIG_EM_E1:
06467          case SIG_EMWINK:
06468          case SIG_FEATD:
06469          case SIG_FEATDMF:
06470          case SIG_FEATDMF_TA:
06471          case SIG_E911:
06472          case SIG_FGC_CAMA:
06473          case SIG_FGC_CAMAMF:
06474          case SIG_FEATB:
06475          case SIG_SF:
06476          case SIG_SFWINK:
06477          case SIG_SF_FEATD:
06478          case SIG_SF_FEATDMF:
06479          case SIG_SF_FEATB:
06480             if (ast->_state == AST_STATE_PRERING)
06481                ast_setstate(ast, AST_STATE_RING);
06482             if ((ast->_state == AST_STATE_DOWN) || (ast->_state == AST_STATE_RING)) {
06483                ast_debug(1, "Ring detected\n");
06484                p->subs[idx].f.frametype = AST_FRAME_CONTROL;
06485                p->subs[idx].f.subclass = AST_CONTROL_RING;
06486             } else if (p->outgoing && ((ast->_state == AST_STATE_RINGING) || (ast->_state == AST_STATE_DIALING))) {
06487                ast_debug(1, "Line answered\n");
06488                if (p->confirmanswer) {
06489                   p->subs[idx].f.frametype = AST_FRAME_NULL;
06490                   p->subs[idx].f.subclass = 0;
06491                } else {
06492                   p->subs[idx].f.frametype = AST_FRAME_CONTROL;
06493                   p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
06494                   ast_setstate(ast, AST_STATE_UP);
06495                }
06496             } else if (ast->_state != AST_STATE_RING)
06497                ast_log(LOG_WARNING, "Ring/Off-hook in strange state %d on channel %d\n", ast->_state, p->channel);
06498             break;
06499          default:
06500             ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
06501          }
06502          break;
06503       case DAHDI_EVENT_RINGBEGIN:
06504          switch (p->sig) {
06505          case SIG_FXSLS:
06506          case SIG_FXSGS:
06507          case SIG_FXSKS:
06508             if (ast->_state == AST_STATE_RING) {
06509                p->ringt = p->ringt_base;
06510             }
06511             break;
06512          }
06513          break;
06514       case DAHDI_EVENT_RINGEROFF:
06515          if (p->inalarm) break;
06516          if ((p->radio || (p->oprmode < 0))) break;
06517          ast->rings++;
06518          if ((ast->rings > p->cidrings) && (p->cidspill)) {
06519             ast_log(LOG_WARNING, "Didn't finish Caller-ID spill.  Cancelling.\n");
06520             ast_free(p->cidspill);
06521             p->cidspill = NULL;
06522             p->callwaitcas = 0;
06523          }
06524          p->subs[idx].f.frametype = AST_FRAME_CONTROL;
06525          p->subs[idx].f.subclass = AST_CONTROL_RINGING;
06526          break;
06527       case DAHDI_EVENT_RINGERON:
06528          break;
06529       case DAHDI_EVENT_NOALARM:
06530          p->inalarm = 0;
06531 #ifdef HAVE_PRI
06532          p->resetting = 0;
06533          /* Extremely unlikely but just in case */
06534          if (p->bearer) {
06535             p->bearer->inalarm = 0;
06536             p->bearer->resetting = 0;
06537          }
06538 #endif
06539          ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel);
06540          manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
06541                         "Channel: %d\r\n", p->channel);
06542          break;
06543       case DAHDI_EVENT_WINKFLASH:
06544          if (p->inalarm) break;
06545          if (p->radio) break;
06546          if (p->oprmode < 0) break;
06547          if (p->oprmode > 1)
06548          {
06549             struct dahdi_params par;
06550 
06551             memset(&par, 0, sizeof(par));
06552             if (ioctl(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par) != -1)
06553             {
06554                if (!par.rxisoffhook)
06555                {
06556                   /* Make sure it stops ringing */
06557                   dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
06558                   dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RING);
06559                   save_conference(p);
06560                   tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
06561                }
06562             }
06563             break;
06564          }
06565          /* Remember last time we got a flash-hook */
06566          p->flashtime = ast_tvnow();
06567          switch (mysig) {
06568          case SIG_FXOLS:
06569          case SIG_FXOGS:
06570          case SIG_FXOKS:
06571             ast_debug(1, "Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n",
06572                idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
06573 
06574             /* Cancel any running CallerID spill */
06575             ast_free(p->cidspill);
06576             p->cidspill = NULL;
06577             restore_conference(p);
06578             p->callwaitcas = 0;
06579 
06580             if (idx != SUB_REAL) {
06581                ast_log(LOG_WARNING, "Got flash hook with index %d on channel %d?!?\n", idx, p->channel);
06582                goto winkflashdone;
06583             }
06584 
06585             if (p->subs[SUB_CALLWAIT].owner) {
06586                /* Need to hold the lock for real-call, private, and call-waiting call */
06587                dahdi_lock_sub_owner(p, SUB_CALLWAIT);
06588                if (!p->subs[SUB_CALLWAIT].owner) {
06589                   /*
06590                    * The call waiting call dissappeared.
06591                    * Let's just ignore this flash-hook.
06592                    */
06593                   ast_log(LOG_NOTICE, "Whoa, the call-waiting call disappeared.\n");
06594                   goto winkflashdone;
06595                }
06596 
06597                /* Swap to call-wait */
06598                swap_subs(p, SUB_REAL, SUB_CALLWAIT);
06599                tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06600                p->owner = p->subs[SUB_REAL].owner;
06601                ast_debug(1, "Making %s the new owner\n", p->owner->name);
06602                if (p->owner->_state == AST_STATE_RINGING) {
06603                   ast_setstate(p->owner, AST_STATE_UP);
06604                   p->subs[SUB_REAL].needanswer = 1;
06605                }
06606                p->callwaitingrepeat = 0;
06607                p->cidcwexpire = 0;
06608                p->cid_suppress_expire = 0;
06609 
06610                /* Start music on hold if appropriate */
06611                if (!p->subs[SUB_CALLWAIT].inthreeway && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
06612                   ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
06613                      S_OR(p->mohsuggest, NULL),
06614                      !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
06615                }
06616                p->subs[SUB_CALLWAIT].needhold = 1;
06617                if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
06618                   ast_queue_control_data(p->subs[SUB_REAL].owner, AST_CONTROL_HOLD,
06619                      S_OR(p->mohsuggest, NULL),
06620                      !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
06621                }
06622                p->subs[SUB_REAL].needunhold = 1;
06623 
06624                /* Unlock the call-waiting call that we swapped to real-call. */
06625                ast_channel_unlock(p->subs[SUB_REAL].owner);
06626             } else if (!p->subs[SUB_THREEWAY].owner) {
06627                if (!p->threewaycalling) {
06628                   /* Just send a flash if no 3-way calling */
06629                   p->subs[SUB_REAL].needflash = 1;
06630                   goto winkflashdone;
06631                } else if (!check_for_conference(p)) {
06632                   char cid_num[256];
06633                   char cid_name[256];
06634 
06635                   cid_num[0] = 0;
06636                   cid_name[0] = 0;
06637                   if (p->dahditrcallerid && p->owner) {
06638                      if (p->owner->cid.cid_num)
06639                         ast_copy_string(cid_num, p->owner->cid.cid_num, sizeof(cid_num));
06640                      if (p->owner->cid.cid_name)
06641                         ast_copy_string(cid_name, p->owner->cid.cid_name, sizeof(cid_name));
06642                   }
06643                   /* XXX This section needs much more error checking!!! XXX */
06644                   /* Start a 3-way call if feasible */
06645                   if (!((ast->pbx) ||
06646                      (ast->_state == AST_STATE_UP) ||
06647                      (ast->_state == AST_STATE_RING))) {
06648                      ast_debug(1, "Flash when call not up or ringing\n");
06649                      goto winkflashdone;
06650                   }
06651                   if (alloc_sub(p, SUB_THREEWAY)) {
06652                      ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n");
06653                      goto winkflashdone;
06654                   }
06655                   /* Make new channel */
06656                   chan = dahdi_new(p, AST_STATE_RESERVED, 0, SUB_THREEWAY, 0, 0);
06657                   if (!chan) {
06658                      ast_log(LOG_WARNING,
06659                         "Cannot allocate new call structure on channel %d\n",
06660                         p->channel);
06661                      unalloc_sub(p, SUB_THREEWAY);
06662                      goto winkflashdone;
06663                   }
06664                   if (p->dahditrcallerid) {
06665                      if (!p->origcid_num)
06666                         p->origcid_num = ast_strdup(p->cid_num);
06667                      if (!p->origcid_name)
06668                         p->origcid_name = ast_strdup(p->cid_name);
06669                      ast_copy_string(p->cid_num, cid_num, sizeof(p->cid_num));
06670                      ast_copy_string(p->cid_name, cid_name, sizeof(p->cid_name));
06671                   }
06672                   /* Swap things around between the three-way and real call */
06673                   swap_subs(p, SUB_THREEWAY, SUB_REAL);
06674                   /* Disable echo canceller for better dialing */
06675                   dahdi_disable_ec(p);
06676                   res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALRECALL);
06677                   if (res)
06678                      ast_log(LOG_WARNING, "Unable to start dial recall tone on channel %d\n", p->channel);
06679                   p->owner = chan;
06680                   if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
06681                      ast_log(LOG_WARNING, "Unable to start simple switch on channel %d\n", p->channel);
06682                      res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
06683                      dahdi_enable_ec(p);
06684                      ast_hangup(chan);
06685                   } else {
06686                      ast_verb(3, "Started three way call on channel %d\n", p->channel);
06687 
06688                      /* Start music on hold if appropriate */
06689                      if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
06690                         ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
06691                            S_OR(p->mohsuggest, NULL),
06692                            !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
06693                      }
06694                      p->subs[SUB_THREEWAY].needhold = 1;
06695                   }
06696                }
06697             } else {
06698                /* Already have a 3 way call */
06699                int orig_3way_sub;
06700 
06701                /* Need to hold the lock for real-call, private, and 3-way call */
06702                dahdi_lock_sub_owner(p, SUB_THREEWAY);
06703                if (!p->subs[SUB_THREEWAY].owner) {
06704                   /*
06705                    * The 3-way call dissappeared.
06706                    * Let's just ignore this flash-hook.
06707                    */
06708                   ast_log(LOG_NOTICE, "Whoa, the 3-way call disappeared.\n");
06709                   goto winkflashdone;
06710                }
06711                orig_3way_sub = SUB_THREEWAY;
06712 
06713                if (p->subs[SUB_THREEWAY].inthreeway) {
06714                   /* Call is already up, drop the last person */
06715                   ast_debug(1, "Got flash with three way call up, dropping last call on %d\n", p->channel);
06716                   /* If the primary call isn't answered yet, use it */
06717                   if ((p->subs[SUB_REAL].owner->_state != AST_STATE_UP) && (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_UP)) {
06718                      /* Swap back -- we're dropping the real 3-way that isn't finished yet*/
06719                      swap_subs(p, SUB_THREEWAY, SUB_REAL);
06720                      orig_3way_sub = SUB_REAL;
06721                      p->owner = p->subs[SUB_REAL].owner;
06722                   }
06723                   /* Drop the last call and stop the conference */
06724                   ast_verb(3, "Dropping three-way call on %s\n", p->subs[SUB_THREEWAY].owner->name);
06725                   p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
06726                   p->subs[SUB_REAL].inthreeway = 0;
06727                   p->subs[SUB_THREEWAY].inthreeway = 0;
06728                } else {
06729                   /* Lets see what we're up to */
06730                   if (((ast->pbx) || (ast->_state == AST_STATE_UP)) &&
06731                      (p->transfertobusy || (ast->_state != AST_STATE_BUSY))) {
06732                      ast_verb(3, "Building conference call with %s and %s\n",
06733                         p->subs[SUB_THREEWAY].owner->name,
06734                         p->subs[SUB_REAL].owner->name);
06735                      /* Put them in the threeway, and flip */
06736                      p->subs[SUB_THREEWAY].inthreeway = 1;
06737                      p->subs[SUB_REAL].inthreeway = 1;
06738                      if (ast->_state == AST_STATE_UP) {
06739                         swap_subs(p, SUB_THREEWAY, SUB_REAL);
06740                         orig_3way_sub = SUB_REAL;
06741                      }
06742                      if (ast_bridged_channel(p->subs[orig_3way_sub].owner)) {
06743                         ast_queue_control(p->subs[orig_3way_sub].owner, AST_CONTROL_UNHOLD);
06744                      }
06745                      p->subs[orig_3way_sub].needunhold = 1;
06746                      p->owner = p->subs[SUB_REAL].owner;
06747                   } else {
06748                      ast_verb(3, "Dumping incomplete call on %s\n", p->subs[SUB_THREEWAY].owner->name);
06749                      swap_subs(p, SUB_THREEWAY, SUB_REAL);
06750                      orig_3way_sub = SUB_REAL;
06751                      p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
06752                      p->owner = p->subs[SUB_REAL].owner;
06753                      if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
06754                         ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
06755                      }
06756                      p->subs[SUB_REAL].needunhold = 1;
06757                      dahdi_enable_ec(p);
06758                   }
06759                }
06760                ast_channel_unlock(p->subs[orig_3way_sub].owner);
06761             }
06762 winkflashdone:
06763             update_conf(p);
06764             break;
06765          case SIG_EM:
06766          case SIG_EM_E1:
06767          case SIG_FEATD:
06768          case SIG_SF:
06769          case SIG_SFWINK:
06770          case SIG_SF_FEATD:
06771          case SIG_FXSLS:
06772          case SIG_FXSGS:
06773             if (option_debug) {
06774                if (p->dialing)
06775                   ast_debug(1, "Ignoring wink on channel %d\n", p->channel);
06776                else
06777                   ast_debug(1, "Got wink in weird state %d on channel %d\n", ast->_state, p->channel);
06778             }
06779             break;
06780          case SIG_FEATDMF_TA:
06781             switch (p->whichwink) {
06782             case 0:
06783                ast_debug(1, "ANI2 set to '%d' and ANI is '%s'\n", p->owner->cid.cid_ani2, p->owner->cid.cid_ani);
06784                snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%d%s#", p->owner->cid.cid_ani2, p->owner->cid.cid_ani);
06785                break;
06786             case 1:
06787                ast_copy_string(p->dop.dialstr, p->finaldial, sizeof(p->dop.dialstr));
06788                break;
06789             case 2:
06790                ast_log(LOG_WARNING, "Received unexpected wink on channel of type SIG_FEATDMF_TA\n");
06791                return NULL;
06792             }
06793             p->whichwink++;
06794             /* Fall through */
06795          case SIG_FEATDMF:
06796          case SIG_E911:
06797          case SIG_FGC_CAMAMF:
06798          case SIG_FGC_CAMA:
06799          case SIG_FEATB:
06800          case SIG_SF_FEATDMF:
06801          case SIG_SF_FEATB:
06802          case SIG_EMWINK:
06803             /* FGD MF and EMWINK *Must* wait for wink */
06804             if (!ast_strlen_zero(p->dop.dialstr)) {
06805                res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
06806                if (res < 0) {
06807                   ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
06808                   p->dop.dialstr[0] = '\0';
06809                   return NULL;
06810                } else
06811                   ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
06812             }
06813             p->dop.dialstr[0] = '\0';
06814             break;
06815          default:
06816             ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
06817          }
06818          break;
06819       case DAHDI_EVENT_HOOKCOMPLETE:
06820          if (p->inalarm) break;
06821          if ((p->radio || (p->oprmode < 0))) break;
06822          if (p->waitingfordt.tv_sec) break;
06823          switch (mysig) {
06824          case SIG_FXSLS:  /* only interesting for FXS */
06825          case SIG_FXSGS:
06826          case SIG_FXSKS:
06827          case SIG_EM:
06828          case SIG_EM_E1:
06829          case SIG_EMWINK:
06830          case SIG_FEATD:
06831          case SIG_SF:
06832          case SIG_SFWINK:
06833          case SIG_SF_FEATD:
06834             if (!ast_strlen_zero(p->dop.dialstr)) {
06835                res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
06836                if (res < 0) {
06837                   ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
06838                   p->dop.dialstr[0] = '\0';
06839                   return NULL;
06840                } else
06841                   ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
06842             }
06843             p->dop.dialstr[0] = '\0';
06844             p->dop.op = DAHDI_DIAL_OP_REPLACE;
06845             break;
06846          case SIG_FEATDMF:
06847          case SIG_FEATDMF_TA:
06848          case SIG_E911:
06849          case SIG_FGC_CAMA:
06850          case SIG_FGC_CAMAMF:
06851          case SIG_FEATB:
06852          case SIG_SF_FEATDMF:
06853          case SIG_SF_FEATB:
06854             ast_debug(1, "Got hook complete in MF FGD, waiting for wink now on channel %d\n",p->channel);
06855             break;
06856          default:
06857             break;
06858          }
06859          break;
06860       case DAHDI_EVENT_POLARITY:
06861          /*
06862           * If we get a Polarity Switch event, this could be
06863           * due to line seizure, remote end connect or remote end disconnect.
06864           *
06865           * Check to see if we should change the polarity state and
06866           * mark the channel as UP or if this is an indication
06867           * of remote end disconnect.
06868           */
06869 
06870          if (p->polarityonanswerdelay > 0) {
06871             /* check if event is not too soon after OffHook or Answer */
06872             if (ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) > p->polarityonanswerdelay) {
06873                switch (ast->_state) {
06874                case AST_STATE_DIALING:       /*!< Digits (or equivalent) have been dialed */
06875                case AST_STATE_RINGING:       /*!< Remote end is ringing */
06876                   if (p->answeronpolarityswitch) {
06877                      ast_debug(1, "Answering on polarity switch! channel %d\n", p->channel);
06878                      ast_setstate(p->owner, AST_STATE_UP);
06879                      p->polarity = POLARITY_REV;
06880                      if (p->hanguponpolarityswitch) {
06881                         p->polaritydelaytv = ast_tvnow();
06882                      }
06883                   } else {
06884                      ast_debug(1, "Ignore Answer on polarity switch, channel %d\n", p->channel);
06885                   }
06886                   break;
06887 
06888                case AST_STATE_UP:         /*!< Line is up */
06889                case AST_STATE_RING:       /*!< Line is ringing */
06890                   if (p->hanguponpolarityswitch) {
06891                      ast_debug(1, "HangingUp on polarity switch! channel %d\n", p->channel);
06892                      ast_softhangup(p->owner, AST_SOFTHANGUP_EXPLICIT);
06893                      p->polarity = POLARITY_IDLE;
06894                   } else {
06895                      ast_debug(1, "Ignore Hangup on polarity switch, channel %d\n", p->channel);
06896                   }
06897                   break;
06898 
06899                case AST_STATE_DOWN:       /*!< Channel is down and available */
06900                case AST_STATE_RESERVED:      /*!< Channel is down, but reserved */
06901                case AST_STATE_OFFHOOK:       /*!< Channel is off hook */
06902                case AST_STATE_BUSY:       /*!< Line is busy */
06903                case AST_STATE_DIALING_OFFHOOK:     /*!< Digits (or equivalent) have been dialed while offhook */
06904                case AST_STATE_PRERING:       /*!< Channel has detected an incoming call and is waiting for ring */
06905                default:
06906                   if (p->answeronpolarityswitch || p->hanguponpolarityswitch) {
06907                      ast_debug(1, "Ignoring Polarity switch on channel %d, state %d\n", p->channel, ast->_state);
06908                   }
06909                }
06910 
06911             } else {
06912                /* event is too soon after OffHook or Answer */
06913                switch (ast->_state) {
06914                case AST_STATE_DIALING:       /*!< Digits (or equivalent) have been dialed */
06915                case AST_STATE_RINGING:       /*!< Remote end is ringing */
06916                   if (p->answeronpolarityswitch) {
06917                      ast_debug(1, "Polarity switch detected but NOT answering (too close to OffHook event) on channel %d, state %d\n", p->channel, ast->_state);
06918                   }
06919                   break;
06920 
06921                case AST_STATE_UP:         /*!< Line is up */
06922                case AST_STATE_RING:       /*!< Line is ringing */
06923                   if (p->hanguponpolarityswitch) {
06924                      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);
06925                   }
06926                   break;
06927 
06928                default: 
06929                   if (p->answeronpolarityswitch || p->hanguponpolarityswitch) {
06930                      ast_debug(1, "Polarity switch detected (too close to previous event) on channel %d, state %d\n", p->channel, ast->_state);
06931                   }
06932                }
06933             }
06934          }
06935 
06936          /* Added more log_debug information below to provide a better indication of what is going on */
06937          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) );
06938          break;
06939       default:
06940          ast_debug(1, "Dunno what to do with event %d on channel %d\n", res, p->channel);
06941    }
06942    return &p->subs[idx].f;
06943 }
06944 
06945 static struct ast_frame *__dahdi_exception(struct ast_channel *ast)
06946 {
06947    struct dahdi_pvt *p = ast->tech_pvt;
06948    int res;
06949    int idx;
06950    struct ast_frame *f;
06951 
06952 
06953    idx = dahdi_get_index(ast, p, 1);
06954    if (idx < 0) {
06955       idx = SUB_REAL;
06956    }
06957 
06958    p->subs[idx].f.frametype = AST_FRAME_NULL;
06959    p->subs[idx].f.datalen = 0;
06960    p->subs[idx].f.samples = 0;
06961    p->subs[idx].f.mallocd = 0;
06962    p->subs[idx].f.offset = 0;
06963    p->subs[idx].f.subclass = 0;
06964    p->subs[idx].f.delivery = ast_tv(0,0);
06965    p->subs[idx].f.src = "dahdi_exception";
06966    p->subs[idx].f.data.ptr = NULL;
06967 
06968    if ((!p->owner) && (!(p->radio || (p->oprmode < 0)))) {
06969       /* If nobody owns us, absorb the event appropriately, otherwise
06970          we loop indefinitely.  This occurs when, during call waiting, the
06971          other end hangs up our channel so that it no longer exists, but we
06972          have neither FLASH'd nor ONHOOK'd to signify our desire to
06973          change to the other channel. */
06974       if (p->fake_event) {
06975          res = p->fake_event;
06976          p->fake_event = 0;
06977       } else
06978          res = dahdi_get_event(p->subs[SUB_REAL].dfd);
06979       /* Switch to real if there is one and this isn't something really silly... */
06980       if ((res != DAHDI_EVENT_RINGEROFF) && (res != DAHDI_EVENT_RINGERON) &&
06981          (res != DAHDI_EVENT_HOOKCOMPLETE)) {
06982          ast_debug(1, "Restoring owner of channel %d on event %d\n", p->channel, res);
06983          p->owner = p->subs[SUB_REAL].owner;
06984          if (p->owner && ast != p->owner) {
06985             /*
06986              * Could this even happen?
06987              * Possible deadlock because we do not have the real-call lock.
06988              */
06989             ast_log(LOG_WARNING, "Event %s on %s is not restored owner %s\n",
06990                event2str(res), ast->name, p->owner->name);
06991          }
06992          if (p->owner && ast_bridged_channel(p->owner))
06993             ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
06994          p->subs[SUB_REAL].needunhold = 1;
06995       }
06996       switch (res) {
06997       case DAHDI_EVENT_ONHOOK:
06998          dahdi_disable_ec(p);
06999          if (p->owner) {
07000             ast_verb(3, "Channel %s still has call, ringing phone\n", p->owner->name);
07001             dahdi_ring_phone(p);
07002             p->callwaitingrepeat = 0;
07003             p->cidcwexpire = 0;
07004             p->cid_suppress_expire = 0;
07005          } else {
07006             ast_log(LOG_WARNING, "Absorbed %s, but nobody is left!?!?\n",
07007                event2str(res));
07008          }
07009          update_conf(p);
07010          break;
07011       case DAHDI_EVENT_RINGOFFHOOK:
07012          dahdi_enable_ec(p);
07013          dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
07014          if (p->owner && (p->owner->_state == AST_STATE_RINGING)) {
07015             p->subs[SUB_REAL].needanswer = 1;
07016             p->dialing = 0;
07017          }
07018          break;
07019       case DAHDI_EVENT_HOOKCOMPLETE:
07020       case DAHDI_EVENT_RINGERON:
07021       case DAHDI_EVENT_RINGEROFF:
07022          /* Do nothing */
07023          break;
07024       case DAHDI_EVENT_WINKFLASH:
07025          p->flashtime = ast_tvnow();
07026          if (p->owner) {
07027             ast_verb(3, "Channel %d flashed to other channel %s\n", p->channel, p->owner->name);
07028             if (p->owner->_state != AST_STATE_UP) {
07029                /* Answer if necessary */
07030                p->subs[SUB_REAL].needanswer = 1;
07031                ast_setstate(p->owner, AST_STATE_UP);
07032             }
07033             p->callwaitingrepeat = 0;
07034             p->cidcwexpire = 0;
07035             p->cid_suppress_expire = 0;
07036             if (ast_bridged_channel(p->owner))
07037                ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
07038             p->subs[SUB_REAL].needunhold = 1;
07039          } else {
07040             ast_log(LOG_WARNING, "Absorbed %s, but nobody is left!?!?\n",
07041                event2str(res));
07042          }
07043          update_conf(p);
07044          break;
07045       default:
07046          ast_log(LOG_WARNING, "Don't know how to absorb event %s\n", event2str(res));
07047          break;
07048       }
07049       f = &p->subs[idx].f;
07050       return f;
07051    }
07052    if (!(p->radio || (p->oprmode < 0)))
07053       ast_debug(1, "Exception on %d, channel %d\n", ast->fds[0],p->channel);
07054    /* If it's not us, return NULL immediately */
07055    if (ast != p->owner) {
07056       ast_log(LOG_WARNING, "We're %s, not %s\n", ast->name, p->owner->name);
07057       f = &p->subs[idx].f;
07058       return f;
07059    }
07060    f = dahdi_handle_event(ast);
07061    return f;
07062 }
07063 
07064 static struct ast_frame *dahdi_exception(struct ast_channel *ast)
07065 {
07066    struct dahdi_pvt *p = ast->tech_pvt;
07067    struct ast_frame *f;
07068    ast_mutex_lock(&p->lock);
07069    f = __dahdi_exception(ast);
07070    ast_mutex_unlock(&p->lock);
07071    return f;
07072 }
07073 
07074 static struct ast_frame *dahdi_read(struct ast_channel *ast)
07075 {
07076    struct dahdi_pvt *p;
07077    int res;
07078    int idx;
07079    void *readbuf;
07080    struct ast_frame *f;
07081 
07082    /*
07083     * For analog channels, we must do deadlock avoidance because
07084     * analog ports can have more than one Asterisk channel using
07085     * the same private structure.
07086     */
07087    p = ast->tech_pvt;
07088    while (ast_mutex_trylock(&p->lock)) {
07089       CHANNEL_DEADLOCK_AVOIDANCE(ast);
07090 
07091       /*
07092        * For PRI channels, we must refresh the private pointer because
07093        * the call could move to another B channel while the Asterisk
07094        * channel is unlocked.
07095        */
07096       p = ast->tech_pvt;
07097    }
07098 
07099    idx = dahdi_get_index(ast, p, 0);
07100 
07101    /* Hang up if we don't really exist */
07102    if (idx < 0)   {
07103       ast_log(LOG_WARNING, "We don't exist?\n");
07104       ast_mutex_unlock(&p->lock);
07105       return NULL;
07106    }
07107 
07108    if ((p->radio || (p->oprmode < 0)) && p->inalarm) {
07109       ast_mutex_unlock(&p->lock);
07110       return NULL;
07111    }
07112 
07113    p->subs[idx].f.frametype = AST_FRAME_NULL;
07114    p->subs[idx].f.datalen = 0;
07115    p->subs[idx].f.samples = 0;
07116    p->subs[idx].f.mallocd = 0;
07117    p->subs[idx].f.offset = 0;
07118    p->subs[idx].f.subclass = 0;
07119    p->subs[idx].f.delivery = ast_tv(0,0);
07120    p->subs[idx].f.src = "dahdi_read";
07121    p->subs[idx].f.data.ptr = NULL;
07122 
07123    /* make sure it sends initial key state as first frame */
07124    if ((p->radio || (p->oprmode < 0)) && (!p->firstradio))
07125    {
07126       struct dahdi_params ps;
07127 
07128       memset(&ps, 0, sizeof(ps));
07129       ps.channo = p->channel;
07130       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
07131          ast_mutex_unlock(&p->lock);
07132          return NULL;
07133       }
07134       p->firstradio = 1;
07135       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
07136       if (ps.rxisoffhook)
07137       {
07138          p->subs[idx].f.subclass = AST_CONTROL_RADIO_KEY;
07139       }
07140       else
07141       {
07142          p->subs[idx].f.subclass = AST_CONTROL_RADIO_UNKEY;
07143       }
07144       ast_mutex_unlock(&p->lock);
07145       return &p->subs[idx].f;
07146    }
07147    if (p->ringt == 1) {
07148       ast_mutex_unlock(&p->lock);
07149       return NULL;
07150    }
07151    else if (p->ringt > 0)
07152       p->ringt--;
07153 
07154 #ifdef HAVE_OPENR2
07155    if (p->mfcr2) {
07156       openr2_chan_process_event(p->r2chan);
07157       if (OR2_DIR_FORWARD == openr2_chan_get_direction(p->r2chan)) {
07158          struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, };
07159          /* if the call is already accepted and we already delivered AST_CONTROL_RINGING
07160           * now enqueue a progress frame to bridge the media up */
07161          if (p->mfcr2_call_accepted &&
07162              !p->mfcr2_progress && 
07163              ast->_state == AST_STATE_RINGING) {
07164             ast_log(LOG_DEBUG, "Enqueuing progress frame after R2 accept in chan %d\n", p->channel);
07165             ast_queue_frame(p->owner, &f);
07166             p->mfcr2_progress = 1;
07167          }
07168       }
07169    }
07170 #endif
07171 
07172    if (p->subs[idx].needringing) {
07173       /* Send ringing frame if requested */
07174       p->subs[idx].needringing = 0;
07175       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
07176       p->subs[idx].f.subclass = AST_CONTROL_RINGING;
07177       ast_setstate(ast, AST_STATE_RINGING);
07178       ast_mutex_unlock(&p->lock);
07179       return &p->subs[idx].f;
07180    }
07181 
07182    if (p->subs[idx].needbusy) {
07183       /* Send busy frame if requested */
07184       p->subs[idx].needbusy = 0;
07185       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
07186       p->subs[idx].f.subclass = AST_CONTROL_BUSY;
07187       ast_mutex_unlock(&p->lock);
07188       return &p->subs[idx].f;
07189    }
07190 
07191    if (p->subs[idx].needcongestion) {
07192       /* Send congestion frame if requested */
07193       p->subs[idx].needcongestion = 0;
07194       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
07195       p->subs[idx].f.subclass = AST_CONTROL_CONGESTION;
07196       ast_mutex_unlock(&p->lock);
07197       return &p->subs[idx].f;
07198    }
07199 
07200    if (p->subs[idx].needcallerid && !ast->cid.cid_tns) {
07201       ast_set_callerid(ast, S_OR(p->lastcid_num, NULL),
07202                      S_OR(p->lastcid_name, NULL),
07203                      S_OR(p->lastcid_num, NULL)
07204                      );
07205       p->subs[idx].needcallerid = 0;
07206    }
07207 
07208    if (p->subs[idx].needanswer) {
07209       /* Send answer frame if requested */
07210       p->subs[idx].needanswer = 0;
07211       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
07212       p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
07213       ast_mutex_unlock(&p->lock);
07214       return &p->subs[idx].f;
07215    }
07216 #ifdef HAVE_OPENR2
07217    if (p->mfcr2 && openr2_chan_get_read_enabled(p->r2chan)) {
07218       /* openr2 took care of reading and handling any event
07219         (needanswer, needbusy etc), if we continue we will read()
07220         twice, lets just return a null frame. This should only
07221         happen when openr2 is dialing out */
07222       ast_mutex_unlock(&p->lock);
07223       return &ast_null_frame;
07224    }
07225 #endif
07226 
07227    if (p->subs[idx].needflash) {
07228       /* Send answer frame if requested */
07229       p->subs[idx].needflash = 0;
07230       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
07231       p->subs[idx].f.subclass = AST_CONTROL_FLASH;
07232       ast_mutex_unlock(&p->lock);
07233       return &p->subs[idx].f;
07234    }
07235 
07236    if (p->subs[idx].needhold) {
07237       /* Send answer frame if requested */
07238       p->subs[idx].needhold = 0;
07239       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
07240       p->subs[idx].f.subclass = AST_CONTROL_HOLD;
07241       ast_mutex_unlock(&p->lock);
07242       ast_debug(1, "Sending hold on '%s'\n", ast->name);
07243       return &p->subs[idx].f;
07244    }
07245 
07246    if (p->subs[idx].needunhold) {
07247       /* Send answer frame if requested */
07248       p->subs[idx].needunhold = 0;
07249       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
07250       p->subs[idx].f.subclass = AST_CONTROL_UNHOLD;
07251       ast_mutex_unlock(&p->lock);
07252       ast_debug(1, "Sending unhold on '%s'\n", ast->name);
07253       return &p->subs[idx].f;
07254    }
07255 
07256    if (ast->rawreadformat == AST_FORMAT_SLINEAR) {
07257       if (!p->subs[idx].linear) {
07258          p->subs[idx].linear = 1;
07259          res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
07260          if (res)
07261             ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to linear mode.\n", p->channel, idx);
07262       }
07263    } else if ((ast->rawreadformat == AST_FORMAT_ULAW) ||
07264       (ast->rawreadformat == AST_FORMAT_ALAW)) {
07265       if (p->subs[idx].linear) {
07266          p->subs[idx].linear = 0;
07267          res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
07268          if (res)
07269             ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to companded mode.\n", p->channel, idx);
07270       }
07271    } else {
07272       ast_log(LOG_WARNING, "Don't know how to read frames in format %s\n", ast_getformatname(ast->rawreadformat));
07273       ast_mutex_unlock(&p->lock);
07274       return NULL;
07275    }
07276    readbuf = ((unsigned char *)p->subs[idx].buffer) + AST_FRIENDLY_OFFSET;
07277    CHECK_BLOCKING(ast);
07278    res = read(p->subs[idx].dfd, readbuf, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
07279    ast_clear_flag(ast, AST_FLAG_BLOCKING);
07280    /* Check for hangup */
07281    if (res < 0) {
07282       f = NULL;
07283       if (res == -1) {
07284          if (errno == EAGAIN) {
07285             /* Return "NULL" frame if there is nobody there */
07286             ast_mutex_unlock(&p->lock);
07287             return &p->subs[idx].f;
07288          } else if (errno == ELAST) {
07289             f = __dahdi_exception(ast);
07290          } else
07291             ast_log(LOG_WARNING, "dahdi_rec: %s\n", strerror(errno));
07292       }
07293       ast_mutex_unlock(&p->lock);
07294       return f;
07295    }
07296    if (res != (p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE)) {
07297       ast_debug(1, "Short read (%d/%d), must be an event...\n", res, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
07298       f = __dahdi_exception(ast);
07299       ast_mutex_unlock(&p->lock);
07300       return f;
07301    }
07302    if (p->tdd) { /* if in TDD mode, see if we receive that */
07303       int c;
07304 
07305       c = tdd_feed(p->tdd,readbuf,READ_SIZE);
07306       if (c < 0) {
07307          ast_debug(1,"tdd_feed failed\n");
07308          ast_mutex_unlock(&p->lock);
07309          return NULL;
07310       }
07311       if (c) { /* if a char to return */
07312          p->subs[idx].f.subclass = 0;
07313          p->subs[idx].f.frametype = AST_FRAME_TEXT;
07314          p->subs[idx].f.mallocd = 0;
07315          p->subs[idx].f.offset = AST_FRIENDLY_OFFSET;
07316          p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET;
07317          p->subs[idx].f.datalen = 1;
07318          *((char *) p->subs[idx].f.data.ptr) = c;
07319          ast_mutex_unlock(&p->lock);
07320          return &p->subs[idx].f;
07321       }
07322    }
07323    if (idx == SUB_REAL) {
07324       /* Ensure the CW timers decrement only on a single subchannel */
07325       if (p->cidcwexpire) {
07326          if (!--p->cidcwexpire) {
07327             /* Expired CID/CW */
07328             ast_verb(3, "CPE does not support Call Waiting Caller*ID.\n");
07329             restore_conference(p);
07330          }
07331       }
07332       if (p->cid_suppress_expire) {
07333          --p->cid_suppress_expire;
07334       }
07335       if (p->callwaitingrepeat) {
07336          if (!--p->callwaitingrepeat) {
07337             /* Expired, Repeat callwaiting tone */
07338             ++p->callwaitrings;
07339             dahdi_callwait(ast);
07340          }
07341       }
07342    }
07343    if (p->subs[idx].linear) {
07344       p->subs[idx].f.datalen = READ_SIZE * 2;
07345    } else
07346       p->subs[idx].f.datalen = READ_SIZE;
07347 
07348    /* Handle CallerID Transmission */
07349    if ((p->owner == ast) && p->cidspill &&((ast->_state == AST_STATE_UP) || (ast->rings == p->cidrings))) {
07350       send_callerid(p);
07351    }
07352 
07353    p->subs[idx].f.frametype = AST_FRAME_VOICE;
07354    p->subs[idx].f.subclass = ast->rawreadformat;
07355    p->subs[idx].f.samples = READ_SIZE;
07356    p->subs[idx].f.mallocd = 0;
07357    p->subs[idx].f.offset = AST_FRIENDLY_OFFSET;
07358    p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET / sizeof(p->subs[idx].buffer[0]);
07359 #if 0
07360    ast_debug(1, "Read %d of voice on %s\n", p->subs[idx].f.datalen, ast->name);
07361 #endif
07362    if (p->dialing || /* Transmitting something */
07363       (idx && (ast->_state != AST_STATE_UP)) || /* Three-way or callwait that isn't up */
07364       ((idx == SUB_CALLWAIT) && !p->subs[SUB_CALLWAIT].inthreeway) /* Inactive and non-confed call-wait */
07365       ) {
07366       /* Whoops, we're still dialing, or in a state where we shouldn't transmit....
07367          don't send anything */
07368       p->subs[idx].f.frametype = AST_FRAME_NULL;
07369       p->subs[idx].f.subclass = 0;
07370       p->subs[idx].f.samples = 0;
07371       p->subs[idx].f.mallocd = 0;
07372       p->subs[idx].f.offset = 0;
07373       p->subs[idx].f.data.ptr = NULL;
07374       p->subs[idx].f.datalen= 0;
07375    }
07376    if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect || p->callprogress || p->waitingfordt.tv_sec) && !idx) {
07377       /* Perform busy detection etc on the dahdi line */
07378       int mute;
07379 
07380       f = ast_dsp_process(ast, p->dsp, &p->subs[idx].f);
07381 
07382       /* Check if DSP code thinks we should be muting this frame and mute the conference if so */
07383       mute = ast_dsp_was_muted(p->dsp);
07384       if (p->muting != mute) {
07385          p->muting = mute;
07386          dahdi_confmute(p, mute);
07387       }
07388 
07389       if (f) {
07390          if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_BUSY)) {
07391             if ((ast->_state == AST_STATE_UP) && !p->outgoing) {
07392                /* Treat this as a "hangup" instead of a "busy" on the assumption that
07393                   a busy */
07394                f = NULL;
07395             }
07396          } else if (f->frametype == AST_FRAME_DTMF_BEGIN
07397             || f->frametype == AST_FRAME_DTMF_END) {
07398 #ifdef HAVE_PRI
07399             if (((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))
07400                && p->call_level < DAHDI_CALL_LEVEL_PROCEEDING
07401                && p->pri
07402                && ((!p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING))
07403                   || (p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)))) {
07404                /* Don't accept in-band DTMF when in overlap dial mode */
07405                ast_debug(1, "Absorbing inband %s DTMF digit: 0x%02X '%c' on %s\n",
07406                   f->frametype == AST_FRAME_DTMF_BEGIN ? "begin" : "end",
07407                   f->subclass, f->subclass, ast->name);
07408 
07409                f->frametype = AST_FRAME_NULL;
07410                f->subclass = 0;
07411             }
07412 #endif
07413             /* DSP clears us of being pulse */
07414             p->pulsedial = 0;
07415          } else if (p->waitingfordt.tv_sec) {
07416             if (ast_tvdiff_ms(ast_tvnow(), p->waitingfordt) >= p->waitfordialtone ) {
07417                p->waitingfordt.tv_sec = 0;
07418                ast_log(LOG_WARNING, "Never saw dialtone on channel %d\n", p->channel);
07419                f=NULL;
07420             } else if (f->frametype == AST_FRAME_VOICE) {
07421                f->frametype = AST_FRAME_NULL;
07422                f->subclass = 0;
07423                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) {
07424                   p->waitingfordt.tv_sec = 0;
07425                   p->dsp_features &= ~DSP_FEATURE_WAITDIALTONE;
07426                   ast_dsp_set_features(p->dsp, p->dsp_features);
07427                   ast_log(LOG_DEBUG, "Got 10 samples of dialtone!\n");
07428                   if (!ast_strlen_zero(p->dop.dialstr)) { /* Dial deferred digits */
07429                      res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
07430                      if (res < 0) {
07431                         ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d\n", p->channel);
07432                         p->dop.dialstr[0] = '\0';
07433                         ast_mutex_unlock(&p->lock);
07434                         return NULL;
07435                      } else {
07436                         ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", p->dop.dialstr);
07437                         p->dialing = 1;
07438                         p->dop.dialstr[0] = '\0';
07439                         p->dop.op = DAHDI_DIAL_OP_REPLACE;
07440                         ast_setstate(ast, AST_STATE_DIALING);
07441                      }
07442                   }
07443                }
07444             }
07445          }
07446       }
07447    } else
07448       f = &p->subs[idx].f;
07449 
07450    if (f) {
07451       switch (f->frametype) {
07452       case AST_FRAME_DTMF_BEGIN:
07453       case AST_FRAME_DTMF_END:
07454          dahdi_handle_dtmf(ast, idx, &f);
07455          break;
07456       case AST_FRAME_VOICE:
07457          if (p->cidspill || p->cid_suppress_expire) {
07458             /* We are/were sending a caller id spill.  Suppress any echo. */
07459             p->subs[idx].f.frametype = AST_FRAME_NULL;
07460             p->subs[idx].f.subclass = 0;
07461             p->subs[idx].f.samples = 0;
07462             p->subs[idx].f.mallocd = 0;
07463             p->subs[idx].f.offset = 0;
07464             p->subs[idx].f.data.ptr = NULL;
07465             p->subs[idx].f.datalen= 0;
07466          }
07467          break;
07468       default:
07469          break;
07470       }
07471    }
07472 
07473    /* If we have a fake_event, trigger exception to handle it */
07474    if (p->fake_event)
07475       ast_set_flag(ast, AST_FLAG_EXCEPTION);
07476 
07477    ast_mutex_unlock(&p->lock);
07478    return f;
07479 }
07480 
07481 static int my_dahdi_write(struct dahdi_pvt *p, unsigned char *buf, int len, int idx, int linear)
07482 {
07483    int sent=0;
07484    int size;
07485    int res;
07486    int fd;
07487    fd = p->subs[idx].dfd;
07488    while (len) {
07489       size = len;
07490       if (size > (linear ? READ_SIZE * 2 : READ_SIZE))
07491          size = (linear ? READ_SIZE * 2 : READ_SIZE);
07492       res = write(fd, buf, size);
07493       if (res != size) {
07494          ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
07495          return sent;
07496       }
07497       len -= size;
07498       buf += size;
07499    }
07500    return sent;
07501 }
07502 
07503 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame)
07504 {
07505    struct dahdi_pvt *p = ast->tech_pvt;
07506    int res;
07507    int idx;
07508    idx = dahdi_get_index(ast, p, 0);
07509    if (idx < 0) {
07510       ast_log(LOG_WARNING, "%s doesn't really exist?\n", ast->name);
07511       return -1;
07512    }
07513 
07514    /* Write a frame of (presumably voice) data */
07515    if (frame->frametype != AST_FRAME_VOICE) {
07516       if (frame->frametype != AST_FRAME_IMAGE)
07517          ast_log(LOG_WARNING, "Don't know what to do with frame type '%d'\n", frame->frametype);
07518       return 0;
07519    }
07520    if ((frame->subclass != AST_FORMAT_SLINEAR) &&
07521       (frame->subclass != AST_FORMAT_ULAW) &&
07522       (frame->subclass != AST_FORMAT_ALAW)) {
07523       ast_log(LOG_WARNING, "Cannot handle frames in %d format\n", frame->subclass);
07524       return -1;
07525    }
07526    if (p->dialing) {
07527       ast_debug(1, "Dropping frame since I'm still dialing on %s...\n",ast->name);
07528       return 0;
07529    }
07530    if (!p->owner) {
07531       ast_debug(1, "Dropping frame since there is no active owner on %s...\n",ast->name);
07532       return 0;
07533    }
07534    if (p->cidspill) {
07535       ast_debug(1, "Dropping frame since I've still got a callerid spill on %s...\n",
07536          ast->name);
07537       return 0;
07538    }
07539    /* Return if it's not valid data */
07540    if (!frame->data.ptr || !frame->datalen)
07541       return 0;
07542 
07543    if (frame->subclass == AST_FORMAT_SLINEAR) {
07544       if (!p->subs[idx].linear) {
07545          p->subs[idx].linear = 1;
07546          res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
07547          if (res)
07548             ast_log(LOG_WARNING, "Unable to set linear mode on channel %d\n", p->channel);
07549       }
07550       res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 1);
07551    } else {
07552       /* x-law already */
07553       if (p->subs[idx].linear) {
07554          p->subs[idx].linear = 0;
07555          res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
07556          if (res)
07557             ast_log(LOG_WARNING, "Unable to set companded mode on channel %d\n", p->channel);
07558       }
07559       res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 0);
07560    }
07561    if (res < 0) {
07562       ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
07563       return -1;
07564    }
07565    return 0;
07566 }
07567 
07568 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen)
07569 {
07570    struct dahdi_pvt *p = chan->tech_pvt;
07571    int res=-1;
07572    int idx;
07573    int func = DAHDI_FLASH;
07574    ast_mutex_lock(&p->lock);
07575    idx = dahdi_get_index(chan, p, 0);
07576    ast_debug(1, "Requested indication %d on channel %s\n", condition, chan->name);
07577 #ifdef HAVE_OPENR2
07578    if (p->mfcr2 && !p->mfcr2_call_accepted) {
07579       ast_mutex_unlock(&p->lock);
07580       /* if this is an R2 call and the call is not yet accepted, we don't want the
07581          tone indications to mess up with the MF tones */
07582       return 0;
07583    }
07584 #endif
07585    if (idx == SUB_REAL) {
07586       switch (condition) {
07587       case AST_CONTROL_BUSY:
07588 #ifdef HAVE_PRI
07589          if ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) {
07590             if (p->priindication_oob) {
07591                chan->hangupcause = AST_CAUSE_USER_BUSY;
07592                chan->_softhangup |= AST_SOFTHANGUP_DEV;
07593                res = 0;
07594                break;
07595             }
07596             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_BUSY);
07597             if (p->call_level < DAHDI_CALL_LEVEL_ALERTING && !p->outgoing) {
07598                chan->hangupcause = AST_CAUSE_USER_BUSY;
07599                p->progress = 1;/* No need to send plain PROGRESS after this. */
07600                if (p->pri && p->pri->pri) {
07601                   if (!pri_grab(p, p->pri)) {
07602 #ifdef HAVE_PRI_PROG_W_CAUSE
07603                      pri_progress_with_cause(p->pri->pri, p->call, PVT_TO_CHANNEL(p), 1, chan->hangupcause);
07604 #else
07605                      pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
07606 #endif
07607                      pri_rel(p->pri);
07608                   } else {
07609                      ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
07610                   }
07611                }
07612             }
07613             break;
07614          }
07615 #endif
07616          res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_BUSY);
07617          break;
07618       case AST_CONTROL_RINGING:
07619 #ifdef HAVE_PRI
07620          if (((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))
07621             && p->call_level < DAHDI_CALL_LEVEL_ALERTING && !p->outgoing) {
07622             p->call_level = DAHDI_CALL_LEVEL_ALERTING;
07623             if (p->pri && p->pri->pri) {
07624                if (!pri_grab(p, p->pri)) {
07625                   pri_acknowledge(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
07626                   pri_rel(p->pri);
07627                } else {
07628                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
07629                }
07630             }
07631          }
07632 #endif
07633 #ifdef HAVE_SS7
07634          if (p->sig == SIG_SS7
07635             && p->call_level < DAHDI_CALL_LEVEL_ALERTING && !p->outgoing) {
07636             p->call_level = DAHDI_CALL_LEVEL_ALERTING;
07637             if (p->ss7 && p->ss7->ss7) {
07638                ss7_grab(p, p->ss7);
07639                if ((isup_far(p->ss7->ss7, p->ss7call)) != -1)
07640                   p->rlt = 1;
07641                if (p->rlt != 1) /* No need to send CPG if call will be RELEASE */
07642                   isup_cpg(p->ss7->ss7, p->ss7call, CPG_EVENT_ALERTING);
07643                ss7_rel(p->ss7);
07644             }
07645          }
07646 #endif
07647 
07648          res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_RINGTONE);
07649 
07650          if (chan->_state != AST_STATE_UP) {
07651             if ((chan->_state != AST_STATE_RING) ||
07652                ((p->sig != SIG_FXSKS) &&
07653              (p->sig != SIG_FXSLS) &&
07654              (p->sig != SIG_FXSGS)))
07655             ast_setstate(chan, AST_STATE_RINGING);
07656          }
07657          break;
07658       case AST_CONTROL_PROCEEDING:
07659          ast_debug(1,"Received AST_CONTROL_PROCEEDING on %s\n",chan->name);
07660 #ifdef HAVE_PRI
07661          if (((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))
07662             && p->call_level < DAHDI_CALL_LEVEL_PROCEEDING && !p->outgoing) {
07663             p->call_level = DAHDI_CALL_LEVEL_PROCEEDING;
07664             if (p->pri && p->pri->pri) {
07665                if (!pri_grab(p, p->pri)) {
07666                   pri_proceeding(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
07667                   pri_rel(p->pri);
07668                } else {
07669                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
07670                }
07671             }
07672             p->dialing = 0;
07673          }
07674 #endif
07675 #ifdef HAVE_SS7
07676          if (p->sig == SIG_SS7) {
07677             /* This IF sends the FAR for an answered ALEG call */
07678             if (chan->_state == AST_STATE_UP && (p->rlt != 1)){
07679                if ((isup_far(p->ss7->ss7, p->ss7call)) != -1)
07680                   p->rlt = 1;
07681             }
07682 
07683             if (p->call_level < DAHDI_CALL_LEVEL_PROCEEDING && !p->outgoing) {
07684                p->call_level = DAHDI_CALL_LEVEL_PROCEEDING;
07685                if (p->ss7 && p->ss7->ss7) {
07686                   ss7_grab(p, p->ss7);
07687                   isup_acm(p->ss7->ss7, p->ss7call);
07688                   ss7_rel(p->ss7);
07689                }
07690             }
07691          }
07692 #endif
07693          /* don't continue in ast_indicate */
07694          res = 0;
07695          break;
07696       case AST_CONTROL_PROGRESS:
07697          ast_debug(1,"Received AST_CONTROL_PROGRESS on %s\n",chan->name);
07698 #ifdef HAVE_PRI
07699          p->digital = 0;   /* Digital-only calls isn't allows any inband progress messages */
07700          if (((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))
07701             && !p->progress && p->call_level < DAHDI_CALL_LEVEL_ALERTING
07702             && !p->outgoing) {
07703             p->progress = 1;/* No need to send plain PROGRESS again. */
07704             if (p->pri && p->pri->pri) {
07705                if (!pri_grab(p, p->pri)) {
07706 #ifdef HAVE_PRI_PROG_W_CAUSE
07707                   pri_progress_with_cause(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1, -1);  /* no cause at all */
07708 #else
07709                   pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
07710 #endif
07711                   pri_rel(p->pri);
07712                } else {
07713                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
07714                }
07715             }
07716          }
07717 #endif
07718 #ifdef HAVE_SS7
07719          if (p->sig == SIG_SS7
07720             && !p->progress && p->call_level < DAHDI_CALL_LEVEL_ALERTING
07721             && !p->outgoing) {
07722             p->progress = 1;/* No need to send inband-information progress again. */
07723             if (p->ss7 && p->ss7->ss7) {
07724                ss7_grab(p, p->ss7);
07725                isup_cpg(p->ss7->ss7, p->ss7call, CPG_EVENT_INBANDINFO);
07726                ss7_rel(p->ss7);
07727                /* enable echo canceler here on SS7 calls */
07728                dahdi_enable_ec(p);
07729             }
07730          }
07731 #endif
07732          /* don't continue in ast_indicate */
07733          res = 0;
07734          break;
07735       case AST_CONTROL_CONGESTION:
07736 #ifdef HAVE_PRI
07737          if ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) {
07738             if (p->priindication_oob) {
07739                /* There are many cause codes that generate an AST_CONTROL_CONGESTION. */
07740                switch (chan->hangupcause) {
07741                case AST_CAUSE_USER_BUSY:
07742                case AST_CAUSE_NORMAL_CLEARING:
07743                case 0:/* Cause has not been set. */
07744                   /* Supply a more appropriate cause. */
07745                   chan->hangupcause = AST_CAUSE_SWITCH_CONGESTION;
07746                   break;
07747                default:
07748                   break;
07749                }
07750                chan->_softhangup |= AST_SOFTHANGUP_DEV;
07751                res = 0;
07752                break;
07753             }
07754             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
07755             if (p->call_level < DAHDI_CALL_LEVEL_ALERTING && !p->outgoing) {
07756                /* There are many cause codes that generate an AST_CONTROL_CONGESTION. */
07757                switch (chan->hangupcause) {
07758                case AST_CAUSE_USER_BUSY:
07759                case AST_CAUSE_NORMAL_CLEARING:
07760                case 0:/* Cause has not been set. */
07761                   /* Supply a more appropriate cause. */
07762                   chan->hangupcause = AST_CAUSE_SWITCH_CONGESTION;
07763                   break;
07764                default:
07765                   break;
07766                }
07767                p->progress = 1;/* No need to send plain PROGRESS after this. */
07768                if (p->pri && p->pri->pri) {
07769                   if (!pri_grab(p, p->pri)) {
07770 #ifdef HAVE_PRI_PROG_W_CAUSE
07771                      pri_progress_with_cause(p->pri->pri, p->call, PVT_TO_CHANNEL(p), 1, chan->hangupcause);
07772 #else
07773                      pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
07774 #endif
07775                      pri_rel(p->pri);
07776                   } else {
07777                      ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
07778                   }
07779                }
07780             }
07781             break;
07782          }
07783 #endif
07784          /* There are many cause codes that generate an AST_CONTROL_CONGESTION. */
07785          switch (chan->hangupcause) {
07786          case AST_CAUSE_USER_BUSY:
07787          case AST_CAUSE_NORMAL_CLEARING:
07788          case 0:/* Cause has not been set. */
07789             /* Supply a more appropriate cause. */
07790             chan->hangupcause = AST_CAUSE_CONGESTION;
07791             break;
07792          default:
07793             break;
07794          }
07795          res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
07796          break;
07797       case AST_CONTROL_HOLD:
07798 #ifdef HAVE_PRI
07799          if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) {
07800             if (!pri_grab(p, p->pri)) {
07801                res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_HOLD);
07802                pri_rel(p->pri);
07803             } else
07804                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
07805          } else
07806 #endif
07807             ast_moh_start(chan, data, p->mohinterpret);
07808          break;
07809       case AST_CONTROL_UNHOLD:
07810 #ifdef HAVE_PRI
07811          if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) {
07812             if (!pri_grab(p, p->pri)) {
07813                res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_RETRIEVAL);
07814                pri_rel(p->pri);
07815             } else
07816                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
07817          } else
07818 #endif
07819             ast_moh_stop(chan);
07820          break;
07821       case AST_CONTROL_RADIO_KEY:
07822          if (p->radio)
07823             res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
07824          res = 0;
07825          break;
07826       case AST_CONTROL_RADIO_UNKEY:
07827          if (p->radio)
07828             res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_RINGOFF);
07829          res = 0;
07830          break;
07831       case AST_CONTROL_FLASH:
07832          /* flash hookswitch */
07833          if (ISTRUNK(p) && (p->sig != SIG_PRI)) {
07834             /* Clear out the dial buffer */
07835             p->dop.dialstr[0] = '\0';
07836             if ((ioctl(p->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
07837                ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
07838                   chan->name, strerror(errno));
07839             } else
07840                res = 0;
07841          } else
07842             res = 0;
07843          break;
07844       case AST_CONTROL_SRCUPDATE:
07845          res = 0;
07846          break;
07847       case -1:
07848          res = tone_zone_play_tone(p->subs[idx].dfd, -1);
07849          break;
07850       }
07851    } else
07852       res = 0;
07853    ast_mutex_unlock(&p->lock);
07854    return res;
07855 }
07856 
07857 static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpbx, int idx, int law, int transfercapability)
07858 {
07859    struct ast_channel *tmp;
07860    int deflaw;
07861    int res;
07862    int x,y;
07863    int features;
07864    struct ast_str *chan_name;
07865    struct ast_variable *v;
07866    struct dahdi_params ps;
07867    if (i->subs[idx].owner) {
07868       ast_log(LOG_WARNING, "Channel %d already has a %s call\n", i->channel,subnames[idx]);
07869       return NULL;
07870    }
07871    y = 1;
07872    chan_name = ast_str_alloca(32);
07873    do {
07874 #ifdef HAVE_PRI
07875       if (i->bearer || (i->pri && (i->sig == SIG_FXSKS)))
07876          ast_str_set(&chan_name, 0, "%d:%d-%d", i->pri->trunkgroup, i->channel, y);
07877       else
07878 #endif
07879       if (i->channel == CHAN_PSEUDO)
07880          ast_str_set(&chan_name, 0, "pseudo-%ld", ast_random());
07881       else
07882          ast_str_set(&chan_name, 0, "%d-%d", i->channel, y);
07883       for (x = 0; x < 3; x++) {
07884          if ((idx != x) && i->subs[x].owner && !strcasecmp(ast_str_buffer(chan_name), i->subs[x].owner->name + 6))
07885             break;
07886       }
07887       y++;
07888    } while (x < 3);
07889    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));
07890    if (!tmp)
07891       return NULL;
07892    tmp->tech = &dahdi_tech;
07893    memset(&ps, 0, sizeof(ps));
07894    ps.channo = i->channel;
07895    res = ioctl(i->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps);
07896    if (res) {
07897       ast_log(LOG_WARNING, "Unable to get parameters, assuming MULAW: %s\n", strerror(errno));
07898       ps.curlaw = DAHDI_LAW_MULAW;
07899    }
07900    if (ps.curlaw == DAHDI_LAW_ALAW)
07901       deflaw = AST_FORMAT_ALAW;
07902    else
07903       deflaw = AST_FORMAT_ULAW;
07904    if (law) {
07905       if (law == DAHDI_LAW_ALAW)
07906          deflaw = AST_FORMAT_ALAW;
07907       else
07908          deflaw = AST_FORMAT_ULAW;
07909    }
07910    ast_channel_set_fd(tmp, 0, i->subs[idx].dfd);
07911    tmp->nativeformats = deflaw;
07912    /* Start out assuming ulaw since it's smaller :) */
07913    tmp->rawreadformat = deflaw;
07914    tmp->readformat = deflaw;
07915    tmp->rawwriteformat = deflaw;
07916    tmp->writeformat = deflaw;
07917    i->subs[idx].linear = 0;
07918    dahdi_setlinear(i->subs[idx].dfd, i->subs[idx].linear);
07919    features = 0;
07920    if (idx == SUB_REAL) {
07921       if (i->busydetect && CANBUSYDETECT(i))
07922          features |= DSP_FEATURE_BUSY_DETECT;
07923       if ((i->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(i))
07924          features |= DSP_FEATURE_CALL_PROGRESS;
07925       if ((i->waitfordialtone) && CANPROGRESSDETECT(i))
07926          features |= DSP_FEATURE_WAITDIALTONE;
07927       if ((!i->outgoing && (i->callprogress & CALLPROGRESS_FAX_INCOMING)) ||
07928          (i->outgoing && (i->callprogress & CALLPROGRESS_FAX_OUTGOING))) {
07929          features |= DSP_FEATURE_FAX_DETECT;
07930       }
07931       x = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
07932       if (ioctl(i->subs[idx].dfd, DAHDI_TONEDETECT, &x)) {
07933          i->hardwaredtmf = 0;
07934          features |= DSP_FEATURE_DIGIT_DETECT;
07935       } else if (NEED_MFDETECT(i)) {
07936          i->hardwaredtmf = 1;
07937          features |= DSP_FEATURE_DIGIT_DETECT;
07938       }
07939    }
07940    if (features) {
07941       if (i->dsp) {
07942          ast_debug(1, "Already have a dsp on %s?\n", tmp->name);
07943       } else {
07944          if (i->channel != CHAN_PSEUDO)
07945             i->dsp = ast_dsp_new();
07946          else
07947             i->dsp = NULL;
07948          if (i->dsp) {
07949             i->dsp_features = features;
07950 #if defined(HAVE_PRI) || defined(HAVE_SS7)
07951             /* We cannot do progress detection until receives PROGRESS message */
07952             if (i->outgoing && ((i->sig == SIG_PRI) || (i->sig == SIG_BRI) || (i->sig == SIG_BRI_PTMP) || (i->sig == SIG_SS7))) {
07953                /* Remember requested DSP features, don't treat
07954                   talking as ANSWER */
07955                i->dsp_features = features & ~DSP_PROGRESS_TALK;
07956                features = 0;
07957             }
07958 #endif
07959             ast_dsp_set_features(i->dsp, features);
07960             ast_dsp_set_digitmode(i->dsp, DSP_DIGITMODE_DTMF | i->dtmfrelax);
07961             if (!ast_strlen_zero(progzone))
07962                ast_dsp_set_call_progress_zone(i->dsp, progzone);
07963             if (i->busydetect && CANBUSYDETECT(i)) {
07964                ast_dsp_set_busy_count(i->dsp, i->busycount);
07965                ast_dsp_set_busy_pattern(i->dsp, i->busy_tonelength, i->busy_quietlength);
07966             }
07967          }
07968       }
07969    }
07970 
07971    if (state == AST_STATE_RING)
07972       tmp->rings = 1;
07973    tmp->tech_pvt = i;
07974    if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) {
07975       /* Only FXO signalled stuff can be picked up */
07976       tmp->callgroup = i->callgroup;
07977       tmp->pickupgroup = i->pickupgroup;
07978    }
07979    if (!ast_strlen_zero(i->parkinglot))
07980       ast_string_field_set(tmp, parkinglot, i->parkinglot);
07981    if (!ast_strlen_zero(i->language))
07982       ast_string_field_set(tmp, language, i->language);
07983    if (!i->owner)
07984       i->owner = tmp;
07985    if (!ast_strlen_zero(i->accountcode))
07986       ast_string_field_set(tmp, accountcode, i->accountcode);
07987    if (i->amaflags)
07988       tmp->amaflags = i->amaflags;
07989    i->subs[idx].owner = tmp;
07990    ast_copy_string(tmp->context, i->context, sizeof(tmp->context));
07991    ast_string_field_set(tmp, call_forward, i->call_forward);
07992    /* If we've been told "no ADSI" then enforce it */
07993    if (!i->adsi)
07994       tmp->adsicpe = AST_ADSI_UNAVAILABLE;
07995    if (!ast_strlen_zero(i->exten))
07996       ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten));
07997    if (!ast_strlen_zero(i->rdnis))
07998       tmp->cid.cid_rdnis = ast_strdup(i->rdnis);
07999    if (!ast_strlen_zero(i->dnid))
08000       tmp->cid.cid_dnid = ast_strdup(i->dnid);
08001 
08002    /* Don't use ast_set_callerid() here because it will
08003     * generate a needless NewCallerID event */
08004 #ifdef PRI_ANI
08005    if (!ast_strlen_zero(i->cid_ani))
08006       tmp->cid.cid_ani = ast_strdup(i->cid_ani);
08007    else
08008       tmp->cid.cid_ani = ast_strdup(i->cid_num);
08009 #else
08010    tmp->cid.cid_ani = ast_strdup(i->cid_num);
08011 #endif
08012    tmp->cid.cid_pres = i->callingpres;
08013    tmp->cid.cid_ton = i->cid_ton;
08014    tmp->cid.cid_ani2 = i->cid_ani2;
08015 #if defined(HAVE_PRI) || defined(HAVE_SS7)
08016    tmp->transfercapability = transfercapability;
08017    pbx_builtin_setvar_helper(tmp, "TRANSFERCAPABILITY", ast_transfercapability2str(transfercapability));
08018    if (transfercapability & AST_TRANS_CAP_DIGITAL)
08019       i->digital = 1;
08020    /* Assume calls are not idle calls unless we're told differently */
08021    i->isidlecall = 0;
08022    i->alreadyhungup = 0;
08023 #endif
08024    /* clear the fake event in case we posted one before we had ast_channel */
08025    i->fake_event = 0;
08026    /* Assure there is no confmute on this channel */
08027    dahdi_confmute(i, 0);
08028    i->muting = 0;
08029    /* Configure the new channel jb */
08030    ast_jb_configure(tmp, &global_jbconf);
08031 
08032    ast_devstate_changed_literal(ast_state_chan2dev(state), tmp->name);
08033 
08034    for (v = i->vars ; v ; v = v->next)
08035       pbx_builtin_setvar_helper(tmp, v->name, v->value);
08036 
08037    if (startpbx) {
08038 #ifdef HAVE_OPENR2
08039       if (i->mfcr2call) {
08040          pbx_builtin_setvar_helper(tmp, "MFCR2_CATEGORY", openr2_proto_get_category_string(i->mfcr2_recvd_category));
08041       }
08042 #endif
08043       if (ast_pbx_start(tmp)) {
08044          ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
08045          ast_hangup(tmp);
08046          i->owner = NULL;
08047          return NULL;
08048       }
08049    }
08050 
08051    ast_module_ref(ast_module_info->self);
08052    return tmp;
08053 }
08054 
08055 
08056 static int my_getsigstr(struct ast_channel *chan, char *str, const char *term, int ms)
08057 {
08058    char c;
08059 
08060    *str = 0; /* start with empty output buffer */
08061    for (;;)
08062    {
08063       /* Wait for the first digit (up to specified ms). */
08064       c = ast_waitfordigit(chan, ms);
08065       /* if timeout, hangup or error, return as such */
08066       if (c < 1)
08067          return c;
08068       *str++ = c;
08069       *str = 0;
08070       if (strchr(term, c))
08071          return 1;
08072    }
08073 }
08074 
08075 static int dahdi_wink(struct dahdi_pvt *p, int idx)
08076 {
08077    int j;
08078    dahdi_set_hook(p->subs[idx].dfd, DAHDI_WINK);
08079    for (;;)
08080    {
08081       /* set bits of interest */
08082       j = DAHDI_IOMUX_SIGEVENT;
08083       /* wait for some happening */
08084       if (ioctl(p->subs[idx].dfd,DAHDI_IOMUX,&j) == -1) return(-1);
08085       /* exit loop if we have it */
08086       if (j & DAHDI_IOMUX_SIGEVENT) break;
08087    }
08088    /* get the event info */
08089    if (ioctl(p->subs[idx].dfd,DAHDI_GETEVENT,&j) == -1) return(-1);
08090    return 0;
08091 }
08092 
08093 /*! \brief enable or disable the chan_dahdi Do-Not-Disturb mode for a DAHDI channel
08094  * \param dahdichan "Physical" DAHDI channel (e.g: DAHDI/5)
08095  * \param on 1 to enable, 0 to disable
08096  *
08097  * chan_dahdi has a DND (Do Not Disturb) mode for each dahdichan (physical
08098  * DAHDI channel). Use this to enable or disable it.
08099  *
08100  * \bug the use of the word "channel" for those dahdichans is really confusing.
08101  */
08102 static void dahdi_dnd(struct dahdi_pvt *dahdichan, int on)
08103 {
08104    /* Do not disturb */
08105    dahdichan->dnd = on;
08106    ast_verb(3, "%s DND on channel %d\n",
08107          on? "Enabled" : "Disabled",
08108          dahdichan->channel);
08109    manager_event(EVENT_FLAG_SYSTEM, "DNDState",
08110          "Channel: DAHDI/%d\r\n"
08111          "Status: %s\r\n", dahdichan->channel,
08112          on? "enabled" : "disabled");
08113 }
08114 
08115 static void *ss_thread(void *data)
08116 {
08117    struct ast_channel *chan = data;
08118    struct dahdi_pvt *p = chan->tech_pvt;
08119    char exten[AST_MAX_EXTENSION] = "";
08120    char exten2[AST_MAX_EXTENSION] = "";
08121    unsigned char buf[256];
08122    char dtmfcid[300];
08123    char dtmfbuf[300];
08124    struct callerid_state *cs = NULL;
08125    char *name = NULL, *number = NULL;
08126    int distMatches;
08127    int curRingData[3];
08128    int receivedRingT;
08129    int counter1;
08130    int counter;
08131    int samples = 0;
08132    struct ast_smdi_md_message *smdi_msg = NULL;
08133    int flags = 0;
08134    int i;
08135    int timeout;
08136    int getforward = 0;
08137    char *s1, *s2;
08138    int len = 0;
08139    int res;
08140    int idx;
08141 
08142    ast_mutex_lock(&ss_thread_lock);
08143    ss_thread_count++;
08144    ast_mutex_unlock(&ss_thread_lock);
08145    /* in the bizarre case where the channel has become a zombie before we
08146       even get started here, abort safely
08147    */
08148    if (!p) {
08149       ast_log(LOG_WARNING, "Channel became a zombie before simple switch could be started (%s)\n", chan->name);
08150       ast_hangup(chan);
08151       goto quit;
08152    }
08153    ast_verb(3, "Starting simple switch on '%s'\n", chan->name);
08154    idx = dahdi_get_index(chan, p, 0);
08155    if (idx < 0) {
08156       ast_hangup(chan);
08157       goto quit;
08158    }
08159    if (p->dsp)
08160       ast_dsp_digitreset(p->dsp);
08161    switch (p->sig) {
08162 #ifdef HAVE_PRI
08163    case SIG_PRI:
08164    case SIG_BRI:
08165    case SIG_BRI_PTMP:
08166       /* Now loop looking for an extension */
08167       ast_copy_string(exten, p->exten, sizeof(exten));
08168       len = strlen(exten);
08169       res = 0;
08170       while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
08171          if (len && !ast_ignore_pattern(chan->context, exten))
08172             tone_zone_play_tone(p->subs[idx].dfd, -1);
08173          else
08174             tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
08175          if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num))
08176             timeout = matchdigittimeout;
08177          else
08178             timeout = gendigittimeout;
08179          res = ast_waitfordigit(chan, timeout);
08180          if (res < 0) {
08181             ast_debug(1, "waitfordigit returned < 0...\n");
08182             ast_hangup(chan);
08183             goto quit;
08184          } else if (res) {
08185             exten[len++] = res;
08186             exten[len] = '\0';
08187          } else
08188             break;
08189       }
08190       /* if no extension was received ('unspecified') on overlap call, use the 's' extension */
08191       if (ast_strlen_zero(exten)) {
08192          ast_verb(3, "Going to extension s|1 because of empty extension received on overlap call\n");
08193          exten[0] = 's';
08194          exten[1] = '\0';
08195       }
08196       tone_zone_play_tone(p->subs[idx].dfd, -1);
08197       if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num)) {
08198          /* Start the real PBX */
08199          ast_copy_string(chan->exten, exten, sizeof(chan->exten));
08200          if (p->dsp) {
08201             ast_dsp_digitreset(p->dsp);
08202          }
08203 #if defined(ISSUE_16789)
08204          /*
08205           * Conditionaled out this code to effectively revert the Mantis
08206           * issue 16789 change.  It breaks overlap dialing through
08207           * Asterisk.  There is not enough information available at this
08208           * point to know if dialing is complete.  The
08209           * ast_exists_extension(), ast_matchmore_extension(), and
08210           * ast_canmatch_extension() calls are not adequate to detect a
08211           * dial through extension pattern of "_9!".
08212           *
08213           * Workaround is to use the dialplan Proceeding() application
08214           * early on non-dial through extensions.
08215           */
08216          if ((p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)
08217             && !ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
08218             ast_mutex_lock(&p->lock);
08219             if (p->pri->pri) {
08220                if (!pri_grab(p, p->pri)) {
08221                   if (p->call_level < DAHDI_CALL_LEVEL_PROCEEDING) {
08222                      p->call_level = DAHDI_CALL_LEVEL_PROCEEDING;
08223                   }
08224                   pri_proceeding(p->pri->pri, p->call, PVT_TO_CHANNEL(p), 0);
08225                   pri_rel(p->pri);
08226                } else {
08227                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
08228                }
08229             }
08230             ast_mutex_unlock(&p->lock);
08231          }
08232 #endif   /* defined(ISSUE_16789) */
08233 
08234          dahdi_enable_ec(p);
08235          ast_setstate(chan, AST_STATE_RING);
08236          res = ast_pbx_run(chan);
08237          if (res) {
08238             ast_log(LOG_WARNING, "PBX exited non-zero!\n");
08239          }
08240       } else {
08241          ast_debug(1, "No such possible extension '%s' in context '%s'\n", exten, chan->context);
08242          chan->hangupcause = AST_CAUSE_UNALLOCATED;
08243          ast_hangup(chan);
08244          p->exten[0] = '\0';
08245          /* Since we send release complete here, we won't get one */
08246          p->call = NULL;
08247       }
08248       goto quit;
08249       break;
08250 #endif
08251    case SIG_FEATD:
08252    case SIG_FEATDMF:
08253    case SIG_FEATDMF_TA:
08254    case SIG_E911:
08255    case SIG_FGC_CAMAMF:
08256    case SIG_FEATB:
08257    case SIG_EMWINK:
08258    case SIG_SF_FEATD:
08259    case SIG_SF_FEATDMF:
08260    case SIG_SF_FEATB:
08261    case SIG_SFWINK:
08262       if (dahdi_wink(p, idx))
08263          goto quit;
08264       /* Fall through */
08265    case SIG_EM:
08266    case SIG_EM_E1:
08267    case SIG_SF:
08268    case SIG_FGC_CAMA:
08269       res = tone_zone_play_tone(p->subs[idx].dfd, -1);
08270       if (p->dsp)
08271          ast_dsp_digitreset(p->dsp);
08272       /* set digit mode appropriately */
08273       if (p->dsp) {
08274          if (NEED_MFDETECT(p))
08275             ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
08276          else
08277             ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
08278       }
08279       memset(dtmfbuf, 0, sizeof(dtmfbuf));
08280       /* Wait for the first digit only if immediate=no */
08281       if (!p->immediate)
08282          /* Wait for the first digit (up to 5 seconds). */
08283          res = ast_waitfordigit(chan, 5000);
08284       else
08285          res = 0;
08286       if (res > 0) {
08287          /* save first char */
08288          dtmfbuf[0] = res;
08289          switch (p->sig) {
08290          case SIG_FEATD:
08291          case SIG_SF_FEATD:
08292             res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
08293             if (res > 0)
08294                res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
08295             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
08296             break;
08297          case SIG_FEATDMF_TA:
08298             res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
08299             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
08300             if (dahdi_wink(p, idx)) goto quit;
08301             dtmfbuf[0] = 0;
08302             /* Wait for the first digit (up to 5 seconds). */
08303             res = ast_waitfordigit(chan, 5000);
08304             if (res <= 0) break;
08305             dtmfbuf[0] = res;
08306             /* fall through intentionally */
08307          case SIG_FEATDMF:
08308          case SIG_E911:
08309          case SIG_FGC_CAMAMF:
08310          case SIG_SF_FEATDMF:
08311             res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
08312             /* if international caca, do it again to get real ANO */
08313             if ((p->sig == SIG_FEATDMF) && (dtmfbuf[1] != '0') && (strlen(dtmfbuf) != 14))
08314             {
08315                if (dahdi_wink(p, idx)) goto quit;
08316                dtmfbuf[0] = 0;
08317                /* Wait for the first digit (up to 5 seconds). */
08318                res = ast_waitfordigit(chan, 5000);
08319                if (res <= 0) break;
08320                dtmfbuf[0] = res;
08321                res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
08322             }
08323             if (res > 0) {
08324                /* if E911, take off hook */
08325                if (p->sig == SIG_E911)
08326                   dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
08327                res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "#", 3000);
08328             }
08329             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
08330             break;
08331          case SIG_FEATB:
08332          case SIG_SF_FEATB:
08333             res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
08334             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
08335             break;
08336          case SIG_EMWINK:
08337             /* if we received a '*', we are actually receiving Feature Group D
08338                dial syntax, so use that mode; otherwise, fall through to normal
08339                mode
08340             */
08341             if (res == '*') {
08342                res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
08343                if (res > 0)
08344                   res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
08345                if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
08346                break;
08347             }
08348          default:
08349             /* If we got the first digit, get the rest */
08350             len = 1;
08351             dtmfbuf[len] = '\0';
08352             while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
08353                if (ast_exists_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
08354                   timeout = matchdigittimeout;
08355                } else {
08356                   timeout = gendigittimeout;
08357                }
08358                res = ast_waitfordigit(chan, timeout);
08359                if (res < 0) {
08360                   ast_debug(1, "waitfordigit returned < 0...\n");
08361                   ast_hangup(chan);
08362                   goto quit;
08363                } else if (res) {
08364                   dtmfbuf[len++] = res;
08365                   dtmfbuf[len] = '\0';
08366                } else {
08367                   break;
08368                }
08369             }
08370             break;
08371          }
08372       }
08373       if (res == -1) {
08374          ast_log(LOG_WARNING, "getdtmf on channel %d: %s\n", p->channel, strerror(errno));
08375          ast_hangup(chan);
08376          goto quit;
08377       } else if (res < 0) {
08378          ast_debug(1, "Got hung up before digits finished\n");
08379          ast_hangup(chan);
08380          goto quit;
08381       }
08382 
08383       if (p->sig == SIG_FGC_CAMA) {
08384          char anibuf[100];
08385 
08386          if (ast_safe_sleep(chan,1000) == -1) {
08387             ast_hangup(chan);
08388             goto quit;
08389          }
08390          dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
08391          ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
08392          res = my_getsigstr(chan, anibuf, "#", 10000);
08393          if ((res > 0) && (strlen(anibuf) > 2)) {
08394             if (anibuf[strlen(anibuf) - 1] == '#')
08395                anibuf[strlen(anibuf) - 1] = 0;
08396             ast_set_callerid(chan, anibuf + 2, NULL, anibuf + 2);
08397          }
08398          ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
08399       }
08400 
08401       ast_copy_string(exten, dtmfbuf, sizeof(exten));
08402       if (ast_strlen_zero(exten))
08403          ast_copy_string(exten, "s", sizeof(exten));
08404       if (p->sig == SIG_FEATD || p->sig == SIG_EMWINK) {
08405          /* Look for Feature Group D on all E&M Wink and Feature Group D trunks */
08406          if (exten[0] == '*') {
08407             char *stringp=NULL;
08408             ast_copy_string(exten2, exten, sizeof(exten2));
08409             /* Parse out extension and callerid */
08410             stringp=exten2 +1;
08411             s1 = strsep(&stringp, "*");
08412             s2 = strsep(&stringp, "*");
08413             if (s2) {
08414                if (!ast_strlen_zero(p->cid_num))
08415                   ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
08416                else
08417                   ast_set_callerid(chan, s1, NULL, s1);
08418                ast_copy_string(exten, s2, sizeof(exten));
08419             } else
08420                ast_copy_string(exten, s1, sizeof(exten));
08421          } else if (p->sig == SIG_FEATD)
08422             ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d.  Assuming E&M Wink instead\n", p->channel);
08423       }
08424       if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
08425          if (exten[0] == '*') {
08426             char *stringp=NULL;
08427             ast_copy_string(exten2, exten, sizeof(exten2));
08428             /* Parse out extension and callerid */
08429             stringp=exten2 +1;
08430             s1 = strsep(&stringp, "#");
08431             s2 = strsep(&stringp, "#");
08432             if (s2) {
08433                if (!ast_strlen_zero(p->cid_num))
08434                   ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
08435                else
08436                   if (*(s1 + 2))
08437                      ast_set_callerid(chan, s1 + 2, NULL, s1 + 2);
08438                ast_copy_string(exten, s2 + 1, sizeof(exten));
08439             } else
08440                ast_copy_string(exten, s1 + 2, sizeof(exten));
08441          } else
08442             ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d.  Assuming E&M Wink instead\n", p->channel);
08443       }
08444       if ((p->sig == SIG_E911) || (p->sig == SIG_FGC_CAMAMF)) {
08445          if (exten[0] == '*') {
08446             char *stringp=NULL;
08447             ast_copy_string(exten2, exten, sizeof(exten2));
08448             /* Parse out extension and callerid */
08449             stringp=exten2 +1;
08450             s1 = strsep(&stringp, "#");
08451             s2 = strsep(&stringp, "#");
08452             if (s2 && (*(s2 + 1) == '0')) {
08453                if (*(s2 + 2))
08454                   ast_set_callerid(chan, s2 + 2, NULL, s2 + 2);
08455             }
08456             if (s1)  ast_copy_string(exten, s1, sizeof(exten));
08457             else ast_copy_string(exten, "911", sizeof(exten));
08458          } else
08459             ast_log(LOG_WARNING, "Got a non-E911/FGC CAMA input on channel %d.  Assuming E&M Wink instead\n", p->channel);
08460       }
08461       if (p->sig == SIG_FEATB) {
08462          if (exten[0] == '*') {
08463             char *stringp=NULL;
08464             ast_copy_string(exten2, exten, sizeof(exten2));
08465             /* Parse out extension and callerid */
08466             stringp=exten2 +1;
08467             s1 = strsep(&stringp, "#");
08468             ast_copy_string(exten, exten2 + 1, sizeof(exten));
08469          } else
08470             ast_log(LOG_WARNING, "Got a non-Feature Group B input on channel %d.  Assuming E&M Wink instead\n", p->channel);
08471       }
08472       if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
08473          dahdi_wink(p, idx);
08474          /* some switches require a minimum guard time between
08475             the last FGD wink and something that answers
08476             immediately. This ensures it */
08477          if (ast_safe_sleep(chan, 100)) {
08478             ast_hangup(chan);
08479             goto quit;
08480          }
08481       }
08482       dahdi_enable_ec(p);
08483       if (NEED_MFDETECT(p)) {
08484          if (p->dsp) {
08485             if (!p->hardwaredtmf)
08486                ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
08487             else {
08488                ast_dsp_free(p->dsp);
08489                p->dsp = NULL;
08490             }
08491          }
08492       }
08493 
08494       if (ast_exists_extension(chan, chan->context, exten, 1, chan->cid.cid_num)) {
08495          ast_copy_string(chan->exten, exten, sizeof(chan->exten));
08496          if (p->dsp) ast_dsp_digitreset(p->dsp);
08497          res = ast_pbx_run(chan);
08498          if (res) {
08499             ast_log(LOG_WARNING, "PBX exited non-zero\n");
08500             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
08501          }
08502          goto quit;
08503       } else {
08504          ast_verb(2, "Unknown extension '%s' in context '%s' requested\n", exten, chan->context);
08505          sleep(2);
08506          res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_INFO);
08507          if (res < 0)
08508             ast_log(LOG_WARNING, "Unable to start special tone on %d\n", p->channel);
08509          else
08510             sleep(1);
08511          res = ast_streamfile(chan, "ss-noservice", chan->language);
08512          if (res >= 0)
08513             ast_waitstream(chan, "");
08514          res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
08515          ast_hangup(chan);
08516          goto quit;
08517       }
08518       break;
08519    case SIG_FXOLS:
08520    case SIG_FXOGS:
08521    case SIG_FXOKS:
08522       /* Read the first digit */
08523       timeout = firstdigittimeout;
08524       /* If starting a threeway call, never timeout on the first digit so someone
08525          can use flash-hook as a "hold" feature */
08526       if (p->subs[SUB_THREEWAY].owner)
08527          timeout = 999999;
08528       while (len < AST_MAX_EXTENSION-1) {
08529          /* Read digit unless it's supposed to be immediate, in which case the
08530             only answer is 's' */
08531          if (p->immediate)
08532             res = 's';
08533          else
08534             res = ast_waitfordigit(chan, timeout);
08535          timeout = 0;
08536          if (res < 0) {
08537             ast_debug(1, "waitfordigit returned < 0...\n");
08538             res = tone_zone_play_tone(p->subs[idx].dfd, -1);
08539             ast_hangup(chan);
08540             goto quit;
08541          } else if (res) {
08542             ast_debug(1,"waitfordigit returned '%c' (%d), timeout = %d\n", res, res, timeout);
08543             exten[len++]=res;
08544             exten[len] = '\0';
08545          }
08546          if (!ast_ignore_pattern(chan->context, exten))
08547             tone_zone_play_tone(p->subs[idx].dfd, -1);
08548          else
08549             tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
08550          if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num) && strcmp(exten, ast_parking_ext())) {
08551             if (!res || !ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
08552                if (getforward) {
08553                   /* Record this as the forwarding extension */
08554                   ast_copy_string(p->call_forward, exten, sizeof(p->call_forward));
08555                   ast_verb(3, "Setting call forward to '%s' on channel %d\n", p->call_forward, p->channel);
08556                   res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
08557                   if (res)
08558                      break;
08559                   usleep(500000);
08560                   res = tone_zone_play_tone(p->subs[idx].dfd, -1);
08561                   sleep(1);
08562                   memset(exten, 0, sizeof(exten));
08563                   res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
08564                   len = 0;
08565                   getforward = 0;
08566                } else {
08567                   res = tone_zone_play_tone(p->subs[idx].dfd, -1);
08568                   ast_copy_string(chan->exten, exten, sizeof(chan->exten));
08569                   if (!ast_strlen_zero(p->cid_num)) {
08570                      if (!p->hidecallerid)
08571                         ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
08572                      else
08573                         ast_set_callerid(chan, NULL, NULL, p->cid_num);
08574                   }
08575                   if (!ast_strlen_zero(p->cid_name)) {
08576                      if (!p->hidecallerid)
08577                         ast_set_callerid(chan, NULL, p->cid_name, NULL);
08578                   }
08579                   ast_setstate(chan, AST_STATE_RING);
08580                   dahdi_enable_ec(p);
08581                   res = ast_pbx_run(chan);
08582                   if (res) {
08583                      ast_log(LOG_WARNING, "PBX exited non-zero\n");
08584                      res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
08585                   }
08586                   goto quit;
08587                }
08588             } else {
08589                /* It's a match, but they just typed a digit, and there is an ambiguous match,
08590                   so just set the timeout to matchdigittimeout and wait some more */
08591                timeout = matchdigittimeout;
08592             }
08593          } else if (res == 0) {
08594             ast_debug(1, "not enough digits (and no ambiguous match)...\n");
08595             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
08596             dahdi_wait_event(p->subs[idx].dfd);
08597             ast_hangup(chan);
08598             goto quit;
08599          } else if (p->callwaiting && !strcmp(exten, "*70")) {
08600             ast_verb(3, "Disabling call waiting on %s\n", chan->name);
08601             /* Disable call waiting if enabled */
08602             p->callwaiting = 0;
08603             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
08604             if (res) {
08605                ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
08606                   chan->name, strerror(errno));
08607             }
08608             len = 0;
08609             ioctl(p->subs[idx].dfd,DAHDI_CONFDIAG,&len);
08610             memset(exten, 0, sizeof(exten));
08611             timeout = firstdigittimeout;
08612 
08613          } else if (!strcmp(exten,ast_pickup_ext())) {
08614             /* Scan all channels and see if there are any
08615              * ringing channels that have call groups
08616              * that equal this channels pickup group
08617              */
08618             if (idx == SUB_REAL) {
08619                /* Switch us from Third call to Call Wait */
08620                if (p->subs[SUB_THREEWAY].owner) {
08621                   /* If you make a threeway call and the *8# a call, it should actually
08622                      look like a callwait */
08623                   alloc_sub(p, SUB_CALLWAIT);
08624                   swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
08625                   unalloc_sub(p, SUB_THREEWAY);
08626                }
08627                dahdi_enable_ec(p);
08628                if (ast_pickup_call(chan)) {
08629                   ast_debug(1, "No call pickup possible...\n");
08630                   res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
08631                   dahdi_wait_event(p->subs[idx].dfd);
08632                }
08633                ast_hangup(chan);
08634                goto quit;
08635             } else {
08636                ast_log(LOG_WARNING, "Huh?  Got *8# on call not on real\n");
08637                ast_hangup(chan);
08638                goto quit;
08639             }
08640 
08641          } else if (!p->hidecallerid && !strcmp(exten, "*67")) {
08642             ast_verb(3, "Disabling Caller*ID on %s\n", chan->name);
08643             /* Disable Caller*ID if enabled */
08644             p->hidecallerid = 1;
08645             if (chan->cid.cid_num)
08646                ast_free(chan->cid.cid_num);
08647             chan->cid.cid_num = NULL;
08648             if (chan->cid.cid_name)
08649                ast_free(chan->cid.cid_name);
08650             chan->cid.cid_name = NULL;
08651             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
08652             if (res) {
08653                ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
08654                   chan->name, strerror(errno));
08655             }
08656             len = 0;
08657             memset(exten, 0, sizeof(exten));
08658             timeout = firstdigittimeout;
08659          } else if (p->callreturn && !strcmp(exten, "*69")) {
08660             res = 0;
08661             if (!ast_strlen_zero(p->lastcid_num)) {
08662                res = ast_say_digit_str(chan, p->lastcid_num, "", chan->language);
08663             }
08664             if (!res)
08665                res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
08666             break;
08667          } else if (!strcmp(exten, "*78")) {
08668             dahdi_dnd(p, 1);
08669             /* Do not disturb */
08670             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
08671             getforward = 0;
08672             memset(exten, 0, sizeof(exten));
08673             len = 0;
08674          } else if (!strcmp(exten, "*79")) {
08675             dahdi_dnd(p, 0);
08676             /* Do not disturb */
08677             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
08678             getforward = 0;
08679             memset(exten, 0, sizeof(exten));
08680             len = 0;
08681          } else if (p->cancallforward && !strcmp(exten, "*72")) {
08682             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
08683             getforward = 1;
08684             memset(exten, 0, sizeof(exten));
08685             len = 0;
08686          } else if (p->cancallforward && !strcmp(exten, "*73")) {
08687             ast_verb(3, "Cancelling call forwarding on channel %d\n", p->channel);
08688             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
08689             memset(p->call_forward, 0, sizeof(p->call_forward));
08690             getforward = 0;
08691             memset(exten, 0, sizeof(exten));
08692             len = 0;
08693          } else if ((p->transfer || p->canpark) && !strcmp(exten, ast_parking_ext()) &&
08694                   p->subs[SUB_THREEWAY].owner &&
08695                   ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
08696             /* This is a three way call, the main call being a real channel,
08697                and we're parking the first call. */
08698             ast_masq_park_call(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), chan, 0, NULL);
08699             ast_verb(3, "Parking call to '%s'\n", chan->name);
08700             break;
08701          } else if (!ast_strlen_zero(p->lastcid_num) && !strcmp(exten, "*60")) {
08702             ast_verb(3, "Blacklisting number %s\n", p->lastcid_num);
08703             res = ast_db_put("blacklist", p->lastcid_num, "1");
08704             if (!res) {
08705                res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
08706                memset(exten, 0, sizeof(exten));
08707                len = 0;
08708             }
08709          } else if (p->hidecallerid && !strcmp(exten, "*82")) {
08710             ast_verb(3, "Enabling Caller*ID on %s\n", chan->name);
08711             /* Enable Caller*ID if enabled */
08712             p->hidecallerid = 0;
08713             if (chan->cid.cid_num)
08714                ast_free(chan->cid.cid_num);
08715             chan->cid.cid_num = NULL;
08716             if (chan->cid.cid_name)
08717                ast_free(chan->cid.cid_name);
08718             chan->cid.cid_name = NULL;
08719             ast_set_callerid(chan, p->cid_num, p->cid_name, NULL);
08720             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
08721             if (res) {
08722                ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
08723                   chan->name, strerror(errno));
08724             }
08725             len = 0;
08726             memset(exten, 0, sizeof(exten));
08727             timeout = firstdigittimeout;
08728          } else if (!strcmp(exten, "*0")) {
08729             struct ast_channel *nbridge =
08730                p->subs[SUB_THREEWAY].owner;
08731             struct dahdi_pvt *pbridge = NULL;
08732             /* set up the private struct of the bridged one, if any */
08733             if (nbridge && ast_bridged_channel(nbridge))
08734                pbridge = ast_bridged_channel(nbridge)->tech_pvt;
08735             if (nbridge && pbridge &&
08736                (nbridge->tech == &dahdi_tech) &&
08737                (ast_bridged_channel(nbridge)->tech == &dahdi_tech) &&
08738                ISTRUNK(pbridge)) {
08739                int func = DAHDI_FLASH;
08740                /* Clear out the dial buffer */
08741                p->dop.dialstr[0] = '\0';
08742                /* flash hookswitch */
08743                if ((ioctl(pbridge->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
08744                   ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
08745                      nbridge->name, strerror(errno));
08746                }
08747                swap_subs(p, SUB_REAL, SUB_THREEWAY);
08748                unalloc_sub(p, SUB_THREEWAY);
08749                p->owner = p->subs[SUB_REAL].owner;
08750                if (ast_bridged_channel(p->subs[SUB_REAL].owner))
08751                   ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
08752                ast_hangup(chan);
08753                goto quit;
08754             } else {
08755                tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
08756                dahdi_wait_event(p->subs[idx].dfd);
08757                tone_zone_play_tone(p->subs[idx].dfd, -1);
08758                swap_subs(p, SUB_REAL, SUB_THREEWAY);
08759                unalloc_sub(p, SUB_THREEWAY);
08760                p->owner = p->subs[SUB_REAL].owner;
08761                ast_hangup(chan);
08762                goto quit;
08763             }
08764          } else if (!ast_canmatch_extension(chan, chan->context, exten, 1, chan->cid.cid_num) &&
08765                      ((exten[0] != '*') || (strlen(exten) > 2))) {
08766             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);
08767             break;
08768          }
08769          if (!timeout)
08770             timeout = gendigittimeout;
08771          if (len && !ast_ignore_pattern(chan->context, exten))
08772             tone_zone_play_tone(p->subs[idx].dfd, -1);
08773       }
08774       break;
08775    case SIG_FXSLS:
08776    case SIG_FXSGS:
08777    case SIG_FXSKS:
08778 #ifdef HAVE_PRI
08779       if (p->pri) {
08780          /* This is a GR-303 trunk actually.  Wait for the first ring... */
08781          struct ast_frame *f;
08782          int res;
08783          time_t start;
08784 
08785          time(&start);
08786          ast_setstate(chan, AST_STATE_RING);
08787          while (time(NULL) < start + 3) {
08788             res = ast_waitfor(chan, 1000);
08789             if (res) {
08790                f = ast_read(chan);
08791                if (!f) {
08792                   ast_log(LOG_WARNING, "Whoa, hangup while waiting for first ring!\n");
08793                   ast_hangup(chan);
08794                   goto quit;
08795                } else if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_RING)) {
08796                   res = 1;
08797                } else
08798                   res = 0;
08799                ast_frfree(f);
08800                if (res) {
08801                   ast_debug(1, "Got ring!\n");
08802                   res = 0;
08803                   break;
08804                }
08805             }
08806          }
08807       }
08808 #endif
08809       /* check for SMDI messages */
08810       if (p->use_smdi && p->smdi_iface) {
08811          smdi_msg = ast_smdi_md_message_wait(p->smdi_iface, SMDI_MD_WAIT_TIMEOUT);
08812 
08813          if (smdi_msg != NULL) {
08814             ast_copy_string(chan->exten, smdi_msg->fwd_st, sizeof(chan->exten));
08815 
08816             if (smdi_msg->type == 'B')
08817                pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "b");
08818             else if (smdi_msg->type == 'N')
08819                pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "u");
08820 
08821             ast_debug(1, "Received SMDI message on %s\n", chan->name);
08822          } else {
08823             ast_log(LOG_WARNING, "SMDI enabled but no SMDI message present\n");
08824          }
08825       }
08826 
08827       if (p->use_callerid && (p->cid_signalling == CID_SIG_SMDI && smdi_msg)) {
08828          number = smdi_msg->calling_st;
08829 
08830       /* If we want caller id, we're in a prering state due to a polarity reversal
08831        * and we're set to use a polarity reversal to trigger the start of caller id,
08832        * grab the caller id and wait for ringing to start... */
08833       } else if (p->use_callerid && (chan->_state == AST_STATE_PRERING && (p->cid_start == CID_START_POLARITY || p->cid_start == CID_START_POLARITY_IN))) {
08834          /* If set to use DTMF CID signalling, listen for DTMF */
08835          if (p->cid_signalling == CID_SIG_DTMF) {
08836             int k = 0;
08837             cs = NULL;
08838             ast_debug(1, "Receiving DTMF cid on channel %s\n", chan->name);
08839             dahdi_setlinear(p->subs[idx].dfd, 0);
08840             /*
08841              * We are the only party interested in the Rx stream since
08842              * we have not answered yet.  We don't need or even want DTMF
08843              * emulation.  The DTMF digits can come so fast that emulation
08844              * can drop some of them.
08845              */
08846             ast_set_flag(chan, AST_FLAG_END_DTMF_ONLY);
08847             res = 4000;/* This is a typical OFF time between rings. */
08848             for (;;) {
08849                struct ast_frame *f;
08850                res = ast_waitfor(chan, res);
08851                if (res <= 0) {
08852                   /*
08853                    * We do not need to restore the dahdi_setlinear()
08854                    * or AST_FLAG_END_DTMF_ONLY flag settings since we
08855                    * are hanging up the channel.
08856                    */
08857                   ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
08858                      "Exiting simple switch\n");
08859                   ast_hangup(chan);
08860                   goto quit;
08861                }
08862                f = ast_read(chan);
08863                if (!f)
08864                   break;
08865                if (f->frametype == AST_FRAME_DTMF) {
08866                   if (k < ARRAY_LEN(dtmfbuf) - 1) {
08867                      dtmfbuf[k++] = f->subclass;
08868                   }
08869                   ast_debug(1, "CID got digit '%c'\n", f->subclass);
08870                   res = 4000;/* This is a typical OFF time between rings. */
08871                }
08872                ast_frfree(f);
08873                if (chan->_state == AST_STATE_RING ||
08874                   chan->_state == AST_STATE_RINGING)
08875                   break; /* Got ring */
08876             }
08877             ast_clear_flag(chan, AST_FLAG_END_DTMF_ONLY);
08878             dtmfbuf[k] = '\0';
08879             dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
08880             /* Got cid and ring. */
08881             ast_debug(1, "CID got string '%s'\n", dtmfbuf);
08882             callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
08883             ast_debug(1, "CID is '%s', flags %d\n", dtmfcid, flags);
08884             /* If first byte is NULL, we have no cid */
08885             if (!ast_strlen_zero(dtmfcid))
08886                number = dtmfcid;
08887             else
08888                number = NULL;
08889          /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */
08890          } else if ((p->cid_signalling == CID_SIG_V23) || (p->cid_signalling == CID_SIG_V23_JP)) {
08891             cs = callerid_new(p->cid_signalling);
08892             if (cs) {
08893                samples = 0;
08894 #if 1
08895                bump_gains(p);
08896 #endif
08897                /* Take out of linear mode for Caller*ID processing */
08898                dahdi_setlinear(p->subs[idx].dfd, 0);
08899 
08900                /* First we wait and listen for the Caller*ID */
08901                for (;;) {
08902                   i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
08903                   if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
08904                      ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
08905                      callerid_free(cs);
08906                      ast_hangup(chan);
08907                      goto quit;
08908                   }
08909                   if (i & DAHDI_IOMUX_SIGEVENT) {
08910                      res = dahdi_get_event(p->subs[idx].dfd);
08911                      ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
08912                      if (res == DAHDI_EVENT_NOALARM) {
08913                         p->inalarm = 0;
08914                      }
08915 
08916                      if (p->cid_signalling == CID_SIG_V23_JP) {
08917                         if (res == DAHDI_EVENT_RINGBEGIN) {
08918                            res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
08919                            usleep(1);
08920                         }
08921                      } else {
08922                         res = 0;
08923                         break;
08924                      }
08925                   } else if (i & DAHDI_IOMUX_READ) {
08926                      res = read(p->subs[idx].dfd, buf, sizeof(buf));
08927                      if (res < 0) {
08928                         if (errno != ELAST) {
08929                            ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
08930                            callerid_free(cs);
08931                            ast_hangup(chan);
08932                            goto quit;
08933                         }
08934                         break;
08935                      }
08936                      samples += res;
08937 
08938                      if (p->cid_signalling == CID_SIG_V23_JP) {
08939                         res = callerid_feed_jp(cs, buf, res, AST_LAW(p));
08940                      } else {
08941                         res = callerid_feed(cs, buf, res, AST_LAW(p));
08942                      }
08943                      if (res < 0) {
08944                         /*
08945                          * The previous diagnostic message output likely
08946                          * explains why it failed.
08947                          */
08948                         ast_log(LOG_WARNING,
08949                            "Failed to decode CallerID on channel '%s'\n",
08950                            chan->name);
08951                         break;
08952                      } else if (res)
08953                         break;
08954                      else if (samples > (8000 * 10))
08955                         break;
08956                   }
08957                }
08958                if (res == 1) {
08959                   callerid_get(cs, &name, &number, &flags);
08960                   ast_log(LOG_NOTICE, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
08961                }
08962 
08963                if (p->cid_signalling == CID_SIG_V23_JP) {
08964                   res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
08965                   usleep(1);
08966                }
08967 
08968                /* Finished with Caller*ID, now wait for a ring to make sure there really is a call coming */
08969                res = 4000;/* This is a typical OFF time between rings. */
08970                for (;;) {
08971                   struct ast_frame *f;
08972                   res = ast_waitfor(chan, res);
08973                   if (res <= 0) {
08974                      ast_log(LOG_WARNING, "CID timed out waiting for ring. "
08975                         "Exiting simple switch\n");
08976                      ast_hangup(chan);
08977                      goto quit;
08978                   }
08979                   if (!(f = ast_read(chan))) {
08980                      ast_log(LOG_WARNING, "Hangup received waiting for ring. Exiting simple switch\n");
08981                      ast_hangup(chan);
08982                      goto quit;
08983                   }
08984                   ast_frfree(f);
08985                   if (chan->_state == AST_STATE_RING ||
08986                      chan->_state == AST_STATE_RINGING)
08987                      break; /* Got ring */
08988                }
08989 
08990                /* We must have a ring by now, so, if configured, lets try to listen for
08991                 * distinctive ringing */
08992                if (p->usedistinctiveringdetection) {
08993                   len = 0;
08994                   distMatches = 0;
08995                   /* Clear the current ring data array so we dont have old data in it. */
08996                   for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
08997                      curRingData[receivedRingT] = 0;
08998                   receivedRingT = 0;
08999                   counter = 0;
09000                   counter1 = 0;
09001                   /* Check to see if context is what it should be, if not set to be. */
09002                   if (strcmp(p->context,p->defcontext) != 0) {
09003                      ast_copy_string(p->context, p->defcontext, sizeof(p->context));
09004                      ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
09005                   }
09006 
09007                   for (;;) {
09008                      i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
09009                      if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
09010                         ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
09011                         callerid_free(cs);
09012                         ast_hangup(chan);
09013                         goto quit;
09014                      }
09015                      if (i & DAHDI_IOMUX_SIGEVENT) {
09016                         res = dahdi_get_event(p->subs[idx].dfd);
09017                         ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
09018                         if (res == DAHDI_EVENT_NOALARM) {
09019                            p->inalarm = 0;
09020                         }
09021                         res = 0;
09022                         /* Let us detect distinctive ring */
09023 
09024                         curRingData[receivedRingT] = p->ringt;
09025 
09026                         if (p->ringt < p->ringt_base/2)
09027                            break;
09028                         /* Increment the ringT counter so we can match it against
09029                            values in chan_dahdi.conf for distinctive ring */
09030                         if (++receivedRingT == ARRAY_LEN(curRingData))
09031                            break;
09032                      } else if (i & DAHDI_IOMUX_READ) {
09033                         res = read(p->subs[idx].dfd, buf, sizeof(buf));
09034                         if (res < 0) {
09035                            if (errno != ELAST) {
09036                               ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
09037                               callerid_free(cs);
09038                               ast_hangup(chan);
09039                               goto quit;
09040                            }
09041                            break;
09042                         }
09043                         if (p->ringt)
09044                            p->ringt--;
09045                         if (p->ringt == 1) {
09046                            res = -1;
09047                            break;
09048                         }
09049                      }
09050                   }
09051                      /* this only shows up if you have n of the dring patterns filled in */
09052                   ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
09053                   for (counter = 0; counter < 3; counter++) {
09054                      /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this
09055                      channel */
09056                      distMatches = 0;
09057                      for (counter1 = 0; counter1 < 3; counter1++) {
09058                         ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
09059                         if (p->drings.ringnum[counter].ring[counter1] == -1) {
09060                            ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
09061                            curRingData[counter1]);
09062                            distMatches++;
09063                         } else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
09064                               curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
09065                            ast_verb(3, "Ring pattern matched in range: %d to %d\n",
09066                            (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
09067                            (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
09068                            distMatches++;
09069                         }
09070                      }
09071 
09072                      if (distMatches == 3) {
09073                         /* The ring matches, set the context to whatever is for distinctive ring.. */
09074                         ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context));
09075                         ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context));
09076                         ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
09077                         break;
09078                      }
09079                   }
09080                }
09081                /* Restore linear mode (if appropriate) for Caller*ID processing */
09082                dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09083 #if 1
09084                restore_gains(p);
09085 #endif
09086             } else
09087                ast_log(LOG_WARNING, "Unable to get caller ID space\n");
09088          } else {
09089             ast_log(LOG_WARNING, "Channel %s in prering "
09090                "state, but I have nothing to do. "
09091                "Terminating simple switch, should be "
09092                "restarted by the actual ring.\n",
09093                chan->name);
09094             ast_hangup(chan);
09095             goto quit;
09096          }
09097       } else if (p->use_callerid && p->cid_start == CID_START_RING) {
09098          if (p->cid_signalling == CID_SIG_DTMF) {
09099             int k = 0;
09100             cs = NULL;
09101             dahdi_setlinear(p->subs[idx].dfd, 0);
09102             res = 2000;
09103             for (;;) {
09104                struct ast_frame *f;
09105                res = ast_waitfor(chan, res);
09106                if (res <= 0) {
09107                   ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
09108                      "Exiting simple switch\n");
09109                   ast_hangup(chan);
09110                   return NULL;
09111                }
09112                f = ast_read(chan);
09113                if (f->frametype == AST_FRAME_DTMF) {
09114                   dtmfbuf[k++] = f->subclass;
09115                   ast_log(LOG_DEBUG, "CID got digit '%c'\n", f->subclass);
09116                   res = 2000;
09117                }
09118                ast_frfree(f);
09119 
09120                if (p->ringt_base == p->ringt)
09121                   break;
09122             }
09123             dtmfbuf[k] = '\0';
09124             dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09125             /* Got cid and ring. */
09126             callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
09127             ast_log(LOG_DEBUG, "CID is '%s', flags %d\n",
09128                dtmfcid, flags);
09129             /* If first byte is NULL, we have no cid */
09130             if (!ast_strlen_zero(dtmfcid))
09131                number = dtmfcid;
09132             else
09133                number = NULL;
09134             /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */
09135          } else {
09136             /* FSK Bell202 callerID */
09137             cs = callerid_new(p->cid_signalling);
09138             if (cs) {
09139 #if 1
09140                bump_gains(p);
09141 #endif
09142                samples = 0;
09143                len = 0;
09144                distMatches = 0;
09145                /* Clear the current ring data array so we dont have old data in it. */
09146                for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
09147                   curRingData[receivedRingT] = 0;
09148                receivedRingT = 0;
09149                counter = 0;
09150                counter1 = 0;
09151                /* Check to see if context is what it should be, if not set to be. */
09152                if (strcmp(p->context,p->defcontext) != 0) {
09153                   ast_copy_string(p->context, p->defcontext, sizeof(p->context));
09154                   ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
09155                }
09156 
09157                /* Take out of linear mode for Caller*ID processing */
09158                dahdi_setlinear(p->subs[idx].dfd, 0);
09159                for (;;) {
09160                   i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
09161                   if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
09162                      ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
09163                      callerid_free(cs);
09164                      ast_hangup(chan);
09165                      goto quit;
09166                   }
09167                   if (i & DAHDI_IOMUX_SIGEVENT) {
09168                      res = dahdi_get_event(p->subs[idx].dfd);
09169                      ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
09170                      if (res == DAHDI_EVENT_NOALARM) {
09171                         p->inalarm = 0;
09172                      }
09173                      /* If we get a PR event, they hung up while processing calerid */
09174                      if ( res == DAHDI_EVENT_POLARITY && p->hanguponpolarityswitch && p->polarity == POLARITY_REV) {
09175                         ast_log(LOG_DEBUG, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p->channel);
09176                         p->polarity = POLARITY_IDLE;
09177                         callerid_free(cs);
09178                         ast_hangup(chan);
09179                         goto quit;
09180                      }
09181                      res = 0;
09182                      /* Let us detect callerid when the telco uses distinctive ring */
09183 
09184                      curRingData[receivedRingT] = p->ringt;
09185 
09186                      if (p->ringt < p->ringt_base/2)
09187                         break;
09188                      /* Increment the ringT counter so we can match it against
09189                         values in chan_dahdi.conf for distinctive ring */
09190                      if (++receivedRingT == ARRAY_LEN(curRingData))
09191                         break;
09192                   } else if (i & DAHDI_IOMUX_READ) {
09193                      res = read(p->subs[idx].dfd, buf, sizeof(buf));
09194                      if (res < 0) {
09195                         if (errno != ELAST) {
09196                            ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
09197                            callerid_free(cs);
09198                            ast_hangup(chan);
09199                            goto quit;
09200                         }
09201                         break;
09202                      }
09203                      if (p->ringt)
09204                         p->ringt--;
09205                      if (p->ringt == 1) {
09206                         res = -1;
09207                         break;
09208                      }
09209                      samples += res;
09210                      res = callerid_feed(cs, buf, res, AST_LAW(p));
09211                      if (res < 0) {
09212                         /*
09213                          * The previous diagnostic message output likely
09214                          * explains why it failed.
09215                          */
09216                         ast_log(LOG_WARNING,
09217                            "Failed to decode CallerID on channel '%s'\n",
09218                            chan->name);
09219                         break;
09220                      } else if (res)
09221                         break;
09222                      else if (samples > (8000 * 10))
09223                         break;
09224                   }
09225                }
09226                if (res == 1) {
09227                   callerid_get(cs, &name, &number, &flags);
09228                   ast_debug(1, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
09229                }
09230                if (distinctiveringaftercid == 1) {
09231                   /* Clear the current ring data array so we dont have old data in it. */
09232                   for (receivedRingT = 0; receivedRingT < 3; receivedRingT++) {
09233                      curRingData[receivedRingT] = 0;
09234                   }
09235                   receivedRingT = 0;
09236                   ast_verb(3, "Detecting post-CID distinctive ring\n");
09237                   for (;;) {
09238                      i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
09239                      if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
09240                         ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
09241                         callerid_free(cs);
09242                         ast_hangup(chan);
09243                         goto quit;
09244                      }
09245                      if (i & DAHDI_IOMUX_SIGEVENT) {
09246                         res = dahdi_get_event(p->subs[idx].dfd);
09247                         ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
09248                         if (res == DAHDI_EVENT_NOALARM) {
09249                            p->inalarm = 0;
09250                         }
09251                         res = 0;
09252                         /* Let us detect callerid when the telco uses distinctive ring */
09253 
09254                         curRingData[receivedRingT] = p->ringt;
09255 
09256                         if (p->ringt < p->ringt_base/2)
09257                            break;
09258                         /* Increment the ringT counter so we can match it against
09259                            values in chan_dahdi.conf for distinctive ring */
09260                         if (++receivedRingT == ARRAY_LEN(curRingData))
09261                            break;
09262                      } else if (i & DAHDI_IOMUX_READ) {
09263                         res = read(p->subs[idx].dfd, buf, sizeof(buf));
09264                         if (res < 0) {
09265                            if (errno != ELAST) {
09266                               ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
09267                               callerid_free(cs);
09268                               ast_hangup(chan);
09269                               goto quit;
09270                            }
09271                            break;
09272                         }
09273                      if (p->ringt)
09274                         p->ringt--;
09275                         if (p->ringt == 1) {
09276                            res = -1;
09277                            break;
09278                         }
09279                      }
09280                   }
09281                }
09282                if (p->usedistinctiveringdetection) {
09283                   /* this only shows up if you have n of the dring patterns filled in */
09284                   ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
09285 
09286                   for (counter = 0; counter < 3; counter++) {
09287                      /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this
09288                      channel */
09289                      /* this only shows up if you have n of the dring patterns filled in */
09290                      ast_verb(3, "Checking %d,%d,%d\n",
09291                            p->drings.ringnum[counter].ring[0],
09292                            p->drings.ringnum[counter].ring[1],
09293                            p->drings.ringnum[counter].ring[2]);
09294                      distMatches = 0;
09295                      for (counter1 = 0; counter1 < 3; counter1++) {
09296                         ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
09297                         if (p->drings.ringnum[counter].ring[counter1] == -1) {
09298                            ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
09299                            curRingData[counter1]);
09300                            distMatches++;
09301                         }
09302                         else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
09303                            curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
09304                            ast_verb(3, "Ring pattern matched in range: %d to %d\n",
09305                            (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
09306                            (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
09307                            distMatches++;
09308                         }
09309                      }
09310                      if (distMatches == 3) {
09311                         /* The ring matches, set the context to whatever is for distinctive ring.. */
09312                         ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context));
09313                         ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context));
09314                         ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
09315                         break;
09316                      }
09317                   }
09318                }
09319                /* Restore linear mode (if appropriate) for Caller*ID processing */
09320                dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09321 #if 1
09322                restore_gains(p);
09323 #endif
09324                if (res < 0) {
09325                   ast_log(LOG_WARNING, "CallerID returned with error on channel '%s'\n", chan->name);
09326                }
09327             } else
09328                ast_log(LOG_WARNING, "Unable to get caller ID space\n");
09329          }
09330       } else
09331          cs = NULL;
09332 
09333       if (number)
09334          ast_shrink_phone_number(number);
09335       ast_set_callerid(chan, number, name, number);
09336 
09337       if (smdi_msg)
09338          ASTOBJ_UNREF(smdi_msg, ast_smdi_md_message_destroy);
09339 
09340       if (cs)
09341          callerid_free(cs);
09342       /* If the CID had Message waiting payload, assume that this for MWI only and hangup the call */
09343       if (flags & CID_MSGWAITING) {
09344          ast_log(LOG_NOTICE, "MWI: Channel %d message waiting!\n", p->channel);
09345          notify_message(p->mailbox, 1);
09346          /* If generated using Ring Pulse Alert, then ring has been answered as a call and needs to be hungup */
09347          if (p->mwimonitor_rpas) {
09348             ast_hangup(chan);
09349             return NULL;
09350          }
09351       } else if (flags & CID_NOMSGWAITING) {
09352          ast_log(LOG_NOTICE, "MWI: Channel %d no message waiting!\n", p->channel);
09353          notify_message(p->mailbox, 0);
09354          /* If generated using Ring Pulse Alert, then ring has been answered as a call and needs to be hungup */
09355          if (p->mwimonitor_rpas) {
09356             ast_hangup(chan);
09357             return NULL;
09358          }
09359       }
09360 
09361       ast_setstate(chan, AST_STATE_RING);
09362       chan->rings = 1;
09363       p->ringt = p->ringt_base;
09364       res = ast_pbx_run(chan);
09365       if (res) {
09366          ast_hangup(chan);
09367          ast_log(LOG_WARNING, "PBX exited non-zero\n");
09368       }
09369       goto quit;
09370    default:
09371       ast_log(LOG_WARNING, "Don't know how to handle simple switch with signalling %s on channel %d\n", sig2str(p->sig), p->channel);
09372       res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
09373       if (res < 0)
09374             ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
09375    }
09376    res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
09377    if (res < 0)
09378          ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
09379    ast_hangup(chan);
09380 quit:
09381    ast_mutex_lock(&ss_thread_lock);
09382    ss_thread_count--;
09383    ast_cond_signal(&ss_thread_complete);
09384    ast_mutex_unlock(&ss_thread_lock);
09385    return NULL;
09386 }
09387 
09388 struct mwi_thread_data {
09389    struct dahdi_pvt *pvt;
09390    unsigned char buf[READ_SIZE];
09391    size_t len;
09392 };
09393 
09394 static int calc_energy(const unsigned char *buf, int len, int law)
09395 {
09396    int x;
09397    int sum = 0;
09398 
09399    if (!len)
09400       return 0;
09401 
09402    for (x = 0; x < len; x++)
09403       sum += abs(law == AST_FORMAT_ULAW ? AST_MULAW(buf[x]) : AST_ALAW(buf[x]));
09404 
09405    return sum / len;
09406 }
09407 
09408 static void *mwi_thread(void *data)
09409 {
09410    struct mwi_thread_data *mtd = data;
09411    struct callerid_state *cs;
09412    pthread_t threadid;
09413    int samples = 0;
09414    char *name, *number;
09415    int flags;
09416    int i, res;
09417    unsigned int spill_done = 0;
09418    int spill_result = -1;
09419 
09420    if (!(cs = callerid_new(mtd->pvt->cid_signalling))) {
09421       mtd->pvt->mwimonitoractive = 0;
09422 
09423       return NULL;
09424    }
09425 
09426    callerid_feed(cs, mtd->buf, mtd->len, AST_LAW(mtd->pvt));
09427 
09428    bump_gains(mtd->pvt);
09429 
09430    for (;;) {
09431       i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
09432       if ((res = ioctl(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_IOMUX, &i))) {
09433          ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
09434          goto quit;
09435       }
09436 
09437       if (i & DAHDI_IOMUX_SIGEVENT) {
09438          struct ast_channel *chan;
09439 
09440          /* If we get an event, screen out events that we do not act on.
09441           * Otherwise, cancel and go to the simple switch to let it deal with it.
09442           */
09443          res = dahdi_get_event(mtd->pvt->subs[SUB_REAL].dfd);
09444 
09445          switch (res) {
09446          case DAHDI_EVENT_NEONMWI_ACTIVE:
09447          case DAHDI_EVENT_NEONMWI_INACTIVE:
09448          case DAHDI_EVENT_NONE:
09449          case DAHDI_EVENT_BITSCHANGED:
09450             break;
09451          case DAHDI_EVENT_NOALARM:
09452             mtd->pvt->inalarm = 0;
09453             ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", mtd->pvt->channel);
09454             manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
09455                "Channel: %d\r\n", mtd->pvt->channel);
09456             break;
09457          case DAHDI_EVENT_ALARM:
09458             mtd->pvt->inalarm = 1;
09459             res = get_alarms(mtd->pvt);
09460             handle_alarms(mtd->pvt, res);
09461             break; /* What to do on channel alarm ???? -- fall thru intentionally?? */
09462          default:
09463             ast_log(LOG_NOTICE, "Got event %d (%s)...  Passing along to ss_thread\n", res, event2str(res));
09464             callerid_free(cs);
09465 
09466             restore_gains(mtd->pvt);
09467             mtd->pvt->ringt = mtd->pvt->ringt_base;
09468 
09469             if ((chan = dahdi_new(mtd->pvt, AST_STATE_RING, 0, SUB_REAL, 0, 0))) {
09470                if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
09471                   ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", mtd->pvt->channel);
09472                   res = tone_zone_play_tone(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
09473                   if (res < 0)
09474                      ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", mtd->pvt->channel);
09475                   ast_hangup(chan);
09476                   goto quit;
09477                }
09478                goto quit_no_clean;
09479 
09480             } else {
09481                ast_log(LOG_WARNING, "Could not create channel to handle call\n");
09482             }
09483          }
09484       } else if (i & DAHDI_IOMUX_READ) {
09485          if ((res = read(mtd->pvt->subs[SUB_REAL].dfd, mtd->buf, sizeof(mtd->buf))) < 0) {
09486             if (errno != ELAST) {
09487                ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
09488                goto quit;
09489             }
09490             break;
09491          }
09492          samples += res;
09493          if (!spill_done) {
09494             if ((spill_result = callerid_feed(cs, mtd->buf, res, AST_LAW(mtd->pvt))) < 0) {
09495                /*
09496                 * The previous diagnostic message output likely
09497                 * explains why it failed.
09498                 */
09499                ast_log(LOG_WARNING, "Failed to decode CallerID\n");
09500                break;
09501             } else if (spill_result) {
09502                spill_done = 1;
09503             }
09504          } else {
09505             /* keep reading data until the energy level drops below the threshold
09506                so we don't get another 'trigger' on the remaining carrier signal
09507             */
09508             if (calc_energy(mtd->buf, res, AST_LAW(mtd->pvt)) <= mwilevel)
09509                break;
09510          }
09511          if (samples > (8000 * 4)) /*Termination case - time to give up*/
09512             break;
09513       }
09514    }
09515 
09516    if (spill_result == 1) {
09517       callerid_get(cs, &name, &number, &flags);
09518       if (flags & CID_MSGWAITING) {
09519          ast_log(LOG_NOTICE, "mwi: Have Messages on channel %d\n", mtd->pvt->channel);
09520          notify_message(mtd->pvt->mailbox, 1);
09521       } else if (flags & CID_NOMSGWAITING) {
09522          ast_log(LOG_NOTICE, "mwi: No Messages on channel %d\n", mtd->pvt->channel);
09523          notify_message(mtd->pvt->mailbox, 0);
09524       } else {
09525          ast_log(LOG_NOTICE, "mwi: Status unknown on channel %d\n", mtd->pvt->channel);
09526       }
09527    }
09528 
09529 
09530 quit:
09531    callerid_free(cs);
09532 
09533    restore_gains(mtd->pvt);
09534 
09535 quit_no_clean:
09536    mtd->pvt->mwimonitoractive = 0;
09537 
09538    ast_free(mtd);
09539 
09540    return NULL;
09541 }
09542 
09543 /*
09544 * The following three functions (mwi_send_init, mwi_send_process_buffer,
09545 * mwi_send_process_event) work with the do_monitor thread to generate mwi spills
09546 * that are sent out via FXA port on voicemail state change.  The execution of
09547 * the mwi send is state driven and can either generate a ring pulse prior to
09548 * sending the fsk spill or simply send an fsk spill.
09549 */
09550 static int mwi_send_init(struct dahdi_pvt * pvt)
09551 {
09552    int x, res;
09553 
09554 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
09555    /* Determine how this spill is to be sent */
09556    if (pvt->mwisend_rpas) {
09557       pvt->mwisend_data.mwisend_current = MWI_SEND_SA;
09558       pvt->mwisendactive = 1;
09559    } else if (pvt->mwisend_fsk) {
09560       pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
09561       pvt->mwisendactive = 1;
09562    } else {
09563       pvt->mwisendactive = 0;
09564       return 0;
09565    }
09566 #else
09567    if (mwisend_rpas) {
09568       pvt->mwisend_data.mwisend_current = MWI_SEND_SA;
09569    } else {
09570       pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
09571    }
09572    pvt->mwisendactive = 1;
09573 #endif
09574 
09575    if (pvt->cidspill) {
09576       ast_log(LOG_WARNING, "cidspill already exists when trying to send FSK MWI\n");
09577       ast_free(pvt->cidspill);
09578       pvt->cidspill = NULL;
09579       pvt->cidpos = 0;
09580       pvt->cidlen = 0;
09581    }
09582    pvt->cidspill = ast_calloc(1, MAX_CALLERID_SIZE);
09583    if (!pvt->cidspill) {
09584       pvt->mwisendactive = 0;
09585       return -1;
09586    }
09587    x = DAHDI_FLUSH_BOTH;
09588    res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
09589    x = 3000;
09590    ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_ONHOOKTRANSFER, &x);
09591 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
09592    if (pvt->mwisend_fsk) {
09593 #endif
09594       pvt->cidlen = vmwi_generate(pvt->cidspill, has_voicemail(pvt), CID_MWI_TYPE_MDMF_FULL,
09595                         AST_LAW(pvt), pvt->cid_name, pvt->cid_num, 0);
09596       pvt->cidpos = 0;
09597 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
09598    }
09599 #endif
09600    return 0;
09601 }
09602 
09603 static int mwi_send_process_buffer(struct dahdi_pvt * pvt, int num_read)
09604 {
09605    struct timeval    now;
09606    int         res;
09607 
09608    /* sanity check to catch if this had been interrupted previously
09609    *  i.e. state says there is more to do but there is no spill allocated
09610    */
09611    if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current && !pvt->cidspill) {
09612       pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
09613    } else if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current) {
09614       /* Normal processing -- Perform mwi send action */
09615       switch ( pvt->mwisend_data.mwisend_current) {
09616       case MWI_SEND_SA:
09617          /* Send the Ring Pulse Signal Alert */
09618          res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &AS_RP_cadence);
09619          if (res) {
09620             ast_log(LOG_WARNING, "Unable to set RP-AS ring cadence: %s\n", strerror(errno));
09621             goto quit;
09622          }
09623          res = dahdi_set_hook(pvt->subs[SUB_REAL].dfd, DAHDI_RING);
09624          pvt->mwisend_data.mwisend_current = MWI_SEND_SA_WAIT;
09625          break;
09626       case MWI_SEND_SA_WAIT:  /* do nothing until I get RINGEROFF event */
09627          break;
09628       case MWI_SEND_PAUSE:  /* Wait between alert and spill - min of 500 mS*/
09629 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
09630          if (pvt->mwisend_fsk) {
09631 #endif
09632             gettimeofday(&now, NULL);
09633             if ((int)(now.tv_sec - pvt->mwisend_data.pause.tv_sec) * 1000000 + (int)now.tv_usec - (int)pvt->mwisend_data.pause.tv_usec > 500000) {
09634                pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
09635             }
09636 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
09637          } else { /* support for mwisendtype=nofsk */
09638             pvt->mwisend_data.mwisend_current = MWI_SEND_CLEANUP;
09639          }
09640 #endif
09641          break;
09642       case MWI_SEND_SPILL:
09643          /* We read some number of bytes.  Write an equal amount of data */
09644          if(0 < num_read) {
09645             if (num_read > pvt->cidlen - pvt->cidpos)
09646                num_read = pvt->cidlen - pvt->cidpos;
09647             res = write(pvt->subs[SUB_REAL].dfd, pvt->cidspill + pvt->cidpos, num_read);
09648             if (res > 0) {
09649                pvt->cidpos += res;
09650                if (pvt->cidpos >= pvt->cidlen) {
09651                   pvt->mwisend_data.mwisend_current = MWI_SEND_CLEANUP;
09652                }
09653             } else {
09654                ast_log(LOG_WARNING, "MWI FSK Send Write failed: %s\n", strerror(errno));
09655                goto quit;
09656             }
09657          }
09658          break;
09659       case MWI_SEND_CLEANUP:
09660          /* For now, do nothing */
09661          pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
09662          break;
09663       default:
09664          /* Should not get here, punt*/
09665          goto quit;
09666       }
09667    }
09668 
09669    if (MWI_SEND_DONE == pvt->mwisend_data.mwisend_current) {
09670       if (pvt->cidspill) {
09671          ast_free(pvt->cidspill);
09672          pvt->cidspill = NULL;
09673          pvt->cidpos = 0;
09674          pvt->cidlen = 0;
09675       }
09676       pvt->mwisendactive = 0;
09677    }
09678    return 0;
09679 quit:
09680    if (pvt->cidspill) {
09681       ast_free(pvt->cidspill);
09682       pvt->cidspill = NULL;
09683       pvt->cidpos = 0;
09684       pvt->cidlen = 0;
09685    }
09686    pvt->mwisendactive = 0;
09687    return -1;
09688 }
09689 
09690 static int mwi_send_process_event(struct dahdi_pvt * pvt, int event)
09691 {
09692    int handled = 0;
09693 
09694    if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current) {
09695       switch (event) {
09696       case DAHDI_EVENT_RINGEROFF:
09697          if(pvt->mwisend_data.mwisend_current == MWI_SEND_SA_WAIT) {
09698             handled = 1;
09699 
09700             if (dahdi_set_hook(pvt->subs[SUB_REAL].dfd, DAHDI_RINGOFF) ) {
09701                ast_log(LOG_WARNING, "Unable to finish RP-AS: %s mwi send aborted\n", strerror(errno));
09702                ast_free(pvt->cidspill);
09703                pvt->cidspill = NULL;
09704                pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
09705                pvt->mwisendactive = 0;
09706             } else {
09707                pvt->mwisend_data.mwisend_current = MWI_SEND_PAUSE;
09708                gettimeofday(&pvt->mwisend_data.pause, NULL);
09709             }
09710          }
09711          break;
09712       /* Going off hook, I need to punt this spill */
09713       case DAHDI_EVENT_RINGOFFHOOK:
09714          if (pvt->cidspill) {
09715             ast_free(pvt->cidspill);
09716             pvt->cidspill = NULL;
09717             pvt->cidpos = 0;
09718             pvt->cidlen = 0;
09719          }
09720          pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
09721          pvt->mwisendactive = 0;
09722          break;
09723       case DAHDI_EVENT_RINGERON:
09724       case DAHDI_EVENT_HOOKCOMPLETE:
09725          break;
09726       default:
09727          break;
09728       }
09729    }
09730    return handled;
09731 }
09732 
09733 /* destroy a DAHDI channel, identified by its number */
09734 static int dahdi_destroy_channel_bynum(int channel)
09735 {
09736    struct dahdi_pvt *tmp = NULL;
09737    struct dahdi_pvt *prev = NULL;
09738 
09739    tmp = iflist;
09740    while (tmp) {
09741       if (tmp->channel == channel) {
09742          int x = DAHDI_FLASH;
09743          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 */
09744          destroy_channel(prev, tmp, 1);
09745          ast_module_unref(ast_module_info->self);
09746          return RESULT_SUCCESS;
09747       }
09748       prev = tmp;
09749       tmp = tmp->next;
09750    }
09751    return RESULT_FAILURE;
09752 }
09753 
09754 static struct dahdi_pvt *handle_init_event(struct dahdi_pvt *i, int event)
09755 {
09756    int res;
09757    pthread_t threadid;
09758    struct ast_channel *chan;
09759 
09760    /* Handle an event on a given channel for the monitor thread. */
09761 
09762    switch (event) {
09763    case DAHDI_EVENT_NONE:
09764    case DAHDI_EVENT_BITSCHANGED:
09765       break;
09766    case DAHDI_EVENT_WINKFLASH:
09767    case DAHDI_EVENT_RINGOFFHOOK:
09768       if (i->inalarm) break;
09769       if (i->radio) break;
09770       /* Got a ring/answer.  What kind of channel are we? */
09771       switch (i->sig) {
09772       case SIG_FXOLS:
09773       case SIG_FXOGS:
09774       case SIG_FXOKS:
09775          res = dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
09776          i->fxsoffhookstate = 1;
09777          if (res && (errno == EBUSY))
09778             break;
09779 
09780          /* Cancel VMWI spill */
09781          ast_free(i->cidspill);
09782          i->cidspill = NULL;
09783          restore_conference(i);
09784 
09785          if (i->immediate) {
09786             dahdi_enable_ec(i);
09787             /* The channel is immediately up.  Start right away */
09788             res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
09789             chan = dahdi_new(i, AST_STATE_RING, 1, SUB_REAL, 0, 0);
09790             if (!chan) {
09791                ast_log(LOG_WARNING, "Unable to start PBX on channel %d\n", i->channel);
09792                res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
09793                if (res < 0)
09794                   ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
09795             }
09796          } else {
09797             /* Check for callerid, digits, etc */
09798             chan = dahdi_new(i, AST_STATE_RESERVED, 0, SUB_REAL, 0, 0);
09799             if (chan) {
09800                if (has_voicemail(i))
09801                   res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
09802                else
09803                   res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
09804                if (res < 0)
09805                   ast_log(LOG_WARNING, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i->channel);
09806                if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
09807                   ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
09808                   res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
09809                   if (res < 0)
09810                      ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
09811                   ast_hangup(chan);
09812                }
09813             } else
09814                ast_log(LOG_WARNING, "Unable to create channel\n");
09815          }
09816          break;
09817       case SIG_FXSLS:
09818       case SIG_FXSGS:
09819       case SIG_FXSKS:
09820             i->ringt = i->ringt_base;
09821             /* Fall through */
09822       case SIG_EMWINK:
09823       case SIG_FEATD:
09824       case SIG_FEATDMF:
09825       case SIG_FEATDMF_TA:
09826       case SIG_E911:
09827       case SIG_FGC_CAMA:
09828       case SIG_FGC_CAMAMF:
09829       case SIG_FEATB:
09830       case SIG_EM:
09831       case SIG_EM_E1:
09832       case SIG_SFWINK:
09833       case SIG_SF_FEATD:
09834       case SIG_SF_FEATDMF:
09835       case SIG_SF_FEATB:
09836       case SIG_SF:
09837          /* Check for callerid, digits, etc */
09838          if (i->cid_start == CID_START_POLARITY_IN) {
09839             chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, 0);
09840          } else {
09841             chan = dahdi_new(i, AST_STATE_RING, 0, SUB_REAL, 0, 0);
09842          }
09843 
09844          if (!chan) {
09845             ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
09846          } else if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
09847             ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
09848             res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
09849             if (res < 0) {
09850                ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
09851             }
09852             ast_hangup(chan);
09853          }
09854          break;
09855       default:
09856          ast_log(LOG_WARNING, "Don't know how to handle ring/answer with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
09857          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
09858          if (res < 0)
09859             ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
09860          return NULL;
09861       }
09862       break;
09863    case DAHDI_EVENT_NOALARM:
09864       i->inalarm = 0;
09865 #if defined(HAVE_PRI)
09866       i->resetting = 0;
09867 #endif   /* defined(HAVE_PRI) */
09868       ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", i->channel);
09869       manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
09870          "Channel: %d\r\n", i->channel);
09871       break;
09872    case DAHDI_EVENT_ALARM:
09873       i->inalarm = 1;
09874 #if defined(HAVE_PRI)
09875       i->resetting = 0;
09876 #endif   /* defined(HAVE_PRI) */
09877       res = get_alarms(i);
09878       handle_alarms(i, res);
09879       /* fall thru intentionally */
09880    case DAHDI_EVENT_ONHOOK:
09881       if (i->radio)
09882          break;
09883       /* Back on hook.  Hang up. */
09884       switch (i->sig) {
09885       case SIG_FXOLS:
09886       case SIG_FXOGS:
09887       case SIG_FEATD:
09888       case SIG_FEATDMF:
09889       case SIG_FEATDMF_TA:
09890       case SIG_E911:
09891       case SIG_FGC_CAMA:
09892       case SIG_FGC_CAMAMF:
09893       case SIG_FEATB:
09894       case SIG_EM:
09895       case SIG_EM_E1:
09896       case SIG_EMWINK:
09897       case SIG_SF_FEATD:
09898       case SIG_SF_FEATDMF:
09899       case SIG_SF_FEATB:
09900       case SIG_SF:
09901       case SIG_SFWINK:
09902       case SIG_FXSLS:
09903       case SIG_FXSGS:
09904       case SIG_FXSKS:
09905       case SIG_GR303FXSKS:
09906          dahdi_disable_ec(i);
09907          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
09908          dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
09909          break;
09910       case SIG_GR303FXOKS:
09911       case SIG_FXOKS:
09912          dahdi_disable_ec(i);
09913          /* Diddle the battery for the zhone */
09914 #ifdef ZHONE_HACK
09915          dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
09916          usleep(1);
09917 #endif
09918          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
09919          dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
09920          break;
09921       case SIG_PRI:
09922       case SIG_SS7:
09923       case SIG_BRI:
09924       case SIG_BRI_PTMP:
09925          dahdi_disable_ec(i);
09926          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
09927          break;
09928       default:
09929          ast_log(LOG_WARNING, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
09930          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
09931          return NULL;
09932       }
09933       if (i->sig & __DAHDI_SIG_FXO) {
09934          i->fxsoffhookstate = 0;
09935       }
09936       break;
09937    case DAHDI_EVENT_POLARITY:
09938       switch (i->sig) {
09939       case SIG_FXSLS:
09940       case SIG_FXSKS:
09941       case SIG_FXSGS:
09942          /* We have already got a PR before the channel was
09943             created, but it wasn't handled. We need polarity
09944             to be REV for remote hangup detection to work.
09945             At least in Spain */
09946          if (i->hanguponpolarityswitch)
09947             i->polarity = POLARITY_REV;
09948          if (i->cid_start == CID_START_POLARITY || i->cid_start == CID_START_POLARITY_IN) {
09949             i->polarity = POLARITY_REV;
09950             ast_verb(2, "Starting post polarity "
09951                "CID detection on channel %d\n",
09952                i->channel);
09953             chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, 0);
09954             if (!chan) {
09955                ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
09956             } else if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
09957                ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
09958             }
09959          }
09960          break;
09961       default:
09962          ast_log(LOG_WARNING, "handle_init_event detected "
09963             "polarity reversal on non-FXO (SIG_FXS) "
09964             "interface %d\n", i->channel);
09965       }
09966       break;
09967    case DAHDI_EVENT_REMOVED: /* destroy channel, will actually do so in do_monitor */
09968       ast_log(LOG_NOTICE,
09969             "Got DAHDI_EVENT_REMOVED. Destroying channel %d\n",
09970             i->channel);
09971       return i;
09972    case DAHDI_EVENT_NEONMWI_ACTIVE:
09973       if (i->mwimonitor_neon) {
09974          notify_message(i->mailbox, 1);
09975          ast_log(LOG_NOTICE, "NEON MWI set for channel %d, mailbox %s \n", i->channel, i->mailbox);
09976       }
09977       break;
09978    case DAHDI_EVENT_NEONMWI_INACTIVE:
09979       if (i->mwimonitor_neon) {
09980          notify_message(i->mailbox, 0);
09981          ast_log(LOG_NOTICE, "NEON MWI cleared for channel %d, mailbox %s\n", i->channel, i->mailbox);
09982       }
09983       break;
09984    }
09985    return NULL;
09986 }
09987 
09988 static void *do_monitor(void *data)
09989 {
09990    int count, res, res2, spoint, pollres=0;
09991    struct dahdi_pvt *i;
09992    struct dahdi_pvt *last = NULL;
09993    struct dahdi_pvt *doomed;
09994    time_t thispass = 0, lastpass = 0;
09995    int found;
09996    char buf[1024];
09997    struct pollfd *pfds=NULL;
09998    int lastalloc = -1;
09999    /* This thread monitors all the frame relay interfaces which are not yet in use
10000       (and thus do not have a separate thread) indefinitely */
10001    /* From here on out, we die whenever asked */
10002 #if 0
10003    if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) {
10004       ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n");
10005       return NULL;
10006    }
10007    ast_debug(1, "Monitor starting...\n");
10008 #endif
10009    pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
10010 
10011    for (;;) {
10012       /* Lock the interface list */
10013       ast_mutex_lock(&iflock);
10014       if (!pfds || (lastalloc != ifcount)) {
10015          if (pfds) {
10016             ast_free(pfds);
10017             pfds = NULL;
10018          }
10019          if (ifcount) {
10020             if (!(pfds = ast_calloc(1, ifcount * sizeof(*pfds)))) {
10021                ast_mutex_unlock(&iflock);
10022                return NULL;
10023             }
10024          }
10025          lastalloc = ifcount;
10026       }
10027       /* Build the stuff we're going to poll on, that is the socket of every
10028          dahdi_pvt that does not have an associated owner channel */
10029       count = 0;
10030       i = iflist;
10031       while (i) {
10032          if ((i->subs[SUB_REAL].dfd > -1) && i->sig && (!i->radio) && !(i->sig & SIG_MFCR2)) {
10033             if (!i->owner && !i->subs[SUB_REAL].owner && !i->mwimonitoractive ) {
10034                /* This needs to be watched, as it lacks an owner */
10035                pfds[count].fd = i->subs[SUB_REAL].dfd;
10036                pfds[count].events = POLLPRI;
10037                pfds[count].revents = 0;
10038                /* If we are monitoring for VMWI or sending CID, we need to
10039                   read from the channel as well */
10040                if (i->cidspill || i->mwisendactive || i->mwimonitor_fsk)
10041                   pfds[count].events |= POLLIN;
10042                count++;
10043             }
10044          }
10045          i = i->next;
10046       }
10047       /* Okay, now that we know what to do, release the interface lock */
10048       ast_mutex_unlock(&iflock);
10049 
10050       pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
10051       pthread_testcancel();
10052       /* Wait at least a second for something to happen */
10053       res = poll(pfds, count, 1000);
10054       pthread_testcancel();
10055       pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
10056 
10057       /* Okay, poll has finished.  Let's see what happened.  */
10058       if (res < 0) {
10059          if ((errno != EAGAIN) && (errno != EINTR))
10060             ast_log(LOG_WARNING, "poll return %d: %s\n", res, strerror(errno));
10061          continue;
10062       }
10063       /* Alright, lock the interface list again, and let's look and see what has
10064          happened */
10065       ast_mutex_lock(&iflock);
10066       found = 0;
10067       spoint = 0;
10068       lastpass = thispass;
10069       thispass = time(NULL);
10070       i = iflist;
10071       doomed = NULL;
10072       for (i = iflist;; i = i->next) {
10073          if (doomed) {
10074             int res;
10075             res = dahdi_destroy_channel_bynum(doomed->channel);
10076             if (!res) {
10077                ast_log(LOG_WARNING, "Couldn't find channel to destroy, hopefully another destroy operation just happened.\n");
10078             }
10079             doomed = NULL;
10080          }
10081          if (!i) {
10082             break;
10083          }
10084 
10085          if (thispass != lastpass) {
10086             if (!found && ((i == last) || ((i == iflist) && !last))) {
10087                last = i;
10088                if (last) {
10089                   /* Only allow MWI to be initiated on a quiescent fxs port */
10090                   if (!last->mwisendactive
10091                      && (last->sig & __DAHDI_SIG_FXO)
10092                      && !last->fxsoffhookstate
10093                      && !last->owner
10094                      && !ast_strlen_zero(last->mailbox)
10095                      && (thispass - last->onhooktime > 3)) {
10096                      res = has_voicemail(last);
10097                      if (last->msgstate != res) {
10098                         /* Set driver resources for signalling VMWI */
10099                         res2 = ioctl(last->subs[SUB_REAL].dfd, DAHDI_VMWI, &res);
10100                         if (res2) {
10101                            /* TODO: This message will ALWAYS be generated on some cards; any way to restrict it to those cards where it is interesting? */
10102                            ast_debug(3, "Unable to control message waiting led on channel %d: %s\n", last->channel, strerror(errno));
10103                         }
10104                         /* If enabled for FSK spill then initiate it */
10105                         if (mwi_send_init(last)) {
10106                            ast_log(LOG_WARNING, "Unable to initiate mwi send sequence on channel %d\n", last->channel);
10107                         }
10108                         last->msgstate = res;
10109                         found ++;
10110                      }
10111                   }
10112                   last = last->next;
10113                }
10114             }
10115          }
10116          if ((i->subs[SUB_REAL].dfd > -1) && i->sig) {
10117             if (i->radio && !i->owner)
10118             {
10119                res = dahdi_get_event(i->subs[SUB_REAL].dfd);
10120                if (res)
10121                {
10122                   ast_debug(1, "Monitor doohicky got event %s on radio channel %d\n", event2str(res), i->channel);
10123                   /* Don't hold iflock while handling init events */
10124                   ast_mutex_unlock(&iflock);
10125                   doomed = handle_init_event(i, res);
10126                   ast_mutex_lock(&iflock);
10127                }
10128                continue;
10129             }
10130             pollres = ast_fdisset(pfds, i->subs[SUB_REAL].dfd, count, &spoint);
10131             if (pollres & POLLIN) {
10132                if (i->owner || i->subs[SUB_REAL].owner) {
10133 #ifdef HAVE_PRI
10134                   if (!i->pri)
10135 #endif
10136                      ast_log(LOG_WARNING, "Whoa....  I'm owned but found (%d) in read...\n", i->subs[SUB_REAL].dfd);
10137                   continue;
10138                }
10139                if (!i->mwimonitor_fsk && !i->mwisendactive) {
10140                   ast_log(LOG_WARNING, "Whoa....  I'm not looking for MWI or sending MWI but am reading (%d)...\n", i->subs[SUB_REAL].dfd);
10141                   continue;
10142                }
10143                res = read(i->subs[SUB_REAL].dfd, buf, sizeof(buf));
10144                if (res > 0) {
10145                   if (i->mwimonitor_fsk) {
10146                      if (calc_energy((unsigned char *) buf, res, AST_LAW(i)) > mwilevel) {
10147                         pthread_attr_t attr;
10148                         pthread_t threadid;
10149                         struct mwi_thread_data *mtd;
10150 
10151                         pthread_attr_init(&attr);
10152                         pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
10153 
10154                         ast_log(LOG_DEBUG, "Maybe some MWI on port %d!\n", i->channel);
10155                         if ((mtd = ast_calloc(1, sizeof(*mtd)))) {
10156                            mtd->pvt = i;
10157                            memcpy(mtd->buf, buf, res);
10158                            mtd->len = res;
10159                            if (ast_pthread_create_background(&threadid, &attr, mwi_thread, mtd)) {
10160                               ast_log(LOG_WARNING, "Unable to start mwi thread on channel %d\n", i->channel);
10161                               ast_free(mtd);
10162                            }
10163                            i->mwimonitoractive = 1;
10164                         }
10165                      }
10166                   }
10167                   if (i->mwisendactive) {
10168                      mwi_send_process_buffer(i, res);
10169                   }
10170                } else {
10171                   ast_log(LOG_WARNING, "Read failed with %d: %s\n", res, strerror(errno));
10172                }
10173             }
10174             if (pollres & POLLPRI) {
10175                if (i->owner || i->subs[SUB_REAL].owner) {
10176 #ifdef HAVE_PRI
10177                   if (!i->pri)
10178 #endif
10179                      ast_log(LOG_WARNING, "Whoa....  I'm owned but found (%d)...\n", i->subs[SUB_REAL].dfd);
10180                   continue;
10181                }
10182                res = dahdi_get_event(i->subs[SUB_REAL].dfd);
10183                ast_debug(1, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel);
10184                /* Don't hold iflock while handling init events */
10185                ast_mutex_unlock(&iflock);
10186                if (0 == i->mwisendactive || 0 == mwi_send_process_event(i, res)) {
10187                   doomed = handle_init_event(i, res);
10188                }
10189                ast_mutex_lock(&iflock);
10190             }
10191          }
10192       }
10193       ast_mutex_unlock(&iflock);
10194    }
10195    /* Never reached */
10196    return NULL;
10197 
10198 }
10199 
10200 static int restart_monitor(void)
10201 {
10202    /* If we're supposed to be stopped -- stay stopped */
10203    if (monitor_thread == AST_PTHREADT_STOP)
10204       return 0;
10205    ast_mutex_lock(&monlock);
10206    if (monitor_thread == pthread_self()) {
10207       ast_mutex_unlock(&monlock);
10208       ast_log(LOG_WARNING, "Cannot kill myself\n");
10209       return -1;
10210    }
10211    if (monitor_thread != AST_PTHREADT_NULL) {
10212       /* Wake up the thread */
10213       pthread_kill(monitor_thread, SIGURG);
10214    } else {
10215       /* Start a new monitor */
10216       if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) {
10217          ast_mutex_unlock(&monlock);
10218          ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
10219          return -1;
10220       }
10221    }
10222    ast_mutex_unlock(&monlock);
10223    return 0;
10224 }
10225 
10226 #if defined(HAVE_PRI)
10227 static int pri_resolve_span(int *span, int channel, int offset, struct dahdi_spaninfo *si)
10228 {
10229    int x;
10230    int trunkgroup;
10231    /* Get appropriate trunk group if there is one */
10232    trunkgroup = pris[*span].mastertrunkgroup;
10233    if (trunkgroup) {
10234       /* Select a specific trunk group */
10235       for (x = 0; x < NUM_SPANS; x++) {
10236          if (pris[x].trunkgroup == trunkgroup) {
10237             *span = x;
10238             return 0;
10239          }
10240       }
10241       ast_log(LOG_WARNING, "Channel %d on span %d configured to use nonexistent trunk group %d\n", channel, *span, trunkgroup);
10242       *span = -1;
10243    } else {
10244       if (pris[*span].trunkgroup) {
10245          ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is trunk group %d (please use spanmap)\n", *span, pris[*span].trunkgroup);
10246          *span = -1;
10247       } else if (pris[*span].mastertrunkgroup) {
10248          ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is already part of trunk group %d\n", *span, pris[*span].mastertrunkgroup);
10249          *span = -1;
10250       } else {
10251          if (si->totalchans == 31) {
10252             /* E1 */
10253             pris[*span].dchannels[0] = 16 + offset;
10254          } else if (si->totalchans == 24) {
10255             /* T1 or J1 */
10256             pris[*span].dchannels[0] = 24 + offset;
10257          } else if (si->totalchans == 3) {
10258             /* BRI */
10259             pris[*span].dchannels[0] = 3 + offset;
10260          } else {
10261             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);
10262             *span = -1;
10263             return 0;
10264          }
10265          pris[*span].dchanavail[0] |= DCHAN_PROVISIONED;
10266          pris[*span].offset = offset;
10267          pris[*span].span = *span + 1;
10268       }
10269    }
10270    return 0;
10271 }
10272 #endif   /* defined(HAVE_PRI) */
10273 
10274 #if defined(HAVE_PRI)
10275 static int pri_create_trunkgroup(int trunkgroup, int *channels)
10276 {
10277    struct dahdi_spaninfo si;
10278    struct dahdi_params p;
10279    int fd;
10280    int span;
10281    int ospan=0;
10282    int x,y;
10283    for (x = 0; x < NUM_SPANS; x++) {
10284       if (pris[x].trunkgroup == trunkgroup) {
10285          ast_log(LOG_WARNING, "Trunk group %d already exists on span %d, Primary d-channel %d\n", trunkgroup, x + 1, pris[x].dchannels[0]);
10286          return -1;
10287       }
10288    }
10289    for (y = 0; y < NUM_DCHANS; y++) {
10290       if (!channels[y])
10291          break;
10292       memset(&si, 0, sizeof(si));
10293       memset(&p, 0, sizeof(p));
10294       fd = open("/dev/dahdi/channel", O_RDWR);
10295       if (fd < 0) {
10296          ast_log(LOG_WARNING, "Failed to open channel: %s\n", strerror(errno));
10297          return -1;
10298       }
10299       x = channels[y];
10300       if (ioctl(fd, DAHDI_SPECIFY, &x)) {
10301          ast_log(LOG_WARNING, "Failed to specify channel %d: %s\n", channels[y], strerror(errno));
10302          close(fd);
10303          return -1;
10304       }
10305       if (ioctl(fd, DAHDI_GET_PARAMS, &p)) {
10306          ast_log(LOG_WARNING, "Failed to get channel parameters for channel %d: %s\n", channels[y], strerror(errno));
10307          return -1;
10308       }
10309       if (ioctl(fd, DAHDI_SPANSTAT, &si)) {
10310          ast_log(LOG_WARNING, "Failed go get span information on channel %d (span %d): %s\n", channels[y], p.spanno, strerror(errno));
10311          close(fd);
10312          return -1;
10313       }
10314       span = p.spanno - 1;
10315       if (pris[span].trunkgroup) {
10316          ast_log(LOG_WARNING, "Span %d is already provisioned for trunk group %d\n", span + 1, pris[span].trunkgroup);
10317          close(fd);
10318          return -1;
10319       }
10320       if (pris[span].pvts[0]) {
10321          ast_log(LOG_WARNING, "Span %d is already provisioned with channels (implicit PRI maybe?)\n", span + 1);
10322          close(fd);
10323          return -1;
10324       }
10325       if (!y) {
10326          pris[span].trunkgroup = trunkgroup;
10327          pris[span].offset = channels[y] - p.chanpos;
10328          ospan = span;
10329       }
10330       pris[ospan].dchannels[y] = channels[y];
10331       pris[ospan].dchanavail[y] |= DCHAN_PROVISIONED;
10332       pris[span].span = span + 1;
10333       close(fd);
10334    }
10335    return 0;
10336 }
10337 #endif   /* defined(HAVE_PRI) */
10338 
10339 #if defined(HAVE_PRI)
10340 static int pri_create_spanmap(int span, int trunkgroup, int logicalspan)
10341 {
10342    if (pris[span].mastertrunkgroup) {
10343       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);
10344       return -1;
10345    }
10346    pris[span].mastertrunkgroup = trunkgroup;
10347    pris[span].prilogicalspan = logicalspan;
10348    return 0;
10349 }
10350 #endif   /* defined(HAVE_PRI) */
10351 
10352 #if defined(HAVE_SS7)
10353 static unsigned int parse_pointcode(const char *pcstring)
10354 {
10355    unsigned int code1, code2, code3;
10356    int numvals;
10357 
10358    numvals = sscanf(pcstring, "%30d-%30d-%30d", &code1, &code2, &code3);
10359    if (numvals == 1)
10360       return code1;
10361    if (numvals == 3)
10362       return (code1 << 16) | (code2 << 8) | code3;
10363 
10364    return 0;
10365 }
10366 #endif   /* defined(HAVE_SS7) */
10367 
10368 #if defined(HAVE_SS7)
10369 static struct dahdi_ss7 * ss7_resolve_linkset(int linkset)
10370 {
10371    if ((linkset < 0) || (linkset >= NUM_SPANS))
10372       return NULL;
10373    else
10374       return &linksets[linkset - 1];
10375 }
10376 #endif   /* defined(HAVE_SS7) */
10377 
10378 #ifdef HAVE_OPENR2
10379 static void dahdi_r2_destroy_links(void)
10380 {
10381    int i = 0;
10382    if (!r2links) {
10383       return;
10384    }
10385    for (; i < r2links_count; i++) {
10386       if (r2links[i]->r2master != AST_PTHREADT_NULL) {
10387          pthread_cancel(r2links[i]->r2master);
10388          pthread_join(r2links[i]->r2master, NULL);
10389          openr2_context_delete(r2links[i]->protocol_context);
10390       }
10391       ast_free(r2links[i]);
10392    }
10393    ast_free(r2links);
10394    r2links = NULL;
10395    r2links_count = 0;
10396 }
10397 
10398 #define R2_LINK_CAPACITY 10
10399 static struct dahdi_mfcr2 *dahdi_r2_get_link(void)
10400 {
10401    struct dahdi_mfcr2 *new_r2link = NULL;
10402    struct dahdi_mfcr2 **new_r2links = NULL;
10403    /* this function is called just when starting up and no monitor threads have been launched,
10404       no need to lock monitored_count member */
10405    if (!r2links_count || (r2links[r2links_count - 1]->monitored_count == R2_LINK_CAPACITY)) {
10406       new_r2link = ast_calloc(1, sizeof(**r2links));
10407       if (!new_r2link) {
10408          ast_log(LOG_ERROR, "Cannot allocate R2 link!\n");
10409          return NULL;
10410       }
10411       new_r2links = ast_realloc(r2links, ((r2links_count + 1) * sizeof(*r2links)));
10412       if (!new_r2links) {
10413          ast_log(LOG_ERROR, "Cannot allocate R2 link!\n");
10414          ast_free(new_r2link);
10415          return NULL;
10416       }
10417       r2links = new_r2links;
10418       new_r2link->r2master = AST_PTHREADT_NULL;
10419       r2links[r2links_count] = new_r2link;
10420       r2links_count++;
10421       ast_log(LOG_DEBUG, "Created new R2 link!\n");
10422    }
10423    return r2links[r2links_count - 1];
10424 }
10425 
10426 static int dahdi_r2_set_context(struct dahdi_mfcr2 *r2_link, const struct dahdi_chan_conf *conf)
10427 {
10428    char tmplogdir[] = "/tmp";
10429    char logdir[OR2_MAX_PATH];
10430    int threshold = 0;
10431    int snres = 0;
10432    r2_link->protocol_context = openr2_context_new(NULL, &dahdi_r2_event_iface,
10433          &dahdi_r2_transcode_iface, conf->mfcr2.variant, conf->mfcr2.max_ani,
10434          conf->mfcr2.max_dnis);
10435    if (!r2_link->protocol_context) {
10436       return -1;
10437    }
10438    openr2_context_set_log_level(r2_link->protocol_context, conf->mfcr2.loglevel);
10439    openr2_context_set_ani_first(r2_link->protocol_context, conf->mfcr2.get_ani_first);
10440 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
10441    openr2_context_set_skip_category_request(r2_link->protocol_context, conf->mfcr2.skip_category_request);
10442 #endif
10443    openr2_context_set_mf_threshold(r2_link->protocol_context, threshold);
10444    openr2_context_set_mf_back_timeout(r2_link->protocol_context, conf->mfcr2.mfback_timeout);
10445    openr2_context_set_metering_pulse_timeout(r2_link->protocol_context, conf->mfcr2.metering_pulse_timeout);
10446    openr2_context_set_double_answer(r2_link->protocol_context, conf->mfcr2.double_answer);
10447    openr2_context_set_immediate_accept(r2_link->protocol_context, conf->mfcr2.immediate_accept);
10448    if (ast_strlen_zero(conf->mfcr2.logdir)) {
10449       if (openr2_context_set_log_directory(r2_link->protocol_context, tmplogdir)) {
10450          ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir);
10451       }
10452    } else {
10453       snres = snprintf(logdir, sizeof(logdir), "%s/%s/%s", ast_config_AST_LOG_DIR, "mfcr2", conf->mfcr2.logdir);
10454       if (snres >= sizeof(logdir)) {
10455          ast_log(LOG_ERROR, "MFC/R2 logging directory truncated, using %s\n", tmplogdir);
10456          if (openr2_context_set_log_directory(r2_link->protocol_context, tmplogdir)) {
10457             ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir);
10458          }
10459       } else {
10460          if (openr2_context_set_log_directory(r2_link->protocol_context, logdir)) {
10461             ast_log(LOG_ERROR, "Failed setting MFC/R2 log directory %s\n", logdir);
10462          }
10463       }
10464    }
10465    if (!ast_strlen_zero(conf->mfcr2.r2proto_file)) {
10466       if (openr2_context_configure_from_advanced_file(r2_link->protocol_context, conf->mfcr2.r2proto_file)) {
10467          ast_log(LOG_ERROR, "Failed to configure r2context from advanced configuration file %s\n", conf->mfcr2.r2proto_file);
10468       }
10469    }
10470    r2_link->monitored_count = 0;
10471    return 0;
10472 }
10473 #endif
10474 
10475 /* converts a DAHDI sigtype to signalling as can be configured from
10476  * chan_dahdi.conf.
10477  * While both have basically the same values, this will later be the
10478  * place to add filters and sanity checks
10479  */
10480 static int sigtype_to_signalling(int sigtype)
10481 {
10482    return sigtype;
10483 }
10484 
10485 static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf, struct dahdi_pri *pri, int reloading)
10486 {
10487    /* Make a dahdi_pvt structure for this interface (or CRV if "pri" is specified) */
10488    struct dahdi_pvt *tmp = NULL, *tmp2, *prev = NULL;
10489    char fn[80];
10490    struct dahdi_bufferinfo bi;
10491 
10492    int res;
10493    int span = 0;
10494    int here = 0;
10495    int x;
10496    struct dahdi_pvt **wlist;
10497    struct dahdi_pvt **wend;
10498    struct dahdi_params p;
10499 
10500    wlist = &iflist;
10501    wend = &ifend;
10502 
10503 #ifdef HAVE_PRI
10504    if (pri) {
10505       wlist = &pri->crvs;
10506       wend = &pri->crvend;
10507    }
10508 #endif
10509 
10510    tmp2 = *wlist;
10511    prev = NULL;
10512 
10513    while (tmp2) {
10514       if (!tmp2->destroy) {
10515          if (tmp2->channel == channel) {
10516             tmp = tmp2;
10517             here = 1;
10518             break;
10519          }
10520          if (tmp2->channel > channel) {
10521             break;
10522          }
10523       }
10524       prev = tmp2;
10525       tmp2 = tmp2->next;
10526    }
10527 
10528    if (!here && reloading != 1) {
10529       if (!(tmp = ast_calloc(1, sizeof(*tmp)))) {
10530          if (tmp)
10531             free(tmp);
10532          return NULL;
10533       }
10534       ast_mutex_init(&tmp->lock);
10535       ifcount++;
10536       for (x = 0; x < 3; x++)
10537          tmp->subs[x].dfd = -1;
10538       tmp->channel = channel;
10539       tmp->priindication_oob = conf->chan.priindication_oob;
10540    }
10541 
10542    if (tmp) {
10543       int chan_sig = conf->chan.sig;
10544 
10545       /* If there are variables in tmp before it is updated to match the new config, clear them */
10546       if (reloading && tmp->vars) {
10547          ast_variables_destroy(tmp->vars);
10548          tmp->vars = NULL;
10549       }
10550 
10551       if (!here) {
10552          if ((channel != CHAN_PSEUDO) && !pri) {
10553             int count = 0;
10554             snprintf(fn, sizeof(fn), "%d", channel);
10555             /* Open non-blocking */
10556             tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
10557             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 */
10558                usleep(1);
10559                tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
10560                count++;
10561             }
10562             /* Allocate a DAHDI structure */
10563             if (tmp->subs[SUB_REAL].dfd < 0) {
10564                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);
10565                destroy_dahdi_pvt(&tmp);
10566                return NULL;
10567             }
10568             memset(&p, 0, sizeof(p));
10569             res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
10570             if (res < 0) {
10571                ast_log(LOG_ERROR, "Unable to get parameters: %s\n", strerror(errno));
10572                destroy_dahdi_pvt(&tmp);
10573                return NULL;
10574             }
10575             if (conf->is_sig_auto)
10576                chan_sig = sigtype_to_signalling(p.sigtype);
10577             if (p.sigtype != (chan_sig & 0x3ffff)) {
10578                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));
10579                destroy_dahdi_pvt(&tmp);
10580                return NULL;
10581             }
10582             tmp->law = p.curlaw;
10583             tmp->span = p.spanno;
10584             span = p.spanno - 1;
10585          } else {
10586             if (channel == CHAN_PSEUDO)
10587                chan_sig = 0;
10588             else if ((chan_sig != SIG_FXOKS) && (chan_sig != SIG_FXSKS)) {
10589                ast_log(LOG_ERROR, "CRV's must use FXO/FXS Kewl Start (fxo_ks/fxs_ks) signalling only.\n");
10590                return NULL;
10591             }
10592          }
10593          tmp->outsigmod = conf->chan.outsigmod;
10594 
10595 #ifdef HAVE_SS7
10596          if (chan_sig == SIG_SS7) {
10597             struct dahdi_ss7 *ss7;
10598             int clear = 0;
10599             if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &clear)) {
10600                ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
10601                destroy_dahdi_pvt(&tmp);
10602                return NULL;
10603             }
10604 
10605             ss7 = ss7_resolve_linkset(cur_linkset);
10606             if (!ss7) {
10607                ast_log(LOG_ERROR, "Unable to find linkset %d\n", cur_linkset);
10608                destroy_dahdi_pvt(&tmp);
10609                return NULL;
10610             }
10611             if (cur_cicbeginswith < 0) {
10612                ast_log(LOG_ERROR, "Need to set cicbeginswith for the channels!\n");
10613                destroy_dahdi_pvt(&tmp);
10614                return NULL;
10615             }
10616 
10617             tmp->cic = cur_cicbeginswith++;
10618 
10619             /* DB: Add CIC's DPC information */
10620             tmp->dpc = cur_defaultdpc;
10621 
10622             tmp->ss7 = ss7;
10623             tmp->ss7call = NULL;
10624             ss7->pvts[ss7->numchans++] = tmp;
10625 
10626             ast_copy_string(ss7->internationalprefix, conf->ss7.internationalprefix, sizeof(ss7->internationalprefix));
10627             ast_copy_string(ss7->nationalprefix, conf->ss7.nationalprefix, sizeof(ss7->nationalprefix));
10628             ast_copy_string(ss7->subscriberprefix, conf->ss7.subscriberprefix, sizeof(ss7->subscriberprefix));
10629             ast_copy_string(ss7->unknownprefix, conf->ss7.unknownprefix, sizeof(ss7->unknownprefix));
10630 
10631             ss7->called_nai = conf->ss7.called_nai;
10632             ss7->calling_nai = conf->ss7.calling_nai;
10633          }
10634 #endif
10635 #ifdef HAVE_OPENR2
10636          if (chan_sig == SIG_MFCR2 && reloading != 1) {
10637             struct dahdi_mfcr2 *r2_link;
10638             r2_link = dahdi_r2_get_link();
10639             if (!r2_link) {
10640                ast_log(LOG_WARNING, "Cannot get another R2 DAHDI context!\n");
10641                destroy_dahdi_pvt(&tmp);
10642                return NULL;
10643             }
10644             if (!r2_link->protocol_context && dahdi_r2_set_context(r2_link, conf)) {
10645                ast_log(LOG_ERROR, "Cannot create OpenR2 protocol context.\n");
10646                destroy_dahdi_pvt(&tmp);
10647                return NULL;
10648             }
10649             if (r2_link->numchans == (sizeof(r2_link->pvts)/sizeof(r2_link->pvts[0]))) {
10650                ast_log(LOG_ERROR, "Cannot add more channels to this link!\n");
10651                destroy_dahdi_pvt(&tmp);
10652                return NULL;
10653             }
10654             r2_link->pvts[r2_link->numchans++] = tmp;
10655             tmp->r2chan = openr2_chan_new_from_fd(r2_link->protocol_context,
10656                                         tmp->subs[SUB_REAL].dfd,
10657                                         NULL, NULL);
10658             if (!tmp->r2chan) {
10659                openr2_liberr_t err = openr2_context_get_last_error(r2_link->protocol_context);
10660                ast_log(LOG_ERROR, "Cannot create OpenR2 channel: %s\n", openr2_context_error_string(err));
10661                destroy_dahdi_pvt(&tmp);
10662                return NULL;
10663             }
10664             tmp->mfcr2 = r2_link;
10665             if (conf->mfcr2.call_files) {
10666                openr2_chan_enable_call_files(tmp->r2chan);
10667             }
10668             openr2_chan_set_client_data(tmp->r2chan, tmp);
10669             /* cast seems to be needed to get rid of the annoying warning regarding format attribute  */
10670             openr2_chan_set_logging_func(tmp->r2chan, (openr2_logging_func_t)dahdi_r2_on_chan_log);
10671             openr2_chan_set_log_level(tmp->r2chan, conf->mfcr2.loglevel);
10672             tmp->mfcr2_category = conf->mfcr2.category;
10673             tmp->mfcr2_charge_calls = conf->mfcr2.charge_calls;
10674             tmp->mfcr2_allow_collect_calls = conf->mfcr2.allow_collect_calls;
10675             tmp->mfcr2_forced_release = conf->mfcr2.forced_release;
10676             tmp->mfcr2_accept_on_offer = conf->mfcr2.accept_on_offer;
10677             tmp->mfcr2call = 0;
10678             tmp->mfcr2_dnis_index = 0;
10679             tmp->mfcr2_ani_index = 0;
10680             r2_link->monitored_count++;
10681          }
10682 #endif
10683 #ifdef HAVE_PRI
10684          if ((chan_sig == SIG_PRI) || (chan_sig == SIG_BRI) || (chan_sig == SIG_BRI_PTMP) || (chan_sig == SIG_GR303FXOKS) || (chan_sig == SIG_GR303FXSKS)) {
10685             int offset;
10686             int myswitchtype;
10687             int matchesdchan;
10688             int x,y;
10689             offset = 0;
10690             if (((chan_sig == SIG_PRI) || (chan_sig == SIG_BRI) || (chan_sig == SIG_BRI_PTMP))
10691                   && ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &offset)) {
10692                ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
10693                destroy_dahdi_pvt(&tmp);
10694                return NULL;
10695             }
10696             if (span >= NUM_SPANS) {
10697                ast_log(LOG_ERROR, "Channel %d does not lie on a span I know of (%d)\n", channel, span);
10698                destroy_dahdi_pvt(&tmp);
10699                return NULL;
10700             } else {
10701                struct dahdi_spaninfo si;
10702                si.spanno = 0;
10703                if (ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SPANSTAT,&si) == -1) {
10704                   ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno));
10705                   destroy_dahdi_pvt(&tmp);
10706                   return NULL;
10707                }
10708                /* Store the logical span first based upon the real span */
10709                tmp->logicalspan = pris[span].prilogicalspan;
10710                pri_resolve_span(&span, channel, (channel - p.chanpos), &si);
10711                if (span < 0) {
10712                   ast_log(LOG_WARNING, "Channel %d: Unable to find locate channel/trunk group!\n", channel);
10713                   destroy_dahdi_pvt(&tmp);
10714                   return NULL;
10715                }
10716                if ((chan_sig == SIG_PRI) ||
10717                      (chan_sig == SIG_BRI) ||
10718                      (chan_sig == SIG_BRI_PTMP))
10719                   myswitchtype = conf->pri.switchtype;
10720                else
10721                   myswitchtype = PRI_SWITCH_GR303_TMC;
10722                /* Make sure this isn't a d-channel */
10723                matchesdchan=0;
10724                for (x = 0; x < NUM_SPANS; x++) {
10725                   for (y = 0; y < NUM_DCHANS; y++) {
10726                      if (pris[x].dchannels[y] == tmp->channel) {
10727                         matchesdchan = 1;
10728                         break;
10729                      }
10730                   }
10731                }
10732                offset = p.chanpos;
10733                if (!matchesdchan) {
10734                   if (pris[span].nodetype && (pris[span].nodetype != conf->pri.nodetype)) {
10735                      ast_log(LOG_ERROR, "Span %d is already a %s node\n", span + 1, pri_node2str(pris[span].nodetype));
10736                      destroy_dahdi_pvt(&tmp);
10737                      return NULL;
10738                   }
10739                   if (pris[span].switchtype && (pris[span].switchtype != myswitchtype)) {
10740                      ast_log(LOG_ERROR, "Span %d is already a %s switch\n", span + 1, pri_switch2str(pris[span].switchtype));
10741                      destroy_dahdi_pvt(&tmp);
10742                      return NULL;
10743                   }
10744                   if ((pris[span].dialplan) && (pris[span].dialplan != conf->pri.dialplan)) {
10745                      ast_log(LOG_ERROR, "Span %d is already a %s dialing plan\n", span + 1, dialplan2str(pris[span].dialplan));
10746                      destroy_dahdi_pvt(&tmp);
10747                      return NULL;
10748                   }
10749                   if (!ast_strlen_zero(pris[span].idledial) && strcmp(pris[span].idledial, conf->pri.idledial)) {
10750                      ast_log(LOG_ERROR, "Span %d already has idledial '%s'.\n", span + 1, conf->pri.idledial);
10751                      destroy_dahdi_pvt(&tmp);
10752                      return NULL;
10753                   }
10754                   if (!ast_strlen_zero(pris[span].idleext) && strcmp(pris[span].idleext, conf->pri.idleext)) {
10755                      ast_log(LOG_ERROR, "Span %d already has idleext '%s'.\n", span + 1, conf->pri.idleext);
10756                      destroy_dahdi_pvt(&tmp);
10757                      return NULL;
10758                   }
10759                   if (pris[span].minunused && (pris[span].minunused != conf->pri.minunused)) {
10760                      ast_log(LOG_ERROR, "Span %d already has minunused of %d.\n", span + 1, conf->pri.minunused);
10761                      destroy_dahdi_pvt(&tmp);
10762                      return NULL;
10763                   }
10764                   if (pris[span].minidle && (pris[span].minidle != conf->pri.minidle)) {
10765                      ast_log(LOG_ERROR, "Span %d already has minidle of %d.\n", span + 1, conf->pri.minidle);
10766                      destroy_dahdi_pvt(&tmp);
10767                      return NULL;
10768                   }
10769                   if (pris[span].numchans >= MAX_CHANNELS) {
10770                      ast_log(LOG_ERROR, "Unable to add channel %d: Too many channels in trunk group %d!\n", channel,
10771                         pris[span].trunkgroup);
10772                      destroy_dahdi_pvt(&tmp);
10773                      return NULL;
10774                   }
10775 
10776                   pris[span].sig = chan_sig;
10777                   pris[span].nodetype = conf->pri.nodetype;
10778                   pris[span].switchtype = myswitchtype;
10779                   pris[span].nsf = conf->pri.nsf;
10780                   pris[span].dialplan = conf->pri.dialplan;
10781                   pris[span].localdialplan = conf->pri.localdialplan;
10782                   pris[span].pvts[pris[span].numchans++] = tmp;
10783                   pris[span].minunused = conf->pri.minunused;
10784                   pris[span].minidle = conf->pri.minidle;
10785                   pris[span].overlapdial = conf->pri.overlapdial;
10786                   pris[span].qsigchannelmapping = conf->pri.qsigchannelmapping;
10787                   pris[span].discardremoteholdretrieval = conf->pri.discardremoteholdretrieval;
10788 #ifdef HAVE_PRI_INBANDDISCONNECT
10789                   pris[span].inbanddisconnect = conf->pri.inbanddisconnect;
10790 #endif
10791                   pris[span].facilityenable = conf->pri.facilityenable;
10792                   ast_copy_string(pris[span].idledial, conf->pri.idledial, sizeof(pris[span].idledial));
10793                   ast_copy_string(pris[span].idleext, conf->pri.idleext, sizeof(pris[span].idleext));
10794                   ast_copy_string(pris[span].internationalprefix, conf->pri.internationalprefix, sizeof(pris[span].internationalprefix));
10795                   ast_copy_string(pris[span].nationalprefix, conf->pri.nationalprefix, sizeof(pris[span].nationalprefix));
10796                   ast_copy_string(pris[span].localprefix, conf->pri.localprefix, sizeof(pris[span].localprefix));
10797                   ast_copy_string(pris[span].privateprefix, conf->pri.privateprefix, sizeof(pris[span].privateprefix));
10798                   ast_copy_string(pris[span].unknownprefix, conf->pri.unknownprefix, sizeof(pris[span].unknownprefix));
10799                   pris[span].resetinterval = conf->pri.resetinterval;
10800 
10801                   tmp->pri = &pris[span];
10802                   tmp->prioffset = offset;
10803                   tmp->call = NULL;
10804 
10805                   tmp->priexclusive = conf->chan.priexclusive;
10806                } else {
10807                   ast_log(LOG_ERROR, "Channel %d is reserved for D-channel.\n", offset);
10808                   destroy_dahdi_pvt(&tmp);
10809                   return NULL;
10810                }
10811             }
10812          } else {
10813             tmp->prioffset = 0;
10814          }
10815 #endif
10816       } else {
10817          chan_sig = tmp->sig;
10818          if (tmp->subs[SUB_REAL].dfd > -1) {
10819             memset(&p, 0, sizeof(p));
10820             res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
10821          }
10822       }
10823       /* Adjust starttime on loopstart and kewlstart trunks to reasonable values */
10824       switch (chan_sig) {
10825       case SIG_FXSKS:
10826       case SIG_FXSLS:
10827       case SIG_EM:
10828       case SIG_EM_E1:
10829       case SIG_EMWINK:
10830       case SIG_FEATD:
10831       case SIG_FEATDMF:
10832       case SIG_FEATDMF_TA:
10833       case SIG_FEATB:
10834       case SIG_E911:
10835       case SIG_SF:
10836       case SIG_SFWINK:
10837       case SIG_FGC_CAMA:
10838       case SIG_FGC_CAMAMF:
10839       case SIG_SF_FEATD:
10840       case SIG_SF_FEATDMF:
10841       case SIG_SF_FEATB:
10842          p.starttime = 250;
10843          break;
10844       }
10845 
10846       if (tmp->radio) {
10847          /* XXX Waiting to hear back from Jim if these should be adjustable XXX */
10848          p.channo = channel;
10849          p.rxwinktime = 1;
10850          p.rxflashtime = 1;
10851          p.starttime = 1;
10852          p.debouncetime = 5;
10853       }
10854       if (!tmp->radio) {
10855          p.channo = channel;
10856          /* Override timing settings based on config file */
10857          if (conf->timing.prewinktime >= 0)
10858             p.prewinktime = conf->timing.prewinktime;
10859          if (conf->timing.preflashtime >= 0)
10860             p.preflashtime = conf->timing.preflashtime;
10861          if (conf->timing.winktime >= 0)
10862             p.winktime = conf->timing.winktime;
10863          if (conf->timing.flashtime >= 0)
10864             p.flashtime = conf->timing.flashtime;
10865          if (conf->timing.starttime >= 0)
10866             p.starttime = conf->timing.starttime;
10867          if (conf->timing.rxwinktime >= 0)
10868             p.rxwinktime = conf->timing.rxwinktime;
10869          if (conf->timing.rxflashtime >= 0)
10870             p.rxflashtime = conf->timing.rxflashtime;
10871          if (conf->timing.debouncetime >= 0)
10872             p.debouncetime = conf->timing.debouncetime;
10873       }
10874 
10875       /* dont set parms on a pseudo-channel (or CRV) */
10876       if (tmp->subs[SUB_REAL].dfd >= 0)
10877       {
10878          res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_PARAMS, &p);
10879          if (res < 0) {
10880             ast_log(LOG_ERROR, "Unable to set parameters: %s\n", strerror(errno));
10881             destroy_dahdi_pvt(&tmp);
10882             return NULL;
10883          }
10884       }
10885 #if 1
10886       if (!here && (tmp->subs[SUB_REAL].dfd > -1)) {
10887          memset(&bi, 0, sizeof(bi));
10888          res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
10889          if (!res) {
10890             bi.txbufpolicy = conf->chan.buf_policy;
10891             bi.rxbufpolicy = conf->chan.buf_policy;
10892             bi.numbufs = conf->chan.buf_no;
10893             res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
10894             if (res < 0) {
10895                ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", channel, strerror(errno));
10896             }
10897          } else {
10898             ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", channel, strerror(errno));
10899          }
10900          tmp->buf_policy = conf->chan.buf_policy;
10901          tmp->buf_no = conf->chan.buf_no;
10902          tmp->usefaxbuffers = conf->chan.usefaxbuffers;
10903          tmp->faxbuf_policy = conf->chan.faxbuf_policy;
10904          tmp->faxbuf_no = conf->chan.faxbuf_no;
10905          /* This is not as gnarly as it may first appear.  If the ioctl above failed, we'd be setting
10906           * tmp->bufsize to zero which would cause subsequent faxbuffer-related ioctl calls to fail.
10907           * The reason the ioctl call above failed should to be determined before worrying about the
10908           * faxbuffer-related ioctl calls */
10909          tmp->bufsize = bi.bufsize;
10910       }
10911 #endif
10912       tmp->immediate = conf->chan.immediate;
10913       tmp->transfertobusy = conf->chan.transfertobusy;
10914       if (chan_sig & __DAHDI_SIG_FXS) {
10915          tmp->mwimonitor_fsk = conf->chan.mwimonitor_fsk;
10916          tmp->mwimonitor_neon = conf->chan.mwimonitor_neon;
10917          tmp->mwimonitor_rpas = conf->chan.mwimonitor_rpas;
10918       }
10919       tmp->sig = chan_sig;
10920       tmp->ringt_base = ringt_base;
10921       tmp->firstradio = 0;
10922       if ((chan_sig == SIG_FXOKS) || (chan_sig == SIG_FXOLS) || (chan_sig == SIG_FXOGS))
10923          tmp->permcallwaiting = conf->chan.callwaiting;
10924       else
10925          tmp->permcallwaiting = 0;
10926       /* Flag to destroy the channel must be cleared on new mkif.  Part of changes for reload to work */
10927       tmp->destroy = 0;
10928       tmp->drings = conf->chan.drings;
10929 
10930       /* 10 is a nice default. */
10931       if (tmp->drings.ringnum[0].range == 0)
10932          tmp->drings.ringnum[0].range = 10;
10933       if (tmp->drings.ringnum[1].range == 0)
10934          tmp->drings.ringnum[1].range = 10;
10935       if (tmp->drings.ringnum[2].range == 0)
10936          tmp->drings.ringnum[2].range = 10;
10937 
10938       tmp->usedistinctiveringdetection = usedistinctiveringdetection;
10939       tmp->callwaitingcallerid = conf->chan.callwaitingcallerid;
10940       tmp->threewaycalling = conf->chan.threewaycalling;
10941       tmp->adsi = conf->chan.adsi;
10942       tmp->use_smdi = conf->chan.use_smdi;
10943       tmp->permhidecallerid = conf->chan.hidecallerid;
10944       tmp->hidecalleridname = conf->chan.hidecalleridname;
10945       tmp->callreturn = conf->chan.callreturn;
10946       tmp->echocancel = conf->chan.echocancel;
10947       tmp->echotraining = conf->chan.echotraining;
10948       tmp->pulse = conf->chan.pulse;
10949       if (tmp->echocancel.head.tap_length) {
10950          tmp->echocanbridged = conf->chan.echocanbridged;
10951       } else {
10952          if (conf->chan.echocanbridged)
10953             ast_log(LOG_NOTICE, "echocancelwhenbridged requires echocancel to be enabled; ignoring\n");
10954          tmp->echocanbridged = 0;
10955       }
10956       tmp->busydetect = conf->chan.busydetect;
10957       tmp->busycount = conf->chan.busycount;
10958       tmp->busy_tonelength = conf->chan.busy_tonelength;
10959       tmp->busy_quietlength = conf->chan.busy_quietlength;
10960       tmp->callprogress = conf->chan.callprogress;
10961       tmp->waitfordialtone = conf->chan.waitfordialtone;
10962       tmp->cancallforward = conf->chan.cancallforward;
10963       tmp->dtmfrelax = conf->chan.dtmfrelax;
10964       tmp->callwaiting = tmp->permcallwaiting;
10965       tmp->hidecallerid = tmp->permhidecallerid;
10966       tmp->channel = channel;
10967       tmp->stripmsd = conf->chan.stripmsd;
10968       tmp->use_callerid = conf->chan.use_callerid;
10969       tmp->cid_signalling = conf->chan.cid_signalling;
10970       tmp->cid_start = conf->chan.cid_start;
10971       tmp->dahditrcallerid = conf->chan.dahditrcallerid;
10972       tmp->restrictcid = conf->chan.restrictcid;
10973       tmp->use_callingpres = conf->chan.use_callingpres;
10974       if (tmp->usedistinctiveringdetection) {
10975          if (!tmp->use_callerid) {
10976             ast_log(LOG_NOTICE, "Distinctive Ring detect requires 'usecallerid' be on\n");
10977             tmp->use_callerid = 1;
10978          }
10979       }
10980 
10981       if (tmp->cid_signalling == CID_SIG_SMDI) {
10982          if (!tmp->use_smdi) {
10983             ast_log(LOG_WARNING, "SMDI callerid requires SMDI to be enabled, enabling...\n");
10984             tmp->use_smdi = 1;
10985          }
10986       }
10987       if (tmp->use_smdi) {
10988          tmp->smdi_iface = ast_smdi_interface_find(conf->smdi_port);
10989          if (!(tmp->smdi_iface)) {
10990             ast_log(LOG_ERROR, "Invalid SMDI port specfied, disabling SMDI support\n");
10991             tmp->use_smdi = 0;
10992          }
10993       }
10994 
10995       ast_copy_string(tmp->accountcode, conf->chan.accountcode, sizeof(tmp->accountcode));
10996       tmp->amaflags = conf->chan.amaflags;
10997       if (!here) {
10998          tmp->confno = -1;
10999          tmp->propconfno = -1;
11000       }
11001       tmp->canpark = conf->chan.canpark;
11002       tmp->transfer = conf->chan.transfer;
11003       ast_copy_string(tmp->defcontext,conf->chan.context,sizeof(tmp->defcontext));
11004       ast_copy_string(tmp->language, conf->chan.language, sizeof(tmp->language));
11005       ast_copy_string(tmp->mohinterpret, conf->chan.mohinterpret, sizeof(tmp->mohinterpret));
11006       ast_copy_string(tmp->mohsuggest, conf->chan.mohsuggest, sizeof(tmp->mohsuggest));
11007       ast_copy_string(tmp->context, conf->chan.context, sizeof(tmp->context));
11008       ast_copy_string(tmp->parkinglot, conf->chan.parkinglot, sizeof(tmp->parkinglot));
11009       tmp->cid_ton = 0;
11010       switch (tmp->sig) {
11011       case SIG_PRI:
11012       case SIG_BRI:
11013       case SIG_BRI_PTMP:
11014       case SIG_SS7:
11015       case SIG_MFCR2:
11016          tmp->cid_num[0] = '\0';
11017          tmp->cid_name[0] = '\0';
11018          break;
11019       default:
11020          ast_copy_string(tmp->cid_num, conf->chan.cid_num, sizeof(tmp->cid_num));
11021          ast_copy_string(tmp->cid_name, conf->chan.cid_name, sizeof(tmp->cid_name));
11022          break;
11023       }
11024       ast_copy_string(tmp->mailbox, conf->chan.mailbox, sizeof(tmp->mailbox));
11025       if (channel != CHAN_PSEUDO && !ast_strlen_zero(tmp->mailbox)) {
11026          char *mailbox, *context;
11027          mailbox = context = ast_strdupa(tmp->mailbox);
11028          strsep(&context, "@");
11029          if (ast_strlen_zero(context))
11030             context = "default";
11031          tmp->mwi_event_sub = ast_event_subscribe(AST_EVENT_MWI, mwi_event_cb, NULL,
11032             AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
11033             AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
11034             AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS,
11035             AST_EVENT_IE_END);
11036       }
11037       tmp->msgstate = -1;
11038 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11039       tmp->mwisend_setting = conf->chan.mwisend_setting;
11040       tmp->mwisend_fsk  = conf->chan.mwisend_fsk;
11041       tmp->mwisend_rpas = conf->chan.mwisend_rpas;
11042 #endif
11043       if (chan_sig & __DAHDI_SIG_FXO) {
11044          memset(&p, 0, sizeof(p));
11045          res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
11046          if (!res) {
11047             tmp->fxsoffhookstate = p.rxisoffhook;
11048          }
11049 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11050          res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_VMWI_CONFIG, &tmp->mwisend_setting);
11051 #endif
11052       }
11053       tmp->onhooktime = time(NULL);
11054       tmp->group = conf->chan.group;
11055       tmp->callgroup = conf->chan.callgroup;
11056       tmp->pickupgroup= conf->chan.pickupgroup;
11057       if (conf->chan.vars) {
11058          struct ast_variable *v, *tmpvar;
11059                    for (v = conf->chan.vars ; v ; v = v->next) {
11060                          if ((tmpvar = ast_variable_new(v->name, v->value, v->file))) {
11061                                   tmpvar->next = tmp->vars;
11062                                    tmp->vars = tmpvar;
11063                            }
11064                   }
11065       }
11066       tmp->cid_rxgain = conf->chan.cid_rxgain;
11067       tmp->rxgain = conf->chan.rxgain;
11068       tmp->txgain = conf->chan.txgain;
11069       tmp->tonezone = conf->chan.tonezone;
11070       if (tmp->subs[SUB_REAL].dfd > -1) {
11071          set_actual_gain(tmp->subs[SUB_REAL].dfd, 0, tmp->rxgain, tmp->txgain, tmp->law);
11072          if (tmp->dsp)
11073             ast_dsp_set_digitmode(tmp->dsp, DSP_DIGITMODE_DTMF | tmp->dtmfrelax);
11074          update_conf(tmp);
11075          if (!here) {
11076             if ((chan_sig != SIG_BRI) && (chan_sig != SIG_BRI_PTMP) && (chan_sig != SIG_PRI)
11077                 && (chan_sig != SIG_SS7) && (chan_sig != SIG_MFCR2))
11078                /* Hang it up to be sure it's good */
11079                dahdi_set_hook(tmp->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
11080          }
11081          ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SETTONEZONE,&tmp->tonezone);
11082 #ifdef HAVE_PRI
11083          /* the dchannel is down so put the channel in alarm */
11084          if (tmp->pri && !pri_is_up(tmp->pri)) {
11085             tmp->inalarm = 1;
11086             tmp->resetting = 0;
11087          }
11088 #endif
11089          if ((res = get_alarms(tmp)) != DAHDI_ALARM_NONE) {
11090             tmp->inalarm = 1;
11091 #if defined(HAVE_PRI)
11092             tmp->resetting = 0;
11093 #endif   /* defined(HAVE_PRI) */
11094             handle_alarms(tmp, res);
11095          }
11096       }
11097 
11098       tmp->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
11099       tmp->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
11100       tmp->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
11101       tmp->sendcalleridafter = conf->chan.sendcalleridafter;
11102       if (!here) {
11103          tmp->locallyblocked = tmp->remotelyblocked = 0;
11104          if ((chan_sig == SIG_PRI) || (chan_sig == SIG_BRI) || (chan_sig == SIG_BRI_PTMP) || (chan_sig == SIG_SS7))
11105             tmp->inservice = 0;
11106          else /* We default to in service on protocols that don't have a reset */
11107             tmp->inservice = 1;
11108       }
11109    }
11110    if (tmp && !here) {
11111       /* nothing on the iflist */
11112       if (!*wlist) {
11113          *wlist = tmp;
11114          tmp->prev = NULL;
11115          tmp->next = NULL;
11116          *wend = tmp;
11117       } else {
11118          /* at least one member on the iflist */
11119          struct dahdi_pvt *working = *wlist;
11120 
11121          /* check if we maybe have to put it on the begining */
11122          if (working->channel > tmp->channel) {
11123             tmp->next = *wlist;
11124             tmp->prev = NULL;
11125             (*wlist)->prev = tmp;
11126             *wlist = tmp;
11127          } else {
11128          /* go through all the members and put the member in the right place */
11129             while (working) {
11130                /* in the middle */
11131                if (working->next) {
11132                   if (working->channel < tmp->channel && working->next->channel > tmp->channel) {
11133                      tmp->next = working->next;
11134                      tmp->prev = working;
11135                      working->next->prev = tmp;
11136                      working->next = tmp;
11137                      break;
11138                   }
11139                } else {
11140                /* the last */
11141                   if (working->channel < tmp->channel) {
11142                      working->next = tmp;
11143                      tmp->next = NULL;
11144                      tmp->prev = working;
11145                      *wend = tmp;
11146                      break;
11147                   }
11148                }
11149                working = working->next;
11150             }
11151          }
11152       }
11153    }
11154    return tmp;
11155 }
11156 
11157 #if defined(HAVE_PRI)
11158 /*!
11159  * \internal
11160  * \brief Determine if a private channel structure is in use.
11161  * \since 1.8
11162  *
11163  * \param pvt Channel to determine if in use.
11164  *
11165  * \return TRUE if the channel is in use.
11166  */
11167 static int sig_pri_is_chan_in_use(struct dahdi_pvt *pvt)
11168 {
11169    return pvt->owner || pvt->call || pvt->allocated || pvt->resetting || pvt->inalarm;
11170 }
11171 #endif   /* defined(HAVE_PRI) */
11172 
11173 #if defined(HAVE_PRI)
11174 /*!
11175  * \internal
11176  * \brief Determine if a private channel structure is available.
11177  * \since 1.8
11178  *
11179  * \param pvt Channel to determine if available.
11180  *
11181  * \return TRUE if the channel is available.
11182  */
11183 static int sig_pri_is_chan_available(struct dahdi_pvt *pvt)
11184 {
11185    return !sig_pri_is_chan_in_use(pvt);
11186 }
11187 #endif   /* defined(HAVE_PRI) */
11188 
11189 #if defined(HAVE_PRI)
11190 /*!
11191  * \internal
11192  * \brief Simple check if the channel is available to use.
11193  * \since 1.8
11194  *
11195  * \param pvt Private channel control structure.
11196  *
11197  * \retval 0 Interface not available.
11198  * \retval 1 Interface is available.
11199  */
11200 static int sig_pri_available_check(struct dahdi_pvt *pvt)
11201 {
11202    /*
11203     * If interface is available for use
11204     * then the channel is available.
11205     */
11206    if (sig_pri_is_chan_available(pvt)) {
11207       return 1;
11208    }
11209    return 0;
11210 }
11211 #endif   /* defined(HAVE_PRI) */
11212 
11213 #if defined(HAVE_PRI)
11214 static int sig_pri_available(struct dahdi_pvt *pvt)
11215 {
11216    struct dahdi_pvt *p = pvt;
11217    struct dahdi_pri *pri;
11218 
11219    if (!p->pri) {
11220       /* Something is wrong here.  A PRI channel without the pri pointer? */
11221       return 0;
11222    }
11223    pri = p->pri;
11224 
11225    ast_mutex_lock(&pri->lock);
11226    if (sig_pri_available_check(p)) {
11227       p->allocated = 1;
11228       ast_mutex_unlock(&pri->lock);
11229       return 1;
11230    }
11231 
11232    ast_mutex_unlock(&pri->lock);
11233    return 0;
11234 }
11235 #endif   /* defined(HAVE_PRI) */
11236 
11237 static inline int available(struct dahdi_pvt *p, int channelmatch, ast_group_t groupmatch, int *busy, int *channelmatched, int *groupmatched)
11238 {
11239    int res;
11240    struct dahdi_params par;
11241 
11242    /* First, check group matching */
11243    if (groupmatch) {
11244       if ((p->group & groupmatch) != groupmatch)
11245          return 0;
11246       *groupmatched = 1;
11247    }
11248    /* Check to see if we have a channel match */
11249    if (channelmatch != -1) {
11250       if (p->channel != channelmatch)
11251          return 0;
11252       *channelmatched = 1;
11253    }
11254 
11255 #if defined(HAVE_PRI)
11256    switch (p->sig) {
11257    case SIG_PRI_LIB_HANDLE_CASES:
11258       return sig_pri_available(p);
11259    default:
11260       break;
11261    }
11262 #endif   /* defined(HAVE_PRI) */
11263 
11264    /* We're at least busy at this point */
11265    if (busy) {
11266       if ((p->sig == SIG_FXOKS) || (p->sig == SIG_FXOLS) || (p->sig == SIG_FXOGS))
11267          *busy = 1;
11268    }
11269    /* If do not disturb, definitely not */
11270    if (p->dnd)
11271       return 0;
11272    /* If guard time, definitely not */
11273    if (p->guardtime && (time(NULL) < p->guardtime))
11274       return 0;
11275 
11276    if (p->locallyblocked || p->remotelyblocked)
11277       return 0;
11278 
11279    /* If no owner definitely available */
11280    if (!p->owner) {
11281 #ifdef HAVE_PRI
11282       /* Trust PRI */
11283       if (p->pri) {
11284          /* Likely only GR-303 gets here. */
11285          return sig_pri_available(p);
11286       }
11287 #endif
11288 #ifdef HAVE_SS7
11289       /* Trust SS7 */
11290       if (p->ss7) {
11291          if (p->ss7call)
11292             return 0;
11293          else
11294             return 1;
11295       }
11296 #endif
11297 #ifdef HAVE_OPENR2
11298       /* Trust MFC/R2 */
11299       if (p->mfcr2) {
11300          if (p->mfcr2call)
11301             return 0;
11302          else
11303             return 1;
11304       }
11305 #endif
11306 
11307       /* Trust hook state */
11308       if (p->sig && !(p->radio || (p->oprmode < 0)))
11309       {
11310          /* Check hook state */
11311          if (p->subs[SUB_REAL].dfd > -1) {
11312             memset(&par, 0, sizeof(par));
11313             res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
11314          } else {
11315             /* Assume not off hook on CVRS */
11316             res = 0;
11317             par.rxisoffhook = 0;
11318          }
11319 
11320          if (res) {
11321             ast_log(LOG_WARNING, "Unable to check hook state on channel %d: %s\n", p->channel, strerror(errno));
11322          }
11323          else if ((p->sig != SIG_FXSKS) && (p->sig != SIG_FXSGS) && (p->sig != SIG_FXSLS)) {
11324             if (par.rxisoffhook) {
11325                ast_debug(1, "Channel %d off hook, can't use\n", p->channel);
11326                /* Not available when the other end is off hook */
11327                return 0;
11328             }
11329          }
11330 #ifdef DAHDI_CHECK_HOOKSTATE
11331          } else { /* FXO channel case (SIG_FXS--) */
11332             /* Channel bank (using CAS), "onhook" does not necessarily means out of service, so return 1 */
11333             if (par.rxbits > -1)
11334                return 1;
11335             /* TDM FXO card, "onhook" means out of service (no battery on the line) */
11336             if (par.rxisoffhook)
11337                return 1;
11338             else
11339                return 0;
11340 #endif
11341       }
11342 
11343       return 1;
11344    }
11345 
11346    /* If it's not an FXO, forget about call wait */
11347    if ((p->sig != SIG_FXOKS) && (p->sig != SIG_FXOLS) && (p->sig != SIG_FXOGS))
11348       return 0;
11349 
11350    if (!p->callwaiting) {
11351       /* If they don't have call waiting enabled, then for sure they're unavailable at this point */
11352       return 0;
11353    }
11354 
11355    if (p->subs[SUB_CALLWAIT].dfd > -1) {
11356       /* If there is already a call waiting call, then we can't take a second one */
11357       return 0;
11358    }
11359 
11360    if ((p->owner->_state != AST_STATE_UP) &&
11361       ((p->owner->_state != AST_STATE_RINGING) || p->outgoing)) {
11362       /* If the current call is not up, then don't allow the call */
11363       return 0;
11364    }
11365    if ((p->subs[SUB_THREEWAY].owner) && (!p->subs[SUB_THREEWAY].inthreeway)) {
11366       /* Can't take a call wait when the three way calling hasn't been merged yet. */
11367       return 0;
11368    }
11369    /* We're cool */
11370    return 1;
11371 }
11372 
11373 /* This function can *ONLY* be used for copying pseudo (CHAN_PSEUDO) private
11374    structures; it makes no attempt to safely copy regular channel private
11375    structures that might contain reference-counted object pointers and other
11376    scary bits
11377 */
11378 static struct dahdi_pvt *duplicate_pseudo(struct dahdi_pvt *src)
11379 {
11380    struct dahdi_pvt *p;
11381    struct dahdi_bufferinfo bi;
11382    int res;
11383 
11384    if ((p = ast_malloc(sizeof(*p)))) {
11385       memcpy(p, src, sizeof(struct dahdi_pvt));
11386       ast_mutex_init(&p->lock);
11387       p->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo");
11388       if (p->subs[SUB_REAL].dfd < 0) {
11389          ast_log(LOG_ERROR, "Unable to dup channel: %s\n", strerror(errno));
11390          destroy_dahdi_pvt(&p);
11391          return NULL;
11392       }
11393       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
11394       if (!res) {
11395          bi.txbufpolicy = src->buf_policy;
11396          bi.rxbufpolicy = src->buf_policy;
11397          bi.numbufs = src->buf_no;
11398          res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
11399          if (res < 0) {
11400             ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel: %s\n", strerror(errno));
11401          }
11402       } else
11403          ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel: %s\n", strerror(errno));
11404    }
11405    p->destroy = 1;
11406    p->next = iflist;
11407    p->prev = NULL;
11408    iflist = p;
11409    if (iflist->next)
11410       iflist->next->prev = p;
11411    return p;
11412 }
11413 
11414 #if defined(HAVE_PRI)
11415 /*!
11416  * \internal
11417  * \brief Find an empty B-channel interface to use.
11418  *
11419  * \param pri PRI span control structure.
11420  * \param backwards TRUE if the search starts from higher channels.
11421  *
11422  * \note Assumes the pri->lock is already obtained.
11423  *
11424  * \retval array-index into private pointer array on success.
11425  * \retval -1 on error.
11426  */
11427 static int pri_find_empty_chan(struct dahdi_pri *pri, int backwards)
11428 {
11429    int x;
11430    if (backwards)
11431       x = pri->numchans;
11432    else
11433       x = 0;
11434    for (;;) {
11435       if (backwards && (x < 0))
11436          break;
11437       if (!backwards && (x >= pri->numchans))
11438          break;
11439       if (pri->pvts[x]
11440          && sig_pri_is_chan_available(pri->pvts[x])) {
11441          ast_debug(1, "Found empty available channel %d/%d\n",
11442             pri->pvts[x]->logicalspan, pri->pvts[x]->prioffset);
11443          return x;
11444       }
11445       if (backwards)
11446          x--;
11447       else
11448          x++;
11449    }
11450    return -1;
11451 }
11452 #endif   /* defined(HAVE_PRI) */
11453 
11454 static struct ast_channel *dahdi_request(const char *type, int format, void *data, int *cause)
11455 {
11456    ast_group_t groupmatch = 0;
11457    int channelmatch = -1;
11458    int roundrobin = 0;
11459    int callwait = 0;
11460    int busy = 0;
11461    struct dahdi_pvt *p;
11462    struct ast_channel *tmp = NULL;
11463    char *dest=NULL;
11464    int x;
11465    char *s;
11466    char opt=0;
11467    int res=0, y=0;
11468    int backwards = 0;
11469 #ifdef HAVE_PRI
11470    int crv;
11471    int bearer = -1;
11472    int trunkgroup;
11473    struct dahdi_pri *pri=NULL;
11474 #endif
11475    struct dahdi_pvt *exitpvt, *start, *end;
11476    ast_mutex_t *lock;
11477    int channelmatched = 0;
11478    int groupmatched = 0;
11479 
11480    /*
11481     * data is ---v
11482     * Dial(DAHDI/pseudo[/extension])
11483     * Dial(DAHDI/<channel#>[c|r<cadance#>|d][/extension])
11484     * Dial(DAHDI/<trunk_group#>:<crv#>[c|r<cadance#>|d][/extension])
11485     * Dial(DAHDI/(g|G|r|R)<group#(0-63)>[c|r<cadance#>|d][/extension])
11486     *
11487     * g - channel group allocation search forward
11488     * G - channel group allocation search backward
11489     * r - channel group allocation round robin search forward
11490     * R - channel group allocation round robin search backward
11491     *
11492     * c - Wait for DTMF digit to confirm answer
11493     * r<cadance#> - Set distintive ring cadance number
11494     * d - Force bearer capability for ISDN/SS7 call to digital.
11495     */
11496 
11497    /* Assume we're locking the iflock */
11498    lock = &iflock;
11499    start = iflist;
11500    end = ifend;
11501    if (data) {
11502       dest = ast_strdupa((char *)data);
11503    } else {
11504       ast_log(LOG_WARNING, "Channel requested with no data\n");
11505       return NULL;
11506    }
11507    if (toupper(dest[0]) == 'G' || toupper(dest[0])=='R') {
11508       /* Retrieve the group number */
11509       char *stringp;
11510 
11511       stringp = dest + 1;
11512       s = strsep(&stringp, "/");
11513       if ((res = sscanf(s, "%30d%1c%30d", &x, &opt, &y)) < 1) {
11514          ast_log(LOG_WARNING, "Unable to determine group for data %s\n", (char *)data);
11515          return NULL;
11516       }
11517       groupmatch = ((ast_group_t) 1 << x);
11518       if (toupper(dest[0]) == 'G') {
11519          if (dest[0] == 'G') {
11520             backwards = 1;
11521             p = ifend;
11522          } else
11523             p = iflist;
11524       } else {
11525          if (dest[0] == 'R') {
11526             backwards = 1;
11527             p = round_robin[x]?round_robin[x]->prev:ifend;
11528             if (!p)
11529                p = ifend;
11530          } else {
11531             p = round_robin[x]?round_robin[x]->next:iflist;
11532             if (!p)
11533                p = iflist;
11534          }
11535          roundrobin = 1;
11536       }
11537    } else {
11538       char *stringp;
11539 
11540       stringp = dest;
11541       s = strsep(&stringp, "/");
11542       p = iflist;
11543       if (!strcasecmp(s, "pseudo")) {
11544          /* Special case for pseudo */
11545          x = CHAN_PSEUDO;
11546          channelmatch = x;
11547       }
11548 #ifdef HAVE_PRI
11549       else if ((res = sscanf(s, "%30d:%30d%1c%30d", &trunkgroup, &crv, &opt, &y)) > 1) {
11550          if ((trunkgroup < 1) || (crv < 1)) {
11551             ast_log(LOG_WARNING, "Unable to determine trunk group and CRV for data %s\n", (char *)data);
11552             return NULL;
11553          }
11554          res--;
11555          for (x = 0; x < NUM_SPANS; x++) {
11556             if (pris[x].trunkgroup == trunkgroup) {
11557                pri = pris + x;
11558                lock = &pri->lock;
11559                start = pri->crvs;
11560                end = pri->crvend;
11561                break;
11562             }
11563          }
11564          if (!pri) {
11565             ast_log(LOG_WARNING, "Unable to find trunk group %d\n", trunkgroup);
11566             return NULL;
11567          }
11568          channelmatch = crv;
11569          p = pris[x].crvs;
11570       }
11571 #endif
11572       else if ((res = sscanf(s, "%30d%1c%30d", &x, &opt, &y)) < 1) {
11573          ast_log(LOG_WARNING, "Unable to determine channel for data %s\n", (char *)data);
11574          return NULL;
11575       } else {
11576          channelmatch = x;
11577       }
11578    }
11579    /* Search for an unowned channel */
11580    ast_mutex_lock(lock);
11581    exitpvt = p;
11582    while (p && !tmp) {
11583       if (roundrobin)
11584          round_robin[x] = p;
11585 #if 0
11586       ast_verbose("name = %s, %d, %d, %llu\n",p->owner ? p->owner->name : "<none>", p->channel, channelmatch, groupmatch);
11587 #endif
11588 
11589       if (p && available(p, channelmatch, groupmatch, &busy, &channelmatched, &groupmatched)) {
11590          ast_debug(1, "Using channel %d\n", p->channel);
11591          if (p->inalarm)
11592             goto next;
11593 
11594          callwait = (p->owner != NULL);
11595 #ifdef HAVE_PRI
11596          if (pri && (p->subs[SUB_REAL].dfd < 0)) {
11597             if (p->sig != SIG_FXSKS) {
11598                /* Gotta find an actual channel to use for this
11599                   CRV if this isn't a callwait */
11600                bearer = pri_find_empty_chan(pri, 0);
11601                if (bearer < 0) {
11602                   ast_log(LOG_NOTICE, "Out of bearer channels on span %d for call to CRV %d:%d\n", pri->span, trunkgroup, crv);
11603                   p = NULL;
11604                   break;
11605                }
11606                pri_assign_bearer(p, pri, pri->pvts[bearer]);
11607             } else {
11608                if (alloc_sub(p, 0)) {
11609                   ast_log(LOG_NOTICE, "Failed to allocate place holder pseudo channel!\n");
11610                   p = NULL;
11611                   break;
11612                } else
11613                   ast_debug(1, "Allocated placeholder pseudo channel\n");
11614 
11615                p->pri = pri;
11616             }
11617          }
11618 #endif
11619 #ifdef HAVE_OPENR2
11620          if (p->mfcr2) {
11621             ast_mutex_lock(&p->lock);
11622             if (p->mfcr2call) {
11623                ast_mutex_unlock(&p->lock);
11624                ast_log(LOG_DEBUG, "Yay!, someone just beat us in the race for channel %d.\n", p->channel);
11625                goto next;
11626             }
11627             p->mfcr2call = 1;
11628             ast_mutex_unlock(&p->lock);
11629          }
11630 #endif
11631          if (p->channel == CHAN_PSEUDO) {
11632             p = duplicate_pseudo(p);
11633             if (!p) {
11634                break;
11635             }
11636          }
11637          if (p->owner) {
11638             if (alloc_sub(p, SUB_CALLWAIT)) {
11639                p = NULL;
11640                break;
11641             }
11642          }
11643 #if defined(HAVE_PRI)
11644          switch (p->sig) {
11645          case SIG_GR303FXOKS:
11646          case SIG_GR303FXSKS:
11647          case SIG_PRI_LIB_HANDLE_CASES:
11648             /*
11649              * We already have the B channel reserved for this call.  We
11650              * just need to make sure that dahdi_hangup() has completed
11651              * cleaning up before continuing.
11652              */
11653             ast_mutex_lock(&p->lock);
11654             ast_mutex_unlock(&p->lock);
11655             break;
11656          default:
11657             break;
11658          }
11659 #endif   /* defined(HAVE_PRI) */
11660          p->outgoing = 1;
11661          tmp = dahdi_new(p, AST_STATE_RESERVED, 0, p->owner ? SUB_CALLWAIT : SUB_REAL, 0, 0);
11662          if (!tmp) {
11663             p->outgoing = 0;
11664 #if defined(HAVE_PRI)
11665             /*
11666              * This should be the last thing to clear when we are done with
11667              * the channel.
11668              */
11669             p->allocated = 0;
11670 #endif   /* defined(HAVE_PRI) */
11671          }
11672 #ifdef HAVE_PRI
11673          if (p->bearer) {
11674             /* Log owner to bearer channel, too */
11675             p->bearer->owner = tmp;
11676          }
11677 #endif
11678          /* Make special notes */
11679          if (res > 1) {
11680             if (opt == 'c') {
11681                /* Confirm answer */
11682                p->confirmanswer = 1;
11683             } else if (opt == 'r') {
11684                /* Distinctive ring */
11685                if (res < 3)
11686                   ast_log(LOG_WARNING, "Distinctive ring missing identifier in '%s'\n", (char *)data);
11687                else
11688                   p->distinctivering = y;
11689             } else if (opt == 'd') {
11690                /* If this is an ISDN call, make it digital */
11691                p->digital = 1;
11692                if (tmp)
11693                   tmp->transfercapability = AST_TRANS_CAP_DIGITAL;
11694             } else {
11695                ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", opt, (char *)data);
11696             }
11697          }
11698          /* Note if the call is a call waiting call */
11699          if (tmp && callwait)
11700             tmp->cdrflags |= AST_CDR_CALLWAIT;
11701          break;
11702       }
11703 next:
11704       if (backwards) {
11705          p = p->prev;
11706          if (!p)
11707             p = end;
11708       } else {
11709          p = p->next;
11710          if (!p)
11711             p = start;
11712       }
11713       /* stop when you roll to the one that we started from */
11714       if (p == exitpvt)
11715          break;
11716    }
11717    ast_mutex_unlock(lock);
11718    restart_monitor();
11719    if (callwait)
11720       *cause = AST_CAUSE_BUSY;
11721    else if (!tmp) {
11722       if (channelmatched) {
11723          if (busy)
11724             *cause = AST_CAUSE_BUSY;
11725       } else if (groupmatched) {
11726          *cause = AST_CAUSE_CONGESTION;
11727       }
11728    }
11729 
11730    return tmp;
11731 }
11732 
11733 #if defined(HAVE_PRI) || defined(HAVE_SS7)
11734 static int dahdi_setlaw(int dfd, int law)
11735 {
11736    return ioctl(dfd, DAHDI_SETLAW, &law);
11737 }
11738 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
11739 
11740 #if defined(HAVE_SS7)
11741 static int ss7_find_cic(struct dahdi_ss7 *linkset, int cic, unsigned int dpc)
11742 {
11743    int i;
11744    int winner = -1;
11745    for (i = 0; i < linkset->numchans; i++) {
11746       if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && linkset->pvts[i]->cic == cic)) {
11747          winner = i;
11748          break;
11749       }
11750    }
11751    return winner;
11752 }
11753 #endif   /* defined(HAVE_SS7) */
11754 
11755 #if defined(HAVE_SS7)
11756 static void ss7_handle_cqm(struct dahdi_ss7 *linkset, int startcic, int endcic, unsigned int dpc)
11757 {
11758    unsigned char status[32];
11759    struct dahdi_pvt *p = NULL;
11760    int i, offset;
11761 
11762    for (i = 0; i < linkset->numchans; i++) {
11763       if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && ((linkset->pvts[i]->cic >= startcic) && (linkset->pvts[i]->cic <= endcic)))) {
11764          p = linkset->pvts[i];
11765          offset = p->cic - startcic;
11766          status[offset] = 0;
11767          if (p->locallyblocked)
11768             status[offset] |= (1 << 0) | (1 << 4);
11769          if (p->remotelyblocked)
11770             status[offset] |= (1 << 1) | (1 << 5);
11771          if (p->ss7call) {
11772             if (p->outgoing)
11773                status[offset] |= (1 << 3);
11774             else
11775                status[offset] |= (1 << 2);
11776          } else
11777             status[offset] |= 0x3 << 2;
11778       }
11779    }
11780 
11781    if (p)
11782       isup_cqr(linkset->ss7, startcic, endcic, dpc, status);
11783    else
11784       ast_log(LOG_WARNING, "Could not find any equipped circuits within CQM CICs\n");
11785 
11786 }
11787 #endif   /* defined(HAVE_SS7) */
11788 
11789 #if defined(HAVE_SS7)
11790 static inline void ss7_hangup_cics(struct dahdi_ss7 *linkset, int startcic, int endcic, unsigned int dpc)
11791 {
11792    int i;
11793 
11794    for (i = 0; i < linkset->numchans; i++) {
11795       if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && ((linkset->pvts[i]->cic >= startcic) && (linkset->pvts[i]->cic <= endcic)))) {
11796          ast_mutex_lock(&linkset->pvts[i]->lock);
11797          if (linkset->pvts[i]->owner)
11798             linkset->pvts[i]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11799          ast_mutex_unlock(&linkset->pvts[i]->lock);
11800       }
11801    }
11802 }
11803 #endif   /* defined(HAVE_SS7) */
11804 
11805 #if defined(HAVE_SS7)
11806 static inline void ss7_block_cics(struct dahdi_ss7 *linkset, int startcic, int endcic, unsigned int dpc, unsigned char state[], int block)
11807 {
11808    int i;
11809 
11810    for (i = 0; i < linkset->numchans; i++) {
11811       if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && ((linkset->pvts[i]->cic >= startcic) && (linkset->pvts[i]->cic <= endcic)))) {
11812          if (state) {
11813             if (state[i])
11814                linkset->pvts[i]->remotelyblocked = block;
11815          } else
11816             linkset->pvts[i]->remotelyblocked = block;
11817       }
11818    }
11819 }
11820 #endif   /* defined(HAVE_SS7) */
11821 
11822 #if defined(HAVE_SS7)
11823 static void ss7_inservice(struct dahdi_ss7 *linkset, int startcic, int endcic, unsigned int dpc)
11824 {
11825    int i;
11826 
11827    for (i = 0; i < linkset->numchans; i++) {
11828       if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && ((linkset->pvts[i]->cic >= startcic) && (linkset->pvts[i]->cic <= endcic))))
11829          linkset->pvts[i]->inservice = 1;
11830    }
11831 }
11832 #endif   /* defined(HAVE_SS7) */
11833 
11834 #if defined(HAVE_SS7)
11835 static void ss7_reset_linkset(struct dahdi_ss7 *linkset)
11836 {
11837    int i, startcic = -1, endcic, dpc;
11838 
11839    if (linkset->numchans <= 0)
11840       return;
11841 
11842    startcic = linkset->pvts[0]->cic;
11843    /* DB: CIC's DPC fix */
11844    dpc = linkset->pvts[0]->dpc;
11845 
11846    for (i = 0; i < linkset->numchans; i++) {
11847       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)) {
11848          continue;
11849       } else {
11850          endcic = linkset->pvts[i]->cic;
11851          ast_verbose("Resetting CICs %d to %d\n", startcic, endcic);
11852          isup_grs(linkset->ss7, startcic, endcic, dpc);
11853 
11854          /* DB: CIC's DPC fix */
11855          if (linkset->pvts[i+1]) {
11856             startcic = linkset->pvts[i+1]->cic;
11857             dpc = linkset->pvts[i+1]->dpc;
11858          }
11859       }
11860    }
11861 }
11862 #endif   /* defined(HAVE_SS7) */
11863 
11864 #if defined(HAVE_SS7)
11865 static void dahdi_loopback(struct dahdi_pvt *p, int enable)
11866 {
11867    if (p->loopedback != enable) {
11868       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_LOOPBACK, &enable)) {
11869          ast_log(LOG_WARNING, "Unable to set loopback on channel %d: %s\n", p->channel, strerror(errno));
11870          return;
11871       }
11872       p->loopedback = enable;
11873    }
11874 }
11875 #endif   /* defined(HAVE_SS7) */
11876 
11877 #if defined(HAVE_SS7)
11878 /* XXX: This function is assumed to be called with the private channel lock and linkset lock held */
11879 static void ss7_start_call(struct dahdi_pvt *p, struct dahdi_ss7 *linkset)
11880 {
11881    struct ss7 *ss7 = linkset->ss7;
11882    int res;
11883    int law = 1;
11884    struct ast_channel *c;
11885    char tmp[256];
11886 
11887    if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &law) == -1)
11888       ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, law, strerror(errno));
11889 
11890    if (linkset->type == SS7_ITU)
11891       law = DAHDI_LAW_ALAW;
11892    else
11893       law = DAHDI_LAW_MULAW;
11894 
11895    res = dahdi_setlaw(p->subs[SUB_REAL].dfd, law);
11896    if (res < 0)
11897       ast_log(LOG_WARNING, "Unable to set law on channel %d\n", p->channel);
11898 
11899    if (!(linkset->flags & LINKSET_FLAG_EXPLICITACM)) {
11900       p->call_level = DAHDI_CALL_LEVEL_PROCEEDING;
11901       isup_acm(ss7, p->ss7call);
11902    } else {
11903       p->call_level = DAHDI_CALL_LEVEL_SETUP;
11904    }
11905 
11906    ast_mutex_unlock(&linkset->lock);
11907    c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, law, 0);
11908    if (!c) {
11909       ast_log(LOG_WARNING, "Unable to start PBX on CIC %d\n", p->cic);
11910       /* Holding this lock is assumed entering the function */
11911       ast_mutex_lock(&linkset->lock);
11912       p->call_level = DAHDI_CALL_LEVEL_IDLE;
11913       return;
11914    } else
11915       ast_verb(3, "Accepting call to '%s' on CIC %d\n", p->exten, p->cic);
11916 
11917    dahdi_enable_ec(p);
11918 
11919    /* We only reference these variables in the context of the ss7_linkset function
11920     * when receiving either and IAM or a COT message.  Since they are only accessed
11921     * from this context, we should be safe to unlock around them */
11922 
11923    ast_mutex_unlock(&p->lock);
11924 
11925    if (!ast_strlen_zero(p->charge_number)) {
11926       pbx_builtin_setvar_helper(c, "SS7_CHARGE_NUMBER", p->charge_number);
11927       /* Clear this after we set it */
11928       p->charge_number[0] = 0;
11929    }
11930    if (!ast_strlen_zero(p->gen_add_number)) {
11931       pbx_builtin_setvar_helper(c, "SS7_GENERIC_ADDRESS", p->gen_add_number);
11932       /* Clear this after we set it */
11933       p->gen_add_number[0] = 0;
11934    }
11935    if (!ast_strlen_zero(p->jip_number)) {
11936       pbx_builtin_setvar_helper(c, "SS7_JIP", p->jip_number);
11937       /* Clear this after we set it */
11938       p->jip_number[0] = 0;
11939    }
11940    if (!ast_strlen_zero(p->gen_dig_number)) {
11941       pbx_builtin_setvar_helper(c, "SS7_GENERIC_DIGITS", p->gen_dig_number);
11942       /* Clear this after we set it */
11943       p->gen_dig_number[0] = 0;
11944    }
11945    if (!ast_strlen_zero(p->orig_called_num)) {
11946       pbx_builtin_setvar_helper(c, "SS7_ORIG_CALLED_NUM", p->orig_called_num);
11947       /* Clear this after we set it */
11948       p->orig_called_num[0] = 0;
11949    }
11950 
11951    snprintf(tmp, sizeof(tmp), "%d", p->gen_dig_type);
11952    pbx_builtin_setvar_helper(c, "SS7_GENERIC_DIGTYPE", tmp);
11953    /* Clear this after we set it */
11954    p->gen_dig_type = 0;
11955 
11956    snprintf(tmp, sizeof(tmp), "%d", p->gen_dig_scheme);
11957    pbx_builtin_setvar_helper(c, "SS7_GENERIC_DIGSCHEME", tmp);
11958    /* Clear this after we set it */
11959    p->gen_dig_scheme = 0;
11960 
11961    if (!ast_strlen_zero(p->lspi_ident)) {
11962       pbx_builtin_setvar_helper(c, "SS7_LSPI_IDENT", p->lspi_ident);
11963       /* Clear this after we set it */
11964       p->lspi_ident[0] = 0;
11965    }
11966 
11967    snprintf(tmp, sizeof(tmp), "%d", p->call_ref_ident);
11968    pbx_builtin_setvar_helper(c, "SS7_CALLREF_IDENT", tmp);
11969    /* Clear this after we set it */
11970    p->call_ref_ident = 0;
11971 
11972    snprintf(tmp, sizeof(tmp), "%d", p->call_ref_pc);
11973    pbx_builtin_setvar_helper(c, "SS7_CALLREF_PC", tmp);
11974    /* Clear this after we set it */
11975    p->call_ref_pc = 0;
11976 
11977    snprintf(tmp, sizeof(tmp), "%d", p->calling_party_cat);
11978    pbx_builtin_setvar_helper(c, "SS7_CALLING_PARTY_CATEGORY", tmp);
11979    /* Clear this after we set it */
11980    p->calling_party_cat = 0;
11981 
11982    if (!ast_strlen_zero(p->redirecting_num)) {
11983       pbx_builtin_setvar_helper(c, "SS7_REDIRECTING_NUMBER", p->redirecting_num);
11984       /* Clear this after we set it */
11985       p->redirecting_num[0] = 0;
11986    }
11987    if (!ast_strlen_zero(p->generic_name)) {
11988       pbx_builtin_setvar_helper(c, "SS7_GENERIC_NAME", p->generic_name);
11989       /* Clear this after we set it */
11990       p->generic_name[0] = 0;
11991    }
11992 
11993    ast_mutex_lock(&p->lock);
11994    ast_mutex_lock(&linkset->lock);
11995 }
11996 #endif   /* defined(HAVE_SS7) */
11997 
11998 #if defined(HAVE_SS7)
11999 static void ss7_apply_plan_to_number(char *buf, size_t size, const struct dahdi_ss7 *ss7, const char *number, const unsigned nai)
12000 {
12001    if (ast_strlen_zero(number)) { /* make sure a number exists so prefix isn't placed on an empty string */
12002       if (size) {
12003          *buf = '\0';
12004       }
12005       return;
12006    }
12007    switch (nai) {
12008    case SS7_NAI_INTERNATIONAL:
12009       snprintf(buf, size, "%s%s", ss7->internationalprefix, number);
12010       break;
12011    case SS7_NAI_NATIONAL:
12012       snprintf(buf, size, "%s%s", ss7->nationalprefix, number);
12013       break;
12014    case SS7_NAI_SUBSCRIBER:
12015       snprintf(buf, size, "%s%s", ss7->subscriberprefix, number);
12016       break;
12017    case SS7_NAI_UNKNOWN:
12018       snprintf(buf, size, "%s%s", ss7->unknownprefix, number);
12019       break;
12020    default:
12021       snprintf(buf, size, "%s", number);
12022       break;
12023    }
12024 }
12025 #endif   /* defined(HAVE_SS7) */
12026 
12027 #if defined(HAVE_SS7)
12028 static int ss7_pres_scr2cid_pres(char presentation_ind, char screening_ind)
12029 {
12030    return ((presentation_ind & 0x3) << 5) | (screening_ind & 0x3);
12031 }
12032 #endif   /* defined(HAVE_SS7) */
12033 
12034 #if defined(HAVE_SS7)
12035 static void *ss7_linkset(void *data)
12036 {
12037    int res, i;
12038    struct timeval *next = NULL, tv;
12039    struct dahdi_ss7 *linkset = (struct dahdi_ss7 *) data;
12040    struct ss7 *ss7 = linkset->ss7;
12041    ss7_event *e = NULL;
12042    struct dahdi_pvt *p;
12043    int chanpos;
12044    struct pollfd pollers[NUM_DCHANS];
12045    int cic;
12046    unsigned int dpc;
12047    int nextms = 0;
12048 
12049    ss7_start(ss7);
12050 
12051    while(1) {
12052       ast_mutex_lock(&linkset->lock);
12053       if ((next = ss7_schedule_next(ss7))) {
12054          tv = ast_tvnow();
12055          tv.tv_sec = next->tv_sec - tv.tv_sec;
12056          tv.tv_usec = next->tv_usec - tv.tv_usec;
12057          if (tv.tv_usec < 0) {
12058             tv.tv_usec += 1000000;
12059             tv.tv_sec -= 1;
12060          }
12061          if (tv.tv_sec < 0) {
12062             tv.tv_sec = 0;
12063             tv.tv_usec = 0;
12064          }
12065          nextms = tv.tv_sec * 1000;
12066          nextms += tv.tv_usec / 1000;
12067       }
12068       ast_mutex_unlock(&linkset->lock);
12069 
12070       for (i = 0; i < linkset->numsigchans; i++) {
12071          pollers[i].fd = linkset->fds[i];
12072          pollers[i].events = ss7_pollflags(ss7, linkset->fds[i]);
12073          pollers[i].revents = 0;
12074       }
12075 
12076       res = poll(pollers, linkset->numsigchans, nextms);
12077       if ((res < 0) && (errno != EINTR)) {
12078          ast_log(LOG_ERROR, "poll(%s)\n", strerror(errno));
12079       } else if (!res) {
12080          ast_mutex_lock(&linkset->lock);
12081          ss7_schedule_run(ss7);
12082          ast_mutex_unlock(&linkset->lock);
12083          continue;
12084       }
12085 
12086       ast_mutex_lock(&linkset->lock);
12087       for (i = 0; i < linkset->numsigchans; i++) {
12088          if (pollers[i].revents & POLLPRI) {
12089             int x;
12090             if (ioctl(pollers[i].fd, DAHDI_GETEVENT, &x)) {
12091                ast_log(LOG_ERROR, "Error in exception retrieval!\n");
12092             }
12093             switch (x) {
12094             case DAHDI_EVENT_OVERRUN:
12095                ast_debug(1, "Overrun detected!\n");
12096                break;
12097             case DAHDI_EVENT_BADFCS:
12098                ast_debug(1, "Bad FCS\n");
12099                break;
12100             case DAHDI_EVENT_ABORT:
12101                ast_debug(1, "HDLC Abort\n");
12102                break;
12103             case DAHDI_EVENT_ALARM:
12104                ast_log(LOG_ERROR, "Alarm on link!\n");
12105                linkset->linkstate[i] |= (LINKSTATE_DOWN | LINKSTATE_INALARM);
12106                linkset->linkstate[i] &= ~LINKSTATE_UP;
12107                ss7_link_alarm(ss7, pollers[i].fd);
12108                break;
12109             case DAHDI_EVENT_NOALARM:
12110                ast_log(LOG_ERROR, "Alarm cleared on link\n");
12111                linkset->linkstate[i] &= ~(LINKSTATE_INALARM | LINKSTATE_DOWN);
12112                linkset->linkstate[i] |= LINKSTATE_STARTING;
12113                ss7_link_noalarm(ss7, pollers[i].fd);
12114                break;
12115             default:
12116                ast_log(LOG_ERROR, "Got exception %d!\n", x);
12117                break;
12118             }
12119          }
12120 
12121          if (pollers[i].revents & POLLIN) {
12122             res = ss7_read(ss7, pollers[i].fd);
12123          }
12124 
12125          if (pollers[i].revents & POLLOUT) {
12126             res = ss7_write(ss7, pollers[i].fd);
12127             if (res < 0) {
12128                ast_debug(1, "Error in write %s\n", strerror(errno));
12129             }
12130          }
12131       }
12132 
12133       while ((e = ss7_check_event(ss7))) {
12134          switch (e->e) {
12135          case SS7_EVENT_UP:
12136             if (linkset->state != LINKSET_STATE_UP) {
12137                ast_verbose("--- SS7 Up ---\n");
12138                ss7_reset_linkset(linkset);
12139             }
12140             linkset->state = LINKSET_STATE_UP;
12141             break;
12142          case SS7_EVENT_DOWN:
12143             ast_verbose("--- SS7 Down ---\n");
12144             linkset->state = LINKSET_STATE_DOWN;
12145             for (i = 0; i < linkset->numchans; i++) {
12146                struct dahdi_pvt *p = linkset->pvts[i];
12147                if (p)
12148                   p->inalarm = 1;
12149             }
12150             break;
12151          case MTP2_LINK_UP:
12152             ast_verbose("MTP2 link up (SLC %d)\n", e->gen.data);
12153             break;
12154          case MTP2_LINK_DOWN:
12155             ast_log(LOG_WARNING, "MTP2 link down (SLC %d)\n", e->gen.data);
12156             break;
12157          case ISUP_EVENT_CPG:
12158             chanpos = ss7_find_cic(linkset, e->cpg.cic, e->cpg.opc);
12159             if (chanpos < 0) {
12160                ast_log(LOG_WARNING, "CPG on unconfigured CIC %d\n", e->cpg.cic);
12161                break;
12162             }
12163             p = linkset->pvts[chanpos];
12164             ast_mutex_lock(&p->lock);
12165             switch (e->cpg.event) {
12166             case CPG_EVENT_ALERTING:
12167                if (p->call_level < DAHDI_CALL_LEVEL_ALERTING) {
12168                   p->call_level = DAHDI_CALL_LEVEL_ALERTING;
12169                }
12170                p->subs[SUB_REAL].needringing = 1;
12171                break;
12172             case CPG_EVENT_PROGRESS:
12173             case CPG_EVENT_INBANDINFO:
12174                {
12175                   struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, };
12176                   ast_debug(1, "Queuing frame PROGRESS on CIC %d\n", p->cic);
12177                   dahdi_queue_frame(p, &f, linkset);
12178                   p->progress = 1;
12179                   p->dialing = 0;
12180                   if (p->dsp && p->dsp_features) {
12181                      ast_dsp_set_features(p->dsp, p->dsp_features);
12182                      p->dsp_features = 0;
12183                   }
12184                }
12185                break;
12186             default:
12187                ast_debug(1, "Do not handle CPG with event type 0x%x\n", e->cpg.event);
12188             }
12189 
12190             ast_mutex_unlock(&p->lock);
12191             break;
12192          case ISUP_EVENT_RSC:
12193             ast_verbose("Resetting CIC %d\n", e->rsc.cic);
12194             chanpos = ss7_find_cic(linkset, e->rsc.cic, e->rsc.opc);
12195             if (chanpos < 0) {
12196                ast_log(LOG_WARNING, "RSC on unconfigured CIC %d\n", e->rsc.cic);
12197                break;
12198             }
12199             p = linkset->pvts[chanpos];
12200             ast_mutex_lock(&p->lock);
12201             p->inservice = 1;
12202             p->remotelyblocked = 0;
12203             dpc = p->dpc;
12204             isup_set_call_dpc(e->rsc.call, dpc);
12205             if (p->ss7call)
12206                p->ss7call = NULL;
12207             if (p->owner)
12208                p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
12209             ast_mutex_unlock(&p->lock);
12210             isup_rlc(ss7, e->rsc.call);
12211             break;
12212          case ISUP_EVENT_GRS:
12213             ast_debug(1, "Got Reset for CICs %d to %d: Acknowledging\n", e->grs.startcic, e->grs.endcic);
12214             chanpos = ss7_find_cic(linkset, e->grs.startcic, e->grs.opc);
12215             if (chanpos < 0) {
12216                ast_log(LOG_WARNING, "GRS on unconfigured CIC %d\n", e->grs.startcic);
12217                break;
12218             }
12219             p = linkset->pvts[chanpos];
12220             isup_gra(ss7, e->grs.startcic, e->grs.endcic, e->grs.opc);
12221             ss7_block_cics(linkset, e->grs.startcic, e->grs.endcic, e->grs.opc, NULL, 0);
12222             ss7_hangup_cics(linkset, e->grs.startcic, e->grs.endcic, e->grs.opc);
12223             break;
12224          case ISUP_EVENT_CQM:
12225             ast_debug(1, "Got Circuit group query message from CICs %d to %d\n", e->cqm.startcic, e->cqm.endcic);
12226             ss7_handle_cqm(linkset, e->cqm.startcic, e->cqm.endcic, e->cqm.opc);
12227             break;
12228          case ISUP_EVENT_GRA:
12229             ast_verbose("Got reset acknowledgement from CIC %d to %d.\n", e->gra.startcic, e->gra.endcic);
12230             ss7_inservice(linkset, e->gra.startcic, e->gra.endcic, e->gra.opc);
12231             ss7_block_cics(linkset, e->gra.startcic, e->gra.endcic, e->gra.opc, e->gra.status, 1);
12232             break;
12233          case ISUP_EVENT_IAM:
12234             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);
12235             chanpos = ss7_find_cic(linkset, e->iam.cic, e->iam.opc);
12236             if (chanpos < 0) {
12237                ast_log(LOG_WARNING, "IAM on unconfigured CIC %d\n", e->iam.cic);
12238                isup_rel(ss7, e->iam.call, -1);
12239                break;
12240             }
12241             p = linkset->pvts[chanpos];
12242             ast_mutex_lock(&p->lock);
12243             if (p->owner) {
12244                if (p->ss7call == e->iam.call) {
12245                   ast_mutex_unlock(&p->lock);
12246                   ast_log(LOG_WARNING, "Duplicate IAM requested on CIC %d\n", e->iam.cic);
12247                   break;
12248                } else {
12249                   ast_mutex_unlock(&p->lock);
12250                   ast_log(LOG_WARNING, "Ring requested on CIC %d already in use!\n", e->iam.cic);
12251                   break;
12252                }
12253             }
12254 
12255             dpc = p->dpc;
12256             p->ss7call = e->iam.call;
12257             isup_set_call_dpc(p->ss7call, dpc);
12258 
12259             if ((p->use_callerid) && (!ast_strlen_zero(e->iam.calling_party_num))) {
12260                ss7_apply_plan_to_number(p->cid_num, sizeof(p->cid_num), linkset, e->iam.calling_party_num, e->iam.calling_nai);
12261                p->callingpres = ss7_pres_scr2cid_pres(e->iam.presentation_ind, e->iam.screening_ind);
12262             } else
12263                p->cid_num[0] = 0;
12264 
12265             if (p->immediate) {
12266                p->exten[0] = 's';
12267                p->exten[1] = '\0';
12268             } else if (!ast_strlen_zero(e->iam.called_party_num)) {
12269                char *st;
12270                ss7_apply_plan_to_number(p->exten, sizeof(p->exten), linkset, e->iam.called_party_num, e->iam.called_nai);
12271                st = strchr(p->exten, '#');
12272                if (st)
12273                   *st = '\0';
12274                } else
12275                   p->exten[0] = '\0';
12276 
12277             p->cid_ani[0] = '\0';
12278             if ((p->use_callerid) && (!ast_strlen_zero(e->iam.generic_name)))
12279                ast_copy_string(p->cid_name, e->iam.generic_name, sizeof(p->cid_name));
12280             else
12281                p->cid_name[0] = '\0';
12282 
12283             p->cid_ani2 = e->iam.oli_ani2;
12284             p->cid_ton = 0;
12285             ast_copy_string(p->charge_number, e->iam.charge_number, sizeof(p->charge_number));
12286             ast_copy_string(p->gen_add_number, e->iam.gen_add_number, sizeof(p->gen_add_number));
12287             p->gen_add_type = e->iam.gen_add_type;
12288             p->gen_add_nai = e->iam.gen_add_nai;
12289             p->gen_add_pres_ind = e->iam.gen_add_pres_ind;
12290             p->gen_add_num_plan = e->iam.gen_add_num_plan;
12291             ast_copy_string(p->gen_dig_number, e->iam.gen_dig_number, sizeof(p->gen_dig_number));
12292             p->gen_dig_type = e->iam.gen_dig_type;
12293             p->gen_dig_scheme = e->iam.gen_dig_scheme;
12294             ast_copy_string(p->jip_number, e->iam.jip_number, sizeof(p->jip_number));
12295             ast_copy_string(p->orig_called_num, e->iam.orig_called_num, sizeof(p->orig_called_num));
12296             ast_copy_string(p->redirecting_num, e->iam.redirecting_num, sizeof(p->redirecting_num));
12297             ast_copy_string(p->generic_name, e->iam.generic_name, sizeof(p->generic_name));
12298             p->calling_party_cat = e->iam.calling_party_cat;
12299 
12300             /* Set DNID */
12301             if (!ast_strlen_zero(e->iam.called_party_num))
12302                ss7_apply_plan_to_number(p->dnid, sizeof(p->dnid), linkset, e->iam.called_party_num, e->iam.called_nai);
12303 
12304             if (ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
12305 
12306                if (e->iam.cot_check_required) {
12307                   dahdi_loopback(p, 1);
12308                } else
12309                   ss7_start_call(p, linkset);
12310             } else {
12311                ast_debug(1, "Call on CIC for unconfigured extension %s\n", p->exten);
12312                p->alreadyhungup = 1;
12313                isup_rel(ss7, e->iam.call, AST_CAUSE_UNALLOCATED);
12314             }
12315             ast_mutex_unlock(&p->lock);
12316             break;
12317          case ISUP_EVENT_COT:
12318             chanpos = ss7_find_cic(linkset, e->cot.cic, e->cot.opc);
12319             if (chanpos < 0) {
12320                ast_log(LOG_WARNING, "COT on unconfigured CIC %d\n", e->cot.cic);
12321                isup_rel(ss7, e->cot.call, -1);
12322                break;
12323             }
12324             p = linkset->pvts[chanpos];
12325 
12326             ast_mutex_lock(&p->lock);
12327 
12328             if (p->loopedback) {
12329                dahdi_loopback(p, 0);
12330                ss7_start_call(p, linkset);
12331             }
12332 
12333             ast_mutex_unlock(&p->lock);
12334 
12335             break;
12336          case ISUP_EVENT_CCR:
12337             ast_debug(1, "Got CCR request on CIC %d\n", e->ccr.cic);
12338             chanpos = ss7_find_cic(linkset, e->ccr.cic, e->ccr.opc);
12339             if (chanpos < 0) {
12340                ast_log(LOG_WARNING, "CCR on unconfigured CIC %d\n", e->ccr.cic);
12341                break;
12342             }
12343 
12344             p = linkset->pvts[chanpos];
12345 
12346             ast_mutex_lock(&p->lock);
12347             dahdi_loopback(p, 1);
12348             ast_mutex_unlock(&p->lock);
12349 
12350             isup_lpa(linkset->ss7, e->ccr.cic, p->dpc);
12351             break;
12352          case ISUP_EVENT_CVT:
12353             ast_debug(1, "Got CVT request on CIC %d\n", e->cvt.cic);
12354             chanpos = ss7_find_cic(linkset, e->cvt.cic, e->cvt.opc);
12355             if (chanpos < 0) {
12356                ast_log(LOG_WARNING, "CVT on unconfigured CIC %d\n", e->cvt.cic);
12357                break;
12358             }
12359 
12360             p = linkset->pvts[chanpos];
12361 
12362             ast_mutex_lock(&p->lock);
12363             dahdi_loopback(p, 1);
12364             ast_mutex_unlock(&p->lock);
12365 
12366             isup_cvr(linkset->ss7, e->cvt.cic, p->dpc);
12367             break;
12368          case ISUP_EVENT_REL:
12369             chanpos = ss7_find_cic(linkset, e->rel.cic, e->rel.opc);
12370             if (chanpos < 0) {
12371                ast_log(LOG_WARNING, "REL on unconfigured CIC %d\n", e->rel.cic);
12372                break;
12373             }
12374             p = linkset->pvts[chanpos];
12375             ast_mutex_lock(&p->lock);
12376             if (p->owner) {
12377                p->owner->hangupcause = e->rel.cause;
12378                p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
12379             } else if (!p->restartpending)
12380                ast_log(LOG_WARNING, "REL on channel (CIC %d) without owner!\n", p->cic);
12381 
12382             /* End the loopback if we have one */
12383             dahdi_loopback(p, 0);
12384 
12385             isup_rlc(ss7, e->rel.call);
12386             p->ss7call = NULL;
12387 
12388             ast_mutex_unlock(&p->lock);
12389             break;
12390          case ISUP_EVENT_ACM:
12391             chanpos = ss7_find_cic(linkset, e->acm.cic, e->acm.opc);
12392             if (chanpos < 0) {
12393                ast_log(LOG_WARNING, "ACM on unconfigured CIC %d\n", e->acm.cic);
12394                isup_rel(ss7, e->acm.call, -1);
12395                break;
12396             } else {
12397                struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROCEEDING, };
12398 
12399                p = linkset->pvts[chanpos];
12400 
12401                ast_debug(1, "Queueing frame from SS7_EVENT_ACM on CIC %d\n", p->cic);
12402 
12403                if (e->acm.call_ref_ident > 0) {
12404                   p->rlt = 1; /* Setting it but not using it here*/
12405                }
12406 
12407                ast_mutex_lock(&p->lock);
12408                dahdi_queue_frame(p, &f, linkset);
12409                if (p->call_level < DAHDI_CALL_LEVEL_PROCEEDING) {
12410                   p->call_level = DAHDI_CALL_LEVEL_PROCEEDING;
12411                }
12412                p->dialing = 0;
12413                /* Send alerting if subscriber is free */
12414                if (e->acm.called_party_status_ind == 1) {
12415                   if (p->call_level < DAHDI_CALL_LEVEL_ALERTING) {
12416                      p->call_level = DAHDI_CALL_LEVEL_ALERTING;
12417                   }
12418                   p->subs[SUB_REAL].needringing = 1;
12419                }
12420                ast_mutex_unlock(&p->lock);
12421             }
12422             break;
12423          case ISUP_EVENT_CGB:
12424             chanpos = ss7_find_cic(linkset, e->cgb.startcic, e->cgb.opc);
12425             if (chanpos < 0) {
12426                ast_log(LOG_WARNING, "CGB on unconfigured CIC %d\n", e->cgb.startcic);
12427                break;
12428             }
12429             p = linkset->pvts[chanpos];
12430             ss7_block_cics(linkset, e->cgb.startcic, e->cgb.endcic, e->cgb.opc, e->cgb.status, 1);
12431             isup_cgba(linkset->ss7, e->cgb.startcic, e->cgb.endcic, e->cgb.opc, e->cgb.status, e->cgb.type);
12432             break;
12433          case ISUP_EVENT_CGU:
12434             chanpos = ss7_find_cic(linkset, e->cgu.startcic, e->cgu.opc);
12435             if (chanpos < 0) {
12436                ast_log(LOG_WARNING, "CGU on unconfigured CIC %d\n", e->cgu.startcic);
12437                break;
12438             }
12439             p = linkset->pvts[chanpos];
12440             ss7_block_cics(linkset, e->cgu.startcic, e->cgu.endcic, e->cgu.opc, e->cgu.status, 0);
12441             isup_cgua(linkset->ss7, e->cgu.startcic, e->cgu.endcic, e->cgu.opc, e->cgu.status, e->cgu.type);
12442             break;
12443          case ISUP_EVENT_UCIC:
12444             chanpos = ss7_find_cic(linkset, e->ucic.cic, e->ucic.opc);
12445             if (chanpos < 0) {
12446                ast_log(LOG_WARNING, "UCIC on unconfigured CIC %d\n", e->ucic.cic);
12447                break;
12448             }
12449             p = linkset->pvts[chanpos];
12450             ast_debug(1, "Unequiped Circuit Id Code on CIC %d\n", e->ucic.cic);
12451             ast_mutex_lock(&p->lock);
12452             p->remotelyblocked = 1;
12453             p->inservice = 0;
12454             ast_mutex_unlock(&p->lock);         //doesn't require a SS7 acknowledgement
12455             break;
12456          case ISUP_EVENT_BLO:
12457             chanpos = ss7_find_cic(linkset, e->blo.cic, e->blo.opc);
12458             if (chanpos < 0) {
12459                ast_log(LOG_WARNING, "BLO on unconfigured CIC %d\n", e->blo.cic);
12460                break;
12461             }
12462             p = linkset->pvts[chanpos];
12463             ast_debug(1, "Blocking CIC %d\n", e->blo.cic);
12464             ast_mutex_lock(&p->lock);
12465             p->remotelyblocked = 1;
12466             ast_mutex_unlock(&p->lock);
12467             isup_bla(linkset->ss7, e->blo.cic, p->dpc);
12468             break;
12469          case ISUP_EVENT_BLA:
12470             chanpos = ss7_find_cic(linkset, e->bla.cic, e->bla.opc);
12471             if (chanpos < 0) {
12472                ast_log(LOG_WARNING, "BLA on unconfigured CIC %d\n", e->bla.cic);
12473                break;
12474             }
12475             ast_debug(1, "Blocking CIC %d\n", e->bla.cic);
12476             p = linkset->pvts[chanpos];
12477             ast_mutex_lock(&p->lock);
12478             p->locallyblocked = 1;
12479             ast_mutex_unlock(&p->lock);
12480             break;
12481          case ISUP_EVENT_UBL:
12482             chanpos = ss7_find_cic(linkset, e->ubl.cic, e->ubl.opc);
12483             if (chanpos < 0) {
12484                ast_log(LOG_WARNING, "UBL on unconfigured CIC %d\n", e->ubl.cic);
12485                break;
12486             }
12487             p = linkset->pvts[chanpos];
12488             ast_debug(1, "Unblocking CIC %d\n", e->ubl.cic);
12489             ast_mutex_lock(&p->lock);
12490             p->remotelyblocked = 0;
12491             ast_mutex_unlock(&p->lock);
12492             isup_uba(linkset->ss7, e->ubl.cic, p->dpc);
12493             break;
12494          case ISUP_EVENT_UBA:
12495             chanpos = ss7_find_cic(linkset, e->uba.cic, e->uba.opc);
12496             if (chanpos < 0) {
12497                ast_log(LOG_WARNING, "UBA on unconfigured CIC %d\n", e->uba.cic);
12498                break;
12499             }
12500             p = linkset->pvts[chanpos];
12501             ast_debug(1, "Unblocking CIC %d\n", e->uba.cic);
12502             ast_mutex_lock(&p->lock);
12503             p->locallyblocked = 0;
12504             ast_mutex_unlock(&p->lock);
12505             break;
12506          case ISUP_EVENT_CON:
12507          case ISUP_EVENT_ANM:
12508             if (e->e == ISUP_EVENT_CON)
12509                cic = e->con.cic;
12510             else
12511                cic = e->anm.cic;
12512 
12513             chanpos = ss7_find_cic(linkset, cic, (e->e == ISUP_EVENT_ANM) ? e->anm.opc : e->con.opc);
12514             if (chanpos < 0) {
12515                ast_log(LOG_WARNING, "ANM/CON on unconfigured CIC %d\n", cic);
12516                isup_rel(ss7, (e->e == ISUP_EVENT_ANM) ? e->anm.call : e->con.call, -1);
12517                break;
12518             } else {
12519                p = linkset->pvts[chanpos];
12520                ast_mutex_lock(&p->lock);
12521                if (p->call_level < DAHDI_CALL_LEVEL_CONNECT) {
12522                   p->call_level = DAHDI_CALL_LEVEL_CONNECT;
12523                }
12524                p->subs[SUB_REAL].needanswer = 1;
12525                if (p->dsp && p->dsp_features) {
12526                   ast_dsp_set_features(p->dsp, p->dsp_features);
12527                   p->dsp_features = 0;
12528                }
12529                dahdi_enable_ec(p);
12530                ast_mutex_unlock(&p->lock);
12531             }
12532             break;
12533          case ISUP_EVENT_RLC:
12534             chanpos = ss7_find_cic(linkset, e->rlc.cic, e->rlc.opc);
12535             if (chanpos < 0) {
12536                ast_log(LOG_WARNING, "RLC on unconfigured CIC %d\n", e->rlc.cic);
12537                break;
12538             } else {
12539                p = linkset->pvts[chanpos];
12540                ast_mutex_lock(&p->lock);
12541                if (p->alreadyhungup)
12542                   p->ss7call = NULL;
12543                else
12544                   ast_log(LOG_NOTICE, "Received RLC out and we haven't sent REL.  Ignoring.\n");
12545                ast_mutex_unlock(&p->lock);
12546                }
12547                break;
12548          case ISUP_EVENT_FAA:
12549             chanpos = ss7_find_cic(linkset, e->faa.cic, e->faa.opc);
12550             if (chanpos < 0) {
12551                ast_log(LOG_WARNING, "FAA on unconfigured CIC %d\n", e->faa.cic);
12552                break;
12553             } else {
12554                p = linkset->pvts[chanpos];
12555                ast_debug(1, "FAA received on CIC %d\n", e->faa.cic);
12556                ast_mutex_lock(&p->lock);
12557                if (p->alreadyhungup){
12558                   p->ss7call = NULL;
12559                   ast_log(LOG_NOTICE, "Received FAA and we haven't sent FAR.  Ignoring.\n");
12560                }
12561                ast_mutex_unlock(&p->lock);
12562             }
12563             break;
12564          default:
12565             ast_debug(1, "Unknown event %s\n", ss7_event2str(e->e));
12566             break;
12567          }
12568       }
12569       ast_mutex_unlock(&linkset->lock);
12570    }
12571 
12572    return 0;
12573 }
12574 #endif   /* defined(HAVE_SS7) */
12575 
12576 #if defined(HAVE_SS7)
12577 static void dahdi_ss7_message(struct ss7 *ss7, char *s)
12578 {
12579 #if 0
12580    int i;
12581 
12582    for (i = 0; i < NUM_SPANS; i++)
12583       if (linksets[i].ss7 == ss7)
12584          break;
12585 
12586    ast_verbose("[%d] %s", i+1, s);
12587 #else
12588    ast_verbose("%s", s);
12589 #endif
12590 }
12591 #endif   /* defined(HAVE_SS7) */
12592 
12593 #if defined(HAVE_SS7)
12594 static void dahdi_ss7_error(struct ss7 *ss7, char *s)
12595 {
12596 #if 0
12597    int i;
12598 
12599    for (i = 0; i < NUM_SPANS; i++)
12600       if (linksets[i].ss7 == ss7)
12601          break;
12602 
12603 #else
12604    ast_log(LOG_ERROR, "%s", s);
12605 #endif
12606 }
12607 #endif   /* defined(HAVE_SS7) */
12608 
12609 #if defined(HAVE_OPENR2)
12610 static void *mfcr2_monitor(void *data)
12611 {
12612    struct dahdi_mfcr2 *mfcr2 = data;
12613    /* we should be using pthread_key_create
12614       and allocate pollers dynamically.
12615       I think do_monitor() could be leaking, since it
12616       could be cancelled at any time and is not
12617       using thread keys, why?, */
12618    struct pollfd pollers[sizeof(mfcr2->pvts)];
12619    int res = 0;
12620    int i = 0;
12621    int oldstate = 0;
12622    int quit_loop = 0;
12623    int maxsleep = 20;
12624    int was_idle = 0;
12625    int pollsize = 0;
12626    /* now that we're ready to get calls, unblock our side and
12627       get current line state */
12628    for (i = 0; i < mfcr2->numchans; i++) {
12629       openr2_chan_set_idle(mfcr2->pvts[i]->r2chan);
12630       openr2_chan_handle_cas(mfcr2->pvts[i]->r2chan);
12631    }
12632    while (1) {
12633       /* we trust here that the mfcr2 channel list will not ever change once
12634          the module is loaded */
12635       pollsize = 0;
12636       for (i = 0; i < mfcr2->numchans; i++) {
12637          pollers[i].revents = 0;
12638          pollers[i].events = 0;
12639          if (mfcr2->pvts[i]->owner) {
12640             continue;
12641          }
12642          if (!mfcr2->pvts[i]->r2chan) {
12643             ast_log(LOG_DEBUG, "Wow, no r2chan on channel %d\n", mfcr2->pvts[i]->channel);
12644             quit_loop = 1;
12645             break;
12646          }
12647          openr2_chan_enable_read(mfcr2->pvts[i]->r2chan);
12648          pollers[i].events = POLLIN | POLLPRI;
12649          pollers[i].fd = mfcr2->pvts[i]->subs[SUB_REAL].dfd;
12650          pollsize++;
12651       }
12652       if (quit_loop) {
12653          break;
12654       }
12655       if (pollsize == 0) {
12656          if (!was_idle) {
12657             ast_log(LOG_DEBUG, "Monitor thread going idle since everybody has an owner\n");
12658             was_idle = 1;
12659          }
12660          poll(NULL, 0, maxsleep);
12661          continue;
12662       }
12663       was_idle = 0;
12664       /* probably poll() is a valid cancel point, lets just be on the safe side
12665          by calling pthread_testcancel */
12666       pthread_testcancel();
12667       res = poll(pollers, mfcr2->numchans, maxsleep);
12668       pthread_testcancel();
12669       if ((res < 0) && (errno != EINTR)) {
12670          ast_log(LOG_ERROR, "going out, poll failed: %s\n", strerror(errno));
12671          break;
12672       }
12673       /* do we want to allow to cancel while processing events? */
12674       pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate);
12675       for (i = 0; i < mfcr2->numchans; i++) {
12676          if (pollers[i].revents & POLLPRI || pollers[i].revents & POLLIN) {
12677             openr2_chan_process_event(mfcr2->pvts[i]->r2chan);
12678          }
12679       }
12680       pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
12681    }
12682    ast_log(LOG_NOTICE, "Quitting MFC/R2 monitor thread\n");
12683    return 0;
12684 }
12685 #endif /* HAVE_OPENR2 */
12686 
12687 #if defined(HAVE_PRI)
12688 static struct dahdi_pvt *pri_find_crv(struct dahdi_pri *pri, int crv)
12689 {
12690    struct dahdi_pvt *p;
12691    p = pri->crvs;
12692    while (p) {
12693       if (p->channel == crv)
12694          return p;
12695       p = p->next;
12696    }
12697    return NULL;
12698 }
12699 #endif   /* defined(HAVE_PRI) */
12700 
12701 #if defined(HAVE_PRI)
12702 /*!
12703  * \internal
12704  * \brief Obtain the DAHDI owner channel lock if the owner exists.
12705  * \since 1.8
12706  *
12707  * \param pri PRI span control structure.
12708  * \param chanpos Channel position in the span.
12709  *
12710  * \note Assumes the pri->lock is already obtained.
12711  * \note Assumes the pri->pvts[chanpos]->lock is already obtained.
12712  *
12713  * \return Nothing
12714  */
12715 static void sig_pri_lock_owner(struct dahdi_pri *pri, int chanpos)
12716 {
12717    for (;;) {
12718       if (!pri->pvts[chanpos]->owner) {
12719          /* There is no owner lock to get. */
12720          break;
12721       }
12722       if (!ast_channel_trylock(pri->pvts[chanpos]->owner)) {
12723          /* We got the lock */
12724          break;
12725       }
12726       /* We must unlock the PRI to avoid the possibility of a deadlock */
12727       ast_mutex_unlock(&pri->lock);
12728       DEADLOCK_AVOIDANCE(&pri->pvts[chanpos]->lock);
12729       ast_mutex_lock(&pri->lock);
12730    }
12731 }
12732 #endif   /* defined(HAVE_PRI) */
12733 
12734 #if defined(HAVE_PRI)
12735 /*!
12736  * \internal
12737  * \brief Queue the given frame onto the owner channel.
12738  * \since 1.8
12739  *
12740  * \param pri PRI span control structure.
12741  * \param chanpos Channel position in the span.
12742  * \param frame Frame to queue onto the owner channel.
12743  *
12744  * \note Assumes the pri->lock is already obtained.
12745  * \note Assumes the sig_pri_lock_private(pri->pvts[chanpos]) is already obtained.
12746  *
12747  * \return Nothing
12748  */
12749 static void pri_queue_frame(struct dahdi_pri *pri, int chanpos, struct ast_frame *frame)
12750 {
12751    sig_pri_lock_owner(pri, chanpos);
12752    if (pri->pvts[chanpos]->owner) {
12753       ast_queue_frame(pri->pvts[chanpos]->owner, frame);
12754       ast_channel_unlock(pri->pvts[chanpos]->owner);
12755    }
12756 }
12757 #endif   /* defined(HAVE_PRI) */
12758 
12759 #if defined(HAVE_PRI)
12760 /*!
12761  * \internal
12762  * \brief Queue a control frame of the specified subclass onto the owner channel.
12763  * \since 1.8
12764  *
12765  * \param pri PRI span control structure.
12766  * \param chanpos Channel position in the span.
12767  * \param subclass Control frame subclass to queue onto the owner channel.
12768  *
12769  * \note Assumes the pri->lock is already obtained.
12770  * \note Assumes the sig_pri_lock_private(pri->pvts[chanpos]) is already obtained.
12771  *
12772  * \return Nothing
12773  */
12774 static void pri_queue_control(struct dahdi_pri *pri, int chanpos, int subclass)
12775 {
12776    struct ast_frame f = {AST_FRAME_CONTROL, };
12777 
12778    f.subclass = subclass;
12779    pri_queue_frame(pri, chanpos, &f);
12780 }
12781 #endif   /* defined(HAVE_PRI) */
12782 
12783 #if defined(HAVE_PRI)
12784 /*!
12785  * \internal
12786  * \brief Find the channel associated with the libpri call.
12787  * \since 1.10
12788  *
12789  * \param pri PRI span control structure.
12790  * \param call LibPRI opaque call pointer to find.
12791  *
12792  * \note Assumes the pri->lock is already obtained.
12793  *
12794  * \retval array-index into private pointer array on success.
12795  * \retval -1 on error.
12796  */
12797 static int pri_find_principle_by_call(struct dahdi_pri *pri, q931_call *call)
12798 {
12799    int idx;
12800 
12801    if (!call) {
12802       /* Cannot find a call without a call. */
12803       return -1;
12804    }
12805    for (idx = 0; idx < pri->numchans; ++idx) {
12806       if (pri->pvts[idx] && pri->pvts[idx]->call == call) {
12807          /* Found the principle */
12808          return idx;
12809       }
12810    }
12811    return -1;
12812 }
12813 #endif   /* defined(HAVE_PRI) */
12814 
12815 #if defined(HAVE_PRI)
12816 /*!
12817  * \internal
12818  * \brief Kill the call.
12819  * \since 1.10
12820  *
12821  * \param pri PRI span control structure.
12822  * \param call LibPRI opaque call pointer to find.
12823  * \param cause Reason call was killed.
12824  *
12825  * \note Assumes the pvt->pri->lock is already obtained.
12826  *
12827  * \return Nothing
12828  */
12829 static void sig_pri_kill_call(struct dahdi_pri *pri, q931_call *call, int cause)
12830 {
12831    int chanpos;
12832 
12833    chanpos = pri_find_principle_by_call(pri, call);
12834    if (chanpos < 0) {
12835       pri_hangup(pri->pri, call, cause);
12836       return;
12837    }
12838    ast_mutex_lock(&pri->pvts[chanpos]->lock);
12839    if (!pri->pvts[chanpos]->owner) {
12840       pri_hangup(pri->pri, call, cause);
12841       pri->pvts[chanpos]->call = NULL;
12842       ast_mutex_unlock(&pri->pvts[chanpos]->lock);
12843       return;
12844    }
12845    pri->pvts[chanpos]->owner->hangupcause = cause;
12846    pri_queue_control(pri, chanpos, AST_CONTROL_HANGUP);
12847    ast_mutex_unlock(&pri->pvts[chanpos]->lock);
12848 }
12849 #endif   /* defined(HAVE_PRI) */
12850 
12851 #if defined(HAVE_PRI)
12852 /*!
12853  * \internal
12854  * \brief Find the private structure for the libpri call.
12855  *
12856  * \param pri PRI span control structure.
12857  * \param channel LibPRI encoded channel ID.
12858  *
12859  * \note Assumes the pri->lock is already obtained.
12860  *
12861  * \retval array-index into private pointer array on success.
12862  * \retval -1 on error.
12863  */
12864 static int pri_find_principle(struct dahdi_pri *pri, int channel)
12865 {
12866    int x;
12867    int span = PRI_SPAN(channel);
12868    int spanfd;
12869    struct dahdi_params param;
12870    int principle = -1;
12871    int explicit = PRI_EXPLICIT(channel);
12872    channel = PRI_CHANNEL(channel);
12873 
12874    if (!explicit) {
12875       spanfd = pri_active_dchan_fd(pri);
12876       memset(&param, 0, sizeof(param));
12877       if (ioctl(spanfd, DAHDI_GET_PARAMS, &param))
12878          return -1;
12879       span = pris[param.spanno - 1].prilogicalspan;
12880    }
12881 
12882    for (x = 0; x < pri->numchans; x++) {
12883       if (pri->pvts[x] && (pri->pvts[x]->prioffset == channel) && (pri->pvts[x]->logicalspan == span)) {
12884          principle = x;
12885          break;
12886       }
12887    }
12888 
12889    return principle;
12890 }
12891 #endif   /* defined(HAVE_PRI) */
12892 
12893 #if defined(HAVE_PRI)
12894 /*!
12895  * \internal
12896  * \brief Fixup the private structure associated with the libpri call.
12897  *
12898  * \param pri PRI span control structure.
12899  * \param principle Array-index into private array to move call to if not already there.
12900  * \param c LibPRI opaque call pointer to find if need to move call.
12901  *
12902  * \note Assumes the pri->lock is already obtained.
12903  *
12904  * \retval principle on success.
12905  * \retval -1 on error.
12906  */
12907 static int pri_fixup_principle(struct dahdi_pri *pri, int principle, q931_call *c)
12908 {
12909    int x;
12910    struct dahdi_pvt *crv;
12911    if (!c) {
12912       if (principle < 0)
12913          return -1;
12914       return principle;
12915    }
12916    if ((principle > -1) &&
12917       (principle < pri->numchans) &&
12918       (pri->pvts[principle]) &&
12919       (pri->pvts[principle]->call == c))
12920       return principle;
12921    /* First, check for other bearers */
12922    for (x = 0; x < pri->numchans; x++) {
12923       if (!pri->pvts[x])
12924          continue;
12925       if (pri->pvts[x]->call == c) {
12926          /* Found our call */
12927          if (principle != x) {
12928             struct dahdi_pvt *new = pri->pvts[principle], *old = pri->pvts[x];
12929 
12930             /* Get locks to safely move to the new private structure. */
12931             ast_mutex_lock(&old->lock);
12932             sig_pri_lock_owner(pri, x);
12933             ast_mutex_lock(&new->lock);
12934 
12935             ast_verb(3, "Moving call (%s) from channel %d to %d.\n",
12936                old->owner ? old->owner->name : "",
12937                old->channel, new->channel);
12938             if (!sig_pri_is_chan_available(new)) {
12939                ast_log(LOG_WARNING,
12940                   "Can't move call (%s) from channel %d to %d.  It is already in use.\n",
12941                   old->owner ? old->owner->name : "",
12942                   old->channel, new->channel);
12943                ast_mutex_unlock(&new->lock);
12944                if (old->owner) {
12945                   ast_channel_unlock(old->owner);
12946                }
12947                ast_mutex_unlock(&old->lock);
12948                return -1;
12949             }
12950 
12951             /* Fix it all up now */
12952             new->owner = old->owner;
12953             old->owner = NULL;
12954             if (new->owner) {
12955                ast_string_field_build(new->owner, name,
12956                   "DAHDI/%d:%d-%d", pri->trunkgroup,
12957                   new->channel, 1);
12958                new->owner->tech_pvt = new;
12959                ast_channel_set_fd(new->owner, 0, new->subs[SUB_REAL].dfd);
12960                new->subs[SUB_REAL].owner = old->subs[SUB_REAL].owner;
12961                old->subs[SUB_REAL].owner = NULL;
12962             } else
12963                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);
12964             new->call = old->call;
12965             old->call = NULL;
12966 
12967             /* Copy any DSP that may be present */
12968             new->dsp = old->dsp;
12969             new->dsp_features = old->dsp_features;
12970             old->dsp = NULL;
12971             old->dsp_features = 0;
12972 
12973             /* Transfer flags from the old channel. */
12974             new->alreadyhungup = old->alreadyhungup;
12975             new->isidlecall = old->isidlecall;
12976             new->progress = old->progress;
12977             new->allocated = old->allocated;
12978             new->outgoing = old->outgoing;
12979             new->digital = old->digital;
12980             old->alreadyhungup = 0;
12981             old->isidlecall = 0;
12982             old->progress = 0;
12983             old->allocated = 0;
12984             old->outgoing = 0;
12985             old->digital = 0;
12986 
12987             /* More stuff to transfer to the new channel. */
12988             new->call_level = old->call_level;
12989             old->call_level = DAHDI_CALL_LEVEL_IDLE;
12990  
12991             ast_mutex_unlock(&old->lock);
12992             if (new->owner) {
12993                ast_channel_unlock(new->owner);
12994             }
12995             ast_mutex_unlock(&new->lock);
12996          }
12997          return principle;
12998       }
12999    }
13000    /* Now check for a CRV with no bearer */
13001    crv = pri->crvs;
13002    while (crv) {
13003       if (crv->call == c) {
13004          /* This is our match...  Perform some basic checks */
13005          if (crv->bearer)
13006             ast_log(LOG_WARNING, "Trying to fix up call which already has a bearer which isn't the one we think it is\n");
13007          else if (pri->pvts[principle]->owner)
13008             ast_log(LOG_WARNING, "Tring to fix up a call to a bearer which already has an owner!\n");
13009          else {
13010             /* Looks good.  Drop the pseudo channel now, clear up the assignment, and
13011                wakeup the potential sleeper */
13012             dahdi_close_sub(crv, SUB_REAL);
13013             pri->pvts[principle]->call = crv->call;
13014             pri_assign_bearer(crv, pri, pri->pvts[principle]);
13015             ast_debug(1, "Assigning bearer %d/%d to CRV %d:%d\n",
13016                pri->pvts[principle]->logicalspan, pri->pvts[principle]->prioffset,
13017                pri->trunkgroup, crv->channel);
13018             wakeup_sub(crv, SUB_REAL, pri);
13019          }
13020          return principle;
13021       }
13022       crv = crv->next;
13023    }
13024    ast_log(LOG_WARNING, "Call specified, but not found?\n");
13025    return -1;
13026 }
13027 #endif   /* defined(HAVE_PRI) */
13028 
13029 #if defined(HAVE_PRI)
13030 /*!
13031  * \internal
13032  * \brief Find and fixup the private structure associated with the libpri call.
13033  *
13034  * \param pri PRI span control structure.
13035  * \param channel LibPRI encoded channel ID.
13036  * \param call LibPRI opaque call pointer.
13037  *
13038  * \details
13039  * This is a combination of pri_find_principle() and pri_fixup_principle()
13040  * to reduce code redundancy and to make handling several PRI_EVENT_xxx's
13041  * consistent for the current architecture.
13042  *
13043  * \note Assumes the pri->lock is already obtained.
13044  *
13045  * \retval array-index into private pointer array on success.
13046  * \retval -1 on error.
13047  */
13048 static int pri_find_fixup_principle(struct dahdi_pri *pri, int channel, q931_call *call)
13049 {
13050    int chanpos;
13051 
13052    chanpos = pri_find_principle(pri, channel);
13053    if (chanpos < 0) {
13054       ast_log(LOG_WARNING, "Span %d: PRI requested channel %d/%d is unconfigured.\n",
13055          pri->span, PRI_SPAN(channel), PRI_CHANNEL(channel));
13056       sig_pri_kill_call(pri, call, PRI_CAUSE_IDENTIFIED_CHANNEL_NOTEXIST);
13057       return -1;
13058    }
13059    chanpos = pri_fixup_principle(pri, chanpos, call);
13060    if (chanpos < 0) {
13061       ast_log(LOG_WARNING, "Span %d: PRI requested channel %d/%d is not available.\n",
13062          pri->span, PRI_SPAN(channel), PRI_CHANNEL(channel));
13063       /*
13064        * Using Q.931 section 5.2.3.1 b) as the reason for picking
13065        * PRI_CAUSE_CHANNEL_UNACCEPTABLE.  Receiving a
13066        * PRI_CAUSE_REQUESTED_CHAN_UNAVAIL would cause us to restart
13067        * that channel (which is not specified by Q.931) and kill some
13068        * other call which would be bad.
13069        */
13070       sig_pri_kill_call(pri, call, PRI_CAUSE_CHANNEL_UNACCEPTABLE);
13071       return -1;
13072    }
13073    return chanpos;
13074 }
13075 #endif   /* defined(HAVE_PRI) */
13076 
13077 #if defined(HAVE_PRI)
13078 static void *do_idle_thread(void *vchan)
13079 {
13080    struct ast_channel *chan = vchan;
13081    struct dahdi_pvt *pvt = chan->tech_pvt;
13082    struct ast_frame *f;
13083    char ex[80];
13084    /* Wait up to 30 seconds for an answer */
13085    int newms, ms = 30000;
13086    ast_verb(3, "Initiating idle call on channel %s\n", chan->name);
13087    snprintf(ex, sizeof(ex), "%d/%s", pvt->channel, pvt->pri->idledial);
13088    if (ast_call(chan, ex, 0)) {
13089       ast_log(LOG_WARNING, "Idle dial failed on '%s' to '%s'\n", chan->name, ex);
13090       ast_hangup(chan);
13091       return NULL;
13092    }
13093    while ((newms = ast_waitfor(chan, ms)) > 0) {
13094       f = ast_read(chan);
13095       if (!f) {
13096          /* Got hangup */
13097          break;
13098       }
13099       if (f->frametype == AST_FRAME_CONTROL) {
13100          switch (f->subclass) {
13101          case AST_CONTROL_ANSWER:
13102             /* Launch the PBX */
13103             ast_copy_string(chan->exten, pvt->pri->idleext, sizeof(chan->exten));
13104             ast_copy_string(chan->context, pvt->pri->idlecontext, sizeof(chan->context));
13105             chan->priority = 1;
13106             ast_verb(4, "Idle channel '%s' answered, sending to %s@%s\n", chan->name, chan->exten, chan->context);
13107             ast_pbx_run(chan);
13108             /* It's already hungup, return immediately */
13109             return NULL;
13110          case AST_CONTROL_BUSY:
13111             ast_verb(4, "Idle channel '%s' busy, waiting...\n", chan->name);
13112             break;
13113          case AST_CONTROL_CONGESTION:
13114             ast_verb(4, "Idle channel '%s' congested, waiting...\n", chan->name);
13115             break;
13116          };
13117       }
13118       ast_frfree(f);
13119       ms = newms;
13120    }
13121    /* Hangup the channel since nothing happend */
13122    ast_hangup(chan);
13123    return NULL;
13124 }
13125 #endif   /* defined(HAVE_PRI) */
13126 
13127 #if defined(HAVE_PRI)
13128 #ifndef PRI_RESTART
13129 #error "Upgrade your libpri"
13130 #endif
13131 static void dahdi_pri_message(struct pri *pri, char *s)
13132 {
13133    int x, y;
13134    int dchan = -1, span = -1;
13135    int dchancount = 0;
13136 
13137    if (pri) {
13138       for (x = 0; x < NUM_SPANS; x++) {
13139          for (y = 0; y < NUM_DCHANS; y++) {
13140             if (pris[x].dchans[y])
13141                dchancount++;
13142 
13143             if (pris[x].dchans[y] == pri)
13144                dchan = y;
13145          }
13146          if (dchan >= 0) {
13147             span = x;
13148             break;
13149          }
13150          dchancount = 0;
13151       }
13152       if (dchancount > 1 && (span > -1))
13153          ast_verbose("[Span %d D-Channel %d]%s", span, dchan, s);
13154       else
13155          ast_verbose("%s", s);
13156    } else
13157       ast_verbose("%s", s);
13158 
13159    ast_mutex_lock(&pridebugfdlock);
13160 
13161    if (pridebugfd >= 0) {
13162       if (write(pridebugfd, s, strlen(s)) < 0) {
13163          ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
13164       }
13165    }
13166 
13167    ast_mutex_unlock(&pridebugfdlock);
13168 }
13169 #endif   /* defined(HAVE_PRI) */
13170 
13171 #if defined(HAVE_PRI)
13172 static void dahdi_pri_error(struct pri *pri, char *s)
13173 {
13174    int x, y;
13175    int dchan = -1, span = -1;
13176    int dchancount = 0;
13177 
13178    if (pri) {
13179       for (x = 0; x < NUM_SPANS; x++) {
13180          for (y = 0; y < NUM_DCHANS; y++) {
13181             if (pris[x].dchans[y])
13182                dchancount++;
13183 
13184             if (pris[x].dchans[y] == pri)
13185                dchan = y;
13186          }
13187          if (dchan >= 0) {
13188             span = x;
13189             break;
13190          }
13191          dchancount = 0;
13192       }
13193       if ((dchancount > 1) && (span > -1))
13194          ast_log(LOG_ERROR, "[Span %d D-Channel %d] PRI: %s", span, dchan, s);
13195       else
13196          ast_log(LOG_ERROR, "%s", s);
13197    } else
13198       ast_log(LOG_ERROR, "%s", s);
13199 
13200    ast_mutex_lock(&pridebugfdlock);
13201 
13202    if (pridebugfd >= 0) {
13203       if (write(pridebugfd, s, strlen(s)) < 0) {
13204          ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
13205       }
13206    }
13207 
13208    ast_mutex_unlock(&pridebugfdlock);
13209 }
13210 #endif   /* defined(HAVE_PRI) */
13211 
13212 #if defined(HAVE_PRI)
13213 /*!
13214  * \internal
13215  * \brief Restart the next channel we think is idle on the span.
13216  *
13217  * \param pri PRI span control structure.
13218  *
13219  * \note Assumes the pri->lock is already obtained.
13220  *
13221  * \return Nothing
13222  */
13223 static void pri_check_restart(struct dahdi_pri *pri)
13224 {
13225    for (++pri->resetpos; pri->resetpos < pri->numchans; ++pri->resetpos) {
13226       if (!pri->pvts[pri->resetpos]
13227          || sig_pri_is_chan_in_use(pri->pvts[pri->resetpos])) {
13228          continue;
13229       }
13230       break;
13231    }
13232    if (pri->resetpos < pri->numchans) {
13233       /* Mark the channel as resetting and restart it */
13234       pri->pvts[pri->resetpos]->resetting = 1;
13235       pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[pri->resetpos]));
13236    } else {
13237       pri->resetting = 0;
13238       time(&pri->lastreset);
13239    }
13240 }
13241 #endif   /* defined(HAVE_PRI) */
13242 
13243 #if defined(HAVE_PRI)
13244 static int pri_hangup_all(struct dahdi_pvt *p, struct dahdi_pri *pri)
13245 {
13246    int x;
13247    int redo;
13248    ast_mutex_unlock(&pri->lock);
13249    ast_mutex_lock(&p->lock);
13250    do {
13251       redo = 0;
13252       for (x = 0; x < 3; x++) {
13253          while (p->subs[x].owner && ast_channel_trylock(p->subs[x].owner)) {
13254             redo++;
13255             DEADLOCK_AVOIDANCE(&p->lock);
13256          }
13257          if (p->subs[x].owner) {
13258             ast_queue_hangup_with_cause(p->subs[x].owner, AST_CAUSE_PRE_EMPTED);
13259             ast_channel_unlock(p->subs[x].owner);
13260          }
13261       }
13262    } while (redo);
13263    ast_mutex_unlock(&p->lock);
13264    ast_mutex_lock(&pri->lock);
13265    return 0;
13266 }
13267 #endif   /* defined(HAVE_PRI) */
13268 
13269 #if defined(HAVE_PRI)
13270 static char * redirectingreason2str(int redirectingreason)
13271 {
13272    switch (redirectingreason) {
13273    case 0:
13274       return "UNKNOWN";
13275    case 1:
13276       return "BUSY";
13277    case 2:
13278       return "NO_REPLY";
13279    case 0xF:
13280       return "UNCONDITIONAL";
13281    default:
13282       return "NOREDIRECT";
13283    }
13284 }
13285 #endif   /* defined(HAVE_PRI) */
13286 
13287 #if defined(HAVE_PRI)
13288 static void apply_plan_to_number(char *buf, size_t size, const struct dahdi_pri *pri, const char *number, const int plan)
13289 {
13290    if (pri->dialplan == -2) { /* autodetect the TON but leave the number untouched */
13291       snprintf(buf, size, "%s", number);
13292       return;
13293    }
13294    if (ast_strlen_zero(number)) { /* make sure a number exists so prefix isn't placed on an empty string */
13295       if (size) {
13296          *buf = '\0';
13297       }
13298       return;
13299    }
13300    switch (plan) {
13301    case PRI_INTERNATIONAL_ISDN:     /* Q.931 dialplan == 0x11 international dialplan => prepend international prefix digits */
13302       snprintf(buf, size, "%s%s", pri->internationalprefix, number);
13303       break;
13304    case PRI_NATIONAL_ISDN:       /* Q.931 dialplan == 0x21 national dialplan => prepend national prefix digits */
13305       snprintf(buf, size, "%s%s", pri->nationalprefix, number);
13306       break;
13307    case PRI_LOCAL_ISDN:       /* Q.931 dialplan == 0x41 local dialplan => prepend local prefix digits */
13308       snprintf(buf, size, "%s%s", pri->localprefix, number);
13309       break;
13310    case PRI_PRIVATE:       /* Q.931 dialplan == 0x49 private dialplan => prepend private prefix digits */
13311       snprintf(buf, size, "%s%s", pri->privateprefix, number);
13312       break;
13313    case PRI_UNKNOWN:       /* Q.931 dialplan == 0x00 unknown dialplan => prepend unknown prefix digits */
13314       snprintf(buf, size, "%s%s", pri->unknownprefix, number);
13315       break;
13316    default:          /* other Q.931 dialplan => don't twiddle with callingnum */
13317       snprintf(buf, size, "%s", number);
13318       break;
13319    }
13320 }
13321 #endif   /* defined(HAVE_PRI) */
13322 
13323 #if defined(HAVE_PRI)
13324 static void *pri_dchannel(void *vpri)
13325 {
13326    struct dahdi_pri *pri = vpri;
13327    pri_event *e;
13328    struct pollfd fds[NUM_DCHANS];
13329    int res;
13330    int chanpos = 0;
13331    int x;
13332    int haveidles;
13333    int activeidles;
13334    int nextidle = -1;
13335    struct ast_channel *c;
13336    struct timeval tv, lowest, *next;
13337    struct timeval lastidle = ast_tvnow();
13338    int doidling=0;
13339    char *cc;
13340    char idlen[80];
13341    struct ast_channel *idle;
13342    pthread_t p;
13343    time_t t;
13344    int i, which=-1;
13345    int numdchans;
13346    int cause=0;
13347    struct dahdi_pvt *crv;
13348    pthread_t threadid;
13349    char ani2str[6];
13350    char plancallingnum[256];
13351    char plancallingani[256];
13352    char calledtonstr[10];
13353    unsigned int len;
13354 
13355    pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
13356 
13357    gettimeofday(&lastidle, NULL);
13358    if (!ast_strlen_zero(pri->idledial) && !ast_strlen_zero(pri->idleext)) {
13359       /* Need to do idle dialing, check to be sure though */
13360       cc = strchr(pri->idleext, '@');
13361       if (cc) {
13362          *cc = '\0';
13363          cc++;
13364          ast_copy_string(pri->idlecontext, cc, sizeof(pri->idlecontext));
13365 #if 0
13366          /* Extensions may not be loaded yet */
13367          if (!ast_exists_extension(NULL, pri->idlecontext, pri->idleext, 1, NULL))
13368             ast_log(LOG_WARNING, "Extension '%s @ %s' does not exist\n", pri->idleext, pri->idlecontext);
13369          else
13370 #endif
13371             doidling = 1;
13372       } else
13373          ast_log(LOG_WARNING, "Idle dial string '%s' lacks '@context'\n", pri->idleext);
13374    }
13375    for (;;) {
13376       for (i = 0; i < NUM_DCHANS; i++) {
13377          if (!pri->dchannels[i])
13378             break;
13379          fds[i].fd = pri->fds[i];
13380          fds[i].events = POLLIN | POLLPRI;
13381          fds[i].revents = 0;
13382       }
13383       numdchans = i;
13384       time(&t);
13385       ast_mutex_lock(&pri->lock);
13386       if ((pri->switchtype != PRI_SWITCH_GR303_TMC) && (pri->sig != SIG_BRI_PTMP) && (pri->resetinterval > 0)) {
13387          if (pri->resetting && pri_is_up(pri)) {
13388             if (pri->resetpos < 0) {
13389                pri_check_restart(pri);
13390             }
13391          } else {
13392             if (!pri->resetting  && (t - pri->lastreset) >= pri->resetinterval) {
13393                pri->resetting = 1;
13394                pri->resetpos = -1;
13395             }
13396          }
13397       }
13398       /* Look for any idle channels if appropriate */
13399       if (doidling && pri_is_up(pri)) {
13400          nextidle = -1;
13401          haveidles = 0;
13402          activeidles = 0;
13403          for (x = pri->numchans; x >= 0; x--) {
13404             if (pri->pvts[x]) {
13405                if (sig_pri_is_chan_available(pri->pvts[x])) {
13406                   if (haveidles < pri->minunused) {
13407                      haveidles++;
13408                   } else {
13409                      nextidle = x;
13410                      break;
13411                   }
13412                } else if (pri->pvts[x]->owner && pri->pvts[x]->isidlecall) {
13413                   activeidles++;
13414                }
13415             }
13416          }
13417          if (nextidle > -1) {
13418             if (ast_tvdiff_ms(ast_tvnow(), lastidle) > 1000) {
13419                /* Don't create a new idle call more than once per second */
13420                snprintf(idlen, sizeof(idlen), "%d/%s", pri->pvts[nextidle]->channel, pri->idledial);
13421                /*
13422                 * Release the PRI lock while we create the channel so other
13423                 * threads can send D channel messages.
13424                 */
13425                ast_mutex_unlock(&pri->lock);
13426                idle = dahdi_request("DAHDI", AST_FORMAT_ULAW, idlen, &cause);
13427                ast_mutex_lock(&pri->lock);
13428                if (idle) {
13429                   pri->pvts[nextidle]->isidlecall = 1;
13430                   if (ast_pthread_create_background(&p, NULL, do_idle_thread, idle)) {
13431                      ast_log(LOG_WARNING, "Unable to start new thread for idle channel '%s'\n", idle->name);
13432                      ast_mutex_unlock(&pri->lock);
13433                      ast_hangup(idle);
13434                      ast_mutex_lock(&pri->lock);
13435                   }
13436                } else {
13437                   ast_log(LOG_WARNING, "Unable to request channel 'DAHDI/%s' for idle call\n", idlen);
13438                }
13439                lastidle = ast_tvnow();
13440             }
13441          } else if ((haveidles < pri->minunused) &&
13442             (activeidles > pri->minidle)) {
13443             /* Mark something for hangup if there is something
13444                that can be hungup */
13445             for (x = pri->numchans; x >= 0; x--) {
13446                /* find a candidate channel */
13447                if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall) {
13448                   pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
13449                   haveidles++;
13450                   /* Stop if we have enough idle channels or
13451                     can't spare any more active idle ones */
13452                   if ((haveidles >= pri->minunused) ||
13453                      (activeidles <= pri->minidle))
13454                      break;
13455                }
13456             }
13457          }
13458       }
13459       /* Start with reasonable max */
13460       lowest = ast_tv(60, 0);
13461       for (i = 0; i < NUM_DCHANS; i++) {
13462          /* Find lowest available d-channel */
13463          if (!pri->dchannels[i])
13464             break;
13465          if ((next = pri_schedule_next(pri->dchans[i]))) {
13466             /* We need relative time here */
13467             tv = ast_tvsub(*next, ast_tvnow());
13468             if (tv.tv_sec < 0) {
13469                tv = ast_tv(0,0);
13470             }
13471             if (doidling || pri->resetting) {
13472                if (tv.tv_sec > 1) {
13473                   tv = ast_tv(1, 0);
13474                }
13475             } else {
13476                if (tv.tv_sec > 60) {
13477                   tv = ast_tv(60, 0);
13478                }
13479             }
13480          } else if (doidling || pri->resetting) {
13481             /* Make sure we stop at least once per second if we're
13482                monitoring idle channels */
13483             tv = ast_tv(1,0);
13484          } else {
13485             /* Don't poll for more than 60 seconds */
13486             tv = ast_tv(60, 0);
13487          }
13488          if (!i || ast_tvcmp(tv, lowest) < 0) {
13489             lowest = tv;
13490          }
13491       }
13492       ast_mutex_unlock(&pri->lock);
13493 
13494       pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
13495       pthread_testcancel();
13496       e = NULL;
13497       res = poll(fds, numdchans, lowest.tv_sec * 1000 + lowest.tv_usec / 1000);
13498       pthread_testcancel();
13499       pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
13500 
13501       ast_mutex_lock(&pri->lock);
13502       if (!res) {
13503          for (which = 0; which < NUM_DCHANS; which++) {
13504             if (!pri->dchans[which])
13505                break;
13506             /* Just a timeout, run the scheduler */
13507             e = pri_schedule_run(pri->dchans[which]);
13508             if (e)
13509                break;
13510          }
13511       } else if (res > -1) {
13512          for (which = 0; which < NUM_DCHANS; which++) {
13513             if (!pri->dchans[which])
13514                break;
13515             if (fds[which].revents & POLLPRI) {
13516                /* Check for an event */
13517                x = 0;
13518                res = ioctl(pri->fds[which], DAHDI_GETEVENT, &x);
13519                if (x) {
13520                   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);
13521                   manager_event(EVENT_FLAG_SYSTEM, "PRIEvent",
13522                      "PRIEvent: %s\r\n"
13523                      "PRIEventCode: %d\r\n"
13524                      "D-channel: %s\r\n"
13525                      "Span: %d\r\n",
13526                      event2str(x),
13527                      x,
13528                      pri_order(which),
13529                      pri->span
13530                      );
13531                }
13532                /* Keep track of alarm state */
13533                if (x == DAHDI_EVENT_ALARM) {
13534                   pri->dchanavail[which] &= ~(DCHAN_NOTINALARM | DCHAN_UP);
13535                   pri_find_dchan(pri);
13536                } else if (x == DAHDI_EVENT_NOALARM) {
13537                   pri->dchanavail[which] |= DCHAN_NOTINALARM;
13538                   pri_restart(pri->dchans[which]);
13539                }
13540 
13541                ast_debug(1, "Got event %s (%d) on D-channel for span %d\n", event2str(x), x, pri->span);
13542             } else if (fds[which].revents & POLLIN) {
13543                e = pri_check_event(pri->dchans[which]);
13544             }
13545             if (e)
13546                break;
13547          }
13548       } else if (errno != EINTR)
13549          ast_log(LOG_WARNING, "pri_event returned error %d (%s)\n", errno, strerror(errno));
13550 
13551       if (e) {
13552          if (pri->debug)
13553             pri_dump_event(pri->dchans[which], e);
13554 
13555          if (e->e != PRI_EVENT_DCHAN_DOWN) {
13556             if (!(pri->dchanavail[which] & DCHAN_UP)) {
13557                ast_verb(2, "%s D-Channel on span %d up\n", pri_order(which), pri->span);
13558             }
13559             pri->dchanavail[which] |= DCHAN_UP;
13560          } else if (pri->sig != SIG_BRI_PTMP) {
13561             if (pri->dchanavail[which] & DCHAN_UP) {
13562                ast_verb(2, "%s D-Channel on span %d down\n", pri_order(which), pri->span);
13563             }
13564             pri->dchanavail[which] &= ~DCHAN_UP;
13565          }
13566 
13567          if ((e->e != PRI_EVENT_DCHAN_UP) && (e->e != PRI_EVENT_DCHAN_DOWN) && (pri->pri != pri->dchans[which]))
13568             /* Must be an NFAS group that has the secondary dchan active */
13569             pri->pri = pri->dchans[which];
13570 
13571          switch (e->e) {
13572          case PRI_EVENT_DCHAN_UP:
13573             pri->no_d_channels = 0;
13574             if (!pri->pri) pri_find_dchan(pri);
13575 
13576             /* Note presense of D-channel */
13577             time(&pri->lastreset);
13578 
13579             /* Restart in 5 seconds */
13580             if (pri->resetinterval > -1) {
13581                pri->lastreset -= pri->resetinterval;
13582                pri->lastreset += 5;
13583             }
13584             /* Take the channels from inalarm condition */
13585             pri->resetting = 0;
13586             for (i = 0; i < pri->numchans; i++) {
13587                if (pri->pvts[i]) {
13588                   pri->pvts[i]->inalarm = 0;
13589                   pri->pvts[i]->resetting = 0;
13590                }
13591             }
13592             break;
13593          case PRI_EVENT_DCHAN_DOWN:
13594             pri_find_dchan(pri);
13595             if (!pri_is_up(pri)) {
13596                if (pri->sig == SIG_BRI_PTMP) {
13597                   /* For PTMP connections with non persistent layer 2 we want
13598                    * to *not* declare inalarm unless there actually is an alarm */
13599                   break;
13600                }
13601                /* Hangup active channels and put them in alarm mode */
13602                pri->resetting = 0;
13603                for (i = 0; i < pri->numchans; i++) {
13604                   struct dahdi_pvt *p = pri->pvts[i];
13605                   if (p) {
13606                      if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
13607                         /* T309 is not enabled : destroy calls when alarm occurs */
13608                         if (p->call) {
13609                            if (p->pri && p->pri->pri) {
13610                               pri_destroycall(p->pri->pri, p->call);
13611                               p->call = NULL;
13612                            } else
13613                               ast_log(LOG_WARNING, "The PRI Call has not been destroyed\n");
13614                         }
13615                         if (p->realcall) {
13616                            pri_hangup_all(p->realcall, pri);
13617                         } else if (p->owner)
13618                            p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
13619                      }
13620                      p->inalarm = 1;
13621                      p->resetting = 0;
13622                   }
13623                }
13624             }
13625             break;
13626          case PRI_EVENT_RESTART:
13627             if (e->restart.channel > -1 && PRI_CHANNEL(e->ring.channel) != 0xFF) {
13628                chanpos = pri_find_principle(pri, e->restart.channel);
13629                if (chanpos < 0)
13630                   ast_log(LOG_WARNING,
13631                      "Span %d: Restart requested on odd/unavailable channel number %d/%d\n",
13632                      pri->span, PRI_SPAN(e->restart.channel),
13633                      PRI_CHANNEL(e->restart.channel));
13634                else {
13635                   ast_verb(3, "Span %d: Channel %d/%d restarted\n", pri->span,
13636                      PRI_SPAN(e->restart.channel),
13637                      PRI_CHANNEL(e->restart.channel));
13638                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
13639                   if (pri->pvts[chanpos]->call) {
13640                      pri_destroycall(pri->pri, pri->pvts[chanpos]->call);
13641                      pri->pvts[chanpos]->call = NULL;
13642                   }
13643                   /* Force soft hangup if appropriate */
13644                   if (pri->pvts[chanpos]->realcall)
13645                      pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
13646                   else if (pri->pvts[chanpos]->owner)
13647                      pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
13648                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13649                }
13650             } else {
13651                ast_verb(3, "Restart requested on entire span %d\n", pri->span);
13652                for (x = 0; x < pri->numchans; x++)
13653                   if (pri->pvts[x]) {
13654                      ast_mutex_lock(&pri->pvts[x]->lock);
13655                      if (pri->pvts[x]->call) {
13656                         pri_destroycall(pri->pri, pri->pvts[x]->call);
13657                         pri->pvts[x]->call = NULL;
13658                      }
13659                      if (pri->pvts[x]->realcall)
13660                         pri_hangup_all(pri->pvts[x]->realcall, pri);
13661                      else if (pri->pvts[x]->owner)
13662                         pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
13663                      ast_mutex_unlock(&pri->pvts[x]->lock);
13664                   }
13665             }
13666             break;
13667          case PRI_EVENT_KEYPAD_DIGIT:
13668             chanpos = pri_find_principle_by_call(pri, e->digit.call);
13669             if (chanpos < 0) {
13670                ast_log(LOG_WARNING,
13671                   "Span %d: Received keypad digits for unknown call.\n", pri->span);
13672                break;
13673             }
13674             ast_mutex_lock(&pri->pvts[chanpos]->lock);
13675             /* queue DTMF frame if the PBX for this call was already started (we're forwarding KEYPAD_DIGITs further on */
13676             if ((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)
13677                && pri->pvts[chanpos]->owner) {
13678                /* how to do that */
13679                int digitlen = strlen(e->digit.digits);
13680                char digit;
13681                int i;
13682                for (i = 0; i < digitlen; i++) {
13683                   digit = e->digit.digits[i];
13684                   {
13685                      struct ast_frame f = { AST_FRAME_DTMF, digit, };
13686                      dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
13687                   }
13688                }
13689             }
13690             ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13691             break;
13692 
13693          case PRI_EVENT_INFO_RECEIVED:
13694             chanpos = pri_find_principle_by_call(pri, e->ring.call);
13695             if (chanpos < 0) {
13696                ast_log(LOG_WARNING,
13697                   "Span %d: Received INFORMATION for unknown call.\n", pri->span);
13698                break;
13699             }
13700             ast_mutex_lock(&pri->pvts[chanpos]->lock);
13701             /* queue DTMF frame if the PBX for this call was already started (we're forwarding INFORMATION further on */
13702             if ((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)
13703                && pri->pvts[chanpos]->owner) {
13704                /* how to do that */
13705                int digitlen = strlen(e->ring.callednum);
13706                char digit;
13707                int i;
13708                for (i = 0; i < digitlen; i++) {
13709                   digit = e->ring.callednum[i];
13710                   {
13711                      struct ast_frame f = { AST_FRAME_DTMF, digit, };
13712                      dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
13713                   }
13714                }
13715             }
13716             ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13717             break;
13718          case PRI_EVENT_RING:
13719             crv = NULL;
13720             chanpos = pri_find_principle_by_call(pri, e->ring.call);
13721             if (-1 < chanpos) {
13722                /* Libpri has already filtered out duplicate SETUPs. */
13723                ast_log(LOG_WARNING,
13724                   "Span %d: Got SETUP with duplicate call ptr.  Dropping call.\n",
13725                   pri->span);
13726                pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_NORMAL_TEMPORARY_FAILURE);
13727                break;
13728             }
13729             if (e->ring.channel == -1 || PRI_CHANNEL(e->ring.channel) == 0xFF) {
13730                /* Any channel requested. */
13731                chanpos = pri_find_empty_chan(pri, 1);
13732             } else if (PRI_CHANNEL(e->ring.channel) == 0x00) {
13733                /* No channel specified. */
13734                {
13735                   /* We will not accept incoming call waiting calls. */
13736                   pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_INCOMPATIBLE_DESTINATION);
13737                   break;
13738                }
13739             } else {
13740                /* A channel is specified. */
13741                chanpos = pri_find_principle(pri, e->ring.channel);
13742                if (chanpos < 0) {
13743                   ast_log(LOG_WARNING,
13744                      "Span %d: SETUP on unconfigured channel %d/%d\n",
13745                      pri->span, PRI_SPAN(e->ring.channel),
13746                      PRI_CHANNEL(e->ring.channel));
13747                } else if (!sig_pri_is_chan_available(pri->pvts[chanpos])) {
13748                   /* This is where we handle initial glare */
13749                   ast_debug(1,
13750                      "Span %d: SETUP requested unavailable channel %d/%d.  Attempting to renegotiate.\n",
13751                      pri->span, PRI_SPAN(e->ring.channel),
13752                      PRI_CHANNEL(e->ring.channel));
13753                   chanpos = -1;
13754                }
13755 #if defined(ALWAYS_PICK_CHANNEL)
13756                if (e->ring.flexible) {
13757                   chanpos = -1;
13758                }
13759 #endif   /* defined(ALWAYS_PICK_CHANNEL) */
13760                if (chanpos < 0 && e->ring.flexible) {
13761                   /* We can try to pick another channel. */
13762                   chanpos = pri_find_empty_chan(pri, 1);
13763                }
13764             }
13765             if (chanpos < 0) {
13766                if (e->ring.flexible) {
13767                   pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION);
13768                } else {
13769                   pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_REQUESTED_CHAN_UNAVAIL);
13770                }
13771                break;
13772             }
13773 
13774             ast_mutex_lock(&pri->pvts[chanpos]->lock);
13775             if (pri->switchtype == PRI_SWITCH_GR303_TMC) {
13776                /* Should be safe to lock CRV AFAIK while bearer is still locked */
13777                crv = pri_find_crv(pri, pri_get_crv(pri->pri, e->ring.call, NULL));
13778                if (crv)
13779                   ast_mutex_lock(&crv->lock);
13780                if (!crv || crv->owner) {
13781                   pri->pvts[chanpos]->call = NULL;
13782                   if (crv) {
13783                      if (crv->owner)
13784                         crv->owner->_softhangup |= AST_SOFTHANGUP_DEV;
13785                      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);
13786                   } else
13787                      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);
13788                   pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_INVALID_CALL_REFERENCE);
13789                   if (crv)
13790                      ast_mutex_unlock(&crv->lock);
13791                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13792                   break;
13793                }
13794             }
13795 
13796             /* Mark channel as in use so noone else will steal it. */
13797             pri->pvts[chanpos]->call = e->ring.call;
13798 
13799             apply_plan_to_number(plancallingnum, sizeof(plancallingnum), pri, e->ring.callingnum, e->ring.callingplan);
13800             if (pri->pvts[chanpos]->use_callerid) {
13801                ast_shrink_phone_number(plancallingnum);
13802                ast_copy_string(pri->pvts[chanpos]->cid_num, plancallingnum, sizeof(pri->pvts[chanpos]->cid_num));
13803 #ifdef PRI_ANI
13804                if (!ast_strlen_zero(e->ring.callingani)) {
13805                   apply_plan_to_number(plancallingani, sizeof(plancallingani), pri, e->ring.callingani, e->ring.callingplanani);
13806                   ast_shrink_phone_number(plancallingani);
13807                   ast_copy_string(pri->pvts[chanpos]->cid_ani, plancallingani, sizeof(pri->pvts[chanpos]->cid_ani));
13808                } else {
13809                   pri->pvts[chanpos]->cid_ani[0] = '\0';
13810                }
13811 #endif
13812                ast_copy_string(pri->pvts[chanpos]->cid_name, e->ring.callingname, sizeof(pri->pvts[chanpos]->cid_name));
13813                pri->pvts[chanpos]->cid_ton = e->ring.callingplan; /* this is the callingplan (TON/NPI), e->ring.callingplan>>4 would be the TON */
13814             } else {
13815                pri->pvts[chanpos]->cid_num[0] = '\0';
13816                pri->pvts[chanpos]->cid_ani[0] = '\0';
13817                pri->pvts[chanpos]->cid_name[0] = '\0';
13818                pri->pvts[chanpos]->cid_ton = 0;
13819             }
13820             apply_plan_to_number(pri->pvts[chanpos]->rdnis, sizeof(pri->pvts[chanpos]->rdnis), pri,
13821                e->ring.redirectingnum, e->ring.callingplanrdnis);
13822 
13823             /* Set DNID on all incoming calls -- even immediate */
13824             ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid));
13825 
13826             /* If immediate=yes go to s|1 */
13827             if (pri->pvts[chanpos]->immediate) {
13828                ast_verb(3, "Going to extension s|1 because of immediate=yes\n");
13829                pri->pvts[chanpos]->exten[0] = 's';
13830                pri->pvts[chanpos]->exten[1] = '\0';
13831             }
13832             /* Get called number */
13833             else if (!ast_strlen_zero(e->ring.callednum)) {
13834                ast_copy_string(pri->pvts[chanpos]->exten, e->ring.callednum, sizeof(pri->pvts[chanpos]->exten));
13835             } else if (pri->overlapdial)
13836                pri->pvts[chanpos]->exten[0] = '\0';
13837             else {
13838                /* Some PRI circuits are set up to send _no_ digits.  Handle them as 's'. */
13839                pri->pvts[chanpos]->exten[0] = 's';
13840                pri->pvts[chanpos]->exten[1] = '\0';
13841             }
13842             /* No number yet, but received "sending complete"? */
13843             if (e->ring.complete && (ast_strlen_zero(e->ring.callednum))) {
13844                ast_verb(3, "Going to extension s|1 because of Complete received\n");
13845                pri->pvts[chanpos]->exten[0] = 's';
13846                pri->pvts[chanpos]->exten[1] = '\0';
13847             }
13848 
13849             /* Make sure extension exists (or in overlap dial mode, can exist) */
13850             if (((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && ast_canmatch_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) ||
13851                ast_exists_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) {
13852                /* Setup law */
13853                int law;
13854                if (pri->switchtype != PRI_SWITCH_GR303_TMC) {
13855                   /* Set to audio mode at this point */
13856                   law = 1;
13857                   if (ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &law) == -1)
13858                      ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", pri->pvts[chanpos]->channel, law, strerror(errno));
13859                }
13860                if (e->ring.layer1 == PRI_LAYER_1_ALAW)
13861                   law = DAHDI_LAW_ALAW;
13862                else
13863                   law = DAHDI_LAW_MULAW;
13864                res = dahdi_setlaw(pri->pvts[chanpos]->subs[SUB_REAL].dfd, law);
13865                if (res < 0)
13866                   ast_log(LOG_WARNING, "Unable to set law on channel %d\n", pri->pvts[chanpos]->channel);
13867                res = set_actual_gain(pri->pvts[chanpos]->subs[SUB_REAL].dfd, 0, pri->pvts[chanpos]->rxgain, pri->pvts[chanpos]->txgain, law);
13868                if (res < 0)
13869                   ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", pri->pvts[chanpos]->channel);
13870                if (e->ring.complete || !(pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
13871                   /* Just announce proceeding */
13872                   pri->pvts[chanpos]->call_level = DAHDI_CALL_LEVEL_PROCEEDING;
13873                   pri_proceeding(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 0);
13874                } else if (pri->switchtype == PRI_SWITCH_GR303_TMC) {
13875                   pri->pvts[chanpos]->call_level = DAHDI_CALL_LEVEL_CONNECT;
13876                   pri_answer(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
13877                } else {
13878                   pri->pvts[chanpos]->call_level = DAHDI_CALL_LEVEL_OVERLAP;
13879                   pri_need_more_info(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
13880                }
13881                /* Get the use_callingpres state */
13882                pri->pvts[chanpos]->callingpres = e->ring.callingpres;
13883 
13884                /* Start PBX */
13885                if (!e->ring.complete
13886                   && (pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)
13887                   && ast_matchmore_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) {
13888                   /*
13889                    * Release the PRI lock while we create the channel so other
13890                    * threads can send D channel messages.  We must also release
13891                    * the private lock to prevent deadlock while creating the
13892                    * channel.
13893                    */
13894                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13895                   ast_mutex_unlock(&pri->lock);
13896                   if (crv) {
13897                      /* Set bearer and such */
13898                      pri_assign_bearer(crv, pri, pri->pvts[chanpos]);
13899                      c = dahdi_new(crv, AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype);
13900                      pri->pvts[chanpos]->owner = &inuse;
13901                      ast_debug(1, "Started up crv %d:%d on bearer channel %d\n", pri->trunkgroup, crv->channel, crv->bearer->channel);
13902                   } else {
13903                      c = dahdi_new(pri->pvts[chanpos], AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype);
13904                   }
13905                   ast_mutex_lock(&pri->lock);
13906                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
13907                   if (c) {
13908                      if (!ast_strlen_zero(e->ring.callingsubaddr)) {
13909                         pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr);
13910                      }
13911                      if (e->ring.ani2 >= 0) {
13912                         snprintf(ani2str, sizeof(ani2str), "%d", e->ring.ani2);
13913                         pbx_builtin_setvar_helper(c, "ANI2", ani2str);
13914                         pri->pvts[chanpos]->cid_ani2 = e->ring.ani2;
13915                      }
13916 
13917 #ifdef SUPPORT_USERUSER
13918                      if (!ast_strlen_zero(e->ring.useruserinfo)) {
13919                         pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo);
13920                      }
13921 #endif
13922 
13923                      snprintf(calledtonstr, sizeof(calledtonstr), "%d", e->ring.calledplan);
13924                      pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr);
13925                      if (e->ring.redirectingreason >= 0)
13926                         pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason));
13927 
13928                      if (!pri->pvts[chanpos]->digital) {
13929                         /*
13930                          * Call has a channel.
13931                          * Indicate that we are providing dialtone.
13932                          */
13933                         pri->pvts[chanpos]->progress = 1;/* No need to send plain PROGRESS again. */
13934 #ifdef HAVE_PRI_PROG_W_CAUSE
13935                         pri_progress_with_cause(pri->pri, e->ring.call,
13936                            PVT_TO_CHANNEL(pri->pvts[chanpos]), 1, -1);/* no cause at all */
13937 #else
13938                         pri_progress(pri->pri, e->ring.call,
13939                            PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
13940 #endif
13941                      }
13942                   }
13943                   if (c && !ast_pthread_create_detached(&threadid, NULL, ss_thread, c)) {
13944                      ast_verb(3, "Accepting overlap call from '%s' to '%s' on channel %d/%d, span %d\n",
13945                         plancallingnum, S_OR(pri->pvts[chanpos]->exten, "<unspecified>"),
13946                         pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
13947                   } else {
13948                      ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n",
13949                         pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
13950                      if (c) {
13951                         /* Avoid deadlock while destroying channel */
13952                         ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13953                         ast_mutex_unlock(&pri->lock);
13954                         ast_hangup(c);
13955                         ast_mutex_lock(&pri->lock);
13956                         ast_mutex_lock(&pri->pvts[chanpos]->lock);
13957                      } else {
13958                         pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION);
13959                         pri->pvts[chanpos]->call = NULL;
13960                      }
13961                   }
13962                } else {
13963                   /*
13964                    * Release the PRI lock while we create the channel so other
13965                    * threads can send D channel messages.  We must also release
13966                    * the private lock to prevent deadlock while creating the
13967                    * channel.
13968                    */
13969                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13970                   ast_mutex_unlock(&pri->lock);
13971                   c = dahdi_new(pri->pvts[chanpos], AST_STATE_RING, 0, SUB_REAL, law, e->ring.ctype);
13972                   ast_mutex_lock(&pri->lock);
13973                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
13974                   if (c) {
13975                      /*
13976                       * It is reasonably safe to set the following
13977                       * channel variables while the PRI and DAHDI private
13978                       * structures are locked.  The PBX has not been
13979                       * started yet and it is unlikely that any other task
13980                       * will do anything with the channel we have just
13981                       * created.
13982                       */
13983                      if (!ast_strlen_zero(e->ring.callingsubaddr)) {
13984                         pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr);
13985                      }
13986                      if (e->ring.ani2 >= 0) {
13987                         snprintf(ani2str, sizeof(ani2str), "%d", e->ring.ani2);
13988                         pbx_builtin_setvar_helper(c, "ANI2", ani2str);
13989                         pri->pvts[chanpos]->cid_ani2 = e->ring.ani2;
13990                      }
13991 
13992 #ifdef SUPPORT_USERUSER
13993                      if (!ast_strlen_zero(e->ring.useruserinfo)) {
13994                         pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo);
13995                      }
13996 #endif
13997 
13998                      if (e->ring.redirectingreason >= 0)
13999                         pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason));
14000 
14001                      snprintf(calledtonstr, sizeof(calledtonstr), "%d", e->ring.calledplan);
14002                      pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr);
14003                   }
14004                   if (c && !ast_pbx_start(c)) {
14005                      ast_verb(3, "Accepting call from '%s' to '%s' on channel %d/%d, span %d\n",
14006                         plancallingnum, pri->pvts[chanpos]->exten,
14007                         pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
14008 
14009                      dahdi_enable_ec(pri->pvts[chanpos]);
14010                   } else {
14011                      ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n",
14012                         pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
14013                      if (c) {
14014                         /* Avoid deadlock while destroying channel */
14015                         ast_mutex_unlock(&pri->pvts[chanpos]->lock);
14016                         ast_mutex_unlock(&pri->lock);
14017                         ast_hangup(c);
14018                         ast_mutex_lock(&pri->lock);
14019                         ast_mutex_lock(&pri->pvts[chanpos]->lock);
14020                      } else {
14021                         pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION);
14022                         pri->pvts[chanpos]->call = NULL;
14023                      }
14024                   }
14025                }
14026             } else {
14027                ast_verb(3,
14028                   "Span %d: Extension %s@%s does not exist.  Rejecting call from '%s'.\n",
14029                   pri->span, pri->pvts[chanpos]->exten, pri->pvts[chanpos]->context,
14030                   pri->pvts[chanpos]->cid_num);
14031                pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_UNALLOCATED);
14032                pri->pvts[chanpos]->call = NULL;
14033                pri->pvts[chanpos]->exten[0] = '\0';
14034             }
14035             if (crv)
14036                ast_mutex_unlock(&crv->lock);
14037             ast_mutex_unlock(&pri->pvts[chanpos]->lock);
14038             break;
14039          case PRI_EVENT_RINGING:
14040             chanpos = pri_find_fixup_principle(pri, e->ringing.channel,
14041                e->ringing.call);
14042             if (chanpos < 0) {
14043                break;
14044             }
14045             ast_mutex_lock(&pri->pvts[chanpos]->lock);
14046             if (ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) {
14047                dahdi_enable_ec(pri->pvts[chanpos]);
14048                pri->pvts[chanpos]->subs[SUB_REAL].needringing = 1;
14049                if (pri->pvts[chanpos]->call_level < DAHDI_CALL_LEVEL_ALERTING) {
14050                   pri->pvts[chanpos]->call_level = DAHDI_CALL_LEVEL_ALERTING;
14051                }
14052             } else
14053                ast_debug(1, "Deferring ringing notification because of extra digits to dial...\n");
14054 
14055             if (
14056 #ifdef PRI_PROGRESS_MASK
14057                e->ringing.progressmask & PRI_PROG_INBAND_AVAILABLE
14058 #else
14059                e->ringing.progress == 8
14060 #endif
14061                ) {
14062                /* Now we can do call progress detection */
14063                if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
14064                   /* RINGING detection isn't required because we got ALERTING signal */
14065                   ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features & ~DSP_PROGRESS_RINGING);
14066                   pri->pvts[chanpos]->dsp_features = 0;
14067                }
14068             }
14069 
14070 #ifdef SUPPORT_USERUSER
14071             if (!ast_strlen_zero(e->ringing.useruserinfo)) {
14072                struct ast_channel *owner = pri->pvts[chanpos]->owner;
14073                ast_mutex_unlock(&pri->pvts[chanpos]->lock);
14074                pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->ringing.useruserinfo);
14075                ast_mutex_lock(&pri->pvts[chanpos]->lock);
14076             }
14077 #endif
14078 
14079             ast_mutex_unlock(&pri->pvts[chanpos]->lock);
14080             break;
14081          case PRI_EVENT_PROGRESS:
14082             chanpos = pri_find_fixup_principle(pri, e->proceeding.channel,
14083                e->proceeding.call);
14084             if (chanpos < 0) {
14085                break;
14086             }
14087             if ((!pri->pvts[chanpos]->progress)
14088 #ifdef PRI_PROGRESS_MASK
14089                || (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE)
14090 #else
14091                || (e->proceeding.progress == 8)
14092 #endif
14093                ) {
14094                struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, };
14095 
14096                if (e->proceeding.cause > -1) {
14097                   ast_verb(3, "PROGRESS with cause code %d received\n", e->proceeding.cause);
14098 
14099                   /* Work around broken, out of spec USER_BUSY cause in a progress message */
14100                   if (e->proceeding.cause == AST_CAUSE_USER_BUSY) {
14101                      if (pri->pvts[chanpos]->owner) {
14102                         ast_verb(3, "PROGRESS with 'user busy' received, signalling AST_CONTROL_BUSY instead of AST_CONTROL_PROGRESS\n");
14103 
14104                         pri->pvts[chanpos]->owner->hangupcause = e->proceeding.cause;
14105                         f.subclass = AST_CONTROL_BUSY;
14106                      }
14107                   }
14108                }
14109 
14110                ast_mutex_lock(&pri->pvts[chanpos]->lock);
14111                ast_debug(1, "Queuing frame from PRI_EVENT_PROGRESS on channel %d/%d span %d\n",
14112                   pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span);
14113                dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
14114                if (
14115 #ifdef PRI_PROGRESS_MASK
14116                   e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE
14117 #else
14118                   e->proceeding.progress == 8
14119 #endif
14120                   ) {
14121                   /* Now we can do call progress detection */
14122                   if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
14123                      ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
14124                      pri->pvts[chanpos]->dsp_features = 0;
14125                   }
14126                   /* Bring voice path up */
14127                   f.subclass = AST_CONTROL_PROGRESS;
14128                   dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
14129                }
14130                pri->pvts[chanpos]->progress = 1;
14131                pri->pvts[chanpos]->dialing = 0;
14132                ast_mutex_unlock(&pri->pvts[chanpos]->lock);
14133             }
14134             break;
14135          case PRI_EVENT_PROCEEDING:
14136             chanpos = pri_find_fixup_principle(pri, e->proceeding.channel,
14137                e->proceeding.call);
14138             if (chanpos < 0) {
14139                break;
14140             }
14141             ast_mutex_lock(&pri->pvts[chanpos]->lock);
14142             if (pri->pvts[chanpos]->call_level < DAHDI_CALL_LEVEL_PROCEEDING) {
14143                struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROCEEDING, };
14144 
14145                pri->pvts[chanpos]->call_level = DAHDI_CALL_LEVEL_PROCEEDING;
14146                ast_debug(1, "Queuing frame from PRI_EVENT_PROCEEDING on channel %d/%d span %d\n",
14147                   pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span);
14148                dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
14149                if (
14150 #ifdef PRI_PROGRESS_MASK
14151                   e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE
14152 #else
14153                   e->proceeding.progress == 8
14154 #endif
14155                   ) {
14156                   /* Now we can do call progress detection */
14157                   if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
14158                      ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
14159                      pri->pvts[chanpos]->dsp_features = 0;
14160                   }
14161                   /* Bring voice path up */
14162                   f.subclass = AST_CONTROL_PROGRESS;
14163                   dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
14164                }
14165                pri->pvts[chanpos]->dialing = 0;
14166             }
14167             ast_mutex_unlock(&pri->pvts[chanpos]->lock);
14168             break;
14169          case PRI_EVENT_FACNAME:
14170             chanpos = pri_find_principle_by_call(pri, e->facname.call);
14171             if (chanpos < 0) {
14172                ast_log(LOG_WARNING, "Span %d: Received facility for unknown call.\n",
14173                   pri->span);
14174                break;
14175             }
14176             if (pri->pvts[chanpos]->use_callerid) {
14177                /* Re-use *69 field for PRI */
14178                ast_mutex_lock(&pri->pvts[chanpos]->lock);
14179                ast_copy_string(pri->pvts[chanpos]->lastcid_num, e->facname.callingnum, sizeof(pri->pvts[chanpos]->lastcid_num));
14180                ast_copy_string(pri->pvts[chanpos]->lastcid_name, e->facname.callingname, sizeof(pri->pvts[chanpos]->lastcid_name));
14181                pri->pvts[chanpos]->subs[SUB_REAL].needcallerid = 1;
14182                dahdi_enable_ec(pri->pvts[chanpos]);
14183                ast_mutex_unlock(&pri->pvts[chanpos]->lock);
14184             }
14185             break;
14186          case PRI_EVENT_ANSWER:
14187             chanpos = pri_find_fixup_principle(pri, e->answer.channel, e->answer.call);
14188             if (chanpos < 0) {
14189                break;
14190             }
14191             ast_mutex_lock(&pri->pvts[chanpos]->lock);
14192             /* Now we can do call progress detection */
14193 
14194             /* We changed this so it turns on the DSP no matter what... progress or no progress.
14195              * By this time, we need DTMF detection and other features that were previously disabled
14196              * -- Matt F */
14197             if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
14198                ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
14199                pri->pvts[chanpos]->dsp_features = 0;
14200             }
14201             if (pri->pvts[chanpos]->realcall && (pri->pvts[chanpos]->realcall->sig == SIG_FXSKS)) {
14202                ast_debug(1, "Starting up GR-303 trunk now that we got CONNECT...\n");
14203                x = DAHDI_START;
14204                res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
14205                if (res < 0) {
14206                   if (errno != EINPROGRESS) {
14207                      ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno));
14208                   }
14209                }
14210             } else if (!ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) {
14211                pri->pvts[chanpos]->dialing = 1;
14212                /* Send any "w" waited stuff */
14213                res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_DIAL, &pri->pvts[chanpos]->dop);
14214                if (res < 0) {
14215                   ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", pri->pvts[chanpos]->channel, strerror(errno));
14216                   pri->pvts[chanpos]->dop.dialstr[0] = '\0';
14217                } else
14218                   ast_debug(1, "Sent deferred digit string: %s\n", pri->pvts[chanpos]->dop.dialstr);
14219 
14220                pri->pvts[chanpos]->dop.dialstr[0] = '\0';
14221             } else if (pri->pvts[chanpos]->confirmanswer) {
14222                ast_debug(1, "Waiting on answer confirmation on channel %d!\n", pri->pvts[chanpos]->channel);
14223             } else {
14224                pri->pvts[chanpos]->dialing = 0;
14225                if (pri->pvts[chanpos]->call_level < DAHDI_CALL_LEVEL_CONNECT) {
14226                   pri->pvts[chanpos]->call_level = DAHDI_CALL_LEVEL_CONNECT;
14227                }
14228                pri->pvts[chanpos]->subs[SUB_REAL].needanswer =1;
14229                /* Enable echo cancellation if it's not on already */
14230                dahdi_enable_ec(pri->pvts[chanpos]);
14231             }
14232 
14233 #ifdef SUPPORT_USERUSER
14234             if (!ast_strlen_zero(e->answer.useruserinfo)) {
14235                struct ast_channel *owner = pri->pvts[chanpos]->owner;
14236                ast_mutex_unlock(&pri->pvts[chanpos]->lock);
14237                pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->answer.useruserinfo);
14238                ast_mutex_lock(&pri->pvts[chanpos]->lock);
14239             }
14240 #endif
14241 
14242             ast_mutex_unlock(&pri->pvts[chanpos]->lock);
14243             break;
14244          case PRI_EVENT_HANGUP:
14245             chanpos = pri_find_principle_by_call(pri, e->hangup.call);
14246             if (chanpos < 0) {
14247                /*
14248                 * Continue hanging up the call even though
14249                 * we do not remember it (if we ever did).
14250                 */
14251                pri_hangup(pri->pri, e->hangup.call, e->hangup.cause);
14252                break;
14253             }
14254             ast_mutex_lock(&pri->pvts[chanpos]->lock);
14255             switch (e->hangup.cause) {
14256             case PRI_CAUSE_INVALID_CALL_REFERENCE:
14257                /*
14258                 * The peer denies the existence of this call so we must
14259                 * continue hanging it up and forget about it.
14260                 */
14261                pri_hangup(pri->pri, e->hangup.call, e->hangup.cause);
14262                pri->pvts[chanpos]->call = NULL;
14263                break;
14264             default:
14265                break;
14266             }
14267             if (!pri->pvts[chanpos]->alreadyhungup) {
14268                /* we're calling here dahdi_hangup so once we get there we need to clear p->call after calling pri_hangup */
14269                pri->pvts[chanpos]->alreadyhungup = 1;
14270                if (pri->pvts[chanpos]->realcall)
14271                   pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
14272                else if (pri->pvts[chanpos]->owner) {
14273                   /* Queue a BUSY instead of a hangup if our cause is appropriate */
14274                   pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
14275                   switch (pri->pvts[chanpos]->owner->_state) {
14276                   case AST_STATE_BUSY:
14277                   case AST_STATE_UP:
14278                      pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
14279                      break;
14280                   default:
14281                      if (!pri->pvts[chanpos]->outgoing) {
14282                         /*
14283                          * The incoming call leg hung up before getting
14284                          * connected so just hangup the call.
14285                          */
14286                         pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
14287                         break;
14288                      }
14289                      switch (e->hangup.cause) {
14290                      case PRI_CAUSE_USER_BUSY:
14291                         pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1;
14292                         break;
14293                      case PRI_CAUSE_CALL_REJECTED:
14294                      case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
14295                      case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
14296                      case PRI_CAUSE_SWITCH_CONGESTION:
14297                      case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
14298                      case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
14299                         pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1;
14300                         break;
14301                      default:
14302                         pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
14303                         break;
14304                      }
14305                      break;
14306                   }
14307                } else {
14308                   /*
14309                    * Continue hanging up the call even though
14310                    * we do not have an owner.
14311                    */
14312                   pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
14313                   pri->pvts[chanpos]->call = NULL;
14314                }
14315                ast_verb(3, "Span %d: Channel %d/%d got hangup, cause %d\n",
14316                   pri->span, pri->pvts[chanpos]->logicalspan,
14317                   pri->pvts[chanpos]->prioffset, e->hangup.cause);
14318             } else {
14319                /* Continue hanging up the call. */
14320                pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
14321                pri->pvts[chanpos]->call = NULL;
14322             }
14323 #if defined(FORCE_RESTART_UNAVAIL_CHANS)
14324             if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL
14325                && pri->sig != SIG_BRI_PTMP && !pri->resetting
14326                && !pri->pvts[chanpos]->resetting) {
14327                ast_verb(3,
14328                   "Span %d: Forcing restart of channel %d/%d since channel reported in use\n",
14329                   pri->span, pri->pvts[chanpos]->logicalspan,
14330                   pri->pvts[chanpos]->prioffset);
14331                pri->pvts[chanpos]->resetting = 1;
14332                pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
14333             }
14334 #endif   /* defined(FORCE_RESTART_UNAVAIL_CHANS) */
14335             if (e->hangup.aoc_units > -1)
14336                ast_verb(3, "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
14337                      pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
14338 
14339 #ifdef SUPPORT_USERUSER
14340             if (pri->pvts[chanpos]->owner && !ast_strlen_zero(e->hangup.useruserinfo)) {
14341                struct ast_channel *owner = pri->pvts[chanpos]->owner;
14342                ast_mutex_unlock(&pri->pvts[chanpos]->lock);
14343                pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
14344                ast_mutex_lock(&pri->pvts[chanpos]->lock);
14345             }
14346 #endif
14347 
14348             ast_mutex_unlock(&pri->pvts[chanpos]->lock);
14349             break;
14350 #ifndef PRI_EVENT_HANGUP_REQ
14351 #error please update libpri
14352 #endif
14353          case PRI_EVENT_HANGUP_REQ:
14354             chanpos = pri_find_principle_by_call(pri, e->hangup.call);
14355             if (chanpos < 0) {
14356                /*
14357                 * Continue hanging up the call even though
14358                 * we do not remember it (if we ever did).
14359                 */
14360                pri_hangup(pri->pri, e->hangup.call, e->hangup.cause);
14361                break;
14362             }
14363             ast_mutex_lock(&pri->pvts[chanpos]->lock);
14364             switch (e->hangup.cause) {
14365             case PRI_CAUSE_INVALID_CALL_REFERENCE:
14366                /*
14367                 * The peer denies the existence of this call so we must
14368                 * continue hanging it up and forget about it.  We should not
14369                 * get this cause here, but for completeness we will handle it
14370                 * anyway.
14371                 */
14372                pri_hangup(pri->pri, e->hangup.call, e->hangup.cause);
14373                pri->pvts[chanpos]->call = NULL;
14374                break;
14375             default:
14376                break;
14377             }
14378             if (pri->pvts[chanpos]->realcall)
14379                pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
14380             else if (pri->pvts[chanpos]->owner) {
14381                pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
14382                switch (pri->pvts[chanpos]->owner->_state) {
14383                case AST_STATE_BUSY:
14384                case AST_STATE_UP:
14385                   pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
14386                   break;
14387                default:
14388                   if (!pri->pvts[chanpos]->outgoing) {
14389                      /*
14390                       * The incoming call leg hung up before getting
14391                       * connected so just hangup the call.
14392                       */
14393                      pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
14394                      break;
14395                   }
14396                   switch (e->hangup.cause) {
14397                   case PRI_CAUSE_USER_BUSY:
14398                      pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1;
14399                      break;
14400                   case PRI_CAUSE_CALL_REJECTED:
14401                   case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
14402                   case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
14403                   case PRI_CAUSE_SWITCH_CONGESTION:
14404                   case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
14405                   case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
14406                      pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1;
14407                      break;
14408                   default:
14409                      pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
14410                      break;
14411                   }
14412                   break;
14413                }
14414                ast_verb(3, "Span %d: Channel %d/%d got hangup request, cause %d\n",
14415                   pri->span, pri->pvts[chanpos]->logicalspan,
14416                   pri->pvts[chanpos]->prioffset, e->hangup.cause);
14417                if (e->hangup.aoc_units > -1)
14418                   ast_verb(3, "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
14419                         pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
14420             } else {
14421                /*
14422                 * Continue hanging up the call even though
14423                 * we do not have an owner.
14424                 */
14425                pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
14426                pri->pvts[chanpos]->call = NULL;
14427             }
14428 #if defined(FORCE_RESTART_UNAVAIL_CHANS)
14429             if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL
14430                && pri->sig != SIG_BRI_PTMP && !pri->resetting
14431                && !pri->pvts[chanpos]->resetting) {
14432                ast_verb(3,
14433                   "Span %d: Forcing restart of channel %d/%d since channel reported in use\n",
14434                   pri->span, pri->pvts[chanpos]->logicalspan,
14435                   pri->pvts[chanpos]->prioffset);
14436                pri->pvts[chanpos]->resetting = 1;
14437                pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
14438             }
14439 #endif   /* defined(FORCE_RESTART_UNAVAIL_CHANS) */
14440 
14441 #ifdef SUPPORT_USERUSER
14442             if (!ast_strlen_zero(e->hangup.useruserinfo)) {
14443                struct ast_channel *owner = pri->pvts[chanpos]->owner;
14444                ast_mutex_unlock(&pri->pvts[chanpos]->lock);
14445                pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
14446                ast_mutex_lock(&pri->pvts[chanpos]->lock);
14447             }
14448 #endif
14449 
14450             ast_mutex_unlock(&pri->pvts[chanpos]->lock);
14451             break;
14452          case PRI_EVENT_HANGUP_ACK:
14453             chanpos = pri_find_principle_by_call(pri, e->hangup.call);
14454             if (chanpos < 0) {
14455                break;
14456             }
14457             ast_mutex_lock(&pri->pvts[chanpos]->lock);
14458             pri->pvts[chanpos]->call = NULL;
14459             if (pri->pvts[chanpos]->owner) {
14460                ast_verb(3, "Span %d: Channel %d/%d got hangup ACK\n", pri->span,
14461                   pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset);
14462             }
14463 #ifdef SUPPORT_USERUSER
14464             if (!ast_strlen_zero(e->hangup.useruserinfo)) {
14465                struct ast_channel *owner = pri->pvts[chanpos]->owner;
14466                ast_mutex_unlock(&pri->pvts[chanpos]->lock);
14467                pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
14468                ast_mutex_lock(&pri->pvts[chanpos]->lock);
14469             }
14470 #endif
14471 
14472             ast_mutex_unlock(&pri->pvts[chanpos]->lock);
14473             break;
14474          case PRI_EVENT_CONFIG_ERR:
14475             ast_log(LOG_WARNING, "PRI Error on span %d: %s\n", pri->span, e->err.err);
14476             break;
14477          case PRI_EVENT_RESTART_ACK:
14478             chanpos = pri_find_principle(pri, e->restartack.channel);
14479             if (chanpos < 0) {
14480                /* Sometime switches (e.g. I421 / British Telecom) don't give us the
14481                   channel number, so we have to figure it out...  This must be why
14482                   everybody resets exactly a channel at a time. */
14483                for (x = 0; x < pri->numchans; x++) {
14484                   if (pri->pvts[x] && pri->pvts[x]->resetting) {
14485                      chanpos = x;
14486                      ast_mutex_lock(&pri->pvts[chanpos]->lock);
14487                      ast_debug(1,
14488                         "Span %d: Assuming restart ack is for channel %d/%d\n",
14489                         pri->span, pri->pvts[chanpos]->logicalspan,
14490                         pri->pvts[chanpos]->prioffset);
14491                      if (pri->pvts[chanpos]->realcall)
14492                         pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
14493                      else if (pri->pvts[chanpos]->owner) {
14494                         ast_log(LOG_WARNING,
14495                            "Span %d: Got restart ack on channel %d/%d with owner\n",
14496                            pri->span, pri->pvts[chanpos]->logicalspan,
14497                            pri->pvts[chanpos]->prioffset);
14498                         pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
14499                      }
14500                      pri->pvts[chanpos]->resetting = 0;
14501                      ast_verb(3,
14502                         "Span %d: Channel %d/%d successfully restarted\n",
14503                         pri->span, pri->pvts[chanpos]->logicalspan,
14504                         pri->pvts[chanpos]->prioffset);
14505                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
14506                      if (pri->resetting)
14507                         pri_check_restart(pri);
14508                      break;
14509                   }
14510                }
14511                if (chanpos < 0) {
14512                   ast_log(LOG_WARNING,
14513                      "Span %d: Restart ACK on strange channel %d/%d\n",
14514                      pri->span, PRI_SPAN(e->restartack.channel),
14515                      PRI_CHANNEL(e->restartack.channel));
14516                }
14517             } else {
14518                ast_mutex_lock(&pri->pvts[chanpos]->lock);
14519                if (pri->pvts[chanpos]->realcall)
14520                   pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
14521                else if (pri->pvts[chanpos]->owner) {
14522                   ast_log(LOG_WARNING,
14523                      "Span %d: Got restart ack on channel %d/%d with owner\n",
14524                      pri->span, pri->pvts[chanpos]->logicalspan,
14525                      pri->pvts[chanpos]->prioffset);
14526                   pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
14527                }
14528                pri->pvts[chanpos]->resetting = 0;
14529                pri->pvts[chanpos]->inservice = 1;
14530                ast_verb(3,
14531                   "Span %d: Channel %d/%d successfully restarted\n",
14532                   pri->span, pri->pvts[chanpos]->logicalspan,
14533                   pri->pvts[chanpos]->prioffset);
14534                ast_mutex_unlock(&pri->pvts[chanpos]->lock);
14535                if (pri->resetting)
14536                   pri_check_restart(pri);
14537             }
14538             break;
14539          case PRI_EVENT_SETUP_ACK:
14540             chanpos = pri_find_fixup_principle(pri, e->setup_ack.channel,
14541                e->setup_ack.call);
14542             if (chanpos < 0) {
14543                break;
14544             }
14545             ast_mutex_lock(&pri->pvts[chanpos]->lock);
14546             if (pri->pvts[chanpos]->call_level < DAHDI_CALL_LEVEL_OVERLAP) {
14547                pri->pvts[chanpos]->call_level = DAHDI_CALL_LEVEL_OVERLAP;
14548             }
14549 
14550             /* Send any queued digits */
14551             len = strlen(pri->pvts[chanpos]->dialdest);
14552             for (x = 0; x < len; ++x) {
14553                ast_debug(1, "Sending pending digit '%c'\n", pri->pvts[chanpos]->dialdest[x]);
14554                pri_information(pri->pri, pri->pvts[chanpos]->call,
14555                   pri->pvts[chanpos]->dialdest[x]);
14556             }
14557 
14558             if (!pri->pvts[chanpos]->progress
14559                && (pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)
14560                && !pri->pvts[chanpos]->digital) {
14561                /*
14562                 * Call has a channel.
14563                 * Indicate for overlap dialing that dialtone may be present.
14564                 */
14565                struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, };
14566                dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
14567                pri->pvts[chanpos]->progress = 1;/* Claim to have seen inband-information */
14568                pri->pvts[chanpos]->dialing = 0;
14569                if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
14570                   ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
14571                   pri->pvts[chanpos]->dsp_features = 0;
14572                }
14573             }
14574             ast_mutex_unlock(&pri->pvts[chanpos]->lock);
14575             break;
14576          case PRI_EVENT_NOTIFY:
14577 #if defined(HAVE_PRI_CALL_HOLD)
14578             chanpos = pri_find_principle_by_call(pri, e->notify.call);
14579             if (chanpos < 0) {
14580                ast_log(LOG_WARNING, "Span %d: Received NOTIFY for unknown call.\n",
14581                   pri->span);
14582                break;
14583             }
14584 #else
14585             /*
14586              * This version of libpri does not supply a call pointer for
14587              * this message.  We are just going to have to trust that the
14588              * correct principle is found.
14589              */
14590             chanpos = pri_find_principle(pri, e->notify.channel);
14591             if (chanpos < 0) {
14592                ast_log(LOG_WARNING, "Received NOTIFY on unconfigured channel %d/%d span %d\n",
14593                   PRI_SPAN(e->notify.channel), PRI_CHANNEL(e->notify.channel), pri->span);
14594                break;
14595             }
14596 #endif   /* !defined(HAVE_PRI_CALL_HOLD) */
14597             if (!pri->discardremoteholdretrieval) {
14598                struct ast_frame f = { AST_FRAME_CONTROL, };
14599                ast_mutex_lock(&pri->pvts[chanpos]->lock);
14600                switch (e->notify.info) {
14601                case PRI_NOTIFY_REMOTE_HOLD:
14602                   f.subclass = AST_CONTROL_HOLD;
14603                   dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
14604                   break;
14605                case PRI_NOTIFY_REMOTE_RETRIEVAL:
14606                   f.subclass = AST_CONTROL_UNHOLD;
14607                   dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
14608                   break;
14609                }
14610                ast_mutex_unlock(&pri->pvts[chanpos]->lock);
14611             }
14612             break;
14613          default:
14614             ast_debug(1, "Event: %d\n", e->e);
14615          }
14616       }
14617       ast_mutex_unlock(&pri->lock);
14618    }
14619    /* Never reached */
14620    return NULL;
14621 }
14622 #endif   /* defined(HAVE_PRI) */
14623 
14624 #if defined(HAVE_PRI)
14625 static int start_pri(struct dahdi_pri *pri)
14626 {
14627    int res, x;
14628    struct dahdi_params p;
14629    struct dahdi_bufferinfo bi;
14630    struct dahdi_spaninfo si;
14631    int i;
14632 
14633    for (i = 0; i < NUM_DCHANS; i++) {
14634       if (!pri->dchannels[i])
14635          break;
14636       pri->fds[i] = open("/dev/dahdi/channel", O_RDWR);
14637       x = pri->dchannels[i];
14638       if ((pri->fds[i] < 0) || (ioctl(pri->fds[i],DAHDI_SPECIFY,&x) == -1)) {
14639          ast_log(LOG_ERROR, "Unable to open D-channel %d (%s)\n", x, strerror(errno));
14640          return -1;
14641       }
14642       memset(&p, 0, sizeof(p));
14643       res = ioctl(pri->fds[i], DAHDI_GET_PARAMS, &p);
14644       if (res) {
14645          dahdi_close_pri_fd(pri, i);
14646          ast_log(LOG_ERROR, "Unable to get parameters for D-channel %d (%s)\n", x, strerror(errno));
14647          return -1;
14648       }
14649       if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC)) {
14650          dahdi_close_pri_fd(pri, i);
14651          ast_log(LOG_ERROR, "D-channel %d is not in HDLC/FCS mode.\n", x);
14652          return -1;
14653       }
14654       memset(&si, 0, sizeof(si));
14655       res = ioctl(pri->fds[i], DAHDI_SPANSTAT, &si);
14656       if (res) {
14657          dahdi_close_pri_fd(pri, i);
14658          ast_log(LOG_ERROR, "Unable to get span state for D-channel %d (%s)\n", x, strerror(errno));
14659       }
14660       if (!si.alarms)
14661          pri->dchanavail[i] |= DCHAN_NOTINALARM;
14662       else
14663          pri->dchanavail[i] &= ~DCHAN_NOTINALARM;
14664       memset(&bi, 0, sizeof(bi));
14665       bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
14666       bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
14667       bi.numbufs = 32;
14668       bi.bufsize = 1024;
14669       if (ioctl(pri->fds[i], DAHDI_SET_BUFINFO, &bi)) {
14670          ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", x, strerror(errno));
14671          dahdi_close_pri_fd(pri, i);
14672          return -1;
14673       }
14674       switch (pri->sig) {
14675       case SIG_BRI:
14676          pri->dchans[i] = pri_new_bri(pri->fds[i], 1, pri->nodetype, pri->switchtype);
14677          break;
14678       case SIG_BRI_PTMP:
14679          pri->dchans[i] = pri_new_bri(pri->fds[i], 0, pri->nodetype, pri->switchtype);
14680          break;
14681       default:
14682          pri->dchans[i] = pri_new(pri->fds[i], pri->nodetype, pri->switchtype);
14683          break;
14684       }
14685       /* Force overlap dial if we're doing GR-303! */
14686       if (pri->switchtype == PRI_SWITCH_GR303_TMC)
14687          pri->overlapdial |= DAHDI_OVERLAPDIAL_BOTH;
14688       pri_set_overlapdial(pri->dchans[i],(pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)?1:0);
14689 #ifdef HAVE_PRI_PROG_W_CAUSE
14690       pri_set_chan_mapping_logical(pri->dchans[i], pri->qsigchannelmapping == DAHDI_CHAN_MAPPING_LOGICAL);
14691 #endif
14692 #ifdef HAVE_PRI_INBANDDISCONNECT
14693       pri_set_inbanddisconnect(pri->dchans[i], pri->inbanddisconnect);
14694 #endif
14695       /* Enslave to master if appropriate */
14696       if (i)
14697          pri_enslave(pri->dchans[0], pri->dchans[i]);
14698       if (!pri->dchans[i]) {
14699          dahdi_close_pri_fd(pri, i);
14700          ast_log(LOG_ERROR, "Unable to create PRI structure\n");
14701          return -1;
14702       }
14703       pri_set_debug(pri->dchans[i], DEFAULT_PRI_DEBUG);
14704       pri_set_nsf(pri->dchans[i], pri->nsf);
14705 #ifdef PRI_GETSET_TIMERS
14706       for (x = 0; x < PRI_MAX_TIMERS; x++) {
14707          if (pritimers[x] != 0)
14708             pri_set_timer(pri->dchans[i], x, pritimers[x]);
14709       }
14710 #endif
14711    }
14712    /* Assume primary is the one we use */
14713    pri->pri = pri->dchans[0];
14714    pri->resetpos = -1;
14715    if (ast_pthread_create_background(&pri->master, NULL, pri_dchannel, pri)) {
14716       for (i = 0; i < NUM_DCHANS; i++) {
14717          if (!pri->dchannels[i])
14718             break;
14719          dahdi_close_pri_fd(pri, i);
14720       }
14721       ast_log(LOG_ERROR, "Unable to spawn D-channel: %s\n", strerror(errno));
14722       return -1;
14723    }
14724    return 0;
14725 }
14726 #endif   /* defined(HAVE_PRI) */
14727 
14728 #if defined(HAVE_PRI)
14729 static char *complete_span_helper(const char *line, const char *word, int pos, int state, int rpos)
14730 {
14731    int which, span;
14732    char *ret = NULL;
14733 
14734    if (pos != rpos)
14735       return ret;
14736 
14737    for (which = span = 0; span < NUM_SPANS; span++) {
14738       if (pris[span].pri && ++which > state) {
14739          if (asprintf(&ret, "%d", span + 1) < 0) { /* user indexes start from 1 */
14740             ast_log(LOG_WARNING, "asprintf() failed: %s\n", strerror(errno));
14741          }
14742          break;
14743       }
14744    }
14745    return ret;
14746 }
14747 #endif   /* defined(HAVE_PRI) */
14748 
14749 #if defined(HAVE_PRI)
14750 static char *complete_span_4(const char *line, const char *word, int pos, int state)
14751 {
14752    return complete_span_helper(line,word,pos,state,3);
14753 }
14754 #endif   /* defined(HAVE_PRI) */
14755 
14756 #if defined(HAVE_PRI)
14757 static char *handle_pri_set_debug_file(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14758 {
14759    int myfd;
14760    switch (cmd) {
14761    case CLI_INIT:
14762       e->command = "pri set debug file";
14763       e->usage = "Usage: pri set debug file [output-file]\n"
14764          "       Sends PRI debug output to the specified output file\n";
14765       return NULL;
14766    case CLI_GENERATE:
14767       return NULL;
14768    }
14769    if (a->argc < 5)
14770       return CLI_SHOWUSAGE;
14771 
14772    if (ast_strlen_zero(a->argv[4]))
14773       return CLI_SHOWUSAGE;
14774 
14775    myfd = open(a->argv[4], O_CREAT|O_WRONLY, AST_FILE_MODE);
14776    if (myfd < 0) {
14777       ast_cli(a->fd, "Unable to open '%s' for writing\n", a->argv[4]);
14778       return CLI_SUCCESS;
14779    }
14780 
14781    ast_mutex_lock(&pridebugfdlock);
14782 
14783    if (pridebugfd >= 0)
14784       close(pridebugfd);
14785 
14786    pridebugfd = myfd;
14787    ast_copy_string(pridebugfilename,a->argv[4],sizeof(pridebugfilename));
14788    ast_mutex_unlock(&pridebugfdlock);
14789    ast_cli(a->fd, "PRI debug output will be sent to '%s'\n", a->argv[4]);
14790    return CLI_SUCCESS;
14791 }
14792 #endif   /* defined(HAVE_PRI) */
14793 
14794 #if defined(HAVE_PRI)
14795 static char *handle_pri_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14796 {
14797    int span;
14798    int x;
14799    int level = 0;
14800    switch (cmd) {
14801    case CLI_INIT:
14802       e->command = "pri set debug {on|off|0|1|2} span";
14803       e->usage =
14804          "Usage: pri set debug {<level>|on|off} span <span>\n"
14805          "       Enables debugging on a given PRI span\n";
14806       return NULL;
14807    case CLI_GENERATE:
14808       return complete_span_4(a->line, a->word, a->pos, a->n);
14809    }
14810    if (a->argc < 6) {
14811       return CLI_SHOWUSAGE;
14812    }
14813 
14814    if (!strcasecmp(a->argv[3], "on")) {
14815       level = 1;
14816    } else if (!strcasecmp(a->argv[3], "off")) {
14817       level = 0;
14818    } else {
14819       level = atoi(a->argv[3]);
14820    }
14821    span = atoi(a->argv[5]);
14822    if ((span < 1) || (span > NUM_SPANS)) {
14823       ast_cli(a->fd, "Invalid span %s.  Should be a number %d to %d\n", a->argv[5], 1, NUM_SPANS);
14824       return CLI_SUCCESS;
14825    }
14826    if (!pris[span-1].pri) {
14827       ast_cli(a->fd, "No PRI running on span %d\n", span);
14828       return CLI_SUCCESS;
14829    }
14830    for (x = 0; x < NUM_DCHANS; x++) {
14831       if (pris[span-1].dchans[x]) {
14832          if (level == 1) {
14833             pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU |
14834                PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE |
14835                PRI_DEBUG_Q921_STATE);
14836             ast_cli(a->fd, "Enabled debugging on span %d\n", span);
14837          } else if (level == 0) {
14838             pri_set_debug(pris[span-1].dchans[x], 0);
14839             //close the file if it's set
14840             ast_mutex_lock(&pridebugfdlock);
14841             close(pridebugfd);
14842             pridebugfd = -1;
14843             ast_cli(a->fd, "PRI debug output to file disabled\n");
14844             ast_mutex_unlock(&pridebugfdlock);
14845          } else {
14846             pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU |
14847                PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE |
14848                PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_STATE);
14849             ast_cli(a->fd, "Enabled debugging on span %d\n", span);
14850          }
14851       }
14852    }
14853    return CLI_SUCCESS;
14854 }
14855 #endif   /* defined(HAVE_PRI) */
14856 
14857 #if defined(HAVE_PRI)
14858 static void build_status(char *s, size_t len, int status, int active)
14859 {
14860    if (!s || len < 1) {
14861       return;
14862    }
14863    s[0] = '\0';
14864    if (status & DCHAN_PROVISIONED)
14865       strncat(s, "Provisioned, ", len - strlen(s) - 1);
14866    if (!(status & DCHAN_NOTINALARM))
14867       strncat(s, "In Alarm, ", len - strlen(s) - 1);
14868    if (status & DCHAN_UP)
14869       strncat(s, "Up", len - strlen(s) - 1);
14870    else
14871       strncat(s, "Down", len - strlen(s) - 1);
14872    if (active)
14873       strncat(s, ", Active", len - strlen(s) - 1);
14874    else
14875       strncat(s, ", Standby", len - strlen(s) - 1);
14876    s[len - 1] = '\0';
14877 }
14878 #endif   /* defined(HAVE_PRI) */
14879 
14880 #if defined(HAVE_PRI)
14881 static char *handle_pri_show_spans(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14882 {
14883    int span;
14884    int x;
14885    char status[256];
14886 
14887    switch (cmd) {
14888    case CLI_INIT:
14889       e->command = "pri show spans";
14890       e->usage =
14891          "Usage: pri show spans\n"
14892          "       Displays PRI Information\n";
14893       return NULL;
14894    case CLI_GENERATE:
14895       return NULL;
14896    }
14897 
14898    if (a->argc != 3)
14899       return CLI_SHOWUSAGE;
14900 
14901    for (span = 0; span < NUM_SPANS; span++) {
14902       if (pris[span].pri) {
14903          for (x = 0; x < NUM_DCHANS; x++) {
14904             if (pris[span].dchannels[x]) {
14905                build_status(status, sizeof(status), pris[span].dchanavail[x], pris[span].dchans[x] == pris[span].pri);
14906                ast_cli(a->fd, "PRI span %d/%d: %s\n", span + 1, x, status);
14907             }
14908          }
14909       }
14910    }
14911    return CLI_SUCCESS;
14912 }
14913 #endif   /* defined(HAVE_PRI) */
14914 
14915 #if defined(HAVE_PRI)
14916 static char *handle_pri_show_span(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14917 {
14918    int span;
14919    int x;
14920    char status[256];
14921    switch (cmd) {
14922    case CLI_INIT:
14923       e->command = "pri show span";
14924       e->usage =
14925          "Usage: pri show span <span>\n"
14926          "       Displays PRI Information on a given PRI span\n";
14927       return NULL;
14928    case CLI_GENERATE:
14929       return complete_span_4(a->line, a->word, a->pos, a->n);
14930    }
14931 
14932    if (a->argc < 4)
14933       return CLI_SHOWUSAGE;
14934    span = atoi(a->argv[3]);
14935    if ((span < 1) || (span > NUM_SPANS)) {
14936       ast_cli(a->fd, "Invalid span '%s'.  Should be a number from %d to %d\n", a->argv[3], 1, NUM_SPANS);
14937       return CLI_SUCCESS;
14938    }
14939    if (!pris[span-1].pri) {
14940       ast_cli(a->fd, "No PRI running on span %d\n", span);
14941       return CLI_SUCCESS;
14942    }
14943    for (x = 0; x < NUM_DCHANS; x++) {
14944       if (pris[span-1].dchannels[x]) {
14945 #ifdef PRI_DUMP_INFO_STR
14946          char *info_str = NULL;
14947 #endif
14948          ast_cli(a->fd, "%s D-channel: %d\n", pri_order(x), pris[span-1].dchannels[x]);
14949          build_status(status, sizeof(status), pris[span-1].dchanavail[x], pris[span-1].dchans[x] == pris[span-1].pri);
14950          ast_cli(a->fd, "Status: %s\n", status);
14951          ast_mutex_lock(&pris[span - 1].lock);
14952 #ifdef PRI_DUMP_INFO_STR
14953          info_str = pri_dump_info_str(pris[span-1].pri);
14954          if (info_str) {
14955             ast_cli(a->fd, "%s", info_str);
14956             ast_free(info_str);
14957          }
14958 #else
14959          pri_dump_info(pris[span-1].pri);
14960 #endif
14961          ast_mutex_unlock(&pris[span - 1].lock);
14962          ast_cli(a->fd, "Overlap Recv: %s\n\n", (pris[span-1].overlapdial & DAHDI_OVERLAPDIAL_INCOMING)?"Yes":"No");
14963       }
14964    }
14965    return CLI_SUCCESS;
14966 }
14967 #endif   /* defined(HAVE_PRI) */
14968 
14969 #if defined(HAVE_PRI)
14970 static char *handle_pri_show_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14971 {
14972    int x;
14973    int span;
14974    int count=0;
14975    int debug=0;
14976 
14977    switch (cmd) {
14978    case CLI_INIT:
14979       e->command = "pri show debug";
14980       e->usage =
14981          "Usage: pri show debug\n"
14982          "  Show the debug state of pri spans\n";
14983       return NULL;
14984    case CLI_GENERATE:
14985       return NULL;
14986    }
14987 
14988    for (span = 0; span < NUM_SPANS; span++) {
14989       if (pris[span].pri) {
14990          for (x = 0; x < NUM_DCHANS; x++) {
14991             debug = 0;
14992             if (pris[span].dchans[x]) {
14993                debug = pri_get_debug(pris[span].dchans[x]);
14994                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" );
14995                count++;
14996             }
14997          }
14998       }
14999 
15000    }
15001    ast_mutex_lock(&pridebugfdlock);
15002    if (pridebugfd >= 0)
15003       ast_cli(a->fd, "Logging PRI debug to file %s\n", pridebugfilename);
15004    ast_mutex_unlock(&pridebugfdlock);
15005 
15006    if (!count)
15007       ast_cli(a->fd, "No debug set or no PRI running\n");
15008    return CLI_SUCCESS;
15009 }
15010 #endif   /* defined(HAVE_PRI) */
15011 
15012 #if defined(HAVE_PRI)
15013 static char *handle_pri_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15014 {
15015    switch (cmd) {
15016    case CLI_INIT:
15017       e->command = "pri show version";
15018       e->usage =
15019          "Usage: pri show version\n"
15020          "Show libpri version information\n";
15021       return NULL;
15022    case CLI_GENERATE:
15023       return NULL;
15024    }
15025 
15026    ast_cli(a->fd, "libpri version: %s\n", pri_get_version());
15027 
15028    return CLI_SUCCESS;
15029 }
15030 #endif   /* defined(HAVE_PRI) */
15031 
15032 #if defined(HAVE_PRI)
15033 static struct ast_cli_entry dahdi_pri_cli[] = {
15034    AST_CLI_DEFINE(handle_pri_debug, "Enables PRI debugging on a span"),
15035    AST_CLI_DEFINE(handle_pri_show_spans, "Displays PRI Information"),
15036    AST_CLI_DEFINE(handle_pri_show_span, "Displays PRI Information"),
15037    AST_CLI_DEFINE(handle_pri_show_debug, "Displays current PRI debug settings"),
15038    AST_CLI_DEFINE(handle_pri_set_debug_file, "Sends PRI debug output to the specified file"),
15039    AST_CLI_DEFINE(handle_pri_version, "Displays libpri version"),
15040 };
15041 #endif   /* defined(HAVE_PRI) */
15042 
15043 #ifdef HAVE_OPENR2
15044 
15045 static char *handle_mfcr2_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15046 {
15047    switch (cmd) {
15048    case CLI_INIT:
15049       e->command = "mfcr2 show version";
15050       e->usage =
15051          "Usage: mfcr2 show version\n"
15052          "       Shows the version of the OpenR2 library being used.\n";
15053       return NULL;
15054    case CLI_GENERATE:
15055       return NULL;
15056    }
15057    ast_cli(a->fd, "OpenR2 version: %s, revision: %s\n", openr2_get_version(), openr2_get_revision());
15058    return CLI_SUCCESS;
15059 }
15060 
15061 static char *handle_mfcr2_show_variants(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15062 {
15063 #define FORMAT "%4s %40s\n"
15064    int i = 0;
15065    int numvariants = 0;
15066    const openr2_variant_entry_t *variants;
15067    switch (cmd) {
15068    case CLI_INIT:
15069       e->command = "mfcr2 show variants";
15070       e->usage =
15071          "Usage: mfcr2 show variants\n"
15072          "       Shows the list of MFC/R2 variants supported.\n";
15073       return NULL;
15074    case CLI_GENERATE:
15075       return NULL;
15076    }
15077    if (!(variants = openr2_proto_get_variant_list(&numvariants))) {
15078       ast_cli(a->fd, "Failed to get list of variants.\n");
15079       return CLI_FAILURE;
15080    }
15081    ast_cli(a->fd, FORMAT, "Variant Code", "Country");
15082    for (i = 0; i < numvariants; i++) {
15083       ast_cli(a->fd, FORMAT, variants[i].name, variants[i].country);
15084    }
15085    return CLI_SUCCESS;
15086 #undef FORMAT
15087 }
15088 
15089 static char *handle_mfcr2_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15090 {
15091 #define FORMAT "%4s %-7.7s %-7.7s %-8.8s %-9.9s %-16.16s %-8.8s %-8.8s\n"
15092    int filtertype = 0;
15093    int targetnum = 0;
15094    char channo[5];
15095    char anino[5];
15096    char dnisno[5];
15097    struct dahdi_pvt *p;
15098    openr2_context_t *r2context;
15099    openr2_variant_t r2variant;
15100    switch (cmd) {
15101    case CLI_INIT:
15102       e->command = "mfcr2 show channels [group|context]";
15103       e->usage =
15104          "Usage: mfcr2 show channels [group <group> | context <context>]\n"
15105          "       Shows the DAHDI channels configured with MFC/R2 signaling.\n";
15106       return NULL;
15107    case CLI_GENERATE:
15108       return NULL;
15109    }
15110    if (!((a->argc == 3) || (a->argc == 5))) {
15111       return CLI_SHOWUSAGE;
15112    }
15113    if (a->argc == 5) {
15114       if (!strcasecmp(a->argv[3], "group")) {
15115          targetnum = atoi(a->argv[4]);
15116          if ((targetnum < 0) || (targetnum > 63))
15117             return CLI_SHOWUSAGE;
15118          targetnum = 1 << targetnum;
15119          filtertype = 1;
15120       } else if (!strcasecmp(a->argv[3], "context")) {
15121          filtertype = 2;
15122       } else {
15123          return CLI_SHOWUSAGE;
15124       }
15125    }
15126    ast_cli(a->fd, FORMAT, "Chan", "Variant", "Max ANI", "Max DNIS", "ANI First", "Immediate Accept", "Tx CAS", "Rx CAS");
15127    ast_mutex_lock(&iflock);
15128    p = iflist;
15129    for (p = iflist; p; p = p->next) {
15130       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
15131          continue;
15132       }
15133       if (filtertype) {
15134          switch(filtertype) {
15135          case 1: /* mfcr2 show channels group <group> */
15136             if (p->group != targetnum) {
15137                continue;
15138             }
15139             break;
15140          case 2: /* mfcr2 show channels context <context> */
15141             if (strcasecmp(p->context, a->argv[4])) {
15142                continue;
15143             }
15144             break;
15145          default:
15146             ;
15147          }
15148       }
15149       r2context = openr2_chan_get_context(p->r2chan);
15150       r2variant = openr2_context_get_variant(r2context);
15151       snprintf(channo, sizeof(channo), "%d", p->channel);
15152       snprintf(anino, sizeof(anino), "%d", openr2_context_get_max_ani(r2context));
15153       snprintf(dnisno, sizeof(dnisno), "%d", openr2_context_get_max_dnis(r2context));
15154       ast_cli(a->fd, FORMAT, channo, openr2_proto_get_variant_string(r2variant),
15155             anino, dnisno, openr2_context_get_ani_first(r2context) ? "Yes" : "No",
15156             openr2_context_get_immediate_accept(r2context) ? "Yes" : "No",
15157             openr2_chan_get_tx_cas_string(p->r2chan), openr2_chan_get_rx_cas_string(p->r2chan));
15158    }
15159    ast_mutex_unlock(&iflock);
15160    return CLI_SUCCESS;
15161 #undef FORMAT
15162 }
15163 
15164 static char *handle_mfcr2_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15165 {
15166    struct dahdi_pvt *p = NULL;
15167    int channo = 0;
15168    char *toklevel = NULL;
15169    char *saveptr = NULL;
15170    char *logval = NULL;
15171    openr2_log_level_t loglevel = OR2_LOG_NOTHING;
15172    openr2_log_level_t tmplevel = OR2_LOG_NOTHING;
15173    switch (cmd) {
15174    case CLI_INIT:
15175       e->command = "mfcr2 set debug";
15176       e->usage =
15177          "Usage: mfcr2 set debug <loglevel> <channel>\n"
15178          "       Set a new logging level for the specified channel.\n"
15179          "       If no channel is specified the logging level will be applied to all channels.\n";
15180       return NULL;
15181    case CLI_GENERATE:
15182       return NULL;
15183    }
15184    if (a->argc < 4) {
15185       return CLI_SHOWUSAGE;
15186    }
15187    channo = (a->argc == 5) ? atoi(a->argv[4]) : -1;
15188    logval = ast_strdupa(a->argv[3]);
15189    toklevel = strtok_r(logval, ",", &saveptr);
15190    if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
15191       ast_cli(a->fd, "Invalid MFC/R2 logging level '%s'.\n", a->argv[3]);
15192       return CLI_FAILURE;
15193    } else if (OR2_LOG_NOTHING == tmplevel) {
15194       loglevel = tmplevel;
15195    } else {
15196       loglevel |= tmplevel;
15197       while ((toklevel = strtok_r(NULL, ",", &saveptr))) {
15198          if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
15199             ast_cli(a->fd, "Ignoring invalid logging level: '%s'.\n", toklevel);
15200             continue;
15201          }
15202          loglevel |= tmplevel;
15203       }
15204    }
15205    ast_mutex_lock(&iflock);
15206    for (p = iflist; p; p = p->next) {
15207       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
15208          continue;
15209       }
15210       if ((channo != -1) && (p->channel != channo )) {
15211          continue;
15212       }
15213       openr2_chan_set_log_level(p->r2chan, loglevel);
15214       if (channo != -1) {
15215          ast_cli(a->fd, "MFC/R2 debugging set to '%s' for channel %d.\n", a->argv[3], p->channel);
15216          break;
15217       }
15218    }
15219    if ((channo != -1) && !p) {
15220       ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
15221    }
15222    if (channo == -1) {
15223       ast_cli(a->fd, "MFC/R2 debugging set to '%s' for all channels.\n", a->argv[3]);
15224    }
15225    ast_mutex_unlock(&iflock);
15226    return CLI_SUCCESS;
15227 }
15228 
15229 static char *handle_mfcr2_call_files(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15230 {
15231    struct dahdi_pvt *p = NULL;
15232    int channo = 0;
15233    switch (cmd) {
15234    case CLI_INIT:
15235       e->command = "mfcr2 call files [on|off]";
15236       e->usage =
15237          "Usage: mfcr2 call files [on|off] <channel>\n"
15238          "       Enable call files creation on the specified channel.\n"
15239          "       If no channel is specified call files creation policy will be applied to all channels.\n";
15240       return NULL;
15241    case CLI_GENERATE:
15242       return NULL;
15243    }
15244    if (a->argc < 4) {
15245       return CLI_SHOWUSAGE;
15246    }
15247    channo = (a->argc == 5) ? atoi(a->argv[4]) : -1;
15248    ast_mutex_lock(&iflock);
15249    for (p = iflist; p; p = p->next) {
15250       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
15251          continue;
15252       }
15253       if ((channo != -1) && (p->channel != channo )) {
15254          continue;
15255       }
15256       if (ast_true(a->argv[3])) {
15257          openr2_chan_enable_call_files(p->r2chan);
15258       } else {
15259          openr2_chan_disable_call_files(p->r2chan);
15260       }
15261       if (channo != -1) {
15262          if (ast_true(a->argv[3])) {
15263             ast_cli(a->fd, "MFC/R2 call files enabled for channel %d.\n", p->channel);
15264          } else {
15265             ast_cli(a->fd, "MFC/R2 call files disabled for channel %d.\n", p->channel);
15266          }
15267          break;
15268       }
15269    }
15270    if ((channo != -1) && !p) {
15271       ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
15272    }
15273    if (channo == -1) {
15274       if (ast_true(a->argv[3])) {
15275          ast_cli(a->fd, "MFC/R2 Call files enabled for all channels.\n");
15276       } else {
15277          ast_cli(a->fd, "MFC/R2 Call files disabled for all channels.\n");
15278       }
15279    }
15280    ast_mutex_unlock(&iflock);
15281    return CLI_SUCCESS;
15282 }
15283 
15284 static char *handle_mfcr2_set_idle(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15285 {
15286    struct dahdi_pvt *p = NULL;
15287    int channo = 0;
15288    switch (cmd) {
15289    case CLI_INIT:
15290       e->command = "mfcr2 set idle";
15291       e->usage =
15292          "Usage: mfcr2 set idle <channel>\n"
15293          "       DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n"
15294          "       Force the given channel into IDLE state.\n"
15295          "       If no channel is specified, all channels will be set to IDLE.\n";
15296       return NULL;
15297    case CLI_GENERATE:
15298       return NULL;
15299    }
15300    channo = (a->argc == 4) ? atoi(a->argv[3]) : -1;
15301    ast_mutex_lock(&iflock);
15302    for (p = iflist; p; p = p->next) {
15303       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
15304          continue;
15305       }
15306       if ((channo != -1) && (p->channel != channo )) {
15307          continue;
15308       }
15309       openr2_chan_set_idle(p->r2chan);
15310       ast_mutex_lock(&p->lock);
15311       p->locallyblocked = 0;
15312       p->mfcr2call = 0;
15313       ast_mutex_unlock(&p->lock);
15314       if (channo != -1) {
15315          break;
15316       }
15317    }
15318    if ((channo != -1) && !p) {
15319       ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
15320    }
15321    ast_mutex_unlock(&iflock);
15322    return CLI_SUCCESS;
15323 }
15324 
15325 static char *handle_mfcr2_set_blocked(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15326 {
15327    struct dahdi_pvt *p = NULL;
15328    int channo = 0;
15329    switch (cmd) {
15330    case CLI_INIT:
15331       e->command = "mfcr2 set blocked";
15332       e->usage =
15333          "Usage: mfcr2 set blocked <channel>\n"
15334          "       DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n"
15335          "       Force the given channel into BLOCKED state.\n"
15336          "       If no channel is specified, all channels will be set to BLOCKED.\n";
15337       return NULL;
15338    case CLI_GENERATE:
15339       return NULL;
15340    }
15341    channo = (a->argc == 4) ? atoi(a->argv[3]) : -1;
15342    ast_mutex_lock(&iflock);
15343    for (p = iflist; p; p = p->next) {
15344       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
15345          continue;
15346       }
15347       if ((channo != -1) && (p->channel != channo )) {
15348          continue;
15349       }
15350       openr2_chan_set_blocked(p->r2chan);
15351       ast_mutex_lock(&p->lock);
15352       p->locallyblocked = 1;
15353       ast_mutex_unlock(&p->lock);
15354       if (channo != -1) {
15355          break;
15356       }
15357    }
15358    if ((channo != -1) && !p) {
15359       ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
15360    }
15361    ast_mutex_unlock(&iflock);
15362    return CLI_SUCCESS;
15363 }
15364 
15365 static struct ast_cli_entry dahdi_mfcr2_cli[] = {
15366    AST_CLI_DEFINE(handle_mfcr2_version, "Show OpenR2 library version"),
15367    AST_CLI_DEFINE(handle_mfcr2_show_variants, "Show supported MFC/R2 variants"),
15368    AST_CLI_DEFINE(handle_mfcr2_show_channels, "Show MFC/R2 channels"),
15369    AST_CLI_DEFINE(handle_mfcr2_set_debug, "Set MFC/R2 channel logging level"),
15370    AST_CLI_DEFINE(handle_mfcr2_call_files, "Enable/Disable MFC/R2 call files"),
15371    AST_CLI_DEFINE(handle_mfcr2_set_idle, "Reset MFC/R2 channel forcing it to IDLE"),
15372    AST_CLI_DEFINE(handle_mfcr2_set_blocked, "Reset MFC/R2 channel forcing it to BLOCKED"),
15373 };
15374 
15375 #endif /* HAVE_OPENR2 */
15376 
15377 static char *dahdi_destroy_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15378 {
15379    int channel;
15380    int ret;
15381    switch (cmd) {
15382    case CLI_INIT:
15383       e->command = "dahdi destroy channel";
15384       e->usage =
15385          "Usage: dahdi destroy channel <chan num>\n"
15386          "  DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.  Immediately removes a given channel, whether it is in use or not\n";
15387       return NULL;
15388    case CLI_GENERATE:
15389       return NULL;
15390    }
15391    if (a->argc != 4)
15392       return CLI_SHOWUSAGE;
15393 
15394    channel = atoi(a->argv[3]);
15395    ret = dahdi_destroy_channel_bynum(channel);
15396    return ( RESULT_SUCCESS == ret ) ? CLI_SUCCESS : CLI_FAILURE;
15397 }
15398 
15399 static void dahdi_softhangup_all(void)
15400 {
15401    struct dahdi_pvt *p;
15402 retry:
15403    ast_mutex_lock(&iflock);
15404    for (p = iflist; p; p = p->next) {
15405       ast_mutex_lock(&p->lock);
15406       if (p->owner && !p->restartpending) {
15407          if (ast_channel_trylock(p->owner)) {
15408             if (option_debug > 2)
15409                ast_verbose("Avoiding deadlock\n");
15410             /* Avoid deadlock since you're not supposed to lock iflock or pvt before a channel */
15411             ast_mutex_unlock(&p->lock);
15412             ast_mutex_unlock(&iflock);
15413             goto retry;
15414          }
15415          if (option_debug > 2)
15416             ast_verbose("Softhanging up on %s\n", p->owner->name);
15417          ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_EXPLICIT);
15418          p->restartpending = 1;
15419          num_restart_pending++;
15420          ast_channel_unlock(p->owner);
15421       }
15422       ast_mutex_unlock(&p->lock);
15423    }
15424    ast_mutex_unlock(&iflock);
15425 }
15426 
15427 static int setup_dahdi(int reload);
15428 static int dahdi_restart(void)
15429 {
15430 #if defined(HAVE_PRI) || defined(HAVE_SS7)
15431    int i, j;
15432 #endif
15433    int cancel_code;
15434    struct dahdi_pvt *p;
15435 
15436    ast_mutex_lock(&restart_lock);
15437    ast_verb(1, "Destroying channels and reloading DAHDI configuration.\n");
15438    dahdi_softhangup_all();
15439    ast_verb(4, "Initial softhangup of all DAHDI channels complete.\n");
15440 #ifdef HAVE_OPENR2
15441    dahdi_r2_destroy_links();
15442 #endif
15443 
15444 #if defined(HAVE_PRI)
15445    for (i = 0; i < NUM_SPANS; i++) {
15446       if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL)) {
15447          cancel_code = pthread_cancel(pris[i].master);
15448          pthread_kill(pris[i].master, SIGURG);
15449          ast_debug(4, "Waiting to join thread of span %d with pid=%p, cancel_code=%d\n", i, (void *) pris[i].master, cancel_code);
15450          pthread_join(pris[i].master, NULL);
15451          ast_debug(4, "Joined thread of span %d\n", i);
15452       }
15453    }
15454 #endif
15455 
15456 #if defined(HAVE_SS7)
15457    for (i = 0; i < NUM_SPANS; i++) {
15458       if (linksets[i].master && (linksets[i].master != AST_PTHREADT_NULL)) {
15459          cancel_code = pthread_cancel(linksets[i].master);
15460          pthread_kill(linksets[i].master, SIGURG);
15461          ast_debug(4, "Waiting to join thread of span %d with pid=%p, cancel_code=%d\n", i, (void *) linksets[i].master, cancel_code);
15462          pthread_join(linksets[i].master, NULL);
15463          ast_debug(4, "Joined thread of span %d\n", i);
15464       }
15465    }
15466 #endif
15467 
15468    ast_mutex_lock(&monlock);
15469    if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
15470       cancel_code = pthread_cancel(monitor_thread);
15471       pthread_kill(monitor_thread, SIGURG);
15472       ast_debug(4, "Waiting to join monitor thread with pid=%p, cancel_code=%d\n", (void *) monitor_thread, cancel_code);
15473       pthread_join(monitor_thread, NULL);
15474       ast_debug(4, "Joined monitor thread\n");
15475    }
15476    monitor_thread = AST_PTHREADT_NULL; /* prepare to restart thread in setup_dahdi once channels are reconfigured */
15477 
15478    ast_mutex_lock(&ss_thread_lock);
15479    while (ss_thread_count > 0) { /* let ss_threads finish and run dahdi_hangup before dahvi_pvts are destroyed */
15480       int x = DAHDI_FLASH;
15481       ast_debug(3, "Waiting on %d ss_thread(s) to finish\n", ss_thread_count);
15482 
15483       for (p = iflist; p; p = p->next) {
15484          if (p->owner)
15485             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 */
15486          }
15487          ast_cond_wait(&ss_thread_complete, &ss_thread_lock);
15488       }
15489 
15490    /* ensure any created channels before monitor threads were stopped are hungup */
15491    dahdi_softhangup_all();
15492    ast_verb(4, "Final softhangup of all DAHDI channels complete.\n");
15493    destroy_all_channels();
15494    ast_debug(1, "Channels destroyed. Now re-reading config. %d active channels remaining.\n", ast_active_channels());
15495 
15496    ast_mutex_unlock(&monlock);
15497 
15498 #ifdef HAVE_PRI
15499    for (i = 0; i < NUM_SPANS; i++) {
15500       for (j = 0; j < NUM_DCHANS; j++)
15501          dahdi_close_pri_fd(&(pris[i]), j);
15502    }
15503 
15504    memset(pris, 0, sizeof(pris));
15505    for (i = 0; i < NUM_SPANS; i++) {
15506       ast_mutex_init(&pris[i].lock);
15507       pris[i].offset = -1;
15508       pris[i].master = AST_PTHREADT_NULL;
15509       for (j = 0; j < NUM_DCHANS; j++)
15510          pris[i].fds[j] = -1;
15511       }
15512    pri_set_error(dahdi_pri_error);
15513    pri_set_message(dahdi_pri_message);
15514 #endif
15515 #ifdef HAVE_SS7
15516    for (i = 0; i < NUM_SPANS; i++) {
15517       for (j = 0; j < NUM_DCHANS; j++)
15518          dahdi_close_ss7_fd(&(linksets[i]), j);
15519    }
15520 
15521    memset(linksets, 0, sizeof(linksets));
15522    for (i = 0; i < NUM_SPANS; i++) {
15523       ast_mutex_init(&linksets[i].lock);
15524       linksets[i].master = AST_PTHREADT_NULL;
15525       for (j = 0; j < NUM_DCHANS; j++)
15526          linksets[i].fds[j] = -1;
15527    }
15528    ss7_set_error(dahdi_ss7_error);
15529    ss7_set_message(dahdi_ss7_message);
15530 #endif
15531 
15532    if (setup_dahdi(2) != 0) {
15533       ast_log(LOG_WARNING, "Reload channels from dahdi config failed!\n");
15534       ast_mutex_unlock(&ss_thread_lock);
15535       return 1;
15536    }
15537    ast_mutex_unlock(&ss_thread_lock);
15538    ast_mutex_unlock(&restart_lock);
15539    return 0;
15540 }
15541 
15542 static char *dahdi_restart_cmd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15543 {
15544    switch (cmd) {
15545    case CLI_INIT:
15546       e->command = "dahdi restart";
15547       e->usage =
15548          "Usage: dahdi restart\n"
15549          "  Restarts the DAHDI channels: destroys them all and then\n"
15550          "  re-reads them from chan_dahdi.conf.\n"
15551          "  Note that this will STOP any running CALL on DAHDI channels.\n"
15552          "";
15553       return NULL;
15554    case CLI_GENERATE:
15555       return NULL;
15556    }
15557    if (a->argc != 2)
15558       return CLI_SHOWUSAGE;
15559 
15560    if (dahdi_restart() != 0)
15561       return CLI_FAILURE;
15562    return CLI_SUCCESS;
15563 }
15564 
15565 static int action_dahdirestart(struct mansession *s, const struct message *m)
15566 {
15567    if (dahdi_restart() != 0) {
15568       astman_send_error(s, m, "Failed rereading DAHDI configuration");
15569       return 1;
15570    }
15571    astman_send_ack(s, m, "DAHDIRestart: Success");
15572    return 0;
15573 }
15574 
15575 static char *dahdi_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15576 {
15577 #define FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
15578 #define FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
15579    unsigned int targetnum = 0;
15580    int filtertype = 0;
15581    struct dahdi_pvt *tmp = NULL;
15582    char tmps[20] = "";
15583    char statestr[20] = "";
15584    char blockstr[20] = "";
15585    ast_mutex_t *lock;
15586    struct dahdi_pvt *start;
15587 #ifdef HAVE_PRI
15588    int trunkgroup;
15589    struct dahdi_pri *pri = NULL;
15590    int x;
15591 #endif
15592    switch (cmd) {
15593    case CLI_INIT:
15594       e->command = "dahdi show channels [trunkgroup|group|context]";
15595       e->usage =
15596          "Usage: dahdi show channels [ trunkgroup <trunkgroup> | group <group> | context <context> ]\n"
15597          "  Shows a list of available channels with optional filtering\n"
15598          "  <group> must be a number between 0 and 63\n";
15599       return NULL;
15600    case CLI_GENERATE:
15601       return NULL;
15602    }
15603 
15604    lock = &iflock;
15605    start = iflist;
15606 
15607    /* syntax: dahdi show channels [ group <group> | context <context> | trunkgroup <trunkgroup> ] */
15608 
15609    if (!((a->argc == 3) || (a->argc == 5)))
15610       return CLI_SHOWUSAGE;
15611 
15612    if (a->argc == 5) {
15613 #ifdef HAVE_PRI
15614       if (!strcasecmp(a->argv[3], "trunkgroup")) {
15615          /* this option requires no special handling, so leave filtertype to zero */
15616          if ((trunkgroup = atoi(a->argv[4])) < 1)
15617             return CLI_SHOWUSAGE;
15618          for (x = 0; x < NUM_SPANS; x++) {
15619             if (pris[x].trunkgroup == trunkgroup) {
15620                pri = pris + x;
15621                break;
15622             }
15623          }
15624          if (pri) {
15625             start = pri->crvs;
15626             lock = &pri->lock;
15627          } else {
15628             ast_cli(a->fd, "No such trunk group %d\n", trunkgroup);
15629             return CLI_FAILURE;
15630          }
15631       } else
15632 #endif
15633       if (!strcasecmp(a->argv[3], "group")) {
15634          targetnum = atoi(a->argv[4]);
15635          if ((targetnum < 0) || (targetnum > 63))
15636             return CLI_SHOWUSAGE;
15637          targetnum = 1 << targetnum;
15638          filtertype = 1;
15639       } else if (!strcasecmp(a->argv[3], "context")) {
15640          filtertype = 2;
15641       }
15642    }
15643 
15644    ast_mutex_lock(lock);
15645 #ifdef HAVE_PRI
15646    ast_cli(a->fd, FORMAT2, pri ? "CRV" : "Chan", "Extension", "Context", "Language", "MOH Interpret", "Blocked", "State");
15647 #else
15648    ast_cli(a->fd, FORMAT2, "Chan", "Extension", "Context", "Language", "MOH Interpret", "Blocked", "State");
15649 #endif
15650 
15651    tmp = start;
15652    while (tmp) {
15653       if (filtertype) {
15654          switch(filtertype) {
15655          case 1: /* dahdi show channels group <group> */
15656             if (!(tmp->group & targetnum)) {
15657                tmp = tmp->next;
15658                continue;
15659             }
15660             break;
15661          case 2: /* dahdi show channels context <context> */
15662             if (strcasecmp(tmp->context, a->argv[4])) {
15663                tmp = tmp->next;
15664                continue;
15665             }
15666             break;
15667          default:
15668             ;
15669          }
15670       }
15671       if (tmp->channel > 0) {
15672          snprintf(tmps, sizeof(tmps), "%d", tmp->channel);
15673       } else
15674          ast_copy_string(tmps, "pseudo", sizeof(tmps));
15675 
15676       if (tmp->locallyblocked)
15677          blockstr[0] = 'L';
15678       else
15679          blockstr[0] = ' ';
15680 
15681       if (tmp->remotelyblocked)
15682          blockstr[1] = 'R';
15683       else
15684          blockstr[1] = ' ';
15685 
15686       blockstr[2] = '\0';
15687 
15688       snprintf(statestr, sizeof(statestr), "%s", "In Service");
15689 
15690       ast_cli(a->fd, FORMAT, tmps, tmp->exten, tmp->context, tmp->language, tmp->mohinterpret, blockstr, statestr);
15691       tmp = tmp->next;
15692    }
15693    ast_mutex_unlock(lock);
15694    return CLI_SUCCESS;
15695 #undef FORMAT
15696 #undef FORMAT2
15697 }
15698 
15699 static char *dahdi_show_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15700 {
15701    int channel;
15702    struct dahdi_pvt *tmp = NULL;
15703    struct dahdi_confinfo ci;
15704    struct dahdi_params ps;
15705    int x;
15706    ast_mutex_t *lock;
15707    struct dahdi_pvt *start;
15708 #ifdef HAVE_PRI
15709    char *c;
15710    int trunkgroup;
15711    struct dahdi_pri *pri=NULL;
15712 #endif
15713    switch (cmd) {
15714    case CLI_INIT:
15715       e->command = "dahdi show channel";
15716       e->usage =
15717          "Usage: dahdi show channel <chan num>\n"
15718          "  Detailed information about a given channel\n";
15719       return NULL;
15720    case CLI_GENERATE:
15721       return NULL;
15722    }
15723 
15724    lock = &iflock;
15725    start = iflist;
15726 
15727    if (a->argc != 4)
15728       return CLI_SHOWUSAGE;
15729 #ifdef HAVE_PRI
15730    if ((c = strchr(a->argv[3], ':'))) {
15731       if (sscanf(a->argv[3], "%30d:%30d", &trunkgroup, &channel) != 2)
15732          return CLI_SHOWUSAGE;
15733       if ((trunkgroup < 1) || (channel < 1))
15734          return CLI_SHOWUSAGE;
15735       for (x = 0; x < NUM_SPANS; x++) {
15736          if (pris[x].trunkgroup == trunkgroup) {
15737             pri = pris + x;
15738             break;
15739          }
15740       }
15741       if (pri) {
15742          start = pri->crvs;
15743          lock = &pri->lock;
15744       } else {
15745          ast_cli(a->fd, "No such trunk group %d\n", trunkgroup);
15746          return CLI_FAILURE;
15747       }
15748    } else
15749 #endif
15750       channel = atoi(a->argv[3]);
15751 
15752    ast_mutex_lock(lock);
15753    tmp = start;
15754    while (tmp) {
15755       if (tmp->channel == channel) {
15756 #ifdef HAVE_PRI
15757          if (pri)
15758             ast_cli(a->fd, "Trunk/CRV: %d/%d\n", trunkgroup, tmp->channel);
15759          else
15760 #endif
15761          ast_cli(a->fd, "Channel: %d\n", tmp->channel);
15762          ast_cli(a->fd, "File Descriptor: %d\n", tmp->subs[SUB_REAL].dfd);
15763          ast_cli(a->fd, "Span: %d\n", tmp->span);
15764          ast_cli(a->fd, "Extension: %s\n", tmp->exten);
15765          ast_cli(a->fd, "Dialing: %s\n", tmp->dialing ? "yes" : "no");
15766          ast_cli(a->fd, "Context: %s\n", tmp->context);
15767          ast_cli(a->fd, "Caller ID: %s\n", tmp->cid_num);
15768          ast_cli(a->fd, "Calling TON: %d\n", tmp->cid_ton);
15769          ast_cli(a->fd, "Caller ID name: %s\n", tmp->cid_name);
15770          ast_cli(a->fd, "Mailbox: %s\n", S_OR(tmp->mailbox, "none"));
15771          if (tmp->vars) {
15772             struct ast_variable *v;
15773             ast_cli(a->fd, "Variables:\n");
15774             for (v = tmp->vars ; v ; v = v->next)
15775                ast_cli(a->fd, "       %s = %s\n", v->name, v->value);
15776          }
15777          ast_cli(a->fd, "Destroy: %d\n", tmp->destroy);
15778          ast_cli(a->fd, "InAlarm: %d\n", tmp->inalarm);
15779          ast_cli(a->fd, "Signalling Type: %s\n", sig2str(tmp->sig));
15780          ast_cli(a->fd, "Radio: %d\n", tmp->radio);
15781          ast_cli(a->fd, "Owner: %s\n", tmp->owner ? tmp->owner->name : "<None>");
15782          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)" : "");
15783          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)" : "");
15784          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)" : "");
15785          ast_cli(a->fd, "Confno: %d\n", tmp->confno);
15786          ast_cli(a->fd, "Propagated Conference: %d\n", tmp->propconfno);
15787          ast_cli(a->fd, "Real in conference: %d\n", tmp->inconference);
15788          ast_cli(a->fd, "DSP: %s\n", tmp->dsp ? "yes" : "no");
15789          ast_cli(a->fd, "Busy Detection: %s\n", tmp->busydetect ? "yes" : "no");
15790          if (tmp->busydetect) {
15791 #if defined(BUSYDETECT_TONEONLY)
15792             ast_cli(a->fd, "    Busy Detector Helper: BUSYDETECT_TONEONLY\n");
15793 #elif defined(BUSYDETECT_COMPARE_TONE_AND_SILENCE)
15794             ast_cli(a->fd, "    Busy Detector Helper: BUSYDETECT_COMPARE_TONE_AND_SILENCE\n");
15795 #endif
15796 #ifdef BUSYDETECT_DEBUG
15797             ast_cli(a->fd, "    Busy Detector Debug: Enabled\n");
15798 #endif
15799             ast_cli(a->fd, "    Busy Count: %d\n", tmp->busycount);
15800             ast_cli(a->fd, "    Busy Pattern: %d,%d\n", tmp->busy_tonelength, tmp->busy_quietlength);
15801          }
15802          ast_cli(a->fd, "TDD: %s\n", tmp->tdd ? "yes" : "no");
15803          ast_cli(a->fd, "Relax DTMF: %s\n", tmp->dtmfrelax ? "yes" : "no");
15804          ast_cli(a->fd, "Dialing/CallwaitCAS: %d/%d\n", tmp->dialing, tmp->callwaitcas);
15805          ast_cli(a->fd, "Default law: %s\n", tmp->law == DAHDI_LAW_MULAW ? "ulaw" : tmp->law == DAHDI_LAW_ALAW ? "alaw" : "unknown");
15806          ast_cli(a->fd, "Fax Handled: %s\n", tmp->faxhandled ? "yes" : "no");
15807          ast_cli(a->fd, "Pulse phone: %s\n", tmp->pulsedial ? "yes" : "no");
15808          ast_cli(a->fd, "DND: %s\n", tmp->dnd ? "yes" : "no");
15809          ast_cli(a->fd, "Echo Cancellation:\n");
15810 
15811          if (tmp->echocancel.head.tap_length) {
15812             ast_cli(a->fd, "\t%d taps\n", tmp->echocancel.head.tap_length);
15813             for (x = 0; x < tmp->echocancel.head.param_count; x++) {
15814                ast_cli(a->fd, "\t\t%s: %ud\n", tmp->echocancel.params[x].name, tmp->echocancel.params[x].value);
15815             }
15816             ast_cli(a->fd, "\t%scurrently %s\n", tmp->echocanbridged ? "" : "(unless TDM bridged) ", tmp->echocanon ? "ON" : "OFF");
15817          } else {
15818             ast_cli(a->fd, "\tnone\n");
15819          }
15820          ast_cli(a->fd, "Wait for dialtone: %dms\n", tmp->waitfordialtone);
15821          if (tmp->master)
15822             ast_cli(a->fd, "Master Channel: %d\n", tmp->master->channel);
15823          for (x = 0; x < MAX_SLAVES; x++) {
15824             if (tmp->slaves[x])
15825                ast_cli(a->fd, "Slave Channel: %d\n", tmp->slaves[x]->channel);
15826          }
15827 #ifdef HAVE_OPENR2
15828          if (tmp->mfcr2) {
15829             char calldir[OR2_MAX_PATH];
15830             openr2_context_t *r2context = openr2_chan_get_context(tmp->r2chan);
15831             openr2_variant_t r2variant = openr2_context_get_variant(r2context);
15832             ast_cli(a->fd, "MFC/R2 MF State: %s\n", openr2_chan_get_mf_state_string(tmp->r2chan));
15833             ast_cli(a->fd, "MFC/R2 MF Group: %s\n", openr2_chan_get_mf_group_string(tmp->r2chan));
15834             ast_cli(a->fd, "MFC/R2 State: %s\n", openr2_chan_get_r2_state_string(tmp->r2chan));
15835             ast_cli(a->fd, "MFC/R2 Call State: %s\n", openr2_chan_get_call_state_string(tmp->r2chan));
15836             ast_cli(a->fd, "MFC/R2 Call Files Enabled: %s\n", openr2_chan_get_call_files_enabled(tmp->r2chan) ? "Yes" : "No");
15837             ast_cli(a->fd, "MFC/R2 Variant: %s\n", openr2_proto_get_variant_string(r2variant));
15838             ast_cli(a->fd, "MFC/R2 Max ANI: %d\n", openr2_context_get_max_ani(r2context));
15839             ast_cli(a->fd, "MFC/R2 Max DNIS: %d\n", openr2_context_get_max_dnis(r2context));
15840             ast_cli(a->fd, "MFC/R2 Get ANI First: %s\n", openr2_context_get_ani_first(r2context) ? "Yes" : "No");
15841 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
15842             ast_cli(a->fd, "MFC/R2 Skip Category Request: %s\n", openr2_context_get_skip_category_request(r2context) ? "Yes" : "No");
15843 #endif
15844             ast_cli(a->fd, "MFC/R2 Immediate Accept: %s\n", openr2_context_get_immediate_accept(r2context) ? "Yes" : "No");
15845             ast_cli(a->fd, "MFC/R2 Accept on Offer: %s\n", tmp->mfcr2_accept_on_offer ? "Yes" : "No");
15846             ast_cli(a->fd, "MFC/R2 Charge Calls: %s\n", tmp->mfcr2_charge_calls ? "Yes" : "No");
15847             ast_cli(a->fd, "MFC/R2 Allow Collect Calls: %s\n", tmp->mfcr2_allow_collect_calls ? "Yes" : "No");
15848             ast_cli(a->fd, "MFC/R2 Forced Release: %s\n", tmp->mfcr2_forced_release ? "Yes" : "No");
15849             ast_cli(a->fd, "MFC/R2 MF Back Timeout: %dms\n", openr2_context_get_mf_back_timeout(r2context));
15850             ast_cli(a->fd, "MFC/R2 R2 Metering Pulse Timeout: %dms\n", openr2_context_get_metering_pulse_timeout(r2context));
15851             ast_cli(a->fd, "MFC/R2 Rx CAS: %s\n", openr2_chan_get_rx_cas_string(tmp->r2chan));
15852             ast_cli(a->fd, "MFC/R2 Tx CAS: %s\n", openr2_chan_get_tx_cas_string(tmp->r2chan));
15853             ast_cli(a->fd, "MFC/R2 MF Tx Signal: %d\n", openr2_chan_get_tx_mf_signal(tmp->r2chan));
15854             ast_cli(a->fd, "MFC/R2 MF Rx Signal: %d\n", openr2_chan_get_rx_mf_signal(tmp->r2chan));
15855             ast_cli(a->fd, "MFC/R2 Call Files Directory: %s\n", openr2_context_get_log_directory(r2context, calldir, sizeof(calldir)));
15856          }
15857 #endif
15858 #ifdef HAVE_SS7
15859          if (tmp->ss7) {
15860             ast_cli(a->fd, "CIC: %d\n", tmp->cic);
15861          }
15862 #endif
15863 #ifdef HAVE_PRI
15864          if (tmp->pri) {
15865             ast_cli(a->fd, "PRI Flags: ");
15866             if (tmp->resetting)
15867                ast_cli(a->fd, "Resetting ");
15868             if (tmp->call)
15869                ast_cli(a->fd, "Call ");
15870             if (tmp->bearer)
15871                ast_cli(a->fd, "Bearer ");
15872             if (tmp->allocated) {
15873                ast_cli(a->fd, "Allocated ");
15874             }
15875             ast_cli(a->fd, "\n");
15876             if (tmp->logicalspan)
15877                ast_cli(a->fd, "PRI Logical Span: %d\n", tmp->logicalspan);
15878             else
15879                ast_cli(a->fd, "PRI Logical Span: Implicit\n");
15880          }
15881 #endif
15882          memset(&ci, 0, sizeof(ci));
15883          ps.channo = tmp->channel;
15884          if (tmp->subs[SUB_REAL].dfd > -1) {
15885             memset(&ci, 0, sizeof(ci));
15886             if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
15887                ast_cli(a->fd, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci.confno, ci.confmode);
15888             }
15889             if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONFMUTE, &x)) {
15890                ast_cli(a->fd, "Actual Confmute: %s\n", x ? "Yes" : "No");
15891             }
15892             memset(&ps, 0, sizeof(ps));
15893             if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
15894                ast_log(LOG_WARNING, "Failed to get parameters on channel %d: %s\n", tmp->channel, strerror(errno));
15895             } else {
15896                ast_cli(a->fd, "Hookstate (FXS only): %s\n", ps.rxisoffhook ? "Offhook" : "Onhook");
15897             }
15898          }
15899          ast_mutex_unlock(lock);
15900          return CLI_SUCCESS;
15901       }
15902       tmp = tmp->next;
15903    }
15904 
15905    ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15906    ast_mutex_unlock(lock);
15907    return CLI_FAILURE;
15908 }
15909 
15910 static char *handle_dahdi_show_cadences(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15911 {
15912    int i, j;
15913    switch (cmd) {
15914    case CLI_INIT:
15915       e->command = "dahdi show cadences";
15916       e->usage =
15917          "Usage: dahdi show cadences\n"
15918          "       Shows all cadences currently defined\n";
15919       return NULL;
15920    case CLI_GENERATE:
15921       return NULL;
15922    }
15923    for (i = 0; i < num_cadence; i++) {
15924       char output[1024];
15925       char tmp[16], tmp2[64];
15926       snprintf(tmp, sizeof(tmp), "r%d: ", i + 1);
15927       term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output));
15928 
15929       for (j = 0; j < 16; j++) {
15930          if (cadences[i].ringcadence[j] == 0)
15931             break;
15932          snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]);
15933          if (cidrings[i] * 2 - 1 == j)
15934             term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1);
15935          else
15936             term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1);
15937          if (j != 0)
15938             strncat(output, ",", sizeof(output) - strlen(output) - 1);
15939          strncat(output, tmp2, sizeof(output) - strlen(output) - 1);
15940       }
15941       ast_cli(a->fd,"%s\n",output);
15942    }
15943    return CLI_SUCCESS;
15944 }
15945 
15946 /* Based on irqmiss.c */
15947 static char *dahdi_show_status(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15948 {
15949    #define FORMAT "%-40.40s %-7.7s %-6d %-6d %-6d %-3.3s %-4.4s %-8.8s %s\n"
15950    #define FORMAT2 "%-40.40s %-7.7s %-6.6s %-6.6s %-6.6s %-3.3s %-4.4s %-8.8s %s\n"
15951    int span;
15952    int res;
15953    char alarmstr[50];
15954 
15955    int ctl;
15956    struct dahdi_spaninfo s;
15957 
15958    switch (cmd) {
15959    case CLI_INIT:
15960       e->command = "dahdi show status";
15961       e->usage =
15962          "Usage: dahdi show status\n"
15963          "       Shows a list of DAHDI cards with status\n";
15964       return NULL;
15965    case CLI_GENERATE:
15966       return NULL;
15967    }
15968    ctl = open("/dev/dahdi/ctl", O_RDWR);
15969    if (ctl < 0) {
15970       ast_cli(a->fd, "No DAHDI found. Unable to open /dev/dahdi/ctl: %s\n", strerror(errno));
15971       return CLI_FAILURE;
15972    }
15973    ast_cli(a->fd, FORMAT2, "Description", "Alarms", "IRQ", "bpviol", "CRC4", "Framing", "Coding", "Options", "LBO");
15974 
15975    for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
15976       s.spanno = span;
15977       res = ioctl(ctl, DAHDI_SPANSTAT, &s);
15978       if (res) {
15979          continue;
15980       }
15981       alarmstr[0] = '\0';
15982       if (s.alarms > 0) {
15983          if (s.alarms & DAHDI_ALARM_BLUE)
15984             strcat(alarmstr, "BLU/");
15985          if (s.alarms & DAHDI_ALARM_YELLOW)
15986             strcat(alarmstr, "YEL/");
15987          if (s.alarms & DAHDI_ALARM_RED)
15988             strcat(alarmstr, "RED/");
15989          if (s.alarms & DAHDI_ALARM_LOOPBACK)
15990             strcat(alarmstr, "LB/");
15991          if (s.alarms & DAHDI_ALARM_RECOVER)
15992             strcat(alarmstr, "REC/");
15993          if (s.alarms & DAHDI_ALARM_NOTOPEN)
15994             strcat(alarmstr, "NOP/");
15995          if (!strlen(alarmstr))
15996             strcat(alarmstr, "UUU/");
15997          if (strlen(alarmstr)) {
15998             /* Strip trailing / */
15999             alarmstr[strlen(alarmstr) - 1] = '\0';
16000          }
16001       } else {
16002          if (s.numchans)
16003             strcpy(alarmstr, "OK");
16004          else
16005             strcpy(alarmstr, "UNCONFIGURED");
16006       }
16007 
16008       ast_cli(a->fd, FORMAT, s.desc, alarmstr, s.irqmisses, s.bpvcount, s.crc4count,
16009          s.lineconfig & DAHDI_CONFIG_D4 ? "D4" :
16010          s.lineconfig & DAHDI_CONFIG_ESF ? "ESF" :
16011          s.lineconfig & DAHDI_CONFIG_CCS ? "CCS" :
16012          "CAS",
16013          s.lineconfig & DAHDI_CONFIG_B8ZS ? "B8ZS" :
16014          s.lineconfig & DAHDI_CONFIG_HDB3 ? "HDB3" :
16015          s.lineconfig & DAHDI_CONFIG_AMI ? "AMI" :
16016          "Unk",
16017          s.lineconfig & DAHDI_CONFIG_CRC4 ?
16018             s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" :
16019             s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "YEL" : "",
16020          lbostr[s.lbo]
16021          );
16022    }
16023    close(ctl);
16024 
16025    return CLI_SUCCESS;
16026 #undef FORMAT
16027 #undef FORMAT2
16028 }
16029 
16030 static char *dahdi_show_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16031 {
16032    int pseudo_fd = -1;
16033    struct dahdi_versioninfo vi;
16034 
16035    switch (cmd) {
16036    case CLI_INIT:
16037       e->command = "dahdi show version";
16038       e->usage =
16039          "Usage: dahdi show version\n"
16040          "       Shows the DAHDI version in use\n";
16041       return NULL;
16042    case CLI_GENERATE:
16043       return NULL;
16044    }
16045    if ((pseudo_fd = open("/dev/dahdi/ctl", O_RDONLY)) < 0) {
16046       ast_cli(a->fd, "Failed to open control file to get version.\n");
16047       return CLI_SUCCESS;
16048    }
16049 
16050    strcpy(vi.version, "Unknown");
16051    strcpy(vi.echo_canceller, "Unknown");
16052 
16053    if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi))
16054       ast_cli(a->fd, "Failed to get DAHDI version: %s\n", strerror(errno));
16055    else
16056       ast_cli(a->fd, "DAHDI Version: %s Echo Canceller: %s\n", vi.version, vi.echo_canceller);
16057 
16058    close(pseudo_fd);
16059 
16060    return CLI_SUCCESS;
16061 }
16062 
16063 static char *dahdi_set_hwgain(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16064 {
16065    int channel;
16066    int gain;
16067    int tx;
16068    struct dahdi_hwgain hwgain;
16069    struct dahdi_pvt *tmp = NULL;
16070 
16071    switch (cmd) {
16072    case CLI_INIT:
16073       e->command = "dahdi set hwgain";
16074       e->usage =
16075          "Usage: dahdi set hwgain <rx|tx> <chan#> <gain>\n"
16076          "  Sets the hardware gain on a a given channel, overriding the\n"
16077          "   value provided at module loadtime, whether the channel is in\n"
16078          "   use or not.  Changes take effect immediately.\n"
16079          "   <rx|tx> which direction do you want to change (relative to our module)\n"
16080          "   <chan num> is the channel number relative to the device\n"
16081          "   <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
16082       return NULL;
16083    case CLI_GENERATE:
16084       return NULL;
16085    }
16086 
16087    if (a->argc != 6)
16088       return CLI_SHOWUSAGE;
16089 
16090    if (!strcasecmp("rx", a->argv[3]))
16091       tx = 0; /* rx */
16092    else if (!strcasecmp("tx", a->argv[3]))
16093       tx = 1; /* tx */
16094    else
16095       return CLI_SHOWUSAGE;
16096 
16097    channel = atoi(a->argv[4]);
16098    gain = atof(a->argv[5])*10.0;
16099 
16100    ast_mutex_lock(&iflock);
16101 
16102    for (tmp = iflist; tmp; tmp = tmp->next) {
16103 
16104       if (tmp->channel != channel)
16105          continue;
16106 
16107       if (tmp->subs[SUB_REAL].dfd == -1)
16108          break;
16109 
16110       hwgain.newgain = gain;
16111       hwgain.tx = tx;
16112       if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_HWGAIN, &hwgain) < 0) {
16113          ast_cli(a->fd, "Unable to set the hardware gain for channel %d: %s\n", channel, strerror(errno));
16114          ast_mutex_unlock(&iflock);
16115          return CLI_FAILURE;
16116       }
16117       ast_cli(a->fd, "hardware %s gain set to %d (%.1f dB) on channel %d\n",
16118          tx ? "tx" : "rx", gain, (float)gain/10.0, channel);
16119       break;
16120    }
16121 
16122    ast_mutex_unlock(&iflock);
16123 
16124    if (tmp)
16125       return CLI_SUCCESS;
16126 
16127    ast_cli(a->fd, "Unable to find given channel %d\n", channel);
16128    return CLI_FAILURE;
16129 
16130 }
16131 
16132 static char *dahdi_set_swgain(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16133 {
16134    int channel;
16135    float gain;
16136    int tx;
16137    int res;
16138    ast_mutex_t *lock;
16139    struct dahdi_pvt *tmp = NULL;
16140 
16141    switch (cmd) {
16142    case CLI_INIT:
16143       e->command = "dahdi set swgain";
16144       e->usage =
16145          "Usage: dahdi set swgain <rx|tx> <chan#> <gain>\n"
16146          "  Sets the software gain on a a given channel, overriding the\n"
16147          "   value provided at module loadtime, whether the channel is in\n"
16148          "   use or not.  Changes take effect immediately.\n"
16149          "   <rx|tx> which direction do you want to change (relative to our module)\n"
16150          "   <chan num> is the channel number relative to the device\n"
16151          "   <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
16152       return NULL;
16153    case CLI_GENERATE:
16154       return NULL;
16155    }
16156 
16157    lock = &iflock;
16158 
16159    if (a->argc != 6)
16160       return CLI_SHOWUSAGE;
16161 
16162    if (!strcasecmp("rx", a->argv[3]))
16163       tx = 0; /* rx */
16164    else if (!strcasecmp("tx", a->argv[3]))
16165       tx = 1; /* tx */
16166    else
16167       return CLI_SHOWUSAGE;
16168 
16169    channel = atoi(a->argv[4]);
16170    gain = atof(a->argv[5]);
16171 
16172    ast_mutex_lock(lock);
16173    for (tmp = iflist; tmp; tmp = tmp->next) {
16174 
16175       if (tmp->channel != channel)
16176          continue;
16177 
16178       if (tmp->subs[SUB_REAL].dfd == -1)
16179          break;
16180 
16181       if (tx)
16182          res = set_actual_txgain(tmp->subs[SUB_REAL].dfd, channel, gain, tmp->law);
16183       else
16184          res = set_actual_rxgain(tmp->subs[SUB_REAL].dfd, channel, gain, tmp->law);
16185 
16186       if (res) {
16187          ast_cli(a->fd, "Unable to set the software gain for channel %d\n", channel);
16188          ast_mutex_unlock(lock);
16189          return CLI_FAILURE;
16190       }
16191 
16192       ast_cli(a->fd, "software %s gain set to %.1f on channel %d\n",
16193          tx ? "tx" : "rx", gain, channel);
16194       break;
16195    }
16196    ast_mutex_unlock(lock);
16197 
16198    if (tmp)
16199       return CLI_SUCCESS;
16200 
16201    ast_cli(a->fd, "Unable to find given channel %d\n", channel);
16202    return CLI_FAILURE;
16203 
16204 }
16205 
16206 static char *dahdi_set_dnd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16207 {
16208    int channel;
16209    int on;
16210    struct dahdi_pvt *dahdi_chan = NULL;
16211 
16212    switch (cmd) {
16213    case CLI_INIT:
16214       e->command = "dahdi set dnd";
16215       e->usage =
16216          "Usage: dahdi set dnd <chan#> <on|off>\n"
16217          "  Sets/resets DND (Do Not Disturb) mode on a channel.\n"
16218          "  Changes take effect immediately.\n"
16219          "  <chan num> is the channel number\n"
16220          "  <on|off> Enable or disable DND mode?\n"
16221          ;
16222       return NULL;
16223    case CLI_GENERATE:
16224       return NULL;
16225    }
16226 
16227    if (a->argc != 5)
16228       return CLI_SHOWUSAGE;
16229 
16230    if ((channel = atoi(a->argv[3])) <= 0) {
16231       ast_cli(a->fd, "Expected channel number, got '%s'\n", a->argv[3]);
16232       return CLI_SHOWUSAGE;
16233    }
16234 
16235    if (ast_true(a->argv[4]))
16236       on = 1;
16237    else if (ast_false(a->argv[4]))
16238       on = 0;
16239    else {
16240       ast_cli(a->fd, "Expected 'on' or 'off', got '%s'\n", a->argv[4]);
16241       return CLI_SHOWUSAGE;
16242    }
16243 
16244    ast_mutex_lock(&iflock);
16245    for (dahdi_chan = iflist; dahdi_chan; dahdi_chan = dahdi_chan->next) {
16246       if (dahdi_chan->channel != channel)
16247          continue;
16248 
16249       /* Found the channel. Actually set it */
16250       dahdi_dnd(dahdi_chan, on);
16251       break;
16252    }
16253    ast_mutex_unlock(&iflock);
16254 
16255    if (!dahdi_chan) {
16256       ast_cli(a->fd, "Unable to find given channel %d\n", channel);
16257       return CLI_FAILURE;
16258    }
16259 
16260    return CLI_SUCCESS;
16261 }
16262 
16263 static struct ast_cli_entry dahdi_cli[] = {
16264    AST_CLI_DEFINE(handle_dahdi_show_cadences, "List cadences"),
16265    AST_CLI_DEFINE(dahdi_show_channels, "Show active DAHDI channels"),
16266    AST_CLI_DEFINE(dahdi_show_channel, "Show information on a channel"),
16267    AST_CLI_DEFINE(dahdi_destroy_channel, "Destroy a channel"),
16268    AST_CLI_DEFINE(dahdi_restart_cmd, "Fully restart DAHDI channels"),
16269    AST_CLI_DEFINE(dahdi_show_status, "Show all DAHDI cards status"),
16270    AST_CLI_DEFINE(dahdi_show_version, "Show the DAHDI version in use"),
16271    AST_CLI_DEFINE(dahdi_set_hwgain, "Set hardware gain on a channel"),
16272    AST_CLI_DEFINE(dahdi_set_swgain, "Set software gain on a channel"),
16273    AST_CLI_DEFINE(dahdi_set_dnd, "Sets/resets DND (Do Not Disturb) mode on a channel"),
16274 };
16275 
16276 #define TRANSFER  0
16277 #define HANGUP    1
16278 
16279 static int dahdi_fake_event(struct dahdi_pvt *p, int mode)
16280 {
16281    if (p) {
16282       switch (mode) {
16283          case TRANSFER:
16284             p->fake_event = DAHDI_EVENT_WINKFLASH;
16285             break;
16286          case HANGUP:
16287             p->fake_event = DAHDI_EVENT_ONHOOK;
16288             break;
16289          default:
16290             ast_log(LOG_WARNING, "I don't know how to handle transfer event with this: %d on channel %s\n",mode, p->owner->name);
16291       }
16292    }
16293    return 0;
16294 }
16295 static struct dahdi_pvt *find_channel(int channel)
16296 {
16297    struct dahdi_pvt *p = iflist;
16298    while (p) {
16299       if (p->channel == channel) {
16300          break;
16301       }
16302       p = p->next;
16303    }
16304    return p;
16305 }
16306 
16307 static int action_dahdidndon(struct mansession *s, const struct message *m)
16308 {
16309    struct dahdi_pvt *p = NULL;
16310    const char *channel = astman_get_header(m, "DAHDIChannel");
16311 
16312    if (ast_strlen_zero(channel)) {
16313       astman_send_error(s, m, "No channel specified");
16314       return 0;
16315    }
16316    p = find_channel(atoi(channel));
16317    if (!p) {
16318       astman_send_error(s, m, "No such channel");
16319       return 0;
16320    }
16321    p->dnd = 1;
16322    astman_send_ack(s, m, "DND Enabled");
16323    return 0;
16324 }
16325 
16326 static int action_dahdidndoff(struct mansession *s, const struct message *m)
16327 {
16328    struct dahdi_pvt *p = NULL;
16329    const char *channel = astman_get_header(m, "DAHDIChannel");
16330 
16331    if (ast_strlen_zero(channel)) {
16332       astman_send_error(s, m, "No channel specified");
16333       return 0;
16334    }
16335    p = find_channel(atoi(channel));
16336    if (!p) {
16337       astman_send_error(s, m, "No such channel");
16338       return 0;
16339    }
16340    p->dnd = 0;
16341    astman_send_ack(s, m, "DND Disabled");
16342    return 0;
16343 }
16344 
16345 static int action_transfer(struct mansession *s, const struct message *m)
16346 {
16347    struct dahdi_pvt *p = NULL;
16348    const char *channel = astman_get_header(m, "DAHDIChannel");
16349 
16350    if (ast_strlen_zero(channel)) {
16351       astman_send_error(s, m, "No channel specified");
16352       return 0;
16353    }
16354    p = find_channel(atoi(channel));
16355    if (!p) {
16356       astman_send_error(s, m, "No such channel");
16357       return 0;
16358    }
16359    dahdi_fake_event(p,TRANSFER);
16360    astman_send_ack(s, m, "DAHDITransfer");
16361    return 0;
16362 }
16363 
16364 static int action_transferhangup(struct mansession *s, const struct message *m)
16365 {
16366    struct dahdi_pvt *p = NULL;
16367    const char *channel = astman_get_header(m, "DAHDIChannel");
16368 
16369    if (ast_strlen_zero(channel)) {
16370       astman_send_error(s, m, "No channel specified");
16371       return 0;
16372    }
16373    p = find_channel(atoi(channel));
16374    if (!p) {
16375       astman_send_error(s, m, "No such channel");
16376       return 0;
16377    }
16378    dahdi_fake_event(p,HANGUP);
16379    astman_send_ack(s, m, "DAHDIHangup");
16380    return 0;
16381 }
16382 
16383 static int action_dahdidialoffhook(struct mansession *s, const struct message *m)
16384 {
16385    struct dahdi_pvt *p = NULL;
16386    const char *channel = astman_get_header(m, "DAHDIChannel");
16387    const char *number = astman_get_header(m, "Number");
16388    int i;
16389 
16390    if (ast_strlen_zero(channel)) {
16391       astman_send_error(s, m, "No channel specified");
16392       return 0;
16393    }
16394    if (ast_strlen_zero(number)) {
16395       astman_send_error(s, m, "No number specified");
16396       return 0;
16397    }
16398    p = find_channel(atoi(channel));
16399    if (!p) {
16400       astman_send_error(s, m, "No such channel");
16401       return 0;
16402    }
16403    if (!p->owner) {
16404       astman_send_error(s, m, "Channel does not have it's owner");
16405       return 0;
16406    }
16407    for (i = 0; i < strlen(number); i++) {
16408       struct ast_frame f = { AST_FRAME_DTMF, number[i] };
16409       dahdi_queue_frame(p, &f, NULL);
16410    }
16411    astman_send_ack(s, m, "DAHDIDialOffhook");
16412    return 0;
16413 }
16414 
16415 static int action_dahdishowchannels(struct mansession *s, const struct message *m)
16416 {
16417    struct dahdi_pvt *tmp = NULL;
16418    const char *id = astman_get_header(m, "ActionID");
16419    const char *dahdichannel = astman_get_header(m, "DAHDIChannel");
16420    char idText[256] = "";
16421    int channels = 0;
16422    int dahdichanquery = -1;
16423    if (!ast_strlen_zero(dahdichannel)) {
16424       dahdichanquery = atoi(dahdichannel);
16425    }
16426 
16427    astman_send_ack(s, m, "DAHDI channel status will follow");
16428    if (!ast_strlen_zero(id))
16429       snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
16430 
16431    ast_mutex_lock(&iflock);
16432 
16433    tmp = iflist;
16434    while (tmp) {
16435       if (tmp->channel > 0) {
16436          int alm = get_alarms(tmp);
16437 
16438          /* If a specific channel is queried for, only deliver status for that channel */
16439          if (dahdichanquery > 0 && tmp->channel != dahdichanquery)
16440             continue;
16441 
16442          channels++;
16443          if (tmp->owner) {
16444             /* Add data if we have a current call */
16445             astman_append(s,
16446                "Event: DAHDIShowChannels\r\n"
16447                "DAHDIChannel: %d\r\n"
16448                "Channel: %s\r\n"
16449                "Uniqueid: %s\r\n"
16450                "AccountCode: %s\r\n"
16451                "Signalling: %s\r\n"
16452                "SignallingCode: %d\r\n"
16453                "Context: %s\r\n"
16454                "DND: %s\r\n"
16455                "Alarm: %s\r\n"
16456                "%s"
16457                "\r\n",
16458                tmp->channel,
16459                tmp->owner->name,
16460                tmp->owner->uniqueid,
16461                tmp->owner->accountcode,
16462                sig2str(tmp->sig),
16463                tmp->sig,
16464                tmp->context,
16465                tmp->dnd ? "Enabled" : "Disabled",
16466                alarm2str(alm), idText);
16467          } else {
16468             astman_append(s,
16469                "Event: DAHDIShowChannels\r\n"
16470                "DAHDIChannel: %d\r\n"
16471                "Signalling: %s\r\n"
16472                "SignallingCode: %d\r\n"
16473                "Context: %s\r\n"
16474                "DND: %s\r\n"
16475                "Alarm: %s\r\n"
16476                "%s"
16477                "\r\n",
16478                tmp->channel, sig2str(tmp->sig), tmp->sig,
16479                tmp->context,
16480                tmp->dnd ? "Enabled" : "Disabled",
16481                alarm2str(alm), idText);
16482          }
16483       }
16484 
16485       tmp = tmp->next;
16486    }
16487 
16488    ast_mutex_unlock(&iflock);
16489 
16490    astman_append(s,
16491       "Event: DAHDIShowChannelsComplete\r\n"
16492       "%s"
16493       "Items: %d\r\n"
16494       "\r\n",
16495       idText,
16496       channels);
16497    return 0;
16498 }
16499 
16500 #if defined(HAVE_SS7)
16501 static int linkset_addsigchan(int sigchan)
16502 {
16503    struct dahdi_ss7 *link;
16504    int res;
16505    int curfd;
16506    struct dahdi_params p;
16507    struct dahdi_bufferinfo bi;
16508    struct dahdi_spaninfo si;
16509 
16510 
16511    link = ss7_resolve_linkset(cur_linkset);
16512    if (!link) {
16513       ast_log(LOG_ERROR, "Invalid linkset number.  Must be between 1 and %d\n", NUM_SPANS + 1);
16514       return -1;
16515    }
16516 
16517    if (cur_ss7type < 0) {
16518       ast_log(LOG_ERROR, "Unspecified or invalid ss7type\n");
16519       return -1;
16520    }
16521 
16522    if (!link->ss7)
16523       link->ss7 = ss7_new(cur_ss7type);
16524 
16525    if (!link->ss7) {
16526       ast_log(LOG_ERROR, "Can't create new SS7!\n");
16527       return -1;
16528    }
16529 
16530    link->type = cur_ss7type;
16531 
16532    if (cur_pointcode < 0) {
16533       ast_log(LOG_ERROR, "Unspecified pointcode!\n");
16534       return -1;
16535    } else
16536       ss7_set_pc(link->ss7, cur_pointcode);
16537 
16538    if (sigchan < 0) {
16539       ast_log(LOG_ERROR, "Invalid sigchan!\n");
16540       return -1;
16541    } else {
16542       if (link->numsigchans >= NUM_DCHANS) {
16543          ast_log(LOG_ERROR, "Too many sigchans on linkset %d\n", cur_linkset);
16544          return -1;
16545       }
16546       curfd = link->numsigchans;
16547 
16548       link->fds[curfd] = open("/dev/dahdi/channel", O_RDWR, 0600);
16549       if ((link->fds[curfd] < 0) || (ioctl(link->fds[curfd],DAHDI_SPECIFY,&sigchan) == -1)) {
16550          ast_log(LOG_ERROR, "Unable to open SS7 sigchan %d (%s)\n", sigchan, strerror(errno));
16551          return -1;
16552       }
16553       memset(&p, 0, sizeof(p));
16554       res = ioctl(link->fds[curfd], DAHDI_GET_PARAMS, &p);
16555       if (res) {
16556          dahdi_close_ss7_fd(link, curfd);
16557          ast_log(LOG_ERROR, "Unable to get parameters for sigchan %d (%s)\n", sigchan, strerror(errno));
16558          return -1;
16559       }
16560       if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC) && (p.sigtype != DAHDI_SIG_MTP2)) {
16561          dahdi_close_ss7_fd(link, curfd);
16562          ast_log(LOG_ERROR, "sigchan %d is not in HDLC/FCS mode.\n", sigchan);
16563          return -1;
16564       }
16565 
16566       memset(&bi, 0, sizeof(bi));
16567       bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
16568       bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
16569       bi.numbufs = 32;
16570       bi.bufsize = 512;
16571 
16572       if (ioctl(link->fds[curfd], DAHDI_SET_BUFINFO, &bi)) {
16573          ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", sigchan, strerror(errno));
16574          dahdi_close_ss7_fd(link, curfd);
16575          return -1;
16576       }
16577 
16578       if (p.sigtype == DAHDI_SIG_MTP2)
16579          ss7_add_link(link->ss7, SS7_TRANSPORT_DAHDIMTP2, link->fds[curfd]);
16580       else
16581          ss7_add_link(link->ss7, SS7_TRANSPORT_DAHDIDCHAN, link->fds[curfd]);
16582 
16583       link->numsigchans++;
16584 
16585       memset(&si, 0, sizeof(si));
16586       res = ioctl(link->fds[curfd], DAHDI_SPANSTAT, &si);
16587       if (res) {
16588          dahdi_close_ss7_fd(link, curfd);
16589          ast_log(LOG_ERROR, "Unable to get span state for sigchan %d (%s)\n", sigchan, strerror(errno));
16590       }
16591 
16592       if (!si.alarms) {
16593          link->linkstate[curfd] = LINKSTATE_DOWN;
16594          ss7_link_noalarm(link->ss7, link->fds[curfd]);
16595       } else {
16596          link->linkstate[curfd] = LINKSTATE_DOWN | LINKSTATE_INALARM;
16597          ss7_link_alarm(link->ss7, link->fds[curfd]);
16598       }
16599    }
16600 
16601    if (cur_adjpointcode < 0) {
16602       ast_log(LOG_ERROR, "Unspecified adjpointcode!\n");
16603       return -1;
16604    } else {
16605       ss7_set_adjpc(link->ss7, link->fds[curfd], cur_adjpointcode);
16606    }
16607 
16608    if (cur_defaultdpc < 0) {
16609       ast_log(LOG_ERROR, "Unspecified defaultdpc!\n");
16610       return -1;
16611    }
16612 
16613    if (cur_networkindicator < 0) {
16614       ast_log(LOG_ERROR, "Invalid networkindicator!\n");
16615       return -1;
16616    } else
16617       ss7_set_network_ind(link->ss7, cur_networkindicator);
16618 
16619    return 0;
16620 }
16621 #endif   /* defined(HAVE_SS7) */
16622 
16623 #if defined(HAVE_SS7)
16624 static char *handle_ss7_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16625 {
16626    int span;
16627    switch (cmd) {
16628    case CLI_INIT:
16629       e->command = "ss7 set debug {on|off} linkset";
16630       e->usage =
16631          "Usage: ss7 set debug {on|off} linkset <linkset>\n"
16632          "       Enables debugging on a given SS7 linkset\n";
16633       return NULL;
16634    case CLI_GENERATE:
16635       return NULL;
16636    }
16637    if (a->argc < 6)
16638       return CLI_SHOWUSAGE;
16639    span = atoi(a->argv[5]);
16640    if ((span < 1) || (span > NUM_SPANS)) {
16641       ast_cli(a->fd, "Invalid linkset %s.  Should be a number from %d to %d\n", a->argv[5], 1, NUM_SPANS);
16642       return CLI_SUCCESS;
16643    }
16644    if (!linksets[span-1].ss7) {
16645       ast_cli(a->fd, "No SS7 running on linkset %d\n", span);
16646       return CLI_SUCCESS;
16647    }
16648    if (linksets[span-1].ss7) {
16649       if (!strcasecmp(a->argv[3], "on")) {
16650          ss7_set_debug(linksets[span-1].ss7, SS7_DEBUG_MTP2 | SS7_DEBUG_MTP3 | SS7_DEBUG_ISUP);
16651          ast_cli(a->fd, "Enabled debugging on linkset %d\n", span);
16652       } else {
16653          ss7_set_debug(linksets[span-1].ss7, 0);
16654          ast_cli(a->fd, "Disabled debugging on linkset %d\n", span);
16655       }
16656    }
16657 
16658    return CLI_SUCCESS;
16659 }
16660 #endif   /* defined(HAVE_SS7) */
16661 
16662 #if defined(HAVE_SS7)
16663 static char *handle_ss7_block_cic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16664 {
16665    int linkset, cic;
16666    int blocked = -1, i;
16667    switch (cmd) {
16668    case CLI_INIT:
16669       e->command = "ss7 block cic";
16670       e->usage =
16671          "Usage: ss7 block cic <linkset> <CIC>\n"
16672          "       Sends a remote blocking request for the given CIC on the specified linkset\n";
16673       return NULL;
16674    case CLI_GENERATE:
16675       return NULL;
16676    }
16677    if (a->argc == 5)
16678       linkset = atoi(a->argv[3]);
16679    else
16680       return CLI_SHOWUSAGE;
16681 
16682    if ((linkset < 1) || (linkset > NUM_SPANS)) {
16683       ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16684       return CLI_SUCCESS;
16685    }
16686 
16687    if (!linksets[linkset-1].ss7) {
16688       ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16689       return CLI_SUCCESS;
16690    }
16691 
16692    cic = atoi(a->argv[4]);
16693 
16694    if (cic < 1) {
16695       ast_cli(a->fd, "Invalid CIC specified!\n");
16696       return CLI_SUCCESS;
16697    }
16698 
16699    for (i = 0; i < linksets[linkset-1].numchans; i++) {
16700       if (linksets[linkset-1].pvts[i]->cic == cic) {
16701          blocked = linksets[linkset-1].pvts[i]->locallyblocked;
16702          if (!blocked) {
16703             ast_mutex_lock(&linksets[linkset-1].lock);
16704             isup_blo(linksets[linkset-1].ss7, cic, linksets[linkset-1].pvts[i]->dpc);
16705             ast_mutex_unlock(&linksets[linkset-1].lock);
16706          }
16707       }
16708    }
16709 
16710    if (blocked < 0) {
16711       ast_cli(a->fd, "Invalid CIC specified!\n");
16712       return CLI_SUCCESS;
16713    }
16714 
16715    if (!blocked)
16716       ast_cli(a->fd, "Sent blocking request for linkset %d on CIC %d\n", linkset, cic);
16717    else
16718       ast_cli(a->fd, "CIC %d already locally blocked\n", cic);
16719 
16720    /* Break poll on the linkset so it sends our messages */
16721    pthread_kill(linksets[linkset-1].master, SIGURG);
16722 
16723    return CLI_SUCCESS;
16724 }
16725 #endif   /* defined(HAVE_SS7) */
16726 
16727 #if defined(HAVE_SS7)
16728 static char *handle_ss7_block_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16729 {
16730    int linkset;
16731    int i;
16732    switch (cmd) {
16733    case CLI_INIT:
16734       e->command = "ss7 block linkset";
16735       e->usage =
16736          "Usage: ss7 block linkset <linkset number>\n"
16737          "       Sends a remote blocking request for all CICs on the given linkset\n";
16738       return NULL;
16739    case CLI_GENERATE:
16740       return NULL;
16741    }
16742    if (a->argc == 4)
16743       linkset = atoi(a->argv[3]);
16744    else
16745       return CLI_SHOWUSAGE;
16746 
16747    if ((linkset < 1) || (linkset > NUM_SPANS)) {
16748       ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16749       return CLI_SUCCESS;
16750    }
16751 
16752    if (!linksets[linkset-1].ss7) {
16753       ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16754       return CLI_SUCCESS;
16755    }
16756 
16757    for (i = 0; i < linksets[linkset-1].numchans; i++) {
16758       ast_cli(a->fd, "Sending remote blocking request on CIC %d\n", linksets[linkset-1].pvts[i]->cic);
16759       ast_mutex_lock(&linksets[linkset-1].lock);
16760       isup_blo(linksets[linkset-1].ss7, linksets[linkset-1].pvts[i]->cic, linksets[linkset-1].pvts[i]->dpc);
16761       ast_mutex_unlock(&linksets[linkset-1].lock);
16762    }
16763 
16764    /* Break poll on the linkset so it sends our messages */
16765    pthread_kill(linksets[linkset-1].master, SIGURG);
16766 
16767    return CLI_SUCCESS;
16768 }
16769 #endif   /* defined(HAVE_SS7) */
16770 
16771 #if defined(HAVE_SS7)
16772 static char *handle_ss7_unblock_cic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16773 {
16774    int linkset, cic;
16775    int i, blocked = -1;
16776    switch (cmd) {
16777    case CLI_INIT:
16778       e->command = "ss7 unblock cic";
16779       e->usage =
16780          "Usage: ss7 unblock cic <linkset> <CIC>\n"
16781          "       Sends a remote unblocking request for the given CIC on the specified linkset\n";
16782       return NULL;
16783    case CLI_GENERATE:
16784       return NULL;
16785    }
16786 
16787    if (a->argc == 5)
16788       linkset = atoi(a->argv[3]);
16789    else
16790       return CLI_SHOWUSAGE;
16791 
16792    if ((linkset < 1) || (linkset > NUM_SPANS)) {
16793       ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16794       return CLI_SUCCESS;
16795    }
16796 
16797    if (!linksets[linkset-1].ss7) {
16798       ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16799       return CLI_SUCCESS;
16800    }
16801 
16802    cic = atoi(a->argv[4]);
16803 
16804    if (cic < 1) {
16805       ast_cli(a->fd, "Invalid CIC specified!\n");
16806       return CLI_SUCCESS;
16807    }
16808 
16809    for (i = 0; i < linksets[linkset-1].numchans; i++) {
16810       if (linksets[linkset-1].pvts[i]->cic == cic) {
16811          blocked = linksets[linkset-1].pvts[i]->locallyblocked;
16812          if (blocked) {
16813             ast_mutex_lock(&linksets[linkset-1].lock);
16814             isup_ubl(linksets[linkset-1].ss7, cic, linksets[linkset-1].pvts[i]->dpc);
16815             ast_mutex_unlock(&linksets[linkset-1].lock);
16816          }
16817       }
16818    }
16819 
16820    if (blocked > 0)
16821       ast_cli(a->fd, "Sent unblocking request for linkset %d on CIC %d\n", linkset, cic);
16822 
16823    /* Break poll on the linkset so it sends our messages */
16824    pthread_kill(linksets[linkset-1].master, SIGURG);
16825 
16826    return CLI_SUCCESS;
16827 }
16828 #endif   /* defined(HAVE_SS7) */
16829 
16830 #if defined(HAVE_SS7)
16831 static char *handle_ss7_unblock_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16832 {
16833    int linkset;
16834    int i;
16835    switch (cmd) {
16836    case CLI_INIT:
16837       e->command = "ss7 unblock linkset";
16838       e->usage =
16839          "Usage: ss7 unblock linkset <linkset number>\n"
16840          "       Sends a remote unblocking request for all CICs on the specified linkset\n";
16841       return NULL;
16842    case CLI_GENERATE:
16843       return NULL;
16844    }
16845 
16846    if (a->argc == 4)
16847       linkset = atoi(a->argv[3]);
16848    else
16849       return CLI_SHOWUSAGE;
16850 
16851    if ((linkset < 1) || (linkset > NUM_SPANS)) {
16852       ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16853       return CLI_SUCCESS;
16854    }
16855 
16856    if (!linksets[linkset-1].ss7) {
16857       ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16858       return CLI_SUCCESS;
16859    }
16860 
16861    for (i = 0; i < linksets[linkset-1].numchans; i++) {
16862       ast_cli(a->fd, "Sending remote unblock request on CIC %d\n", linksets[linkset-1].pvts[i]->cic);
16863       ast_mutex_lock(&linksets[linkset-1].lock);
16864       isup_ubl(linksets[linkset-1].ss7, linksets[linkset-1].pvts[i]->cic, linksets[linkset-1].pvts[i]->dpc);
16865       ast_mutex_unlock(&linksets[linkset-1].lock);
16866    }
16867 
16868    /* Break poll on the linkset so it sends our messages */
16869    pthread_kill(linksets[linkset-1].master, SIGURG);
16870 
16871    return CLI_SUCCESS;
16872 }
16873 #endif   /* defined(HAVE_SS7) */
16874 
16875 #if defined(HAVE_SS7)
16876 static char *handle_ss7_show_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16877 {
16878    int linkset;
16879    struct dahdi_ss7 *ss7;
16880    switch (cmd) {
16881    case CLI_INIT:
16882       e->command = "ss7 show linkset";
16883       e->usage =
16884          "Usage: ss7 show linkset <span>\n"
16885          "       Shows the status of an SS7 linkset.\n";
16886       return NULL;
16887    case CLI_GENERATE:
16888       return NULL;
16889    }
16890 
16891    if (a->argc < 4)
16892       return CLI_SHOWUSAGE;
16893    linkset = atoi(a->argv[3]);
16894    if ((linkset < 1) || (linkset > NUM_SPANS)) {
16895       ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16896       return CLI_SUCCESS;
16897    }
16898    if (!linksets[linkset-1].ss7) {
16899       ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16900       return CLI_SUCCESS;
16901    }
16902    if (linksets[linkset-1].ss7)
16903       ss7 = &linksets[linkset-1];
16904 
16905    ast_cli(a->fd, "SS7 linkset %d status: %s\n", linkset, (ss7->state == LINKSET_STATE_UP) ? "Up" : "Down");
16906 
16907    return CLI_SUCCESS;
16908 }
16909 #endif   /* defined(HAVE_SS7) */
16910 
16911 #if defined(HAVE_SS7)
16912 static char *handle_ss7_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16913 {
16914    switch (cmd) {
16915    case CLI_INIT:
16916       e->command = "ss7 show version";
16917       e->usage =
16918          "Usage: ss7 show version\n"
16919          "  Show the libss7 version\n";
16920       return NULL;
16921    case CLI_GENERATE:
16922       return NULL;
16923    }
16924 
16925    ast_cli(a->fd, "libss7 version: %s\n", ss7_get_version());
16926 
16927    return CLI_SUCCESS;
16928 }
16929 #endif   /* defined(HAVE_SS7) */
16930 
16931 #if defined(HAVE_SS7)
16932 static struct ast_cli_entry dahdi_ss7_cli[] = {
16933    AST_CLI_DEFINE(handle_ss7_debug, "Enables SS7 debugging on a linkset"),
16934    AST_CLI_DEFINE(handle_ss7_block_cic, "Blocks the given CIC"),
16935    AST_CLI_DEFINE(handle_ss7_unblock_cic, "Unblocks the given CIC"),
16936    AST_CLI_DEFINE(handle_ss7_block_linkset, "Blocks all CICs on a linkset"),
16937    AST_CLI_DEFINE(handle_ss7_unblock_linkset, "Unblocks all CICs on a linkset"),
16938    AST_CLI_DEFINE(handle_ss7_show_linkset, "Shows the status of a linkset"),
16939    AST_CLI_DEFINE(handle_ss7_version, "Displays libss7 version"),
16940 };
16941 #endif   /* defined(HAVE_SS7) */
16942 
16943 static int __unload_module(void)
16944 {
16945    struct dahdi_pvt *p;
16946 #if defined(HAVE_PRI) || defined(HAVE_SS7)
16947    int i, j;
16948 #endif
16949 
16950 #ifdef HAVE_PRI
16951    for (i = 0; i < NUM_SPANS; i++) {
16952       if (pris[i].master != AST_PTHREADT_NULL)
16953          pthread_cancel(pris[i].master);
16954    }
16955    ast_cli_unregister_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
16956    ast_unregister_application(dahdi_send_keypad_facility_app);
16957 #ifdef HAVE_PRI_PROG_W_CAUSE
16958    ast_unregister_application(dahdi_send_callrerouting_facility_app);
16959 #endif
16960 #endif
16961 #if defined(HAVE_SS7)
16962    for (i = 0; i < NUM_SPANS; i++) {
16963       if (linksets[i].master != AST_PTHREADT_NULL)
16964          pthread_cancel(linksets[i].master);
16965       }
16966    ast_cli_unregister_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
16967 #endif
16968 #if defined(HAVE_OPENR2)
16969    dahdi_r2_destroy_links();
16970    ast_cli_unregister_multiple(dahdi_mfcr2_cli, ARRAY_LEN(dahdi_mfcr2_cli));
16971    ast_unregister_application(dahdi_accept_r2_call_app);
16972 #endif
16973 
16974    ast_cli_unregister_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli));
16975    ast_manager_unregister( "DAHDIDialOffhook" );
16976    ast_manager_unregister( "DAHDIHangup" );
16977    ast_manager_unregister( "DAHDITransfer" );
16978    ast_manager_unregister( "DAHDIDNDoff" );
16979    ast_manager_unregister( "DAHDIDNDon" );
16980    ast_manager_unregister("DAHDIShowChannels");
16981    ast_manager_unregister("DAHDIRestart");
16982    ast_channel_unregister(&dahdi_tech);
16983    ast_mutex_lock(&iflock);
16984    /* Hangup all interfaces if they have an owner */
16985    p = iflist;
16986    while (p) {
16987       if (p->owner)
16988          ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
16989       p = p->next;
16990    }
16991    ast_mutex_unlock(&iflock);
16992    ast_mutex_lock(&monlock);
16993    if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
16994       pthread_cancel(monitor_thread);
16995       pthread_kill(monitor_thread, SIGURG);
16996       pthread_join(monitor_thread, NULL);
16997    }
16998    monitor_thread = AST_PTHREADT_STOP;
16999    ast_mutex_unlock(&monlock);
17000 
17001    destroy_all_channels();
17002 
17003 #if defined(HAVE_PRI)
17004    for (i = 0; i < NUM_SPANS; i++) {
17005       if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL))
17006          pthread_join(pris[i].master, NULL);
17007       for (j = 0; j < NUM_DCHANS; j++) {
17008          dahdi_close_pri_fd(&(pris[i]), j);
17009       }
17010    }
17011 #endif
17012 
17013 #if defined(HAVE_SS7)
17014    for (i = 0; i < NUM_SPANS; i++) {
17015       if (linksets[i].master && (linksets[i].master != AST_PTHREADT_NULL))
17016          pthread_join(linksets[i].master, NULL);
17017       for (j = 0; j < NUM_DCHANS; j++) {
17018          dahdi_close_ss7_fd(&(linksets[i]), j);
17019       }
17020    }
17021 #endif
17022    ast_cond_destroy(&ss_thread_complete);
17023    return 0;
17024 }
17025 
17026 static int unload_module(void)
17027 {
17028 #if defined(HAVE_PRI) || defined(HAVE_SS7)
17029    int y;
17030 #endif
17031 #ifdef HAVE_PRI
17032    for (y = 0; y < NUM_SPANS; y++)
17033       ast_mutex_destroy(&pris[y].lock);
17034 #endif
17035 #ifdef HAVE_SS7
17036    for (y = 0; y < NUM_SPANS; y++)
17037       ast_mutex_destroy(&linksets[y].lock);
17038 #endif /* HAVE_SS7 */
17039    return __unload_module();
17040 }
17041 
17042 static int build_channels(struct dahdi_chan_conf *conf, int iscrv, const char *value, int reload, int lineno, int *found_pseudo)
17043 {
17044    char *c, *chan;
17045    int x, start, finish;
17046    struct dahdi_pvt *tmp;
17047 #ifdef HAVE_PRI
17048    struct dahdi_pri *pri;
17049    int trunkgroup, y;
17050 #endif
17051 
17052    if ((reload == 0) && (conf->chan.sig < 0) && !conf->is_sig_auto) {
17053       ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n");
17054       return -1;
17055    }
17056 
17057    c = ast_strdupa(value);
17058 
17059 #ifdef HAVE_PRI
17060    pri = NULL;
17061    if (iscrv) {
17062       if (sscanf(c, "%30d:%n", &trunkgroup, &y) != 1) {
17063          ast_log(LOG_WARNING, "CRV must begin with trunkgroup followed by a colon at line %d.\n", lineno);
17064          return -1;
17065       }
17066       if (trunkgroup < 1) {
17067          ast_log(LOG_WARNING, "CRV trunk group must be a positive number at line %d.\n", lineno);
17068          return -1;
17069       }
17070       c += y;
17071       for (y = 0; y < NUM_SPANS; y++) {
17072          if (pris[y].trunkgroup == trunkgroup) {
17073             pri = pris + y;
17074             break;
17075          }
17076       }
17077       if (!pri) {
17078          ast_log(LOG_WARNING, "No such trunk group %d at CRV declaration at line %d.\n", trunkgroup, lineno);
17079          return -1;
17080       }
17081    }
17082 #endif
17083 
17084    while ((chan = strsep(&c, ","))) {
17085       if (sscanf(chan, "%30d-%30d", &start, &finish) == 2) {
17086          /* Range */
17087       } else if (sscanf(chan, "%30d", &start)) {
17088          /* Just one */
17089          finish = start;
17090       } else if (!strcasecmp(chan, "pseudo")) {
17091          finish = start = CHAN_PSEUDO;
17092          if (found_pseudo)
17093             *found_pseudo = 1;
17094       } else {
17095          ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan);
17096          return -1;
17097       }
17098       if (finish < start) {
17099          ast_log(LOG_WARNING, "Sillyness: %d < %d\n", start, finish);
17100          x = finish;
17101          finish = start;
17102          start = x;
17103       }
17104 
17105       for (x = start; x <= finish; x++) {
17106 #ifdef HAVE_PRI
17107          tmp = mkintf(x, conf, pri, reload);
17108 #else
17109          tmp = mkintf(x, conf, NULL, reload);
17110 #endif
17111 
17112          if (tmp) {
17113 #ifdef HAVE_PRI
17114             if (pri)
17115                ast_verb(3, "%s CRV %d:%d, %s signalling\n", reload ? "Reconfigured" : "Registered", trunkgroup, x, sig2str(tmp->sig));
17116             else
17117 #endif
17118                ast_verb(3, "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", x, sig2str(tmp->sig));
17119          } else {
17120             ast_log(LOG_ERROR, "Unable to %s channel '%s'\n",
17121                (reload == 1) ? "reconfigure" : "register", value);
17122             return -1;
17123          }
17124       }
17125    }
17126 
17127    return 0;
17128 }
17129 
17130 /** The length of the parameters list of 'dahdichan'.
17131  * \todo Move definition of MAX_CHANLIST_LEN to a proper place. */
17132 #define MAX_CHANLIST_LEN 80
17133 
17134 static void process_echocancel(struct dahdi_chan_conf *confp, const char *data, unsigned int line)
17135 {
17136    char *parse = ast_strdupa(data);
17137    char *params[DAHDI_MAX_ECHOCANPARAMS + 1];
17138    unsigned int param_count;
17139    unsigned int x;
17140 
17141    if (!(param_count = ast_app_separate_args(parse, ',', params, ARRAY_LEN(params))))
17142       return;
17143 
17144    memset(&confp->chan.echocancel, 0, sizeof(confp->chan.echocancel));
17145 
17146    /* first parameter is tap length, process it here */
17147 
17148    x = ast_strlen_zero(params[0]) ? 0 : atoi(params[0]);
17149 
17150    if ((x == 32) || (x == 64) || (x == 128) || (x == 256) || (x == 512) || (x == 1024))
17151       confp->chan.echocancel.head.tap_length = x;
17152    else if ((confp->chan.echocancel.head.tap_length = ast_true(params[0])))
17153       confp->chan.echocancel.head.tap_length = 128;
17154 
17155    /* now process any remaining parameters */
17156 
17157    for (x = 1; x < param_count; x++) {
17158       struct {
17159          char *name;
17160          char *value;
17161       } param;
17162 
17163       if (ast_app_separate_args(params[x], '=', (char **) &param, 2) < 1) {
17164          ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, params[x]);
17165          continue;
17166       }
17167 
17168       if (ast_strlen_zero(param.name) || (strlen(param.name) > sizeof(confp->chan.echocancel.params[0].name)-1)) {
17169          ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, param.name);
17170          continue;
17171       }
17172 
17173       strcpy(confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].name, param.name);
17174 
17175       if (param.value) {
17176          if (sscanf(param.value, "%30d", &confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].value) != 1) {
17177             ast_log(LOG_WARNING, "Invalid echocancel parameter value supplied at line %d: '%s'\n", line, param.value);
17178             continue;
17179          }
17180       }
17181       confp->chan.echocancel.head.param_count++;
17182    }
17183 }
17184 
17185 /*! process_dahdi() - ignore keyword 'channel' and similar */
17186 #define PROC_DAHDI_OPT_NOCHAN  (1 << 0)
17187 /*! process_dahdi() - No warnings on non-existing cofiguration keywords */
17188 #define PROC_DAHDI_OPT_NOWARN  (1 << 1)
17189 
17190 static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct ast_variable *v, int reload, int options)
17191 {
17192    struct dahdi_pvt *tmp;
17193    int y;
17194    int found_pseudo = 0;
17195    char dahdichan[MAX_CHANLIST_LEN] = {};
17196 
17197    for (; v; v = v->next) {
17198       if (!ast_jb_read_conf(&global_jbconf, v->name, v->value))
17199          continue;
17200 
17201       /* must have parkinglot in confp before build_channels is called */
17202       if (!strcasecmp(v->name, "parkinglot")) {
17203          ast_copy_string(confp->chan.parkinglot, v->value, sizeof(confp->chan.parkinglot));
17204       }
17205 
17206       /* Create the interface list */
17207       if (!strcasecmp(v->name, "channel")
17208 #ifdef HAVE_PRI
17209          || !strcasecmp(v->name, "crv")
17210 #endif
17211          ) {
17212          int iscrv;
17213          if (options & PROC_DAHDI_OPT_NOCHAN) {
17214             ast_log(LOG_WARNING, "Channel '%s' ignored.\n", v->value);
17215             continue;
17216          }
17217          iscrv = !strcasecmp(v->name, "crv");
17218          if (build_channels(confp, iscrv, v->value, reload, v->lineno, &found_pseudo))
17219                return -1;
17220          ast_log(LOG_DEBUG, "Channel '%s' configured.\n", v->value);
17221       } else if (!strcasecmp(v->name, "buffers")) {
17222          if (parse_buffers_policy(v->value, &confp->chan.buf_no, &confp->chan.buf_policy)) {
17223             ast_log(LOG_WARNING, "Using default buffer policy.\n");
17224             confp->chan.buf_no = numbufs;
17225             confp->chan.buf_policy = DAHDI_POLICY_IMMEDIATE;
17226          }
17227       } else if (!strcasecmp(v->name, "faxbuffers")) {
17228          if (!parse_buffers_policy(v->value, &confp->chan.faxbuf_no, &confp->chan.faxbuf_policy)) {
17229             confp->chan.usefaxbuffers = 1;
17230          }
17231       } else if (!strcasecmp(v->name, "dahdichan")) {
17232          ast_copy_string(dahdichan, v->value, sizeof(dahdichan));
17233       } else if (!strcasecmp(v->name, "usedistinctiveringdetection")) {
17234          usedistinctiveringdetection = ast_true(v->value);
17235       } else if (!strcasecmp(v->name, "distinctiveringaftercid")) {
17236          distinctiveringaftercid = ast_true(v->value);
17237       } else if (!strcasecmp(v->name, "dring1context")) {
17238          ast_copy_string(confp->chan.drings.ringContext[0].contextData,v->value,sizeof(confp->chan.drings.ringContext[0].contextData));
17239       } else if (!strcasecmp(v->name, "dring2context")) {
17240          ast_copy_string(confp->chan.drings.ringContext[1].contextData,v->value,sizeof(confp->chan.drings.ringContext[1].contextData));
17241       } else if (!strcasecmp(v->name, "dring3context")) {
17242          ast_copy_string(confp->chan.drings.ringContext[2].contextData,v->value,sizeof(confp->chan.drings.ringContext[2].contextData));
17243       } else if (!strcasecmp(v->name, "dring1range")) {
17244          confp->chan.drings.ringnum[0].range = atoi(v->value);
17245       } else if (!strcasecmp(v->name, "dring2range")) {
17246          confp->chan.drings.ringnum[1].range = atoi(v->value);
17247       } else if (!strcasecmp(v->name, "dring3range")) {
17248          confp->chan.drings.ringnum[2].range = atoi(v->value);
17249       } else if (!strcasecmp(v->name, "dring1")) {
17250          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]);
17251       } else if (!strcasecmp(v->name, "dring2")) {
17252          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]);
17253       } else if (!strcasecmp(v->name, "dring3")) {
17254          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]);
17255       } else if (!strcasecmp(v->name, "usecallerid")) {
17256          confp->chan.use_callerid = ast_true(v->value);
17257       } else if (!strcasecmp(v->name, "cidsignalling")) {
17258          if (!strcasecmp(v->value, "bell"))
17259             confp->chan.cid_signalling = CID_SIG_BELL;
17260          else if (!strcasecmp(v->value, "v23"))
17261             confp->chan.cid_signalling = CID_SIG_V23;
17262          else if (!strcasecmp(v->value, "dtmf"))
17263             confp->chan.cid_signalling = CID_SIG_DTMF;
17264          else if (!strcasecmp(v->value, "smdi"))
17265             confp->chan.cid_signalling = CID_SIG_SMDI;
17266          else if (!strcasecmp(v->value, "v23_jp"))
17267             confp->chan.cid_signalling = CID_SIG_V23_JP;
17268          else if (ast_true(v->value))
17269             confp->chan.cid_signalling = CID_SIG_BELL;
17270       } else if (!strcasecmp(v->name, "cidstart")) {
17271          if (!strcasecmp(v->value, "ring"))
17272             confp->chan.cid_start = CID_START_RING;
17273          else if (!strcasecmp(v->value, "polarity_in"))
17274             confp->chan.cid_start = CID_START_POLARITY_IN;
17275          else if (!strcasecmp(v->value, "polarity"))
17276             confp->chan.cid_start = CID_START_POLARITY;
17277          else if (ast_true(v->value))
17278             confp->chan.cid_start = CID_START_RING;
17279       } else if (!strcasecmp(v->name, "threewaycalling")) {
17280          confp->chan.threewaycalling = ast_true(v->value);
17281       } else if (!strcasecmp(v->name, "cancallforward")) {
17282          confp->chan.cancallforward = ast_true(v->value);
17283       } else if (!strcasecmp(v->name, "relaxdtmf")) {
17284          if (ast_true(v->value))
17285             confp->chan.dtmfrelax = DSP_DIGITMODE_RELAXDTMF;
17286          else
17287             confp->chan.dtmfrelax = 0;
17288       } else if (!strcasecmp(v->name, "mailbox")) {
17289          ast_copy_string(confp->chan.mailbox, v->value, sizeof(confp->chan.mailbox));
17290       } else if (!strcasecmp(v->name, "hasvoicemail")) {
17291          if (ast_true(v->value) && ast_strlen_zero(confp->chan.mailbox)) {
17292             ast_copy_string(confp->chan.mailbox, cat, sizeof(confp->chan.mailbox));
17293          }
17294       } else if (!strcasecmp(v->name, "adsi")) {
17295          confp->chan.adsi = ast_true(v->value);
17296       } else if (!strcasecmp(v->name, "usesmdi")) {
17297          confp->chan.use_smdi = ast_true(v->value);
17298       } else if (!strcasecmp(v->name, "smdiport")) {
17299          ast_copy_string(confp->smdi_port, v->value, sizeof(confp->smdi_port));
17300       } else if (!strcasecmp(v->name, "transfer")) {
17301          confp->chan.transfer = ast_true(v->value);
17302       } else if (!strcasecmp(v->name, "canpark")) {
17303          confp->chan.canpark = ast_true(v->value);
17304       } else if (!strcasecmp(v->name, "echocancelwhenbridged")) {
17305          confp->chan.echocanbridged = ast_true(v->value);
17306       } else if (!strcasecmp(v->name, "busydetect")) {
17307          confp->chan.busydetect = ast_true(v->value);
17308       } else if (!strcasecmp(v->name, "busycount")) {
17309          confp->chan.busycount = atoi(v->value);
17310       } else if (!strcasecmp(v->name, "busypattern")) {
17311          if (sscanf(v->value, "%30d,%30d", &confp->chan.busy_tonelength, &confp->chan.busy_quietlength) != 2) {
17312             ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength,quietlength at line %d.\n", v->lineno);
17313          }
17314       } else if (!strcasecmp(v->name, "callprogress")) {
17315          confp->chan.callprogress &= ~CALLPROGRESS_PROGRESS;
17316          if (ast_true(v->value))
17317             confp->chan.callprogress |= CALLPROGRESS_PROGRESS;
17318       } else if (!strcasecmp(v->name, "waitfordialtone")) {
17319          confp->chan.waitfordialtone = atoi(v->value);
17320       } else if (!strcasecmp(v->name, "faxdetect")) {
17321          confp->chan.callprogress &= ~CALLPROGRESS_FAX;
17322          if (!strcasecmp(v->value, "incoming")) {
17323             confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING;
17324          } else if (!strcasecmp(v->value, "outgoing")) {
17325             confp->chan.callprogress |= CALLPROGRESS_FAX_OUTGOING;
17326          } else if (!strcasecmp(v->value, "both") || ast_true(v->value))
17327             confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING;
17328       } else if (!strcasecmp(v->name, "echocancel")) {
17329          process_echocancel(confp, v->value, v->lineno);
17330       } else if (!strcasecmp(v->name, "echotraining")) {
17331          if (sscanf(v->value, "%30d", &y) == 1) {
17332             if ((y < 10) || (y > 4000)) {
17333                ast_log(LOG_WARNING, "Echo training time must be within the range of 10 to 4000 ms at line %d.\n", v->lineno);
17334             } else {
17335                confp->chan.echotraining = y;
17336             }
17337          } else if (ast_true(v->value)) {
17338             confp->chan.echotraining = 400;
17339          } else
17340             confp->chan.echotraining = 0;
17341       } else if (!strcasecmp(v->name, "hidecallerid")) {
17342          confp->chan.hidecallerid = ast_true(v->value);
17343       } else if (!strcasecmp(v->name, "hidecalleridname")) {
17344          confp->chan.hidecalleridname = ast_true(v->value);
17345       } else if (!strcasecmp(v->name, "pulsedial")) {
17346          confp->chan.pulse = ast_true(v->value);
17347       } else if (!strcasecmp(v->name, "callreturn")) {
17348          confp->chan.callreturn = ast_true(v->value);
17349       } else if (!strcasecmp(v->name, "callwaiting")) {
17350          confp->chan.callwaiting = ast_true(v->value);
17351       } else if (!strcasecmp(v->name, "callwaitingcallerid")) {
17352          confp->chan.callwaitingcallerid = ast_true(v->value);
17353       } else if (!strcasecmp(v->name, "context")) {
17354          ast_copy_string(confp->chan.context, v->value, sizeof(confp->chan.context));
17355       } else if (!strcasecmp(v->name, "language")) {
17356          ast_copy_string(confp->chan.language, v->value, sizeof(confp->chan.language));
17357       } else if (!strcasecmp(v->name, "progzone")) {
17358          ast_copy_string(progzone, v->value, sizeof(progzone));
17359       } else if (!strcasecmp(v->name, "mohinterpret")
17360          ||!strcasecmp(v->name, "musiconhold") || !strcasecmp(v->name, "musicclass")) {
17361          ast_copy_string(confp->chan.mohinterpret, v->value, sizeof(confp->chan.mohinterpret));
17362       } else if (!strcasecmp(v->name, "mohsuggest")) {
17363          ast_copy_string(confp->chan.mohsuggest, v->value, sizeof(confp->chan.mohsuggest));
17364       } else if (!strcasecmp(v->name, "parkinglot")) {
17365          ast_copy_string(parkinglot, v->value, sizeof(parkinglot));
17366       } else if (!strcasecmp(v->name, "stripmsd")) {
17367          ast_log(LOG_NOTICE, "Configuration option \"%s\" has been deprecated. Please use dialplan instead\n", v->name);
17368          confp->chan.stripmsd = atoi(v->value);
17369       } else if (!strcasecmp(v->name, "jitterbuffers")) {
17370          numbufs = atoi(v->value);
17371       } else if (!strcasecmp(v->name, "group")) {
17372          confp->chan.group = ast_get_group(v->value);
17373       } else if (!strcasecmp(v->name, "callgroup")) {
17374          if (!strcasecmp(v->value, "none"))
17375             confp->chan.callgroup = 0;
17376          else
17377             confp->chan.callgroup = ast_get_group(v->value);
17378       } else if (!strcasecmp(v->name, "pickupgroup")) {
17379          if (!strcasecmp(v->value, "none"))
17380             confp->chan.pickupgroup = 0;
17381          else
17382             confp->chan.pickupgroup = ast_get_group(v->value);
17383       } else if (!strcasecmp(v->name, "setvar")) {
17384          char *varname = ast_strdupa(v->value), *varval = NULL;
17385          struct ast_variable *tmpvar;
17386          if (varname && (varval = strchr(varname, '='))) {
17387             *varval++ = '\0';
17388             if ((tmpvar = ast_variable_new(varname, varval, ""))) {
17389                tmpvar->next = confp->chan.vars;
17390                confp->chan.vars = tmpvar;
17391             }
17392          }
17393       } else if (!strcasecmp(v->name, "immediate")) {
17394          confp->chan.immediate = ast_true(v->value);
17395       } else if (!strcasecmp(v->name, "transfertobusy")) {
17396          confp->chan.transfertobusy = ast_true(v->value);
17397       } else if (!strcasecmp(v->name, "mwimonitor")) {
17398          confp->chan.mwimonitor_neon = 0;
17399          confp->chan.mwimonitor_fsk = 0;
17400          confp->chan.mwimonitor_rpas = 0;
17401          if (strcasestr(v->value, "fsk")) {
17402             confp->chan.mwimonitor_fsk = 1;
17403          }
17404          if (strcasestr(v->value, "rpas")) {
17405             confp->chan.mwimonitor_rpas = 1;
17406          }
17407          if (strcasestr(v->value, "neon")) {
17408             confp->chan.mwimonitor_neon = 1;
17409          }
17410          /* If set to true or yes, assume that simple fsk is desired */
17411          if (ast_true(v->value)) {
17412             confp->chan.mwimonitor_fsk = 1;
17413          }
17414       } else if (!strcasecmp(v->name, "cid_rxgain")) {
17415          if (sscanf(v->value, "%30f", &confp->chan.cid_rxgain) != 1) {
17416             ast_log(LOG_WARNING, "Invalid cid_rxgain: %s at line %d.\n", v->value, v->lineno);
17417          }
17418       } else if (!strcasecmp(v->name, "rxgain")) {
17419          if (sscanf(v->value, "%30f", &confp->chan.rxgain) != 1) {
17420             ast_log(LOG_WARNING, "Invalid rxgain: %s at line %d.\n", v->value, v->lineno);
17421          }
17422       } else if (!strcasecmp(v->name, "txgain")) {
17423          if (sscanf(v->value, "%30f", &confp->chan.txgain) != 1) {
17424             ast_log(LOG_WARNING, "Invalid txgain: %s at line %d.\n", v->value, v->lineno);
17425          }
17426       } else if (!strcasecmp(v->name, "tonezone")) {
17427          if (sscanf(v->value, "%30d", &confp->chan.tonezone) != 1) {
17428             ast_log(LOG_WARNING, "Invalid tonezone: %s at line %d.\n", v->value, v->lineno);
17429          }
17430       } else if (!strcasecmp(v->name, "callerid")) {
17431          if (!strcasecmp(v->value, "asreceived")) {
17432             confp->chan.cid_num[0] = '\0';
17433             confp->chan.cid_name[0] = '\0';
17434          } else {
17435             ast_callerid_split(v->value, confp->chan.cid_name, sizeof(confp->chan.cid_name), confp->chan.cid_num, sizeof(confp->chan.cid_num));
17436          }
17437       } else if (!strcasecmp(v->name, "fullname")) {
17438          ast_copy_string(confp->chan.cid_name, v->value, sizeof(confp->chan.cid_name));
17439       } else if (!strcasecmp(v->name, "cid_number")) {
17440          ast_copy_string(confp->chan.cid_num, v->value, sizeof(confp->chan.cid_num));
17441       } else if (!strcasecmp(v->name, "useincomingcalleridondahditransfer")) {
17442          confp->chan.dahditrcallerid = ast_true(v->value);
17443       } else if (!strcasecmp(v->name, "restrictcid")) {
17444          confp->chan.restrictcid = ast_true(v->value);
17445       } else if (!strcasecmp(v->name, "usecallingpres")) {
17446          confp->chan.use_callingpres = ast_true(v->value);
17447       } else if (!strcasecmp(v->name, "accountcode")) {
17448          ast_copy_string(confp->chan.accountcode, v->value, sizeof(confp->chan.accountcode));
17449       } else if (!strcasecmp(v->name, "amaflags")) {
17450          y = ast_cdr_amaflags2int(v->value);
17451          if (y < 0)
17452             ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d.\n", v->value, v->lineno);
17453          else
17454             confp->chan.amaflags = y;
17455       } else if (!strcasecmp(v->name, "polarityonanswerdelay")) {
17456          confp->chan.polarityonanswerdelay = atoi(v->value);
17457       } else if (!strcasecmp(v->name, "answeronpolarityswitch")) {
17458          confp->chan.answeronpolarityswitch = ast_true(v->value);
17459       } else if (!strcasecmp(v->name, "hanguponpolarityswitch")) {
17460          confp->chan.hanguponpolarityswitch = ast_true(v->value);
17461       } else if (!strcasecmp(v->name, "sendcalleridafter")) {
17462          confp->chan.sendcalleridafter = atoi(v->value);
17463       } else if (!strcasecmp(v->name, "mwimonitornotify")) {
17464          ast_copy_string(mwimonitornotify, v->value, sizeof(mwimonitornotify));
17465       } else if (!strcasecmp(v->name, "mwisendtype")) {
17466 #ifndef HAVE_DAHDI_LINEREVERSE_VMWI  /* backward compatibility for older dahdi VMWI implementation */
17467          if (!strcasecmp(v->value, "rpas")) { /* Ring Pulse Alert Signal */
17468             mwisend_rpas = 1;
17469          } else {
17470             mwisend_rpas = 0;
17471          }
17472 #else
17473          /* Default is fsk, to turn it off you must specify nofsk */
17474          memset(&confp->chan.mwisend_setting, 0, sizeof(confp->chan.mwisend_setting));
17475          if (strcasestr(v->value, "nofsk")) {      /* NoFSK */
17476             confp->chan.mwisend_fsk = 0;
17477          } else {             /* Default FSK */
17478             confp->chan.mwisend_fsk = 1;
17479          }
17480          if (strcasestr(v->value, "rpas")) {       /* Ring Pulse Alert Signal, normally followed by FSK */
17481             confp->chan.mwisend_rpas = 1;
17482          } else {
17483             confp->chan.mwisend_rpas = 0;
17484          }
17485          if (strcasestr(v->value, "lrev")) {       /* Line Reversal */
17486             confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_LREV;
17487          }
17488          if (strcasestr(v->value, "hvdc")) {       /* HV 90VDC */
17489             confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_HVDC;
17490          }
17491          if ( (strcasestr(v->value, "neon")) || (strcasestr(v->value, "hvac")) ){   /* 90V DC pulses */
17492             confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_HVAC;
17493          }
17494 #endif
17495       } else if (reload != 1) {
17496           if (!strcasecmp(v->name, "signalling") || !strcasecmp(v->name, "signaling")) {
17497             int orig_radio = confp->chan.radio;
17498             int orig_outsigmod = confp->chan.outsigmod;
17499             int orig_auto = confp->is_sig_auto;
17500 
17501             confp->chan.radio = 0;
17502             confp->chan.outsigmod = -1;
17503             confp->is_sig_auto = 0;
17504             if (!strcasecmp(v->value, "em")) {
17505                confp->chan.sig = SIG_EM;
17506             } else if (!strcasecmp(v->value, "em_e1")) {
17507                confp->chan.sig = SIG_EM_E1;
17508             } else if (!strcasecmp(v->value, "em_w")) {
17509                confp->chan.sig = SIG_EMWINK;
17510             } else if (!strcasecmp(v->value, "fxs_ls")) {
17511                confp->chan.sig = SIG_FXSLS;
17512             } else if (!strcasecmp(v->value, "fxs_gs")) {
17513                confp->chan.sig = SIG_FXSGS;
17514             } else if (!strcasecmp(v->value, "fxs_ks")) {
17515                confp->chan.sig = SIG_FXSKS;
17516             } else if (!strcasecmp(v->value, "fxo_ls")) {
17517                confp->chan.sig = SIG_FXOLS;
17518             } else if (!strcasecmp(v->value, "fxo_gs")) {
17519                confp->chan.sig = SIG_FXOGS;
17520             } else if (!strcasecmp(v->value, "fxo_ks")) {
17521                confp->chan.sig = SIG_FXOKS;
17522             } else if (!strcasecmp(v->value, "fxs_rx")) {
17523                confp->chan.sig = SIG_FXSKS;
17524                confp->chan.radio = 1;
17525             } else if (!strcasecmp(v->value, "fxo_rx")) {
17526                confp->chan.sig = SIG_FXOLS;
17527                confp->chan.radio = 1;
17528             } else if (!strcasecmp(v->value, "fxs_tx")) {
17529                confp->chan.sig = SIG_FXSLS;
17530                confp->chan.radio = 1;
17531             } else if (!strcasecmp(v->value, "fxo_tx")) {
17532                confp->chan.sig = SIG_FXOGS;
17533                confp->chan.radio = 1;
17534             } else if (!strcasecmp(v->value, "em_rx")) {
17535                confp->chan.sig = SIG_EM;
17536                confp->chan.radio = 1;
17537             } else if (!strcasecmp(v->value, "em_tx")) {
17538                confp->chan.sig = SIG_EM;
17539                confp->chan.radio = 1;
17540             } else if (!strcasecmp(v->value, "em_rxtx")) {
17541                confp->chan.sig = SIG_EM;
17542                confp->chan.radio = 2;
17543             } else if (!strcasecmp(v->value, "em_txrx")) {
17544                confp->chan.sig = SIG_EM;
17545                confp->chan.radio = 2;
17546             } else if (!strcasecmp(v->value, "sf")) {
17547                confp->chan.sig = SIG_SF;
17548             } else if (!strcasecmp(v->value, "sf_w")) {
17549                confp->chan.sig = SIG_SFWINK;
17550             } else if (!strcasecmp(v->value, "sf_featd")) {
17551                confp->chan.sig = SIG_FEATD;
17552             } else if (!strcasecmp(v->value, "sf_featdmf")) {
17553                confp->chan.sig = SIG_FEATDMF;
17554             } else if (!strcasecmp(v->value, "sf_featb")) {
17555                confp->chan.sig = SIG_SF_FEATB;
17556             } else if (!strcasecmp(v->value, "sf")) {
17557                confp->chan.sig = SIG_SF;
17558             } else if (!strcasecmp(v->value, "sf_rx")) {
17559                confp->chan.sig = SIG_SF;
17560                confp->chan.radio = 1;
17561             } else if (!strcasecmp(v->value, "sf_tx")) {
17562                confp->chan.sig = SIG_SF;
17563                confp->chan.radio = 1;
17564             } else if (!strcasecmp(v->value, "sf_rxtx")) {
17565                confp->chan.sig = SIG_SF;
17566                confp->chan.radio = 2;
17567             } else if (!strcasecmp(v->value, "sf_txrx")) {
17568                confp->chan.sig = SIG_SF;
17569                confp->chan.radio = 2;
17570             } else if (!strcasecmp(v->value, "featd")) {
17571                confp->chan.sig = SIG_FEATD;
17572             } else if (!strcasecmp(v->value, "featdmf")) {
17573                confp->chan.sig = SIG_FEATDMF;
17574             } else if (!strcasecmp(v->value, "featdmf_ta")) {
17575                confp->chan.sig = SIG_FEATDMF_TA;
17576             } else if (!strcasecmp(v->value, "e911")) {
17577                confp->chan.sig = SIG_E911;
17578             } else if (!strcasecmp(v->value, "fgccama")) {
17579                confp->chan.sig = SIG_FGC_CAMA;
17580             } else if (!strcasecmp(v->value, "fgccamamf")) {
17581                confp->chan.sig = SIG_FGC_CAMAMF;
17582             } else if (!strcasecmp(v->value, "featb")) {
17583                confp->chan.sig = SIG_FEATB;
17584 #ifdef HAVE_PRI
17585             } else if (!strcasecmp(v->value, "pri_net")) {
17586                confp->chan.sig = SIG_PRI;
17587                confp->pri.nodetype = PRI_NETWORK;
17588             } else if (!strcasecmp(v->value, "pri_cpe")) {
17589                confp->chan.sig = SIG_PRI;
17590                confp->pri.nodetype = PRI_CPE;
17591             } else if (!strcasecmp(v->value, "bri_cpe")) {
17592                confp->chan.sig = SIG_BRI;
17593                confp->pri.nodetype = PRI_CPE;
17594             } else if (!strcasecmp(v->value, "bri_net")) {
17595                confp->chan.sig = SIG_BRI;
17596                confp->pri.nodetype = PRI_NETWORK;
17597             } else if (!strcasecmp(v->value, "bri_cpe_ptmp")) {
17598                confp->chan.sig = SIG_BRI_PTMP;
17599                confp->pri.nodetype = PRI_CPE;
17600             } else if (!strcasecmp(v->value, "bri_net_ptmp")) {
17601                ast_log(LOG_WARNING, "How cool would it be if someone implemented this mode!  For now, sucks for you. (line %d)\n", v->lineno);
17602             } else if (!strcasecmp(v->value, "gr303fxoks_net")) {
17603                confp->chan.sig = SIG_GR303FXOKS;
17604                confp->pri.nodetype = PRI_NETWORK;
17605             } else if (!strcasecmp(v->value, "gr303fxsks_cpe")) {
17606                confp->chan.sig = SIG_GR303FXSKS;
17607                confp->pri.nodetype = PRI_CPE;
17608 #endif
17609 #ifdef HAVE_SS7
17610             } else if (!strcasecmp(v->value, "ss7")) {
17611                confp->chan.sig = SIG_SS7;
17612 #endif
17613 #ifdef HAVE_OPENR2
17614             } else if (!strcasecmp(v->value, "mfcr2")) {
17615                confp->chan.sig = SIG_MFCR2;
17616 #endif
17617             } else if (!strcasecmp(v->value, "auto")) {
17618                confp->is_sig_auto = 1;
17619             } else {
17620                confp->chan.outsigmod = orig_outsigmod;
17621                confp->chan.radio = orig_radio;
17622                confp->is_sig_auto = orig_auto;
17623                ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
17624             }
17625           } else if (!strcasecmp(v->name, "outsignalling") || !strcasecmp(v->name, "outsignaling")) {
17626             if (!strcasecmp(v->value, "em")) {
17627                confp->chan.outsigmod = SIG_EM;
17628             } else if (!strcasecmp(v->value, "em_e1")) {
17629                confp->chan.outsigmod = SIG_EM_E1;
17630             } else if (!strcasecmp(v->value, "em_w")) {
17631                confp->chan.outsigmod = SIG_EMWINK;
17632             } else if (!strcasecmp(v->value, "sf")) {
17633                confp->chan.outsigmod = SIG_SF;
17634             } else if (!strcasecmp(v->value, "sf_w")) {
17635                confp->chan.outsigmod = SIG_SFWINK;
17636             } else if (!strcasecmp(v->value, "sf_featd")) {
17637                confp->chan.outsigmod = SIG_FEATD;
17638             } else if (!strcasecmp(v->value, "sf_featdmf")) {
17639                confp->chan.outsigmod = SIG_FEATDMF;
17640             } else if (!strcasecmp(v->value, "sf_featb")) {
17641                confp->chan.outsigmod = SIG_SF_FEATB;
17642             } else if (!strcasecmp(v->value, "sf")) {
17643                confp->chan.outsigmod = SIG_SF;
17644             } else if (!strcasecmp(v->value, "featd")) {
17645                confp->chan.outsigmod = SIG_FEATD;
17646             } else if (!strcasecmp(v->value, "featdmf")) {
17647                confp->chan.outsigmod = SIG_FEATDMF;
17648             } else if (!strcasecmp(v->value, "featdmf_ta")) {
17649                confp->chan.outsigmod = SIG_FEATDMF_TA;
17650             } else if (!strcasecmp(v->value, "e911")) {
17651                confp->chan.outsigmod = SIG_E911;
17652             } else if (!strcasecmp(v->value, "fgccama")) {
17653                confp->chan.outsigmod = SIG_FGC_CAMA;
17654             } else if (!strcasecmp(v->value, "fgccamamf")) {
17655                confp->chan.outsigmod = SIG_FGC_CAMAMF;
17656             } else if (!strcasecmp(v->value, "featb")) {
17657                confp->chan.outsigmod = SIG_FEATB;
17658             } else {
17659                ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
17660             }
17661 #ifdef HAVE_PRI
17662          } else if (!strcasecmp(v->name, "pridialplan")) {
17663             if (!strcasecmp(v->value, "national")) {
17664                confp->pri.dialplan = PRI_NATIONAL_ISDN + 1;
17665             } else if (!strcasecmp(v->value, "unknown")) {
17666                confp->pri.dialplan = PRI_UNKNOWN + 1;
17667             } else if (!strcasecmp(v->value, "private")) {
17668                confp->pri.dialplan = PRI_PRIVATE + 1;
17669             } else if (!strcasecmp(v->value, "international")) {
17670                confp->pri.dialplan = PRI_INTERNATIONAL_ISDN + 1;
17671             } else if (!strcasecmp(v->value, "local")) {
17672                confp->pri.dialplan = PRI_LOCAL_ISDN + 1;
17673             } else if (!strcasecmp(v->value, "dynamic")) {
17674                confp->pri.dialplan = -1;
17675             } else if (!strcasecmp(v->value, "redundant")) {
17676                confp->pri.dialplan = -2;
17677             } else {
17678                ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno);
17679             }
17680          } else if (!strcasecmp(v->name, "prilocaldialplan")) {
17681             if (!strcasecmp(v->value, "national")) {
17682                confp->pri.localdialplan = PRI_NATIONAL_ISDN + 1;
17683             } else if (!strcasecmp(v->value, "unknown")) {
17684                confp->pri.localdialplan = PRI_UNKNOWN + 1;
17685             } else if (!strcasecmp(v->value, "private")) {
17686                confp->pri.localdialplan = PRI_PRIVATE + 1;
17687             } else if (!strcasecmp(v->value, "international")) {
17688                confp->pri.localdialplan = PRI_INTERNATIONAL_ISDN + 1;
17689             } else if (!strcasecmp(v->value, "local")) {
17690                confp->pri.localdialplan = PRI_LOCAL_ISDN + 1;
17691             } else if (!strcasecmp(v->value, "dynamic")) {
17692                confp->pri.localdialplan = -1;
17693             } else if (!strcasecmp(v->value, "redundant")) {
17694                confp->pri.localdialplan = -2;
17695             } else {
17696                ast_log(LOG_WARNING, "Unknown PRI localdialplan '%s' at line %d.\n", v->value, v->lineno);
17697             }
17698          } else if (!strcasecmp(v->name, "switchtype")) {
17699             if (!strcasecmp(v->value, "national"))
17700                confp->pri.switchtype = PRI_SWITCH_NI2;
17701             else if (!strcasecmp(v->value, "ni1"))
17702                confp->pri.switchtype = PRI_SWITCH_NI1;
17703             else if (!strcasecmp(v->value, "dms100"))
17704                confp->pri.switchtype = PRI_SWITCH_DMS100;
17705             else if (!strcasecmp(v->value, "4ess"))
17706                confp->pri.switchtype = PRI_SWITCH_ATT4ESS;
17707             else if (!strcasecmp(v->value, "5ess"))
17708                confp->pri.switchtype = PRI_SWITCH_LUCENT5E;
17709             else if (!strcasecmp(v->value, "euroisdn"))
17710                confp->pri.switchtype = PRI_SWITCH_EUROISDN_E1;
17711             else if (!strcasecmp(v->value, "qsig"))
17712                confp->pri.switchtype = PRI_SWITCH_QSIG;
17713             else {
17714                ast_log(LOG_ERROR, "Unknown switchtype '%s' at line %d.\n", v->value, v->lineno);
17715                return -1;
17716             }
17717          } else if (!strcasecmp(v->name, "nsf")) {
17718             if (!strcasecmp(v->value, "sdn"))
17719                confp->pri.nsf = PRI_NSF_SDN;
17720             else if (!strcasecmp(v->value, "megacom"))
17721                confp->pri.nsf = PRI_NSF_MEGACOM;
17722             else if (!strcasecmp(v->value, "tollfreemegacom"))
17723                confp->pri.nsf = PRI_NSF_TOLL_FREE_MEGACOM;
17724             else if (!strcasecmp(v->value, "accunet"))
17725                confp->pri.nsf = PRI_NSF_ACCUNET;
17726             else if (!strcasecmp(v->value, "none"))
17727                confp->pri.nsf = PRI_NSF_NONE;
17728             else {
17729                ast_log(LOG_WARNING, "Unknown network-specific facility '%s' at line %d.\n", v->value, v->lineno);
17730                confp->pri.nsf = PRI_NSF_NONE;
17731             }
17732          } else if (!strcasecmp(v->name, "priindication")) {
17733             if (!strcasecmp(v->value, "outofband"))
17734                confp->chan.priindication_oob = 1;
17735             else if (!strcasecmp(v->value, "inband"))
17736                confp->chan.priindication_oob = 0;
17737             else
17738                ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d.\n",
17739                   v->value, v->lineno);
17740          } else if (!strcasecmp(v->name, "priexclusive")) {
17741             confp->chan.priexclusive = ast_true(v->value);
17742          } else if (!strcasecmp(v->name, "internationalprefix")) {
17743             ast_copy_string(confp->pri.internationalprefix, v->value, sizeof(confp->pri.internationalprefix));
17744          } else if (!strcasecmp(v->name, "nationalprefix")) {
17745             ast_copy_string(confp->pri.nationalprefix, v->value, sizeof(confp->pri.nationalprefix));
17746          } else if (!strcasecmp(v->name, "localprefix")) {
17747             ast_copy_string(confp->pri.localprefix, v->value, sizeof(confp->pri.localprefix));
17748          } else if (!strcasecmp(v->name, "privateprefix")) {
17749             ast_copy_string(confp->pri.privateprefix, v->value, sizeof(confp->pri.privateprefix));
17750          } else if (!strcasecmp(v->name, "unknownprefix")) {
17751             ast_copy_string(confp->pri.unknownprefix, v->value, sizeof(confp->pri.unknownprefix));
17752          } else if (!strcasecmp(v->name, "resetinterval")) {
17753             if (!strcasecmp(v->value, "never"))
17754                confp->pri.resetinterval = -1;
17755             else if (atoi(v->value) >= 60)
17756                confp->pri.resetinterval = atoi(v->value);
17757             else
17758                ast_log(LOG_WARNING, "'%s' is not a valid reset interval, should be >= 60 seconds or 'never' at line %d.\n",
17759                   v->value, v->lineno);
17760          } else if (!strcasecmp(v->name, "minunused")) {
17761             confp->pri.minunused = atoi(v->value);
17762          } else if (!strcasecmp(v->name, "minidle")) {
17763             confp->pri.minidle = atoi(v->value);
17764          } else if (!strcasecmp(v->name, "idleext")) {
17765             ast_copy_string(confp->pri.idleext, v->value, sizeof(confp->pri.idleext));
17766          } else if (!strcasecmp(v->name, "idledial")) {
17767             ast_copy_string(confp->pri.idledial, v->value, sizeof(confp->pri.idledial));
17768          } else if (!strcasecmp(v->name, "overlapdial")) {
17769             if (ast_true(v->value)) {
17770                confp->pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
17771             } else if (!strcasecmp(v->value, "incoming")) {
17772                confp->pri.overlapdial = DAHDI_OVERLAPDIAL_INCOMING;
17773             } else if (!strcasecmp(v->value, "outgoing")) {
17774                confp->pri.overlapdial = DAHDI_OVERLAPDIAL_OUTGOING;
17775             } else if (!strcasecmp(v->value, "both") || ast_true(v->value)) {
17776                confp->pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
17777             } else {
17778                confp->pri.overlapdial = DAHDI_OVERLAPDIAL_NONE;
17779             }
17780 #ifdef HAVE_PRI_PROG_W_CAUSE
17781          } else if (!strcasecmp(v->name, "qsigchannelmapping")) {
17782             if (!strcasecmp(v->value, "logical")) {
17783                confp->pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_LOGICAL;
17784             } else if (!strcasecmp(v->value, "physical")) {
17785                confp->pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL;
17786             } else {
17787                confp->pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL;
17788             }
17789 #endif
17790          } else if (!strcasecmp(v->name, "discardremoteholdretrieval")) {
17791             confp->pri.discardremoteholdretrieval = ast_true(v->value);
17792 #ifdef HAVE_PRI_INBANDDISCONNECT
17793          } else if (!strcasecmp(v->name, "inbanddisconnect")) {
17794             confp->pri.inbanddisconnect = ast_true(v->value);
17795 #endif
17796          } else if (!strcasecmp(v->name, "pritimer")) {
17797 #ifdef PRI_GETSET_TIMERS
17798             char tmp[20];
17799             char *timerc;
17800             char *c;
17801             int timer;
17802             int timeridx;
17803 
17804             ast_copy_string(tmp, v->value, sizeof(tmp));
17805             c = tmp;
17806             timerc = strsep(&c, ",");
17807             if (!ast_strlen_zero(timerc) && !ast_strlen_zero(c)) {
17808                timeridx = pri_timer2idx(timerc);
17809                timer = atoi(c);
17810                if (timeridx < 0 || PRI_MAX_TIMERS <= timeridx) {
17811                   ast_log(LOG_WARNING,
17812                      "'%s' is not a valid ISDN timer at line %d.\n", timerc,
17813                      v->lineno);
17814                } else if (!timer) {
17815                   ast_log(LOG_WARNING,
17816                      "'%s' is not a valid value for ISDN timer '%s' at line %d.\n",
17817                      c, timerc, v->lineno);
17818                } else {
17819                   pritimers[timeridx] = timer;
17820                }
17821             } else {
17822                ast_log(LOG_WARNING,
17823                   "'%s' is not a valid ISDN timer configuration string at line %d.\n",
17824                   v->value, v->lineno);
17825             }
17826 
17827          } else if (!strcasecmp(v->name, "facilityenable")) {
17828             confp->pri.facilityenable = ast_true(v->value);
17829 #endif /* PRI_GETSET_TIMERS */
17830 #endif /* HAVE_PRI */
17831 #ifdef HAVE_SS7
17832          } else if (!strcasecmp(v->name, "ss7type")) {
17833             if (!strcasecmp(v->value, "itu")) {
17834                cur_ss7type = SS7_ITU;
17835             } else if (!strcasecmp(v->value, "ansi")) {
17836                cur_ss7type = SS7_ANSI;
17837             } else
17838                ast_log(LOG_WARNING, "'%s' is an unknown ss7 switch type at line %d.!\n", v->value, v->lineno);
17839          } else if (!strcasecmp(v->name, "linkset")) {
17840             cur_linkset = atoi(v->value);
17841          } else if (!strcasecmp(v->name, "pointcode")) {
17842             cur_pointcode = parse_pointcode(v->value);
17843          } else if (!strcasecmp(v->name, "adjpointcode")) {
17844             cur_adjpointcode = parse_pointcode(v->value);
17845          } else if (!strcasecmp(v->name, "defaultdpc")) {
17846             cur_defaultdpc = parse_pointcode(v->value);
17847          } else if (!strcasecmp(v->name, "cicbeginswith")) {
17848             cur_cicbeginswith = atoi(v->value);
17849          } else if (!strcasecmp(v->name, "networkindicator")) {
17850             if (!strcasecmp(v->value, "national"))
17851                cur_networkindicator = SS7_NI_NAT;
17852             else if (!strcasecmp(v->value, "national_spare"))
17853                cur_networkindicator = SS7_NI_NAT_SPARE;
17854             else if (!strcasecmp(v->value, "international"))
17855                cur_networkindicator = SS7_NI_INT;
17856             else if (!strcasecmp(v->value, "international_spare"))
17857                cur_networkindicator = SS7_NI_INT_SPARE;
17858             else
17859                cur_networkindicator = -1;
17860          } else if (!strcasecmp(v->name, "ss7_internationalprefix")) {
17861             ast_copy_string(confp->ss7.internationalprefix, v->value, sizeof(confp->ss7.internationalprefix));
17862          } else if (!strcasecmp(v->name, "ss7_nationalprefix")) {
17863             ast_copy_string(confp->ss7.nationalprefix, v->value, sizeof(confp->ss7.nationalprefix));
17864          } else if (!strcasecmp(v->name, "ss7_subscriberprefix")) {
17865             ast_copy_string(confp->ss7.subscriberprefix, v->value, sizeof(confp->ss7.subscriberprefix));
17866          } else if (!strcasecmp(v->name, "ss7_unknownprefix")) {
17867             ast_copy_string(confp->ss7.unknownprefix, v->value, sizeof(confp->ss7.unknownprefix));
17868          } else if (!strcasecmp(v->name, "ss7_called_nai")) {
17869             if (!strcasecmp(v->value, "national")) {
17870                confp->ss7.called_nai = SS7_NAI_NATIONAL;
17871             } else if (!strcasecmp(v->value, "international")) {
17872                confp->ss7.called_nai = SS7_NAI_INTERNATIONAL;
17873             } else if (!strcasecmp(v->value, "subscriber")) {
17874                confp->ss7.called_nai = SS7_NAI_SUBSCRIBER;
17875             } else if (!strcasecmp(v->value, "unknown")) {
17876                confp->ss7.called_nai = SS7_NAI_UNKNOWN;
17877             } else if (!strcasecmp(v->value, "dynamic")) {
17878                confp->ss7.called_nai = SS7_NAI_DYNAMIC;
17879             } else {
17880                ast_log(LOG_WARNING, "Unknown SS7 called_nai '%s' at line %d.\n", v->value, v->lineno);
17881             }
17882          } else if (!strcasecmp(v->name, "ss7_calling_nai")) {
17883             if (!strcasecmp(v->value, "national")) {
17884                confp->ss7.calling_nai = SS7_NAI_NATIONAL;
17885             } else if (!strcasecmp(v->value, "international")) {
17886                confp->ss7.calling_nai = SS7_NAI_INTERNATIONAL;
17887             } else if (!strcasecmp(v->value, "subscriber")) {
17888                confp->ss7.calling_nai = SS7_NAI_SUBSCRIBER;
17889             } else if (!strcasecmp(v->value, "unknown")) {
17890                confp->ss7.calling_nai = SS7_NAI_UNKNOWN;
17891             } else if (!strcasecmp(v->value, "dynamic")) {
17892                confp->ss7.calling_nai = SS7_NAI_DYNAMIC;
17893             } else {
17894                ast_log(LOG_WARNING, "Unknown SS7 calling_nai '%s' at line %d.\n", v->value, v->lineno);
17895             }
17896          } else if (!strcasecmp(v->name, "sigchan")) {
17897             int sigchan, res;
17898             sigchan = atoi(v->value);
17899             res = linkset_addsigchan(sigchan);
17900             if (res < 0)
17901                return -1;
17902 
17903          } else if (!strcasecmp(v->name, "ss7_explicitacm")) {
17904             struct dahdi_ss7 *link;
17905             link = ss7_resolve_linkset(cur_linkset);
17906             if (!link) {
17907                ast_log(LOG_ERROR, "Invalid linkset number.  Must be between 1 and %d\n", NUM_SPANS + 1);
17908                return -1;
17909             }
17910             if (ast_true(v->value))
17911                link->flags |= LINKSET_FLAG_EXPLICITACM;
17912 #endif /* HAVE_SS7 */
17913 #ifdef HAVE_OPENR2
17914          } else if (!strcasecmp(v->name, "mfcr2_advanced_protocol_file")) {
17915             ast_copy_string(confp->mfcr2.r2proto_file, v->value, sizeof(confp->mfcr2.r2proto_file));
17916             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);
17917          } else if (!strcasecmp(v->name, "mfcr2_logdir")) {
17918             ast_copy_string(confp->mfcr2.logdir, v->value, sizeof(confp->mfcr2.logdir));
17919          } else if (!strcasecmp(v->name, "mfcr2_variant")) {
17920             confp->mfcr2.variant = openr2_proto_get_variant(v->value);
17921             if (OR2_VAR_UNKNOWN == confp->mfcr2.variant) {
17922                ast_log(LOG_WARNING, "Unknown MFC/R2 variant '%s' at line %d, defaulting to ITU.\n", v->value, v->lineno);
17923                confp->mfcr2.variant = OR2_VAR_ITU;
17924             }
17925          } else if (!strcasecmp(v->name, "mfcr2_mfback_timeout")) {
17926             confp->mfcr2.mfback_timeout = atoi(v->value);
17927             if (!confp->mfcr2.mfback_timeout) {
17928                ast_log(LOG_WARNING, "MF timeout of 0? hum, I will protect you from your ignorance. Setting default.\n");
17929                confp->mfcr2.mfback_timeout = -1;
17930             } else if (confp->mfcr2.mfback_timeout > 0 && confp->mfcr2.mfback_timeout < 500) {
17931                ast_log(LOG_WARNING, "MF timeout less than 500ms is not recommended, you have been warned!\n");
17932             }
17933          } else if (!strcasecmp(v->name, "mfcr2_metering_pulse_timeout")) {
17934             confp->mfcr2.metering_pulse_timeout = atoi(v->value);
17935             if (confp->mfcr2.metering_pulse_timeout > 500) {
17936                ast_log(LOG_WARNING, "Metering pulse timeout greater than 500ms is not recommended, you have been warned!\n");
17937             }
17938          } else if (!strcasecmp(v->name, "mfcr2_get_ani_first")) {
17939             confp->mfcr2.get_ani_first = ast_true(v->value) ? 1 : 0;
17940          } else if (!strcasecmp(v->name, "mfcr2_double_answer")) {
17941             confp->mfcr2.double_answer = ast_true(v->value) ? 1 : 0;
17942          } else if (!strcasecmp(v->name, "mfcr2_charge_calls")) {
17943             confp->mfcr2.charge_calls = ast_true(v->value) ? 1 : 0;
17944          } else if (!strcasecmp(v->name, "mfcr2_accept_on_offer")) {
17945             confp->mfcr2.accept_on_offer = ast_true(v->value) ? 1 : 0;
17946          } else if (!strcasecmp(v->name, "mfcr2_allow_collect_calls")) {
17947             confp->mfcr2.allow_collect_calls = ast_true(v->value) ? 1 : 0;
17948          } else if (!strcasecmp(v->name, "mfcr2_forced_release")) {
17949             confp->mfcr2.forced_release = ast_true(v->value) ? 1 : 0;
17950          } else if (!strcasecmp(v->name, "mfcr2_immediate_accept")) {
17951             confp->mfcr2.immediate_accept = ast_true(v->value) ? 1 : 0;
17952 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
17953          } else if (!strcasecmp(v->name, "mfcr2_skip_category")) {
17954             confp->mfcr2.skip_category_request = ast_true(v->value) ? 1 : 0;
17955 #endif
17956          } else if (!strcasecmp(v->name, "mfcr2_call_files")) {
17957             confp->mfcr2.call_files = ast_true(v->value) ? 1 : 0;
17958          } else if (!strcasecmp(v->name, "mfcr2_max_ani")) {
17959             confp->mfcr2.max_ani = atoi(v->value);
17960             if (confp->mfcr2.max_ani >= AST_MAX_EXTENSION){
17961                confp->mfcr2.max_ani = AST_MAX_EXTENSION - 1;
17962             }
17963          } else if (!strcasecmp(v->name, "mfcr2_max_dnis")) {
17964             confp->mfcr2.max_dnis = atoi(v->value);
17965             if (confp->mfcr2.max_dnis >= AST_MAX_EXTENSION){
17966                confp->mfcr2.max_dnis = AST_MAX_EXTENSION - 1;
17967             }
17968          } else if (!strcasecmp(v->name, "mfcr2_category")) {
17969             confp->mfcr2.category = openr2_proto_get_category(v->value);
17970             if (OR2_CALLING_PARTY_CATEGORY_UNKNOWN == confp->mfcr2.category) {
17971                confp->mfcr2.category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER;
17972                ast_log(LOG_WARNING, "Invalid MFC/R2 caller category '%s' at line %d. Using national subscriber as default.\n",
17973                      v->value, v->lineno);
17974             }
17975          } else if (!strcasecmp(v->name, "mfcr2_logging")) {
17976             openr2_log_level_t tmplevel;
17977             char *clevel;
17978             char *logval = ast_strdupa(v->value);
17979             while (logval) {
17980                clevel = strsep(&logval,",");
17981                if (-1 == (tmplevel = openr2_log_get_level(clevel))) {
17982                   ast_log(LOG_WARNING, "Ignoring invalid logging level: '%s' at line %d.\n", clevel, v->lineno);
17983                   continue;
17984                }
17985                confp->mfcr2.loglevel |= tmplevel;
17986             }
17987 #endif /* HAVE_OPENR2 */
17988          } else if (!strcasecmp(v->name, "cadence")) {
17989             /* setup to scan our argument */
17990             int element_count, c[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
17991             int i;
17992             struct dahdi_ring_cadence new_cadence;
17993             int cid_location = -1;
17994             int firstcadencepos = 0;
17995             char original_args[80];
17996             int cadence_is_ok = 1;
17997 
17998             ast_copy_string(original_args, v->value, sizeof(original_args));
17999             /* 16 cadences allowed (8 pairs) */
18000             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]);
18001 
18002             /* Cadence must be even (on/off) */
18003             if (element_count % 2 == 1) {
18004                ast_log(LOG_ERROR, "Must be a silence duration for each ring duration: %s at line %d.\n", original_args, v->lineno);
18005                cadence_is_ok = 0;
18006             }
18007 
18008             /* Ring cadences cannot be negative */
18009             for (i = 0; i < element_count; i++) {
18010                if (c[i] == 0) {
18011                   ast_log(LOG_ERROR, "Ring or silence duration cannot be zero: %s at line %d.\n", original_args, v->lineno);
18012                   cadence_is_ok = 0;
18013                   break;
18014                } else if (c[i] < 0) {
18015                   if (i % 2 == 1) {
18016                      /* Silence duration, negative possibly okay */
18017                      if (cid_location == -1) {
18018                         cid_location = i;
18019                         c[i] *= -1;
18020                      } else {
18021                         ast_log(LOG_ERROR, "CID location specified twice: %s at line %d.\n", original_args, v->lineno);
18022                         cadence_is_ok = 0;
18023                         break;
18024                      }
18025                   } else {
18026                      if (firstcadencepos == 0) {
18027                         firstcadencepos = i; /* only recorded to avoid duplicate specification */
18028                                  /* duration will be passed negative to the DAHDI driver */
18029                      } else {
18030                          ast_log(LOG_ERROR, "First cadence position specified twice: %s at line %d.\n", original_args, v->lineno);
18031                         cadence_is_ok = 0;
18032                         break;
18033                      }
18034                   }
18035                }
18036             }
18037 
18038             /* Substitute our scanned cadence */
18039             for (i = 0; i < 16; i++) {
18040                new_cadence.ringcadence[i] = c[i];
18041             }
18042 
18043             if (cadence_is_ok) {
18044                /* ---we scanned it without getting annoyed; now some sanity checks--- */
18045                if (element_count < 2) {
18046                   ast_log(LOG_ERROR, "Minimum cadence is ring,pause: %s at line %d.\n", original_args, v->lineno);
18047                } else {
18048                   if (cid_location == -1) {
18049                      /* user didn't say; default to first pause */
18050                      cid_location = 1;
18051                   } else {
18052                      /* convert element_index to cidrings value */
18053                      cid_location = (cid_location + 1) / 2;
18054                   }
18055                   /* ---we like their cadence; try to install it--- */
18056                   if (!user_has_defined_cadences++)
18057                      /* this is the first user-defined cadence; clear the default user cadences */
18058                      num_cadence = 0;
18059                   if ((num_cadence+1) >= NUM_CADENCE_MAX)
18060                      ast_log(LOG_ERROR, "Already %d cadences; can't add another: %s at line %d.\n", NUM_CADENCE_MAX, original_args, v->lineno);
18061                   else {
18062                      cadences[num_cadence] = new_cadence;
18063                      cidrings[num_cadence++] = cid_location;
18064                      ast_verb(3, "cadence 'r%d' added: %s\n",num_cadence,original_args);
18065                   }
18066                }
18067             }
18068          } else if (!strcasecmp(v->name, "ringtimeout")) {
18069             ringt_base = (atoi(v->value) * 8) / READ_SIZE;
18070          } else if (!strcasecmp(v->name, "prewink")) {
18071             confp->timing.prewinktime = atoi(v->value);
18072          } else if (!strcasecmp(v->name, "preflash")) {
18073             confp->timing.preflashtime = atoi(v->value);
18074          } else if (!strcasecmp(v->name, "wink")) {
18075             confp->timing.winktime = atoi(v->value);
18076          } else if (!strcasecmp(v->name, "flash")) {
18077             confp->timing.flashtime = atoi(v->value);
18078          } else if (!strcasecmp(v->name, "start")) {
18079             confp->timing.starttime = atoi(v->value);
18080          } else if (!strcasecmp(v->name, "rxwink")) {
18081             confp->timing.rxwinktime = atoi(v->value);
18082          } else if (!strcasecmp(v->name, "rxflash")) {
18083             confp->timing.rxflashtime = atoi(v->value);
18084          } else if (!strcasecmp(v->name, "debounce")) {
18085             confp->timing.debouncetime = atoi(v->value);
18086          } else if (!strcasecmp(v->name, "toneduration")) {
18087             int toneduration;
18088             int ctlfd;
18089             int res;
18090             struct dahdi_dialparams dps;
18091 
18092             ctlfd = open("/dev/dahdi/ctl", O_RDWR);
18093             if (ctlfd == -1) {
18094                ast_log(LOG_ERROR, "Unable to open /dev/dahdi/ctl to set toneduration at line %d.\n", v->lineno);
18095                return -1;
18096             }
18097 
18098             toneduration = atoi(v->value);
18099             if (toneduration > -1) {
18100                memset(&dps, 0, sizeof(dps));
18101 
18102                dps.dtmf_tonelen = dps.mfv1_tonelen = toneduration;
18103                res = ioctl(ctlfd, DAHDI_SET_DIALPARAMS, &dps);
18104                if (res < 0) {
18105                   ast_log(LOG_ERROR, "Invalid tone duration: %d ms at line %d: %s\n", toneduration, v->lineno, strerror(errno));
18106                   close(ctlfd);
18107                   return -1;
18108                }
18109             }
18110             close(ctlfd);
18111          } else if (!strcasecmp(v->name, "defaultcic")) {
18112             ast_copy_string(defaultcic, v->value, sizeof(defaultcic));
18113          } else if (!strcasecmp(v->name, "defaultozz")) {
18114             ast_copy_string(defaultozz, v->value, sizeof(defaultozz));
18115          } else if (!strcasecmp(v->name, "mwilevel")) {
18116             mwilevel = atoi(v->value);
18117          }
18118       } else if (!(options & PROC_DAHDI_OPT_NOWARN) )
18119          ast_log(LOG_WARNING, "Ignoring any changes to '%s' (on reload) at line %d.\n", v->name, v->lineno);
18120    }
18121 
18122    /* Since confp has already filled invidual dahdi_pvt objects with channels at this point, clear the variables in confp's pvt. */
18123    if (confp->chan.vars) {
18124       ast_variables_destroy(confp->chan.vars);
18125       confp->chan.vars = NULL;
18126    }
18127 
18128    if (dahdichan[0]) {
18129       /* The user has set 'dahdichan' */
18130       /*< \todo pass proper line number instead of 0 */
18131       if (build_channels(confp, 0, dahdichan, reload, 0, &found_pseudo)) {
18132          return -1;
18133       }
18134    }
18135    /*< \todo why check for the pseudo in the per-channel section.
18136     * Any actual use for manual setup of the pseudo channel? */
18137    if (!found_pseudo && reload != 1) {
18138       /* use the default configuration for a channel, so
18139          that any settings from real configured channels
18140          don't "leak" into the pseudo channel config
18141       */
18142       struct dahdi_chan_conf conf = dahdi_chan_conf_default();
18143 
18144       tmp = mkintf(CHAN_PSEUDO, &conf, NULL, reload);
18145 
18146       if (tmp) {
18147          ast_verb(3, "Automatically generated pseudo channel\n");
18148       } else {
18149          ast_log(LOG_WARNING, "Unable to register pseudo channel!\n");
18150       }
18151    }
18152    return 0;
18153 }
18154 
18155 static int setup_dahdi(int reload)
18156 {
18157    struct ast_config *cfg, *ucfg;
18158    struct ast_variable *v;
18159    struct dahdi_chan_conf base_conf = dahdi_chan_conf_default();
18160    struct dahdi_chan_conf conf;
18161    struct ast_flags config_flags = { reload == 1 ? CONFIG_FLAG_FILEUNCHANGED : 0 };
18162    const char *cat;
18163    int res;
18164 
18165 #ifdef HAVE_PRI
18166    char *c;
18167    int spanno;
18168    int i;
18169    int logicalspan;
18170    int trunkgroup;
18171    int dchannels[NUM_DCHANS];
18172 #endif
18173 
18174    cfg = ast_config_load(config, config_flags);
18175 
18176    /* Error if we have no config file */
18177    if (!cfg) {
18178       ast_log(LOG_ERROR, "Unable to load config %s\n", config);
18179       return 0;
18180    } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
18181       ucfg = ast_config_load("users.conf", config_flags);
18182       if (ucfg == CONFIG_STATUS_FILEUNCHANGED) {
18183          return 0;
18184       } else if (ucfg == CONFIG_STATUS_FILEINVALID) {
18185          ast_log(LOG_ERROR, "File users.conf cannot be parsed.  Aborting.\n");
18186          return 0;
18187       }
18188       ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
18189       if ((cfg = ast_config_load(config, config_flags)) == CONFIG_STATUS_FILEINVALID) {
18190          ast_log(LOG_ERROR, "File %s cannot be parsed.  Aborting.\n", config);
18191          ast_config_destroy(ucfg);
18192          return 0;
18193       }
18194    } else if (cfg == CONFIG_STATUS_FILEINVALID) {
18195       ast_log(LOG_ERROR, "File %s cannot be parsed.  Aborting.\n", config);
18196       return 0;
18197    } else {
18198       ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
18199       if ((ucfg = ast_config_load("users.conf", config_flags)) == CONFIG_STATUS_FILEINVALID) {
18200          ast_log(LOG_ERROR, "File users.conf cannot be parsed.  Aborting.\n");
18201          ast_config_destroy(cfg);
18202          return 0;
18203       }
18204    }
18205 
18206    /* It's a little silly to lock it, but we mind as well just to be sure */
18207    ast_mutex_lock(&iflock);
18208 #ifdef HAVE_PRI
18209    if (reload != 1) {
18210       /* Process trunkgroups first */
18211       v = ast_variable_browse(cfg, "trunkgroups");
18212       while (v) {
18213          if (!strcasecmp(v->name, "trunkgroup")) {
18214             trunkgroup = atoi(v->value);
18215             if (trunkgroup > 0) {
18216                if ((c = strchr(v->value, ','))) {
18217                   i = 0;
18218                   memset(dchannels, 0, sizeof(dchannels));
18219                   while (c && (i < NUM_DCHANS)) {
18220                      dchannels[i] = atoi(c + 1);
18221                      if (dchannels[i] < 0) {
18222                         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);
18223                      } else
18224                         i++;
18225                      c = strchr(c + 1, ',');
18226                   }
18227                   if (i) {
18228                      if (pri_create_trunkgroup(trunkgroup, dchannels)) {
18229                         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);
18230                   } else
18231                         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");
18232                   } else
18233                      ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
18234                } else
18235                   ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
18236             } else
18237                ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of chan_dahdi.conf\n", v->lineno);
18238          } else if (!strcasecmp(v->name, "spanmap")) {
18239             spanno = atoi(v->value);
18240             if (spanno > 0) {
18241                if ((c = strchr(v->value, ','))) {
18242                   trunkgroup = atoi(c + 1);
18243                   if (trunkgroup > 0) {
18244                      if ((c = strchr(c + 1, ',')))
18245                         logicalspan = atoi(c + 1);
18246                      else
18247                         logicalspan = 0;
18248                      if (logicalspan >= 0) {
18249                         if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) {
18250                            ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
18251                      } else
18252                            ast_verb(2, "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
18253                      } else
18254                         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);
18255                   } else
18256                      ast_log(LOG_WARNING, "Trunk group must be a postive number at line %d of chan_dahdi.conf\n", v->lineno);
18257                } else
18258                   ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of chan_dahdi.conf\n", v->lineno);
18259             } else
18260                ast_log(LOG_WARNING, "Span number must be a postive integer at line %d of chan_dahdi.conf\n", v->lineno);
18261          } else {
18262             ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name);
18263          }
18264          v = v->next;
18265       }
18266    }
18267 #endif
18268 
18269    /* Copy the default jb config over global_jbconf */
18270    memcpy(&global_jbconf, &default_jbconf, sizeof(global_jbconf));
18271 
18272    mwimonitornotify[0] = '\0';
18273 
18274    v = ast_variable_browse(cfg, "channels");
18275    if ((res = process_dahdi(&base_conf, "", v, reload, 0))) {
18276       ast_mutex_unlock(&iflock);
18277       ast_config_destroy(cfg);
18278       if (ucfg) {
18279          ast_config_destroy(ucfg);
18280       }
18281       return res;
18282    }
18283 
18284    /* Now get configuration from all normal sections in chan_dahdi.conf: */
18285    for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) {
18286       /* [channels] and [trunkgroups] are used. Let's also reserve
18287        * [globals] and [general] for future use
18288        */
18289       if (!strcasecmp(cat, "general") ||
18290          !strcasecmp(cat, "trunkgroups") ||
18291          !strcasecmp(cat, "globals") ||
18292          !strcasecmp(cat, "channels")) {
18293          continue;
18294       }
18295 
18296       memcpy(&conf, &base_conf, sizeof(conf));
18297 
18298       if ((res = process_dahdi(&conf, cat, ast_variable_browse(cfg, cat), reload, PROC_DAHDI_OPT_NOCHAN))) {
18299          ast_mutex_unlock(&iflock);
18300          ast_config_destroy(cfg);
18301          if (ucfg) {
18302             ast_config_destroy(ucfg);
18303          }
18304          return res;
18305       }
18306    }
18307 
18308    ast_config_destroy(cfg);
18309 
18310    if (ucfg) {
18311       const char *chans;
18312 
18313       /* Reset conf back to defaults, so values from chan_dahdi.conf don't leak in. */
18314       base_conf = dahdi_chan_conf_default();
18315       process_dahdi(&base_conf, "", ast_variable_browse(ucfg, "general"), 1, 0);
18316 
18317       for (cat = ast_category_browse(ucfg, NULL); cat ; cat = ast_category_browse(ucfg, cat)) {
18318          if (!strcasecmp(cat, "general")) {
18319             continue;
18320          }
18321 
18322          chans = ast_variable_retrieve(ucfg, cat, "dahdichan");
18323 
18324          if (ast_strlen_zero(chans)) {
18325             continue;
18326          }
18327 
18328          memcpy(&conf, &base_conf, sizeof(conf));
18329 
18330          if ((res = process_dahdi(&conf, cat, ast_variable_browse(ucfg, cat), reload, PROC_DAHDI_OPT_NOCHAN | PROC_DAHDI_OPT_NOWARN))) {
18331             ast_config_destroy(ucfg);
18332             ast_mutex_unlock(&iflock);
18333             return res;
18334          }
18335       }
18336       ast_config_destroy(ucfg);
18337    }
18338    ast_mutex_unlock(&iflock);
18339 
18340 #ifdef HAVE_PRI
18341    if (reload != 1) {
18342       int x;
18343       for (x = 0; x < NUM_SPANS; x++) {
18344          if (pris[x].pvts[0]) {
18345             if (start_pri(pris + x)) {
18346                ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1);
18347                return -1;
18348             } else
18349                ast_verb(2, "Starting D-Channel on span %d\n", x + 1);
18350          }
18351       }
18352    }
18353 #endif
18354 #ifdef HAVE_SS7
18355    if (reload != 1) {
18356       int x;
18357       for (x = 0; x < NUM_SPANS; x++) {
18358          if (linksets[x].ss7) {
18359             if (ast_pthread_create(&linksets[x].master, NULL, ss7_linkset, &linksets[x])) {
18360                ast_log(LOG_ERROR, "Unable to start SS7 linkset on span %d\n", x + 1);
18361                return -1;
18362             } else
18363                ast_verb(2, "Starting SS7 linkset on span %d\n", x + 1);
18364          }
18365       }
18366    }
18367 #endif
18368 #ifdef HAVE_OPENR2
18369    if (reload != 1) {
18370       int x;
18371       for (x = 0; x < r2links_count; x++) {
18372          if (ast_pthread_create(&r2links[x]->r2master, NULL, mfcr2_monitor, r2links[x])) {
18373             ast_log(LOG_ERROR, "Unable to start R2 monitor on channel group %d\n", x + 1);
18374             return -1;
18375          } else {
18376             ast_verb(2, "Starting R2 monitor on channel group %d\n", x + 1);
18377          }
18378       }
18379    }
18380 #endif
18381    /* And start the monitor for the first time */
18382    restart_monitor();
18383    return 0;
18384 }
18385 
18386 static int load_module(void)
18387 {
18388    int res;
18389 #if defined(HAVE_PRI) || defined(HAVE_SS7)
18390    int y, i;
18391 #endif
18392 
18393 #ifdef HAVE_PRI
18394    memset(pris, 0, sizeof(pris));
18395    for (y = 0; y < NUM_SPANS; y++) {
18396       ast_mutex_init(&pris[y].lock);
18397       pris[y].offset = -1;
18398       pris[y].master = AST_PTHREADT_NULL;
18399       for (i = 0; i < NUM_DCHANS; i++)
18400          pris[y].fds[i] = -1;
18401    }
18402    pri_set_error(dahdi_pri_error);
18403    pri_set_message(dahdi_pri_message);
18404    ast_register_application_xml(dahdi_send_keypad_facility_app, dahdi_send_keypad_facility_exec);
18405 #ifdef HAVE_PRI_PROG_W_CAUSE
18406    ast_register_application_xml(dahdi_send_callrerouting_facility_app, dahdi_send_callrerouting_facility_exec);
18407 #endif
18408 #endif
18409 #ifdef HAVE_SS7
18410    memset(linksets, 0, sizeof(linksets));
18411    for (y = 0; y < NUM_SPANS; y++) {
18412       ast_mutex_init(&linksets[y].lock);
18413       linksets[y].master = AST_PTHREADT_NULL;
18414       for (i = 0; i < NUM_DCHANS; i++)
18415          linksets[y].fds[i] = -1;
18416    }
18417    ss7_set_error(dahdi_ss7_error);
18418    ss7_set_message(dahdi_ss7_message);
18419 #endif /* HAVE_SS7 */
18420    res = setup_dahdi(0);
18421    /* Make sure we can register our DAHDI channel type */
18422    if (res)
18423       return AST_MODULE_LOAD_DECLINE;
18424    if (ast_channel_register(&dahdi_tech)) {
18425       ast_log(LOG_ERROR, "Unable to register channel class 'DAHDI'\n");
18426       __unload_module();
18427       return AST_MODULE_LOAD_FAILURE;
18428    }
18429 #ifdef HAVE_PRI
18430    ast_string_field_init(&inuse, 16);
18431    ast_string_field_set(&inuse, name, "GR-303InUse");
18432    ast_cli_register_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
18433 #endif
18434 #ifdef HAVE_SS7
18435    ast_cli_register_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
18436 #endif
18437 #ifdef HAVE_OPENR2
18438    ast_cli_register_multiple(dahdi_mfcr2_cli, sizeof(dahdi_mfcr2_cli)/sizeof(dahdi_mfcr2_cli[0]));
18439    ast_register_application_xml(dahdi_accept_r2_call_app, dahdi_accept_r2_call_exec);
18440 #endif
18441 
18442    ast_cli_register_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli));
18443 
18444    memset(round_robin, 0, sizeof(round_robin));
18445    ast_manager_register( "DAHDITransfer", 0, action_transfer, "Transfer DAHDI Channel" );
18446    ast_manager_register( "DAHDIHangup", 0, action_transferhangup, "Hangup DAHDI Channel" );
18447    ast_manager_register( "DAHDIDialOffhook", 0, action_dahdidialoffhook, "Dial over DAHDI channel while offhook" );
18448    ast_manager_register( "DAHDIDNDon", 0, action_dahdidndon, "Toggle DAHDI channel Do Not Disturb status ON" );
18449    ast_manager_register( "DAHDIDNDoff", 0, action_dahdidndoff, "Toggle DAHDI channel Do Not Disturb status OFF" );
18450    ast_manager_register("DAHDIShowChannels", 0, action_dahdishowchannels, "Show status DAHDI channels");
18451    ast_manager_register("DAHDIRestart", 0, action_dahdirestart, "Fully Restart DAHDI channels (terminates calls)");
18452 
18453    ast_cond_init(&ss_thread_complete, NULL);
18454 
18455    return res;
18456 }
18457 
18458 static int dahdi_sendtext(struct ast_channel *c, const char *text)
18459 {
18460 #define  END_SILENCE_LEN 400
18461 #define  HEADER_MS 50
18462 #define  TRAILER_MS 5
18463 #define  HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8)
18464 #define  ASCII_BYTES_PER_CHAR 80
18465 
18466    unsigned char *buf,*mybuf;
18467    struct dahdi_pvt *p = c->tech_pvt;
18468    struct pollfd fds[1];
18469    int size,res,fd,len,x;
18470    int bytes=0;
18471    /* Initial carrier (imaginary) */
18472    float cr = 1.0;
18473    float ci = 0.0;
18474    float scont = 0.0;
18475    int idx;
18476 
18477    idx = dahdi_get_index(c, p, 0);
18478    if (idx < 0) {
18479       ast_log(LOG_WARNING, "Huh?  I don't exist?\n");
18480       return -1;
18481    }
18482    if (!text[0]) return(0); /* if nothing to send, dont */
18483    if ((!p->tdd) && (!p->mate)) return(0);  /* if not in TDD mode, just return */
18484    if (p->mate)
18485       buf = ast_malloc(((strlen(text) + 1) * ASCII_BYTES_PER_CHAR) + END_SILENCE_LEN + HEADER_LEN);
18486    else
18487       buf = ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN);
18488    if (!buf)
18489       return -1;
18490    mybuf = buf;
18491    if (p->mate) {
18492       int codec = AST_LAW(p);
18493       for (x = 0; x < HEADER_MS; x++) {   /* 50 ms of Mark */
18494          PUT_CLID_MARKMS;
18495       }
18496       /* Put actual message */
18497       for (x = 0; text[x]; x++) {
18498          PUT_CLID(text[x]);
18499       }
18500       for (x = 0; x < TRAILER_MS; x++) {  /* 5 ms of Mark */
18501          PUT_CLID_MARKMS;
18502       }
18503       len = bytes;
18504       buf = mybuf;
18505    } else {
18506       len = tdd_generate(p->tdd, buf, text);
18507       if (len < 1) {
18508          ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text));
18509          ast_free(mybuf);
18510          return -1;
18511       }
18512    }
18513    memset(buf + len, 0x7f, END_SILENCE_LEN);
18514    len += END_SILENCE_LEN;
18515    fd = p->subs[idx].dfd;
18516    while (len) {
18517       if (ast_check_hangup(c)) {
18518          ast_free(mybuf);
18519          return -1;
18520       }
18521       size = len;
18522       if (size > READ_SIZE)
18523          size = READ_SIZE;
18524       fds[0].fd = fd;
18525       fds[0].events = POLLOUT | POLLPRI;
18526       fds[0].revents = 0;
18527       res = poll(fds, 1, -1);
18528       if (!res) {
18529          ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
18530          continue;
18531       }
18532       /* if got exception */
18533       if (fds[0].revents & POLLPRI) {
18534          ast_free(mybuf);
18535          return -1;
18536       }
18537       if (!(fds[0].revents & POLLOUT)) {
18538          ast_debug(1, "write fd not ready on channel %d\n", p->channel);
18539          continue;
18540       }
18541       res = write(fd, buf, size);
18542       if (res != size) {
18543          if (res == -1) {
18544             ast_free(mybuf);
18545             return -1;
18546          }
18547          ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
18548          break;
18549       }
18550       len -= size;
18551       buf += size;
18552    }
18553    ast_free(mybuf);
18554    return(0);
18555 }
18556 
18557 
18558 static int reload(void)
18559 {
18560    int res = 0;
18561 
18562    res = setup_dahdi(1);
18563    if (res) {
18564       ast_log(LOG_WARNING, "Reload of chan_dahdi.so is unsuccessful!\n");
18565       return -1;
18566    }
18567    return 0;
18568 }
18569 
18570 /* This is a workaround so that menuselect displays a proper description
18571  * AST_MODULE_INFO(, , "DAHDI Telephony"
18572  */
18573 
18574 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, tdesc,
18575    .load = load_module,
18576    .unload = unload_module,
18577    .reload = reload,
18578    );