Sat Jul 12 2014 17:18:27

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 - 2008, 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    <use type="module">res_smdi</use>
00042    <depend>dahdi</depend>
00043    <depend>tonezone</depend>
00044    <use type="external">pri</use>
00045    <use type="external">ss7</use>
00046    <use type="external">openr2</use>
00047    <support_level>core</support_level>
00048  ***/
00049 
00050 #include "asterisk.h"
00051 
00052 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 417957 $")
00053 
00054 #if defined(__NetBSD__) || defined(__FreeBSD__)
00055 #include <pthread.h>
00056 #include <signal.h>
00057 #else
00058 #include <sys/signal.h>
00059 #endif
00060 #include <sys/ioctl.h>
00061 #include <sys/stat.h>
00062 #include <math.h>
00063 #include <ctype.h>
00064 
00065 #include <dahdi/user.h>
00066 #include <dahdi/tonezone.h>
00067 #include "sig_analog.h"
00068 /* Analog signaling is currently still present in chan_dahdi for use with
00069  * radio. Sig_analog does not currently handle any radio operations. If
00070  * radio only uses analog signaling, then the radio handling logic could
00071  * be placed in sig_analog and the duplicated code could be removed.
00072  */
00073 
00074 #if defined(HAVE_PRI)
00075 #include "sig_pri.h"
00076 #ifndef PRI_RESTART
00077 #error "Upgrade your libpri"
00078 #endif
00079 #endif   /* defined(HAVE_PRI) */
00080 
00081 #if defined(HAVE_SS7)
00082 #include "sig_ss7.h"
00083 #if defined(LIBSS7_ABI_COMPATIBILITY)
00084 #error "Your installed libss7 is not compatible"
00085 #endif
00086 #endif   /* defined(HAVE_SS7) */
00087 
00088 #ifdef HAVE_OPENR2
00089 /* put this here until sig_mfcr2 comes along */
00090 #define SIG_MFCR2_MAX_CHANNELS   672      /*!< No more than a DS3 per trunk group */
00091 #include <openr2.h>
00092 #endif
00093 
00094 #include "asterisk/lock.h"
00095 #include "asterisk/channel.h"
00096 #include "asterisk/config.h"
00097 #include "asterisk/module.h"
00098 #include "asterisk/pbx.h"
00099 #include "asterisk/file.h"
00100 #include "asterisk/ulaw.h"
00101 #include "asterisk/alaw.h"
00102 #include "asterisk/callerid.h"
00103 #include "asterisk/adsi.h"
00104 #include "asterisk/cli.h"
00105 #include "asterisk/cdr.h"
00106 #include "asterisk/cel.h"
00107 #include "asterisk/features.h"
00108 #include "asterisk/musiconhold.h"
00109 #include "asterisk/say.h"
00110 #include "asterisk/tdd.h"
00111 #include "asterisk/app.h"
00112 #include "asterisk/dsp.h"
00113 #include "asterisk/astdb.h"
00114 #include "asterisk/manager.h"
00115 #include "asterisk/causes.h"
00116 #include "asterisk/term.h"
00117 #include "asterisk/utils.h"
00118 #include "asterisk/transcap.h"
00119 #include "asterisk/stringfields.h"
00120 #include "asterisk/abstract_jb.h"
00121 #include "asterisk/smdi.h"
00122 #include "asterisk/astobj.h"
00123 #include "asterisk/event.h"
00124 #include "asterisk/devicestate.h"
00125 #include "asterisk/paths.h"
00126 #include "asterisk/ccss.h"
00127 #include "asterisk/data.h"
00128 
00129 /*** DOCUMENTATION
00130    <application name="DAHDISendKeypadFacility" language="en_US">
00131       <synopsis>
00132          Send digits out of band over a PRI.
00133       </synopsis>
00134       <syntax>
00135          <parameter name="digits" required="true" />
00136       </syntax>
00137       <description>
00138          <para>This application will send the given string of digits in a Keypad
00139          Facility IE over the current channel.</para>
00140       </description>
00141    </application>
00142    <application name="DAHDISendCallreroutingFacility" language="en_US">
00143       <synopsis>
00144          Send an ISDN call rerouting/deflection facility message.
00145       </synopsis>
00146       <syntax argsep=",">
00147          <parameter name="destination" required="true">
00148             <para>Destination number.</para>
00149          </parameter>
00150          <parameter name="original">
00151             <para>Original called number.</para>
00152          </parameter>
00153          <parameter name="reason">
00154             <para>Diversion reason, if not specified defaults to <literal>unknown</literal></para>
00155          </parameter>
00156       </syntax>
00157       <description>
00158          <para>This application will send an ISDN switch specific call
00159          rerouting/deflection facility message over the current channel.
00160          Supported switches depend upon the version of libpri in use.</para>
00161       </description>
00162    </application>
00163    <application name="DAHDIAcceptR2Call" language="en_US">
00164       <synopsis>
00165          Accept an R2 call if its not already accepted (you still need to answer it)
00166       </synopsis>
00167       <syntax>
00168          <parameter name="charge" required="true">
00169             <para>Yes or No.</para>
00170             <para>Whether you want to accept the call with charge or without charge.</para>
00171          </parameter>
00172       </syntax>
00173       <description>
00174          <para>This application will Accept the R2 call either with charge or no charge.</para>
00175       </description>
00176    </application>
00177    <manager name="DAHDITransfer" language="en_US">
00178       <synopsis>
00179          Transfer DAHDI Channel.
00180       </synopsis>
00181       <syntax>
00182          <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
00183          <parameter name="DAHDIChannel" required="true">
00184             <para>DAHDI channel number to transfer.</para>
00185          </parameter>
00186       </syntax>
00187       <description>
00188          <para>Simulate a flash hook event by the user connected to the channel.</para>
00189          <note><para>Valid only for analog channels.</para></note>
00190       </description>
00191    </manager>
00192    <manager name="DAHDIHangup" language="en_US">
00193       <synopsis>
00194          Hangup DAHDI Channel.
00195       </synopsis>
00196       <syntax>
00197          <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
00198          <parameter name="DAHDIChannel" required="true">
00199             <para>DAHDI channel number to hangup.</para>
00200          </parameter>
00201       </syntax>
00202       <description>
00203          <para>Simulate an on-hook event by the user connected to the channel.</para>
00204          <note><para>Valid only for analog channels.</para></note>
00205       </description>
00206    </manager>
00207    <manager name="DAHDIDialOffhook" language="en_US">
00208       <synopsis>
00209          Dial over DAHDI channel while offhook.
00210       </synopsis>
00211       <syntax>
00212          <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
00213          <parameter name="DAHDIChannel" required="true">
00214             <para>DAHDI channel number to dial digits.</para>
00215          </parameter>
00216          <parameter name="Number" required="true">
00217             <para>Digits to dial.</para>
00218          </parameter>
00219       </syntax>
00220       <description>
00221          <para>Generate DTMF control frames to the bridged peer.</para>
00222       </description>
00223    </manager>
00224    <manager name="DAHDIDNDon" language="en_US">
00225       <synopsis>
00226          Toggle DAHDI channel Do Not Disturb status ON.
00227       </synopsis>
00228       <syntax>
00229          <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
00230          <parameter name="DAHDIChannel" required="true">
00231             <para>DAHDI channel number to set DND on.</para>
00232          </parameter>
00233       </syntax>
00234       <description>
00235          <para>Equivalent to the CLI command "dahdi set dnd <variable>channel</variable> on".</para>
00236          <note><para>Feature only supported by analog channels.</para></note>
00237       </description>
00238    </manager>
00239    <manager name="DAHDIDNDoff" language="en_US">
00240       <synopsis>
00241          Toggle DAHDI channel Do Not Disturb status OFF.
00242       </synopsis>
00243       <syntax>
00244          <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
00245          <parameter name="DAHDIChannel" required="true">
00246             <para>DAHDI channel number to set DND off.</para>
00247          </parameter>
00248       </syntax>
00249       <description>
00250          <para>Equivalent to the CLI command "dahdi set dnd <variable>channel</variable> off".</para>
00251          <note><para>Feature only supported by analog channels.</para></note>
00252       </description>
00253    </manager>
00254    <manager name="DAHDIShowChannels" language="en_US">
00255       <synopsis>
00256          Show status of DAHDI channels.
00257       </synopsis>
00258       <syntax>
00259          <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
00260          <parameter name="DAHDIChannel">
00261             <para>Specify the specific channel number to show.  Show all channels if zero or not present.</para>
00262          </parameter>
00263       </syntax>
00264       <description>
00265          <para>Similar to the CLI command "dahdi show channels".</para>
00266       </description>
00267    </manager>
00268    <manager name="DAHDIRestart" language="en_US">
00269       <synopsis>
00270          Fully Restart DAHDI channels (terminates calls).
00271       </synopsis>
00272       <syntax>
00273          <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
00274       </syntax>
00275       <description>
00276          <para>Equivalent to the CLI command "dahdi restart".</para>
00277       </description>
00278    </manager>
00279    <manager name="PRIShowSpans" language="en_US">
00280       <synopsis>
00281          Show status of PRI spans.
00282       </synopsis>
00283       <syntax>
00284          <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
00285          <parameter name="Span">
00286             <para>Specify the specific span to show.  Show all spans if zero or not present.</para>
00287          </parameter>
00288       </syntax>
00289       <description>
00290          <para>Similar to the CLI command "pri show spans".</para>
00291       </description>
00292    </manager>
00293  ***/
00294 
00295 #define SMDI_MD_WAIT_TIMEOUT 1500 /* 1.5 seconds */
00296 
00297 static const char * const lbostr[] = {
00298 "0 db (CSU)/0-133 feet (DSX-1)",
00299 "133-266 feet (DSX-1)",
00300 "266-399 feet (DSX-1)",
00301 "399-533 feet (DSX-1)",
00302 "533-655 feet (DSX-1)",
00303 "-7.5db (CSU)",
00304 "-15db (CSU)",
00305 "-22.5db (CSU)"
00306 };
00307 
00308 /*! Global jitterbuffer configuration - by default, jb is disabled
00309  *  \note Values shown here match the defaults shown in chan_dahdi.conf.sample */
00310 static struct ast_jb_conf default_jbconf =
00311 {
00312    .flags = 0,
00313    .max_size = 200,
00314    .resync_threshold = 1000,
00315    .impl = "fixed",
00316    .target_extra = 40,
00317 };
00318 static struct ast_jb_conf global_jbconf;
00319 
00320 /*!
00321  * \note Define ZHONE_HACK to cause us to go off hook and then back on hook when
00322  * the user hangs up to reset the state machine so ring works properly.
00323  * This is used to be able to support kewlstart by putting the zhone in
00324  * groundstart mode since their forward disconnect supervision is entirely
00325  * broken even though their documentation says it isn't and their support
00326  * is entirely unwilling to provide any assistance with their channel banks
00327  * even though their web site says they support their products for life.
00328  */
00329 /* #define ZHONE_HACK */
00330 
00331 /*! \brief Typically, how many rings before we should send Caller*ID */
00332 #define DEFAULT_CIDRINGS 1
00333 
00334 #define AST_LAW(p) (((p)->law == DAHDI_LAW_ALAW) ? AST_FORMAT_ALAW : AST_FORMAT_ULAW)
00335 
00336 
00337 /*! \brief Signaling types that need to use MF detection should be placed in this macro */
00338 #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))
00339 
00340 static const char tdesc[] = "DAHDI Telephony Driver"
00341 #if defined(HAVE_PRI) || defined(HAVE_SS7) || defined(HAVE_OPENR2)
00342    " w/"
00343    #if defined(HAVE_PRI)
00344       "PRI"
00345    #endif   /* defined(HAVE_PRI) */
00346    #if defined(HAVE_SS7)
00347       #if defined(HAVE_PRI)
00348       " & "
00349       #endif   /* defined(HAVE_PRI) */
00350       "SS7"
00351    #endif   /* defined(HAVE_SS7) */
00352    #if defined(HAVE_OPENR2)
00353       #if defined(HAVE_PRI) || defined(HAVE_SS7)
00354       " & "
00355       #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
00356       "MFC/R2"
00357    #endif   /* defined(HAVE_OPENR2) */
00358 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) || defined(HAVE_OPENR2) */
00359 ;
00360 
00361 static const char config[] = "chan_dahdi.conf";
00362 
00363 #define SIG_EM    DAHDI_SIG_EM
00364 #define SIG_EMWINK   (0x0100000 | DAHDI_SIG_EM)
00365 #define SIG_FEATD (0x0200000 | DAHDI_SIG_EM)
00366 #define  SIG_FEATDMF (0x0400000 | DAHDI_SIG_EM)
00367 #define  SIG_FEATB   (0x0800000 | DAHDI_SIG_EM)
00368 #define  SIG_E911 (0x1000000 | DAHDI_SIG_EM)
00369 #define  SIG_FEATDMF_TA (0x2000000 | DAHDI_SIG_EM)
00370 #define  SIG_FGC_CAMA   (0x4000000 | DAHDI_SIG_EM)
00371 #define  SIG_FGC_CAMAMF (0x8000000 | DAHDI_SIG_EM)
00372 #define SIG_FXSLS DAHDI_SIG_FXSLS
00373 #define SIG_FXSGS DAHDI_SIG_FXSGS
00374 #define SIG_FXSKS DAHDI_SIG_FXSKS
00375 #define SIG_FXOLS DAHDI_SIG_FXOLS
00376 #define SIG_FXOGS DAHDI_SIG_FXOGS
00377 #define SIG_FXOKS DAHDI_SIG_FXOKS
00378 #define SIG_PRI      DAHDI_SIG_CLEAR
00379 #define SIG_BRI      (0x2000000 | DAHDI_SIG_CLEAR)
00380 #define SIG_BRI_PTMP (0X4000000 | DAHDI_SIG_CLEAR)
00381 #define SIG_SS7      (0x1000000 | DAHDI_SIG_CLEAR)
00382 #define SIG_MFCR2    DAHDI_SIG_CAS
00383 #define  SIG_SF      DAHDI_SIG_SF
00384 #define SIG_SFWINK   (0x0100000 | DAHDI_SIG_SF)
00385 #define SIG_SF_FEATD (0x0200000 | DAHDI_SIG_SF)
00386 #define  SIG_SF_FEATDMF (0x0400000 | DAHDI_SIG_SF)
00387 #define  SIG_SF_FEATB   (0x0800000 | DAHDI_SIG_SF)
00388 #define SIG_EM_E1 DAHDI_SIG_EM_E1
00389 
00390 #ifdef LOTS_OF_SPANS
00391 #define NUM_SPANS DAHDI_MAX_SPANS
00392 #else
00393 #define NUM_SPANS       32
00394 #endif
00395 
00396 #define CHAN_PSEUDO  -2
00397 
00398 #define CALLPROGRESS_PROGRESS    1
00399 #define CALLPROGRESS_FAX_OUTGOING   2
00400 #define CALLPROGRESS_FAX_INCOMING   4
00401 #define CALLPROGRESS_FAX      (CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING)
00402 
00403 #define NUM_CADENCE_MAX 25
00404 static int num_cadence = 4;
00405 static int user_has_defined_cadences = 0;
00406 
00407 static struct dahdi_ring_cadence cadences[NUM_CADENCE_MAX] = {
00408    { { 125, 125, 2000, 4000 } },       /*!< Quick chirp followed by normal ring */
00409    { { 250, 250, 500, 1000, 250, 250, 500, 4000 } }, /*!< British style ring */
00410    { { 125, 125, 125, 125, 125, 4000 } }, /*!< Three short bursts */
00411    { { 1000, 500, 2500, 5000 } },   /*!< Long ring */
00412 };
00413 
00414 /*! \brief cidrings says in which pause to transmit the cid information, where the first pause
00415  * is 1, the second pause is 2 and so on.
00416  */
00417 
00418 static int cidrings[NUM_CADENCE_MAX] = {
00419    2,                            /*!< Right after first long ring */
00420    4,                            /*!< Right after long part */
00421    3,                            /*!< After third chirp */
00422    2,                            /*!< Second spell */
00423 };
00424 
00425 /* ETSI EN300 659-1 specifies the ring pulse between 200 and 300 mS */
00426 static struct dahdi_ring_cadence AS_RP_cadence = {{250, 10000}};
00427 
00428 #define ISTRUNK(p) ((p->sig == SIG_FXSLS) || (p->sig == SIG_FXSKS) || \
00429          (p->sig == SIG_FXSGS) || (p->sig == SIG_PRI))
00430 
00431 #define CANBUSYDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */)
00432 #define CANPROGRESSDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */)
00433 
00434 static char defaultcic[64] = "";
00435 static char defaultozz[64] = "";
00436 
00437 /*! Run this script when the MWI state changes on an FXO line, if mwimonitor is enabled */
00438 static char mwimonitornotify[PATH_MAX] = "";
00439 #ifndef HAVE_DAHDI_LINEREVERSE_VMWI
00440 static int  mwisend_rpas = 0;
00441 #endif
00442 
00443 static char progzone[10] = "";
00444 
00445 static int usedistinctiveringdetection = 0;
00446 static int distinctiveringaftercid = 0;
00447 
00448 static int numbufs = 4;
00449 
00450 static int mwilevel = 512;
00451 static int dtmfcid_level = 256;
00452 
00453 #define REPORT_CHANNEL_ALARMS 1
00454 #define REPORT_SPAN_ALARMS    2 
00455 static int report_alarms = REPORT_CHANNEL_ALARMS;
00456 
00457 #ifdef HAVE_PRI
00458 static int pridebugfd = -1;
00459 static char pridebugfilename[1024] = "";
00460 #endif
00461 
00462 /*! \brief Wait up to 16 seconds for first digit (FXO logic) */
00463 static int firstdigittimeout = 16000;
00464 
00465 /*! \brief How long to wait for following digits (FXO logic) */
00466 static int gendigittimeout = 8000;
00467 
00468 /*! \brief How long to wait for an extra digit, if there is an ambiguous match */
00469 static int matchdigittimeout = 3000;
00470 
00471 /*! \brief Protect the interface list (of dahdi_pvt's) */
00472 AST_MUTEX_DEFINE_STATIC(iflock);
00473 
00474 
00475 static int ifcount = 0;
00476 
00477 #ifdef HAVE_PRI
00478 AST_MUTEX_DEFINE_STATIC(pridebugfdlock);
00479 #endif
00480 
00481 /*! \brief Protect the monitoring thread, so only one process can kill or start it, and not
00482    when it's doing something critical. */
00483 AST_MUTEX_DEFINE_STATIC(monlock);
00484 
00485 /*! \brief This is the thread for the monitor which checks for input on the channels
00486    which are not currently in use. */
00487 static pthread_t monitor_thread = AST_PTHREADT_NULL;
00488 static ast_cond_t ss_thread_complete;
00489 AST_MUTEX_DEFINE_STATIC(ss_thread_lock);
00490 AST_MUTEX_DEFINE_STATIC(restart_lock);
00491 static int ss_thread_count = 0;
00492 static int num_restart_pending = 0;
00493 
00494 static int restart_monitor(void);
00495 
00496 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);
00497 
00498 static int dahdi_sendtext(struct ast_channel *c, const char *text);
00499 
00500 static void mwi_event_cb(const struct ast_event *event, void *userdata)
00501 {
00502    /* This module does not handle MWI in an event-based manner.  However, it
00503     * subscribes to MWI for each mailbox that is configured so that the core
00504     * knows that we care about it.  Then, chan_dahdi will get the MWI from the
00505     * event cache instead of checking the mailbox directly. */
00506 }
00507 
00508 /*! \brief Avoid the silly dahdi_getevent which ignores a bunch of events */
00509 static inline int dahdi_get_event(int fd)
00510 {
00511    int j;
00512    if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
00513       return -1;
00514    return j;
00515 }
00516 
00517 /*! \brief Avoid the silly dahdi_waitevent which ignores a bunch of events */
00518 static inline int dahdi_wait_event(int fd)
00519 {
00520    int i, j = 0;
00521    i = DAHDI_IOMUX_SIGEVENT;
00522    if (ioctl(fd, DAHDI_IOMUX, &i) == -1)
00523       return -1;
00524    if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
00525       return -1;
00526    return j;
00527 }
00528 
00529 /*! Chunk size to read -- we use 20ms chunks to make things happy. */
00530 #define READ_SIZE 160
00531 
00532 #define MASK_AVAIL      (1 << 0) /*!< Channel available for PRI use */
00533 #define MASK_INUSE      (1 << 1) /*!< Channel currently in use */
00534 
00535 #define CALLWAITING_SILENT_SAMPLES     ((300 * 8) / READ_SIZE) /*!< 300 ms */
00536 #define CALLWAITING_REPEAT_SAMPLES     ((10000 * 8) / READ_SIZE) /*!< 10,000 ms */
00537 #define CALLWAITING_SUPPRESS_SAMPLES   ((100 * 8) / READ_SIZE) /*!< 100 ms */
00538 #define CIDCW_EXPIRE_SAMPLES        ((500 * 8) / READ_SIZE) /*!< 500 ms */
00539 #define MIN_MS_SINCE_FLASH          ((2000) )   /*!< 2000 ms */
00540 #define DEFAULT_RINGT               ((8000 * 8) / READ_SIZE) /*!< 8,000 ms */
00541 #define DEFAULT_DIALTONE_DETECT_TIMEOUT ((10000 * 8) / READ_SIZE) /*!< 10,000 ms */
00542 
00543 struct dahdi_pvt;
00544 
00545 /*!
00546  * \brief Configured ring timeout base.
00547  * \note Value computed from "ringtimeout" read in from chan_dahdi.conf if it exists.
00548  */
00549 static int ringt_base = DEFAULT_RINGT;
00550 
00551 #if defined(HAVE_SS7)
00552 
00553 struct dahdi_ss7 {
00554    struct sig_ss7_linkset ss7;
00555 };
00556 
00557 static struct dahdi_ss7 linksets[NUM_SPANS];
00558 
00559 static int cur_ss7type = -1;
00560 static int cur_linkset = -1;
00561 static int cur_pointcode = -1;
00562 static int cur_cicbeginswith = -1;
00563 static int cur_adjpointcode = -1;
00564 static int cur_networkindicator = -1;
00565 static int cur_defaultdpc = -1;
00566 #endif   /* defined(HAVE_SS7) */
00567 
00568 #ifdef HAVE_OPENR2
00569 struct dahdi_mfcr2_conf {
00570    openr2_variant_t variant;
00571    int mfback_timeout;
00572    int metering_pulse_timeout;
00573    int max_ani;
00574    int max_dnis;
00575 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2
00576    int dtmf_time_on;
00577    int dtmf_time_off;
00578 #endif
00579 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 3
00580    int dtmf_end_timeout;
00581 #endif
00582    signed int get_ani_first:2;
00583 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
00584    signed int skip_category_request:2;
00585 #endif
00586    unsigned int call_files:1;
00587    unsigned int allow_collect_calls:1;
00588    unsigned int charge_calls:1;
00589    unsigned int accept_on_offer:1;
00590    unsigned int forced_release:1;
00591    unsigned int double_answer:1;
00592    signed int immediate_accept:2;
00593 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2
00594    signed int dtmf_dialing:2;
00595    signed int dtmf_detection:2;
00596 #endif
00597    char logdir[OR2_MAX_PATH];
00598    char r2proto_file[OR2_MAX_PATH];
00599    openr2_log_level_t loglevel;
00600    openr2_calling_party_category_t category;
00601 };
00602 
00603 /* MFC-R2 pseudo-link structure */
00604 struct dahdi_mfcr2 {
00605    pthread_t r2master;            /*!< Thread of master */
00606    openr2_context_t *protocol_context;    /*!< OpenR2 context handle */
00607    struct dahdi_pvt *pvts[SIG_MFCR2_MAX_CHANNELS];     /*!< Member channel pvt structs */
00608    int numchans;                          /*!< Number of channels in this R2 block */
00609    struct dahdi_mfcr2_conf conf;         /*!< Configuration used to setup this pseudo-link */
00610 };
00611 
00612 /* malloc'd array of malloc'd r2links */
00613 static struct dahdi_mfcr2 **r2links;
00614 /* how many r2links have been malloc'd */
00615 static int r2links_count = 0;
00616 
00617 #endif /* HAVE_OPENR2 */
00618 
00619 #ifdef HAVE_PRI
00620 
00621 struct dahdi_pri {
00622    int dchannels[SIG_PRI_NUM_DCHANS];     /*!< What channel are the dchannels on */
00623    int mastertrunkgroup;               /*!< What trunk group is our master */
00624    int prilogicalspan;                 /*!< Logical span number within trunk group */
00625    struct sig_pri_span pri;
00626 };
00627 
00628 static struct dahdi_pri pris[NUM_SPANS];
00629 
00630 #if defined(HAVE_PRI_CCSS)
00631 /*! DAHDI PRI CCSS agent and monitor type name. */
00632 static const char dahdi_pri_cc_type[] = "DAHDI/PRI";
00633 #endif   /* defined(HAVE_PRI_CCSS) */
00634 
00635 #else
00636 /*! Shut up the compiler */
00637 struct dahdi_pri;
00638 #endif
00639 
00640 #define SUB_REAL  0        /*!< Active call */
00641 #define SUB_CALLWAIT 1        /*!< Call-Waiting call on hold */
00642 #define SUB_THREEWAY 2        /*!< Three-way call */
00643 
00644 /* Polarity states */
00645 #define POLARITY_IDLE   0
00646 #define POLARITY_REV    1
00647 
00648 
00649 struct distRingData {
00650    int ring[3];
00651    int range;
00652 };
00653 struct ringContextData {
00654    char contextData[AST_MAX_CONTEXT];
00655 };
00656 struct dahdi_distRings {
00657    struct distRingData ringnum[3];
00658    struct ringContextData ringContext[3];
00659 };
00660 
00661 static const char * const subnames[] = {
00662    "Real",
00663    "Callwait",
00664    "Threeway"
00665 };
00666 
00667 struct dahdi_subchannel {
00668    int dfd;
00669    struct ast_channel *owner;
00670    int chan;
00671    short buffer[AST_FRIENDLY_OFFSET/2 + READ_SIZE];
00672    struct ast_frame f;     /*!< One frame for each channel.  How did this ever work before? */
00673    unsigned int needringing:1;
00674    unsigned int needbusy:1;
00675    unsigned int needcongestion:1;
00676    unsigned int needanswer:1;
00677    unsigned int needflash:1;
00678    unsigned int needhold:1;
00679    unsigned int needunhold:1;
00680    unsigned int linear:1;
00681    unsigned int inthreeway:1;
00682    struct dahdi_confinfo curconf;
00683 };
00684 
00685 #define CONF_USER_REAL     (1 << 0)
00686 #define CONF_USER_THIRDCALL   (1 << 1)
00687 
00688 #define MAX_SLAVES   4
00689 
00690 /* States for sending MWI message
00691  * First three states are required for send Ring Pulse Alert Signal
00692  */
00693 typedef enum {
00694    MWI_SEND_NULL = 0,
00695    MWI_SEND_SA,
00696    MWI_SEND_SA_WAIT,
00697    MWI_SEND_PAUSE,
00698    MWI_SEND_SPILL,
00699    MWI_SEND_CLEANUP,
00700    MWI_SEND_DONE,
00701 } mwisend_states;
00702 
00703 struct mwisend_info {
00704    struct   timeval  pause;
00705    mwisend_states    mwisend_current;
00706 };
00707 
00708 /*! Specify the lists dahdi_pvt can be put in. */
00709 enum DAHDI_IFLIST {
00710    DAHDI_IFLIST_NONE,   /*!< The dahdi_pvt is not in any list. */
00711    DAHDI_IFLIST_MAIN,   /*!< The dahdi_pvt is in the main interface list */
00712 #if defined(HAVE_PRI)
00713    DAHDI_IFLIST_NO_B_CHAN, /*!< The dahdi_pvt is in a no B channel interface list */
00714 #endif   /* defined(HAVE_PRI) */
00715 };
00716 
00717 struct dahdi_pvt {
00718    ast_mutex_t lock;             /*!< Channel private lock. */
00719    struct callerid_state *cs;
00720    struct ast_channel *owner;       /*!< Our current active owner (if applicable) */
00721                      /*!< Up to three channels can be associated with this call */
00722 
00723    struct dahdi_subchannel sub_unused;    /*!< Just a safety precaution */
00724    struct dahdi_subchannel subs[3];       /*!< Sub-channels */
00725    struct dahdi_confinfo saveconf;        /*!< Saved conference info */
00726 
00727    struct dahdi_pvt *slaves[MAX_SLAVES];     /*!< Slave to us (follows our conferencing) */
00728    struct dahdi_pvt *master;           /*!< Master to us (we follow their conferencing) */
00729    int inconference;          /*!< If our real should be in the conference */
00730 
00731    int bufsize;                /*!< Size of the buffers */
00732    int buf_no;             /*!< Number of buffers */
00733    int buf_policy;            /*!< Buffer policy */
00734    int faxbuf_no;              /*!< Number of Fax buffers */
00735    int faxbuf_policy;          /*!< Fax buffer policy */
00736    int sig;             /*!< Signalling style */
00737    /*!
00738     * \brief Nonzero if the signaling type is sent over a radio.
00739     * \note Set to a couple of nonzero values but it is only tested like a boolean.
00740     */
00741    int radio;
00742    int outsigmod;             /*!< Outbound Signalling style (modifier) */
00743    int oprmode;               /*!< "Operator Services" mode */
00744    struct dahdi_pvt *oprpeer;          /*!< "Operator Services" peer tech_pvt ptr */
00745    /*! \brief Amount of gain to increase during caller id */
00746    float cid_rxgain;
00747    /*! \brief Software Rx gain set by chan_dahdi.conf */
00748    float rxgain;
00749    /*! \brief Software Tx gain set by chan_dahdi.conf */
00750    float txgain;
00751 
00752    float txdrc; /*!< Dynamic Range Compression factor. a number between 1 and 6ish */
00753    float rxdrc;
00754    
00755    int tonezone;              /*!< tone zone for this chan, or -1 for default */
00756    enum DAHDI_IFLIST which_iflist;  /*!< Which interface list is this structure listed? */
00757    struct dahdi_pvt *next;          /*!< Next channel in list */
00758    struct dahdi_pvt *prev;          /*!< Prev channel in list */
00759 
00760    /* flags */
00761 
00762    /*!
00763     * \brief TRUE if ADSI (Analog Display Services Interface) available
00764     * \note Set from the "adsi" value read in from chan_dahdi.conf
00765     */
00766    unsigned int adsi:1;
00767    /*!
00768     * \brief TRUE if we can use a polarity reversal to mark when an outgoing
00769     * call is answered by the remote party.
00770     * \note Set from the "answeronpolarityswitch" value read in from chan_dahdi.conf
00771     */
00772    unsigned int answeronpolarityswitch:1;
00773    /*!
00774     * \brief TRUE if busy detection is enabled.
00775     * (Listens for the beep-beep busy pattern.)
00776     * \note Set from the "busydetect" value read in from chan_dahdi.conf
00777     */
00778    unsigned int busydetect:1;
00779    /*!
00780     * \brief TRUE if call return is enabled.
00781     * (*69, if your dialplan doesn't catch this first)
00782     * \note Set from the "callreturn" value read in from chan_dahdi.conf
00783     */
00784    unsigned int callreturn:1;
00785    /*!
00786     * \brief TRUE if busy extensions will hear the call-waiting tone
00787     * and can use hook-flash to switch between callers.
00788     * \note Can be disabled by dialing *70.
00789     * \note Initialized with the "callwaiting" value read in from chan_dahdi.conf
00790     */
00791    unsigned int callwaiting:1;
00792    /*!
00793     * \brief TRUE if send caller ID for Call Waiting
00794     * \note Set from the "callwaitingcallerid" value read in from chan_dahdi.conf
00795     */
00796    unsigned int callwaitingcallerid:1;
00797    /*!
00798     * \brief TRUE if support for call forwarding enabled.
00799     * Dial *72 to enable call forwarding.
00800     * Dial *73 to disable call forwarding.
00801     * \note Set from the "cancallforward" value read in from chan_dahdi.conf
00802     */
00803    unsigned int cancallforward:1;
00804    /*!
00805     * \brief TRUE if support for call parking is enabled.
00806     * \note Set from the "canpark" value read in from chan_dahdi.conf
00807     */
00808    unsigned int canpark:1;
00809    /*! \brief TRUE if to wait for a DTMF digit to confirm answer */
00810    unsigned int confirmanswer:1;
00811    /*!
00812     * \brief TRUE if the channel is to be destroyed on hangup.
00813     * (Used by pseudo channels.)
00814     */
00815    unsigned int destroy:1;
00816    unsigned int didtdd:1;           /*!< flag to say its done it once */
00817    /*! \brief TRUE if analog type line dialed no digits in Dial() */
00818    unsigned int dialednone:1;
00819    /*!
00820     * \brief TRUE if in the process of dialing digits or sending something.
00821     * \note This is used as a receive squelch for ISDN until connected.
00822     */
00823    unsigned int dialing:1;
00824    /*! \brief TRUE if the transfer capability of the call is digital. */
00825    unsigned int digital:1;
00826    /*! \brief TRUE if Do-Not-Disturb is enabled, present only for non sig_analog */
00827    unsigned int dnd:1;
00828    /*! \brief XXX BOOLEAN Purpose??? */
00829    unsigned int echobreak:1;
00830    /*!
00831     * \brief TRUE if echo cancellation enabled when bridged.
00832     * \note Initialized with the "echocancelwhenbridged" value read in from chan_dahdi.conf
00833     * \note Disabled if the echo canceller is not setup.
00834     */
00835    unsigned int echocanbridged:1;
00836    /*! \brief TRUE if echo cancellation is turned on. */
00837    unsigned int echocanon:1;
00838    /*! \brief TRUE if a fax tone has already been handled. */
00839    unsigned int faxhandled:1;
00840    /*! TRUE if dynamic faxbuffers are configured for use, default is OFF */
00841    unsigned int usefaxbuffers:1;
00842    /*! TRUE while buffer configuration override is in use */
00843    unsigned int bufferoverrideinuse:1;
00844    /*! \brief TRUE if over a radio and dahdi_read() has been called. */
00845    unsigned int firstradio:1;
00846    /*!
00847     * \brief TRUE if the call will be considered "hung up" on a polarity reversal.
00848     * \note Set from the "hanguponpolarityswitch" value read in from chan_dahdi.conf
00849     */
00850    unsigned int hanguponpolarityswitch:1;
00851    /*! \brief TRUE if DTMF detection needs to be done by hardware. */
00852    unsigned int hardwaredtmf:1;
00853    /*!
00854     * \brief TRUE if the outgoing caller ID is blocked/hidden.
00855     * \note Caller ID can be disabled by dialing *67.
00856     * \note Caller ID can be enabled by dialing *82.
00857     * \note Initialized with the "hidecallerid" value read in from chan_dahdi.conf
00858     */
00859    unsigned int hidecallerid:1;
00860    /*!
00861     * \brief TRUE if hide just the name not the number for legacy PBX use.
00862     * \note Only applies to PRI channels.
00863     * \note Set from the "hidecalleridname" value read in from chan_dahdi.conf
00864     */
00865    unsigned int hidecalleridname:1;
00866    /*! \brief TRUE if DTMF detection is disabled. */
00867    unsigned int ignoredtmf:1;
00868    /*!
00869     * \brief TRUE if the channel should be answered immediately
00870     * without attempting to gather any digits.
00871     * \note Set from the "immediate" value read in from chan_dahdi.conf
00872     */
00873    unsigned int immediate:1;
00874    /*! \brief TRUE if in an alarm condition. */
00875    unsigned int inalarm:1;
00876    /*! \brief TRUE if TDD in MATE mode */
00877    unsigned int mate:1;
00878    /*! \brief TRUE if we originated the call leg. */
00879    unsigned int outgoing:1;
00880    /* unsigned int overlapdial:1;         unused and potentially confusing */
00881    /*!
00882     * \brief TRUE if busy extensions will hear the call-waiting tone
00883     * and can use hook-flash to switch between callers.
00884     * \note Set from the "callwaiting" value read in from chan_dahdi.conf
00885     */
00886    unsigned int permcallwaiting:1;
00887    /*!
00888     * \brief TRUE if the outgoing caller ID is blocked/restricted/hidden.
00889     * \note Set from the "hidecallerid" value read in from chan_dahdi.conf
00890     */
00891    unsigned int permhidecallerid:1;
00892    /*!
00893     * \brief TRUE if PRI congestion/busy indications are sent out-of-band.
00894     * \note Set from the "priindication" value read in from chan_dahdi.conf
00895     */
00896    unsigned int priindication_oob:1;
00897    /*!
00898     * \brief TRUE if PRI B channels are always exclusively selected.
00899     * \note Set from the "priexclusive" value read in from chan_dahdi.conf
00900     */
00901    unsigned int priexclusive:1;
00902    /*!
00903     * \brief TRUE if we will pulse dial.
00904     * \note Set from the "pulsedial" value read in from chan_dahdi.conf
00905     */
00906    unsigned int pulse:1;
00907    /*! \brief TRUE if a pulsed digit was detected. (Pulse dial phone detected) */
00908    unsigned int pulsedial:1;
00909    unsigned int restartpending:1;      /*!< flag to ensure counted only once for restart */
00910    /*!
00911     * \brief TRUE if caller ID is restricted.
00912     * \note Set but not used.  Should be deleted.  Redundant with permhidecallerid.
00913     * \note Set from the "restrictcid" value read in from chan_dahdi.conf
00914     */
00915    unsigned int restrictcid:1;
00916    /*!
00917     * \brief TRUE if three way calling is enabled
00918     * \note Set from the "threewaycalling" value read in from chan_dahdi.conf
00919     */
00920    unsigned int threewaycalling:1;
00921    /*!
00922     * \brief TRUE if call transfer is enabled
00923     * \note For FXS ports (either direct analog or over T1/E1):
00924     *   Support flash-hook call transfer
00925     * \note For digital ports using ISDN PRI protocols:
00926     *   Support switch-side transfer (called 2BCT, RLT or other names)
00927     * \note Set from the "transfer" value read in from chan_dahdi.conf
00928     */
00929    unsigned int transfer:1;
00930    /*!
00931     * \brief TRUE if caller ID is used on this channel.
00932     * \note PRI and SS7 spans will save caller ID from the networking peer.
00933     * \note FXS ports will generate the caller ID spill.
00934     * \note FXO ports will listen for the caller ID spill.
00935     * \note Set from the "usecallerid" value read in from chan_dahdi.conf
00936     */
00937    unsigned int use_callerid:1;
00938    /*!
00939     * \brief TRUE if we will use the calling presentation setting
00940     * from the Asterisk channel for outgoing calls.
00941     * \note Only applies to PRI and SS7 channels.
00942     * \note Set from the "usecallingpres" value read in from chan_dahdi.conf
00943     */
00944    unsigned int use_callingpres:1;
00945    /*!
00946     * \brief TRUE if distinctive rings are to be detected.
00947     * \note For FXO lines
00948     * \note Set indirectly from the "usedistinctiveringdetection" value read in from chan_dahdi.conf
00949     */
00950    unsigned int usedistinctiveringdetection:1;
00951    /*!
00952     * \brief TRUE if we should use the callerid from incoming call on dahdi transfer.
00953     * \note Set from the "useincomingcalleridondahditransfer" value read in from chan_dahdi.conf
00954     */
00955    unsigned int dahditrcallerid:1;
00956    /*!
00957     * \brief TRUE if allowed to flash-transfer to busy channels.
00958     * \note Set from the "transfertobusy" value read in from chan_dahdi.conf
00959     */
00960    unsigned int transfertobusy:1;
00961    /*!
00962     * \brief TRUE if the FXO port monitors for neon type MWI indications from the other end.
00963     * \note Set if the "mwimonitor" value read in contains "neon" from chan_dahdi.conf
00964     */
00965    unsigned int mwimonitor_neon:1;
00966    /*!
00967     * \brief TRUE if the FXO port monitors for fsk type MWI indications from the other end.
00968     * \note Set if the "mwimonitor" value read in contains "fsk" from chan_dahdi.conf
00969     */
00970    unsigned int mwimonitor_fsk:1;
00971    /*!
00972     * \brief TRUE if the FXO port monitors for rpas precursor to fsk MWI indications from the other end.
00973     * \note RPAS - Ring Pulse Alert Signal
00974     * \note Set if the "mwimonitor" value read in contains "rpas" from chan_dahdi.conf
00975     */
00976    unsigned int mwimonitor_rpas:1;
00977    /*! \brief TRUE if an MWI monitor thread is currently active */
00978    unsigned int mwimonitoractive:1;
00979    /*! \brief TRUE if a MWI message sending thread is active */
00980    unsigned int mwisendactive:1;
00981    /*!
00982     * \brief TRUE if channel is out of reset and ready
00983     * \note Set but not used.
00984     */
00985    unsigned int inservice:1;
00986    /*!
00987     * \brief TRUE if the channel is locally blocked.
00988     * \note Applies to SS7 and MFCR2 channels.
00989     */
00990    unsigned int locallyblocked:1;
00991    /*!
00992     * \brief TRUE if the channel is remotely blocked.
00993     * \note Applies to SS7 and MFCR2 channels.
00994     */
00995    unsigned int remotelyblocked:1;
00996    /*!
00997     * \brief TRUE if the channel alarms will be managed also as Span ones
00998     * \note Applies to all channels
00999     */
01000    unsigned int manages_span_alarms:1;
01001 
01002 #if defined(HAVE_PRI)
01003    struct sig_pri_span *pri;
01004    int logicalspan;
01005 #endif
01006    /*!
01007     * \brief TRUE if SMDI (Simplified Message Desk Interface) is enabled
01008     * \note Set from the "usesmdi" value read in from chan_dahdi.conf
01009     */
01010    unsigned int use_smdi:1;
01011    struct mwisend_info mwisend_data;
01012    /*! \brief The SMDI interface to get SMDI messages from. */
01013    struct ast_smdi_interface *smdi_iface;
01014 
01015    /*! \brief Distinctive Ring data */
01016    struct dahdi_distRings drings;
01017 
01018    /*!
01019     * \brief The configured context for incoming calls.
01020     * \note The "context" string read in from chan_dahdi.conf
01021     */
01022    char context[AST_MAX_CONTEXT];
01023    /*! 
01024     * \brief A description for the channel configuration
01025     * \note The "description" string read in from chan_dahdi.conf
01026     */
01027    char description[32];
01028    /*!
01029     * \brief Saved context string.
01030     */
01031    char defcontext[AST_MAX_CONTEXT];
01032    /*! \brief Extension to use in the dialplan. */
01033    char exten[AST_MAX_EXTENSION];
01034    /*!
01035     * \brief Language configured for calls.
01036     * \note The "language" string read in from chan_dahdi.conf
01037     */
01038    char language[MAX_LANGUAGE];
01039    /*!
01040     * \brief The configured music-on-hold class to use for calls.
01041     * \note The "musicclass" or "mohinterpret" or "musiconhold" string read in from chan_dahdi.conf
01042     */
01043    char mohinterpret[MAX_MUSICCLASS];
01044    /*!
01045     * \brief Suggested music-on-hold class for peer channel to use for calls.
01046     * \note The "mohsuggest" string read in from chan_dahdi.conf
01047     */
01048    char mohsuggest[MAX_MUSICCLASS];
01049    char parkinglot[AST_MAX_EXTENSION]; /*!< Parking lot for this channel */
01050 #if defined(HAVE_PRI) || defined(HAVE_SS7)
01051    /*! \brief Automatic Number Identification number (Alternate PRI caller ID number) */
01052    char cid_ani[AST_MAX_EXTENSION];
01053 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
01054    /*! \brief Automatic Number Identification code from PRI */
01055    int cid_ani2;
01056    /*! \brief Caller ID number from an incoming call. */
01057    char cid_num[AST_MAX_EXTENSION];
01058    /*!
01059     * \brief Caller ID tag from incoming call
01060     * \note the "cid_tag" string read in from chan_dahdi.conf
01061     */
01062    char cid_tag[AST_MAX_EXTENSION];
01063    /*! \brief Caller ID Q.931 TON/NPI field values.  Set by PRI. Zero otherwise. */
01064    int cid_ton;
01065    /*! \brief Caller ID name from an incoming call. */
01066    char cid_name[AST_MAX_EXTENSION];
01067    /*! \brief Caller ID subaddress from an incoming call. */
01068    char cid_subaddr[AST_MAX_EXTENSION];
01069    char *origcid_num;            /*!< malloced original callerid */
01070    char *origcid_name;           /*!< malloced original callerid */
01071    /*! \brief Call waiting number. */
01072    char callwait_num[AST_MAX_EXTENSION];
01073    /*! \brief Call waiting name. */
01074    char callwait_name[AST_MAX_EXTENSION];
01075    /*! \brief Redirecting Directory Number Information Service (RDNIS) number */
01076    char rdnis[AST_MAX_EXTENSION];
01077    /*! \brief Dialed Number Identifier */
01078    char dnid[AST_MAX_EXTENSION];
01079    /*!
01080     * \brief Bitmapped groups this belongs to.
01081     * \note The "group" bitmapped group string read in from chan_dahdi.conf
01082     */
01083    ast_group_t group;
01084    /*! \brief Default call PCM encoding format: DAHDI_LAW_ALAW or DAHDI_LAW_MULAW. */
01085    int law_default;
01086    /*! \brief Active PCM encoding format: DAHDI_LAW_ALAW or DAHDI_LAW_MULAW */
01087    int law;
01088    int confno;             /*!< Our conference */
01089    int confusers;             /*!< Who is using our conference */
01090    int propconfno;               /*!< Propagated conference number */
01091    /*!
01092     * \brief Bitmapped call groups this belongs to.
01093     * \note The "callgroup" bitmapped group string read in from chan_dahdi.conf
01094     */
01095    ast_group_t callgroup;
01096    /*!
01097     * \brief Bitmapped pickup groups this belongs to.
01098     * \note The "pickupgroup" bitmapped group string read in from chan_dahdi.conf
01099     */
01100    ast_group_t pickupgroup;
01101    /*!
01102     * \brief Named call groups this belongs to.
01103     * \note The "namedcallgroup" string read in from chan_dahdi.conf
01104     */
01105    struct ast_namedgroups *named_callgroups;
01106    /*!
01107     * \brief Named pickup groups this belongs to.
01108     * \note The "namedpickupgroup" string read in from chan_dahdi.conf
01109     */
01110    struct ast_namedgroups *named_pickupgroups;
01111    /*!
01112     * \brief Channel variable list with associated values to set when a channel is created.
01113     * \note The "setvar" strings read in from chan_dahdi.conf
01114     */
01115    struct ast_variable *vars;
01116    int channel;               /*!< Channel Number */
01117    int span;               /*!< Span number */
01118    time_t guardtime;          /*!< Must wait this much time before using for new call */
01119    int cid_signalling;           /*!< CID signalling type bell202 or v23 */
01120    int cid_start;             /*!< CID start indicator, polarity or ring or DTMF without warning event */
01121    int dtmfcid_holdoff_state;    /*!< State indicator that allows for line to settle before checking for dtmf energy */
01122    struct timeval dtmfcid_delay;  /*!< Time value used for allow line to settle */
01123    int callingpres;           /*!< The value of calling presentation that we're going to use when placing a PRI call */
01124    int callwaitingrepeat;           /*!< How many samples to wait before repeating call waiting */
01125    int cidcwexpire;           /*!< When to stop waiting for CID/CW CAS response (In samples) */
01126    int cid_suppress_expire;      /*!< How many samples to suppress after a CID spill. */
01127    /*! \brief Analog caller ID waveform sample buffer */
01128    unsigned char *cidspill;
01129    /*! \brief Position in the cidspill buffer to send out next. */
01130    int cidpos;
01131    /*! \brief Length of the cidspill buffer containing samples. */
01132    int cidlen;
01133    /*! \brief Ring timeout timer?? */
01134    int ringt;
01135    /*!
01136     * \brief Ring timeout base.
01137     * \note Value computed indirectly from "ringtimeout" read in from chan_dahdi.conf
01138     */
01139    int ringt_base;
01140    /*!
01141     * \brief Number of most significant digits/characters to strip from the dialed number.
01142     * \note Feature is deprecated.  Use dialplan logic.
01143     * \note The characters are stripped before the PRI TON/NPI prefix
01144     * characters are processed.
01145     */
01146    int stripmsd;
01147    /*!
01148     * \brief TRUE if Call Waiting (CW) CPE Alert Signal (CAS) is being sent.
01149     * \note
01150     * After CAS is sent, the call waiting caller id will be sent if the phone
01151     * gives a positive reply.
01152     */
01153    int callwaitcas;
01154    /*! \brief Number of call waiting rings. */
01155    int callwaitrings;
01156    /*! \brief Echo cancel parameters. */
01157    struct {
01158       struct dahdi_echocanparams head;
01159       struct dahdi_echocanparam params[DAHDI_MAX_ECHOCANPARAMS];
01160    } echocancel;
01161    /*!
01162     * \brief Echo training time. 0 = disabled
01163     * \note Set from the "echotraining" value read in from chan_dahdi.conf
01164     */
01165    int echotraining;
01166    /*! \brief Filled with 'w'.  XXX Purpose?? */
01167    char echorest[20];
01168    /*!
01169     * \brief Number of times to see "busy" tone before hanging up.
01170     * \note Set from the "busycount" value read in from chan_dahdi.conf
01171     */
01172    int busycount;
01173    /*!
01174     * \brief Busy cadence pattern description.
01175     * \note Set from the "busypattern" value read from chan_dahdi.conf
01176     */
01177    struct ast_dsp_busy_pattern busy_cadence;
01178    /*!
01179     * \brief Bitmapped call progress detection flags. CALLPROGRESS_xxx values.
01180     * \note Bits set from the "callprogress" and "faxdetect" values read in from chan_dahdi.conf
01181     */
01182    int callprogress;
01183    /*!
01184     * \brief Number of milliseconds to wait for dialtone.
01185     * \note Set from the "waitfordialtone" value read in from chan_dahdi.conf
01186     */
01187    int waitfordialtone;
01188    /*!
01189     * \brief Number of frames to watch for dialtone in incoming calls
01190     * \note Set from the "dialtone_detect" value read in from chan_dahdi.conf
01191     */
01192    int dialtone_detect;
01193    int dialtone_scanning_time_elapsed; /*!< Amount of audio scanned for dialtone, in frames */
01194    struct timeval waitingfordt;        /*!< Time we started waiting for dialtone */
01195    struct timeval flashtime;        /*!< Last flash-hook time */
01196    /*! \brief Opaque DSP configuration structure. */
01197    struct ast_dsp *dsp;
01198    /*! \brief DAHDI dial operation command struct for ioctl() call. */
01199    struct dahdi_dialoperation dop;
01200    int whichwink;             /*!< SIG_FEATDMF_TA Which wink are we on? */
01201    /*! \brief Second part of SIG_FEATDMF_TA wink operation. */
01202    char finaldial[64];
01203    char accountcode[AST_MAX_ACCOUNT_CODE];      /*!< Account code */
01204    int amaflags;              /*!< AMA Flags */
01205    struct tdd_state *tdd;           /*!< TDD flag */
01206    /*! \brief Accumulated call forwarding number. */
01207    char call_forward[AST_MAX_EXTENSION];
01208    /*!
01209     * \brief Voice mailbox location.
01210     * \note Set from the "mailbox" string read in from chan_dahdi.conf
01211     */
01212    char mailbox[AST_MAX_EXTENSION];
01213    /*! \brief Opaque event subscription parameters for message waiting indication support. */
01214    struct ast_event_sub *mwi_event_sub;
01215    /*! \brief Delayed dialing for E911.  Overlap digits for ISDN. */
01216    char dialdest[256];
01217 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
01218    struct dahdi_vmwi_info mwisend_setting;            /*!< Which VMWI methods to use */
01219    unsigned int mwisend_fsk: 1;     /*! Variable for enabling FSK MWI handling in chan_dahdi */
01220    unsigned int mwisend_rpas:1;     /*! Variable for enabling Ring Pulse Alert before MWI FSK Spill */
01221 #endif
01222    int distinctivering;          /*!< Which distinctivering to use */
01223    int dtmfrelax;             /*!< whether to run in relaxed DTMF mode */
01224    /*! \brief Holding place for event injected from outside normal operation. */
01225    int fake_event;
01226    /*!
01227     * \brief Minimal time period (ms) between the answer polarity
01228     * switch and hangup polarity switch.
01229     */
01230    int polarityonanswerdelay;
01231    /*! \brief Start delay time if polarityonanswerdelay is nonzero. */
01232    struct timeval polaritydelaytv;
01233    /*!
01234     * \brief Send caller ID on FXS after this many rings. Set to 1 for US.
01235     * \note Set from the "sendcalleridafter" value read in from chan_dahdi.conf
01236     */
01237    int sendcalleridafter;
01238    /*! \brief Current line interface polarity. POLARITY_IDLE, POLARITY_REV */
01239    int polarity;
01240    /*! \brief DSP feature flags: DSP_FEATURE_xxx */
01241    int dsp_features;
01242 #if defined(HAVE_SS7)
01243    /*! \brief SS7 control parameters */
01244    struct sig_ss7_linkset *ss7;
01245 #endif   /* defined(HAVE_SS7) */
01246 #ifdef HAVE_OPENR2
01247    struct dahdi_mfcr2 *mfcr2;
01248    openr2_chan_t *r2chan;
01249    openr2_calling_party_category_t mfcr2_recvd_category;
01250    openr2_calling_party_category_t mfcr2_category;
01251    int mfcr2_dnis_index;
01252    int mfcr2_ani_index;
01253    int mfcr2call:1;
01254    int mfcr2_answer_pending:1;
01255    int mfcr2_charge_calls:1;
01256    int mfcr2_allow_collect_calls:1;
01257    int mfcr2_forced_release:1;
01258    int mfcr2_dnis_matched:1;
01259    int mfcr2_call_accepted:1;
01260    int mfcr2_accept_on_offer:1;
01261    int mfcr2_progress_sent:1;
01262 #endif
01263    /*! \brief DTMF digit in progress.  0 when no digit in progress. */
01264    char begindigit;
01265    /*! \brief TRUE if confrence is muted. */
01266    int muting;
01267    void *sig_pvt;
01268    struct ast_cc_config_params *cc_params;
01269    /* DAHDI channel names may differ greatly from the
01270     * string that was provided to an app such as Dial. We
01271     * need to save the original string passed to dahdi_request
01272     * for call completion purposes. This way, we can replicate
01273     * the original dialed string later.
01274     */
01275    char dialstring[AST_CHANNEL_NAME];
01276 };
01277 
01278 #define DATA_EXPORT_DAHDI_PVT(MEMBER)              \
01279    MEMBER(dahdi_pvt, cid_rxgain, AST_DATA_DOUBLE)        \
01280    MEMBER(dahdi_pvt, rxgain, AST_DATA_DOUBLE)         \
01281    MEMBER(dahdi_pvt, txgain, AST_DATA_DOUBLE)         \
01282    MEMBER(dahdi_pvt, txdrc, AST_DATA_DOUBLE)       \
01283    MEMBER(dahdi_pvt, rxdrc, AST_DATA_DOUBLE)       \
01284    MEMBER(dahdi_pvt, adsi, AST_DATA_BOOLEAN)       \
01285    MEMBER(dahdi_pvt, answeronpolarityswitch, AST_DATA_BOOLEAN) \
01286    MEMBER(dahdi_pvt, busydetect, AST_DATA_BOOLEAN)       \
01287    MEMBER(dahdi_pvt, callreturn, AST_DATA_BOOLEAN)       \
01288    MEMBER(dahdi_pvt, callwaiting, AST_DATA_BOOLEAN)      \
01289    MEMBER(dahdi_pvt, callwaitingcallerid, AST_DATA_BOOLEAN) \
01290    MEMBER(dahdi_pvt, cancallforward, AST_DATA_BOOLEAN)      \
01291    MEMBER(dahdi_pvt, canpark, AST_DATA_BOOLEAN)       \
01292    MEMBER(dahdi_pvt, confirmanswer, AST_DATA_BOOLEAN)    \
01293    MEMBER(dahdi_pvt, destroy, AST_DATA_BOOLEAN)       \
01294    MEMBER(dahdi_pvt, didtdd, AST_DATA_BOOLEAN)        \
01295    MEMBER(dahdi_pvt, dialednone, AST_DATA_BOOLEAN)       \
01296    MEMBER(dahdi_pvt, dialing, AST_DATA_BOOLEAN)       \
01297    MEMBER(dahdi_pvt, digital, AST_DATA_BOOLEAN)       \
01298    MEMBER(dahdi_pvt, dnd, AST_DATA_BOOLEAN)        \
01299    MEMBER(dahdi_pvt, echobreak, AST_DATA_BOOLEAN)        \
01300    MEMBER(dahdi_pvt, echocanbridged, AST_DATA_BOOLEAN)      \
01301    MEMBER(dahdi_pvt, echocanon, AST_DATA_BOOLEAN)        \
01302    MEMBER(dahdi_pvt, faxhandled, AST_DATA_BOOLEAN)       \
01303    MEMBER(dahdi_pvt, usefaxbuffers, AST_DATA_BOOLEAN)    \
01304    MEMBER(dahdi_pvt, bufferoverrideinuse, AST_DATA_BOOLEAN) \
01305    MEMBER(dahdi_pvt, firstradio, AST_DATA_BOOLEAN)       \
01306    MEMBER(dahdi_pvt, hanguponpolarityswitch, AST_DATA_BOOLEAN) \
01307    MEMBER(dahdi_pvt, hardwaredtmf, AST_DATA_BOOLEAN)     \
01308    MEMBER(dahdi_pvt, hidecallerid, AST_DATA_BOOLEAN)     \
01309    MEMBER(dahdi_pvt, hidecalleridname, AST_DATA_BOOLEAN)    \
01310    MEMBER(dahdi_pvt, ignoredtmf, AST_DATA_BOOLEAN)       \
01311    MEMBER(dahdi_pvt, immediate, AST_DATA_BOOLEAN)        \
01312    MEMBER(dahdi_pvt, inalarm, AST_DATA_BOOLEAN)       \
01313    MEMBER(dahdi_pvt, mate, AST_DATA_BOOLEAN)       \
01314    MEMBER(dahdi_pvt, outgoing, AST_DATA_BOOLEAN)         \
01315    MEMBER(dahdi_pvt, permcallwaiting, AST_DATA_BOOLEAN)     \
01316    MEMBER(dahdi_pvt, priindication_oob, AST_DATA_BOOLEAN)      \
01317    MEMBER(dahdi_pvt, priexclusive, AST_DATA_BOOLEAN)     \
01318    MEMBER(dahdi_pvt, pulse, AST_DATA_BOOLEAN)         \
01319    MEMBER(dahdi_pvt, pulsedial, AST_DATA_BOOLEAN)        \
01320    MEMBER(dahdi_pvt, restartpending, AST_DATA_BOOLEAN)      \
01321    MEMBER(dahdi_pvt, restrictcid, AST_DATA_BOOLEAN)      \
01322    MEMBER(dahdi_pvt, threewaycalling, AST_DATA_BOOLEAN)     \
01323    MEMBER(dahdi_pvt, transfer, AST_DATA_BOOLEAN)         \
01324    MEMBER(dahdi_pvt, use_callerid, AST_DATA_BOOLEAN)     \
01325    MEMBER(dahdi_pvt, use_callingpres, AST_DATA_BOOLEAN)     \
01326    MEMBER(dahdi_pvt, usedistinctiveringdetection, AST_DATA_BOOLEAN)  \
01327    MEMBER(dahdi_pvt, dahditrcallerid, AST_DATA_BOOLEAN)        \
01328    MEMBER(dahdi_pvt, transfertobusy, AST_DATA_BOOLEAN)         \
01329    MEMBER(dahdi_pvt, mwimonitor_neon, AST_DATA_BOOLEAN)        \
01330    MEMBER(dahdi_pvt, mwimonitor_fsk, AST_DATA_BOOLEAN)         \
01331    MEMBER(dahdi_pvt, mwimonitor_rpas, AST_DATA_BOOLEAN)        \
01332    MEMBER(dahdi_pvt, mwimonitoractive, AST_DATA_BOOLEAN)       \
01333    MEMBER(dahdi_pvt, mwisendactive, AST_DATA_BOOLEAN)       \
01334    MEMBER(dahdi_pvt, inservice, AST_DATA_BOOLEAN)           \
01335    MEMBER(dahdi_pvt, locallyblocked, AST_DATA_BOOLEAN)         \
01336    MEMBER(dahdi_pvt, remotelyblocked, AST_DATA_BOOLEAN)        \
01337    MEMBER(dahdi_pvt, manages_span_alarms, AST_DATA_BOOLEAN)    \
01338    MEMBER(dahdi_pvt, use_smdi, AST_DATA_BOOLEAN)            \
01339    MEMBER(dahdi_pvt, context, AST_DATA_STRING)           \
01340    MEMBER(dahdi_pvt, defcontext, AST_DATA_STRING)           \
01341    MEMBER(dahdi_pvt, description, AST_DATA_STRING)          \
01342    MEMBER(dahdi_pvt, exten, AST_DATA_STRING)          \
01343    MEMBER(dahdi_pvt, language, AST_DATA_STRING)          \
01344    MEMBER(dahdi_pvt, mohinterpret, AST_DATA_STRING)         \
01345    MEMBER(dahdi_pvt, mohsuggest, AST_DATA_STRING)           \
01346    MEMBER(dahdi_pvt, parkinglot, AST_DATA_STRING)
01347 
01348 AST_DATA_STRUCTURE(dahdi_pvt, DATA_EXPORT_DAHDI_PVT);
01349 
01350 static struct dahdi_pvt *iflist = NULL;   /*!< Main interface list start */
01351 static struct dahdi_pvt *ifend = NULL; /*!< Main interface list end */
01352 
01353 #if defined(HAVE_PRI)
01354 static struct dahdi_parms_pseudo {
01355    int buf_no;             /*!< Number of buffers */
01356    int buf_policy;            /*!< Buffer policy */
01357    int faxbuf_no;              /*!< Number of Fax buffers */
01358    int faxbuf_policy;          /*!< Fax buffer policy */
01359 } dahdi_pseudo_parms;
01360 #endif   /* defined(HAVE_PRI) */
01361 
01362 /*! \brief Channel configuration from chan_dahdi.conf .
01363  * This struct is used for parsing the [channels] section of chan_dahdi.conf.
01364  * Generally there is a field here for every possible configuration item.
01365  *
01366  * The state of fields is saved along the parsing and whenever a 'channel'
01367  * statement is reached, the current dahdi_chan_conf is used to configure the
01368  * channel (struct dahdi_pvt)
01369  *
01370  * \see dahdi_chan_init for the default values.
01371  */
01372 struct dahdi_chan_conf {
01373    struct dahdi_pvt chan;
01374 #ifdef HAVE_PRI
01375    struct dahdi_pri pri;
01376 #endif
01377 
01378 #if defined(HAVE_SS7)
01379    struct dahdi_ss7 ss7;
01380 #endif   /* defined(HAVE_SS7) */
01381 
01382 #ifdef HAVE_OPENR2
01383    struct dahdi_mfcr2_conf mfcr2;
01384 #endif
01385    struct dahdi_params timing;
01386    int is_sig_auto; /*!< Use channel signalling from DAHDI? */
01387    /*! Continue configuration even if a channel is not there. */
01388    int ignore_failed_channels;
01389 
01390    /*!
01391     * \brief The serial port to listen for SMDI data on
01392     * \note Set from the "smdiport" string read in from chan_dahdi.conf
01393     */
01394    char smdi_port[SMDI_MAX_FILENAME_LEN];
01395 };
01396 
01397 /*! returns a new dahdi_chan_conf with default values (by-value) */
01398 static struct dahdi_chan_conf dahdi_chan_conf_default(void)
01399 {
01400    /* recall that if a field is not included here it is initialized
01401     * to 0 or equivalent
01402     */
01403    struct dahdi_chan_conf conf = {
01404 #ifdef HAVE_PRI
01405       .pri.pri = {
01406          .nsf = PRI_NSF_NONE,
01407          .switchtype = PRI_SWITCH_NI2,
01408          .dialplan = PRI_UNKNOWN + 1,
01409          .localdialplan = PRI_NATIONAL_ISDN + 1,
01410          .nodetype = PRI_CPE,
01411          .qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL,
01412          .inband_on_setup_ack = 1,
01413          .inband_on_proceeding = 1,
01414 
01415 #if defined(HAVE_PRI_CCSS)
01416          .cc_ptmp_recall_mode = 1,/* specificRecall */
01417          .cc_qsig_signaling_link_req = 1,/* retain */
01418          .cc_qsig_signaling_link_rsp = 1,/* retain */
01419 #endif   /* defined(HAVE_PRI_CCSS) */
01420 
01421          .minunused = 2,
01422          .idleext = "",
01423          .idledial = "",
01424          .internationalprefix = "",
01425          .nationalprefix = "",
01426          .localprefix = "",
01427          .privateprefix = "",
01428          .unknownprefix = "",
01429          .colp_send = SIG_PRI_COLP_UPDATE,
01430          .resetinterval = -1,
01431       },
01432 #endif
01433 #if defined(HAVE_SS7)
01434       .ss7.ss7 = {
01435          .called_nai = SS7_NAI_NATIONAL,
01436          .calling_nai = SS7_NAI_NATIONAL,
01437          .internationalprefix = "",
01438          .nationalprefix = "",
01439          .subscriberprefix = "",
01440          .unknownprefix = ""
01441       },
01442 #endif   /* defined(HAVE_SS7) */
01443 #ifdef HAVE_OPENR2
01444       .mfcr2 = {
01445          .variant = OR2_VAR_ITU,
01446          .mfback_timeout = -1,
01447          .metering_pulse_timeout = -1,
01448          .max_ani = 10,
01449          .max_dnis = 4,
01450          .get_ani_first = -1,
01451 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
01452          .skip_category_request = -1,
01453 #endif
01454          .call_files = 0,
01455          .allow_collect_calls = 0,
01456          .charge_calls = 1,
01457          .accept_on_offer = 1,
01458          .forced_release = 0,
01459          .double_answer = 0,
01460          .immediate_accept = -1,
01461 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2
01462          .dtmf_dialing = -1,
01463          .dtmf_detection = -1,
01464          .dtmf_time_on = OR2_DEFAULT_DTMF_ON,
01465          .dtmf_time_off = OR2_DEFAULT_DTMF_OFF,
01466 #endif
01467 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 3
01468          .dtmf_end_timeout = -1,
01469 #endif
01470          .logdir = "",
01471          .r2proto_file = "",
01472          .loglevel = OR2_LOG_ERROR | OR2_LOG_WARNING,
01473          .category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER
01474       },
01475 #endif
01476       .chan = {
01477          .context = "default",
01478          .cid_num = "",
01479          .cid_name = "",
01480          .cid_tag = "",
01481          .mohinterpret = "default",
01482          .mohsuggest = "",
01483          .parkinglot = "",
01484          .transfertobusy = 1,
01485 
01486          .cid_signalling = CID_SIG_BELL,
01487          .cid_start = CID_START_RING,
01488          .dahditrcallerid = 0,
01489          .use_callerid = 1,
01490          .sig = -1,
01491          .outsigmod = -1,
01492 
01493          .cid_rxgain = +5.0,
01494 
01495          .tonezone = -1,
01496 
01497          .echocancel.head.tap_length = 1,
01498 
01499          .busycount = 3,
01500 
01501          .accountcode = "",
01502 
01503          .mailbox = "",
01504 
01505 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
01506          .mwisend_fsk = 1,
01507 #endif
01508          .polarityonanswerdelay = 600,
01509 
01510          .sendcalleridafter = DEFAULT_CIDRINGS,
01511 
01512          .buf_policy = DAHDI_POLICY_IMMEDIATE,
01513          .buf_no = numbufs,
01514          .usefaxbuffers = 0,
01515          .cc_params = ast_cc_config_params_init(),
01516       },
01517       .timing = {
01518          .prewinktime = -1,
01519          .preflashtime = -1,
01520          .winktime = -1,
01521          .flashtime = -1,
01522          .starttime = -1,
01523          .rxwinktime = -1,
01524          .rxflashtime = -1,
01525          .debouncetime = -1
01526       },
01527       .is_sig_auto = 1,
01528       .smdi_port = "/dev/ttyS0",
01529    };
01530 
01531    return conf;
01532 }
01533 
01534 
01535 static struct ast_channel *dahdi_request(const char *type, struct ast_format_cap *cap, const struct ast_channel *requestor, const char *data, int *cause);
01536 static int dahdi_digit_begin(struct ast_channel *ast, char digit);
01537 static int dahdi_digit_end(struct ast_channel *ast, char digit, unsigned int duration);
01538 static int dahdi_sendtext(struct ast_channel *c, const char *text);
01539 static int dahdi_call(struct ast_channel *ast, const char *rdest, int timeout);
01540 static int dahdi_hangup(struct ast_channel *ast);
01541 static int dahdi_answer(struct ast_channel *ast);
01542 static struct ast_frame *dahdi_read(struct ast_channel *ast);
01543 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame);
01544 static struct ast_frame *dahdi_exception(struct ast_channel *ast);
01545 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen);
01546 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
01547 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen);
01548 static int dahdi_queryoption(struct ast_channel *chan, int option, void *data, int *datalen);
01549 static int dahdi_func_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len);
01550 static int dahdi_func_write(struct ast_channel *chan, const char *function, char *data, const char *value);
01551 static int dahdi_devicestate(const char *data);
01552 static int dahdi_cc_callback(struct ast_channel *inbound, const char *dest, ast_cc_callback_fn callback);
01553 
01554 static struct ast_channel_tech dahdi_tech = {
01555    .type = "DAHDI",
01556    .description = tdesc,
01557    .requester = dahdi_request,
01558    .send_digit_begin = dahdi_digit_begin,
01559    .send_digit_end = dahdi_digit_end,
01560    .send_text = dahdi_sendtext,
01561    .call = dahdi_call,
01562    .hangup = dahdi_hangup,
01563    .answer = dahdi_answer,
01564    .read = dahdi_read,
01565    .write = dahdi_write,
01566    .bridge = dahdi_bridge,
01567    .exception = dahdi_exception,
01568    .indicate = dahdi_indicate,
01569    .fixup = dahdi_fixup,
01570    .setoption = dahdi_setoption,
01571    .queryoption = dahdi_queryoption,
01572    .func_channel_read = dahdi_func_read,
01573    .func_channel_write = dahdi_func_write,
01574    .devicestate = dahdi_devicestate,
01575    .cc_callback = dahdi_cc_callback,
01576 };
01577 
01578 #define GET_CHANNEL(p) ((p)->channel)
01579 
01580 #define SIG_PRI_LIB_HANDLE_CASES \
01581    SIG_PRI:                \
01582    case SIG_BRI:              \
01583    case SIG_BRI_PTMP
01584 
01585 /*!
01586  * \internal
01587  * \brief Determine if sig_pri handles the signaling.
01588  * \since 1.8
01589  *
01590  * \param signaling Signaling to determine if is for sig_pri.
01591  *
01592  * \return TRUE if the signaling is for sig_pri.
01593  */
01594 static inline int dahdi_sig_pri_lib_handles(int signaling)
01595 {
01596    int handles;
01597 
01598    switch (signaling) {
01599    case SIG_PRI_LIB_HANDLE_CASES:
01600       handles = 1;
01601       break;
01602    default:
01603       handles = 0;
01604       break;
01605    }
01606 
01607    return handles;
01608 }
01609 
01610 static int analog_lib_handles(int signalling, int radio, int oprmode)
01611 {
01612    switch (signalling) {
01613    case SIG_FXOLS:
01614    case SIG_FXOGS:
01615    case SIG_FXOKS:
01616    case SIG_FXSLS:
01617    case SIG_FXSGS:
01618    case SIG_FXSKS:
01619    case SIG_EMWINK:
01620    case SIG_EM:
01621    case SIG_EM_E1:
01622    case SIG_FEATD:
01623    case SIG_FEATDMF:
01624    case SIG_E911:
01625    case SIG_FGC_CAMA:
01626    case SIG_FGC_CAMAMF:
01627    case SIG_FEATB:
01628    case SIG_SFWINK:
01629    case SIG_SF:
01630    case SIG_SF_FEATD:
01631    case SIG_SF_FEATDMF:
01632    case SIG_FEATDMF_TA:
01633    case SIG_SF_FEATB:
01634       break;
01635    default:
01636       /* The rest of the function should cover the remainder of signalling types */
01637       return 0;
01638    }
01639 
01640    if (radio) {
01641       return 0;
01642    }
01643 
01644    if (oprmode) {
01645       return 0;
01646    }
01647 
01648    return 1;
01649 }
01650 
01651 static enum analog_sigtype dahdisig_to_analogsig(int sig)
01652 {
01653    switch (sig) {
01654    case SIG_FXOLS:
01655       return ANALOG_SIG_FXOLS;
01656    case SIG_FXOGS:
01657       return ANALOG_SIG_FXOGS;
01658    case SIG_FXOKS:
01659       return ANALOG_SIG_FXOKS;
01660    case SIG_FXSLS:
01661       return ANALOG_SIG_FXSLS;
01662    case SIG_FXSGS:
01663       return ANALOG_SIG_FXSGS;
01664    case SIG_FXSKS:
01665       return ANALOG_SIG_FXSKS;
01666    case SIG_EMWINK:
01667       return ANALOG_SIG_EMWINK;
01668    case SIG_EM:
01669       return ANALOG_SIG_EM;
01670    case SIG_EM_E1:
01671       return ANALOG_SIG_EM_E1;
01672    case SIG_FEATD:
01673       return ANALOG_SIG_FEATD;
01674    case SIG_FEATDMF:
01675       return ANALOG_SIG_FEATDMF;
01676    case SIG_E911:
01677       return SIG_E911;
01678    case SIG_FGC_CAMA:
01679       return ANALOG_SIG_FGC_CAMA;
01680    case SIG_FGC_CAMAMF:
01681       return ANALOG_SIG_FGC_CAMAMF;
01682    case SIG_FEATB:
01683       return ANALOG_SIG_FEATB;
01684    case SIG_SFWINK:
01685       return ANALOG_SIG_SFWINK;
01686    case SIG_SF:
01687       return ANALOG_SIG_SF;
01688    case SIG_SF_FEATD:
01689       return ANALOG_SIG_SF_FEATD;
01690    case SIG_SF_FEATDMF:
01691       return ANALOG_SIG_SF_FEATDMF;
01692    case SIG_FEATDMF_TA:
01693       return ANALOG_SIG_FEATDMF_TA;
01694    case SIG_SF_FEATB:
01695       return ANALOG_SIG_FEATB;
01696    default:
01697       return -1;
01698    }
01699 }
01700 
01701 
01702 static int analog_tone_to_dahditone(enum analog_tone tone)
01703 {
01704    switch (tone) {
01705    case ANALOG_TONE_RINGTONE:
01706       return DAHDI_TONE_RINGTONE;
01707    case ANALOG_TONE_STUTTER:
01708       return DAHDI_TONE_STUTTER;
01709    case ANALOG_TONE_CONGESTION:
01710       return DAHDI_TONE_CONGESTION;
01711    case ANALOG_TONE_DIALTONE:
01712       return DAHDI_TONE_DIALTONE;
01713    case ANALOG_TONE_DIALRECALL:
01714       return DAHDI_TONE_DIALRECALL;
01715    case ANALOG_TONE_INFO:
01716       return DAHDI_TONE_INFO;
01717    default:
01718       return -1;
01719    }
01720 }
01721 
01722 static int analogsub_to_dahdisub(enum analog_sub analogsub)
01723 {
01724    int index;
01725 
01726    switch (analogsub) {
01727    case ANALOG_SUB_REAL:
01728       index = SUB_REAL;
01729       break;
01730    case ANALOG_SUB_CALLWAIT:
01731       index = SUB_CALLWAIT;
01732       break;
01733    case ANALOG_SUB_THREEWAY:
01734       index = SUB_THREEWAY;
01735       break;
01736    default:
01737       ast_log(LOG_ERROR, "Unidentified sub!\n");
01738       index = SUB_REAL;
01739    }
01740 
01741    return index;
01742 }
01743 
01744 static enum analog_event dahdievent_to_analogevent(int event);
01745 static int bump_gains(struct dahdi_pvt *p);
01746 static int dahdi_setlinear(int dfd, int linear);
01747 
01748 static int my_start_cid_detect(void *pvt, int cid_signalling)
01749 {
01750    struct dahdi_pvt *p = pvt;
01751    int index = SUB_REAL;
01752    p->cs = callerid_new(cid_signalling);
01753    if (!p->cs) {
01754       ast_log(LOG_ERROR, "Unable to alloc callerid\n");
01755       return -1;
01756    }
01757    bump_gains(p);
01758    dahdi_setlinear(p->subs[index].dfd, 0);
01759 
01760    return 0;
01761 }
01762 
01763 static int my_stop_cid_detect(void *pvt)
01764 {
01765    struct dahdi_pvt *p = pvt;
01766    int index = SUB_REAL;
01767    if (p->cs)
01768       callerid_free(p->cs);
01769    dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
01770    return 0;
01771 }
01772 
01773 static int my_get_callerid(void *pvt, char *namebuf, char *numbuf, enum analog_event *ev, size_t timeout)
01774 {
01775    struct dahdi_pvt *p = pvt;
01776    struct analog_pvt *analog_p = p->sig_pvt;
01777    struct pollfd poller;
01778    char *name, *num;
01779    int index = SUB_REAL;
01780    int res;
01781    unsigned char buf[256];
01782    int flags;
01783    struct ast_format tmpfmt;
01784 
01785    poller.fd = p->subs[SUB_REAL].dfd;
01786    poller.events = POLLPRI | POLLIN;
01787    poller.revents = 0;
01788 
01789    res = poll(&poller, 1, timeout);
01790 
01791    if (poller.revents & POLLPRI) {
01792       *ev = dahdievent_to_analogevent(dahdi_get_event(p->subs[SUB_REAL].dfd));
01793       return 1;
01794    }
01795 
01796    if (poller.revents & POLLIN) {
01797       /*** NOTES ***/
01798       /* Change API: remove cid_signalling from get_callerid, add a new start_cid_detect and stop_cid_detect function
01799        * to enable slin mode and allocate cid detector. get_callerid should be able to be called any number of times until
01800        * either a timeout occurs or CID is detected (returns 0). returning 1 should be event received, and -1 should be
01801        * a failure and die, and returning 2 means no event was received. */
01802       res = read(p->subs[index].dfd, buf, sizeof(buf));
01803       if (res < 0) {
01804          ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
01805          return -1;
01806       }
01807 
01808       if (analog_p->ringt > 0) {
01809          if (!(--analog_p->ringt)) {
01810             /* only return if we timeout from a ring event */
01811             return -1;
01812          }
01813       }
01814 
01815       if (p->cid_signalling == CID_SIG_V23_JP) {
01816          res = callerid_feed_jp(p->cs, buf, res, ast_format_set(&tmpfmt, AST_LAW(p), 0));
01817       } else {
01818          res = callerid_feed(p->cs, buf, res, ast_format_set(&tmpfmt, AST_LAW(p), 0));
01819       }
01820       if (res < 0) {
01821          /*
01822           * The previous diagnostic message output likely
01823           * explains why it failed.
01824           */
01825          ast_log(LOG_WARNING, "Failed to decode CallerID\n");
01826          return -1;
01827       }
01828 
01829       if (res == 1) {
01830          callerid_get(p->cs, &name, &num, &flags);
01831          if (name)
01832             ast_copy_string(namebuf, name, ANALOG_MAX_CID);
01833          if (num)
01834             ast_copy_string(numbuf, num, ANALOG_MAX_CID);
01835 
01836          ast_debug(1, "CallerID number: %s, name: %s, flags=%d\n", num, name, flags);
01837          return 0;
01838       }
01839    }
01840 
01841    *ev = ANALOG_EVENT_NONE;
01842    return 2;
01843 }
01844 
01845 static const char *event2str(int event);
01846 static int restore_gains(struct dahdi_pvt *p);
01847 
01848 static int my_distinctive_ring(struct ast_channel *chan, void *pvt, int idx, int *ringdata)
01849 {
01850    unsigned char buf[256];
01851    int distMatches;
01852    int curRingData[RING_PATTERNS];
01853    int receivedRingT;
01854    int counter1;
01855    int counter;
01856    int i;
01857    int res;
01858    int checkaftercid = 0;
01859 
01860    struct dahdi_pvt *p = pvt;
01861    struct analog_pvt *analog_p = p->sig_pvt;
01862 
01863    if (ringdata == NULL) {
01864       ringdata = curRingData;
01865    } else {
01866       checkaftercid = 1;
01867    }
01868 
01869    /* We must have a ring by now, so, if configured, lets try to listen for
01870     * distinctive ringing */
01871    if ((checkaftercid && distinctiveringaftercid) || !checkaftercid) {
01872       /* Clear the current ring data array so we don't have old data in it. */
01873       for (receivedRingT = 0; receivedRingT < RING_PATTERNS; receivedRingT++)
01874          ringdata[receivedRingT] = 0;
01875       receivedRingT = 0;
01876       if (checkaftercid && distinctiveringaftercid)
01877          ast_verb(3, "Detecting post-CID distinctive ring\n");
01878       /* Check to see if context is what it should be, if not set to be. */
01879       else if (strcmp(p->context,p->defcontext) != 0) {
01880          ast_copy_string(p->context, p->defcontext, sizeof(p->context));
01881          ast_channel_context_set(chan, p->defcontext);
01882       }
01883 
01884       for (;;) {
01885          i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
01886          if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
01887             ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
01888             ast_hangup(chan);
01889             return 1;
01890          }
01891          if (i & DAHDI_IOMUX_SIGEVENT) {
01892             res = dahdi_get_event(p->subs[idx].dfd);
01893             if (res == DAHDI_EVENT_NOALARM) {
01894                p->inalarm = 0;
01895                analog_p->inalarm = 0;
01896             }
01897             ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
01898             res = 0;
01899             /* Let us detect distinctive ring */
01900 
01901             ringdata[receivedRingT] = analog_p->ringt;
01902 
01903             if (analog_p->ringt < analog_p->ringt_base/2)
01904                break;
01905             /* Increment the ringT counter so we can match it against
01906                values in chan_dahdi.conf for distinctive ring */
01907             if (++receivedRingT == RING_PATTERNS)
01908                break;
01909          } else if (i & DAHDI_IOMUX_READ) {
01910             res = read(p->subs[idx].dfd, buf, sizeof(buf));
01911             if (res < 0) {
01912                if (errno != ELAST) {
01913                   ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
01914                   ast_hangup(chan);
01915                   return 1;
01916                }
01917                break;
01918             }
01919             if (analog_p->ringt > 0) {
01920                if (!(--analog_p->ringt)) {
01921                   res = -1;
01922                   break;
01923                }
01924             }
01925          }
01926       }
01927    }
01928    if ((checkaftercid && usedistinctiveringdetection) || !checkaftercid) {
01929       /* this only shows up if you have n of the dring patterns filled in */
01930       ast_verb(3, "Detected ring pattern: %d,%d,%d\n",ringdata[0],ringdata[1],ringdata[2]);
01931       for (counter = 0; counter < 3; counter++) {
01932       /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this channel */
01933          distMatches = 0;
01934          /* this only shows up if you have n of the dring patterns filled in */
01935          ast_verb(3, "Checking %d,%d,%d\n",
01936                p->drings.ringnum[counter].ring[0],
01937                p->drings.ringnum[counter].ring[1],
01938                p->drings.ringnum[counter].ring[2]);
01939          for (counter1 = 0; counter1 < 3; counter1++) {
01940             ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
01941             if (p->drings.ringnum[counter].ring[counter1] == -1) {
01942                ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
01943                ringdata[counter1]);
01944                distMatches++;
01945             } else if (ringdata[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
01946                               ringdata[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
01947                ast_verb(3, "Ring pattern matched in range: %d to %d\n",
01948                (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
01949                (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
01950                distMatches++;
01951             }
01952          }
01953 
01954          if (distMatches == 3) {
01955             /* The ring matches, set the context to whatever is for distinctive ring.. */
01956             ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context));
01957             ast_channel_context_set(chan, S_OR(p->drings.ringContext[counter].contextData, p->defcontext));
01958             ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
01959             break;
01960          }
01961       }
01962    }
01963    /* Restore linear mode (if appropriate) for Caller*ID processing */
01964    dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
01965    restore_gains(p);
01966 
01967    return 0;
01968 }
01969 
01970 static int my_stop_callwait(void *pvt)
01971 {
01972    struct dahdi_pvt *p = pvt;
01973    p->callwaitingrepeat = 0;
01974    p->cidcwexpire = 0;
01975    p->cid_suppress_expire = 0;
01976 
01977    return 0;
01978 }
01979 
01980 static int send_callerid(struct dahdi_pvt *p);
01981 static int save_conference(struct dahdi_pvt *p);
01982 static int restore_conference(struct dahdi_pvt *p);
01983 
01984 static int my_callwait(void *pvt)
01985 {
01986    struct dahdi_pvt *p = pvt;
01987    struct ast_format tmpfmt;
01988    p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
01989    if (p->cidspill) {
01990       ast_log(LOG_WARNING, "Spill already exists?!?\n");
01991       ast_free(p->cidspill);
01992    }
01993 
01994    /*
01995     * SAS: Subscriber Alert Signal, 440Hz for 300ms
01996     * CAS: CPE Alert Signal, 2130Hz * 2750Hz sine waves
01997     */
01998    if (!(p->cidspill = ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE * 4)))
01999       return -1;
02000    save_conference(p);
02001    /* Silence */
02002    memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
02003    if (!p->callwaitrings && p->callwaitingcallerid) {
02004       ast_gen_cas(p->cidspill, 1, 2400 + 680, ast_format_set(&tmpfmt, AST_LAW(p), 0));
02005       p->callwaitcas = 1;
02006       p->cidlen = 2400 + 680 + READ_SIZE * 4;
02007    } else {
02008       ast_gen_cas(p->cidspill, 1, 2400, ast_format_set(&tmpfmt, AST_LAW(p), 0));
02009       p->callwaitcas = 0;
02010       p->cidlen = 2400 + READ_SIZE * 4;
02011    }
02012    p->cidpos = 0;
02013    send_callerid(p);
02014 
02015    return 0;
02016 }
02017 
02018 static int my_send_callerid(void *pvt, int cwcid, struct ast_party_caller *caller)
02019 {
02020    struct dahdi_pvt *p = pvt;
02021    struct ast_format tmpfmt;
02022 
02023    ast_debug(2, "Starting cid spill\n");
02024 
02025    if (p->cidspill) {
02026       ast_log(LOG_WARNING, "cidspill already exists??\n");
02027       ast_free(p->cidspill);
02028    }
02029 
02030    if ((p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) {
02031       if (cwcid == 0) {
02032          p->cidlen = ast_callerid_generate(p->cidspill,
02033             caller->id.name.str,
02034             caller->id.number.str,
02035             ast_format_set(&tmpfmt, AST_LAW(p), 0));
02036       } else {
02037          ast_verb(3, "CPE supports Call Waiting Caller*ID.  Sending '%s/%s'\n",
02038             caller->id.name.str, caller->id.number.str);
02039          p->callwaitcas = 0;
02040          p->cidcwexpire = 0;
02041          p->cidlen = ast_callerid_callwaiting_generate(p->cidspill,
02042             caller->id.name.str,
02043             caller->id.number.str,
02044             ast_format_set(&tmpfmt, AST_LAW(p), 0));
02045          p->cidlen += READ_SIZE * 4;
02046       }
02047       p->cidpos = 0;
02048       p->cid_suppress_expire = 0;
02049       send_callerid(p);
02050    }
02051    return 0;
02052 }
02053 
02054 static int my_dsp_reset_and_flush_digits(void *pvt)
02055 {
02056    struct dahdi_pvt *p = pvt;
02057    if (p->dsp)
02058       ast_dsp_digitreset(p->dsp);
02059 
02060    return 0;
02061 }
02062 
02063 static int my_dsp_set_digitmode(void *pvt, enum analog_dsp_digitmode mode)
02064 {
02065    struct dahdi_pvt *p = pvt;
02066 
02067    if (p->channel == CHAN_PSEUDO)
02068       ast_log(LOG_ERROR, "You have assumed incorrectly sir!\n");
02069 
02070    if (mode == ANALOG_DIGITMODE_DTMF) {
02071       /* If we do hardware dtmf, no need for a DSP */
02072       if (p->hardwaredtmf) {
02073          if (p->dsp) {
02074             ast_dsp_free(p->dsp);
02075             p->dsp = NULL;
02076          }
02077          return 0;
02078       }
02079 
02080       if (!p->dsp) {
02081          p->dsp = ast_dsp_new();
02082          if (!p->dsp) {
02083             ast_log(LOG_ERROR, "Unable to allocate DSP\n");
02084             return -1;
02085          }
02086       }
02087 
02088       ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
02089    } else if (mode == ANALOG_DIGITMODE_MF) {
02090       if (!p->dsp) {
02091          p->dsp = ast_dsp_new();
02092          if (!p->dsp) {
02093             ast_log(LOG_ERROR, "Unable to allocate DSP\n");
02094             return -1;
02095          }
02096       }
02097       ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
02098    }
02099    return 0;
02100 }
02101 
02102 static int dahdi_wink(struct dahdi_pvt *p, int index);
02103 
02104 static int my_wink(void *pvt, enum analog_sub sub)
02105 {
02106    struct dahdi_pvt *p = pvt;
02107    int index = analogsub_to_dahdisub(sub);
02108    if (index != SUB_REAL) {
02109       ast_log(LOG_ERROR, "We used a sub other than SUB_REAL (incorrect assumption sir)\n");
02110    }
02111    return dahdi_wink(p, index);
02112 }
02113 
02114 static void wakeup_sub(struct dahdi_pvt *p, int a);
02115 
02116 static int reset_conf(struct dahdi_pvt *p);
02117 
02118 static inline int dahdi_confmute(struct dahdi_pvt *p, int muted);
02119 
02120 static void my_handle_dtmf(void *pvt, struct ast_channel *ast, enum analog_sub analog_index, struct ast_frame **dest)
02121 {
02122    struct ast_frame *f = *dest;
02123    struct dahdi_pvt *p = pvt;
02124    int idx = analogsub_to_dahdisub(analog_index);
02125 
02126    ast_debug(1, "%s DTMF digit: 0x%02X '%c' on %s\n",
02127       f->frametype == AST_FRAME_DTMF_BEGIN ? "Begin" : "End",
02128       (unsigned)f->subclass.integer, f->subclass.integer, ast_channel_name(ast));
02129 
02130    if (f->subclass.integer == 'f') {
02131       if (f->frametype == AST_FRAME_DTMF_END) {
02132          /* Fax tone -- Handle and return NULL */
02133          if ((p->callprogress & CALLPROGRESS_FAX) && !p->faxhandled) {
02134             /* If faxbuffers are configured, use them for the fax transmission */
02135             if (p->usefaxbuffers && !p->bufferoverrideinuse) {
02136                struct dahdi_bufferinfo bi = {
02137                   .txbufpolicy = p->faxbuf_policy,
02138                   .bufsize = p->bufsize,
02139                   .numbufs = p->faxbuf_no
02140                };
02141                int res;
02142 
02143                if ((res = ioctl(p->subs[idx].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
02144                   ast_log(LOG_WARNING, "Channel '%s' unable to set buffer policy, reason: %s\n", ast_channel_name(ast), strerror(errno));
02145                } else {
02146                   p->bufferoverrideinuse = 1;
02147                }
02148             }
02149             p->faxhandled = 1;
02150             if (p->dsp) {
02151                p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
02152                ast_dsp_set_features(p->dsp, p->dsp_features);
02153                ast_debug(1, "Disabling FAX tone detection on %s after tone received\n", ast_channel_name(ast));
02154             }
02155             if (strcmp(ast_channel_exten(ast), "fax")) {
02156                const char *target_context = S_OR(ast_channel_macrocontext(ast), ast_channel_context(ast));
02157 
02158                /* We need to unlock 'ast' here because ast_exists_extension has the
02159                 * potential to start autoservice on the channel. Such action is prone
02160                 * to deadlock.
02161                 */
02162                ast_mutex_unlock(&p->lock);
02163                ast_channel_unlock(ast);
02164                if (ast_exists_extension(ast, target_context, "fax", 1,
02165                   S_COR(ast_channel_caller(ast)->id.number.valid, ast_channel_caller(ast)->id.number.str, NULL))) {
02166                   ast_channel_lock(ast);
02167                   ast_mutex_lock(&p->lock);
02168                   ast_verb(3, "Redirecting %s to fax extension\n", ast_channel_name(ast));
02169                   /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
02170                   pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast_channel_exten(ast));
02171                   if (ast_async_goto(ast, target_context, "fax", 1))
02172                      ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast_channel_name(ast), target_context);
02173                } else {
02174                   ast_channel_lock(ast);
02175                   ast_mutex_lock(&p->lock);
02176                   ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
02177                }
02178             } else {
02179                ast_debug(1, "Already in a fax extension, not redirecting\n");
02180             }
02181          } else {
02182             ast_debug(1, "Fax already handled\n");
02183          }
02184          dahdi_confmute(p, 0);
02185       }
02186       p->subs[idx].f.frametype = AST_FRAME_NULL;
02187       p->subs[idx].f.subclass.integer = 0;
02188       *dest = &p->subs[idx].f;
02189    }
02190 }
02191 
02192 static void my_lock_private(void *pvt)
02193 {
02194    struct dahdi_pvt *p = pvt;
02195    ast_mutex_lock(&p->lock);
02196 }
02197 
02198 static void my_unlock_private(void *pvt)
02199 {
02200    struct dahdi_pvt *p = pvt;
02201    ast_mutex_unlock(&p->lock);
02202 }
02203 
02204 static void my_deadlock_avoidance_private(void *pvt)
02205 {
02206    struct dahdi_pvt *p = pvt;
02207 
02208    DEADLOCK_AVOIDANCE(&p->lock);
02209 }
02210 
02211 /*!
02212  * \internal
02213  * \brief Post an AMI DAHDI channel association event.
02214  * \since 1.8
02215  *
02216  * \param p DAHDI private pointer
02217  * \param chan Channel associated with the private pointer
02218  *
02219  * \return Nothing
02220  */
02221 static void dahdi_ami_channel_event(struct dahdi_pvt *p, struct ast_channel *chan)
02222 {
02223    char ch_name[20];
02224 
02225    if (p->channel < CHAN_PSEUDO) {
02226       /* No B channel */
02227       snprintf(ch_name, sizeof(ch_name), "no-media (%d)", p->channel);
02228    } else if (p->channel == CHAN_PSEUDO) {
02229       /* Pseudo channel */
02230       strcpy(ch_name, "pseudo");
02231    } else {
02232       /* Real channel */
02233       snprintf(ch_name, sizeof(ch_name), "%d", p->channel);
02234    }
02235    /*** DOCUMENTATION
02236       <managerEventInstance>
02237          <synopsis>Raised when a DAHDI channel is created or an underlying technology is associated with a DAHDI channel.</synopsis>
02238       </managerEventInstance>
02239    ***/
02240    ast_manager_event(chan, EVENT_FLAG_CALL, "DAHDIChannel",
02241       "Channel: %s\r\n"
02242       "Uniqueid: %s\r\n"
02243       "DAHDISpan: %d\r\n"
02244       "DAHDIChannel: %s\r\n",
02245       ast_channel_name(chan),
02246       ast_channel_uniqueid(chan),
02247       p->span,
02248       ch_name);
02249 }
02250 
02251 #ifdef HAVE_PRI
02252 /*!
02253  * \internal
02254  * \brief Post an AMI DAHDI channel association event.
02255  * \since 1.8
02256  *
02257  * \param pvt DAHDI private pointer
02258  * \param chan Channel associated with the private pointer
02259  *
02260  * \return Nothing
02261  */
02262 static void my_ami_channel_event(void *pvt, struct ast_channel *chan)
02263 {
02264    struct dahdi_pvt *p = pvt;
02265 
02266    dahdi_ami_channel_event(p, chan);
02267 }
02268 #endif
02269 
02270 /* linear_mode = 0 - turn linear mode off, >0 - turn linear mode on
02271 *  returns the last value of the linear setting 
02272 */ 
02273 static int my_set_linear_mode(void *pvt, enum analog_sub sub, int linear_mode)
02274 {
02275    struct dahdi_pvt *p = pvt;
02276    int oldval;
02277    int idx = analogsub_to_dahdisub(sub);
02278    
02279    dahdi_setlinear(p->subs[idx].dfd, linear_mode);
02280    oldval = p->subs[idx].linear;
02281    p->subs[idx].linear = linear_mode ? 1 : 0;
02282    return oldval;
02283 }
02284 
02285 static void my_set_inthreeway(void *pvt, enum analog_sub sub, int inthreeway)
02286 {
02287    struct dahdi_pvt *p = pvt;
02288    int idx = analogsub_to_dahdisub(sub);
02289 
02290    p->subs[idx].inthreeway = inthreeway;
02291 }
02292 
02293 static int get_alarms(struct dahdi_pvt *p);
02294 static void handle_alarms(struct dahdi_pvt *p, int alms);
02295 static void my_get_and_handle_alarms(void *pvt)
02296 {
02297    int res;
02298    struct dahdi_pvt *p = pvt;
02299 
02300    res = get_alarms(p);
02301    handle_alarms(p, res);
02302 }
02303 
02304 static void *my_get_sigpvt_bridged_channel(struct ast_channel *chan)
02305 {
02306    struct ast_channel *bridged = ast_bridged_channel(chan);
02307 
02308    if (bridged && ast_channel_tech(bridged) == &dahdi_tech) {
02309       struct dahdi_pvt *p = ast_channel_tech_pvt(bridged);
02310 
02311       if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
02312          return p->sig_pvt;
02313       }
02314    }
02315    return NULL;
02316 }
02317 
02318 static int my_get_sub_fd(void *pvt, enum analog_sub sub)
02319 {
02320    struct dahdi_pvt *p = pvt;
02321    int dahdi_sub = analogsub_to_dahdisub(sub);
02322    return p->subs[dahdi_sub].dfd;
02323 }
02324 
02325 static void my_set_cadence(void *pvt, int *cid_rings, struct ast_channel *ast)
02326 {
02327    struct dahdi_pvt *p = pvt;
02328 
02329    /* Choose proper cadence */
02330    if ((p->distinctivering > 0) && (p->distinctivering <= num_cadence)) {
02331       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &cadences[p->distinctivering - 1]))
02332          ast_log(LOG_WARNING, "Unable to set distinctive ring cadence %d on '%s': %s\n", p->distinctivering, ast_channel_name(ast), strerror(errno));
02333       *cid_rings = cidrings[p->distinctivering - 1];
02334    } else {
02335       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, NULL))
02336          ast_log(LOG_WARNING, "Unable to reset default ring on '%s': %s\n", ast_channel_name(ast), strerror(errno));
02337       *cid_rings = p->sendcalleridafter;
02338    }
02339 }
02340 
02341 static void my_set_alarm(void *pvt, int in_alarm)
02342 {
02343    struct dahdi_pvt *p = pvt;
02344 
02345    p->inalarm = in_alarm;
02346 }
02347 
02348 static void my_set_dialing(void *pvt, int is_dialing)
02349 {
02350    struct dahdi_pvt *p = pvt;
02351 
02352    p->dialing = is_dialing;
02353 }
02354 
02355 static void my_set_outgoing(void *pvt, int is_outgoing)
02356 {
02357    struct dahdi_pvt *p = pvt;
02358 
02359    p->outgoing = is_outgoing;
02360 }
02361 
02362 #if defined(HAVE_PRI) || defined(HAVE_SS7)
02363 static void my_set_digital(void *pvt, int is_digital)
02364 {
02365    struct dahdi_pvt *p = pvt;
02366 
02367    p->digital = is_digital;
02368 }
02369 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
02370 
02371 #if defined(HAVE_SS7)
02372 static void my_set_inservice(void *pvt, int is_inservice)
02373 {
02374    struct dahdi_pvt *p = pvt;
02375 
02376    p->inservice = is_inservice;
02377 }
02378 #endif   /* defined(HAVE_SS7) */
02379 
02380 #if defined(HAVE_SS7)
02381 static void my_set_locallyblocked(void *pvt, int is_blocked)
02382 {
02383    struct dahdi_pvt *p = pvt;
02384 
02385    p->locallyblocked = is_blocked;
02386 }
02387 #endif   /* defined(HAVE_SS7) */
02388 
02389 #if defined(HAVE_SS7)
02390 static void my_set_remotelyblocked(void *pvt, int is_blocked)
02391 {
02392    struct dahdi_pvt *p = pvt;
02393 
02394    p->remotelyblocked = is_blocked;
02395 }
02396 #endif   /* defined(HAVE_SS7) */
02397 
02398 static void my_set_ringtimeout(void *pvt, int ringt)
02399 {
02400    struct dahdi_pvt *p = pvt;
02401    p->ringt = ringt;
02402 }
02403 
02404 static void my_set_waitingfordt(void *pvt, struct ast_channel *ast)
02405 {
02406    struct dahdi_pvt *p = pvt;
02407 
02408    if (p->waitfordialtone && CANPROGRESSDETECT(p) && p->dsp) {
02409       ast_debug(1, "Defer dialing for %dms or dialtone\n", p->waitfordialtone);
02410       gettimeofday(&p->waitingfordt, NULL);
02411       ast_setstate(ast, AST_STATE_OFFHOOK);
02412    }
02413 }
02414 
02415 static int my_check_waitingfordt(void *pvt)
02416 {
02417    struct dahdi_pvt *p = pvt;
02418 
02419    if (p->waitingfordt.tv_sec) {
02420       return 1;
02421    }
02422 
02423    return 0;
02424 }
02425 
02426 static void my_set_confirmanswer(void *pvt, int flag)
02427 {
02428    struct dahdi_pvt *p = pvt;
02429    p->confirmanswer = flag;
02430 }
02431 
02432 static int my_check_confirmanswer(void *pvt)
02433 {
02434    struct dahdi_pvt *p = pvt;
02435    if (p->confirmanswer) {
02436       return 1;
02437    }
02438 
02439    return 0;
02440 }
02441 
02442 static void my_set_callwaiting(void *pvt, int callwaiting_enable)
02443 {
02444    struct dahdi_pvt *p = pvt;
02445 
02446    p->callwaiting = callwaiting_enable;
02447 }
02448 
02449 static void my_cancel_cidspill(void *pvt)
02450 {
02451    struct dahdi_pvt *p = pvt;
02452 
02453    ast_free(p->cidspill);
02454    p->cidspill = NULL;
02455    restore_conference(p);
02456 }
02457 
02458 static int my_confmute(void *pvt, int mute)
02459 {
02460    struct dahdi_pvt *p = pvt;
02461    return dahdi_confmute(p, mute);
02462 }
02463 
02464 static void my_set_pulsedial(void *pvt, int flag)
02465 {
02466    struct dahdi_pvt *p = pvt;
02467    p->pulsedial = flag;
02468 }
02469 
02470 static void my_set_new_owner(void *pvt, struct ast_channel *new_owner)
02471 {
02472    struct dahdi_pvt *p = pvt;
02473 
02474    p->owner = new_owner;
02475 }
02476 
02477 static const char *my_get_orig_dialstring(void *pvt)
02478 {
02479    struct dahdi_pvt *p = pvt;
02480 
02481    return p->dialstring;
02482 }
02483 
02484 static void my_increase_ss_count(void)
02485 {
02486    ast_mutex_lock(&ss_thread_lock);
02487    ss_thread_count++;
02488    ast_mutex_unlock(&ss_thread_lock);
02489 }
02490 
02491 static void my_decrease_ss_count(void)
02492 {
02493    ast_mutex_lock(&ss_thread_lock);
02494    ss_thread_count--;
02495    ast_cond_signal(&ss_thread_complete);
02496    ast_mutex_unlock(&ss_thread_lock);
02497 }
02498 
02499 static void my_all_subchannels_hungup(void *pvt)
02500 {
02501    struct dahdi_pvt *p = pvt;
02502    int res, law;
02503 
02504    p->faxhandled = 0;
02505    p->didtdd = 0;
02506 
02507    if (p->dsp) {
02508       ast_dsp_free(p->dsp);
02509       p->dsp = NULL;
02510    }
02511 
02512    p->law = p->law_default;
02513    law = p->law_default;
02514    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
02515    if (res < 0)
02516       ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
02517 
02518    dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
02519 
02520 #if 1
02521    {
02522    int i;
02523    p->owner = NULL;
02524    /* Cleanup owners here */
02525    for (i = 0; i < 3; i++) {
02526       p->subs[i].owner = NULL;
02527    }
02528    }
02529 #endif
02530 
02531    reset_conf(p);
02532    if (num_restart_pending == 0) {
02533       restart_monitor();
02534    }
02535 }
02536 
02537 static int conf_del(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index);
02538 
02539 static int my_conf_del(void *pvt, enum analog_sub sub)
02540 {
02541    struct dahdi_pvt *p = pvt;
02542    int x = analogsub_to_dahdisub(sub);
02543 
02544    return conf_del(p, &p->subs[x], x);
02545 }
02546 
02547 static int conf_add(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index, int slavechannel);
02548 
02549 static int my_conf_add(void *pvt, enum analog_sub sub)
02550 {
02551    struct dahdi_pvt *p = pvt;
02552    int x = analogsub_to_dahdisub(sub);
02553 
02554    return conf_add(p, &p->subs[x], x, 0);
02555 }
02556 
02557 static int isslavenative(struct dahdi_pvt *p, struct dahdi_pvt **out);
02558 
02559 static int my_complete_conference_update(void *pvt, int needconference)
02560 {
02561    struct dahdi_pvt *p = pvt;
02562    int needconf = needconference;
02563    int x;
02564    int useslavenative;
02565    struct dahdi_pvt *slave = NULL;
02566 
02567    useslavenative = isslavenative(p, &slave);
02568 
02569    /* If we have a slave, add him to our conference now. or DAX
02570       if this is slave native */
02571    for (x = 0; x < MAX_SLAVES; x++) {
02572       if (p->slaves[x]) {
02573          if (useslavenative)
02574             conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
02575          else {
02576             conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
02577             needconf++;
02578          }
02579       }
02580    }
02581    /* If we're supposed to be in there, do so now */
02582    if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
02583       if (useslavenative)
02584          conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
02585       else {
02586          conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
02587          needconf++;
02588       }
02589    }
02590    /* If we have a master, add ourselves to his conference */
02591    if (p->master) {
02592       if (isslavenative(p->master, NULL)) {
02593          conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
02594       } else {
02595          conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
02596       }
02597    }
02598    if (!needconf) {
02599       /* Nobody is left (or should be left) in our conference.
02600          Kill it. */
02601       p->confno = -1;
02602    }
02603 
02604    return 0;
02605 }
02606 
02607 static int check_for_conference(struct dahdi_pvt *p);
02608 
02609 static int my_check_for_conference(void *pvt)
02610 {
02611    struct dahdi_pvt *p = pvt;
02612    return check_for_conference(p);
02613 }
02614 
02615 static void my_swap_subchannels(void *pvt, enum analog_sub a, struct ast_channel *ast_a,  enum analog_sub b, struct ast_channel *ast_b)
02616 {
02617    struct dahdi_pvt *p = pvt;
02618    int da, db;
02619    int tchan;
02620    int tinthreeway;
02621 
02622    da = analogsub_to_dahdisub(a);
02623    db = analogsub_to_dahdisub(b);
02624 
02625    tchan = p->subs[da].chan;
02626    p->subs[da].chan = p->subs[db].chan;
02627    p->subs[db].chan = tchan;
02628 
02629    tinthreeway = p->subs[da].inthreeway;
02630    p->subs[da].inthreeway = p->subs[db].inthreeway;
02631    p->subs[db].inthreeway = tinthreeway;
02632 
02633    p->subs[da].owner = ast_a;
02634    p->subs[db].owner = ast_b;
02635 
02636    if (ast_a)
02637       ast_channel_set_fd(ast_a, 0, p->subs[da].dfd);
02638    if (ast_b)
02639       ast_channel_set_fd(ast_b, 0, p->subs[db].dfd);
02640 
02641    wakeup_sub(p, a);
02642    wakeup_sub(p, b);
02643 
02644    return;
02645 }
02646 
02647 /*!
02648  * \internal
02649  * \brief performs duties of dahdi_new, but also removes and possibly unbinds (if callid_created is 1) before returning
02650  * \note this variant of dahdi should only be used in conjunction with ast_callid_threadstorage_auto()
02651  *
02652  * \param callid_created value returned from ast_callid_threadstorage_auto()
02653  */
02654 static struct ast_channel *dahdi_new_callid_clean(struct dahdi_pvt *i, int state, int startpbx, int idx, int law, const char *linked, struct ast_callid *callid, int callid_created);
02655 
02656 static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpbx, int idx, int law, const char *linkedid, struct ast_callid *callid);
02657 
02658 static struct ast_channel *my_new_analog_ast_channel(void *pvt, int state, int startpbx, enum analog_sub sub, const struct ast_channel *requestor)
02659 {
02660    struct ast_callid *callid = NULL;
02661    int callid_created = ast_callid_threadstorage_auto(&callid);
02662    struct dahdi_pvt *p = pvt;
02663    int dsub = analogsub_to_dahdisub(sub);
02664 
02665    return dahdi_new_callid_clean(p, state, startpbx, dsub, 0, requestor ? ast_channel_linkedid(requestor) : "", callid, callid_created);
02666 }
02667 
02668 #if defined(HAVE_PRI) || defined(HAVE_SS7)
02669 static int dahdi_setlaw(int dfd, int law)
02670 {
02671    int res;
02672    res = ioctl(dfd, DAHDI_SETLAW, &law);
02673    if (res)
02674       return res;
02675    return 0;
02676 }
02677 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
02678 
02679 #if defined(HAVE_PRI)
02680 static struct ast_channel *my_new_pri_ast_channel(void *pvt, int state, enum sig_pri_law law, char *exten, const struct ast_channel *requestor)
02681 {
02682    struct dahdi_pvt *p = pvt;
02683    int audio;
02684    int newlaw = -1;
02685    struct ast_callid *callid = NULL;
02686    int callid_created = ast_callid_threadstorage_auto(&callid);
02687 
02688    switch (p->sig) {
02689    case SIG_PRI_LIB_HANDLE_CASES:
02690       if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
02691          /* PRI nobch pseudo channel.  Does not handle ioctl(DAHDI_AUDIOMODE) */
02692          break;
02693       }
02694       /* Fall through */
02695    default:
02696       /* Set to audio mode at this point */
02697       audio = 1;
02698       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &audio) == -1) {
02699          ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n",
02700             p->channel, audio, strerror(errno));
02701       }
02702       break;
02703    }
02704 
02705    if (law != SIG_PRI_DEFLAW) {
02706       dahdi_setlaw(p->subs[SUB_REAL].dfd, (law == SIG_PRI_ULAW) ? DAHDI_LAW_MULAW : DAHDI_LAW_ALAW);
02707    }
02708 
02709    ast_copy_string(p->exten, exten, sizeof(p->exten));
02710 
02711    switch (law) {
02712       case SIG_PRI_DEFLAW:
02713          newlaw = 0;
02714          break;
02715       case SIG_PRI_ALAW:
02716          newlaw = DAHDI_LAW_ALAW;
02717          break;
02718       case SIG_PRI_ULAW:
02719          newlaw = DAHDI_LAW_MULAW;
02720          break;
02721    }
02722 
02723    return dahdi_new_callid_clean(p, state, 0, SUB_REAL, newlaw, requestor ? ast_channel_linkedid(requestor) : "", callid, callid_created);
02724 }
02725 #endif   /* defined(HAVE_PRI) */
02726 
02727 static int set_actual_gain(int fd, float rxgain, float txgain, float rxdrc, float txdrc, int law);
02728 
02729 #if defined(HAVE_PRI) || defined(HAVE_SS7)
02730 /*!
02731  * \internal
02732  * \brief Open the PRI/SS7 channel media path.
02733  * \since 1.8
02734  *
02735  * \param p Channel private control structure.
02736  *
02737  * \return Nothing
02738  */
02739 static void my_pri_ss7_open_media(void *p)
02740 {
02741    struct dahdi_pvt *pvt = p;
02742    int res;
02743    int dfd;
02744    int set_val;
02745 
02746    dfd = pvt->subs[SUB_REAL].dfd;
02747 
02748    /* Open the media path. */
02749    set_val = 1;
02750    res = ioctl(dfd, DAHDI_AUDIOMODE, &set_val);
02751    if (res < 0) {
02752       ast_log(LOG_WARNING, "Unable to enable audio mode on channel %d (%s)\n",
02753          pvt->channel, strerror(errno));
02754    }
02755 
02756    /* Set correct companding law for this call. */
02757    res = dahdi_setlaw(dfd, pvt->law);
02758    if (res < 0) {
02759       ast_log(LOG_WARNING, "Unable to set law on channel %d\n", pvt->channel);
02760    }
02761 
02762    /* Set correct gain for this call. */
02763    if (pvt->digital) {
02764       res = set_actual_gain(dfd, 0, 0, pvt->rxdrc, pvt->txdrc, pvt->law);
02765    } else {
02766       res = set_actual_gain(dfd, pvt->rxgain, pvt->txgain, pvt->rxdrc, pvt->txdrc,
02767          pvt->law);
02768    }
02769    if (res < 0) {
02770       ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", pvt->channel);
02771    }
02772 
02773    if (pvt->dsp_features && pvt->dsp) {
02774       ast_dsp_set_features(pvt->dsp, pvt->dsp_features);
02775       pvt->dsp_features = 0;
02776    }
02777 }
02778 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
02779 
02780 #if defined(HAVE_PRI)
02781 /*!
02782  * \internal
02783  * \brief Ask DAHDI to dial the given dial string.
02784  * \since 1.8.11
02785  *
02786  * \param p Channel private control structure.
02787  * \param dial_string String to pass to DAHDI to dial.
02788  *
02789  * \note The channel private lock needs to be held when calling.
02790  *
02791  * \return Nothing
02792  */
02793 static void my_pri_dial_digits(void *p, const char *dial_string)
02794 {
02795    struct dahdi_dialoperation zo = {
02796       .op = DAHDI_DIAL_OP_APPEND,
02797    };
02798    struct dahdi_pvt *pvt = p;
02799    int res;
02800 
02801    snprintf(zo.dialstr, sizeof(zo.dialstr), "T%s", dial_string);
02802    ast_debug(1, "Channel %d: Sending '%s' to DAHDI_DIAL.\n", pvt->channel, zo.dialstr);
02803    res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo);
02804    if (res) {
02805       ast_log(LOG_WARNING, "Channel %d: Couldn't dial '%s': %s\n",
02806          pvt->channel, dial_string, strerror(errno));
02807    } else {
02808       pvt->dialing = 1;
02809    }
02810 }
02811 #endif   /* defined(HAVE_PRI) */
02812 
02813 static int unalloc_sub(struct dahdi_pvt *p, int x);
02814 
02815 static int my_unallocate_sub(void *pvt, enum analog_sub analogsub)
02816 {
02817    struct dahdi_pvt *p = pvt;
02818 
02819    return unalloc_sub(p, analogsub_to_dahdisub(analogsub));
02820 }
02821 
02822 static int alloc_sub(struct dahdi_pvt *p, int x);
02823 
02824 static int my_allocate_sub(void *pvt, enum analog_sub analogsub)
02825 {
02826    struct dahdi_pvt *p = pvt;
02827 
02828    return alloc_sub(p, analogsub_to_dahdisub(analogsub));
02829 }
02830 
02831 static int has_voicemail(struct dahdi_pvt *p);
02832 
02833 static int my_has_voicemail(void *pvt)
02834 {
02835    struct dahdi_pvt *p = pvt;
02836 
02837    return has_voicemail(p);
02838 }
02839 
02840 static int my_play_tone(void *pvt, enum analog_sub sub, enum analog_tone tone)
02841 {
02842    struct dahdi_pvt *p = pvt;
02843    int index;
02844 
02845    index = analogsub_to_dahdisub(sub);
02846 
02847    return tone_zone_play_tone(p->subs[index].dfd, analog_tone_to_dahditone(tone));
02848 }
02849 
02850 static enum analog_event dahdievent_to_analogevent(int event)
02851 {
02852    enum analog_event res;
02853 
02854    switch (event) {
02855    case DAHDI_EVENT_ONHOOK:
02856       res = ANALOG_EVENT_ONHOOK;
02857       break;
02858    case DAHDI_EVENT_RINGOFFHOOK:
02859       res = ANALOG_EVENT_RINGOFFHOOK;
02860       break;
02861    case DAHDI_EVENT_WINKFLASH:
02862       res = ANALOG_EVENT_WINKFLASH;
02863       break;
02864    case DAHDI_EVENT_ALARM:
02865       res = ANALOG_EVENT_ALARM;
02866       break;
02867    case DAHDI_EVENT_NOALARM:
02868       res = ANALOG_EVENT_NOALARM;
02869       break;
02870    case DAHDI_EVENT_DIALCOMPLETE:
02871       res = ANALOG_EVENT_DIALCOMPLETE;
02872       break;
02873    case DAHDI_EVENT_RINGERON:
02874       res = ANALOG_EVENT_RINGERON;
02875       break;
02876    case DAHDI_EVENT_RINGEROFF:
02877       res = ANALOG_EVENT_RINGEROFF;
02878       break;
02879    case DAHDI_EVENT_HOOKCOMPLETE:
02880       res = ANALOG_EVENT_HOOKCOMPLETE;
02881       break;
02882    case DAHDI_EVENT_PULSE_START:
02883       res = ANALOG_EVENT_PULSE_START;
02884       break;
02885    case DAHDI_EVENT_POLARITY:
02886       res = ANALOG_EVENT_POLARITY;
02887       break;
02888    case DAHDI_EVENT_RINGBEGIN:
02889       res = ANALOG_EVENT_RINGBEGIN;
02890       break;
02891    case DAHDI_EVENT_EC_DISABLED:
02892       res = ANALOG_EVENT_EC_DISABLED;
02893       break;
02894    case DAHDI_EVENT_REMOVED:
02895       res = ANALOG_EVENT_REMOVED;
02896       break;
02897    case DAHDI_EVENT_NEONMWI_ACTIVE:
02898       res = ANALOG_EVENT_NEONMWI_ACTIVE;
02899       break;
02900    case DAHDI_EVENT_NEONMWI_INACTIVE:
02901       res = ANALOG_EVENT_NEONMWI_INACTIVE;
02902       break;
02903 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
02904    case DAHDI_EVENT_TX_CED_DETECTED:
02905       res = ANALOG_EVENT_TX_CED_DETECTED;
02906       break;
02907    case DAHDI_EVENT_RX_CED_DETECTED:
02908       res = ANALOG_EVENT_RX_CED_DETECTED;
02909       break;
02910    case DAHDI_EVENT_EC_NLP_DISABLED:
02911       res = ANALOG_EVENT_EC_NLP_DISABLED;
02912       break;
02913    case DAHDI_EVENT_EC_NLP_ENABLED:
02914       res = ANALOG_EVENT_EC_NLP_ENABLED;
02915       break;
02916 #endif
02917    case DAHDI_EVENT_PULSEDIGIT:
02918       res = ANALOG_EVENT_PULSEDIGIT;
02919       break;
02920    case DAHDI_EVENT_DTMFDOWN:
02921       res = ANALOG_EVENT_DTMFDOWN;
02922       break;
02923    case DAHDI_EVENT_DTMFUP:
02924       res = ANALOG_EVENT_DTMFUP;
02925       break;
02926    default:
02927       switch(event & 0xFFFF0000) {
02928       case DAHDI_EVENT_PULSEDIGIT:
02929       case DAHDI_EVENT_DTMFDOWN:
02930       case DAHDI_EVENT_DTMFUP:
02931          /* The event includes a digit number in the low word.
02932           * Converting it to a 'enum analog_event' would remove
02933           * that information. Thus it is returned as-is.
02934           */
02935          return event;
02936       }
02937 
02938       res = ANALOG_EVENT_ERROR;
02939       break;
02940    }
02941 
02942    return res;
02943 }
02944 
02945 static inline int dahdi_wait_event(int fd);
02946 
02947 static int my_wait_event(void *pvt)
02948 {
02949    struct dahdi_pvt *p = pvt;
02950 
02951    return dahdi_wait_event(p->subs[SUB_REAL].dfd);
02952 }
02953 
02954 static int my_get_event(void *pvt)
02955 {
02956    struct dahdi_pvt *p = pvt;
02957    int res;
02958 
02959    if (p->fake_event) {
02960       res = p->fake_event;
02961       p->fake_event = 0;
02962    } else
02963       res = dahdi_get_event(p->subs[SUB_REAL].dfd);
02964 
02965    return dahdievent_to_analogevent(res);
02966 }
02967 
02968 static int my_is_off_hook(void *pvt)
02969 {
02970    struct dahdi_pvt *p = pvt;
02971    int res;
02972    struct dahdi_params par;
02973 
02974    memset(&par, 0, sizeof(par));
02975 
02976    if (p->subs[SUB_REAL].dfd > -1)
02977       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
02978    else {
02979       /* Assume not off hook on CVRS */
02980       res = 0;
02981       par.rxisoffhook = 0;
02982    }
02983    if (res) {
02984       ast_log(LOG_WARNING, "Unable to check hook state on channel %d: %s\n", p->channel, strerror(errno));
02985    }
02986 
02987    if ((p->sig == SIG_FXSKS) || (p->sig == SIG_FXSGS)) {
02988       /* When "onhook" that means no battery on the line, and thus
02989       it is out of service..., if it's on a TDM card... If it's a channel
02990       bank, there is no telling... */
02991       return (par.rxbits > -1) || par.rxisoffhook;
02992    }
02993 
02994    return par.rxisoffhook;
02995 }
02996 
02997 static void dahdi_enable_ec(struct dahdi_pvt *p);
02998 static void dahdi_disable_ec(struct dahdi_pvt *p);
02999 
03000 static int my_set_echocanceller(void *pvt, int enable)
03001 {
03002    struct dahdi_pvt *p = pvt;
03003 
03004    if (enable)
03005       dahdi_enable_ec(p);
03006    else
03007       dahdi_disable_ec(p);
03008 
03009    return 0;
03010 }
03011 
03012 static int dahdi_ring_phone(struct dahdi_pvt *p);
03013 
03014 static int my_ring(void *pvt)
03015 {
03016    struct dahdi_pvt *p = pvt;
03017 
03018    return dahdi_ring_phone(p);
03019 }
03020 
03021 static int my_flash(void *pvt)
03022 {
03023    struct dahdi_pvt *p = pvt;
03024    int func = DAHDI_FLASH;
03025    return ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &func);
03026 }
03027 
03028 static inline int dahdi_set_hook(int fd, int hs);
03029 
03030 static int my_off_hook(void *pvt)
03031 {
03032    struct dahdi_pvt *p = pvt;
03033    return dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
03034 }
03035 
03036 static void my_set_needringing(void *pvt, int value)
03037 {
03038    struct dahdi_pvt *p = pvt;
03039    p->subs[SUB_REAL].needringing = value;
03040 }
03041 
03042 static void my_set_polarity(void *pvt, int value)
03043 {
03044    struct dahdi_pvt *p = pvt;
03045 
03046    if (p->channel == CHAN_PSEUDO) {
03047       return;
03048    }
03049    p->polarity = value;
03050    ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETPOLARITY, &value);
03051 }
03052 
03053 static void my_start_polarityswitch(void *pvt)
03054 {
03055    struct dahdi_pvt *p = pvt;
03056 
03057    if (p->answeronpolarityswitch || p->hanguponpolarityswitch) {
03058       my_set_polarity(pvt, 0);
03059    }
03060 }
03061 
03062 static void my_answer_polarityswitch(void *pvt)
03063 {
03064    struct dahdi_pvt *p = pvt;
03065 
03066    if (!p->answeronpolarityswitch) {
03067       return;
03068    }
03069 
03070    my_set_polarity(pvt, 1);
03071 }
03072 
03073 static void my_hangup_polarityswitch(void *pvt)
03074 {
03075    struct dahdi_pvt *p = pvt;
03076 
03077    if (!p->hanguponpolarityswitch) {
03078       return;
03079    }
03080 
03081    if (p->answeronpolarityswitch) {
03082       my_set_polarity(pvt, 0);
03083    } else {
03084       my_set_polarity(pvt, 1);
03085    }
03086 }
03087 
03088 static int my_start(void *pvt)
03089 {
03090    struct dahdi_pvt *p = pvt;
03091    int x = DAHDI_START;
03092 
03093    return ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
03094 }
03095 
03096 static int my_dial_digits(void *pvt, enum analog_sub sub, struct analog_dialoperation *dop)
03097 {
03098    int index = analogsub_to_dahdisub(sub);
03099    int res;
03100    struct dahdi_pvt *p = pvt;
03101    struct dahdi_dialoperation ddop;
03102 
03103    if (dop->op != ANALOG_DIAL_OP_REPLACE) {
03104       ast_log(LOG_ERROR, "Fix the dial_digits callback!\n");
03105       return -1;
03106    }
03107 
03108    if (sub != ANALOG_SUB_REAL) {
03109       ast_log(LOG_ERROR, "Trying to dial_digits '%s' on channel %d subchannel %u\n",
03110          dop->dialstr, p->channel, sub);
03111       return -1;
03112    }
03113 
03114    ddop.op = DAHDI_DIAL_OP_REPLACE;
03115    ast_copy_string(ddop.dialstr, dop->dialstr, sizeof(ddop.dialstr));
03116 
03117    ast_debug(1, "Channel %d: Sending '%s' to DAHDI_DIAL.\n", p->channel, ddop.dialstr);
03118 
03119    res = ioctl(p->subs[index].dfd, DAHDI_DIAL, &ddop);
03120    if (res == -1) {
03121       ast_debug(1, "DAHDI_DIAL ioctl failed on %s: %s\n", ast_channel_name(p->owner), strerror(errno));
03122    }
03123 
03124    return res;
03125 }
03126 
03127 static void dahdi_train_ec(struct dahdi_pvt *p);
03128 
03129 static int my_train_echocanceller(void *pvt)
03130 {
03131    struct dahdi_pvt *p = pvt;
03132 
03133    dahdi_train_ec(p);
03134 
03135    return 0;
03136 }
03137 
03138 static int my_is_dialing(void *pvt, enum analog_sub sub)
03139 {
03140    struct dahdi_pvt *p = pvt;
03141    int index;
03142    int x;
03143 
03144    index = analogsub_to_dahdisub(sub);
03145 
03146    if (ioctl(p->subs[index].dfd, DAHDI_DIALING, &x)) {
03147       ast_debug(1, "DAHDI_DIALING ioctl failed!\n");
03148       return -1;
03149    }
03150 
03151    return x;
03152 }
03153 
03154 static int my_on_hook(void *pvt)
03155 {
03156    struct dahdi_pvt *p = pvt;
03157    return dahdi_set_hook(p->subs[ANALOG_SUB_REAL].dfd, DAHDI_ONHOOK);
03158 }
03159 
03160 #if defined(HAVE_PRI)
03161 static void my_pri_fixup_chans(void *chan_old, void *chan_new)
03162 {
03163    struct dahdi_pvt *old_chan = chan_old;
03164    struct dahdi_pvt *new_chan = chan_new;
03165 
03166    new_chan->owner = old_chan->owner;
03167    old_chan->owner = NULL;
03168    if (new_chan->owner) {
03169       ast_channel_tech_pvt_set(new_chan->owner, new_chan);
03170       ast_channel_internal_fd_set(new_chan->owner, 0, new_chan->subs[SUB_REAL].dfd);
03171       new_chan->subs[SUB_REAL].owner = old_chan->subs[SUB_REAL].owner;
03172       old_chan->subs[SUB_REAL].owner = NULL;
03173    }
03174    /* Copy any DSP that may be present */
03175    new_chan->dsp = old_chan->dsp;
03176    new_chan->dsp_features = old_chan->dsp_features;
03177    old_chan->dsp = NULL;
03178    old_chan->dsp_features = 0;
03179 
03180    /* Transfer flags from the old channel. */
03181    new_chan->dialing = old_chan->dialing;
03182    new_chan->digital = old_chan->digital;
03183    new_chan->outgoing = old_chan->outgoing;
03184    old_chan->dialing = 0;
03185    old_chan->digital = 0;
03186    old_chan->outgoing = 0;
03187 
03188    /* More stuff to transfer to the new channel. */
03189    new_chan->law = old_chan->law;
03190    strcpy(new_chan->dialstring, old_chan->dialstring);
03191 }
03192 #endif   /* defined(HAVE_PRI) */
03193 
03194 #if defined(HAVE_PRI)
03195 static int sig_pri_tone_to_dahditone(enum sig_pri_tone tone)
03196 {
03197    switch (tone) {
03198    case SIG_PRI_TONE_RINGTONE:
03199       return DAHDI_TONE_RINGTONE;
03200    case SIG_PRI_TONE_STUTTER:
03201       return DAHDI_TONE_STUTTER;
03202    case SIG_PRI_TONE_CONGESTION:
03203       return DAHDI_TONE_CONGESTION;
03204    case SIG_PRI_TONE_DIALTONE:
03205       return DAHDI_TONE_DIALTONE;
03206    case SIG_PRI_TONE_DIALRECALL:
03207       return DAHDI_TONE_DIALRECALL;
03208    case SIG_PRI_TONE_INFO:
03209       return DAHDI_TONE_INFO;
03210    case SIG_PRI_TONE_BUSY:
03211       return DAHDI_TONE_BUSY;
03212    default:
03213       return -1;
03214    }
03215 }
03216 #endif   /* defined(HAVE_PRI) */
03217 
03218 #if defined(HAVE_PRI)
03219 static int pri_destroy_dchan(struct sig_pri_span *pri);
03220 
03221 static void my_handle_dchan_exception(struct sig_pri_span *pri, int index)
03222 {
03223    int x;
03224 
03225    ioctl(pri->fds[index], DAHDI_GETEVENT, &x);
03226    switch (x) {
03227    case DAHDI_EVENT_NONE:
03228       break;
03229    case DAHDI_EVENT_ALARM:
03230    case DAHDI_EVENT_NOALARM:
03231       if (sig_pri_is_alarm_ignored(pri)) {
03232          break;
03233       }
03234       /* Fall through */
03235    default:
03236       ast_log(LOG_NOTICE, "PRI got event: %s (%d) on D-channel of span %d\n",
03237          event2str(x), x, pri->span);
03238       break;
03239    }
03240    /* Keep track of alarm state */
03241    switch (x) {
03242    case DAHDI_EVENT_ALARM:
03243       pri_event_alarm(pri, index, 0);
03244       break;
03245    case DAHDI_EVENT_NOALARM:
03246       pri_event_noalarm(pri, index, 0);
03247       break;
03248    case DAHDI_EVENT_REMOVED:
03249       pri_destroy_dchan(pri);
03250       break;
03251    default:
03252       break;
03253    }
03254 }
03255 #endif   /* defined(HAVE_PRI) */
03256 
03257 #if defined(HAVE_PRI)
03258 static int my_pri_play_tone(void *pvt, enum sig_pri_tone tone)
03259 {
03260    struct dahdi_pvt *p = pvt;
03261 
03262    return tone_zone_play_tone(p->subs[SUB_REAL].dfd, sig_pri_tone_to_dahditone(tone));
03263 }
03264 #endif   /* defined(HAVE_PRI) */
03265 
03266 #if defined(HAVE_PRI) || defined(HAVE_SS7)
03267 /*!
03268  * \internal
03269  * \brief Set the caller id information.
03270  * \since 1.8
03271  *
03272  * \param pvt DAHDI private structure
03273  * \param caller Caller-id information to set.
03274  *
03275  * \return Nothing
03276  */
03277 static void my_set_callerid(void *pvt, const struct ast_party_caller *caller)
03278 {
03279    struct dahdi_pvt *p = pvt;
03280 
03281    ast_copy_string(p->cid_num,
03282       S_COR(caller->id.number.valid, caller->id.number.str, ""),
03283       sizeof(p->cid_num));
03284    ast_copy_string(p->cid_name,
03285       S_COR(caller->id.name.valid, caller->id.name.str, ""),
03286       sizeof(p->cid_name));
03287    ast_copy_string(p->cid_subaddr,
03288       S_COR(caller->id.subaddress.valid, caller->id.subaddress.str, ""),
03289       sizeof(p->cid_subaddr));
03290    p->cid_ton = caller->id.number.plan;
03291    p->callingpres = ast_party_id_presentation(&caller->id);
03292    if (caller->id.tag) {
03293       ast_copy_string(p->cid_tag, caller->id.tag, sizeof(p->cid_tag));
03294    }
03295    ast_copy_string(p->cid_ani,
03296       S_COR(caller->ani.number.valid, caller->ani.number.str, ""),
03297       sizeof(p->cid_ani));
03298    p->cid_ani2 = caller->ani2;
03299 }
03300 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
03301 
03302 #if defined(HAVE_PRI) || defined(HAVE_SS7)
03303 /*!
03304  * \internal
03305  * \brief Set the Dialed Number Identifier.
03306  * \since 1.8
03307  *
03308  * \param pvt DAHDI private structure
03309  * \param dnid Dialed Number Identifier string.
03310  *
03311  * \return Nothing
03312  */
03313 static void my_set_dnid(void *pvt, const char *dnid)
03314 {
03315    struct dahdi_pvt *p = pvt;
03316 
03317    ast_copy_string(p->dnid, dnid, sizeof(p->dnid));
03318 }
03319 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
03320 
03321 #if defined(HAVE_PRI)
03322 /*!
03323  * \internal
03324  * \brief Set the Redirecting Directory Number Information Service (RDNIS).
03325  * \since 1.8
03326  *
03327  * \param pvt DAHDI private structure
03328  * \param rdnis Redirecting Directory Number Information Service (RDNIS) string.
03329  *
03330  * \return Nothing
03331  */
03332 static void my_set_rdnis(void *pvt, const char *rdnis)
03333 {
03334    struct dahdi_pvt *p = pvt;
03335 
03336    ast_copy_string(p->rdnis, rdnis, sizeof(p->rdnis));
03337 }
03338 #endif   /* defined(HAVE_PRI) */
03339 
03340 #if defined(HAVE_PRI)
03341 /*!
03342  * \internal
03343  * \brief Make a dialstring for native ISDN CC to recall properly.
03344  * \since 1.8
03345  *
03346  * \param priv Channel private control structure.
03347  * \param buf Where to put the modified dialstring.
03348  * \param buf_size Size of modified dialstring buffer.
03349  *
03350  * \details
03351  * original dialstring:
03352  * DAHDI/[i<span>-](g|G|r|R)<group#(0-63)>[c|r<cadance#>|d][/extension[/options]]
03353  *
03354  * The modified dialstring will have prefixed the channel-group section
03355  * with the ISDN channel restriction.
03356  *
03357  * buf:
03358  * DAHDI/i<span>-(g|G|r|R)<group#(0-63)>[c|r<cadance#>|d][/extension[/options]]
03359  *
03360  * The routine will check to see if the ISDN channel restriction is already
03361  * in the original dialstring.
03362  *
03363  * \return Nothing
03364  */
03365 static void my_pri_make_cc_dialstring(void *priv, char *buf, size_t buf_size)
03366 {
03367    char *dial;
03368    struct dahdi_pvt *pvt;
03369    AST_DECLARE_APP_ARGS(args,
03370       AST_APP_ARG(tech);   /* channel technology token */
03371       AST_APP_ARG(group);  /* channel/group token */
03372       //AST_APP_ARG(ext);  /* extension token */
03373       //AST_APP_ARG(opts); /* options token */
03374       //AST_APP_ARG(other);   /* Any remining unused arguments */
03375    );
03376 
03377    pvt = priv;
03378    dial = ast_strdupa(pvt->dialstring);
03379    AST_NONSTANDARD_APP_ARGS(args, dial, '/');
03380    if (!args.tech) {
03381       ast_copy_string(buf, pvt->dialstring, buf_size);
03382       return;
03383    }
03384    if (!args.group) {
03385       /* Append the ISDN span channel restriction to the dialstring. */
03386       snprintf(buf, buf_size, "%s/i%d-", args.tech, pvt->pri->span);
03387       return;
03388    }
03389    if (isdigit(args.group[0]) || args.group[0] == 'i' || strchr(args.group, '!')) {
03390       /* The ISDN span channel restriction is not needed or already
03391        * in the dialstring. */
03392       ast_copy_string(buf, pvt->dialstring, buf_size);
03393       return;
03394    }
03395    /* Insert the ISDN span channel restriction into the dialstring. */
03396    snprintf(buf, buf_size, "%s/i%d-%s", args.tech, pvt->pri->span, args.group);
03397 }
03398 #endif   /* defined(HAVE_PRI) */
03399 
03400 #if defined(HAVE_PRI)
03401 /*!
03402  * \internal
03403  * \brief Reevaluate the PRI span device state.
03404  * \since 1.8
03405  *
03406  * \param pri Asterisk D channel control structure.
03407  *
03408  * \return Nothing
03409  *
03410  * \note Assumes the pri->lock is already obtained.
03411  */
03412 static void dahdi_pri_update_span_devstate(struct sig_pri_span *pri)
03413 {
03414    unsigned idx;
03415    unsigned num_b_chans;   /* Number of B channels provisioned on the span. */
03416    unsigned in_use;     /* Number of B channels in use on the span. */
03417    unsigned in_alarm;      /* TRUE if the span is in alarm condition. */
03418    enum ast_device_state new_state;
03419 
03420    /* Count the number of B channels and the number of B channels in use. */
03421    num_b_chans = 0;
03422    in_use = 0;
03423    in_alarm = 1;
03424    for (idx = pri->numchans; idx--;) {
03425       if (pri->pvts[idx] && !pri->pvts[idx]->no_b_channel) {
03426          /* This is a B channel interface. */
03427          ++num_b_chans;
03428          if (!sig_pri_is_chan_available(pri->pvts[idx])) {
03429             ++in_use;
03430          }
03431          if (!pri->pvts[idx]->inalarm) {
03432             /* There is a channel that is not in alarm. */
03433             in_alarm = 0;
03434          }
03435       }
03436    }
03437 
03438    /* Update the span congestion device state and report any change. */
03439    if (in_alarm) {
03440       new_state = AST_DEVICE_UNAVAILABLE;
03441    } else {
03442       new_state = num_b_chans == in_use ? AST_DEVICE_BUSY : AST_DEVICE_NOT_INUSE;
03443    }
03444    if (pri->congestion_devstate != new_state) {
03445       pri->congestion_devstate = new_state;
03446       ast_devstate_changed(AST_DEVICE_UNKNOWN, AST_DEVSTATE_NOT_CACHABLE, "DAHDI/I%d/congestion", pri->span);
03447    }
03448 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
03449    /* Update the span threshold device state and report any change. */
03450    if (in_alarm) {
03451       new_state = AST_DEVICE_UNAVAILABLE;
03452    } else if (!in_use) {
03453       new_state = AST_DEVICE_NOT_INUSE;
03454    } else if (!pri->user_busy_threshold) {
03455       new_state = in_use < num_b_chans ? AST_DEVICE_INUSE : AST_DEVICE_BUSY;
03456    } else {
03457       new_state = in_use < pri->user_busy_threshold ? AST_DEVICE_INUSE
03458          : AST_DEVICE_BUSY;
03459    }
03460    if (pri->threshold_devstate != new_state) {
03461       pri->threshold_devstate = new_state;
03462       ast_devstate_changed(AST_DEVICE_UNKNOWN, AST_DEVSTATE_NOT_CACHABLE, "DAHDI/I%d/threshold", pri->span);
03463    }
03464 #endif   /* defined(THRESHOLD_DEVSTATE_PLACEHOLDER) */
03465 }
03466 #endif   /* defined(HAVE_PRI) */
03467 
03468 #if defined(HAVE_PRI)
03469 /*!
03470  * \internal
03471  * \brief Reference this module.
03472  * \since 1.8
03473  *
03474  * \return Nothing
03475  */
03476 static void my_module_ref(void)
03477 {
03478    ast_module_ref(ast_module_info->self);
03479 }
03480 #endif   /* defined(HAVE_PRI) */
03481 
03482 #if defined(HAVE_PRI)
03483 /*!
03484  * \internal
03485  * \brief Unreference this module.
03486  * \since 1.8
03487  *
03488  * \return Nothing
03489  */
03490 static void my_module_unref(void)
03491 {
03492    ast_module_unref(ast_module_info->self);
03493 }
03494 #endif   /* defined(HAVE_PRI) */
03495 
03496 #if defined(HAVE_PRI)
03497 #if defined(HAVE_PRI_CALL_WAITING)
03498 static void my_pri_init_config(void *priv, struct sig_pri_span *pri);
03499 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
03500 static int dahdi_new_pri_nobch_channel(struct sig_pri_span *pri);
03501 
03502 struct sig_pri_callback sig_pri_callbacks =
03503 {
03504    .handle_dchan_exception = my_handle_dchan_exception,
03505    .play_tone = my_pri_play_tone,
03506    .set_echocanceller = my_set_echocanceller,
03507    .dsp_reset_and_flush_digits = my_dsp_reset_and_flush_digits,
03508    .lock_private = my_lock_private,
03509    .unlock_private = my_unlock_private,
03510    .deadlock_avoidance_private = my_deadlock_avoidance_private,
03511    .new_ast_channel = my_new_pri_ast_channel,
03512    .fixup_chans = my_pri_fixup_chans,
03513    .set_alarm = my_set_alarm,
03514    .set_dialing = my_set_dialing,
03515    .set_outgoing = my_set_outgoing,
03516    .set_digital = my_set_digital,
03517    .set_callerid = my_set_callerid,
03518    .set_dnid = my_set_dnid,
03519    .set_rdnis = my_set_rdnis,
03520    .new_nobch_intf = dahdi_new_pri_nobch_channel,
03521 #if defined(HAVE_PRI_CALL_WAITING)
03522    .init_config = my_pri_init_config,
03523 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
03524    .get_orig_dialstring = my_get_orig_dialstring,
03525    .make_cc_dialstring = my_pri_make_cc_dialstring,
03526    .update_span_devstate = dahdi_pri_update_span_devstate,
03527    .module_ref = my_module_ref,
03528    .module_unref = my_module_unref,
03529    .dial_digits = my_pri_dial_digits,
03530    .open_media = my_pri_ss7_open_media,
03531    .ami_channel_event = my_ami_channel_event,
03532 };
03533 #endif   /* defined(HAVE_PRI) */
03534 
03535 #if defined(HAVE_SS7)
03536 /*!
03537  * \internal
03538  * \brief Handle the SS7 link exception.
03539  * \since 1.8
03540  *
03541  * \param linkset Controlling linkset for the channel.
03542  * \param which Link index of the signaling channel.
03543  *
03544  * \return Nothing
03545  */
03546 static void my_handle_link_exception(struct sig_ss7_linkset *linkset, int which)
03547 {
03548    int event;
03549 
03550    if (ioctl(linkset->fds[which], DAHDI_GETEVENT, &event)) {
03551       ast_log(LOG_ERROR, "SS7: Error in exception retrieval on span %d/%d!\n",
03552          linkset->span, which);
03553       return;
03554    }
03555    switch (event) {
03556    case DAHDI_EVENT_NONE:
03557       break;
03558    case DAHDI_EVENT_ALARM:
03559       ast_log(LOG_ERROR, "SS7 got event: %s(%d) on span %d/%d\n",
03560          event2str(event), event, linkset->span, which);
03561       sig_ss7_link_alarm(linkset, which);
03562       break;
03563    case DAHDI_EVENT_NOALARM:
03564       ast_log(LOG_ERROR, "SS7 got event: %s(%d) on span %d/%d\n",
03565          event2str(event), event, linkset->span, which);
03566       sig_ss7_link_noalarm(linkset, which);
03567       break;
03568    default:
03569       ast_log(LOG_NOTICE, "SS7 got event: %s(%d) on span %d/%d\n",
03570          event2str(event), event, linkset->span, which);
03571       break;
03572    }
03573 }
03574 #endif   /* defined(HAVE_SS7) */
03575 
03576 #if defined(HAVE_SS7)
03577 static void my_ss7_set_loopback(void *pvt, int enable)
03578 {
03579    struct dahdi_pvt *p = pvt;
03580 
03581    if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_LOOPBACK, &enable)) {
03582       ast_log(LOG_WARNING, "Unable to set loopback on channel %d: %s\n", p->channel,
03583          strerror(errno));
03584    }
03585 }
03586 #endif   /* defined(HAVE_SS7) */
03587 
03588 #if defined(HAVE_SS7)
03589 /*!
03590  * \internal
03591  * \brief Create a new asterisk channel structure for SS7.
03592  * \since 1.8
03593  *
03594  * \param pvt Private channel structure.
03595  * \param state Initial state of new channel.
03596  * \param law Combanding law to use.
03597  * \param exten Dialplan extension for incoming call.
03598  * \param requestor Channel requesting this new channel.
03599  *
03600  * \retval ast_channel on success.
03601  * \retval NULL on error.
03602  */
03603 static struct ast_channel *my_new_ss7_ast_channel(void *pvt, int state, enum sig_ss7_law law, char *exten, const struct ast_channel *requestor)
03604 {
03605    struct dahdi_pvt *p = pvt;
03606    int audio;
03607    int newlaw;
03608    struct ast_callid *callid = NULL;
03609    int callid_created = ast_callid_threadstorage_auto(&callid);
03610 
03611    /* Set to audio mode at this point */
03612    audio = 1;
03613    if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &audio) == -1)
03614       ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n",
03615          p->channel, audio, strerror(errno));
03616 
03617    if (law != SIG_SS7_DEFLAW) {
03618       dahdi_setlaw(p->subs[SUB_REAL].dfd,
03619          (law == SIG_SS7_ULAW) ? DAHDI_LAW_MULAW : DAHDI_LAW_ALAW);
03620    }
03621 
03622    ast_copy_string(p->exten, exten, sizeof(p->exten));
03623 
03624    newlaw = -1;
03625    switch (law) {
03626    case SIG_SS7_DEFLAW:
03627       newlaw = 0;
03628       break;
03629    case SIG_SS7_ALAW:
03630       newlaw = DAHDI_LAW_ALAW;
03631       break;
03632    case SIG_SS7_ULAW:
03633       newlaw = DAHDI_LAW_MULAW;
03634       break;
03635    }
03636    return dahdi_new_callid_clean(p, state, 0, SUB_REAL, newlaw, requestor ? ast_channel_linkedid(requestor) : "", callid, callid_created);
03637 }
03638 #endif   /* defined(HAVE_SS7) */
03639 
03640 #if defined(HAVE_SS7)
03641 static int sig_ss7_tone_to_dahditone(enum sig_ss7_tone tone)
03642 {
03643    switch (tone) {
03644    case SIG_SS7_TONE_RINGTONE:
03645       return DAHDI_TONE_RINGTONE;
03646    case SIG_SS7_TONE_STUTTER:
03647       return DAHDI_TONE_STUTTER;
03648    case SIG_SS7_TONE_CONGESTION:
03649       return DAHDI_TONE_CONGESTION;
03650    case SIG_SS7_TONE_DIALTONE:
03651       return DAHDI_TONE_DIALTONE;
03652    case SIG_SS7_TONE_DIALRECALL:
03653       return DAHDI_TONE_DIALRECALL;
03654    case SIG_SS7_TONE_INFO:
03655       return DAHDI_TONE_INFO;
03656    case SIG_SS7_TONE_BUSY:
03657       return DAHDI_TONE_BUSY;
03658    default:
03659       return -1;
03660    }
03661 }
03662 #endif   /* defined(HAVE_SS7) */
03663 
03664 #if defined(HAVE_SS7)
03665 static int my_ss7_play_tone(void *pvt, enum sig_ss7_tone tone)
03666 {
03667    struct dahdi_pvt *p = pvt;
03668 
03669    return tone_zone_play_tone(p->subs[SUB_REAL].dfd, sig_ss7_tone_to_dahditone(tone));
03670 }
03671 #endif   /* defined(HAVE_SS7) */
03672 
03673 #if defined(HAVE_SS7)
03674 struct sig_ss7_callback sig_ss7_callbacks =
03675 {
03676    .lock_private = my_lock_private,
03677    .unlock_private = my_unlock_private,
03678    .deadlock_avoidance_private = my_deadlock_avoidance_private,
03679 
03680    .set_echocanceller = my_set_echocanceller,
03681    .set_loopback = my_ss7_set_loopback,
03682 
03683    .new_ast_channel = my_new_ss7_ast_channel,
03684    .play_tone = my_ss7_play_tone,
03685 
03686    .handle_link_exception = my_handle_link_exception,
03687    .set_alarm = my_set_alarm,
03688    .set_dialing = my_set_dialing,
03689    .set_outgoing = my_set_outgoing,
03690    .set_digital = my_set_digital,
03691    .set_inservice = my_set_inservice,
03692    .set_locallyblocked = my_set_locallyblocked,
03693    .set_remotelyblocked = my_set_remotelyblocked,
03694    .set_callerid = my_set_callerid,
03695    .set_dnid = my_set_dnid,
03696    .open_media = my_pri_ss7_open_media,
03697 };
03698 #endif   /* defined(HAVE_SS7) */
03699 
03700 /*!
03701  * \brief Send MWI state change
03702  *
03703  * \arg mailbox_full This is the mailbox associated with the FXO line that the
03704  *      MWI state has changed on.
03705  * \arg thereornot This argument should simply be set to 1 or 0, to indicate
03706  *      whether there are messages waiting or not.
03707  *
03708  *  \return nothing
03709  *
03710  * This function does two things:
03711  *
03712  * 1) It generates an internal Asterisk event notifying any other module that
03713  *    cares about MWI that the state of a mailbox has changed.
03714  *
03715  * 2) It runs the script specified by the mwimonitornotify option to allow
03716  *    some custom handling of the state change.
03717  */
03718 static void notify_message(char *mailbox_full, int thereornot)
03719 {
03720    char s[sizeof(mwimonitornotify) + 80];
03721    struct ast_event *event;
03722    char *mailbox, *context;
03723 
03724    /* Strip off @default */
03725    context = mailbox = ast_strdupa(mailbox_full);
03726    strsep(&context, "@");
03727    if (ast_strlen_zero(context))
03728       context = "default";
03729 
03730    if (!(event = ast_event_new(AST_EVENT_MWI,
03731          AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
03732          AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
03733          AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot,
03734          AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot,
03735          AST_EVENT_IE_END))) {
03736       return;
03737    }
03738 
03739    ast_event_queue_and_cache(event);
03740 
03741    if (!ast_strlen_zero(mailbox) && !ast_strlen_zero(mwimonitornotify)) {
03742       snprintf(s, sizeof(s), "%s %s %d", mwimonitornotify, mailbox, thereornot);
03743       ast_safe_system(s);
03744    }
03745 }
03746 
03747 static void my_handle_notify_message(struct ast_channel *chan, void *pvt, int cid_flags, int neon_mwievent)
03748 {
03749    struct dahdi_pvt *p = pvt;
03750 
03751    if (neon_mwievent > -1 && !p->mwimonitor_neon)
03752       return;
03753 
03754    if (neon_mwievent == ANALOG_EVENT_NEONMWI_ACTIVE || cid_flags & CID_MSGWAITING) {
03755       ast_log(LOG_NOTICE, "MWI: Channel %d message waiting, mailbox %s\n", p->channel, p->mailbox);
03756       notify_message(p->mailbox, 1);
03757    } else if (neon_mwievent == ANALOG_EVENT_NEONMWI_INACTIVE || cid_flags & CID_NOMSGWAITING) {
03758       ast_log(LOG_NOTICE, "MWI: Channel %d no message waiting, mailbox %s\n", p->channel, p->mailbox);
03759       notify_message(p->mailbox, 0);
03760    }
03761    /* If the CID had Message waiting payload, assume that this for MWI only and hangup the call */
03762    /* If generated using Ring Pulse Alert, then ring has been answered as a call and needs to be hungup */
03763    if (neon_mwievent == -1 && p->mwimonitor_rpas) {
03764       ast_hangup(chan);
03765       return;
03766    }
03767 }
03768 
03769 static int my_have_progressdetect(void *pvt)
03770 {
03771    struct dahdi_pvt *p = pvt;
03772 
03773    if ((p->callprogress & CALLPROGRESS_PROGRESS)
03774       && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
03775       return 1;
03776    } else {
03777       /* Don't have progress detection. */
03778       return 0;
03779    }
03780 }
03781 
03782 struct analog_callback analog_callbacks =
03783 {
03784    .play_tone = my_play_tone,
03785    .get_event = my_get_event,
03786    .wait_event = my_wait_event,
03787    .is_off_hook = my_is_off_hook,
03788    .set_echocanceller = my_set_echocanceller,
03789    .ring = my_ring,
03790    .flash = my_flash,
03791    .off_hook = my_off_hook,
03792    .dial_digits = my_dial_digits,
03793    .train_echocanceller = my_train_echocanceller,
03794    .on_hook = my_on_hook,
03795    .is_dialing = my_is_dialing,
03796    .allocate_sub = my_allocate_sub,
03797    .unallocate_sub = my_unallocate_sub,
03798    .swap_subs = my_swap_subchannels,
03799    .has_voicemail = my_has_voicemail,
03800    .check_for_conference = my_check_for_conference,
03801    .conf_add = my_conf_add,
03802    .conf_del = my_conf_del,
03803    .complete_conference_update = my_complete_conference_update,
03804    .start = my_start,
03805    .all_subchannels_hungup = my_all_subchannels_hungup,
03806    .lock_private = my_lock_private,
03807    .unlock_private = my_unlock_private,
03808    .deadlock_avoidance_private = my_deadlock_avoidance_private,
03809    .handle_dtmf = my_handle_dtmf,
03810    .wink = my_wink,
03811    .new_ast_channel = my_new_analog_ast_channel,
03812    .dsp_set_digitmode = my_dsp_set_digitmode,
03813    .dsp_reset_and_flush_digits = my_dsp_reset_and_flush_digits,
03814    .send_callerid = my_send_callerid,
03815    .callwait = my_callwait,
03816    .stop_callwait = my_stop_callwait,
03817    .get_callerid = my_get_callerid,
03818    .start_cid_detect = my_start_cid_detect,
03819    .stop_cid_detect = my_stop_cid_detect,
03820    .handle_notify_message = my_handle_notify_message,
03821    .increase_ss_count = my_increase_ss_count,
03822    .decrease_ss_count = my_decrease_ss_count,
03823    .distinctive_ring = my_distinctive_ring,
03824    .set_linear_mode = my_set_linear_mode,
03825    .set_inthreeway = my_set_inthreeway,
03826    .get_and_handle_alarms = my_get_and_handle_alarms,
03827    .get_sigpvt_bridged_channel = my_get_sigpvt_bridged_channel,
03828    .get_sub_fd = my_get_sub_fd,
03829    .set_cadence = my_set_cadence,
03830    .set_alarm = my_set_alarm,
03831    .set_dialing = my_set_dialing,
03832    .set_outgoing = my_set_outgoing,
03833    .set_ringtimeout = my_set_ringtimeout,
03834    .set_waitingfordt = my_set_waitingfordt,
03835    .check_waitingfordt = my_check_waitingfordt,
03836    .set_confirmanswer = my_set_confirmanswer,
03837    .check_confirmanswer = my_check_confirmanswer,
03838    .set_callwaiting = my_set_callwaiting,
03839    .cancel_cidspill = my_cancel_cidspill,
03840    .confmute = my_confmute,
03841    .set_pulsedial = my_set_pulsedial,
03842    .set_new_owner = my_set_new_owner,
03843    .get_orig_dialstring = my_get_orig_dialstring,
03844    .set_needringing = my_set_needringing,
03845    .set_polarity = my_set_polarity,
03846    .start_polarityswitch = my_start_polarityswitch,
03847    .answer_polarityswitch = my_answer_polarityswitch,
03848    .hangup_polarityswitch = my_hangup_polarityswitch,
03849    .have_progressdetect = my_have_progressdetect,
03850 };
03851 
03852 /*! Round robin search locations. */
03853 static struct dahdi_pvt *round_robin[32];
03854 
03855 #define dahdi_get_index(ast, p, nullok)   _dahdi_get_index(ast, p, nullok, __PRETTY_FUNCTION__, __LINE__)
03856 static int _dahdi_get_index(struct ast_channel *ast, struct dahdi_pvt *p, int nullok, const char *fname, unsigned long line)
03857 {
03858    int res;
03859    if (p->subs[SUB_REAL].owner == ast)
03860       res = 0;
03861    else if (p->subs[SUB_CALLWAIT].owner == ast)
03862       res = 1;
03863    else if (p->subs[SUB_THREEWAY].owner == ast)
03864       res = 2;
03865    else {
03866       res = -1;
03867       if (!nullok)
03868          ast_log(LOG_WARNING,
03869             "Unable to get index for '%s' on channel %d (%s(), line %lu)\n",
03870             ast ? ast_channel_name(ast) : "", p->channel, fname, line);
03871    }
03872    return res;
03873 }
03874 
03875 /*!
03876  * \internal
03877  * \brief Obtain the specified subchannel owner lock if the owner exists.
03878  *
03879  * \param pvt Channel private struct.
03880  * \param sub_idx Subchannel owner to lock.
03881  *
03882  * \note Assumes the pvt->lock is already obtained.
03883  *
03884  * \note
03885  * Because deadlock avoidance may have been necessary, you need to confirm
03886  * the state of things before continuing.
03887  *
03888  * \return Nothing
03889  */
03890 static void dahdi_lock_sub_owner(struct dahdi_pvt *pvt, int sub_idx)
03891 {
03892    for (;;) {
03893       if (!pvt->subs[sub_idx].owner) {
03894          /* No subchannel owner pointer */
03895          break;
03896       }
03897       if (!ast_channel_trylock(pvt->subs[sub_idx].owner)) {
03898          /* Got subchannel owner lock */
03899          break;
03900       }
03901       /* We must unlock the private to avoid the possibility of a deadlock */
03902       DEADLOCK_AVOIDANCE(&pvt->lock);
03903    }
03904 }
03905 
03906 static void wakeup_sub(struct dahdi_pvt *p, int a)
03907 {
03908    dahdi_lock_sub_owner(p, a);
03909    if (p->subs[a].owner) {
03910       ast_queue_frame(p->subs[a].owner, &ast_null_frame);
03911       ast_channel_unlock(p->subs[a].owner);
03912    }
03913 }
03914 
03915 static void dahdi_queue_frame(struct dahdi_pvt *p, struct ast_frame *f)
03916 {
03917    for (;;) {
03918       if (p->owner) {
03919          if (ast_channel_trylock(p->owner)) {
03920             DEADLOCK_AVOIDANCE(&p->lock);
03921          } else {
03922             ast_queue_frame(p->owner, f);
03923             ast_channel_unlock(p->owner);
03924             break;
03925          }
03926       } else
03927          break;
03928    }
03929 }
03930 
03931 static void handle_clear_alarms(struct dahdi_pvt *p)
03932 {
03933 #if defined(HAVE_PRI)
03934    if (dahdi_sig_pri_lib_handles(p->sig) && sig_pri_is_alarm_ignored(p->pri)) {
03935       return;
03936    }
03937 #endif   /* defined(HAVE_PRI) */
03938 
03939    if (report_alarms & REPORT_CHANNEL_ALARMS) {
03940       ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel);
03941       /*** DOCUMENTATION
03942          <managerEventInstance>
03943             <synopsis>Raised when an alarm is cleared on a DAHDI channel.</synopsis>
03944          </managerEventInstance>
03945       ***/
03946       manager_event(EVENT_FLAG_SYSTEM, "AlarmClear", "Channel: %d\r\n", p->channel);
03947    }
03948    if (report_alarms & REPORT_SPAN_ALARMS && p->manages_span_alarms) {
03949       ast_log(LOG_NOTICE, "Alarm cleared on span %d\n", p->span);
03950       /*** DOCUMENTATION
03951          <managerEventInstance>
03952             <synopsis>Raised when an alarm is cleared on a DAHDI span.</synopsis>
03953          </managerEventInstance>
03954       ***/
03955       manager_event(EVENT_FLAG_SYSTEM, "SpanAlarmClear", "Span: %d\r\n", p->span);
03956    }
03957 }
03958 
03959 #ifdef HAVE_OPENR2
03960 
03961 static int dahdi_r2_answer(struct dahdi_pvt *p)
03962 {
03963    int res = 0;
03964    /* openr2 1.1.0 and older does not even define OR2_LIB_INTERFACE
03965    * and does not has support for openr2_chan_answer_call_with_mode
03966    *  */
03967 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
03968    const char *double_answer = pbx_builtin_getvar_helper(p->owner, "MFCR2_DOUBLE_ANSWER");
03969    int wants_double_answer = ast_true(double_answer) ? 1 : 0;
03970    if (!double_answer) {
03971       /* this still can result in double answer if the channel context
03972       * was configured that way */
03973       res = openr2_chan_answer_call(p->r2chan);
03974    } else if (wants_double_answer) {
03975       res = openr2_chan_answer_call_with_mode(p->r2chan, OR2_ANSWER_DOUBLE);
03976    } else {
03977       res = openr2_chan_answer_call_with_mode(p->r2chan, OR2_ANSWER_SIMPLE);
03978    }
03979 #else
03980    res = openr2_chan_answer_call(p->r2chan);
03981 #endif
03982    return res;
03983 }
03984 
03985 
03986 
03987 /* should be called with the ast_channel locked */
03988 static openr2_calling_party_category_t dahdi_r2_get_channel_category(struct ast_channel *c)
03989 {
03990    openr2_calling_party_category_t cat;
03991    const char *catstr = pbx_builtin_getvar_helper(c, "MFCR2_CATEGORY");
03992    struct dahdi_pvt *p = ast_channel_tech_pvt(c);
03993    if (ast_strlen_zero(catstr)) {
03994       ast_debug(1, "No MFC/R2 category specified for chan %s, using default %s\n",
03995             ast_channel_name(c), openr2_proto_get_category_string(p->mfcr2_category));
03996       return p->mfcr2_category;
03997    }
03998    if ((cat = openr2_proto_get_category(catstr)) == OR2_CALLING_PARTY_CATEGORY_UNKNOWN) {
03999       ast_log(LOG_WARNING, "Invalid category specified '%s' for chan %s, using default %s\n",
04000             catstr, ast_channel_name(c), openr2_proto_get_category_string(p->mfcr2_category));
04001       return p->mfcr2_category;
04002    }
04003    ast_debug(1, "Using category %s\n", catstr);
04004    return cat;
04005 }
04006 
04007 static void dahdi_r2_on_call_init(openr2_chan_t *r2chan)
04008 {
04009    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04010    ast_mutex_lock(&p->lock);
04011    if (p->mfcr2call) {
04012       ast_mutex_unlock(&p->lock);
04013       /* TODO: This can happen when some other thread just finished dahdi_request requesting this very same
04014          interface but has not yet seized the line (dahdi_call), and the far end wins and seize the line,
04015          can we avoid this somehow?, at this point when dahdi_call send the seize, it is likely that since
04016          the other end will see our seize as a forced release and drop the call, we will see an invalid
04017          pattern that will be seen and treated as protocol error. */
04018       ast_log(LOG_ERROR, "Collision of calls on chan %d detected!.\n", openr2_chan_get_number(r2chan));
04019       return;
04020    }
04021    p->mfcr2call = 1;
04022    /* better safe than sorry ... */
04023    p->cid_name[0] = '\0';
04024    p->cid_num[0] = '\0';
04025    p->cid_subaddr[0] = '\0';
04026    p->rdnis[0] = '\0';
04027    p->exten[0] = '\0';
04028    p->mfcr2_ani_index = '\0';
04029    p->mfcr2_dnis_index = '\0';
04030    p->mfcr2_dnis_matched = 0;
04031    p->mfcr2_answer_pending = 0;
04032    p->mfcr2_call_accepted = 0;
04033    ast_mutex_unlock(&p->lock);
04034    ast_verbose("New MFC/R2 call detected on chan %d.\n", openr2_chan_get_number(r2chan));
04035 }
04036 
04037 static void dahdi_r2_on_hardware_alarm(openr2_chan_t *r2chan, int alarm)
04038 {
04039    int res;
04040    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04041    ast_mutex_lock(&p->lock);
04042    p->inalarm = alarm ? 1 : 0;
04043    if (p->inalarm) {
04044       res = get_alarms(p);
04045       handle_alarms(p, res);
04046    } else {
04047       handle_clear_alarms(p);
04048    }
04049    ast_mutex_unlock(&p->lock);
04050 }
04051 
04052 static void dahdi_r2_on_os_error(openr2_chan_t *r2chan, int errorcode)
04053 {
04054    ast_log(LOG_ERROR, "OS error on chan %d: %s\n", openr2_chan_get_number(r2chan), strerror(errorcode));
04055 }
04056 
04057 static void dahdi_r2_on_protocol_error(openr2_chan_t *r2chan, openr2_protocol_error_t reason)
04058 {
04059    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04060    ast_log(LOG_ERROR, "MFC/R2 protocol error on chan %d: %s\n", openr2_chan_get_number(r2chan), openr2_proto_get_error(reason));
04061    if (p->owner) {
04062       ast_channel_hangupcause_set(p->owner, AST_CAUSE_PROTOCOL_ERROR);
04063       ast_channel_softhangup_internal_flag_add(p->owner, AST_SOFTHANGUP_DEV);
04064    }
04065    ast_mutex_lock(&p->lock);
04066    p->mfcr2call = 0;
04067    ast_mutex_unlock(&p->lock);
04068 }
04069 
04070 static void dahdi_r2_disconnect_call(struct dahdi_pvt *p, openr2_call_disconnect_cause_t cause)
04071 {
04072    if (openr2_chan_disconnect_call(p->r2chan, cause)) {
04073       ast_log(LOG_NOTICE, "Bad! failed to disconnect call on channel %d with reason %s, hope for the best!\n",
04074          p->channel, openr2_proto_get_disconnect_string(cause));
04075       /* force the chan to idle and release the call flag now since we will not see a clean on_call_end */
04076       openr2_chan_set_idle(p->r2chan);
04077       ast_mutex_lock(&p->lock);
04078       p->mfcr2call = 0;
04079       ast_mutex_unlock(&p->lock);
04080    }
04081 }
04082 
04083 static void dahdi_r2_on_call_offered(openr2_chan_t *r2chan, const char *ani, const char *dnis, openr2_calling_party_category_t category)
04084 {
04085    struct dahdi_pvt *p;
04086    struct ast_channel *c;
04087    struct ast_callid *callid = NULL;
04088    int callid_created = ast_callid_threadstorage_auto(&callid);
04089    ast_verbose("MFC/R2 call offered on chan %d. ANI = %s, DNIS = %s, Category = %s\n",
04090          openr2_chan_get_number(r2chan), ani ? ani : "(restricted)", dnis,
04091          openr2_proto_get_category_string(category));
04092    p = openr2_chan_get_client_data(r2chan);
04093    /* if collect calls are not allowed and this is a collect call, reject it! */
04094    if (!p->mfcr2_allow_collect_calls && category == OR2_CALLING_PARTY_CATEGORY_COLLECT_CALL) {
04095       ast_log(LOG_NOTICE, "Rejecting MFC/R2 collect call\n");
04096       dahdi_r2_disconnect_call(p, OR2_CAUSE_COLLECT_CALL_REJECTED);
04097       goto dahdi_r2_on_call_offered_cleanup;
04098    }
04099    ast_mutex_lock(&p->lock);
04100    p->mfcr2_recvd_category = category;
04101    /* if we're not supposed to use CID, clear whatever we have */
04102    if (!p->use_callerid) {
04103       ast_debug(1, "No CID allowed in configuration, CID is being cleared!\n");
04104       p->cid_num[0] = 0;
04105       p->cid_name[0] = 0;
04106    }
04107    /* if we're supposed to answer immediately, clear DNIS and set 's' exten */
04108    if (p->immediate || !openr2_context_get_max_dnis(openr2_chan_get_context(r2chan))) {
04109       ast_debug(1, "Setting exten => s because of immediate or 0 DNIS configured\n");
04110       p->exten[0] = 's';
04111       p->exten[1] = 0;
04112    }
04113    ast_mutex_unlock(&p->lock);
04114    if (!ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
04115       ast_log(LOG_NOTICE, "MFC/R2 call on channel %d requested non-existent extension '%s' in context '%s'. Rejecting call.\n",
04116             p->channel, p->exten, p->context);
04117       dahdi_r2_disconnect_call(p, OR2_CAUSE_UNALLOCATED_NUMBER);
04118       goto dahdi_r2_on_call_offered_cleanup;
04119    }
04120    if (!p->mfcr2_accept_on_offer) {
04121       /* The user wants us to start the PBX thread right away without accepting the call first */
04122       c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, NULL, callid);
04123       if (c) {
04124          /* Done here, don't disable reading now since we still need to generate MF tones to accept
04125             the call or reject it and detect the tone off condition of the other end, all of this
04126             will be done in the PBX thread now */
04127          goto dahdi_r2_on_call_offered_cleanup;
04128       }
04129       ast_log(LOG_WARNING, "Unable to create PBX channel in DAHDI channel %d\n", p->channel);
04130       dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER);
04131    } else if (p->mfcr2_charge_calls) {
04132       ast_debug(1, "Accepting MFC/R2 call with charge on chan %d\n", p->channel);
04133       openr2_chan_accept_call(r2chan, OR2_CALL_WITH_CHARGE);
04134    } else {
04135       ast_debug(1, "Accepting MFC/R2 call with no charge on chan %d\n", p->channel);
04136       openr2_chan_accept_call(r2chan, OR2_CALL_NO_CHARGE);
04137    }
04138 
04139 dahdi_r2_on_call_offered_cleanup:
04140    ast_callid_threadstorage_auto_clean(callid, callid_created);
04141 }
04142 
04143 static void dahdi_r2_on_call_end(openr2_chan_t *r2chan)
04144 {
04145    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04146    ast_verbose("MFC/R2 call end on channel %d\n", p->channel);
04147    ast_mutex_lock(&p->lock);
04148    p->mfcr2call = 0;
04149    ast_mutex_unlock(&p->lock);
04150 }
04151 
04152 static void dahdi_enable_ec(struct dahdi_pvt *p);
04153 static void dahdi_r2_on_call_accepted(openr2_chan_t *r2chan, openr2_call_mode_t mode)
04154 {
04155    struct dahdi_pvt *p = NULL;
04156    struct ast_channel *c = NULL;
04157    struct ast_callid *callid = NULL;
04158    int callid_created = ast_callid_threadstorage_auto(&callid);
04159    p = openr2_chan_get_client_data(r2chan);
04160    dahdi_enable_ec(p);
04161    p->mfcr2_call_accepted = 1;
04162    /* if it's an incoming call ... */
04163    if (OR2_DIR_BACKWARD == openr2_chan_get_direction(r2chan)) {
04164       ast_verbose("MFC/R2 call has been accepted on backward channel %d\n", openr2_chan_get_number(r2chan));
04165       /* If accept on offer is not set, it means at this point the PBX thread is already
04166          launched (was launched in the 'on call offered' handler) and therefore this callback
04167          is being executed already in the PBX thread rather than the monitor thread, don't launch
04168          any other thread, just disable the openr2 reading and answer the call if needed */
04169       if (!p->mfcr2_accept_on_offer) {
04170          openr2_chan_disable_read(r2chan);
04171          if (p->mfcr2_answer_pending) {
04172             ast_debug(1, "Answering MFC/R2 call after accepting it on chan %d\n", openr2_chan_get_number(r2chan));
04173             dahdi_r2_answer(p);
04174          }
04175          goto dahdi_r2_on_call_accepted_cleanup;
04176       }
04177       c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, NULL, callid);
04178       if (c) {
04179          /* chan_dahdi will take care of reading from now on in the PBX thread, tell the
04180             library to forget about it */
04181          openr2_chan_disable_read(r2chan);
04182          goto dahdi_r2_on_call_accepted_cleanup;
04183       }
04184       ast_log(LOG_WARNING, "Unable to create PBX channel in DAHDI channel %d\n", p->channel);
04185       /* failed to create the channel, bail out and report it as an out of order line */
04186       dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER);
04187       goto dahdi_r2_on_call_accepted_cleanup;
04188    }
04189    /* this is an outgoing call, no need to launch the PBX thread, most likely we're in one already */
04190    ast_verbose("MFC/R2 call has been accepted on forward channel %d\n", p->channel);
04191    p->subs[SUB_REAL].needringing = 1;
04192    p->dialing = 0;
04193    /* chan_dahdi will take care of reading from now on in the PBX thread, tell the library to forget about it */
04194    openr2_chan_disable_read(r2chan);
04195 
04196 dahdi_r2_on_call_accepted_cleanup:
04197    ast_callid_threadstorage_auto_clean(callid, callid_created);
04198 }
04199 
04200 static void dahdi_r2_on_call_answered(openr2_chan_t *r2chan)
04201 {
04202    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04203    ast_verbose("MFC/R2 call has been answered on channel %d\n", openr2_chan_get_number(r2chan));
04204    p->subs[SUB_REAL].needanswer = 1;
04205 }
04206 
04207 static void dahdi_r2_on_call_read(openr2_chan_t *r2chan, const unsigned char *buf, int buflen)
04208 {
04209    /*ast_debug(1, "Read data from dahdi channel %d\n", openr2_chan_get_number(r2chan));*/
04210 }
04211 
04212 static int dahdi_r2_cause_to_ast_cause(openr2_call_disconnect_cause_t cause)
04213 {
04214    switch (cause) {
04215    case OR2_CAUSE_BUSY_NUMBER:
04216       return AST_CAUSE_BUSY;
04217    case OR2_CAUSE_NETWORK_CONGESTION:
04218       return AST_CAUSE_CONGESTION;
04219    case OR2_CAUSE_OUT_OF_ORDER:
04220       return AST_CAUSE_DESTINATION_OUT_OF_ORDER;
04221    case OR2_CAUSE_UNALLOCATED_NUMBER:
04222       return AST_CAUSE_UNREGISTERED;
04223    case OR2_CAUSE_NO_ANSWER:
04224       return AST_CAUSE_NO_ANSWER;
04225    case OR2_CAUSE_NORMAL_CLEARING:
04226       return AST_CAUSE_NORMAL_CLEARING;
04227    case OR2_CAUSE_UNSPECIFIED:
04228    default:
04229       return AST_CAUSE_NOTDEFINED;
04230    }
04231 }
04232 
04233 static void dahdi_r2_on_call_disconnect(openr2_chan_t *r2chan, openr2_call_disconnect_cause_t cause)
04234 {
04235    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04236    char cause_str[50];
04237    struct ast_control_pvt_cause_code *cause_code;
04238    int datalen = sizeof(*cause_code);
04239 
04240    ast_verbose("MFC/R2 call disconnected on channel %d\n", openr2_chan_get_number(r2chan));
04241    ast_mutex_lock(&p->lock);
04242    if (!p->owner) {
04243       ast_mutex_unlock(&p->lock);
04244       /* no owner, therefore we can't use dahdi_hangup to disconnect, do it right now */
04245       dahdi_r2_disconnect_call(p, OR2_CAUSE_NORMAL_CLEARING);
04246       return;
04247    }
04248 
04249    snprintf(cause_str, sizeof(cause_str), "R2 DISCONNECT (%s)", openr2_proto_get_disconnect_string(cause));
04250    datalen += strlen(cause_str);
04251    cause_code = ast_alloca(datalen);
04252    memset(cause_code, 0, datalen);
04253    cause_code->ast_cause = dahdi_r2_cause_to_ast_cause(cause);
04254    ast_copy_string(cause_code->chan_name, ast_channel_name(p->owner), AST_CHANNEL_NAME);
04255    ast_copy_string(cause_code->code, cause_str, datalen + 1 - sizeof(*cause_code));
04256    ast_queue_control_data(p->owner, AST_CONTROL_PVT_CAUSE_CODE, cause_code, datalen);
04257    ast_channel_hangupcause_hash_set(p->owner, cause_code, datalen);
04258 
04259    /* when we have an owner we don't call dahdi_r2_disconnect_call here, that will
04260       be done in dahdi_hangup */
04261    if (ast_channel_state(p->owner) == AST_STATE_UP) {
04262       ast_channel_softhangup_internal_flag_add(p->owner, AST_SOFTHANGUP_DEV);
04263       ast_mutex_unlock(&p->lock);
04264    } else if (openr2_chan_get_direction(r2chan) == OR2_DIR_FORWARD) {
04265       /* being the forward side we must report what happened to the call to whoever requested it */
04266       switch (cause) {
04267       case OR2_CAUSE_BUSY_NUMBER:
04268          p->subs[SUB_REAL].needbusy = 1;
04269          break;
04270       case OR2_CAUSE_NETWORK_CONGESTION:
04271       case OR2_CAUSE_OUT_OF_ORDER:
04272       case OR2_CAUSE_UNALLOCATED_NUMBER:
04273       case OR2_CAUSE_NO_ANSWER:
04274       case OR2_CAUSE_UNSPECIFIED:
04275       case OR2_CAUSE_NORMAL_CLEARING:
04276          p->subs[SUB_REAL].needcongestion = 1;
04277          break;
04278       default:
04279          ast_channel_softhangup_internal_flag_add(p->owner, AST_SOFTHANGUP_DEV);
04280       }
04281       ast_mutex_unlock(&p->lock);
04282    } else {
04283       ast_mutex_unlock(&p->lock);
04284       /* being the backward side and not UP yet, we only need to request hangup */
04285       /* TODO: what about doing this same thing when were AST_STATE_UP? */
04286       ast_queue_hangup_with_cause(p->owner, dahdi_r2_cause_to_ast_cause(cause));
04287    }
04288 }
04289 
04290 static void dahdi_r2_write_log(openr2_log_level_t level, char *logmessage)
04291 {
04292    switch (level) {
04293    case OR2_LOG_NOTICE:
04294       ast_verbose("%s", logmessage);
04295       break;
04296    case OR2_LOG_WARNING:
04297       ast_log(LOG_WARNING, "%s", logmessage);
04298       break;
04299    case OR2_LOG_ERROR:
04300       ast_log(LOG_ERROR, "%s", logmessage);
04301       break;
04302    case OR2_LOG_STACK_TRACE:
04303    case OR2_LOG_MF_TRACE:
04304    case OR2_LOG_CAS_TRACE:
04305    case OR2_LOG_DEBUG:
04306    case OR2_LOG_EX_DEBUG:
04307       ast_debug(1, "%s", logmessage);
04308       break;
04309    default:
04310       ast_log(LOG_WARNING, "We should handle logging level %d here.\n", level);
04311       ast_debug(1, "%s", logmessage);
04312       break;
04313    }
04314 }
04315 
04316 static void dahdi_r2_on_line_blocked(openr2_chan_t *r2chan)
04317 {
04318    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04319    ast_mutex_lock(&p->lock);
04320    p->remotelyblocked = 1;
04321    ast_mutex_unlock(&p->lock);
04322    ast_log(LOG_NOTICE, "Far end blocked on chan %d\n", openr2_chan_get_number(r2chan));
04323 }
04324 
04325 static void dahdi_r2_on_line_idle(openr2_chan_t *r2chan)
04326 {
04327    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04328    ast_mutex_lock(&p->lock);
04329    p->remotelyblocked = 0;
04330    ast_mutex_unlock(&p->lock);
04331    ast_log(LOG_NOTICE, "Far end unblocked on chan %d\n", openr2_chan_get_number(r2chan));
04332 }
04333 
04334 static void dahdi_r2_on_context_log(openr2_context_t *r2context, openr2_log_level_t level, const char *fmt, va_list ap)
04335    __attribute__((format (printf, 3, 0)));
04336 static void dahdi_r2_on_context_log(openr2_context_t *r2context, openr2_log_level_t level, const char *fmt, va_list ap)
04337 {
04338 #define CONTEXT_TAG "Context - "
04339    char logmsg[256];
04340    char completemsg[sizeof(logmsg) + sizeof(CONTEXT_TAG) - 1];
04341    vsnprintf(logmsg, sizeof(logmsg), fmt, ap);
04342    snprintf(completemsg, sizeof(completemsg), CONTEXT_TAG "%s", logmsg);
04343    dahdi_r2_write_log(level, completemsg);
04344 #undef CONTEXT_TAG
04345 }
04346 
04347 static void dahdi_r2_on_chan_log(openr2_chan_t *r2chan, openr2_log_level_t level, const char *fmt, va_list ap)
04348    __attribute__((format (printf, 3, 0)));
04349 static void dahdi_r2_on_chan_log(openr2_chan_t *r2chan, openr2_log_level_t level, const char *fmt, va_list ap)
04350 {
04351 #define CHAN_TAG "Chan "
04352    char logmsg[256];
04353    char completemsg[sizeof(logmsg) + sizeof(CHAN_TAG) - 1];
04354    vsnprintf(logmsg, sizeof(logmsg), fmt, ap);
04355    snprintf(completemsg, sizeof(completemsg), CHAN_TAG "%d - %s", openr2_chan_get_number(r2chan), logmsg);
04356    dahdi_r2_write_log(level, completemsg);
04357 }
04358 
04359 static int dahdi_r2_on_dnis_digit_received(openr2_chan_t *r2chan, char digit)
04360 {
04361    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04362    /* if 'immediate' is set, let's stop requesting DNIS */
04363    if (p->immediate) {
04364       return 0;
04365    }
04366    p->exten[p->mfcr2_dnis_index] = digit;
04367    p->rdnis[p->mfcr2_dnis_index] = digit;
04368    p->mfcr2_dnis_index++;
04369    p->exten[p->mfcr2_dnis_index] = 0;
04370    p->rdnis[p->mfcr2_dnis_index] = 0;
04371    /* if the DNIS is a match and cannot match more, stop requesting DNIS */
04372    if ((p->mfcr2_dnis_matched ||
04373        (ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num) && (p->mfcr2_dnis_matched = 1))) &&
04374        !ast_matchmore_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
04375       return 0;
04376    }
04377    /* otherwise keep going */
04378    return 1;
04379 }
04380 
04381 static void dahdi_r2_on_ani_digit_received(openr2_chan_t *r2chan, char digit)
04382 {
04383    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04384    p->cid_num[p->mfcr2_ani_index] = digit;
04385    p->cid_name[p->mfcr2_ani_index] = digit;
04386    p->mfcr2_ani_index++;
04387    p->cid_num[p->mfcr2_ani_index] = 0;
04388    p->cid_name[p->mfcr2_ani_index] = 0;
04389 }
04390 
04391 static void dahdi_r2_on_billing_pulse_received(openr2_chan_t *r2chan)
04392 {
04393    ast_verbose("MFC/R2 billing pulse received on channel %d\n", openr2_chan_get_number(r2chan));
04394 }
04395 
04396 static openr2_event_interface_t dahdi_r2_event_iface = {
04397    .on_call_init = dahdi_r2_on_call_init,
04398    .on_call_offered = dahdi_r2_on_call_offered,
04399    .on_call_accepted = dahdi_r2_on_call_accepted,
04400    .on_call_answered = dahdi_r2_on_call_answered,
04401    .on_call_disconnect = dahdi_r2_on_call_disconnect,
04402    .on_call_end = dahdi_r2_on_call_end,
04403    .on_call_read = dahdi_r2_on_call_read,
04404    .on_hardware_alarm = dahdi_r2_on_hardware_alarm,
04405    .on_os_error = dahdi_r2_on_os_error,
04406    .on_protocol_error = dahdi_r2_on_protocol_error,
04407    .on_line_blocked = dahdi_r2_on_line_blocked,
04408    .on_line_idle = dahdi_r2_on_line_idle,
04409    /* cast seems to be needed to get rid of the annoying warning regarding format attribute  */
04410    .on_context_log = (openr2_handle_context_logging_func)dahdi_r2_on_context_log,
04411    .on_dnis_digit_received = dahdi_r2_on_dnis_digit_received,
04412    .on_ani_digit_received = dahdi_r2_on_ani_digit_received,
04413    /* so far we do nothing with billing pulses */
04414    .on_billing_pulse_received = dahdi_r2_on_billing_pulse_received
04415 };
04416 
04417 static inline int16_t dahdi_r2_alaw_to_linear(uint8_t sample)
04418 {
04419    return AST_ALAW(sample);
04420 }
04421 
04422 static inline uint8_t dahdi_r2_linear_to_alaw(int sample)
04423 {
04424    return AST_LIN2A(sample);
04425 }
04426 
04427 static openr2_transcoder_interface_t dahdi_r2_transcode_iface = {
04428    dahdi_r2_alaw_to_linear,
04429    dahdi_r2_linear_to_alaw
04430 };
04431 
04432 #endif /* HAVE_OPENR2 */
04433 
04434 static void swap_subs(struct dahdi_pvt *p, int a, int b)
04435 {
04436    int tchan;
04437    int tinthreeway;
04438    struct ast_channel *towner;
04439 
04440    ast_debug(1, "Swapping %d and %d\n", a, b);
04441 
04442    tchan = p->subs[a].chan;
04443    towner = p->subs[a].owner;
04444    tinthreeway = p->subs[a].inthreeway;
04445 
04446    p->subs[a].chan = p->subs[b].chan;
04447    p->subs[a].owner = p->subs[b].owner;
04448    p->subs[a].inthreeway = p->subs[b].inthreeway;
04449 
04450    p->subs[b].chan = tchan;
04451    p->subs[b].owner = towner;
04452    p->subs[b].inthreeway = tinthreeway;
04453 
04454    if (p->subs[a].owner)
04455       ast_channel_set_fd(p->subs[a].owner, 0, p->subs[a].dfd);
04456    if (p->subs[b].owner)
04457       ast_channel_set_fd(p->subs[b].owner, 0, p->subs[b].dfd);
04458    wakeup_sub(p, a);
04459    wakeup_sub(p, b);
04460 }
04461 
04462 static int dahdi_open(char *fn)
04463 {
04464    int fd;
04465    int isnum;
04466    int chan = 0;
04467    int bs;
04468    int x;
04469    isnum = 1;
04470    for (x = 0; x < strlen(fn); x++) {
04471       if (!isdigit(fn[x])) {
04472          isnum = 0;
04473          break;
04474       }
04475    }
04476    if (isnum) {
04477       chan = atoi(fn);
04478       if (chan < 1) {
04479          ast_log(LOG_WARNING, "Invalid channel number '%s'\n", fn);
04480          return -1;
04481       }
04482       fn = "/dev/dahdi/channel";
04483    }
04484    fd = open(fn, O_RDWR | O_NONBLOCK);
04485    if (fd < 0) {
04486       ast_log(LOG_WARNING, "Unable to open '%s': %s\n", fn, strerror(errno));
04487       return -1;
04488    }
04489    if (chan) {
04490       if (ioctl(fd, DAHDI_SPECIFY, &chan)) {
04491          x = errno;
04492          close(fd);
04493          errno = x;
04494          ast_log(LOG_WARNING, "Unable to specify channel %d: %s\n", chan, strerror(errno));
04495          return -1;
04496       }
04497    }
04498    bs = READ_SIZE;
04499    if (ioctl(fd, DAHDI_SET_BLOCKSIZE, &bs) == -1) {
04500       ast_log(LOG_WARNING, "Unable to set blocksize '%d': %s\n", bs,  strerror(errno));
04501       x = errno;
04502       close(fd);
04503       errno = x;
04504       return -1;
04505    }
04506    return fd;
04507 }
04508 
04509 static void dahdi_close(int fd)
04510 {
04511    if (fd > 0)
04512       close(fd);
04513 }
04514 
04515 static void dahdi_close_sub(struct dahdi_pvt *chan_pvt, int sub_num)
04516 {
04517    dahdi_close(chan_pvt->subs[sub_num].dfd);
04518    chan_pvt->subs[sub_num].dfd = -1;
04519 }
04520 
04521 #if defined(HAVE_PRI)
04522 static void dahdi_close_pri_fd(struct dahdi_pri *pri, int fd_num)
04523 {
04524    dahdi_close(pri->pri.fds[fd_num]);
04525    pri->pri.fds[fd_num] = -1;
04526 }
04527 #endif   /* defined(HAVE_PRI) */
04528 
04529 #if defined(HAVE_SS7)
04530 static void dahdi_close_ss7_fd(struct dahdi_ss7 *ss7, int fd_num)
04531 {
04532    dahdi_close(ss7->ss7.fds[fd_num]);
04533    ss7->ss7.fds[fd_num] = -1;
04534 }
04535 #endif   /* defined(HAVE_SS7) */
04536 
04537 static int dahdi_setlinear(int dfd, int linear)
04538 {
04539    return ioctl(dfd, DAHDI_SETLINEAR, &linear);
04540 }
04541 
04542 
04543 static int alloc_sub(struct dahdi_pvt *p, int x)
04544 {
04545    struct dahdi_bufferinfo bi;
04546    int res;
04547    if (p->subs[x].dfd >= 0) {
04548       ast_log(LOG_WARNING, "%s subchannel of %d already in use\n", subnames[x], p->channel);
04549       return -1;
04550    }
04551 
04552    p->subs[x].dfd = dahdi_open("/dev/dahdi/pseudo");
04553    if (p->subs[x].dfd <= -1) {
04554       ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno));
04555       return -1;
04556    }
04557 
04558    res = ioctl(p->subs[x].dfd, DAHDI_GET_BUFINFO, &bi);
04559    if (!res) {
04560       bi.txbufpolicy = p->buf_policy;
04561       bi.rxbufpolicy = p->buf_policy;
04562       bi.numbufs = p->buf_no;
04563       res = ioctl(p->subs[x].dfd, DAHDI_SET_BUFINFO, &bi);
04564       if (res < 0) {
04565          ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", x, strerror(errno));
04566       }
04567    } else
04568       ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", x, strerror(errno));
04569 
04570    if (ioctl(p->subs[x].dfd, DAHDI_CHANNO, &p->subs[x].chan) == 1) {
04571       ast_log(LOG_WARNING, "Unable to get channel number for pseudo channel on FD %d: %s\n", p->subs[x].dfd, strerror(errno));
04572       dahdi_close_sub(p, x);
04573       p->subs[x].dfd = -1;
04574       return -1;
04575    }
04576    ast_debug(1, "Allocated %s subchannel on FD %d channel %d\n", subnames[x], p->subs[x].dfd, p->subs[x].chan);
04577    return 0;
04578 }
04579 
04580 static int unalloc_sub(struct dahdi_pvt *p, int x)
04581 {
04582    if (!x) {
04583       ast_log(LOG_WARNING, "Trying to unalloc the real channel %d?!?\n", p->channel);
04584       return -1;
04585    }
04586    ast_debug(1, "Released sub %d of channel %d\n", x, p->channel);
04587    dahdi_close_sub(p, x);
04588    p->subs[x].linear = 0;
04589    p->subs[x].chan = 0;
04590    p->subs[x].owner = NULL;
04591    p->subs[x].inthreeway = 0;
04592    p->polarity = POLARITY_IDLE;
04593    memset(&p->subs[x].curconf, 0, sizeof(p->subs[x].curconf));
04594    return 0;
04595 }
04596 
04597 static int digit_to_dtmfindex(char digit)
04598 {
04599    if (isdigit(digit))
04600       return DAHDI_TONE_DTMF_BASE + (digit - '0');
04601    else if (digit >= 'A' && digit <= 'D')
04602       return DAHDI_TONE_DTMF_A + (digit - 'A');
04603    else if (digit >= 'a' && digit <= 'd')
04604       return DAHDI_TONE_DTMF_A + (digit - 'a');
04605    else if (digit == '*')
04606       return DAHDI_TONE_DTMF_s;
04607    else if (digit == '#')
04608       return DAHDI_TONE_DTMF_p;
04609    else
04610       return -1;
04611 }
04612 
04613 static int dahdi_digit_begin(struct ast_channel *chan, char digit)
04614 {
04615    struct dahdi_pvt *pvt;
04616    int idx;
04617    int dtmf = -1;
04618    int res;
04619 
04620    pvt = ast_channel_tech_pvt(chan);
04621 
04622    ast_mutex_lock(&pvt->lock);
04623 
04624    idx = dahdi_get_index(chan, pvt, 0);
04625 
04626    if ((idx != SUB_REAL) || !pvt->owner)
04627       goto out;
04628 
04629 #ifdef HAVE_PRI
04630    switch (pvt->sig) {
04631    case SIG_PRI_LIB_HANDLE_CASES:
04632       res = sig_pri_digit_begin(pvt->sig_pvt, chan, digit);
04633       if (!res)
04634          goto out;
04635       break;
04636    default:
04637       break;
04638    }
04639 #endif
04640    if ((dtmf = digit_to_dtmfindex(digit)) == -1)
04641       goto out;
04642 
04643    if (pvt->pulse || ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &dtmf)) {
04644       struct dahdi_dialoperation zo = {
04645          .op = DAHDI_DIAL_OP_APPEND,
04646       };
04647 
04648       zo.dialstr[0] = 'T';
04649       zo.dialstr[1] = digit;
04650       zo.dialstr[2] = '\0';
04651       if ((res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo)))
04652          ast_log(LOG_WARNING, "Channel %s couldn't dial digit %c: %s\n",
04653             ast_channel_name(chan), digit, strerror(errno));
04654       else
04655          pvt->dialing = 1;
04656    } else {
04657       ast_debug(1, "Channel %s started VLDTMF digit '%c'\n",
04658          ast_channel_name(chan), digit);
04659       pvt->dialing = 1;
04660       pvt->begindigit = digit;
04661    }
04662 
04663 out:
04664    ast_mutex_unlock(&pvt->lock);
04665 
04666    return 0;
04667 }
04668 
04669 static int dahdi_digit_end(struct ast_channel *chan, char digit, unsigned int duration)
04670 {
04671    struct dahdi_pvt *pvt;
04672    int res = 0;
04673    int idx;
04674    int x;
04675 
04676    pvt = ast_channel_tech_pvt(chan);
04677 
04678    ast_mutex_lock(&pvt->lock);
04679 
04680    idx = dahdi_get_index(chan, pvt, 0);
04681 
04682    if ((idx != SUB_REAL) || !pvt->owner || pvt->pulse)
04683       goto out;
04684 
04685 #ifdef HAVE_PRI
04686    /* This means that the digit was already sent via PRI signalling */
04687    if (dahdi_sig_pri_lib_handles(pvt->sig) && !pvt->begindigit) {
04688       goto out;
04689    }
04690 #endif
04691 
04692    if (pvt->begindigit) {
04693       x = -1;
04694       ast_debug(1, "Channel %s ending VLDTMF digit '%c'\n",
04695          ast_channel_name(chan), digit);
04696       res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &x);
04697       pvt->dialing = 0;
04698       pvt->begindigit = 0;
04699    }
04700 
04701 out:
04702    ast_mutex_unlock(&pvt->lock);
04703 
04704    return res;
04705 }
04706 
04707 static const char * const events[] = {
04708    "No event",
04709    "On hook",
04710    "Ring/Answered",
04711    "Wink/Flash",
04712    "Alarm",
04713    "No more alarm",
04714    "HDLC Abort",
04715    "HDLC Overrun",
04716    "HDLC Bad FCS",
04717    "Dial Complete",
04718    "Ringer On",
04719    "Ringer Off",
04720    "Hook Transition Complete",
04721    "Bits Changed",
04722    "Pulse Start",
04723    "Timer Expired",
04724    "Timer Ping",
04725    "Polarity Reversal",
04726    "Ring Begin",
04727 };
04728 
04729 static struct {
04730    int alarm;
04731    char *name;
04732 } alarms[] = {
04733    { DAHDI_ALARM_RED, "Red Alarm" },
04734    { DAHDI_ALARM_YELLOW, "Yellow Alarm" },
04735    { DAHDI_ALARM_BLUE, "Blue Alarm" },
04736    { DAHDI_ALARM_RECOVER, "Recovering" },
04737    { DAHDI_ALARM_LOOPBACK, "Loopback" },
04738    { DAHDI_ALARM_NOTOPEN, "Not Open" },
04739    { DAHDI_ALARM_NONE, "None" },
04740 };
04741 
04742 static char *alarm2str(int alm)
04743 {
04744    int x;
04745    for (x = 0; x < ARRAY_LEN(alarms); x++) {
04746       if (alarms[x].alarm & alm)
04747          return alarms[x].name;
04748    }
04749    return alm ? "Unknown Alarm" : "No Alarm";
04750 }
04751 
04752 static const char *event2str(int event)
04753 {
04754    static char buf[256];
04755    if ((event < (ARRAY_LEN(events))) && (event > -1))
04756       return events[event];
04757    sprintf(buf, "Event %d", event); /* safe */
04758    return buf;
04759 }
04760 
04761 static char *dahdi_sig2str(int sig)
04762 {
04763    static char buf[256];
04764    switch (sig) {
04765    case SIG_EM:
04766       return "E & M Immediate";
04767    case SIG_EMWINK:
04768       return "E & M Wink";
04769    case SIG_EM_E1:
04770       return "E & M E1";
04771    case SIG_FEATD:
04772       return "Feature Group D (DTMF)";
04773    case SIG_FEATDMF:
04774       return "Feature Group D (MF)";
04775    case SIG_FEATDMF_TA:
04776       return "Feature Groud D (MF) Tandem Access";
04777    case SIG_FEATB:
04778       return "Feature Group B (MF)";
04779    case SIG_E911:
04780       return "E911 (MF)";
04781    case SIG_FGC_CAMA:
04782       return "FGC/CAMA (Dialpulse)";
04783    case SIG_FGC_CAMAMF:
04784       return "FGC/CAMA (MF)";
04785    case SIG_FXSLS:
04786       return "FXS Loopstart";
04787    case SIG_FXSGS:
04788       return "FXS Groundstart";
04789    case SIG_FXSKS:
04790       return "FXS Kewlstart";
04791    case SIG_FXOLS:
04792       return "FXO Loopstart";
04793    case SIG_FXOGS:
04794       return "FXO Groundstart";
04795    case SIG_FXOKS:
04796       return "FXO Kewlstart";
04797    case SIG_PRI:
04798       return "ISDN PRI";
04799    case SIG_BRI:
04800       return "ISDN BRI Point to Point";
04801    case SIG_BRI_PTMP:
04802       return "ISDN BRI Point to MultiPoint";
04803    case SIG_SS7:
04804       return "SS7";
04805    case SIG_MFCR2:
04806       return "MFC/R2";
04807    case SIG_SF:
04808       return "SF (Tone) Immediate";
04809    case SIG_SFWINK:
04810       return "SF (Tone) Wink";
04811    case SIG_SF_FEATD:
04812       return "SF (Tone) with Feature Group D (DTMF)";
04813    case SIG_SF_FEATDMF:
04814       return "SF (Tone) with Feature Group D (MF)";
04815    case SIG_SF_FEATB:
04816       return "SF (Tone) with Feature Group B (MF)";
04817    case 0:
04818       return "Pseudo";
04819    default:
04820       snprintf(buf, sizeof(buf), "Unknown signalling %d", sig);
04821       return buf;
04822    }
04823 }
04824 
04825 #define sig2str dahdi_sig2str
04826 
04827 static int conf_add(struct dahdi_pvt *p, struct dahdi_subchannel *c, int idx, int slavechannel)
04828 {
04829    /* If the conference already exists, and we're already in it
04830       don't bother doing anything */
04831    struct dahdi_confinfo zi;
04832 
04833    memset(&zi, 0, sizeof(zi));
04834    zi.chan = 0;
04835 
04836    if (slavechannel > 0) {
04837       /* If we have only one slave, do a digital mon */
04838       zi.confmode = DAHDI_CONF_DIGITALMON;
04839       zi.confno = slavechannel;
04840    } else {
04841       if (!idx) {
04842          /* Real-side and pseudo-side both participate in conference */
04843          zi.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER |
04844             DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER;
04845       } else
04846          zi.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER;
04847       zi.confno = p->confno;
04848    }
04849    if ((zi.confno == c->curconf.confno) && (zi.confmode == c->curconf.confmode))
04850       return 0;
04851    if (c->dfd < 0)
04852       return 0;
04853    if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
04854       ast_log(LOG_WARNING, "Failed to add %d to conference %d/%d: %s\n", c->dfd, zi.confmode, zi.confno, strerror(errno));
04855       return -1;
04856    }
04857    if (slavechannel < 1) {
04858       p->confno = zi.confno;
04859    }
04860    c->curconf = zi;
04861    ast_debug(1, "Added %d to conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
04862    return 0;
04863 }
04864 
04865 static int isourconf(struct dahdi_pvt *p, struct dahdi_subchannel *c)
04866 {
04867    /* If they're listening to our channel, they're ours */
04868    if ((p->channel == c->curconf.confno) && (c->curconf.confmode == DAHDI_CONF_DIGITALMON))
04869       return 1;
04870    /* If they're a talker on our (allocated) conference, they're ours */
04871    if ((p->confno > 0) && (p->confno == c->curconf.confno) && (c->curconf.confmode & DAHDI_CONF_TALKER))
04872       return 1;
04873    return 0;
04874 }
04875 
04876 static int conf_del(struct dahdi_pvt *p, struct dahdi_subchannel *c, int idx)
04877 {
04878    struct dahdi_confinfo zi;
04879    if (/* Can't delete if there's no dfd */
04880       (c->dfd < 0) ||
04881       /* Don't delete from the conference if it's not our conference */
04882       !isourconf(p, c)
04883       /* Don't delete if we don't think it's conferenced at all (implied) */
04884       ) return 0;
04885    memset(&zi, 0, sizeof(zi));
04886    if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
04887       ast_log(LOG_WARNING, "Failed to drop %d from conference %d/%d: %s\n", c->dfd, c->curconf.confmode, c->curconf.confno, strerror(errno));
04888       return -1;
04889    }
04890    ast_debug(1, "Removed %d from conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
04891    memcpy(&c->curconf, &zi, sizeof(c->curconf));
04892    return 0;
04893 }
04894 
04895 static int isslavenative(struct dahdi_pvt *p, struct dahdi_pvt **out)
04896 {
04897    int x;
04898    int useslavenative;
04899    struct dahdi_pvt *slave = NULL;
04900    /* Start out optimistic */
04901    useslavenative = 1;
04902    /* Update conference state in a stateless fashion */
04903    for (x = 0; x < 3; x++) {
04904       /* Any three-way calling makes slave native mode *definitely* out
04905          of the question */
04906       if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway)
04907          useslavenative = 0;
04908    }
04909    /* If we don't have any 3-way calls, check to see if we have
04910       precisely one slave */
04911    if (useslavenative) {
04912       for (x = 0; x < MAX_SLAVES; x++) {
04913          if (p->slaves[x]) {
04914             if (slave) {
04915                /* Whoops already have a slave!  No
04916                   slave native and stop right away */
04917                slave = NULL;
04918                useslavenative = 0;
04919                break;
04920             } else {
04921                /* We have one slave so far */
04922                slave = p->slaves[x];
04923             }
04924          }
04925       }
04926    }
04927    /* If no slave, slave native definitely out */
04928    if (!slave)
04929       useslavenative = 0;
04930    else if (slave->law != p->law) {
04931       useslavenative = 0;
04932       slave = NULL;
04933    }
04934    if (out)
04935       *out = slave;
04936    return useslavenative;
04937 }
04938 
04939 static int reset_conf(struct dahdi_pvt *p)
04940 {
04941    p->confno = -1;
04942    memset(&p->subs[SUB_REAL].curconf, 0, sizeof(p->subs[SUB_REAL].curconf));
04943    if (p->subs[SUB_REAL].dfd > -1) {
04944       struct dahdi_confinfo zi;
04945 
04946       memset(&zi, 0, sizeof(zi));
04947       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &zi))
04948          ast_log(LOG_WARNING, "Failed to reset conferencing on channel %d: %s\n", p->channel, strerror(errno));
04949    }
04950    return 0;
04951 }
04952 
04953 static int update_conf(struct dahdi_pvt *p)
04954 {
04955    int needconf = 0;
04956    int x;
04957    int useslavenative;
04958    struct dahdi_pvt *slave = NULL;
04959 
04960    useslavenative = isslavenative(p, &slave);
04961    /* Start with the obvious, general stuff */
04962    for (x = 0; x < 3; x++) {
04963       /* Look for three way calls */
04964       if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) {
04965          conf_add(p, &p->subs[x], x, 0);
04966          needconf++;
04967       } else {
04968          conf_del(p, &p->subs[x], x);
04969       }
04970    }
04971    /* If we have a slave, add him to our conference now. or DAX
04972       if this is slave native */
04973    for (x = 0; x < MAX_SLAVES; x++) {
04974       if (p->slaves[x]) {
04975          if (useslavenative)
04976             conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
04977          else {
04978             conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
04979             needconf++;
04980          }
04981       }
04982    }
04983    /* If we're supposed to be in there, do so now */
04984    if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
04985       if (useslavenative)
04986          conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
04987       else {
04988          conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
04989          needconf++;
04990       }
04991    }
04992    /* If we have a master, add ourselves to his conference */
04993    if (p->master) {
04994       if (isslavenative(p->master, NULL)) {
04995          conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
04996       } else {
04997          conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
04998       }
04999    }
05000    if (!needconf) {
05001       /* Nobody is left (or should be left) in our conference.
05002          Kill it. */
05003       p->confno = -1;
05004    }
05005    ast_debug(1, "Updated conferencing on %d, with %d conference users\n", p->channel, needconf);
05006    return 0;
05007 }
05008 
05009 static void dahdi_enable_ec(struct dahdi_pvt *p)
05010 {
05011    int res;
05012    if (!p)
05013       return;
05014    if (p->echocanon) {
05015       ast_debug(1, "Echo cancellation already on\n");
05016       return;
05017    }
05018    if (p->digital) {
05019       ast_debug(1, "Echo cancellation isn't required on digital connection\n");
05020       return;
05021    }
05022    if (p->echocancel.head.tap_length) {
05023 #if defined(HAVE_PRI) || defined(HAVE_SS7)
05024       switch (p->sig) {
05025 #if defined(HAVE_PRI)
05026       case SIG_PRI_LIB_HANDLE_CASES:
05027          if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
05028             /*
05029              * PRI nobch pseudo channel.  Does not need ec anyway.
05030              * Does not handle ioctl(DAHDI_AUDIOMODE)
05031              */
05032             return;
05033          }
05034          /* Fall through */
05035 #endif   /* defined(HAVE_PRI) */
05036 #if defined(HAVE_SS7)
05037       case SIG_SS7:
05038 #endif   /* defined(HAVE_SS7) */
05039          {
05040             int x = 1;
05041 
05042             res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x);
05043             if (res)
05044                ast_log(LOG_WARNING,
05045                   "Unable to enable audio mode on channel %d (%s)\n",
05046                   p->channel, strerror(errno));
05047          }
05048          break;
05049       default:
05050          break;
05051       }
05052 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
05053       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &p->echocancel);
05054       if (res) {
05055          ast_log(LOG_WARNING, "Unable to enable echo cancellation on channel %d (%s)\n", p->channel, strerror(errno));
05056       } else {
05057          p->echocanon = 1;
05058          ast_debug(1, "Enabled echo cancellation on channel %d\n", p->channel);
05059       }
05060    } else
05061       ast_debug(1, "No echo cancellation requested\n");
05062 }
05063 
05064 static void dahdi_train_ec(struct dahdi_pvt *p)
05065 {
05066    int x;
05067    int res;
05068 
05069    if (p && p->echocanon && p->echotraining) {
05070       x = p->echotraining;
05071       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOTRAIN, &x);
05072       if (res)
05073          ast_log(LOG_WARNING, "Unable to request echo training on channel %d: %s\n", p->channel, strerror(errno));
05074       else
05075          ast_debug(1, "Engaged echo training on channel %d\n", p->channel);
05076    } else {
05077       ast_debug(1, "No echo training requested\n");
05078    }
05079 }
05080 
05081 static void dahdi_disable_ec(struct dahdi_pvt *p)
05082 {
05083    int res;
05084 
05085    if (p->echocanon) {
05086       struct dahdi_echocanparams ecp = { .tap_length = 0 };
05087 
05088       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &ecp);
05089 
05090       if (res)
05091          ast_log(LOG_WARNING, "Unable to disable echo cancellation on channel %d: %s\n", p->channel, strerror(errno));
05092       else
05093          ast_debug(1, "Disabled echo cancellation on channel %d\n", p->channel);
05094    }
05095 
05096    p->echocanon = 0;
05097 }
05098 
05099 /* perform a dynamic range compression transform on the given sample */
05100 static int drc_sample(int sample, float drc)
05101 {
05102    float neg;
05103    float shallow, steep;
05104    float max = SHRT_MAX;
05105    
05106    neg = (sample < 0 ? -1 : 1);
05107    steep = drc*sample;
05108    shallow = neg*(max-max/drc)+(float)sample/drc;
05109    if (abs(steep) < abs(shallow)) {
05110       sample = steep;
05111    }
05112    else {
05113       sample = shallow;
05114    }
05115 
05116    return sample;
05117 }
05118 
05119 
05120 static void fill_txgain(struct dahdi_gains *g, float gain, float drc, int law)
05121 {
05122    int j;
05123    int k;
05124 
05125    float linear_gain = pow(10.0, gain / 20.0);
05126 
05127    switch (law) {
05128    case DAHDI_LAW_ALAW:
05129       for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
05130          if (gain || drc) {
05131             k = AST_ALAW(j);
05132             if (drc) {
05133                k = drc_sample(k, drc);
05134             }
05135             k = (float)k * linear_gain;
05136             if (k > 32767) {
05137                k = 32767;
05138             } else if (k < -32768) {
05139                k = -32768;
05140             }
05141             g->txgain[j] = AST_LIN2A(k);
05142          } else {
05143             g->txgain[j] = j;
05144          }
05145       }
05146       break;
05147    case DAHDI_LAW_MULAW:
05148       for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
05149          if (gain || drc) {
05150             k = AST_MULAW(j);
05151             if (drc) {
05152                k = drc_sample(k, drc);
05153             }
05154             k = (float)k * linear_gain;
05155             if (k > 32767) {
05156                k = 32767;
05157             } else if (k < -32768) {
05158                k = -32768;
05159             }
05160             g->txgain[j] = AST_LIN2MU(k);
05161 
05162          } else {
05163             g->txgain[j] = j;
05164          }
05165       }
05166       break;
05167    }
05168 }
05169 
05170 static void fill_rxgain(struct dahdi_gains *g, float gain, float drc, int law)
05171 {
05172    int j;
05173    int k;
05174    float linear_gain = pow(10.0, gain / 20.0);
05175 
05176    switch (law) {
05177    case DAHDI_LAW_ALAW:
05178       for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
05179          if (gain || drc) {
05180             k = AST_ALAW(j);
05181             if (drc) {
05182                k = drc_sample(k, drc);
05183             }
05184             k = (float)k * linear_gain;
05185             if (k > 32767) {
05186                k = 32767;
05187             } else if (k < -32768) {
05188                k = -32768;
05189             }
05190             g->rxgain[j] = AST_LIN2A(k);
05191          } else {
05192             g->rxgain[j] = j;
05193          }
05194       }
05195       break;
05196    case DAHDI_LAW_MULAW:
05197       for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
05198          if (gain || drc) {
05199             k = AST_MULAW(j);
05200             if (drc) {
05201                k = drc_sample(k, drc);
05202             }
05203             k = (float)k * linear_gain;
05204             if (k > 32767) {
05205                k = 32767;
05206             } else if (k < -32768) {
05207                k = -32768;
05208             }
05209             g->rxgain[j] = AST_LIN2MU(k);
05210          } else {
05211             g->rxgain[j] = j;
05212          }
05213       }
05214       break;
05215    }
05216 }
05217 
05218 static int set_actual_txgain(int fd, float gain, float drc, int law)
05219 {
05220    struct dahdi_gains g;
05221    int res;
05222 
05223    memset(&g, 0, sizeof(g));
05224    res = ioctl(fd, DAHDI_GETGAINS, &g);
05225    if (res) {
05226       ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
05227       return res;
05228    }
05229 
05230    fill_txgain(&g, gain, drc, law);
05231 
05232    return ioctl(fd, DAHDI_SETGAINS, &g);
05233 }
05234 
05235 static int set_actual_rxgain(int fd, float gain, float drc, int law)
05236 {
05237    struct dahdi_gains g;
05238    int res;
05239 
05240    memset(&g, 0, sizeof(g));
05241    res = ioctl(fd, DAHDI_GETGAINS, &g);
05242    if (res) {
05243       ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
05244       return res;
05245    }
05246 
05247    fill_rxgain(&g, gain, drc, law);
05248 
05249    return ioctl(fd, DAHDI_SETGAINS, &g);
05250 }
05251 
05252 static int set_actual_gain(int fd, float rxgain, float txgain, float rxdrc, float txdrc, int law)
05253 {
05254    return set_actual_txgain(fd, txgain, txdrc, law) | set_actual_rxgain(fd, rxgain, rxdrc, law);
05255 }
05256 
05257 static int bump_gains(struct dahdi_pvt *p)
05258 {
05259    int res;
05260 
05261    /* Bump receive gain by value stored in cid_rxgain */
05262    res = set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain + p->cid_rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
05263    if (res) {
05264       ast_log(LOG_WARNING, "Unable to bump gain: %s\n", strerror(errno));
05265       return -1;
05266    }
05267 
05268    return 0;
05269 }
05270 
05271 static int restore_gains(struct dahdi_pvt *p)
05272 {
05273    int res;
05274 
05275    res = set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
05276    if (res) {
05277       ast_log(LOG_WARNING, "Unable to restore gains: %s\n", strerror(errno));
05278       return -1;
05279    }
05280 
05281    return 0;
05282 }
05283 
05284 static inline int dahdi_set_hook(int fd, int hs)
05285 {
05286    int x, res;
05287 
05288    x = hs;
05289    res = ioctl(fd, DAHDI_HOOK, &x);
05290 
05291    if (res < 0) {
05292       if (errno == EINPROGRESS)
05293          return 0;
05294       ast_log(LOG_WARNING, "DAHDI hook failed returned %d (trying %d): %s\n", res, hs, strerror(errno));
05295       /* will expectedly fail if phone is off hook during operation, such as during a restart */
05296    }
05297 
05298    return res;
05299 }
05300 
05301 static inline int dahdi_confmute(struct dahdi_pvt *p, int muted)
05302 {
05303    int x, res;
05304 
05305    x = muted;
05306 #if defined(HAVE_PRI) || defined(HAVE_SS7)
05307    switch (p->sig) {
05308 #if defined(HAVE_PRI)
05309    case SIG_PRI_LIB_HANDLE_CASES:
05310       if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
05311          /* PRI nobch pseudo channel.  Does not handle ioctl(DAHDI_AUDIOMODE) */
05312          break;
05313       }
05314       /* Fall through */
05315 #endif   /* defined(HAVE_PRI) */
05316 #if defined(HAVE_SS7)
05317    case SIG_SS7:
05318 #endif   /* defined(HAVE_SS7) */
05319       {
05320          int y = 1;
05321 
05322          res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &y);
05323          if (res)
05324             ast_log(LOG_WARNING, "Unable to set audio mode on %d: %s\n",
05325                p->channel, strerror(errno));
05326       }
05327       break;
05328    default:
05329       break;
05330    }
05331 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
05332    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_CONFMUTE, &x);
05333    if (res < 0)
05334       ast_log(LOG_WARNING, "DAHDI confmute(%d) failed on channel %d: %s\n", muted, p->channel, strerror(errno));
05335    return res;
05336 }
05337 
05338 static int save_conference(struct dahdi_pvt *p)
05339 {
05340    struct dahdi_confinfo c;
05341    int res;
05342    if (p->saveconf.confmode) {
05343       ast_log(LOG_WARNING, "Can't save conference -- already in use\n");
05344       return -1;
05345    }
05346    p->saveconf.chan = 0;
05347    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &p->saveconf);
05348    if (res) {
05349       ast_log(LOG_WARNING, "Unable to get conference info: %s\n", strerror(errno));
05350       p->saveconf.confmode = 0;
05351       return -1;
05352    }
05353    memset(&c, 0, sizeof(c));
05354    c.confmode = DAHDI_CONF_NORMAL;
05355    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &c);
05356    if (res) {
05357       ast_log(LOG_WARNING, "Unable to set conference info: %s\n", strerror(errno));
05358       return -1;
05359    }
05360    ast_debug(1, "Disabled conferencing\n");
05361    return 0;
05362 }
05363 
05364 static int restore_conference(struct dahdi_pvt *p)
05365 {
05366    int res;
05367    if (p->saveconf.confmode) {
05368       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &p->saveconf);
05369       p->saveconf.confmode = 0;
05370       if (res) {
05371          ast_log(LOG_WARNING, "Unable to restore conference info: %s\n", strerror(errno));
05372          return -1;
05373       }
05374       ast_debug(1, "Restored conferencing\n");
05375    }
05376    return 0;
05377 }
05378 
05379 static int send_cwcidspill(struct dahdi_pvt *p)
05380 {
05381    struct ast_format tmpfmt;
05382 
05383    p->callwaitcas = 0;
05384    p->cidcwexpire = 0;
05385    p->cid_suppress_expire = 0;
05386    if (!(p->cidspill = ast_malloc(MAX_CALLERID_SIZE)))
05387       return -1;
05388    p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, p->callwait_name, p->callwait_num, ast_format_set(&tmpfmt, AST_LAW(p), 0));
05389    /* Make sure we account for the end */
05390    p->cidlen += READ_SIZE * 4;
05391    p->cidpos = 0;
05392    send_callerid(p);
05393    ast_verb(3, "CPE supports Call Waiting Caller*ID.  Sending '%s/%s'\n", p->callwait_name, p->callwait_num);
05394    return 0;
05395 }
05396 
05397 static int has_voicemail(struct dahdi_pvt *p)
05398 {
05399    int new_msgs;
05400    struct ast_event *event;
05401    char *mailbox, *context;
05402 
05403    mailbox = context = ast_strdupa(p->mailbox);
05404    strsep(&context, "@");
05405    if (ast_strlen_zero(context))
05406       context = "default";
05407 
05408    event = ast_event_get_cached(AST_EVENT_MWI,
05409       AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
05410       AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
05411       AST_EVENT_IE_END);
05412 
05413    if (event) {
05414       new_msgs = ast_event_get_ie_uint(event, AST_EVENT_IE_NEWMSGS);
05415       ast_event_destroy(event);
05416    } else
05417       new_msgs = ast_app_has_voicemail(p->mailbox, NULL);
05418 
05419    return new_msgs;
05420 }
05421 
05422 
05423 
05424 static int send_callerid(struct dahdi_pvt *p)
05425 {
05426    /* Assumes spill in p->cidspill, p->cidlen in length and we're p->cidpos into it */
05427    int res;
05428    /* Take out of linear mode if necessary */
05429    if (p->subs[SUB_REAL].linear) {
05430       p->subs[SUB_REAL].linear = 0;
05431       dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
05432    }
05433    while (p->cidpos < p->cidlen) {
05434       res = write(p->subs[SUB_REAL].dfd, p->cidspill + p->cidpos, p->cidlen - p->cidpos);
05435       ast_debug(4, "writing callerid at pos %d of %d, res = %d\n", p->cidpos, p->cidlen, res);
05436       if (res < 0) {
05437          if (errno == EAGAIN)
05438             return 0;
05439          else {
05440             ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
05441             return -1;
05442          }
05443       }
05444       if (!res)
05445          return 0;
05446       p->cidpos += res;
05447    }
05448    p->cid_suppress_expire = CALLWAITING_SUPPRESS_SAMPLES;
05449    ast_free(p->cidspill);
05450    p->cidspill = NULL;
05451    if (p->callwaitcas) {
05452       /* Wait for CID/CW to expire */
05453       p->cidcwexpire = CIDCW_EXPIRE_SAMPLES;
05454       p->cid_suppress_expire = p->cidcwexpire;
05455    } else
05456       restore_conference(p);
05457    return 0;
05458 }
05459 
05460 static int dahdi_callwait(struct ast_channel *ast)
05461 {
05462    struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
05463    struct ast_format tmpfmt;
05464    p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
05465    if (p->cidspill) {
05466       ast_log(LOG_WARNING, "Spill already exists?!?\n");
05467       ast_free(p->cidspill);
05468    }
05469 
05470    /*
05471     * SAS: Subscriber Alert Signal, 440Hz for 300ms
05472     * CAS: CPE Alert Signal, 2130Hz * 2750Hz sine waves
05473     */
05474    if (!(p->cidspill = ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE * 4)))
05475       return -1;
05476    save_conference(p);
05477    /* Silence */
05478    memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
05479    if (!p->callwaitrings && p->callwaitingcallerid) {
05480       ast_gen_cas(p->cidspill, 1, 2400 + 680, ast_format_set(&tmpfmt, AST_LAW(p), 0));
05481       p->callwaitcas = 1;
05482       p->cidlen = 2400 + 680 + READ_SIZE * 4;
05483    } else {
05484       ast_gen_cas(p->cidspill, 1, 2400, ast_format_set(&tmpfmt, AST_LAW(p), 0));
05485       p->callwaitcas = 0;
05486       p->cidlen = 2400 + READ_SIZE * 4;
05487    }
05488    p->cidpos = 0;
05489    send_callerid(p);
05490 
05491    return 0;
05492 }
05493 
05494 static int dahdi_call(struct ast_channel *ast, const char *rdest, int timeout)
05495 {
05496    struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
05497    int x, res, mysig;
05498    char *dest;
05499    AST_DECLARE_APP_ARGS(args,
05500       AST_APP_ARG(group);  /* channel/group token */
05501       AST_APP_ARG(ext); /* extension token */
05502       //AST_APP_ARG(opts); /* options token */
05503       AST_APP_ARG(other);  /* Any remining unused arguments */
05504    );
05505 
05506    ast_mutex_lock(&p->lock);
05507    ast_copy_string(p->dialdest, rdest, sizeof(p->dialdest));
05508 
05509    /* Split the dialstring */
05510    dest = ast_strdupa(rdest);
05511    AST_NONSTANDARD_APP_ARGS(args, dest, '/');
05512    if (!args.ext) {
05513       args.ext = "";
05514    }
05515 
05516 #if defined(HAVE_PRI)
05517    if (dahdi_sig_pri_lib_handles(p->sig)) {
05518       char *subaddr;
05519 
05520       sig_pri_extract_called_num_subaddr(p->sig_pvt, rdest, p->exten, sizeof(p->exten));
05521 
05522       /* Remove any subaddress for uniformity with incoming calls. */
05523       subaddr = strchr(p->exten, ':');
05524       if (subaddr) {
05525          *subaddr = '\0';
05526       }
05527    } else
05528 #endif   /* defined(HAVE_PRI) */
05529    {
05530       ast_copy_string(p->exten, args.ext, sizeof(p->exten));
05531    }
05532 
05533    if ((ast_channel_state(ast) == AST_STATE_BUSY)) {
05534       p->subs[SUB_REAL].needbusy = 1;
05535       ast_mutex_unlock(&p->lock);
05536       return 0;
05537    }
05538    if ((ast_channel_state(ast) != AST_STATE_DOWN) && (ast_channel_state(ast) != AST_STATE_RESERVED)) {
05539       ast_log(LOG_WARNING, "dahdi_call called on %s, neither down nor reserved\n", ast_channel_name(ast));
05540       ast_mutex_unlock(&p->lock);
05541       return -1;
05542    }
05543    p->waitingfordt.tv_sec = 0;
05544    p->dialednone = 0;
05545    if ((p->radio || (p->oprmode < 0)))  /* if a radio channel, up immediately */
05546    {
05547       /* Special pseudo -- automatically up */
05548       ast_setstate(ast, AST_STATE_UP);
05549       ast_mutex_unlock(&p->lock);
05550       return 0;
05551    }
05552    x = DAHDI_FLUSH_READ | DAHDI_FLUSH_WRITE;
05553    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
05554    if (res)
05555       ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", p->channel, strerror(errno));
05556    p->outgoing = 1;
05557 
05558    if (IS_DIGITAL(ast_channel_transfercapability(ast))){
05559       set_actual_gain(p->subs[SUB_REAL].dfd, 0, 0, p->rxdrc, p->txdrc, p->law);
05560    } else {
05561       set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
05562    }  
05563 
05564 #ifdef HAVE_PRI
05565    if (dahdi_sig_pri_lib_handles(p->sig)) {
05566       res = sig_pri_call(p->sig_pvt, ast, rdest, timeout,
05567          (p->law == DAHDI_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW);
05568       ast_mutex_unlock(&p->lock);
05569       return res;
05570    }
05571 #endif
05572 
05573 #if defined(HAVE_SS7)
05574    if (p->sig == SIG_SS7) {
05575       res = sig_ss7_call(p->sig_pvt, ast, rdest);
05576       ast_mutex_unlock(&p->lock);
05577       return res;
05578    }
05579 #endif   /* defined(HAVE_SS7) */
05580 
05581    /* If this is analog signalling we can exit here */
05582    if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
05583       p->callwaitrings = 0;
05584       res = analog_call(p->sig_pvt, ast, rdest, timeout);
05585       ast_mutex_unlock(&p->lock);
05586       return res;
05587    }
05588 
05589    mysig = p->outsigmod > -1 ? p->outsigmod : p->sig;
05590    switch (mysig) {
05591    case 0:
05592       /* Special pseudo -- automatically up*/
05593       ast_setstate(ast, AST_STATE_UP);
05594       break;
05595    case SIG_MFCR2:
05596       break;
05597    default:
05598       ast_debug(1, "not yet implemented\n");
05599       ast_mutex_unlock(&p->lock);
05600       return -1;
05601    }
05602 
05603 #ifdef HAVE_OPENR2
05604    if (p->mfcr2) {
05605       openr2_calling_party_category_t chancat;
05606       int callres = 0;
05607       char *c, *l;
05608 
05609       /* We'll get it in a moment -- but use dialdest to store pre-setup_ack digits */
05610       p->dialdest[0] = '\0';
05611 
05612       c = args.ext;
05613       if (!p->hidecallerid) {
05614          l = ast_channel_connected(ast)->id.number.valid ? ast_channel_connected(ast)->id.number.str : NULL;
05615       } else {
05616          l = NULL;
05617       }
05618       if (strlen(c) < p->stripmsd) {
05619          ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
05620          ast_mutex_unlock(&p->lock);
05621          return -1;
05622       }
05623       p->dialing = 1;
05624       chancat = dahdi_r2_get_channel_category(ast);
05625       callres = openr2_chan_make_call(p->r2chan, l, (c + p->stripmsd), chancat);
05626       if (-1 == callres) {
05627          ast_mutex_unlock(&p->lock);
05628          ast_log(LOG_ERROR, "unable to make new MFC/R2 call!\n");
05629          return -1;
05630       }
05631       p->mfcr2_call_accepted = 0;
05632       p->mfcr2_progress_sent = 0;
05633       ast_setstate(ast, AST_STATE_DIALING);
05634    }
05635 #endif /* HAVE_OPENR2 */
05636    ast_mutex_unlock(&p->lock);
05637    return 0;
05638 }
05639 
05640 /*!
05641  * \internal
05642  * \brief Insert the given chan_dahdi interface structure into the interface list.
05643  * \since 1.8
05644  *
05645  * \param pvt chan_dahdi private interface structure to insert.
05646  *
05647  * \details
05648  * The interface list is a doubly linked list sorted by the chan_dahdi channel number.
05649  * Any duplicates are inserted after the existing entries.
05650  *
05651  * \note The new interface must not already be in the list.
05652  *
05653  * \return Nothing
05654  */
05655 static void dahdi_iflist_insert(struct dahdi_pvt *pvt)
05656 {
05657    struct dahdi_pvt *cur;
05658 
05659    pvt->which_iflist = DAHDI_IFLIST_MAIN;
05660 
05661    /* Find place in middle of list for the new interface. */
05662    for (cur = iflist; cur; cur = cur->next) {
05663       if (pvt->channel < cur->channel) {
05664          /* New interface goes before the current interface. */
05665          pvt->prev = cur->prev;
05666          pvt->next = cur;
05667          if (cur->prev) {
05668             /* Insert into the middle of the list. */
05669             cur->prev->next = pvt;
05670          } else {
05671             /* Insert at head of list. */
05672             iflist = pvt;
05673          }
05674          cur->prev = pvt;
05675          return;
05676       }
05677    }
05678 
05679    /* New interface goes onto the end of the list */
05680    pvt->prev = ifend;
05681    pvt->next = NULL;
05682    if (ifend) {
05683       ifend->next = pvt;
05684    }
05685    ifend = pvt;
05686    if (!iflist) {
05687       /* List was empty */
05688       iflist = pvt;
05689    }
05690 }
05691 
05692 /*!
05693  * \internal
05694  * \brief Extract the given chan_dahdi interface structure from the interface list.
05695  * \since 1.8
05696  *
05697  * \param pvt chan_dahdi private interface structure to extract.
05698  *
05699  * \note
05700  * The given interface structure can be either in the interface list or a stand alone
05701  * structure that has not been put in the list if the next and prev pointers are NULL.
05702  *
05703  * \return Nothing
05704  */
05705 static void dahdi_iflist_extract(struct dahdi_pvt *pvt)
05706 {
05707    /* Extract from the forward chain. */
05708    if (pvt->prev) {
05709       pvt->prev->next = pvt->next;
05710    } else if (iflist == pvt) {
05711       /* Node is at the head of the list. */
05712       iflist = pvt->next;
05713    }
05714 
05715    /* Extract from the reverse chain. */
05716    if (pvt->next) {
05717       pvt->next->prev = pvt->prev;
05718    } else if (ifend == pvt) {
05719       /* Node is at the end of the list. */
05720       ifend = pvt->prev;
05721    }
05722 
05723    /* Node is no longer in the list. */
05724    pvt->which_iflist = DAHDI_IFLIST_NONE;
05725    pvt->prev = NULL;
05726    pvt->next = NULL;
05727 }
05728 
05729 #if defined(HAVE_PRI)
05730 /*!
05731  * \internal
05732  * \brief Insert the given chan_dahdi interface structure into the no B channel list.
05733  * \since 1.8
05734  *
05735  * \param pri sig_pri span control structure holding no B channel list.
05736  * \param pvt chan_dahdi private interface structure to insert.
05737  *
05738  * \details
05739  * The interface list is a doubly linked list sorted by the chan_dahdi channel number.
05740  * Any duplicates are inserted after the existing entries.
05741  *
05742  * \note The new interface must not already be in the list.
05743  *
05744  * \return Nothing
05745  */
05746 static void dahdi_nobch_insert(struct sig_pri_span *pri, struct dahdi_pvt *pvt)
05747 {
05748    struct dahdi_pvt *cur;
05749 
05750    pvt->which_iflist = DAHDI_IFLIST_NO_B_CHAN;
05751 
05752    /* Find place in middle of list for the new interface. */
05753    for (cur = pri->no_b_chan_iflist; cur; cur = cur->next) {
05754       if (pvt->channel < cur->channel) {
05755          /* New interface goes before the current interface. */
05756          pvt->prev = cur->prev;
05757          pvt->next = cur;
05758          if (cur->prev) {
05759             /* Insert into the middle of the list. */
05760             cur->prev->next = pvt;
05761          } else {
05762             /* Insert at head of list. */
05763             pri->no_b_chan_iflist = pvt;
05764          }
05765          cur->prev = pvt;
05766          return;
05767       }
05768    }
05769 
05770    /* New interface goes onto the end of the list */
05771    pvt->prev = pri->no_b_chan_end;
05772    pvt->next = NULL;
05773    if (pri->no_b_chan_end) {
05774       ((struct dahdi_pvt *) pri->no_b_chan_end)->next = pvt;
05775    }
05776    pri->no_b_chan_end = pvt;
05777    if (!pri->no_b_chan_iflist) {
05778       /* List was empty */
05779       pri->no_b_chan_iflist = pvt;
05780    }
05781 }
05782 #endif   /* defined(HAVE_PRI) */
05783 
05784 #if defined(HAVE_PRI)
05785 /*!
05786  * \internal
05787  * \brief Extract the given chan_dahdi interface structure from the no B channel list.
05788  * \since 1.8
05789  *
05790  * \param pri sig_pri span control structure holding no B channel list.
05791  * \param pvt chan_dahdi private interface structure to extract.
05792  *
05793  * \note
05794  * The given interface structure can be either in the interface list or a stand alone
05795  * structure that has not been put in the list if the next and prev pointers are NULL.
05796  *
05797  * \return Nothing
05798  */
05799 static void dahdi_nobch_extract(struct sig_pri_span *pri, struct dahdi_pvt *pvt)
05800 {
05801    /* Extract from the forward chain. */
05802    if (pvt->prev) {
05803       pvt->prev->next = pvt->next;
05804    } else if (pri->no_b_chan_iflist == pvt) {
05805       /* Node is at the head of the list. */
05806       pri->no_b_chan_iflist = pvt->next;
05807    }
05808 
05809    /* Extract from the reverse chain. */
05810    if (pvt->next) {
05811       pvt->next->prev = pvt->prev;
05812    } else if (pri->no_b_chan_end == pvt) {
05813       /* Node is at the end of the list. */
05814       pri->no_b_chan_end = pvt->prev;
05815    }
05816 
05817    /* Node is no longer in the list. */
05818    pvt->which_iflist = DAHDI_IFLIST_NONE;
05819    pvt->prev = NULL;
05820    pvt->next = NULL;
05821 }
05822 #endif   /* defined(HAVE_PRI) */
05823 
05824 #if defined(HAVE_PRI)
05825 /*!
05826  * \internal
05827  * \brief Unlink the channel interface from the PRI private pointer array.
05828  * \since 1.8
05829  *
05830  * \param pvt chan_dahdi private interface structure to unlink.
05831  *
05832  * \return Nothing
05833  */
05834 static void dahdi_unlink_pri_pvt(struct dahdi_pvt *pvt)
05835 {
05836    unsigned idx;
05837    struct sig_pri_span *pri;
05838 
05839    pri = pvt->pri;
05840    if (!pri) {
05841       /* Not PRI signaling so cannot be in a PRI private pointer array. */
05842       return;
05843    }
05844    ast_mutex_lock(&pri->lock);
05845    for (idx = 0; idx < pri->numchans; ++idx) {
05846       if (pri->pvts[idx] == pvt->sig_pvt) {
05847          pri->pvts[idx] = NULL;
05848          ast_mutex_unlock(&pri->lock);
05849          return;
05850       }
05851    }
05852    ast_mutex_unlock(&pri->lock);
05853 }
05854 #endif   /* defined(HAVE_PRI) */
05855 
05856 #if defined(HAVE_SS7)
05857 /*!
05858  * \internal
05859  * \brief Unlink the channel interface from the SS7 private pointer array.
05860  * \since 1.8
05861  *
05862  * \param pvt chan_dahdi private interface structure to unlink.
05863  *
05864  * \return Nothing
05865  */
05866 static void dahdi_unlink_ss7_pvt(struct dahdi_pvt *pvt)
05867 {
05868    unsigned idx;
05869    struct sig_ss7_linkset *ss7;
05870 
05871    ss7 = pvt->ss7;
05872    if (!ss7) {
05873       /* Not SS7 signaling so cannot be in a SS7 private pointer array. */
05874       return;
05875    }
05876    ast_mutex_lock(&ss7->lock);
05877    for (idx = 0; idx < ss7->numchans; ++idx) {
05878       if (ss7->pvts[idx] == pvt->sig_pvt) {
05879          ss7->pvts[idx] = NULL;
05880          ast_mutex_unlock(&ss7->lock);
05881          return;
05882       }
05883    }
05884    ast_mutex_unlock(&ss7->lock);
05885 }
05886 #endif   /* defined(HAVE_SS7) */
05887 
05888 static struct dahdi_pvt *find_next_iface_in_span(struct dahdi_pvt *cur)
05889 {
05890    if (cur->next && cur->next->span == cur->span) {
05891       return cur->next;
05892    } else if (cur->prev && cur->prev->span == cur->span) {
05893       return cur->prev;
05894    }
05895 
05896    return NULL;
05897 }
05898 
05899 static void destroy_dahdi_pvt(struct dahdi_pvt *pvt)
05900 {
05901    struct dahdi_pvt *p = pvt;
05902 
05903    if (p->manages_span_alarms) {
05904       struct dahdi_pvt *next = find_next_iface_in_span(p);
05905       if (next) {
05906          next->manages_span_alarms = 1;
05907       }
05908    }
05909 
05910    /* Remove channel from the list */
05911 #if defined(HAVE_PRI)
05912    dahdi_unlink_pri_pvt(p);
05913 #endif   /* defined(HAVE_PRI) */
05914 #if defined(HAVE_SS7)
05915    dahdi_unlink_ss7_pvt(p);
05916 #endif   /* defined(HAVE_SS7) */
05917    switch (pvt->which_iflist) {
05918    case DAHDI_IFLIST_NONE:
05919       break;
05920    case DAHDI_IFLIST_MAIN:
05921       dahdi_iflist_extract(p);
05922       break;
05923 #if defined(HAVE_PRI)
05924    case DAHDI_IFLIST_NO_B_CHAN:
05925       if (p->pri) {
05926          dahdi_nobch_extract(p->pri, p);
05927       }
05928       break;
05929 #endif   /* defined(HAVE_PRI) */
05930    }
05931 
05932    if (p->sig_pvt) {
05933       if (analog_lib_handles(p->sig, 0, 0)) {
05934          analog_delete(p->sig_pvt);
05935       }
05936       switch (p->sig) {
05937 #if defined(HAVE_PRI)
05938       case SIG_PRI_LIB_HANDLE_CASES:
05939          sig_pri_chan_delete(p->sig_pvt);
05940          break;
05941 #endif   /* defined(HAVE_PRI) */
05942 #if defined(HAVE_SS7)
05943       case SIG_SS7:
05944          sig_ss7_chan_delete(p->sig_pvt);
05945          break;
05946 #endif   /* defined(HAVE_SS7) */
05947       default:
05948          break;
05949       }
05950    }
05951    ast_free(p->cidspill);
05952    if (p->use_smdi)
05953       ast_smdi_interface_unref(p->smdi_iface);
05954    if (p->mwi_event_sub)
05955       ast_event_unsubscribe(p->mwi_event_sub);
05956    if (p->vars) {
05957       ast_variables_destroy(p->vars);
05958    }
05959    if (p->cc_params) {
05960       ast_cc_config_params_destroy(p->cc_params);
05961    }
05962 
05963    p->named_callgroups = ast_unref_namedgroups(p->named_callgroups);
05964    p->named_pickupgroups = ast_unref_namedgroups(p->named_pickupgroups);
05965 
05966    ast_mutex_destroy(&p->lock);
05967    dahdi_close_sub(p, SUB_REAL);
05968    if (p->owner)
05969       ast_channel_tech_pvt_set(p->owner, NULL);
05970    ast_free(p);
05971 }
05972 
05973 static void destroy_channel(struct dahdi_pvt *cur, int now)
05974 {
05975    int i;
05976 
05977    if (!now) {
05978       /* Do not destroy the channel now if it is owned by someone. */
05979       if (cur->owner) {
05980          return;
05981       }
05982       for (i = 0; i < 3; i++) {
05983          if (cur->subs[i].owner) {
05984             return;
05985          }
05986       }
05987    }
05988    destroy_dahdi_pvt(cur);
05989 }
05990 
05991 static void destroy_all_channels(void)
05992 {
05993    int chan;
05994 #if defined(HAVE_PRI)
05995    unsigned span;
05996    struct sig_pri_span *pri;
05997 #endif   /* defined(HAVE_PRI) */
05998    struct dahdi_pvt *p;
05999 
06000    while (num_restart_pending) {
06001       usleep(1);
06002    }
06003 
06004    ast_mutex_lock(&iflock);
06005    /* Destroy all the interfaces and free their memory */
06006    while (iflist) {
06007       p = iflist;
06008 
06009       chan = p->channel;
06010 #if defined(HAVE_PRI_SERVICE_MESSAGES)
06011       {
06012          char db_chan_name[20];
06013          char db_answer[5];
06014          char state;
06015          int why = -1;
06016 
06017          snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, p->span, chan);
06018          if (!ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) {
06019             sscanf(db_answer, "%1c:%30d", &state, &why);
06020          }
06021          if (!why) {
06022             /* SRVST persistence is not required */
06023             ast_db_del(db_chan_name, SRVST_DBKEY);
06024          }
06025       }
06026 #endif   /* defined(HAVE_PRI_SERVICE_MESSAGES) */
06027       /* Free associated memory */
06028       destroy_dahdi_pvt(p);
06029       ast_verb(3, "Unregistered channel %d\n", chan);
06030    }
06031    ifcount = 0;
06032    ast_mutex_unlock(&iflock);
06033 
06034 #if defined(HAVE_PRI)
06035    /* Destroy all of the no B channel interface lists */
06036    for (span = 0; span < NUM_SPANS; ++span) {
06037       if (!pris[span].dchannels[0]) {
06038          break;
06039       }
06040       pri = &pris[span].pri;
06041       ast_mutex_lock(&pri->lock);
06042       while (pri->no_b_chan_iflist) {
06043          p = pri->no_b_chan_iflist;
06044 
06045          /* Free associated memory */
06046          destroy_dahdi_pvt(p);
06047       }
06048       ast_mutex_unlock(&pri->lock);
06049    }
06050 #endif   /* defined(HAVE_PRI) */
06051 }
06052 
06053 #if defined(HAVE_PRI)
06054 static char *dahdi_send_keypad_facility_app = "DAHDISendKeypadFacility";
06055 
06056 static int dahdi_send_keypad_facility_exec(struct ast_channel *chan, const char *digits)
06057 {
06058    /* Data will be our digit string */
06059    struct dahdi_pvt *p;
06060 
06061    if (ast_strlen_zero(digits)) {
06062       ast_debug(1, "No digit string sent to application!\n");
06063       return -1;
06064    }
06065 
06066    p = (struct dahdi_pvt *)ast_channel_tech_pvt(chan);
06067 
06068    if (!p) {
06069       ast_debug(1, "Unable to find technology private\n");
06070       return -1;
06071    }
06072 
06073    pri_send_keypad_facility_exec(p->sig_pvt, digits);
06074 
06075    return 0;
06076 }
06077 #endif   /* defined(HAVE_PRI) */
06078 
06079 #if defined(HAVE_PRI)
06080 #if defined(HAVE_PRI_PROG_W_CAUSE)
06081 static char *dahdi_send_callrerouting_facility_app = "DAHDISendCallreroutingFacility";
06082 
06083 static int dahdi_send_callrerouting_facility_exec(struct ast_channel *chan, const char *data)
06084 {
06085    /* Data will be our digit string */
06086    struct dahdi_pvt *pvt;
06087    char *parse;
06088    int res;
06089    AST_DECLARE_APP_ARGS(args,
06090       AST_APP_ARG(destination);
06091       AST_APP_ARG(original);
06092       AST_APP_ARG(reason);
06093    );
06094 
06095    if (ast_strlen_zero(data)) {
06096       ast_debug(1, "No data sent to application!\n");
06097       return -1;
06098    }
06099    if (ast_channel_tech(chan) != &dahdi_tech) {
06100       ast_debug(1, "Only DAHDI technology accepted!\n");
06101       return -1;
06102    }
06103    pvt = (struct dahdi_pvt *) ast_channel_tech_pvt(chan);
06104    if (!pvt) {
06105       ast_debug(1, "Unable to find technology private\n");
06106       return -1;
06107    }
06108    switch (pvt->sig) {
06109    case SIG_PRI_LIB_HANDLE_CASES:
06110       break;
06111    default:
06112       ast_debug(1, "callrerouting attempted on non-ISDN channel %s\n",
06113          ast_channel_name(chan));
06114       return -1;
06115    }
06116 
06117    parse = ast_strdupa(data);
06118    AST_STANDARD_APP_ARGS(args, parse);
06119 
06120    if (ast_strlen_zero(args.destination)) {
06121       ast_log(LOG_WARNING, "callrerouting facility requires at least destination number argument\n");
06122       return -1;
06123    }
06124 
06125    if (ast_strlen_zero(args.original)) {
06126       ast_log(LOG_WARNING, "Callrerouting Facility without original called number argument\n");
06127       args.original = NULL;
06128    }
06129 
06130    if (ast_strlen_zero(args.reason)) {
06131       ast_log(LOG_NOTICE, "Callrerouting Facility without diversion reason argument, defaulting to unknown\n");
06132       args.reason = NULL;
06133    }
06134 
06135    res = pri_send_callrerouting_facility_exec(pvt->sig_pvt, ast_channel_state(chan),
06136       args.destination, args.original, args.reason);
06137    if (!res) {
06138       /*
06139        * Wait up to 5 seconds for a reply before hanging up this call
06140        * leg if the peer does not disconnect first.
06141        */
06142       ast_safe_sleep(chan, 5000);
06143    }
06144 
06145    return -1;
06146 }
06147 #endif   /* defined(HAVE_PRI_PROG_W_CAUSE) */
06148 #endif   /* defined(HAVE_PRI) */
06149 
06150 #if defined(HAVE_OPENR2)
06151 static const char * const dahdi_accept_r2_call_app = "DAHDIAcceptR2Call";
06152 
06153 static int dahdi_accept_r2_call_exec(struct ast_channel *chan, const char *data)
06154 {
06155    /* data is whether to accept with charge or no charge */
06156    openr2_call_mode_t accept_mode;
06157    int res, timeout, maxloops;
06158    struct ast_frame *f;
06159    struct dahdi_pvt *p;
06160    char *parse;
06161    AST_DECLARE_APP_ARGS(args,
06162          AST_APP_ARG(charge);
06163    );
06164 
06165    if (ast_strlen_zero(data)) {
06166       ast_debug(1, "No data sent to application!\n");
06167       return -1;
06168    }
06169 
06170    if (ast_channel_tech(chan) != &dahdi_tech) {
06171       ast_debug(1, "Only DAHDI technology accepted!\n");
06172       return -1;
06173    }
06174 
06175    p = (struct dahdi_pvt *)ast_channel_tech_pvt(chan);
06176    if (!p) {
06177       ast_debug(1, "Unable to find technology private!\n");
06178       return -1;
06179    }
06180 
06181    parse = ast_strdupa(data);
06182    AST_STANDARD_APP_ARGS(args, parse);
06183 
06184    if (ast_strlen_zero(args.charge)) {
06185       ast_log(LOG_WARNING, "DAHDIAcceptR2Call requires 'yes' or 'no' for the charge parameter\n");
06186       return -1;
06187    }
06188 
06189    ast_mutex_lock(&p->lock);
06190    if (!p->mfcr2 || !p->mfcr2call) {
06191       ast_mutex_unlock(&p->lock);
06192       ast_debug(1, "Channel %s does not seems to be an R2 active channel!\n", ast_channel_name(chan));
06193       return -1;
06194    }
06195 
06196    if (p->mfcr2_call_accepted) {
06197       ast_mutex_unlock(&p->lock);
06198       ast_debug(1, "MFC/R2 call already accepted on channel %s!\n", ast_channel_name(chan));
06199       return 0;
06200    }
06201    accept_mode = ast_true(args.charge) ? OR2_CALL_WITH_CHARGE : OR2_CALL_NO_CHARGE;
06202    if (openr2_chan_accept_call(p->r2chan, accept_mode)) {
06203       ast_mutex_unlock(&p->lock);
06204       ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n");
06205       return -1;
06206    }
06207    ast_mutex_unlock(&p->lock);
06208 
06209    res = 0;
06210    timeout = 100;
06211    maxloops = 50; /* wait up to 5 seconds */
06212    /* we need to read() until the call is accepted */
06213    while (maxloops > 0) {
06214       maxloops--;
06215       if (ast_check_hangup(chan)) {
06216          break;
06217       }
06218       res = ast_waitfor(chan, timeout);
06219       if (res < 0) {
06220          ast_debug(1, "ast_waitfor failed on channel %s, going out ...\n", ast_channel_name(chan));
06221          res = -1;
06222          break;
06223       }
06224       if (res == 0) {
06225          continue;
06226       }
06227       res = 0;
06228       f = ast_read(chan);
06229       if (!f) {
06230          ast_debug(1, "No frame read on channel %s, going out ...\n", ast_channel_name(chan));
06231          res = -1;
06232          break;
06233       }
06234       if (f->frametype == AST_FRAME_CONTROL && f->subclass.integer == AST_CONTROL_HANGUP) {
06235          ast_debug(1, "Got HANGUP frame on channel %s, going out ...\n", ast_channel_name(chan));
06236          ast_frfree(f);
06237          res = -1;
06238          break;
06239       }
06240       ast_frfree(f);
06241       ast_mutex_lock(&p->lock);
06242       if (p->mfcr2_call_accepted) {
06243          ast_mutex_unlock(&p->lock);
06244          ast_debug(1, "Accepted MFC/R2 call!\n");
06245          break;
06246       }
06247       ast_mutex_unlock(&p->lock);
06248    }
06249    if (res == -1) {
06250       ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n");
06251    }
06252    return res;
06253 }
06254 
06255 static openr2_call_disconnect_cause_t dahdi_ast_cause_to_r2_cause(int cause)
06256 {
06257    openr2_call_disconnect_cause_t r2cause = OR2_CAUSE_NORMAL_CLEARING;
06258    switch (cause) {
06259    case AST_CAUSE_USER_BUSY:
06260    case AST_CAUSE_CALL_REJECTED:
06261    case AST_CAUSE_INTERWORKING: /* I don't know wtf is this but is used sometimes when ekiga rejects a call */
06262       r2cause = OR2_CAUSE_BUSY_NUMBER;
06263       break;
06264 
06265    case AST_CAUSE_NORMAL_CIRCUIT_CONGESTION:
06266    case AST_CAUSE_SWITCH_CONGESTION:
06267       r2cause = OR2_CAUSE_NETWORK_CONGESTION;
06268       break;
06269 
06270    case AST_CAUSE_UNALLOCATED:
06271       r2cause = OR2_CAUSE_UNALLOCATED_NUMBER;
06272       break;
06273 
06274    case AST_CAUSE_NETWORK_OUT_OF_ORDER:
06275    case AST_CAUSE_DESTINATION_OUT_OF_ORDER:
06276       r2cause = OR2_CAUSE_OUT_OF_ORDER;
06277       break;
06278 
06279    case AST_CAUSE_NO_ANSWER:
06280    case AST_CAUSE_NO_USER_RESPONSE:
06281       r2cause = OR2_CAUSE_NO_ANSWER;
06282       break;
06283 
06284    default:
06285       r2cause = OR2_CAUSE_NORMAL_CLEARING;
06286       break;
06287    }
06288    ast_debug(1, "ast cause %d resulted in openr2 cause %d/%s\n",
06289          cause, r2cause, openr2_proto_get_disconnect_string(r2cause));
06290    return r2cause;
06291 }
06292 #endif
06293 
06294 static int revert_fax_buffers(struct dahdi_pvt *p, struct ast_channel *ast)
06295 {
06296    if (p->bufferoverrideinuse) {
06297       /* faxbuffers are in use, revert them */
06298       struct dahdi_bufferinfo bi = {
06299          .txbufpolicy = p->buf_policy,
06300          .rxbufpolicy = p->buf_policy,
06301          .bufsize = p->bufsize,
06302          .numbufs = p->buf_no
06303       };
06304       int bpres;
06305 
06306       if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
06307          ast_log(LOG_WARNING, "Channel '%s' unable to revert buffer policy: %s\n", ast_channel_name(ast), strerror(errno));
06308       }
06309       p->bufferoverrideinuse = 0;
06310       return bpres;
06311    }
06312 
06313    return -1;
06314 }
06315 
06316 static int dahdi_hangup(struct ast_channel *ast)
06317 {
06318    int res = 0;
06319    int idx,x;
06320    int law;
06321    /*static int restore_gains(struct dahdi_pvt *p);*/
06322    struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
06323    struct dahdi_params par;
06324 
06325    ast_debug(1, "dahdi_hangup(%s)\n", ast_channel_name(ast));
06326    if (!ast_channel_tech_pvt(ast)) {
06327       ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
06328       return 0;
06329    }
06330 
06331    ast_mutex_lock(&p->lock);
06332    p->exten[0] = '\0';
06333    if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
06334       dahdi_confmute(p, 0);
06335       restore_gains(p);
06336       p->ignoredtmf = 0;
06337       p->waitingfordt.tv_sec = 0;
06338 
06339       res = analog_hangup(p->sig_pvt, ast);
06340       revert_fax_buffers(p, ast);
06341 
06342       goto hangup_out;
06343    } else {
06344       p->cid_num[0] = '\0';
06345       p->cid_name[0] = '\0';
06346       p->cid_subaddr[0] = '\0';
06347    }
06348 
06349 #if defined(HAVE_PRI)
06350    if (dahdi_sig_pri_lib_handles(p->sig)) {
06351       x = 1;
06352       ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
06353 
06354       dahdi_confmute(p, 0);
06355       p->muting = 0;
06356       restore_gains(p);
06357       if (p->dsp) {
06358          ast_dsp_free(p->dsp);
06359          p->dsp = NULL;
06360       }
06361       p->ignoredtmf = 0;
06362 
06363       /* Real channel, do some fixup */
06364       p->subs[SUB_REAL].owner = NULL;
06365       p->subs[SUB_REAL].needbusy = 0;
06366       dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
06367 
06368       p->owner = NULL;
06369       p->cid_tag[0] = '\0';
06370       p->ringt = 0;/* Probably not used in this mode.  Reset anyway. */
06371       p->distinctivering = 0;/* Probably not used in this mode. Reset anyway. */
06372       p->confirmanswer = 0;/* Probably not used in this mode. Reset anyway. */
06373       p->outgoing = 0;
06374       p->digital = 0;
06375       p->faxhandled = 0;
06376       p->pulsedial = 0;/* Probably not used in this mode. Reset anyway. */
06377 
06378       revert_fax_buffers(p, ast);
06379 
06380       p->law = p->law_default;
06381       law = p->law_default;
06382       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
06383       if (res < 0) {
06384          ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n",
06385             p->channel, strerror(errno));
06386       }
06387 
06388       sig_pri_hangup(p->sig_pvt, ast);
06389 
06390       tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06391       dahdi_disable_ec(p);
06392 
06393       x = 0;
06394       ast_channel_setoption(ast, AST_OPTION_TDD, &x, sizeof(char), 0);
06395       p->didtdd = 0;/* Probably not used in this mode. Reset anyway. */
06396 
06397       p->rdnis[0] = '\0';
06398       update_conf(p);
06399       reset_conf(p);
06400 
06401       /* Restore data mode */
06402       x = 0;
06403       ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
06404 
06405       if (num_restart_pending == 0) {
06406          restart_monitor();
06407       }
06408       goto hangup_out;
06409    }
06410 #endif   /* defined(HAVE_PRI) */
06411 
06412 #if defined(HAVE_SS7)
06413    if (p->sig == SIG_SS7) {
06414       x = 1;
06415       ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
06416 
06417       dahdi_confmute(p, 0);
06418       p->muting = 0;
06419       restore_gains(p);
06420       if (p->dsp) {
06421          ast_dsp_free(p->dsp);
06422          p->dsp = NULL;
06423       }
06424       p->ignoredtmf = 0;
06425 
06426       /* Real channel, do some fixup */
06427       p->subs[SUB_REAL].owner = NULL;
06428       p->subs[SUB_REAL].needbusy = 0;
06429       dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
06430 
06431       p->owner = NULL;
06432       p->ringt = 0;/* Probably not used in this mode.  Reset anyway. */
06433       p->distinctivering = 0;/* Probably not used in this mode. Reset anyway. */
06434       p->confirmanswer = 0;/* Probably not used in this mode. Reset anyway. */
06435       p->outgoing = 0;
06436       p->digital = 0;
06437       p->faxhandled = 0;
06438       p->pulsedial = 0;/* Probably not used in this mode. Reset anyway. */
06439 
06440       revert_fax_buffers(p, ast);
06441 
06442       p->law = p->law_default;
06443       law = p->law_default;
06444       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
06445       if (res < 0) {
06446          ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n",
06447             p->channel, strerror(errno));
06448       }
06449 
06450       sig_ss7_hangup(p->sig_pvt, ast);
06451 
06452       tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06453       dahdi_disable_ec(p);
06454 
06455       x = 0;
06456       ast_channel_setoption(ast, AST_OPTION_TDD, &x, sizeof(char), 0);
06457       p->didtdd = 0;/* Probably not used in this mode. Reset anyway. */
06458 
06459       update_conf(p);
06460       reset_conf(p);
06461 
06462       /* Restore data mode */
06463       x = 0;
06464       ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
06465 
06466       if (num_restart_pending == 0) {
06467          restart_monitor();
06468       }
06469       goto hangup_out;
06470    }
06471 #endif   /* defined(HAVE_SS7) */
06472 
06473    idx = dahdi_get_index(ast, p, 1);
06474 
06475    dahdi_confmute(p, 0);
06476    p->muting = 0;
06477    restore_gains(p);
06478    if (p->origcid_num) {
06479       ast_copy_string(p->cid_num, p->origcid_num, sizeof(p->cid_num));
06480       ast_free(p->origcid_num);
06481       p->origcid_num = NULL;
06482    }
06483    if (p->origcid_name) {
06484       ast_copy_string(p->cid_name, p->origcid_name, sizeof(p->cid_name));
06485       ast_free(p->origcid_name);
06486       p->origcid_name = NULL;
06487    }
06488    if (p->dsp)
06489       ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
06490 
06491    ast_debug(1, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n",
06492       p->channel, idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
06493    p->ignoredtmf = 0;
06494 
06495    if (idx > -1) {
06496       /* Real channel, do some fixup */
06497       p->subs[idx].owner = NULL;
06498       p->subs[idx].needanswer = 0;
06499       p->subs[idx].needflash = 0;
06500       p->subs[idx].needringing = 0;
06501       p->subs[idx].needbusy = 0;
06502       p->subs[idx].needcongestion = 0;
06503       p->subs[idx].linear = 0;
06504       p->polarity = POLARITY_IDLE;
06505       dahdi_setlinear(p->subs[idx].dfd, 0);
06506       if (idx == SUB_REAL) {
06507          if ((p->subs[SUB_CALLWAIT].dfd > -1) && (p->subs[SUB_THREEWAY].dfd > -1)) {
06508             ast_debug(1, "Normal call hung up with both three way call and a call waiting call in place?\n");
06509             if (p->subs[SUB_CALLWAIT].inthreeway) {
06510                /* We had flipped over to answer a callwait and now it's gone */
06511                ast_debug(1, "We were flipped over to the callwait, moving back and unowning.\n");
06512                /* Move to the call-wait, but un-own us until they flip back. */
06513                swap_subs(p, SUB_CALLWAIT, SUB_REAL);
06514                unalloc_sub(p, SUB_CALLWAIT);
06515                p->owner = NULL;
06516             } else {
06517                /* The three way hung up, but we still have a call wait */
06518                ast_debug(1, "We were in the threeway and have a callwait still.  Ditching the threeway.\n");
06519                swap_subs(p, SUB_THREEWAY, SUB_REAL);
06520                unalloc_sub(p, SUB_THREEWAY);
06521                if (p->subs[SUB_REAL].inthreeway) {
06522                   /* This was part of a three way call.  Immediately make way for
06523                      another call */
06524                   ast_debug(1, "Call was complete, setting owner to former third call\n");
06525                   p->owner = p->subs[SUB_REAL].owner;
06526                } else {
06527                   /* This call hasn't been completed yet...  Set owner to NULL */
06528                   ast_debug(1, "Call was incomplete, setting owner to NULL\n");
06529                   p->owner = NULL;
06530                }
06531                p->subs[SUB_REAL].inthreeway = 0;
06532             }
06533          } else if (p->subs[SUB_CALLWAIT].dfd > -1) {
06534             /* Move to the call-wait and switch back to them. */
06535             swap_subs(p, SUB_CALLWAIT, SUB_REAL);
06536             unalloc_sub(p, SUB_CALLWAIT);
06537             p->owner = p->subs[SUB_REAL].owner;
06538             if (ast_channel_state(p->owner) != AST_STATE_UP)
06539                p->subs[SUB_REAL].needanswer = 1;
06540             if (ast_bridged_channel(p->subs[SUB_REAL].owner))
06541                ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
06542          } else if (p->subs[SUB_THREEWAY].dfd > -1) {
06543             swap_subs(p, SUB_THREEWAY, SUB_REAL);
06544             unalloc_sub(p, SUB_THREEWAY);
06545             if (p->subs[SUB_REAL].inthreeway) {
06546                /* This was part of a three way call.  Immediately make way for
06547                   another call */
06548                ast_debug(1, "Call was complete, setting owner to former third call\n");
06549                p->owner = p->subs[SUB_REAL].owner;
06550             } else {
06551                /* This call hasn't been completed yet...  Set owner to NULL */
06552                ast_debug(1, "Call was incomplete, setting owner to NULL\n");
06553                p->owner = NULL;
06554             }
06555             p->subs[SUB_REAL].inthreeway = 0;
06556          }
06557       } else if (idx == SUB_CALLWAIT) {
06558          /* Ditch the holding callwait call, and immediately make it availabe */
06559          if (p->subs[SUB_CALLWAIT].inthreeway) {
06560             /* This is actually part of a three way, placed on hold.  Place the third part
06561                on music on hold now */
06562             if (p->subs[SUB_THREEWAY].owner && ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
06563                ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
06564                   S_OR(p->mohsuggest, NULL),
06565                   !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
06566             }
06567             p->subs[SUB_THREEWAY].inthreeway = 0;
06568             /* Make it the call wait now */
06569             swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
06570             unalloc_sub(p, SUB_THREEWAY);
06571          } else
06572             unalloc_sub(p, SUB_CALLWAIT);
06573       } else if (idx == SUB_THREEWAY) {
06574          if (p->subs[SUB_CALLWAIT].inthreeway) {
06575             /* The other party of the three way call is currently in a call-wait state.
06576                Start music on hold for them, and take the main guy out of the third call */
06577             if (p->subs[SUB_CALLWAIT].owner && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
06578                ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
06579                   S_OR(p->mohsuggest, NULL),
06580                   !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
06581             }
06582             p->subs[SUB_CALLWAIT].inthreeway = 0;
06583          }
06584          p->subs[SUB_REAL].inthreeway = 0;
06585          /* If this was part of a three way call index, let us make
06586             another three way call */
06587          unalloc_sub(p, SUB_THREEWAY);
06588       } else {
06589          /* This wasn't any sort of call, but how are we an index? */
06590          ast_log(LOG_WARNING, "Index found but not any type of call?\n");
06591       }
06592    }
06593 
06594    if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) {
06595       p->owner = NULL;
06596       p->ringt = 0;
06597       p->distinctivering = 0;
06598       p->confirmanswer = 0;
06599       p->outgoing = 0;
06600       p->digital = 0;
06601       p->faxhandled = 0;
06602       p->pulsedial = 0;
06603       if (p->dsp) {
06604          ast_dsp_free(p->dsp);
06605          p->dsp = NULL;
06606       }
06607 
06608       revert_fax_buffers(p, ast);
06609 
06610       p->law = p->law_default;
06611       law = p->law_default;
06612       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
06613       if (res < 0)
06614          ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
06615       /* Perform low level hangup if no owner left */
06616 #ifdef HAVE_OPENR2
06617       if (p->mfcr2 && p->mfcr2call && openr2_chan_get_direction(p->r2chan) != OR2_DIR_STOPPED) {
06618          ast_debug(1, "disconnecting MFC/R2 call on chan %d\n", p->channel);
06619          /* If it's an incoming call, check the mfcr2_forced_release setting */
06620          if (openr2_chan_get_direction(p->r2chan) == OR2_DIR_BACKWARD && p->mfcr2_forced_release) {
06621             dahdi_r2_disconnect_call(p, OR2_CAUSE_FORCED_RELEASE);
06622          } else {
06623             const char *r2causestr = pbx_builtin_getvar_helper(ast, "MFCR2_CAUSE");
06624             int r2cause_user = r2causestr ? atoi(r2causestr) : 0;
06625             openr2_call_disconnect_cause_t r2cause = r2cause_user ? dahdi_ast_cause_to_r2_cause(r2cause_user)
06626                                                              : dahdi_ast_cause_to_r2_cause(ast_channel_hangupcause(ast));
06627             dahdi_r2_disconnect_call(p, r2cause);
06628          }
06629       } else if (p->mfcr2call) {
06630          ast_debug(1, "Clearing call request on channel %d\n", p->channel);
06631          /* since ast_request() was called but not ast_call() we have not yet dialed
06632          and the openr2 stack will not call on_call_end callback, we need to unset
06633          the mfcr2call flag and bump the monitor count so the monitor thread can take
06634          care of this channel events from now on */
06635          p->mfcr2call = 0;
06636       }
06637 #endif
06638       switch (p->sig) {
06639       case SIG_SS7:
06640       case SIG_MFCR2:
06641       case SIG_PRI_LIB_HANDLE_CASES:
06642       case 0:
06643          break;
06644       default:
06645          res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
06646          break;
06647       }
06648       if (res < 0) {
06649          ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast_channel_name(ast));
06650       }
06651       switch (p->sig) {
06652       case SIG_FXOGS:
06653       case SIG_FXOLS:
06654       case SIG_FXOKS:
06655          memset(&par, 0, sizeof(par));
06656          res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
06657          if (!res) {
06658             struct analog_pvt *analog_p = p->sig_pvt;
06659 #if 0
06660             ast_debug(1, "Hanging up channel %d, offhook = %d\n", p->channel, par.rxisoffhook);
06661 #endif
06662             /* If they're off hook, try playing congestion */
06663             if ((par.rxisoffhook) && (!(p->radio || (p->oprmode < 0))))
06664                tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
06665             else
06666                tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06667             analog_p->fxsoffhookstate = par.rxisoffhook;
06668          }
06669          break;
06670       case SIG_FXSGS:
06671       case SIG_FXSLS:
06672       case SIG_FXSKS:
06673          /* Make sure we're not made available for at least two seconds assuming
06674          we were actually used for an inbound or outbound call. */
06675          if (ast_channel_state(ast) != AST_STATE_RESERVED) {
06676             time(&p->guardtime);
06677             p->guardtime += 2;
06678          }
06679          break;
06680       default:
06681          tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06682          break;
06683       }
06684       if (p->sig)
06685          dahdi_disable_ec(p);
06686       x = 0;
06687       ast_channel_setoption(ast,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0);
06688       ast_channel_setoption(ast,AST_OPTION_TDD,&x,sizeof(char),0);
06689       p->didtdd = 0;
06690       p->callwaitcas = 0;
06691       p->callwaiting = p->permcallwaiting;
06692       p->hidecallerid = p->permhidecallerid;
06693       p->waitingfordt.tv_sec = 0;
06694       p->dialing = 0;
06695       p->rdnis[0] = '\0';
06696       update_conf(p);
06697       reset_conf(p);
06698       /* Restore data mode */
06699       switch (p->sig) {
06700       case SIG_PRI_LIB_HANDLE_CASES:
06701       case SIG_SS7:
06702          x = 0;
06703          ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
06704          break;
06705       default:
06706          break;
06707       }
06708       if (num_restart_pending == 0)
06709          restart_monitor();
06710    }
06711 
06712    p->callwaitingrepeat = 0;
06713    p->cidcwexpire = 0;
06714    p->cid_suppress_expire = 0;
06715    p->oprmode = 0;
06716 hangup_out:
06717    ast_channel_tech_pvt_set(ast, NULL);
06718    ast_free(p->cidspill);
06719    p->cidspill = NULL;
06720 
06721    ast_mutex_unlock(&p->lock);
06722    ast_verb(3, "Hungup '%s'\n", ast_channel_name(ast));
06723 
06724    ast_mutex_lock(&iflock);
06725    if (p->restartpending) {
06726       num_restart_pending--;
06727    }
06728 
06729    if (p->destroy) {
06730       destroy_channel(p, 0);
06731    }
06732    ast_mutex_unlock(&iflock);
06733 
06734    ast_module_unref(ast_module_info->self);
06735    return 0;
06736 }
06737 
06738 static int dahdi_answer(struct ast_channel *ast)
06739 {
06740    struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
06741    int res = 0;
06742    int idx;
06743    ast_setstate(ast, AST_STATE_UP);/*! \todo XXX this is redundantly set by the analog and PRI submodules! */
06744    ast_mutex_lock(&p->lock);
06745    idx = dahdi_get_index(ast, p, 0);
06746    if (idx < 0)
06747       idx = SUB_REAL;
06748    /* nothing to do if a radio channel */
06749    if ((p->radio || (p->oprmode < 0))) {
06750       ast_mutex_unlock(&p->lock);
06751       return 0;
06752    }
06753 
06754    if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
06755       res = analog_answer(p->sig_pvt, ast);
06756       ast_mutex_unlock(&p->lock);
06757       return res;
06758    }
06759 
06760    switch (p->sig) {
06761 #if defined(HAVE_PRI)
06762    case SIG_PRI_LIB_HANDLE_CASES:
06763       res = sig_pri_answer(p->sig_pvt, ast);
06764       break;
06765 #endif   /* defined(HAVE_PRI) */
06766 #if defined(HAVE_SS7)
06767    case SIG_SS7:
06768       res = sig_ss7_answer(p->sig_pvt, ast);
06769       break;
06770 #endif   /* defined(HAVE_SS7) */
06771 #ifdef HAVE_OPENR2
06772    case SIG_MFCR2:
06773       if (!p->mfcr2_call_accepted) {
06774          /* The call was not accepted on offer nor the user, so it must be accepted now before answering,
06775             openr2_chan_answer_call will be called when the callback on_call_accepted is executed */
06776          p->mfcr2_answer_pending = 1;
06777          if (p->mfcr2_charge_calls) {
06778             ast_debug(1, "Accepting MFC/R2 call with charge before answering on chan %d\n", p->channel);
06779             openr2_chan_accept_call(p->r2chan, OR2_CALL_WITH_CHARGE);
06780          } else {
06781             ast_debug(1, "Accepting MFC/R2 call with no charge before answering on chan %d\n", p->channel);
06782             openr2_chan_accept_call(p->r2chan, OR2_CALL_NO_CHARGE);
06783          }
06784       } else {
06785          ast_debug(1, "Answering MFC/R2 call on chan %d\n", p->channel);
06786          dahdi_r2_answer(p);
06787       }
06788       break;
06789 #endif
06790    case 0:
06791       ast_mutex_unlock(&p->lock);
06792       return 0;
06793    default:
06794       ast_log(LOG_WARNING, "Don't know how to answer signalling %d (channel %d)\n", p->sig, p->channel);
06795       res = -1;
06796       break;
06797    }
06798    ast_mutex_unlock(&p->lock);
06799    return res;
06800 }
06801 
06802 static void disable_dtmf_detect(struct dahdi_pvt *p)
06803 {
06804    int val = 0;
06805 
06806    p->ignoredtmf = 1;
06807 
06808    ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
06809 
06810    if (!p->hardwaredtmf && p->dsp) {
06811       p->dsp_features &= ~DSP_FEATURE_DIGIT_DETECT;
06812       ast_dsp_set_features(p->dsp, p->dsp_features);
06813    }
06814 }
06815 
06816 static void enable_dtmf_detect(struct dahdi_pvt *p)
06817 {
06818    int val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
06819 
06820    if (p->channel == CHAN_PSEUDO)
06821       return;
06822 
06823    p->ignoredtmf = 0;
06824 
06825    ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
06826 
06827    if (!p->hardwaredtmf && p->dsp) {
06828       p->dsp_features |= DSP_FEATURE_DIGIT_DETECT;
06829       ast_dsp_set_features(p->dsp, p->dsp_features);
06830    }
06831 }
06832 
06833 static int dahdi_queryoption(struct ast_channel *chan, int option, void *data, int *datalen)
06834 {
06835    char *cp;
06836    struct dahdi_pvt *p = ast_channel_tech_pvt(chan);
06837 
06838    /* all supported options require data */
06839    if (!p || !data || (*datalen < 1)) {
06840       errno = EINVAL;
06841       return -1;
06842    }
06843 
06844    switch (option) {
06845    case AST_OPTION_DIGIT_DETECT:
06846       cp = (char *) data;
06847       *cp = p->ignoredtmf ? 0 : 1;
06848       ast_debug(1, "Reporting digit detection %sabled on %s\n", *cp ? "en" : "dis", ast_channel_name(chan));
06849       break;
06850    case AST_OPTION_FAX_DETECT:
06851       cp = (char *) data;
06852       *cp = (p->dsp_features & DSP_FEATURE_FAX_DETECT) ? 0 : 1;
06853       ast_debug(1, "Reporting fax tone detection %sabled on %s\n", *cp ? "en" : "dis", ast_channel_name(chan));
06854       break;
06855    case AST_OPTION_CC_AGENT_TYPE:
06856 #if defined(HAVE_PRI)
06857 #if defined(HAVE_PRI_CCSS)
06858       if (dahdi_sig_pri_lib_handles(p->sig)) {
06859          ast_copy_string((char *) data, dahdi_pri_cc_type, *datalen);
06860          break;
06861       }
06862 #endif   /* defined(HAVE_PRI_CCSS) */
06863 #endif   /* defined(HAVE_PRI) */
06864       return -1;
06865    default:
06866       return -1;
06867    }
06868 
06869    errno = 0;
06870 
06871    return 0;
06872 }
06873 
06874 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen)
06875 {
06876    char *cp;
06877    signed char *scp;
06878    int x;
06879    int idx;
06880    struct dahdi_pvt *p = ast_channel_tech_pvt(chan), *pp;
06881    struct oprmode *oprmode;
06882 
06883 
06884    /* all supported options require data */
06885    if (!p || !data || (datalen < 1)) {
06886       errno = EINVAL;
06887       return -1;
06888    }
06889 
06890    switch (option) {
06891    case AST_OPTION_TXGAIN:
06892       scp = (signed char *) data;
06893       idx = dahdi_get_index(chan, p, 0);
06894       if (idx < 0) {
06895          ast_log(LOG_WARNING, "No index in TXGAIN?\n");
06896          return -1;
06897       }
06898       ast_debug(1, "Setting actual tx gain on %s to %f\n", ast_channel_name(chan), p->txgain + (float) *scp);
06899       return set_actual_txgain(p->subs[idx].dfd, p->txgain + (float) *scp, p->txdrc, p->law);
06900    case AST_OPTION_RXGAIN:
06901       scp = (signed char *) data;
06902       idx = dahdi_get_index(chan, p, 0);
06903       if (idx < 0) {
06904          ast_log(LOG_WARNING, "No index in RXGAIN?\n");
06905          return -1;
06906       }
06907       ast_debug(1, "Setting actual rx gain on %s to %f\n", ast_channel_name(chan), p->rxgain + (float) *scp);
06908       return set_actual_rxgain(p->subs[idx].dfd, p->rxgain + (float) *scp, p->rxdrc, p->law);
06909    case AST_OPTION_TONE_VERIFY:
06910       if (!p->dsp)
06911          break;
06912       cp = (char *) data;
06913       switch (*cp) {
06914       case 1:
06915          ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",ast_channel_name(chan));
06916          ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | p->dtmfrelax);  /* set mute mode if desired */
06917          break;
06918       case 2:
06919          ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",ast_channel_name(chan));
06920          ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX | p->dtmfrelax);  /* set mute mode if desired */
06921          break;
06922       default:
06923          ast_debug(1, "Set option TONE VERIFY, mode: OFF(0) on %s\n",ast_channel_name(chan));
06924          ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);  /* set mute mode if desired */
06925          break;
06926       }
06927       break;
06928    case AST_OPTION_TDD:
06929       /* turn on or off TDD */
06930       cp = (char *) data;
06931       p->mate = 0;
06932       if (!*cp) { /* turn it off */
06933          ast_debug(1, "Set option TDD MODE, value: OFF(0) on %s\n",ast_channel_name(chan));
06934          if (p->tdd)
06935             tdd_free(p->tdd);
06936          p->tdd = 0;
06937          break;
06938       }
06939       ast_debug(1, "Set option TDD MODE, value: %s(%d) on %s\n",
06940          (*cp == 2) ? "MATE" : "ON", (int) *cp, ast_channel_name(chan));
06941       dahdi_disable_ec(p);
06942       /* otherwise, turn it on */
06943       if (!p->didtdd) { /* if havent done it yet */
06944          unsigned char mybuf[41000];/*! \todo XXX This is an abuse of the stack!! */
06945          unsigned char *buf;
06946          int size, res, fd, len;
06947          struct pollfd fds[1];
06948 
06949          buf = mybuf;
06950          memset(buf, 0x7f, sizeof(mybuf)); /* set to silence */
06951          ast_tdd_gen_ecdisa(buf + 16000, 16000);  /* put in tone */
06952          len = 40000;
06953          idx = dahdi_get_index(chan, p, 0);
06954          if (idx < 0) {
06955             ast_log(LOG_WARNING, "No index in TDD?\n");
06956             return -1;
06957          }
06958          fd = p->subs[idx].dfd;
06959          while (len) {
06960             if (ast_check_hangup(chan))
06961                return -1;
06962             size = len;
06963             if (size > READ_SIZE)
06964                size = READ_SIZE;
06965             fds[0].fd = fd;
06966             fds[0].events = POLLPRI | POLLOUT;
06967             fds[0].revents = 0;
06968             res = poll(fds, 1, -1);
06969             if (!res) {
06970                ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
06971                continue;
06972             }
06973             /* if got exception */
06974             if (fds[0].revents & POLLPRI)
06975                return -1;
06976             if (!(fds[0].revents & POLLOUT)) {
06977                ast_debug(1, "write fd not ready on channel %d\n", p->channel);
06978                continue;
06979             }
06980             res = write(fd, buf, size);
06981             if (res != size) {
06982                if (res == -1) return -1;
06983                ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
06984                break;
06985             }
06986             len -= size;
06987             buf += size;
06988          }
06989          p->didtdd = 1; /* set to have done it now */
06990       }
06991       if (*cp == 2) { /* Mate mode */
06992          if (p->tdd)
06993             tdd_free(p->tdd);
06994          p->tdd = 0;
06995          p->mate = 1;
06996          break;
06997       }
06998       if (!p->tdd) { /* if we don't have one yet */
06999          p->tdd = tdd_new(); /* allocate one */
07000       }
07001       break;
07002    case AST_OPTION_RELAXDTMF:  /* Relax DTMF decoding (or not) */
07003       if (!p->dsp)
07004          break;
07005       cp = (char *) data;
07006       ast_debug(1, "Set option RELAX DTMF, value: %s(%d) on %s\n",
07007          *cp ? "ON" : "OFF", (int) *cp, ast_channel_name(chan));
07008       ast_dsp_set_digitmode(p->dsp, ((*cp) ? DSP_DIGITMODE_RELAXDTMF : DSP_DIGITMODE_DTMF) | p->dtmfrelax);
07009       break;
07010    case AST_OPTION_AUDIO_MODE:  /* Set AUDIO mode (or not) */
07011 #if defined(HAVE_PRI)
07012       if (dahdi_sig_pri_lib_handles(p->sig)
07013          && ((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
07014          /* PRI nobch pseudo channel.  Does not handle ioctl(DAHDI_AUDIOMODE) */
07015          break;
07016       }
07017 #endif   /* defined(HAVE_PRI) */
07018 
07019       cp = (char *) data;
07020       if (!*cp) {
07021          ast_debug(1, "Set option AUDIO MODE, value: OFF(0) on %s\n", ast_channel_name(chan));
07022          x = 0;
07023          dahdi_disable_ec(p);
07024       } else {
07025          ast_debug(1, "Set option AUDIO MODE, value: ON(1) on %s\n", ast_channel_name(chan));
07026          x = 1;
07027       }
07028       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x) == -1)
07029          ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, x, strerror(errno));
07030       break;
07031    case AST_OPTION_OPRMODE:  /* Operator services mode */
07032       oprmode = (struct oprmode *) data;
07033       /* We don't support operator mode across technologies */
07034       if (strcasecmp(ast_channel_tech(chan)->type, ast_channel_tech(oprmode->peer)->type)) {
07035          ast_log(LOG_NOTICE, "Operator mode not supported on %s to %s calls.\n",
07036                ast_channel_tech(chan)->type, ast_channel_tech(oprmode->peer)->type);
07037          errno = EINVAL;
07038          return -1;
07039       }
07040       pp = ast_channel_tech_pvt(oprmode->peer);
07041       p->oprmode = pp->oprmode = 0;
07042       /* setup peers */
07043       p->oprpeer = pp;
07044       pp->oprpeer = p;
07045       /* setup modes, if any */
07046       if (oprmode->mode)
07047       {
07048          pp->oprmode = oprmode->mode;
07049          p->oprmode = -oprmode->mode;
07050       }
07051       ast_debug(1, "Set Operator Services mode, value: %d on %s/%s\n",
07052          oprmode->mode, ast_channel_name(chan),ast_channel_name(oprmode->peer));
07053       break;
07054    case AST_OPTION_ECHOCAN:
07055       cp = (char *) data;
07056       if (*cp) {
07057          ast_debug(1, "Enabling echo cancellation on %s\n", ast_channel_name(chan));
07058          dahdi_enable_ec(p);
07059       } else {
07060          ast_debug(1, "Disabling echo cancellation on %s\n", ast_channel_name(chan));
07061          dahdi_disable_ec(p);
07062       }
07063       break;
07064    case AST_OPTION_DIGIT_DETECT:
07065       cp = (char *) data;
07066       ast_debug(1, "%sabling digit detection on %s\n", *cp ? "En" : "Dis", ast_channel_name(chan));
07067       if (*cp) {
07068          enable_dtmf_detect(p);
07069       } else {
07070          disable_dtmf_detect(p);
07071       }
07072       break;
07073    case AST_OPTION_FAX_DETECT:
07074       cp = (char *) data;
07075       if (p->dsp) {
07076          ast_debug(1, "%sabling fax tone detection on %s\n", *cp ? "En" : "Dis", ast_channel_name(chan));
07077          if (*cp) {
07078             p->dsp_features |= DSP_FEATURE_FAX_DETECT;
07079          } else {
07080             p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
07081          }
07082          ast_dsp_set_features(p->dsp, p->dsp_features);
07083       }
07084       break;
07085    default:
07086       return -1;
07087    }
07088    errno = 0;
07089 
07090    return 0;
07091 }
07092 
07093 static int dahdi_func_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len)
07094 {
07095    struct dahdi_pvt *p = ast_channel_tech_pvt(chan);
07096    int res = 0;
07097 
07098    if (!p) {
07099       /* No private structure! */
07100       *buf = '\0';
07101       return -1;
07102    }
07103 
07104    if (!strcasecmp(data, "rxgain")) {
07105       ast_mutex_lock(&p->lock);
07106       snprintf(buf, len, "%f", p->rxgain);
07107       ast_mutex_unlock(&p->lock);
07108    } else if (!strcasecmp(data, "txgain")) {
07109       ast_mutex_lock(&p->lock);
07110       snprintf(buf, len, "%f", p->txgain);
07111       ast_mutex_unlock(&p->lock);
07112    } else if (!strcasecmp(data, "dahdi_channel")) {
07113       ast_mutex_lock(&p->lock);
07114       snprintf(buf, len, "%d", p->channel);
07115       ast_mutex_unlock(&p->lock);
07116    } else if (!strcasecmp(data, "dahdi_span")) {
07117       ast_mutex_lock(&p->lock);
07118       snprintf(buf, len, "%d", p->span);
07119       ast_mutex_unlock(&p->lock);
07120    } else if (!strcasecmp(data, "dahdi_type")) {
07121       ast_mutex_lock(&p->lock);
07122       switch (p->sig) {
07123 #if defined(HAVE_OPENR2)
07124       case SIG_MFCR2:
07125          ast_copy_string(buf, "mfc/r2", len);
07126          break;
07127 #endif   /* defined(HAVE_OPENR2) */
07128 #if defined(HAVE_PRI)
07129       case SIG_PRI_LIB_HANDLE_CASES:
07130          ast_copy_string(buf, "pri", len);
07131          break;
07132 #endif   /* defined(HAVE_PRI) */
07133       case 0:
07134          ast_copy_string(buf, "pseudo", len);
07135          break;
07136 #if defined(HAVE_SS7)
07137       case SIG_SS7:
07138          ast_copy_string(buf, "ss7", len);
07139          break;
07140 #endif   /* defined(HAVE_SS7) */
07141       default:
07142          /* The only thing left is analog ports. */
07143          ast_copy_string(buf, "analog", len);
07144          break;
07145       }
07146       ast_mutex_unlock(&p->lock);
07147 #if defined(HAVE_PRI)
07148 #if defined(HAVE_PRI_REVERSE_CHARGE)
07149    } else if (!strcasecmp(data, "reversecharge")) {
07150       ast_mutex_lock(&p->lock);
07151       switch (p->sig) {
07152       case SIG_PRI_LIB_HANDLE_CASES:
07153          snprintf(buf, len, "%d", ((struct sig_pri_chan *) p->sig_pvt)->reverse_charging_indication);
07154          break;
07155       default:
07156          *buf = '\0';
07157          res = -1;
07158          break;
07159       }
07160       ast_mutex_unlock(&p->lock);
07161 #endif
07162 #if defined(HAVE_PRI_SETUP_KEYPAD)
07163    } else if (!strcasecmp(data, "keypad_digits")) {
07164       ast_mutex_lock(&p->lock);
07165       switch (p->sig) {
07166       case SIG_PRI_LIB_HANDLE_CASES:
07167          ast_copy_string(buf, ((struct sig_pri_chan *) p->sig_pvt)->keypad_digits,
07168             len);
07169          break;
07170       default:
07171          *buf = '\0';
07172          res = -1;
07173          break;
07174       }
07175       ast_mutex_unlock(&p->lock);
07176 #endif   /* defined(HAVE_PRI_SETUP_KEYPAD) */
07177    } else if (!strcasecmp(data, "no_media_path")) {
07178       ast_mutex_lock(&p->lock);
07179       switch (p->sig) {
07180       case SIG_PRI_LIB_HANDLE_CASES:
07181          /*
07182           * TRUE if the call is on hold or is call waiting because
07183           * there is no media path available.
07184           */
07185          snprintf(buf, len, "%d", ((struct sig_pri_chan *) p->sig_pvt)->no_b_channel);
07186          break;
07187       default:
07188          *buf = '\0';
07189          res = -1;
07190          break;
07191       }
07192       ast_mutex_unlock(&p->lock);
07193 #endif   /* defined(HAVE_PRI) */
07194    } else {
07195       *buf = '\0';
07196       res = -1;
07197    }
07198 
07199    return res;
07200 }
07201 
07202 
07203 static int parse_buffers_policy(const char *parse, int *num_buffers, int *policy)
07204 {
07205    int res;
07206    char policy_str[21] = "";
07207 
07208    if ((res = sscanf(parse, "%30d,%20s", num_buffers, policy_str)) != 2) {
07209       ast_log(LOG_WARNING, "Parsing buffer string '%s' failed.\n", parse);
07210       return 1;
07211    }
07212    if (*num_buffers < 0) {
07213       ast_log(LOG_WARNING, "Invalid buffer count given '%d'.\n", *num_buffers);
07214       return -1;
07215    }
07216    if (!strcasecmp(policy_str, "full")) {
07217       *policy = DAHDI_POLICY_WHEN_FULL;
07218    } else if (!strcasecmp(policy_str, "immediate")) {
07219       *policy = DAHDI_POLICY_IMMEDIATE;
07220 #if defined(HAVE_DAHDI_HALF_FULL)
07221    } else if (!strcasecmp(policy_str, "half")) {
07222       *policy = DAHDI_POLICY_HALF_FULL;
07223 #endif
07224    } else {
07225       ast_log(LOG_WARNING, "Invalid policy name given '%s'.\n", policy_str);
07226       return -1;
07227    }
07228 
07229    return 0;
07230 }
07231 
07232 static int dahdi_func_write(struct ast_channel *chan, const char *function, char *data, const char *value)
07233 {
07234    struct dahdi_pvt *p = ast_channel_tech_pvt(chan);
07235    int res = 0;
07236 
07237    if (!p) {
07238       /* No private structure! */
07239       return -1;
07240    }
07241 
07242    if (!strcasecmp(data, "buffers")) {
07243       int num_bufs, policy;
07244 
07245       if (!(parse_buffers_policy(value, &num_bufs, &policy))) {
07246          struct dahdi_bufferinfo bi = {
07247             .txbufpolicy = policy,
07248             .rxbufpolicy = policy,
07249             .bufsize = p->bufsize,
07250             .numbufs = num_bufs,
07251          };
07252          int bpres;
07253 
07254          if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
07255             ast_log(LOG_WARNING, "Channel '%d' unable to override buffer policy: %s\n", p->channel, strerror(errno));
07256          } else {
07257             p->bufferoverrideinuse = 1;
07258          }
07259       } else {
07260          res = -1;
07261       }
07262    } else if (!strcasecmp(data, "echocan_mode")) {
07263       if (!strcasecmp(value, "on")) {
07264          ast_mutex_lock(&p->lock);
07265          dahdi_enable_ec(p);
07266          ast_mutex_unlock(&p->lock);
07267       } else if (!strcasecmp(value, "off")) {
07268          ast_mutex_lock(&p->lock);
07269          dahdi_disable_ec(p);
07270          ast_mutex_unlock(&p->lock);
07271 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
07272       } else if (!strcasecmp(value, "fax")) {
07273          int blah = 1;
07274 
07275          ast_mutex_lock(&p->lock);
07276          if (!p->echocanon) {
07277             dahdi_enable_ec(p);
07278          }
07279          if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_FAX_MODE, &blah)) {
07280             ast_log(LOG_WARNING, "Unable to place echocan into fax mode on channel %d: %s\n", p->channel, strerror(errno));
07281          }
07282          ast_mutex_unlock(&p->lock);
07283       } else if (!strcasecmp(value, "voice")) {
07284          int blah = 0;
07285 
07286          ast_mutex_lock(&p->lock);
07287          if (!p->echocanon) {
07288             dahdi_enable_ec(p);
07289          }
07290          if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_FAX_MODE, &blah)) {
07291             ast_log(LOG_WARNING, "Unable to place echocan into voice mode on channel %d: %s\n", p->channel, strerror(errno));
07292          }
07293          ast_mutex_unlock(&p->lock);
07294 #endif
07295       } else {
07296          ast_log(LOG_WARNING, "Unsupported value '%s' provided for '%s' item.\n", value, data);
07297          res = -1;
07298       }
07299    } else {
07300       res = -1;
07301    }
07302 
07303    return res;
07304 }
07305 
07306 static void dahdi_unlink(struct dahdi_pvt *slave, struct dahdi_pvt *master, int needlock)
07307 {
07308    /* Unlink a specific slave or all slaves/masters from a given master */
07309    int x;
07310    int hasslaves;
07311    if (!master)
07312       return;
07313    if (needlock) {
07314       ast_mutex_lock(&master->lock);
07315       if (slave) {
07316          while (ast_mutex_trylock(&slave->lock)) {
07317             DEADLOCK_AVOIDANCE(&master->lock);
07318          }
07319       }
07320    }
07321    hasslaves = 0;
07322    for (x = 0; x < MAX_SLAVES; x++) {
07323       if (master->slaves[x]) {
07324          if (!slave || (master->slaves[x] == slave)) {
07325             /* Take slave out of the conference */
07326             ast_debug(1, "Unlinking slave %d from %d\n", master->slaves[x]->channel, master->channel);
07327             conf_del(master, &master->slaves[x]->subs[SUB_REAL], SUB_REAL);
07328             conf_del(master->slaves[x], &master->subs[SUB_REAL], SUB_REAL);
07329             master->slaves[x]->master = NULL;
07330             master->slaves[x] = NULL;
07331          } else
07332             hasslaves = 1;
07333       }
07334       if (!hasslaves)
07335          master->inconference = 0;
07336    }
07337    if (!slave) {
07338       if (master->master) {
07339          /* Take master out of the conference */
07340          conf_del(master->master, &master->subs[SUB_REAL], SUB_REAL);
07341          conf_del(master, &master->master->subs[SUB_REAL], SUB_REAL);
07342          hasslaves = 0;
07343          for (x = 0; x < MAX_SLAVES; x++) {
07344             if (master->master->slaves[x] == master)
07345                master->master->slaves[x] = NULL;
07346             else if (master->master->slaves[x])
07347                hasslaves = 1;
07348          }
07349          if (!hasslaves)
07350             master->master->inconference = 0;
07351       }
07352       master->master = NULL;
07353    }
07354    update_conf(master);
07355    if (needlock) {
07356       if (slave)
07357          ast_mutex_unlock(&slave->lock);
07358       ast_mutex_unlock(&master->lock);
07359    }
07360 }
07361 
07362 static void dahdi_link(struct dahdi_pvt *slave, struct dahdi_pvt *master) {
07363    int x;
07364    if (!slave || !master) {
07365       ast_log(LOG_WARNING, "Tried to link to/from NULL??\n");
07366       return;
07367    }
07368    for (x = 0; x < MAX_SLAVES; x++) {
07369       if (!master->slaves[x]) {
07370          master->slaves[x] = slave;
07371          break;
07372       }
07373    }
07374    if (x >= MAX_SLAVES) {
07375       ast_log(LOG_WARNING, "Replacing slave %d with new slave, %d\n", master->slaves[MAX_SLAVES - 1]->channel, slave->channel);
07376       master->slaves[MAX_SLAVES - 1] = slave;
07377    }
07378    if (slave->master)
07379       ast_log(LOG_WARNING, "Replacing master %d with new master, %d\n", slave->master->channel, master->channel);
07380    slave->master = master;
07381 
07382    ast_debug(1, "Making %d slave to master %d at %d\n", slave->channel, master->channel, x);
07383 }
07384 
07385 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)
07386 {
07387    struct ast_channel *who;
07388    struct dahdi_pvt *p0, *p1, *op0, *op1;
07389    struct dahdi_pvt *master = NULL, *slave = NULL;
07390    struct ast_frame *f;
07391    int inconf = 0;
07392    int nothingok = 1;
07393    int ofd0, ofd1;
07394    int oi0, oi1, i0 = -1, i1 = -1, t0, t1;
07395    int os0 = -1, os1 = -1;
07396    int priority = 0;
07397    struct ast_channel *oc0, *oc1;
07398    enum ast_bridge_result res;
07399    struct timeval start = ast_tvnow();
07400 #ifdef PRI_2BCT
07401    int triedtopribridge = 0;
07402    q931_call *q931c0;
07403    q931_call *q931c1;
07404 #endif
07405 
07406    /* For now, don't attempt to native bridge if either channel needs DTMF detection.
07407       There is code below to handle it properly until DTMF is actually seen,
07408       but due to currently unresolved issues it's ignored...
07409    */
07410 
07411    if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1))
07412       return AST_BRIDGE_FAILED_NOWARN;
07413 
07414    ast_channel_lock_both(c0, c1);
07415 
07416    p0 = ast_channel_tech_pvt(c0);
07417    p1 = ast_channel_tech_pvt(c1);
07418    /* cant do pseudo-channels here */
07419    if (!p0 || (!p0->sig) || !p1 || (!p1->sig)) {
07420       ast_channel_unlock(c0);
07421       ast_channel_unlock(c1);
07422       return AST_BRIDGE_FAILED_NOWARN;
07423    }
07424 
07425    oi0 = dahdi_get_index(c0, p0, 0);
07426    oi1 = dahdi_get_index(c1, p1, 0);
07427    if ((oi0 < 0) || (oi1 < 0)) {
07428       ast_channel_unlock(c0);
07429       ast_channel_unlock(c1);
07430       return AST_BRIDGE_FAILED;
07431    }
07432 
07433    op0 = p0 = ast_channel_tech_pvt(c0);
07434    op1 = p1 = ast_channel_tech_pvt(c1);
07435    ofd0 = ast_channel_fd(c0, 0);
07436    ofd1 = ast_channel_fd(c1, 0);
07437    oc0 = p0->owner;
07438    oc1 = p1->owner;
07439 
07440    if (ast_mutex_trylock(&p0->lock)) {
07441       /* Don't block, due to potential for deadlock */
07442       ast_channel_unlock(c0);
07443       ast_channel_unlock(c1);
07444       ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
07445       return AST_BRIDGE_RETRY;
07446    }
07447    if (ast_mutex_trylock(&p1->lock)) {
07448       /* Don't block, due to potential for deadlock */
07449       ast_mutex_unlock(&p0->lock);
07450       ast_channel_unlock(c0);
07451       ast_channel_unlock(c1);
07452       ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
07453       return AST_BRIDGE_RETRY;
07454    }
07455 
07456    if ((p0->callwaiting && p0->callwaitingcallerid)
07457       || (p1->callwaiting && p1->callwaitingcallerid)) {
07458       /*
07459        * Call Waiting Caller ID requires DTMF detection to know if it
07460        * can send the CID spill.
07461        *
07462        * For now, don't attempt to native bridge if either channel
07463        * needs DTMF detection.  There is code below to handle it
07464        * properly until DTMF is actually seen, but due to currently
07465        * unresolved issues it's ignored...
07466        */
07467       ast_mutex_unlock(&p0->lock);
07468       ast_mutex_unlock(&p1->lock);
07469       ast_channel_unlock(c0);
07470       ast_channel_unlock(c1);
07471       return AST_BRIDGE_FAILED_NOWARN;
07472    }
07473 
07474 #if defined(HAVE_PRI)
07475    if ((dahdi_sig_pri_lib_handles(p0->sig)
07476          && ((struct sig_pri_chan *) p0->sig_pvt)->no_b_channel)
07477       || (dahdi_sig_pri_lib_handles(p1->sig)
07478          && ((struct sig_pri_chan *) p1->sig_pvt)->no_b_channel)) {
07479       /*
07480        * PRI nobch channels (hold and call waiting) are equivalent to
07481        * pseudo channels and cannot be done here.
07482        */
07483       ast_mutex_unlock(&p0->lock);
07484       ast_mutex_unlock(&p1->lock);
07485       ast_channel_unlock(c0);
07486       ast_channel_unlock(c1);
07487       return AST_BRIDGE_FAILED_NOWARN;
07488    }
07489 #endif   /* defined(HAVE_PRI) */
07490 
07491    if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
07492       if (p0->owner && p1->owner) {
07493          /* If we don't have a call-wait in a 3-way, and we aren't in a 3-way, we can be master */
07494          if (!p0->subs[SUB_CALLWAIT].inthreeway && !p1->subs[SUB_REAL].inthreeway) {
07495             master = p0;
07496             slave = p1;
07497             inconf = 1;
07498          } else if (!p1->subs[SUB_CALLWAIT].inthreeway && !p0->subs[SUB_REAL].inthreeway) {
07499             master = p1;
07500             slave = p0;
07501             inconf = 1;
07502          } else {
07503             ast_log(LOG_WARNING, "Huh?  Both calls are callwaits or 3-ways?  That's clever...?\n");
07504             ast_log(LOG_WARNING, "p0: chan %d/%d/CW%d/3W%d, p1: chan %d/%d/CW%d/3W%d\n",
07505                p0->channel,
07506                oi0, (p0->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
07507                p0->subs[SUB_REAL].inthreeway, p0->channel,
07508                oi0, (p1->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
07509                p1->subs[SUB_REAL].inthreeway);
07510          }
07511          nothingok = 0;
07512       }
07513    } else if ((oi0 == SUB_REAL) && (oi1 == SUB_THREEWAY)) {
07514       if (p1->subs[SUB_THREEWAY].inthreeway) {
07515          master = p1;
07516          slave = p0;
07517          nothingok = 0;
07518       }
07519    } else if ((oi0 == SUB_THREEWAY) && (oi1 == SUB_REAL)) {
07520       if (p0->subs[SUB_THREEWAY].inthreeway) {
07521          master = p0;
07522          slave = p1;
07523          nothingok = 0;
07524       }
07525    } else if ((oi0 == SUB_REAL) && (oi1 == SUB_CALLWAIT)) {
07526       /* We have a real and a call wait.  If we're in a three way call, put us in it, otherwise,
07527          don't put us in anything */
07528       if (p1->subs[SUB_CALLWAIT].inthreeway) {
07529          master = p1;
07530          slave = p0;
07531          nothingok = 0;
07532       }
07533    } else if ((oi0 == SUB_CALLWAIT) && (oi1 == SUB_REAL)) {
07534       /* Same as previous */
07535       if (p0->subs[SUB_CALLWAIT].inthreeway) {
07536          master = p0;
07537          slave = p1;
07538          nothingok = 0;
07539       }
07540    }
07541    ast_debug(1, "master: %d, slave: %d, nothingok: %d\n",
07542       master ? master->channel : 0, slave ? slave->channel : 0, nothingok);
07543    if (master && slave) {
07544       /* Stop any tones, or play ringtone as appropriate.  If they're bridged
07545          in an active threeway call with a channel that is ringing, we should
07546          indicate ringing. */
07547       if ((oi1 == SUB_THREEWAY) &&
07548          p1->subs[SUB_THREEWAY].inthreeway &&
07549          p1->subs[SUB_REAL].owner &&
07550          p1->subs[SUB_REAL].inthreeway &&
07551          (ast_channel_state(p1->subs[SUB_REAL].owner) == AST_STATE_RINGING)) {
07552          ast_debug(1,
07553             "Playing ringback on %d/%d(%s) since %d/%d(%s) is in a ringing three-way\n",
07554             p0->channel, oi0, ast_channel_name(c0), p1->channel, oi1, ast_channel_name(c1));
07555          tone_zone_play_tone(p0->subs[oi0].dfd, DAHDI_TONE_RINGTONE);
07556          os1 = ast_channel_state(p1->subs[SUB_REAL].owner);
07557       } else {
07558          ast_debug(1, "Stopping tones on %d/%d(%s) talking to %d/%d(%s)\n",
07559             p0->channel, oi0, ast_channel_name(c0), p1->channel, oi1, ast_channel_name(c1));
07560          tone_zone_play_tone(p0->subs[oi0].dfd, -1);
07561       }
07562       if ((oi0 == SUB_THREEWAY) &&
07563          p0->subs[SUB_THREEWAY].inthreeway &&
07564          p0->subs[SUB_REAL].owner &&
07565          p0->subs[SUB_REAL].inthreeway &&
07566          (ast_channel_state(p0->subs[SUB_REAL].owner) == AST_STATE_RINGING)) {
07567          ast_debug(1,
07568             "Playing ringback on %d/%d(%s) since %d/%d(%s) is in a ringing three-way\n",
07569             p1->channel, oi1, ast_channel_name(c1), p0->channel, oi0, ast_channel_name(c0));
07570          tone_zone_play_tone(p1->subs[oi1].dfd, DAHDI_TONE_RINGTONE);
07571          os0 = ast_channel_state(p0->subs[SUB_REAL].owner);
07572       } else {
07573          ast_debug(1, "Stopping tones on %d/%d(%s) talking to %d/%d(%s)\n",
07574             p1->channel, oi1, ast_channel_name(c1), p0->channel, oi0, ast_channel_name(c0));
07575          tone_zone_play_tone(p1->subs[oi1].dfd, -1);
07576       }
07577       if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
07578          if (!p0->echocanbridged || !p1->echocanbridged) {
07579             /* Disable echo cancellation if appropriate */
07580             dahdi_disable_ec(p0);
07581             dahdi_disable_ec(p1);
07582          }
07583       }
07584       dahdi_link(slave, master);
07585       master->inconference = inconf;
07586    } else if (!nothingok)
07587       ast_log(LOG_WARNING, "Can't link %d/%s with %d/%s\n", p0->channel, subnames[oi0], p1->channel, subnames[oi1]);
07588 
07589    update_conf(p0);
07590    update_conf(p1);
07591    t0 = p0->subs[SUB_REAL].inthreeway;
07592    t1 = p1->subs[SUB_REAL].inthreeway;
07593 
07594    ast_mutex_unlock(&p0->lock);
07595    ast_mutex_unlock(&p1->lock);
07596 
07597    ast_channel_unlock(c0);
07598    ast_channel_unlock(c1);
07599 
07600    /* Native bridge failed */
07601    if ((!master || !slave) && !nothingok) {
07602       dahdi_enable_ec(p0);
07603       dahdi_enable_ec(p1);
07604       return AST_BRIDGE_FAILED;
07605    }
07606 
07607    ast_verb(3, "Native bridging %s and %s\n", ast_channel_name(c0), ast_channel_name(c1));
07608 
07609    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
07610       disable_dtmf_detect(op0);
07611 
07612    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
07613       disable_dtmf_detect(op1);
07614 
07615    for (;;) {
07616       struct ast_channel *c0_priority[2] = {c0, c1};
07617       struct ast_channel *c1_priority[2] = {c1, c0};
07618       int ms;
07619 
07620       /* Here's our main loop...  Start by locking things, looking for private parts,
07621          and then balking if anything is wrong */
07622 
07623       ast_channel_lock_both(c0, c1);
07624 
07625       p0 = ast_channel_tech_pvt(c0);
07626       p1 = ast_channel_tech_pvt(c1);
07627 
07628       if (op0 == p0)
07629          i0 = dahdi_get_index(c0, p0, 1);
07630       if (op1 == p1)
07631          i1 = dahdi_get_index(c1, p1, 1);
07632 
07633       ast_channel_unlock(c0);
07634       ast_channel_unlock(c1);
07635       ms = ast_remaining_ms(start, timeoutms);
07636       if (!ms ||
07637          (op0 != p0) ||
07638          (op1 != p1) ||
07639          (ofd0 != ast_channel_fd(c0, 0)) ||
07640          (ofd1 != ast_channel_fd(c1, 0)) ||
07641          (p0->subs[SUB_REAL].owner && (os0 > -1) && (os0 != ast_channel_state(p0->subs[SUB_REAL].owner))) ||
07642          (p1->subs[SUB_REAL].owner && (os1 > -1) && (os1 != ast_channel_state(p1->subs[SUB_REAL].owner))) ||
07643          (oc0 != p0->owner) ||
07644          (oc1 != p1->owner) ||
07645          (t0 != p0->subs[SUB_REAL].inthreeway) ||
07646          (t1 != p1->subs[SUB_REAL].inthreeway) ||
07647          (oi0 != i0) ||
07648          (oi1 != i1)) {
07649          ast_debug(1, "Something changed out on %d/%d to %d/%d, returning -3 to restart\n",
07650             op0->channel, oi0, op1->channel, oi1);
07651          res = AST_BRIDGE_RETRY;
07652          goto return_from_bridge;
07653       }
07654 
07655 #ifdef PRI_2BCT
07656       if (!triedtopribridge) {
07657          triedtopribridge = 1;
07658          if (p0->pri && p0->pri == p1->pri && p0->pri->transfer) {
07659             ast_mutex_lock(&p0->pri->lock);
07660             switch (p0->sig) {
07661             case SIG_PRI_LIB_HANDLE_CASES:
07662                q931c0 = ((struct sig_pri_chan *) (p0->sig_pvt))->call;
07663                break;
07664             default:
07665                q931c0 = NULL;
07666                break;
07667             }
07668             switch (p1->sig) {
07669             case SIG_PRI_LIB_HANDLE_CASES:
07670                q931c1 = ((struct sig_pri_chan *) (p1->sig_pvt))->call;
07671                break;
07672             default:
07673                q931c1 = NULL;
07674                break;
07675             }
07676             if (q931c0 && q931c1) {
07677                pri_channel_bridge(q931c0, q931c1);
07678             }
07679             ast_mutex_unlock(&p0->pri->lock);
07680          }
07681       }
07682 #endif
07683 
07684       who = ast_waitfor_n(priority ? c0_priority : c1_priority, 2, &ms);
07685       if (!who) {
07686          ast_debug(1, "Ooh, empty read...\n");
07687          continue;
07688       }
07689       f = ast_read(who);
07690       switch (f ? f->frametype : AST_FRAME_CONTROL) {
07691       case AST_FRAME_CONTROL:
07692          if (f && f->subclass.integer == AST_CONTROL_PVT_CAUSE_CODE) {
07693             ast_channel_hangupcause_hash_set((who == c0) ? c1 : c0, f->data.ptr, f->datalen);
07694             break;
07695          }
07696          *fo = f;
07697          *rc = who;
07698          res = AST_BRIDGE_COMPLETE;
07699          goto return_from_bridge;
07700       case AST_FRAME_DTMF_END:
07701          if ((who == c0) && p0->pulsedial) {
07702             ast_write(c1, f);
07703          } else if ((who == c1) && p1->pulsedial) {
07704             ast_write(c0, f);
07705          } else {
07706             *fo = f;
07707             *rc = who;
07708             res = AST_BRIDGE_COMPLETE;
07709             goto return_from_bridge;
07710          }
07711          break;
07712       case AST_FRAME_TEXT:
07713          if (who == c0) {
07714             ast_write(c1, f);
07715          } else {
07716             ast_write(c0, f);
07717          }
07718          break;
07719       case AST_FRAME_VOICE:
07720          /* Native bridge handles voice frames in hardware. */
07721       case AST_FRAME_NULL:
07722          break;
07723       default:
07724          ast_debug(1, "Chan '%s' is discarding frame of frametype:%u\n",
07725             ast_channel_name(who), f->frametype);
07726          break;
07727       }
07728       ast_frfree(f);
07729 
07730       /* Swap who gets priority */
07731       priority = !priority;
07732    }
07733 
07734 return_from_bridge:
07735    if (op0 == p0)
07736       dahdi_enable_ec(p0);
07737 
07738    if (op1 == p1)
07739       dahdi_enable_ec(p1);
07740 
07741    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
07742       enable_dtmf_detect(op0);
07743 
07744    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
07745       enable_dtmf_detect(op1);
07746 
07747    dahdi_unlink(slave, master, 1);
07748 
07749    return res;
07750 }
07751 
07752 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
07753 {
07754    struct dahdi_pvt *p = ast_channel_tech_pvt(newchan);
07755    int x;
07756 
07757    ast_mutex_lock(&p->lock);
07758 
07759    ast_debug(1, "New owner for channel %d is %s\n", p->channel, ast_channel_name(newchan));
07760    if (p->owner == oldchan) {
07761       p->owner = newchan;
07762    }
07763    for (x = 0; x < 3; x++) {
07764       if (p->subs[x].owner == oldchan) {
07765          if (!x) {
07766             dahdi_unlink(NULL, p, 0);
07767          }
07768          p->subs[x].owner = newchan;
07769       }
07770    }
07771    if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
07772       analog_fixup(oldchan, newchan, p->sig_pvt);
07773 #if defined(HAVE_PRI)
07774    } else if (dahdi_sig_pri_lib_handles(p->sig)) {
07775       sig_pri_fixup(oldchan, newchan, p->sig_pvt);
07776 #endif   /* defined(HAVE_PRI) */
07777 #if defined(HAVE_SS7)
07778    } else if (p->sig == SIG_SS7) {
07779       sig_ss7_fixup(oldchan, newchan, p->sig_pvt);
07780 #endif   /* defined(HAVE_SS7) */
07781    }
07782    update_conf(p);
07783 
07784    ast_mutex_unlock(&p->lock);
07785 
07786    if (ast_channel_state(newchan) == AST_STATE_RINGING) {
07787       dahdi_indicate(newchan, AST_CONTROL_RINGING, NULL, 0);
07788    }
07789    return 0;
07790 }
07791 
07792 static int dahdi_ring_phone(struct dahdi_pvt *p)
07793 {
07794    int x;
07795    int res;
07796    /* Make sure our transmit state is on hook */
07797    x = 0;
07798    x = DAHDI_ONHOOK;
07799    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
07800    do {
07801       x = DAHDI_RING;
07802       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
07803       if (res) {
07804          switch (errno) {
07805          case EBUSY:
07806          case EINTR:
07807             /* Wait just in case */
07808             usleep(10000);
07809             continue;
07810          case EINPROGRESS:
07811             res = 0;
07812             break;
07813          default:
07814             ast_log(LOG_WARNING, "Couldn't ring the phone: %s\n", strerror(errno));
07815             res = 0;
07816          }
07817       }
07818    } while (res);
07819    return res;
07820 }
07821 
07822 static void *analog_ss_thread(void *data);
07823 
07824 static int attempt_transfer(struct dahdi_pvt *p)
07825 {
07826    /* In order to transfer, we need at least one of the channels to
07827       actually be in a call bridge.  We can't conference two applications
07828       together (but then, why would we want to?) */
07829    if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
07830       /* The three-way person we're about to transfer to could still be in MOH, so
07831          stop if now if appropriate */
07832       if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner))
07833          ast_queue_control(p->subs[SUB_THREEWAY].owner, AST_CONTROL_UNHOLD);
07834       if (ast_channel_state(p->subs[SUB_REAL].owner) == AST_STATE_RINGING) {
07835          ast_indicate(ast_bridged_channel(p->subs[SUB_REAL].owner), AST_CONTROL_RINGING);
07836       }
07837       if (ast_channel_state(p->subs[SUB_THREEWAY].owner) == AST_STATE_RING) {
07838          tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE);
07839       }
07840        if (ast_channel_masquerade(p->subs[SUB_THREEWAY].owner, ast_bridged_channel(p->subs[SUB_REAL].owner))) {
07841          ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
07842                ast_channel_name(ast_bridged_channel(p->subs[SUB_REAL].owner)), ast_channel_name(p->subs[SUB_THREEWAY].owner));
07843          return -1;
07844       }
07845       /* Orphan the channel after releasing the lock */
07846       ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
07847       unalloc_sub(p, SUB_THREEWAY);
07848    } else if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
07849       ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
07850       if (ast_channel_state(p->subs[SUB_THREEWAY].owner) == AST_STATE_RINGING) {
07851          ast_indicate(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), AST_CONTROL_RINGING);
07852       }
07853       if (ast_channel_state(p->subs[SUB_REAL].owner) == AST_STATE_RING) {
07854          tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
07855       }
07856       if (ast_channel_masquerade(p->subs[SUB_REAL].owner, ast_bridged_channel(p->subs[SUB_THREEWAY].owner))) {
07857          ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
07858                ast_channel_name(ast_bridged_channel(p->subs[SUB_THREEWAY].owner)), ast_channel_name(p->subs[SUB_REAL].owner));
07859          return -1;
07860       }
07861       /* Three-way is now the REAL */
07862       swap_subs(p, SUB_THREEWAY, SUB_REAL);
07863       ast_channel_unlock(p->subs[SUB_REAL].owner);
07864       unalloc_sub(p, SUB_THREEWAY);
07865       /* Tell the caller not to hangup */
07866       return 1;
07867    } else {
07868       ast_debug(1, "Neither %s nor %s are in a bridge, nothing to transfer\n",
07869          ast_channel_name(p->subs[SUB_REAL].owner), ast_channel_name(p->subs[SUB_THREEWAY].owner));
07870       ast_channel_softhangup_internal_flag_add(p->subs[SUB_THREEWAY].owner, AST_SOFTHANGUP_DEV);
07871       return -1;
07872    }
07873    return 0;
07874 }
07875 
07876 static int check_for_conference(struct dahdi_pvt *p)
07877 {
07878    struct dahdi_confinfo ci;
07879    /* Fine if we already have a master, etc */
07880    if (p->master || (p->confno > -1))
07881       return 0;
07882    memset(&ci, 0, sizeof(ci));
07883    if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
07884       ast_log(LOG_WARNING, "Failed to get conference info on channel %d: %s\n", p->channel, strerror(errno));
07885       return 0;
07886    }
07887    /* If we have no master and don't have a confno, then
07888       if we're in a conference, it's probably a MeetMe room or
07889       some such, so don't let us 3-way out! */
07890    if ((p->subs[SUB_REAL].curconf.confno != ci.confno) || (p->subs[SUB_REAL].curconf.confmode != ci.confmode)) {
07891       ast_verb(3, "Avoiding 3-way call when in an external conference\n");
07892       return 1;
07893    }
07894    return 0;
07895 }
07896 
07897 /*! Checks channel for alarms
07898  * \param p a channel to check for alarms.
07899  * \returns the alarms on the span to which the channel belongs, or alarms on
07900  *          the channel if no span alarms.
07901  */
07902 static int get_alarms(struct dahdi_pvt *p)
07903 {
07904    int res;
07905    struct dahdi_spaninfo zi;
07906    struct dahdi_params params;
07907 
07908    memset(&zi, 0, sizeof(zi));
07909    zi.spanno = p->span;
07910 
07911    if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SPANSTAT, &zi)) >= 0) {
07912       if (zi.alarms != DAHDI_ALARM_NONE)
07913          return zi.alarms;
07914    } else {
07915       ast_log(LOG_WARNING, "Unable to determine alarm on channel %d: %s\n", p->channel, strerror(errno));
07916       return 0;
07917    }
07918 
07919    /* No alarms on the span. Check for channel alarms. */
07920    memset(&params, 0, sizeof(params));
07921    if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &params)) >= 0)
07922       return params.chan_alarms;
07923 
07924    ast_log(LOG_WARNING, "Unable to determine alarm on channel %d\n", p->channel);
07925 
07926    return DAHDI_ALARM_NONE;
07927 }
07928 
07929 static void dahdi_handle_dtmf(struct ast_channel *ast, int idx, struct ast_frame **dest)
07930 {
07931    struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
07932    struct ast_frame *f = *dest;
07933 
07934    ast_debug(1, "%s DTMF digit: 0x%02X '%c' on %s\n",
07935       f->frametype == AST_FRAME_DTMF_BEGIN ? "Begin" : "End",
07936       (unsigned)f->subclass.integer, f->subclass.integer, ast_channel_name(ast));
07937 
07938    if (p->confirmanswer) {
07939       if (f->frametype == AST_FRAME_DTMF_END) {
07940          ast_debug(1, "Confirm answer on %s!\n", ast_channel_name(ast));
07941          /* Upon receiving a DTMF digit, consider this an answer confirmation instead
07942             of a DTMF digit */
07943          p->subs[idx].f.frametype = AST_FRAME_CONTROL;
07944          p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
07945          /* Reset confirmanswer so DTMF's will behave properly for the duration of the call */
07946          p->confirmanswer = 0;
07947       } else {
07948          p->subs[idx].f.frametype = AST_FRAME_NULL;
07949          p->subs[idx].f.subclass.integer = 0;
07950       }
07951       *dest = &p->subs[idx].f;
07952    } else if (p->callwaitcas) {
07953       if (f->frametype == AST_FRAME_DTMF_END) {
07954          if ((f->subclass.integer == 'A') || (f->subclass.integer == 'D')) {
07955             ast_debug(1, "Got some DTMF, but it's for the CAS\n");
07956             ast_free(p->cidspill);
07957             p->cidspill = NULL;
07958             send_cwcidspill(p);
07959          }
07960          p->callwaitcas = 0;
07961       }
07962       p->subs[idx].f.frametype = AST_FRAME_NULL;
07963       p->subs[idx].f.subclass.integer = 0;
07964       *dest = &p->subs[idx].f;
07965    } else if (f->subclass.integer == 'f') {
07966       if (f->frametype == AST_FRAME_DTMF_END) {
07967          /* Fax tone -- Handle and return NULL */
07968          if ((p->callprogress & CALLPROGRESS_FAX) && !p->faxhandled) {
07969             /* If faxbuffers are configured, use them for the fax transmission */
07970             if (p->usefaxbuffers && !p->bufferoverrideinuse) {
07971                struct dahdi_bufferinfo bi = {
07972                   .txbufpolicy = p->faxbuf_policy,
07973                   .bufsize = p->bufsize,
07974                   .numbufs = p->faxbuf_no
07975                };
07976                int res;
07977 
07978                if ((res = ioctl(p->subs[idx].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
07979                   ast_log(LOG_WARNING, "Channel '%s' unable to set buffer policy, reason: %s\n", ast_channel_name(ast), strerror(errno));
07980                } else {
07981                   p->bufferoverrideinuse = 1;
07982                }
07983             }
07984             p->faxhandled = 1;
07985             if (p->dsp) {
07986                p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
07987                ast_dsp_set_features(p->dsp, p->dsp_features);
07988                ast_debug(1, "Disabling FAX tone detection on %s after tone received\n", ast_channel_name(ast));
07989             }
07990             if (strcmp(ast_channel_exten(ast), "fax")) {
07991                const char *target_context = S_OR(ast_channel_macrocontext(ast), ast_channel_context(ast));
07992 
07993                /* We need to unlock 'ast' here because ast_exists_extension has the
07994                 * potential to start autoservice on the channel. Such action is prone
07995                 * to deadlock.
07996                 */
07997                ast_mutex_unlock(&p->lock);
07998                ast_channel_unlock(ast);
07999                if (ast_exists_extension(ast, target_context, "fax", 1,
08000                   S_COR(ast_channel_caller(ast)->id.number.valid, ast_channel_caller(ast)->id.number.str, NULL))) {
08001                   ast_channel_lock(ast);
08002                   ast_mutex_lock(&p->lock);
08003                   ast_verb(3, "Redirecting %s to fax extension\n", ast_channel_name(ast));
08004                   /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
08005                   pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast_channel_exten(ast));
08006                   if (ast_async_goto(ast, target_context, "fax", 1))
08007                      ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast_channel_name(ast), target_context);
08008                } else {
08009                   ast_channel_lock(ast);
08010                   ast_mutex_lock(&p->lock);
08011                   ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
08012                }
08013             } else {
08014                ast_debug(1, "Already in a fax extension, not redirecting\n");
08015             }
08016          } else {
08017             ast_debug(1, "Fax already handled\n");
08018          }
08019          dahdi_confmute(p, 0);
08020       }
08021       p->subs[idx].f.frametype = AST_FRAME_NULL;
08022       p->subs[idx].f.subclass.integer = 0;
08023       *dest = &p->subs[idx].f;
08024    }
08025 }
08026 
08027 static void handle_alarms(struct dahdi_pvt *p, int alms)
08028 {
08029    const char *alarm_str;
08030 
08031 #if defined(HAVE_PRI)
08032    if (dahdi_sig_pri_lib_handles(p->sig) && sig_pri_is_alarm_ignored(p->pri)) {
08033       return;
08034    }
08035 #endif   /* defined(HAVE_PRI) */
08036 
08037    alarm_str = alarm2str(alms);
08038    if (report_alarms & REPORT_CHANNEL_ALARMS) {
08039       ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", p->channel, alarm_str);
08040       /*** DOCUMENTATION
08041          <managerEventInstance>
08042             <synopsis>Raised when an alarm is set on a DAHDI channel.</synopsis>
08043          </managerEventInstance>
08044       ***/
08045       manager_event(EVENT_FLAG_SYSTEM, "Alarm",
08046                  "Alarm: %s\r\n"
08047                  "Channel: %d\r\n",
08048                  alarm_str, p->channel);
08049    }
08050 
08051    if (report_alarms & REPORT_SPAN_ALARMS && p->manages_span_alarms) {
08052       ast_log(LOG_WARNING, "Detected alarm on span %d: %s\n", p->span, alarm_str);
08053       /*** DOCUMENTATION
08054          <managerEventInstance>
08055             <synopsis>Raised when an alarm is set on a DAHDI span.</synopsis>
08056          </managerEventInstance>
08057       ***/
08058       manager_event(EVENT_FLAG_SYSTEM, "SpanAlarm",
08059                  "Alarm: %s\r\n"
08060                  "Span: %d\r\n",
08061                  alarm_str, p->span);
08062    }
08063 }
08064 
08065 static struct ast_frame *dahdi_handle_event(struct ast_channel *ast)
08066 {
08067    int res, x;
08068    int idx, mysig;
08069    char *c;
08070    struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
08071    pthread_t threadid;
08072    struct ast_channel *chan;
08073    struct ast_frame *f;
08074 
08075    idx = dahdi_get_index(ast, p, 0);
08076    if (idx < 0) {
08077       return &ast_null_frame;
08078    }
08079    mysig = p->sig;
08080    if (p->outsigmod > -1)
08081       mysig = p->outsigmod;
08082    p->subs[idx].f.frametype = AST_FRAME_NULL;
08083    p->subs[idx].f.subclass.integer = 0;
08084    p->subs[idx].f.datalen = 0;
08085    p->subs[idx].f.samples = 0;
08086    p->subs[idx].f.mallocd = 0;
08087    p->subs[idx].f.offset = 0;
08088    p->subs[idx].f.src = "dahdi_handle_event";
08089    p->subs[idx].f.data.ptr = NULL;
08090    f = &p->subs[idx].f;
08091 
08092    if (p->fake_event) {
08093       res = p->fake_event;
08094       p->fake_event = 0;
08095    } else
08096       res = dahdi_get_event(p->subs[idx].dfd);
08097 
08098    ast_debug(1, "Got event %s(%d) on channel %d (index %d)\n", event2str(res), res, p->channel, idx);
08099 
08100    if (res & (DAHDI_EVENT_PULSEDIGIT | DAHDI_EVENT_DTMFUP)) {
08101       p->pulsedial = (res & DAHDI_EVENT_PULSEDIGIT) ? 1 : 0;
08102       ast_debug(1, "Detected %sdigit '%c'\n", p->pulsedial ? "pulse ": "", res & 0xff);
08103 #if defined(HAVE_PRI)
08104       if (dahdi_sig_pri_lib_handles(p->sig)
08105          && ((struct sig_pri_chan *) p->sig_pvt)->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING
08106          && p->pri
08107          && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
08108          /* absorb event */
08109       } else
08110 #endif   /* defined(HAVE_PRI) */
08111       {
08112          /* Unmute conference */
08113          dahdi_confmute(p, 0);
08114          p->subs[idx].f.frametype = AST_FRAME_DTMF_END;
08115          p->subs[idx].f.subclass.integer = res & 0xff;
08116          dahdi_handle_dtmf(ast, idx, &f);
08117       }
08118       return f;
08119    }
08120 
08121    if (res & DAHDI_EVENT_DTMFDOWN) {
08122       ast_debug(1, "DTMF Down '%c'\n", res & 0xff);
08123 #if defined(HAVE_PRI)
08124       if (dahdi_sig_pri_lib_handles(p->sig)
08125          && ((struct sig_pri_chan *) p->sig_pvt)->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING
08126          && p->pri
08127          && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
08128          /* absorb event */
08129       } else
08130 #endif   /* defined(HAVE_PRI) */
08131       {
08132          /* Mute conference */
08133          dahdi_confmute(p, 1);
08134          p->subs[idx].f.frametype = AST_FRAME_DTMF_BEGIN;
08135          p->subs[idx].f.subclass.integer = res & 0xff;
08136          dahdi_handle_dtmf(ast, idx, &f);
08137       }
08138       return &p->subs[idx].f;
08139    }
08140 
08141    switch (res) {
08142    case DAHDI_EVENT_EC_DISABLED:
08143       ast_verb(3, "Channel %d echo canceler disabled.\n", p->channel);
08144       p->echocanon = 0;
08145       break;
08146 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
08147    case DAHDI_EVENT_TX_CED_DETECTED:
08148       ast_verb(3, "Channel %d detected a CED tone towards the network.\n", p->channel);
08149       break;
08150    case DAHDI_EVENT_RX_CED_DETECTED:
08151       ast_verb(3, "Channel %d detected a CED tone from the network.\n", p->channel);
08152       break;
08153    case DAHDI_EVENT_EC_NLP_DISABLED:
08154       ast_verb(3, "Channel %d echo canceler disabled its NLP.\n", p->channel);
08155       break;
08156    case DAHDI_EVENT_EC_NLP_ENABLED:
08157       ast_verb(3, "Channel %d echo canceler enabled its NLP.\n", p->channel);
08158       break;
08159 #endif
08160    case DAHDI_EVENT_BITSCHANGED:
08161 #ifdef HAVE_OPENR2
08162       if (p->sig != SIG_MFCR2) {
08163          ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig));
08164       } else {
08165          ast_debug(1, "bits changed in chan %d\n", p->channel);
08166          openr2_chan_handle_cas(p->r2chan);
08167       }
08168 #else
08169       ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig));
08170 #endif
08171       break;
08172    case DAHDI_EVENT_PULSE_START:
08173       /* Stop tone if there's a pulse start and the PBX isn't started */
08174       if (!ast_channel_pbx(ast))
08175          tone_zone_play_tone(p->subs[idx].dfd, -1);
08176       break;
08177    case DAHDI_EVENT_DIALCOMPLETE:
08178       /* DAHDI has completed dialing all digits sent using DAHDI_DIAL. */
08179 #if defined(HAVE_PRI)
08180       if (dahdi_sig_pri_lib_handles(p->sig)) {
08181          if (p->inalarm) {
08182             break;
08183          }
08184          if (ioctl(p->subs[idx].dfd, DAHDI_DIALING, &x) == -1) {
08185             ast_debug(1, "DAHDI_DIALING ioctl failed on %s: %s\n",
08186                ast_channel_name(ast), strerror(errno));
08187             return NULL;
08188          }
08189          if (x) {
08190             /* Still dialing in DAHDI driver */
08191             break;
08192          }
08193          /*
08194           * The ast channel is locked and the private may be locked more
08195           * than once.
08196           */
08197          sig_pri_dial_complete(p->sig_pvt, ast);
08198          break;
08199       }
08200 #endif   /* defined(HAVE_PRI) */
08201 #ifdef HAVE_OPENR2
08202       if ((p->sig & SIG_MFCR2) && p->r2chan && ast_channel_state(ast) != AST_STATE_UP) {
08203          /* we don't need to do anything for this event for R2 signaling
08204             if the call is being setup */
08205          break;
08206       }
08207 #endif
08208       if (p->inalarm) break;
08209       if ((p->radio || (p->oprmode < 0))) break;
08210       if (ioctl(p->subs[idx].dfd,DAHDI_DIALING,&x) == -1) {
08211          ast_debug(1, "DAHDI_DIALING ioctl failed on %s: %s\n",ast_channel_name(ast), strerror(errno));
08212          return NULL;
08213       }
08214       if (!x) { /* if not still dialing in driver */
08215          dahdi_enable_ec(p);
08216          if (p->echobreak) {
08217             dahdi_train_ec(p);
08218             ast_copy_string(p->dop.dialstr, p->echorest, sizeof(p->dop.dialstr));
08219             p->dop.op = DAHDI_DIAL_OP_REPLACE;
08220             res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
08221             p->echobreak = 0;
08222          } else {
08223             p->dialing = 0;
08224             if ((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) {
08225                /* if thru with dialing after offhook */
08226                if (ast_channel_state(ast) == AST_STATE_DIALING_OFFHOOK) {
08227                   ast_setstate(ast, AST_STATE_UP);
08228                   p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08229                   p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
08230                   break;
08231                } else { /* if to state wait for offhook to dial rest */
08232                   /* we now wait for off hook */
08233                   ast_setstate(ast,AST_STATE_DIALING_OFFHOOK);
08234                }
08235             }
08236             if (ast_channel_state(ast) == AST_STATE_DIALING) {
08237                if ((p->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
08238                   ast_debug(1, "Done dialing, but waiting for progress detection before doing more...\n");
08239                } else if (p->confirmanswer || (!p->dialednone
08240                   && ((mysig == SIG_EM) || (mysig == SIG_EM_E1)
08241                      || (mysig == SIG_EMWINK) || (mysig == SIG_FEATD)
08242                      || (mysig == SIG_FEATDMF_TA) || (mysig == SIG_FEATDMF)
08243                      || (mysig == SIG_E911) || (mysig == SIG_FGC_CAMA)
08244                      || (mysig == SIG_FGC_CAMAMF) || (mysig == SIG_FEATB)
08245                      || (mysig == SIG_SF) || (mysig == SIG_SFWINK)
08246                      || (mysig == SIG_SF_FEATD) || (mysig == SIG_SF_FEATDMF)
08247                      || (mysig == SIG_SF_FEATB)))) {
08248                   ast_setstate(ast, AST_STATE_RINGING);
08249                } else if (!p->answeronpolarityswitch) {
08250                   ast_setstate(ast, AST_STATE_UP);
08251                   p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08252                   p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
08253                   /* If aops=0 and hops=1, this is necessary */
08254                   p->polarity = POLARITY_REV;
08255                } else {
08256                   /* Start clean, so we can catch the change to REV polarity when party answers */
08257                   p->polarity = POLARITY_IDLE;
08258                }
08259             }
08260          }
08261       }
08262       break;
08263    case DAHDI_EVENT_ALARM:
08264       switch (p->sig) {
08265 #if defined(HAVE_PRI)
08266       case SIG_PRI_LIB_HANDLE_CASES:
08267          sig_pri_chan_alarm_notify(p->sig_pvt, 0);
08268          break;
08269 #endif   /* defined(HAVE_PRI) */
08270 #if defined(HAVE_SS7)
08271       case SIG_SS7:
08272          sig_ss7_set_alarm(p->sig_pvt, 1);
08273          break;
08274 #endif   /* defined(HAVE_SS7) */
08275       default:
08276          p->inalarm = 1;
08277          break;
08278       }
08279       res = get_alarms(p);
08280       handle_alarms(p, res);
08281 #ifdef HAVE_PRI
08282       if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
08283          /* fall through intentionally */
08284       } else {
08285          break;
08286       }
08287 #endif
08288 #if defined(HAVE_SS7)
08289       if (p->sig == SIG_SS7)
08290          break;
08291 #endif   /* defined(HAVE_SS7) */
08292 #ifdef HAVE_OPENR2
08293       if (p->sig == SIG_MFCR2)
08294          break;
08295 #endif
08296    case DAHDI_EVENT_ONHOOK:
08297       if (p->radio) {
08298          p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08299          p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_UNKEY;
08300          break;
08301       }
08302       if (p->oprmode < 0)
08303       {
08304          if (p->oprmode != -1) break;
08305          if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
08306          {
08307             /* Make sure it starts ringing */
08308             dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
08309             dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RING);
08310             save_conference(p->oprpeer);
08311             tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
08312          }
08313          break;
08314       }
08315       switch (p->sig) {
08316       case SIG_FXOLS:
08317       case SIG_FXOGS:
08318       case SIG_FXOKS:
08319          /* Check for some special conditions regarding call waiting */
08320          if (idx == SUB_REAL) {
08321             /* The normal line was hung up */
08322             if (p->subs[SUB_CALLWAIT].owner) {
08323                /* There's a call waiting call, so ring the phone, but make it unowned in the mean time */
08324                swap_subs(p, SUB_CALLWAIT, SUB_REAL);
08325                ast_verb(3, "Channel %d still has (callwait) call, ringing phone\n", p->channel);
08326                unalloc_sub(p, SUB_CALLWAIT);
08327 #if 0
08328                p->subs[idx].needanswer = 0;
08329                p->subs[idx].needringing = 0;
08330 #endif
08331                p->callwaitingrepeat = 0;
08332                p->cidcwexpire = 0;
08333                p->cid_suppress_expire = 0;
08334                p->owner = NULL;
08335                /* Don't start streaming audio yet if the incoming call isn't up yet */
08336                if (ast_channel_state(p->subs[SUB_REAL].owner) != AST_STATE_UP)
08337                   p->dialing = 1;
08338                dahdi_ring_phone(p);
08339             } else if (p->subs[SUB_THREEWAY].owner) {
08340                unsigned int mssinceflash;
08341                /* Here we have to retain the lock on both the main channel, the 3-way channel, and
08342                   the private structure -- not especially easy or clean */
08343                while (p->subs[SUB_THREEWAY].owner && ast_channel_trylock(p->subs[SUB_THREEWAY].owner)) {
08344                   /* Yuck, didn't get the lock on the 3-way, gotta release everything and re-grab! */
08345                   DLA_UNLOCK(&p->lock);
08346                   CHANNEL_DEADLOCK_AVOIDANCE(ast);
08347                   /* We can grab ast and p in that order, without worry.  We should make sure
08348                      nothing seriously bad has happened though like some sort of bizarre double
08349                      masquerade! */
08350                   DLA_LOCK(&p->lock);
08351                   if (p->owner != ast) {
08352                      ast_log(LOG_WARNING, "This isn't good...\n");
08353                      return NULL;
08354                   }
08355                }
08356                if (!p->subs[SUB_THREEWAY].owner) {
08357                   ast_log(LOG_NOTICE, "Whoa, threeway disappeared kinda randomly.\n");
08358                   return NULL;
08359                }
08360                mssinceflash = ast_tvdiff_ms(ast_tvnow(), p->flashtime);
08361                ast_debug(1, "Last flash was %u ms ago\n", mssinceflash);
08362                if (mssinceflash < MIN_MS_SINCE_FLASH) {
08363                   /* It hasn't been long enough since the last flashook.  This is probably a bounce on
08364                      hanging up.  Hangup both channels now */
08365                   if (p->subs[SUB_THREEWAY].owner)
08366                      ast_queue_hangup_with_cause(p->subs[SUB_THREEWAY].owner, AST_CAUSE_NO_ANSWER);
08367                   ast_channel_softhangup_internal_flag_add(p->subs[SUB_THREEWAY].owner, AST_SOFTHANGUP_DEV);
08368                   ast_debug(1, "Looks like a bounced flash, hanging up both calls on %d\n", p->channel);
08369                   ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08370                } else if ((ast_channel_pbx(ast)) || (ast_channel_state(ast) == AST_STATE_UP)) {
08371                   if (p->transfer) {
08372                      /* In any case this isn't a threeway call anymore */
08373                      p->subs[SUB_REAL].inthreeway = 0;
08374                      p->subs[SUB_THREEWAY].inthreeway = 0;
08375                      /* Only attempt transfer if the phone is ringing; why transfer to busy tone eh? */
08376                      if (!p->transfertobusy && ast_channel_state(ast) == AST_STATE_BUSY) {
08377                         ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08378                         /* Swap subs and dis-own channel */
08379                         swap_subs(p, SUB_THREEWAY, SUB_REAL);
08380                         p->owner = NULL;
08381                         /* Ring the phone */
08382                         dahdi_ring_phone(p);
08383                      } else {
08384                         if ((res = attempt_transfer(p)) < 0) {
08385                            ast_channel_softhangup_internal_flag_add(p->subs[SUB_THREEWAY].owner, AST_SOFTHANGUP_DEV);
08386                            if (p->subs[SUB_THREEWAY].owner)
08387                               ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08388                         } else if (res) {
08389                            /* Don't actually hang up at this point */
08390                            if (p->subs[SUB_THREEWAY].owner)
08391                               ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08392                            break;
08393                         }
08394                      }
08395                   } else {
08396                      ast_channel_softhangup_internal_flag_add(p->subs[SUB_THREEWAY].owner, AST_SOFTHANGUP_DEV);
08397                      if (p->subs[SUB_THREEWAY].owner)
08398                         ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08399                   }
08400                } else {
08401                   ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08402                   /* Swap subs and dis-own channel */
08403                   swap_subs(p, SUB_THREEWAY, SUB_REAL);
08404                   p->owner = NULL;
08405                   /* Ring the phone */
08406                   dahdi_ring_phone(p);
08407                }
08408             }
08409          } else {
08410             ast_log(LOG_WARNING, "Got a hangup and my index is %d?\n", idx);
08411          }
08412          /* Fall through */
08413       default:
08414          dahdi_disable_ec(p);
08415          return NULL;
08416       }
08417       break;
08418    case DAHDI_EVENT_RINGOFFHOOK:
08419       if (p->inalarm) break;
08420       if (p->oprmode < 0)
08421       {
08422          if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
08423          {
08424             /* Make sure it stops ringing */
08425             dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
08426             tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, -1);
08427             restore_conference(p->oprpeer);
08428          }
08429          break;
08430       }
08431       if (p->radio)
08432       {
08433          p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08434          p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_KEY;
08435          break;
08436       }
08437       /* for E911, its supposed to wait for offhook then dial
08438          the second half of the dial string */
08439       if (((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) && (ast_channel_state(ast) == AST_STATE_DIALING_OFFHOOK)) {
08440          c = strchr(p->dialdest, '/');
08441          if (c)
08442             c++;
08443          else
08444             c = p->dialdest;
08445          if (*c) snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*0%s#", c);
08446          else ast_copy_string(p->dop.dialstr,"M*2#", sizeof(p->dop.dialstr));
08447          if (strlen(p->dop.dialstr) > 4) {
08448             memset(p->echorest, 'w', sizeof(p->echorest) - 1);
08449             strcpy(p->echorest + (p->echotraining / 401) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
08450             p->echorest[sizeof(p->echorest) - 1] = '\0';
08451             p->echobreak = 1;
08452             p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
08453          } else
08454             p->echobreak = 0;
08455          if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
08456             int saveerr = errno;
08457 
08458             x = DAHDI_ONHOOK;
08459             ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
08460             ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
08461             return NULL;
08462             }
08463          p->dialing = 1;
08464          return &p->subs[idx].f;
08465       }
08466       switch (p->sig) {
08467       case SIG_FXOLS:
08468       case SIG_FXOGS:
08469       case SIG_FXOKS:
08470          switch (ast_channel_state(ast)) {
08471          case AST_STATE_RINGING:
08472             dahdi_enable_ec(p);
08473             dahdi_train_ec(p);
08474             p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08475             p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
08476             /* Make sure it stops ringing */
08477             p->subs[SUB_REAL].needringing = 0;
08478             dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
08479             ast_debug(1, "channel %d answered\n", p->channel);
08480 
08481             /* Cancel any running CallerID spill */
08482             ast_free(p->cidspill);
08483             p->cidspill = NULL;
08484             restore_conference(p);
08485 
08486             p->dialing = 0;
08487             p->callwaitcas = 0;
08488             if (p->confirmanswer) {
08489                /* Ignore answer if "confirm answer" is enabled */
08490                p->subs[idx].f.frametype = AST_FRAME_NULL;
08491                p->subs[idx].f.subclass.integer = 0;
08492             } else if (!ast_strlen_zero(p->dop.dialstr)) {
08493                /* nick@dccinc.com 4/3/03 - fxo should be able to do deferred dialing */
08494                res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
08495                if (res < 0) {
08496                   ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
08497                   p->dop.dialstr[0] = '\0';
08498                   return NULL;
08499                } else {
08500                   ast_debug(1, "Sent FXO deferred digit string: %s\n", p->dop.dialstr);
08501                   p->subs[idx].f.frametype = AST_FRAME_NULL;
08502                   p->subs[idx].f.subclass.integer = 0;
08503                   p->dialing = 1;
08504                }
08505                p->dop.dialstr[0] = '\0';
08506                ast_setstate(ast, AST_STATE_DIALING);
08507             } else
08508                ast_setstate(ast, AST_STATE_UP);
08509             return &p->subs[idx].f;
08510          case AST_STATE_DOWN:
08511             ast_setstate(ast, AST_STATE_RING);
08512             ast_channel_rings_set(ast, 1);
08513             p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08514             p->subs[idx].f.subclass.integer = AST_CONTROL_OFFHOOK;
08515             ast_debug(1, "channel %d picked up\n", p->channel);
08516             return &p->subs[idx].f;
08517          case AST_STATE_UP:
08518             /* Make sure it stops ringing */
08519             dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
08520             /* Okay -- probably call waiting*/
08521             if (ast_bridged_channel(p->owner))
08522                ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
08523             p->subs[idx].needunhold = 1;
08524             break;
08525          case AST_STATE_RESERVED:
08526             /* Start up dialtone */
08527             if (has_voicemail(p))
08528                res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
08529             else
08530                res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
08531             break;
08532          default:
08533             ast_log(LOG_WARNING, "FXO phone off hook in weird state %u??\n", ast_channel_state(ast));
08534          }
08535          break;
08536       case SIG_FXSLS:
08537       case SIG_FXSGS:
08538       case SIG_FXSKS:
08539          if (ast_channel_state(ast) == AST_STATE_RING) {
08540             p->ringt = p->ringt_base;
08541          }
08542 
08543          /* If we get a ring then we cannot be in
08544           * reversed polarity. So we reset to idle */
08545          ast_debug(1, "Setting IDLE polarity due "
08546             "to ring. Old polarity was %d\n",
08547             p->polarity);
08548          p->polarity = POLARITY_IDLE;
08549 
08550          /* Fall through */
08551       case SIG_EM:
08552       case SIG_EM_E1:
08553       case SIG_EMWINK:
08554       case SIG_FEATD:
08555       case SIG_FEATDMF:
08556       case SIG_FEATDMF_TA:
08557       case SIG_E911:
08558       case SIG_FGC_CAMA:
08559       case SIG_FGC_CAMAMF:
08560       case SIG_FEATB:
08561       case SIG_SF:
08562       case SIG_SFWINK:
08563       case SIG_SF_FEATD:
08564       case SIG_SF_FEATDMF:
08565       case SIG_SF_FEATB:
08566          if (ast_channel_state(ast) == AST_STATE_PRERING)
08567             ast_setstate(ast, AST_STATE_RING);
08568          if ((ast_channel_state(ast) == AST_STATE_DOWN) || (ast_channel_state(ast) == AST_STATE_RING)) {
08569             ast_debug(1, "Ring detected\n");
08570             p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08571             p->subs[idx].f.subclass.integer = AST_CONTROL_RING;
08572          } else if (p->outgoing && ((ast_channel_state(ast) == AST_STATE_RINGING) || (ast_channel_state(ast) == AST_STATE_DIALING))) {
08573             ast_debug(1, "Line answered\n");
08574             if (p->confirmanswer) {
08575                p->subs[idx].f.frametype = AST_FRAME_NULL;
08576                p->subs[idx].f.subclass.integer = 0;
08577             } else {
08578                p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08579                p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
08580                ast_setstate(ast, AST_STATE_UP);
08581             }
08582          } else if (ast_channel_state(ast) != AST_STATE_RING)
08583             ast_log(LOG_WARNING, "Ring/Off-hook in strange state %u on channel %d\n", ast_channel_state(ast), p->channel);
08584          break;
08585       default:
08586          ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
08587       }
08588       break;
08589    case DAHDI_EVENT_RINGBEGIN:
08590       switch (p->sig) {
08591       case SIG_FXSLS:
08592       case SIG_FXSGS:
08593       case SIG_FXSKS:
08594          if (ast_channel_state(ast) == AST_STATE_RING) {
08595             p->ringt = p->ringt_base;
08596          }
08597          break;
08598       }
08599       break;
08600    case DAHDI_EVENT_RINGERON:
08601       break;
08602    case DAHDI_EVENT_NOALARM:
08603       switch (p->sig) {
08604 #if defined(HAVE_PRI)
08605       case SIG_PRI_LIB_HANDLE_CASES:
08606          sig_pri_chan_alarm_notify(p->sig_pvt, 1);
08607          break;
08608 #endif   /* defined(HAVE_PRI) */
08609 #if defined(HAVE_SS7)
08610       case SIG_SS7:
08611          sig_ss7_set_alarm(p->sig_pvt, 0);
08612          break;
08613 #endif   /* defined(HAVE_SS7) */
08614       default:
08615          p->inalarm = 0;
08616          break;
08617       }
08618       handle_clear_alarms(p);
08619       break;
08620    case DAHDI_EVENT_WINKFLASH:
08621       if (p->inalarm) break;
08622       if (p->radio) break;
08623       if (p->oprmode < 0) break;
08624       if (p->oprmode > 1)
08625       {
08626          struct dahdi_params par;
08627 
08628          memset(&par, 0, sizeof(par));
08629          if (ioctl(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par) != -1)
08630          {
08631             if (!par.rxisoffhook)
08632             {
08633                /* Make sure it stops ringing */
08634                dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
08635                dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RING);
08636                save_conference(p);
08637                tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
08638             }
08639          }
08640          break;
08641       }
08642       /* Remember last time we got a flash-hook */
08643       p->flashtime = ast_tvnow();
08644       switch (mysig) {
08645       case SIG_FXOLS:
08646       case SIG_FXOGS:
08647       case SIG_FXOKS:
08648          ast_debug(1, "Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n",
08649             idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
08650 
08651          /* Cancel any running CallerID spill */
08652          ast_free(p->cidspill);
08653          p->cidspill = NULL;
08654          restore_conference(p);
08655          p->callwaitcas = 0;
08656 
08657          if (idx != SUB_REAL) {
08658             ast_log(LOG_WARNING, "Got flash hook with index %d on channel %d?!?\n", idx, p->channel);
08659             goto winkflashdone;
08660          }
08661 
08662          if (p->subs[SUB_CALLWAIT].owner) {
08663             /* Swap to call-wait */
08664             swap_subs(p, SUB_REAL, SUB_CALLWAIT);
08665             tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
08666             p->owner = p->subs[SUB_REAL].owner;
08667             ast_debug(1, "Making %s the new owner\n", ast_channel_name(p->owner));
08668             if (ast_channel_state(p->owner) == AST_STATE_RINGING) {
08669                ast_setstate(p->owner, AST_STATE_UP);
08670                p->subs[SUB_REAL].needanswer = 1;
08671             }
08672             p->callwaitingrepeat = 0;
08673             p->cidcwexpire = 0;
08674             p->cid_suppress_expire = 0;
08675             /* Start music on hold if appropriate */
08676             if (!p->subs[SUB_CALLWAIT].inthreeway && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
08677                ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
08678                   S_OR(p->mohsuggest, NULL),
08679                   !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
08680             }
08681             p->subs[SUB_CALLWAIT].needhold = 1;
08682             if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
08683                ast_queue_control_data(p->subs[SUB_REAL].owner, AST_CONTROL_HOLD,
08684                   S_OR(p->mohsuggest, NULL),
08685                   !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
08686             }
08687             p->subs[SUB_REAL].needunhold = 1;
08688          } else if (!p->subs[SUB_THREEWAY].owner) {
08689             if (!p->threewaycalling) {
08690                /* Just send a flash if no 3-way calling */
08691                p->subs[SUB_REAL].needflash = 1;
08692                goto winkflashdone;
08693             } else if (!check_for_conference(p)) {
08694                struct ast_callid *callid = NULL;
08695                int callid_created;
08696                char cid_num[256];
08697                char cid_name[256];
08698 
08699                cid_num[0] = 0;
08700                cid_name[0] = 0;
08701                if (p->dahditrcallerid && p->owner) {
08702                   if (ast_channel_caller(p->owner)->id.number.valid
08703                      && ast_channel_caller(p->owner)->id.number.str) {
08704                      ast_copy_string(cid_num, ast_channel_caller(p->owner)->id.number.str,
08705                         sizeof(cid_num));
08706                   }
08707                   if (ast_channel_caller(p->owner)->id.name.valid
08708                      && ast_channel_caller(p->owner)->id.name.str) {
08709                      ast_copy_string(cid_name, ast_channel_caller(p->owner)->id.name.str,
08710                         sizeof(cid_name));
08711                   }
08712                }
08713                /* XXX This section needs much more error checking!!! XXX */
08714                /* Start a 3-way call if feasible */
08715                if (!((ast_channel_pbx(ast)) ||
08716                   (ast_channel_state(ast) == AST_STATE_UP) ||
08717                   (ast_channel_state(ast) == AST_STATE_RING))) {
08718                   ast_debug(1, "Flash when call not up or ringing\n");
08719                   goto winkflashdone;
08720                }
08721                if (alloc_sub(p, SUB_THREEWAY)) {
08722                   ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n");
08723                   goto winkflashdone;
08724                }
08725                callid_created = ast_callid_threadstorage_auto(&callid);
08726                /*
08727                 * Make new channel
08728                 *
08729                 * We cannot hold the p or ast locks while creating a new
08730                 * channel.
08731                 */
08732                ast_mutex_unlock(&p->lock);
08733                ast_channel_unlock(ast);
08734                chan = dahdi_new(p, AST_STATE_RESERVED, 0, SUB_THREEWAY, 0, NULL, callid);
08735                ast_channel_lock(ast);
08736                ast_mutex_lock(&p->lock);
08737                if (p->dahditrcallerid) {
08738                   if (!p->origcid_num)
08739                      p->origcid_num = ast_strdup(p->cid_num);
08740                   if (!p->origcid_name)
08741                      p->origcid_name = ast_strdup(p->cid_name);
08742                   ast_copy_string(p->cid_num, cid_num, sizeof(p->cid_num));
08743                   ast_copy_string(p->cid_name, cid_name, sizeof(p->cid_name));
08744                }
08745                /* Swap things around between the three-way and real call */
08746                swap_subs(p, SUB_THREEWAY, SUB_REAL);
08747                /* Disable echo canceller for better dialing */
08748                dahdi_disable_ec(p);
08749                res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALRECALL);
08750                if (res)
08751                   ast_log(LOG_WARNING, "Unable to start dial recall tone on channel %d\n", p->channel);
08752                p->owner = chan;
08753                if (!chan) {
08754                   ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", p->channel);
08755                } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
08756                   ast_log(LOG_WARNING, "Unable to start simple switch on channel %d\n", p->channel);
08757                   res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
08758                   dahdi_enable_ec(p);
08759                   ast_hangup(chan);
08760                } else {
08761                   ast_verb(3, "Started three way call on channel %d\n", p->channel);
08762 
08763                   /* Start music on hold if appropriate */
08764                   if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
08765                      ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
08766                         S_OR(p->mohsuggest, NULL),
08767                         !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
08768                   }
08769                   p->subs[SUB_THREEWAY].needhold = 1;
08770                }
08771                ast_callid_threadstorage_auto_clean(callid, callid_created);
08772             }
08773          } else {
08774             /* Already have a 3 way call */
08775             if (p->subs[SUB_THREEWAY].inthreeway) {
08776                /* Call is already up, drop the last person */
08777                ast_debug(1, "Got flash with three way call up, dropping last call on %d\n", p->channel);
08778                /* If the primary call isn't answered yet, use it */
08779                if ((ast_channel_state(p->subs[SUB_REAL].owner) != AST_STATE_UP) && (ast_channel_state(p->subs[SUB_THREEWAY].owner) == AST_STATE_UP)) {
08780                   /* Swap back -- we're dropping the real 3-way that isn't finished yet*/
08781                   swap_subs(p, SUB_THREEWAY, SUB_REAL);
08782                   p->owner = p->subs[SUB_REAL].owner;
08783                }
08784                /* Drop the last call and stop the conference */
08785                ast_verb(3, "Dropping three-way call on %s\n", ast_channel_name(p->subs[SUB_THREEWAY].owner));
08786                ast_channel_softhangup_internal_flag_add(p->subs[SUB_THREEWAY].owner, AST_SOFTHANGUP_DEV);
08787                p->subs[SUB_REAL].inthreeway = 0;
08788                p->subs[SUB_THREEWAY].inthreeway = 0;
08789             } else {
08790                /* Lets see what we're up to */
08791                if (((ast_channel_pbx(ast)) || (ast_channel_state(ast) == AST_STATE_UP)) &&
08792                   (p->transfertobusy || (ast_channel_state(ast) != AST_STATE_BUSY))) {
08793                   int otherindex = SUB_THREEWAY;
08794 
08795                   ast_verb(3, "Building conference call with %s and %s\n",
08796                      ast_channel_name(p->subs[SUB_THREEWAY].owner),
08797                      ast_channel_name(p->subs[SUB_REAL].owner));
08798                   /* Put them in the threeway, and flip */
08799                   p->subs[SUB_THREEWAY].inthreeway = 1;
08800                   p->subs[SUB_REAL].inthreeway = 1;
08801                   if (ast_channel_state(ast) == AST_STATE_UP) {
08802                      swap_subs(p, SUB_THREEWAY, SUB_REAL);
08803                      otherindex = SUB_REAL;
08804                   }
08805                   if (p->subs[otherindex].owner && ast_bridged_channel(p->subs[otherindex].owner))
08806                      ast_queue_control(p->subs[otherindex].owner, AST_CONTROL_UNHOLD);
08807                   p->subs[otherindex].needunhold = 1;
08808                   p->owner = p->subs[SUB_REAL].owner;
08809                } else {
08810                   ast_verb(3, "Dumping incomplete call on on %s\n", ast_channel_name(p->subs[SUB_THREEWAY].owner));
08811                   swap_subs(p, SUB_THREEWAY, SUB_REAL);
08812                   ast_channel_softhangup_internal_flag_add(p->subs[SUB_THREEWAY].owner, AST_SOFTHANGUP_DEV);
08813                   p->owner = p->subs[SUB_REAL].owner;
08814                   if (p->subs[SUB_REAL].owner && ast_bridged_channel(p->subs[SUB_REAL].owner))
08815                      ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
08816                   p->subs[SUB_REAL].needunhold = 1;
08817                   dahdi_enable_ec(p);
08818                }
08819             }
08820          }
08821 winkflashdone:
08822          update_conf(p);
08823          break;
08824       case SIG_EM:
08825       case SIG_EM_E1:
08826       case SIG_FEATD:
08827       case SIG_SF:
08828       case SIG_SFWINK:
08829       case SIG_SF_FEATD:
08830       case SIG_FXSLS:
08831       case SIG_FXSGS:
08832          if (p->dialing)
08833             ast_debug(1, "Ignoring wink on channel %d\n", p->channel);
08834          else
08835             ast_debug(1, "Got wink in weird state %u on channel %d\n", ast_channel_state(ast), p->channel);
08836          break;
08837       case SIG_FEATDMF_TA:
08838          switch (p->whichwink) {
08839          case 0:
08840             ast_debug(1, "ANI2 set to '%d' and ANI is '%s'\n", ast_channel_caller(p->owner)->ani2,
08841                S_COR(ast_channel_caller(p->owner)->ani.number.valid,
08842                   ast_channel_caller(p->owner)->ani.number.str, ""));
08843             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%d%s#",
08844                ast_channel_caller(p->owner)->ani2,
08845                S_COR(ast_channel_caller(p->owner)->ani.number.valid,
08846                   ast_channel_caller(p->owner)->ani.number.str, ""));
08847             break;
08848          case 1:
08849             ast_copy_string(p->dop.dialstr, p->finaldial, sizeof(p->dop.dialstr));
08850             break;
08851          case 2:
08852             ast_log(LOG_WARNING, "Received unexpected wink on channel of type SIG_FEATDMF_TA\n");
08853             return NULL;
08854          }
08855          p->whichwink++;
08856          /* Fall through */
08857       case SIG_FEATDMF:
08858       case SIG_E911:
08859       case SIG_FGC_CAMAMF:
08860       case SIG_FGC_CAMA:
08861       case SIG_FEATB:
08862       case SIG_SF_FEATDMF:
08863       case SIG_SF_FEATB:
08864       case SIG_EMWINK:
08865          /* FGD MF and EMWINK *Must* wait for wink */
08866          if (!ast_strlen_zero(p->dop.dialstr)) {
08867             res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
08868             if (res < 0) {
08869                ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
08870                p->dop.dialstr[0] = '\0';
08871                return NULL;
08872             } else
08873                ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
08874          }
08875          p->dop.dialstr[0] = '\0';
08876          break;
08877       default:
08878          ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
08879       }
08880       break;
08881    case DAHDI_EVENT_HOOKCOMPLETE:
08882       if (p->inalarm) break;
08883       if ((p->radio || (p->oprmode < 0))) break;
08884       if (p->waitingfordt.tv_sec) break;
08885       switch (mysig) {
08886       case SIG_FXSLS:  /* only interesting for FXS */
08887       case SIG_FXSGS:
08888       case SIG_FXSKS:
08889       case SIG_EM:
08890       case SIG_EM_E1:
08891       case SIG_EMWINK:
08892       case SIG_FEATD:
08893       case SIG_SF:
08894       case SIG_SFWINK:
08895       case SIG_SF_FEATD:
08896          if (!ast_strlen_zero(p->dop.dialstr)) {
08897             res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
08898             if (res < 0) {
08899                ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
08900                p->dop.dialstr[0] = '\0';
08901                return NULL;
08902             } else
08903                ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
08904          }
08905          p->dop.dialstr[0] = '\0';
08906          p->dop.op = DAHDI_DIAL_OP_REPLACE;
08907          break;
08908       case SIG_FEATDMF:
08909       case SIG_FEATDMF_TA:
08910       case SIG_E911:
08911       case SIG_FGC_CAMA:
08912       case SIG_FGC_CAMAMF:
08913       case SIG_FEATB:
08914       case SIG_SF_FEATDMF:
08915       case SIG_SF_FEATB:
08916          ast_debug(1, "Got hook complete in MF FGD, waiting for wink now on channel %d\n",p->channel);
08917          break;
08918       default:
08919          break;
08920       }
08921       break;
08922    case DAHDI_EVENT_POLARITY:
08923       /*
08924        * If we get a Polarity Switch event, check to see
08925        * if we should change the polarity state and
08926        * mark the channel as UP or if this is an indication
08927        * of remote end disconnect.
08928        */
08929       if (p->polarity == POLARITY_IDLE) {
08930          p->polarity = POLARITY_REV;
08931          if (p->answeronpolarityswitch &&
08932             ((ast_channel_state(ast) == AST_STATE_DIALING) ||
08933             (ast_channel_state(ast) == AST_STATE_RINGING))) {
08934             ast_debug(1, "Answering on polarity switch!\n");
08935             ast_setstate(p->owner, AST_STATE_UP);
08936             if (p->hanguponpolarityswitch) {
08937                p->polaritydelaytv = ast_tvnow();
08938             }
08939          } else
08940             ast_debug(1, "Ignore switch to REVERSED Polarity on channel %d, state %u\n", p->channel, ast_channel_state(ast));
08941       }
08942       /* Removed else statement from here as it was preventing hangups from ever happening*/
08943       /* Added AST_STATE_RING in if statement below to deal with calling party hangups that take place when ringing */
08944       if (p->hanguponpolarityswitch &&
08945          (p->polarityonanswerdelay > 0) &&
08946          (p->polarity == POLARITY_REV) &&
08947          ((ast_channel_state(ast) == AST_STATE_UP) || (ast_channel_state(ast) == AST_STATE_RING)) ) {
08948          /* Added log_debug information below to provide a better indication of what is going on */
08949          ast_debug(1, "Polarity Reversal event occured - DEBUG 1: channel %d, state %u, pol= %d, aonp= %d, honp= %d, pdelay= %d, tv= %" PRIi64 "\n", p->channel, ast_channel_state(ast), p->polarity, p->answeronpolarityswitch, p->hanguponpolarityswitch, p->polarityonanswerdelay, ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) );
08950 
08951          if (ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) > p->polarityonanswerdelay) {
08952             ast_debug(1, "Polarity Reversal detected and now Hanging up on channel %d\n", p->channel);
08953             ast_softhangup(p->owner, AST_SOFTHANGUP_EXPLICIT);
08954             p->polarity = POLARITY_IDLE;
08955          } else
08956             ast_debug(1, "Polarity Reversal detected but NOT hanging up (too close to answer event) on channel %d, state %u\n", p->channel, ast_channel_state(ast));
08957 
08958       } else {
08959          p->polarity = POLARITY_IDLE;
08960          ast_debug(1, "Ignoring Polarity switch to IDLE on channel %d, state %u\n", p->channel, ast_channel_state(ast));
08961       }
08962       /* Added more log_debug information below to provide a better indication of what is going on */
08963       ast_debug(1, "Polarity Reversal event occured - DEBUG 2: channel %d, state %u, pol= %d, aonp= %d, honp= %d, pdelay= %d, tv= %" PRIi64 "\n", p->channel, ast_channel_state(ast), p->polarity, p->answeronpolarityswitch, p->hanguponpolarityswitch, p->polarityonanswerdelay, ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) );
08964       break;
08965    default:
08966       ast_debug(1, "Dunno what to do with event %d on channel %d\n", res, p->channel);
08967    }
08968    return &p->subs[idx].f;
08969 }
08970 
08971 static struct ast_frame *__dahdi_exception(struct ast_channel *ast)
08972 {
08973    int res;
08974    int idx;
08975    struct ast_frame *f;
08976    int usedindex = -1;
08977    struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
08978 
08979    if ((idx = dahdi_get_index(ast, p, 0)) < 0) {
08980       idx = SUB_REAL;
08981    }
08982 
08983    p->subs[idx].f.frametype = AST_FRAME_NULL;
08984    p->subs[idx].f.datalen = 0;
08985    p->subs[idx].f.samples = 0;
08986    p->subs[idx].f.mallocd = 0;
08987    p->subs[idx].f.offset = 0;
08988    p->subs[idx].f.subclass.integer = 0;
08989    p->subs[idx].f.delivery = ast_tv(0,0);
08990    p->subs[idx].f.src = "dahdi_exception";
08991    p->subs[idx].f.data.ptr = NULL;
08992 
08993 
08994    if ((!p->owner) && (!(p->radio || (p->oprmode < 0)))) {
08995       /* If nobody owns us, absorb the event appropriately, otherwise
08996          we loop indefinitely.  This occurs when, during call waiting, the
08997          other end hangs up our channel so that it no longer exists, but we
08998          have neither FLASH'd nor ONHOOK'd to signify our desire to
08999          change to the other channel. */
09000       if (p->fake_event) {
09001          res = p->fake_event;
09002          p->fake_event = 0;
09003       } else
09004          res = dahdi_get_event(p->subs[SUB_REAL].dfd);
09005       /* Switch to real if there is one and this isn't something really silly... */
09006       if ((res != DAHDI_EVENT_RINGEROFF) && (res != DAHDI_EVENT_RINGERON) &&
09007          (res != DAHDI_EVENT_HOOKCOMPLETE)) {
09008          ast_debug(1, "Restoring owner of channel %d on event %d\n", p->channel, res);
09009          p->owner = p->subs[SUB_REAL].owner;
09010          if (p->owner && ast_bridged_channel(p->owner))
09011             ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
09012          p->subs[SUB_REAL].needunhold = 1;
09013       }
09014       switch (res) {
09015       case DAHDI_EVENT_ONHOOK:
09016          dahdi_disable_ec(p);
09017          if (p->owner) {
09018             ast_verb(3, "Channel %s still has call, ringing phone\n", ast_channel_name(p->owner));
09019             dahdi_ring_phone(p);
09020             p->callwaitingrepeat = 0;
09021             p->cidcwexpire = 0;
09022             p->cid_suppress_expire = 0;
09023          } else
09024             ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
09025          update_conf(p);
09026          break;
09027       case DAHDI_EVENT_RINGOFFHOOK:
09028          dahdi_enable_ec(p);
09029          dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
09030          if (p->owner && (ast_channel_state(p->owner) == AST_STATE_RINGING)) {
09031             p->subs[SUB_REAL].needanswer = 1;
09032             p->dialing = 0;
09033          }
09034          break;
09035       case DAHDI_EVENT_HOOKCOMPLETE:
09036       case DAHDI_EVENT_RINGERON:
09037       case DAHDI_EVENT_RINGEROFF:
09038          /* Do nothing */
09039          break;
09040       case DAHDI_EVENT_WINKFLASH:
09041          p->flashtime = ast_tvnow();
09042          if (p->owner) {
09043             ast_verb(3, "Channel %d flashed to other channel %s\n", p->channel, ast_channel_name(p->owner));
09044             if (ast_channel_state(p->owner) != AST_STATE_UP) {
09045                /* Answer if necessary */
09046                usedindex = dahdi_get_index(p->owner, p, 0);
09047                if (usedindex > -1) {
09048                   p->subs[usedindex].needanswer = 1;
09049                }
09050                ast_setstate(p->owner, AST_STATE_UP);
09051             }
09052             p->callwaitingrepeat = 0;
09053             p->cidcwexpire = 0;
09054             p->cid_suppress_expire = 0;
09055             if (ast_bridged_channel(p->owner))
09056                ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
09057             p->subs[SUB_REAL].needunhold = 1;
09058          } else
09059             ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
09060          update_conf(p);
09061          break;
09062       default:
09063          ast_log(LOG_WARNING, "Don't know how to absorb event %s\n", event2str(res));
09064       }
09065       f = &p->subs[idx].f;
09066       return f;
09067    }
09068    if (!(p->radio || (p->oprmode < 0)))
09069       ast_debug(1, "Exception on %d, channel %d\n", ast_channel_fd(ast, 0), p->channel);
09070    /* If it's not us, return NULL immediately */
09071    if (ast != p->owner) {
09072       if (p->owner) {
09073          ast_log(LOG_WARNING, "We're %s, not %s\n", ast_channel_name(ast), ast_channel_name(p->owner));
09074       }
09075       f = &p->subs[idx].f;
09076       return f;
09077    }
09078 
09079    f = dahdi_handle_event(ast);
09080    if (!f) {
09081       const char *name = ast_strdupa(ast_channel_name(ast));
09082 
09083       /* Tell the CDR this DAHDI device hung up */
09084       ast_mutex_unlock(&p->lock);
09085       ast_channel_unlock(ast);
09086       ast_set_hangupsource(ast, name, 0);
09087       ast_channel_lock(ast);
09088       ast_mutex_lock(&p->lock);
09089    }
09090    return f;
09091 }
09092 
09093 static struct ast_frame *dahdi_exception(struct ast_channel *ast)
09094 {
09095    struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
09096    struct ast_frame *f;
09097    ast_mutex_lock(&p->lock);
09098    if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
09099       struct analog_pvt *analog_p = p->sig_pvt;
09100       f = analog_exception(analog_p, ast);
09101    } else {
09102       f = __dahdi_exception(ast);
09103    }
09104    ast_mutex_unlock(&p->lock);
09105    return f;
09106 }
09107 
09108 static struct ast_frame *dahdi_read(struct ast_channel *ast)
09109 {
09110    struct dahdi_pvt *p;
09111    int res;
09112    int idx;
09113    void *readbuf;
09114    struct ast_frame *f;
09115 
09116    /*
09117     * For analog channels, we must do deadlock avoidance because
09118     * analog ports can have more than one Asterisk channel using
09119     * the same private structure.
09120     */
09121    p = ast_channel_tech_pvt(ast);
09122    while (ast_mutex_trylock(&p->lock)) {
09123       CHANNEL_DEADLOCK_AVOIDANCE(ast);
09124 
09125       /*
09126        * Check to see if the channel is still associated with the same
09127        * private structure.  While the Asterisk channel was unlocked
09128        * the following events may have occured:
09129        *
09130        * 1) A masquerade may have associated the channel with another
09131        * technology or private structure.
09132        *
09133        * 2) For PRI calls, call signaling could change the channel
09134        * association to another B channel (private structure).
09135        */
09136       if (ast_channel_tech_pvt(ast) != p) {
09137          /* The channel is no longer associated.  Quit gracefully. */
09138          return &ast_null_frame;
09139       }
09140    }
09141 
09142    idx = dahdi_get_index(ast, p, 0);
09143 
09144    /* Hang up if we don't really exist */
09145    if (idx < 0)   {
09146       ast_log(LOG_WARNING, "We don't exist?\n");
09147       ast_mutex_unlock(&p->lock);
09148       return NULL;
09149    }
09150 
09151    if ((p->radio || (p->oprmode < 0)) && p->inalarm) {
09152       ast_mutex_unlock(&p->lock);
09153       return NULL;
09154    }
09155 
09156    p->subs[idx].f.frametype = AST_FRAME_NULL;
09157    p->subs[idx].f.datalen = 0;
09158    p->subs[idx].f.samples = 0;
09159    p->subs[idx].f.mallocd = 0;
09160    p->subs[idx].f.offset = 0;
09161    p->subs[idx].f.subclass.integer = 0;
09162    p->subs[idx].f.delivery = ast_tv(0,0);
09163    p->subs[idx].f.src = "dahdi_read";
09164    p->subs[idx].f.data.ptr = NULL;
09165 
09166    /* make sure it sends initial key state as first frame */
09167    if ((p->radio || (p->oprmode < 0)) && (!p->firstradio))
09168    {
09169       struct dahdi_params ps;
09170 
09171       memset(&ps, 0, sizeof(ps));
09172       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
09173          ast_mutex_unlock(&p->lock);
09174          return NULL;
09175       }
09176       p->firstradio = 1;
09177       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09178       if (ps.rxisoffhook)
09179       {
09180          p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_KEY;
09181       }
09182       else
09183       {
09184          p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_UNKEY;
09185       }
09186       ast_mutex_unlock(&p->lock);
09187       return &p->subs[idx].f;
09188    }
09189    if (p->ringt > 0) {
09190       if (!(--p->ringt)) {
09191          ast_mutex_unlock(&p->lock);
09192          return NULL;
09193       }
09194    }
09195 
09196 #ifdef HAVE_OPENR2
09197    if (p->mfcr2) {
09198       openr2_chan_process_event(p->r2chan);
09199       if (OR2_DIR_FORWARD == openr2_chan_get_direction(p->r2chan)) {
09200          struct ast_frame fr = { AST_FRAME_CONTROL, { AST_CONTROL_PROGRESS } };
09201          /* if the call is already accepted and we already delivered AST_CONTROL_RINGING
09202           * now enqueue a progress frame to bridge the media up */
09203          if (p->mfcr2_call_accepted &&
09204             !p->mfcr2_progress_sent && 
09205             ast_channel_state(ast) == AST_STATE_RINGING) {
09206             ast_debug(1, "Enqueuing progress frame after R2 accept in chan %d\n", p->channel);
09207             ast_queue_frame(p->owner, &fr);
09208             p->mfcr2_progress_sent = 1;
09209          }
09210       }
09211    }
09212 #endif
09213 
09214    if (p->subs[idx].needringing) {
09215       /* Send ringing frame if requested */
09216       p->subs[idx].needringing = 0;
09217       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09218       p->subs[idx].f.subclass.integer = AST_CONTROL_RINGING;
09219       ast_setstate(ast, AST_STATE_RINGING);
09220       ast_mutex_unlock(&p->lock);
09221       return &p->subs[idx].f;
09222    }
09223 
09224    if (p->subs[idx].needbusy) {
09225       /* Send busy frame if requested */
09226       p->subs[idx].needbusy = 0;
09227       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09228       p->subs[idx].f.subclass.integer = AST_CONTROL_BUSY;
09229       ast_mutex_unlock(&p->lock);
09230       return &p->subs[idx].f;
09231    }
09232 
09233    if (p->subs[idx].needcongestion) {
09234       /* Send congestion frame if requested */
09235       p->subs[idx].needcongestion = 0;
09236       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09237       p->subs[idx].f.subclass.integer = AST_CONTROL_CONGESTION;
09238       ast_mutex_unlock(&p->lock);
09239       return &p->subs[idx].f;
09240    }
09241 
09242    if (p->subs[idx].needanswer) {
09243       /* Send answer frame if requested */
09244       p->subs[idx].needanswer = 0;
09245       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09246       p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
09247       ast_mutex_unlock(&p->lock);
09248       return &p->subs[idx].f;
09249    }
09250 #ifdef HAVE_OPENR2
09251    if (p->mfcr2 && openr2_chan_get_read_enabled(p->r2chan)) {
09252       /* openr2 took care of reading and handling any event
09253         (needanswer, needbusy etc), if we continue we will read()
09254         twice, lets just return a null frame. This should only
09255         happen when openr2 is dialing out */
09256       ast_mutex_unlock(&p->lock);
09257       return &ast_null_frame;
09258    }
09259 #endif
09260 
09261    if (p->subs[idx].needflash) {
09262       /* Send answer frame if requested */
09263       p->subs[idx].needflash = 0;
09264       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09265       p->subs[idx].f.subclass.integer = AST_CONTROL_FLASH;
09266       ast_mutex_unlock(&p->lock);
09267       return &p->subs[idx].f;
09268    }
09269 
09270    if (p->subs[idx].needhold) {
09271       /* Send answer frame if requested */
09272       p->subs[idx].needhold = 0;
09273       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09274       p->subs[idx].f.subclass.integer = AST_CONTROL_HOLD;
09275       ast_mutex_unlock(&p->lock);
09276       ast_debug(1, "Sending hold on '%s'\n", ast_channel_name(ast));
09277       return &p->subs[idx].f;
09278    }
09279 
09280    if (p->subs[idx].needunhold) {
09281       /* Send answer frame if requested */
09282       p->subs[idx].needunhold = 0;
09283       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09284       p->subs[idx].f.subclass.integer = AST_CONTROL_UNHOLD;
09285       ast_mutex_unlock(&p->lock);
09286       ast_debug(1, "Sending unhold on '%s'\n", ast_channel_name(ast));
09287       return &p->subs[idx].f;
09288    }
09289 
09290    /*
09291     * If we have a fake_event, fake an exception to handle it only
09292     * if this channel owns the private.
09293     */
09294    if (p->fake_event && p->owner == ast) {
09295       if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
09296          struct analog_pvt *analog_p = p->sig_pvt;
09297 
09298          f = analog_exception(analog_p, ast);
09299       } else {
09300          f = __dahdi_exception(ast);
09301       }
09302       ast_mutex_unlock(&p->lock);
09303       return f;
09304    }
09305 
09306    if (ast_channel_rawreadformat(ast)->id == AST_FORMAT_SLINEAR) {
09307       if (!p->subs[idx].linear) {
09308          p->subs[idx].linear = 1;
09309          res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09310          if (res)
09311             ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to linear mode.\n", p->channel, idx);
09312       }
09313    } else if ((ast_channel_rawreadformat(ast)->id == AST_FORMAT_ULAW) ||
09314       (ast_channel_rawreadformat(ast)->id == AST_FORMAT_ALAW)) {
09315       if (p->subs[idx].linear) {
09316          p->subs[idx].linear = 0;
09317          res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09318          if (res)
09319             ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to companded mode.\n", p->channel, idx);
09320       }
09321    } else {
09322       ast_log(LOG_WARNING, "Don't know how to read frames in format %s\n", ast_getformatname(ast_channel_rawreadformat(ast)));
09323       ast_mutex_unlock(&p->lock);
09324       return NULL;
09325    }
09326    readbuf = ((unsigned char *)p->subs[idx].buffer) + AST_FRIENDLY_OFFSET;
09327    CHECK_BLOCKING(ast);
09328    res = read(p->subs[idx].dfd, readbuf, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
09329    ast_clear_flag(ast_channel_flags(ast), AST_FLAG_BLOCKING);
09330    /* Check for hangup */
09331    if (res < 0) {
09332       f = NULL;
09333       if (res == -1) {
09334          if (errno == EAGAIN) {
09335             /* Return "NULL" frame if there is nobody there */
09336             ast_mutex_unlock(&p->lock);
09337             return &p->subs[idx].f;
09338          } else if (errno == ELAST) {
09339             if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
09340                struct analog_pvt *analog_p = p->sig_pvt;
09341                f = analog_exception(analog_p, ast);
09342             } else {
09343                f = __dahdi_exception(ast);
09344             }
09345          } else
09346             ast_log(LOG_WARNING, "dahdi_rec: %s\n", strerror(errno));
09347       }
09348       ast_mutex_unlock(&p->lock);
09349       return f;
09350    }
09351    if (res != (p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE)) {
09352       ast_debug(1, "Short read (%d/%d), must be an event...\n", res, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
09353       if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
09354          struct analog_pvt *analog_p = p->sig_pvt;
09355          f = analog_exception(analog_p, ast);
09356       } else {
09357          f = __dahdi_exception(ast);
09358       }
09359       ast_mutex_unlock(&p->lock);
09360       return f;
09361    }
09362    if (p->tdd) { /* if in TDD mode, see if we receive that */
09363       int c;
09364 
09365       c = tdd_feed(p->tdd,readbuf,READ_SIZE);
09366       if (c < 0) {
09367          ast_debug(1,"tdd_feed failed\n");
09368          ast_mutex_unlock(&p->lock);
09369          return NULL;
09370       }
09371       if (c) { /* if a char to return */
09372          p->subs[idx].f.subclass.integer = 0;
09373          p->subs[idx].f.frametype = AST_FRAME_TEXT;
09374          p->subs[idx].f.mallocd = 0;
09375          p->subs[idx].f.offset = AST_FRIENDLY_OFFSET;
09376          p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET;
09377          p->subs[idx].f.datalen = 1;
09378          *((char *) p->subs[idx].f.data.ptr) = c;
09379          ast_mutex_unlock(&p->lock);
09380          return &p->subs[idx].f;
09381       }
09382    }
09383    if (idx == SUB_REAL) {
09384       /* Ensure the CW timers decrement only on a single subchannel */
09385       if (p->cidcwexpire) {
09386          if (!--p->cidcwexpire) {
09387             /* Expired CID/CW */
09388             ast_verb(3, "CPE does not support Call Waiting Caller*ID.\n");
09389             restore_conference(p);
09390          }
09391       }
09392       if (p->cid_suppress_expire) {
09393          --p->cid_suppress_expire;
09394       }
09395       if (p->callwaitingrepeat) {
09396          if (!--p->callwaitingrepeat) {
09397             /* Expired, Repeat callwaiting tone */
09398             ++p->callwaitrings;
09399             dahdi_callwait(ast);
09400          }
09401       }
09402    }
09403    if (p->subs[idx].linear) {
09404       p->subs[idx].f.datalen = READ_SIZE * 2;
09405    } else
09406       p->subs[idx].f.datalen = READ_SIZE;
09407 
09408    /* Handle CallerID Transmission */
09409    if ((p->owner == ast) && p->cidspill) {
09410       send_callerid(p);
09411    }
09412 
09413    p->subs[idx].f.frametype = AST_FRAME_VOICE;
09414    ast_format_copy(&p->subs[idx].f.subclass.format, ast_channel_rawreadformat(ast));
09415    p->subs[idx].f.samples = READ_SIZE;
09416    p->subs[idx].f.mallocd = 0;
09417    p->subs[idx].f.offset = AST_FRIENDLY_OFFSET;
09418    p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET / sizeof(p->subs[idx].buffer[0]);
09419 #if 0
09420    ast_debug(1, "Read %d of voice on %s\n", p->subs[idx].f.datalen, ast->name);
09421 #endif
09422    if ((p->dialing && !p->waitingfordt.tv_sec) ||  p->radio || /* Transmitting something */
09423       (idx && (ast_channel_state(ast) != AST_STATE_UP)) || /* Three-way or callwait that isn't up */
09424       ((idx == SUB_CALLWAIT) && !p->subs[SUB_CALLWAIT].inthreeway) /* Inactive and non-confed call-wait */
09425       ) {
09426       /* Whoops, we're still dialing, or in a state where we shouldn't transmit....
09427          don't send anything */
09428       p->subs[idx].f.frametype = AST_FRAME_NULL;
09429       p->subs[idx].f.subclass.integer = 0;
09430       p->subs[idx].f.samples = 0;
09431       p->subs[idx].f.mallocd = 0;
09432       p->subs[idx].f.offset = 0;
09433       p->subs[idx].f.data.ptr = NULL;
09434       p->subs[idx].f.datalen= 0;
09435    }
09436    if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect || p->callprogress || p->waitingfordt.tv_sec || p->dialtone_detect) && !idx) {
09437       /* Perform busy detection etc on the dahdi line */
09438       int mute;
09439 
09440       f = ast_dsp_process(ast, p->dsp, &p->subs[idx].f);
09441 
09442       /* Check if DSP code thinks we should be muting this frame and mute the conference if so */
09443       mute = ast_dsp_was_muted(p->dsp);
09444       if (p->muting != mute) {
09445          p->muting = mute;
09446          dahdi_confmute(p, mute);
09447       }
09448 
09449       if (f) {
09450          if ((p->dsp_features & DSP_FEATURE_WAITDIALTONE) && (p->dialtone_detect > 0)
09451             && !p->outgoing && ast_channel_state(ast) == AST_STATE_UP) {
09452             if (++p->dialtone_scanning_time_elapsed >= p->dialtone_detect) {
09453                p->dsp_features &= ~DSP_FEATURE_WAITDIALTONE;
09454                ast_dsp_set_features(p->dsp, p->dsp_features);
09455             }
09456          }
09457          if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass.integer == AST_CONTROL_BUSY)) {
09458             if ((ast_channel_state(ast) == AST_STATE_UP) && !p->outgoing) {
09459                /*
09460                 * Treat this as a "hangup" instead of a "busy" on the
09461                 * assumption that a busy means the incoming call went away.
09462                 */
09463                ast_frfree(f);
09464                f = NULL;
09465             }
09466          } else if (p->dialtone_detect && !p->outgoing && f->frametype == AST_FRAME_VOICE) {
09467             if ((ast_dsp_get_tstate(p->dsp) == DSP_TONE_STATE_DIALTONE) && (ast_dsp_get_tcount(p->dsp) > 9)) {
09468                /* Dialtone detected on inbound call; hangup the channel */
09469                ast_frfree(f);
09470                f = NULL;
09471             }
09472          } else if (f->frametype == AST_FRAME_DTMF_BEGIN
09473             || f->frametype == AST_FRAME_DTMF_END) {
09474 #ifdef HAVE_PRI
09475             if (dahdi_sig_pri_lib_handles(p->sig)
09476                && ((struct sig_pri_chan *) p->sig_pvt)->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING
09477                && p->pri
09478                && ((!p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING))
09479                   || (p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)))) {
09480                /* Don't accept in-band DTMF when in overlap dial mode */
09481                ast_debug(1, "Absorbing inband %s DTMF digit: 0x%02X '%c' on %s\n",
09482                   f->frametype == AST_FRAME_DTMF_BEGIN ? "begin" : "end",
09483                   (unsigned)f->subclass.integer, f->subclass.integer, ast_channel_name(ast));
09484 
09485                f->frametype = AST_FRAME_NULL;
09486                f->subclass.integer = 0;
09487             }
09488 #endif
09489             /* DSP clears us of being pulse */
09490             p->pulsedial = 0;
09491          } else if (p->waitingfordt.tv_sec) {
09492             if (ast_tvdiff_ms(ast_tvnow(), p->waitingfordt) >= p->waitfordialtone ) {
09493                p->waitingfordt.tv_sec = 0;
09494                ast_log(LOG_WARNING, "Never saw dialtone on channel %d\n", p->channel);
09495                ast_frfree(f);
09496                f = NULL;
09497             } else if (f->frametype == AST_FRAME_VOICE) {
09498                f->frametype = AST_FRAME_NULL;
09499                f->subclass.integer = 0;
09500                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) {
09501                   p->waitingfordt.tv_sec = 0;
09502                   p->dsp_features &= ~DSP_FEATURE_WAITDIALTONE;
09503                   ast_dsp_set_features(p->dsp, p->dsp_features);
09504                   ast_debug(1, "Got 10 samples of dialtone!\n");
09505                   if (!ast_strlen_zero(p->dop.dialstr)) { /* Dial deferred digits */
09506                      res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
09507                      if (res < 0) {
09508                         ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d\n", p->channel);
09509                         p->dop.dialstr[0] = '\0';
09510                         ast_mutex_unlock(&p->lock);
09511                         ast_frfree(f);
09512                         return NULL;
09513                      } else {
09514                         ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
09515                         p->dialing = 1;
09516                         p->dop.dialstr[0] = '\0';
09517                         p->dop.op = DAHDI_DIAL_OP_REPLACE;
09518                         ast_setstate(ast, AST_STATE_DIALING);
09519                      }
09520                   }
09521                }
09522             }
09523          }
09524       }
09525    } else
09526       f = &p->subs[idx].f;
09527 
09528    if (f) {
09529       switch (f->frametype) {
09530       case AST_FRAME_DTMF_BEGIN:
09531       case AST_FRAME_DTMF_END:
09532          if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
09533             analog_handle_dtmf(p->sig_pvt, ast, idx, &f);
09534          } else {
09535             dahdi_handle_dtmf(ast, idx, &f);
09536          }
09537          break;
09538       case AST_FRAME_VOICE:
09539          if (p->cidspill || p->cid_suppress_expire) {
09540             /* We are/were sending a caller id spill.  Suppress any echo. */
09541             p->subs[idx].f.frametype = AST_FRAME_NULL;
09542             p->subs[idx].f.subclass.integer = 0;
09543             p->subs[idx].f.samples = 0;
09544             p->subs[idx].f.mallocd = 0;
09545             p->subs[idx].f.offset = 0;
09546             p->subs[idx].f.data.ptr = NULL;
09547             p->subs[idx].f.datalen= 0;
09548          }
09549          break;
09550       default:
09551          break;
09552       }
09553    }
09554 
09555    ast_mutex_unlock(&p->lock);
09556    return f;
09557 }
09558 
09559 static int my_dahdi_write(struct dahdi_pvt *p, unsigned char *buf, int len, int idx, int linear)
09560 {
09561    int sent=0;
09562    int size;
09563    int res;
09564    int fd;
09565    fd = p->subs[idx].dfd;
09566    while (len) {
09567       size = len;
09568       if (size > (linear ? READ_SIZE * 2 : READ_SIZE))
09569          size = (linear ? READ_SIZE * 2 : READ_SIZE);
09570       res = write(fd, buf, size);
09571       if (res != size) {
09572          ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
09573          return sent;
09574       }
09575       len -= size;
09576       buf += size;
09577    }
09578    return sent;
09579 }
09580 
09581 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame)
09582 {
09583    struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
09584    int res;
09585    int idx;
09586    idx = dahdi_get_index(ast, p, 0);
09587    if (idx < 0) {
09588       ast_log(LOG_WARNING, "%s doesn't really exist?\n", ast_channel_name(ast));
09589       return -1;
09590    }
09591 
09592    /* Write a frame of (presumably voice) data */
09593    if (frame->frametype != AST_FRAME_VOICE) {
09594       if (frame->frametype != AST_FRAME_IMAGE)
09595          ast_log(LOG_WARNING, "Don't know what to do with frame type '%u'\n", frame->frametype);
09596       return 0;
09597    }
09598    if ((frame->subclass.format.id != AST_FORMAT_SLINEAR) &&
09599       (frame->subclass.format.id != AST_FORMAT_ULAW) &&
09600       (frame->subclass.format.id != AST_FORMAT_ALAW)) {
09601       ast_log(LOG_WARNING, "Cannot handle frames in %s format\n", ast_getformatname(&frame->subclass.format));
09602       return -1;
09603    }
09604    if (p->dialing) {
09605       ast_debug(1, "Dropping frame since I'm still dialing on %s...\n",ast_channel_name(ast));
09606       return 0;
09607    }
09608    if (!p->owner) {
09609       ast_debug(1, "Dropping frame since there is no active owner on %s...\n",ast_channel_name(ast));
09610       return 0;
09611    }
09612    if (p->cidspill) {
09613       ast_debug(1, "Dropping frame since I've still got a callerid spill on %s...\n",
09614          ast_channel_name(ast));
09615       return 0;
09616    }
09617    /* Return if it's not valid data */
09618    if (!frame->data.ptr || !frame->datalen)
09619       return 0;
09620 
09621    if (frame->subclass.format.id == AST_FORMAT_SLINEAR) {
09622       if (!p->subs[idx].linear) {
09623          p->subs[idx].linear = 1;
09624          res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09625          if (res)
09626             ast_log(LOG_WARNING, "Unable to set linear mode on channel %d\n", p->channel);
09627       }
09628       res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 1);
09629    } else {
09630       /* x-law already */
09631       if (p->subs[idx].linear) {
09632          p->subs[idx].linear = 0;
09633          res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09634          if (res)
09635             ast_log(LOG_WARNING, "Unable to set companded mode on channel %d\n", p->channel);
09636       }
09637       res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 0);
09638    }
09639    if (res < 0) {
09640       ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
09641       return -1;
09642    }
09643    return 0;
09644 }
09645 
09646 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen)
09647 {
09648    struct dahdi_pvt *p = ast_channel_tech_pvt(chan);
09649    int res=-1;
09650    int idx;
09651    int func = DAHDI_FLASH;
09652 
09653    ast_mutex_lock(&p->lock);
09654    ast_debug(1, "Requested indication %d on channel %s\n", condition, ast_channel_name(chan));
09655    switch (p->sig) {
09656 #if defined(HAVE_PRI)
09657    case SIG_PRI_LIB_HANDLE_CASES:
09658       res = sig_pri_indicate(p->sig_pvt, chan, condition, data, datalen);
09659       ast_mutex_unlock(&p->lock);
09660       return res;
09661 #endif   /* defined(HAVE_PRI) */
09662 #if defined(HAVE_SS7)
09663    case SIG_SS7:
09664       res = sig_ss7_indicate(p->sig_pvt, chan, condition, data, datalen);
09665       ast_mutex_unlock(&p->lock);
09666       return res;
09667 #endif   /* defined(HAVE_SS7) */
09668    default:
09669       break;
09670    }
09671 #ifdef HAVE_OPENR2
09672    if (p->mfcr2 && !p->mfcr2_call_accepted) {
09673       ast_mutex_unlock(&p->lock);
09674       /* if this is an R2 call and the call is not yet accepted, we don't want the
09675          tone indications to mess up with the MF tones */
09676       return 0;
09677    }
09678 #endif
09679    idx = dahdi_get_index(chan, p, 0);
09680    if (idx == SUB_REAL) {
09681       switch (condition) {
09682       case AST_CONTROL_BUSY:
09683          res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_BUSY);
09684          break;
09685       case AST_CONTROL_RINGING:
09686          res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_RINGTONE);
09687 
09688          if (ast_channel_state(chan) != AST_STATE_UP) {
09689             if ((ast_channel_state(chan) != AST_STATE_RING) ||
09690                ((p->sig != SIG_FXSKS) &&
09691              (p->sig != SIG_FXSLS) &&
09692              (p->sig != SIG_FXSGS)))
09693             ast_setstate(chan, AST_STATE_RINGING);
09694          }
09695          break;
09696       case AST_CONTROL_INCOMPLETE:
09697          ast_debug(1, "Received AST_CONTROL_INCOMPLETE on %s\n", ast_channel_name(chan));
09698          /* act as a progress or proceeding, allowing the caller to enter additional numbers */
09699          res = 0;
09700          break;
09701       case AST_CONTROL_PROCEEDING:
09702          ast_debug(1, "Received AST_CONTROL_PROCEEDING on %s\n", ast_channel_name(chan));
09703          /* don't continue in ast_indicate */
09704          res = 0;
09705          break;
09706       case AST_CONTROL_PROGRESS:
09707          ast_debug(1, "Received AST_CONTROL_PROGRESS on %s\n", ast_channel_name(chan));
09708          /* don't continue in ast_indicate */
09709          res = 0;
09710          break;
09711       case AST_CONTROL_CONGESTION:
09712          /* There are many cause codes that generate an AST_CONTROL_CONGESTION. */
09713          switch (ast_channel_hangupcause(chan)) {
09714          case AST_CAUSE_USER_BUSY:
09715          case AST_CAUSE_NORMAL_CLEARING:
09716          case 0:/* Cause has not been set. */
09717             /* Supply a more appropriate cause. */
09718             ast_channel_hangupcause_set(chan, AST_CAUSE_CONGESTION);
09719             break;
09720          default:
09721             break;
09722          }
09723          break;
09724       case AST_CONTROL_HOLD:
09725          ast_moh_start(chan, data, p->mohinterpret);
09726          break;
09727       case AST_CONTROL_UNHOLD:
09728          ast_moh_stop(chan);
09729          break;
09730       case AST_CONTROL_RADIO_KEY:
09731          if (p->radio)
09732             res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
09733          res = 0;
09734          break;
09735       case AST_CONTROL_RADIO_UNKEY:
09736          if (p->radio)
09737             res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_RINGOFF);
09738          res = 0;
09739          break;
09740       case AST_CONTROL_FLASH:
09741          /* flash hookswitch */
09742          if (ISTRUNK(p) && (p->sig != SIG_PRI)) {
09743             /* Clear out the dial buffer */
09744             p->dop.dialstr[0] = '\0';
09745             if ((ioctl(p->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
09746                ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
09747                   ast_channel_name(chan), strerror(errno));
09748             } else
09749                res = 0;
09750          } else
09751             res = 0;
09752          break;
09753       case AST_CONTROL_SRCUPDATE:
09754          res = 0;
09755          break;
09756       case -1:
09757          res = tone_zone_play_tone(p->subs[idx].dfd, -1);
09758          break;
09759       }
09760    } else {
09761       res = 0;
09762    }
09763    ast_mutex_unlock(&p->lock);
09764    return res;
09765 }
09766 
09767 #if defined(HAVE_PRI)
09768 static struct ast_str *create_channel_name(struct dahdi_pvt *i, int is_outgoing, char *address)
09769 #else
09770 static struct ast_str *create_channel_name(struct dahdi_pvt *i)
09771 #endif   /* defined(HAVE_PRI) */
09772 {
09773    struct ast_str *chan_name;
09774    int x, y;
09775 
09776    /* Create the new channel name tail. */
09777    if (!(chan_name = ast_str_create(32))) {
09778       return NULL;
09779    }
09780    if (i->channel == CHAN_PSEUDO) {
09781       ast_str_set(&chan_name, 0, "pseudo-%ld", ast_random());
09782 #if defined(HAVE_PRI)
09783    } else if (i->pri) {
09784       ast_mutex_lock(&i->pri->lock);
09785       y = ++i->pri->new_chan_seq;
09786       if (is_outgoing) {
09787          ast_str_set(&chan_name, 0, "i%d/%s-%x", i->pri->span, address, (unsigned)y);
09788          address[0] = '\0';
09789       } else if (ast_strlen_zero(i->cid_subaddr)) {
09790          /* Put in caller-id number only since there is no subaddress. */
09791          ast_str_set(&chan_name, 0, "i%d/%s-%x", i->pri->span, i->cid_num, (unsigned)y);
09792       } else {
09793          /* Put in caller-id number and subaddress. */
09794          ast_str_set(&chan_name, 0, "i%d/%s:%s-%x", i->pri->span, i->cid_num,
09795             i->cid_subaddr, (unsigned)y);
09796       }
09797       ast_mutex_unlock(&i->pri->lock);
09798 #endif   /* defined(HAVE_PRI) */
09799    } else {
09800       y = 1;
09801       do {
09802          ast_str_set(&chan_name, 0, "%d-%d", i->channel, y);
09803          for (x = 0; x < 3; ++x) {
09804             if (i->subs[x].owner && !strcasecmp(ast_str_buffer(chan_name),
09805                ast_channel_name(i->subs[x].owner) + 6)) {
09806                break;
09807             }
09808          }
09809          ++y;
09810       } while (x < 3);
09811    }
09812    return chan_name;
09813 }
09814 
09815 static struct ast_channel *dahdi_new_callid_clean(struct dahdi_pvt *i, int state, int startpbx, int idx, int law, const char *linkedid, struct ast_callid *callid, int callid_created)
09816 {
09817    struct ast_channel *new_channel = dahdi_new(i, state, startpbx, idx, law, linkedid, callid);
09818 
09819    ast_callid_threadstorage_auto_clean(callid, callid_created);
09820 
09821    return new_channel;
09822 }
09823 
09824 static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpbx, int idx, int law, const char *linkedid, struct ast_callid *callid)
09825 {
09826    struct ast_channel *tmp;
09827    struct ast_format deflaw;
09828    int x;
09829    int features;
09830    struct ast_str *chan_name;
09831    struct ast_variable *v;
09832    char *dashptr;
09833    char device_name[AST_CHANNEL_NAME];
09834 
09835    if (i->subs[idx].owner) {
09836       ast_log(LOG_WARNING, "Channel %d already has a %s call\n", i->channel,subnames[idx]);
09837       return NULL;
09838    }
09839 
09840    ast_format_clear(&deflaw);
09841 #if defined(HAVE_PRI)
09842    /*
09843     * The dnid has been stuffed with the called-number[:subaddress]
09844     * by dahdi_request() for outgoing calls.
09845     */
09846    chan_name = create_channel_name(i, i->outgoing, i->dnid);
09847 #else
09848    chan_name = create_channel_name(i);
09849 #endif   /* defined(HAVE_PRI) */
09850    if (!chan_name) {
09851       return NULL;
09852    }
09853 
09854    tmp = ast_channel_alloc(0, state, i->cid_num, i->cid_name, i->accountcode, i->exten, i->context, linkedid, i->amaflags, "DAHDI/%s", ast_str_buffer(chan_name));
09855    ast_free(chan_name);
09856    if (!tmp) {
09857       return NULL;
09858    }
09859 
09860    if (callid) {
09861       ast_channel_callid_set(tmp, callid);
09862    }
09863 
09864    ast_channel_tech_set(tmp, &dahdi_tech);
09865 #if defined(HAVE_PRI)
09866    if (i->pri) {
09867       ast_cc_copy_config_params(i->cc_params, i->pri->cc_params);
09868    }
09869 #endif   /* defined(HAVE_PRI) */
09870    ast_channel_cc_params_init(tmp, i->cc_params);
09871    if (law) {
09872       i->law = law;
09873       if (law == DAHDI_LAW_ALAW) {
09874          ast_format_set(&deflaw, AST_FORMAT_ALAW, 0);
09875       } else {
09876          ast_format_set(&deflaw, AST_FORMAT_ULAW, 0);
09877       }
09878    } else {
09879       switch (i->sig) {
09880       case SIG_PRI_LIB_HANDLE_CASES:
09881          /* Make sure companding law is known. */
09882          i->law = (i->law_default == DAHDI_LAW_ALAW)
09883             ? DAHDI_LAW_ALAW : DAHDI_LAW_MULAW;
09884          break;
09885       default:
09886          i->law = i->law_default;
09887          break;
09888       }
09889       if (i->law_default == DAHDI_LAW_ALAW) {
09890          ast_format_set(&deflaw, AST_FORMAT_ALAW, 0);
09891       } else {
09892          ast_format_set(&deflaw, AST_FORMAT_ULAW, 0);
09893       }
09894    }
09895    ast_channel_set_fd(tmp, 0, i->subs[idx].dfd);
09896    ast_format_cap_add(ast_channel_nativeformats(tmp), &deflaw);
09897    /* Start out assuming ulaw since it's smaller :) */
09898    ast_format_copy(ast_channel_rawreadformat(tmp), &deflaw);
09899    ast_format_copy(ast_channel_readformat(tmp), &deflaw);
09900    ast_format_copy(ast_channel_rawwriteformat(tmp), &deflaw);
09901    ast_format_copy(ast_channel_writeformat(tmp), &deflaw);
09902    i->subs[idx].linear = 0;
09903    dahdi_setlinear(i->subs[idx].dfd, i->subs[idx].linear);
09904    features = 0;
09905    if (idx == SUB_REAL) {
09906       if (i->busydetect && CANBUSYDETECT(i))
09907          features |= DSP_FEATURE_BUSY_DETECT;
09908       if ((i->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(i))
09909          features |= DSP_FEATURE_CALL_PROGRESS;
09910       if ((i->waitfordialtone || i->dialtone_detect) && CANPROGRESSDETECT(i))
09911          features |= DSP_FEATURE_WAITDIALTONE;
09912       if ((!i->outgoing && (i->callprogress & CALLPROGRESS_FAX_INCOMING)) ||
09913          (i->outgoing && (i->callprogress & CALLPROGRESS_FAX_OUTGOING))) {
09914          features |= DSP_FEATURE_FAX_DETECT;
09915       }
09916       x = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
09917       if (ioctl(i->subs[idx].dfd, DAHDI_TONEDETECT, &x)) {
09918          i->hardwaredtmf = 0;
09919          features |= DSP_FEATURE_DIGIT_DETECT;
09920       } else if (NEED_MFDETECT(i)) {
09921          i->hardwaredtmf = 1;
09922          features |= DSP_FEATURE_DIGIT_DETECT;
09923       }
09924    }
09925    if (features) {
09926       if (i->dsp) {
09927          ast_debug(1, "Already have a dsp on %s?\n", ast_channel_name(tmp));
09928       } else {
09929          if (i->channel != CHAN_PSEUDO)
09930             i->dsp = ast_dsp_new();
09931          else
09932             i->dsp = NULL;
09933          if (i->dsp) {
09934             i->dsp_features = features;
09935 #if defined(HAVE_PRI) || defined(HAVE_SS7)
09936             /* We cannot do progress detection until receive PROGRESS message */
09937             if (i->outgoing && (dahdi_sig_pri_lib_handles(i->sig) || (i->sig == SIG_SS7))) {
09938                /* Remember requested DSP features, don't treat
09939                   talking as ANSWER */
09940                i->dsp_features = features & ~DSP_PROGRESS_TALK;
09941                features = 0;
09942             }
09943 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
09944             ast_dsp_set_features(i->dsp, features);
09945             ast_dsp_set_digitmode(i->dsp, DSP_DIGITMODE_DTMF | i->dtmfrelax);
09946             if (!ast_strlen_zero(progzone))
09947                ast_dsp_set_call_progress_zone(i->dsp, progzone);
09948             if (i->busydetect && CANBUSYDETECT(i)) {
09949                ast_dsp_set_busy_count(i->dsp, i->busycount);
09950                ast_dsp_set_busy_pattern(i->dsp, &i->busy_cadence);
09951             }
09952          }
09953       }
09954    }
09955 
09956    i->dialtone_scanning_time_elapsed = 0;
09957 
09958    if (state == AST_STATE_RING)
09959       ast_channel_rings_set(tmp, 1);
09960    ast_channel_tech_pvt_set(tmp, i);
09961    if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) {
09962       /* Only FXO signalled stuff can be picked up */
09963       ast_channel_callgroup_set(tmp, i->callgroup);
09964       ast_channel_pickupgroup_set(tmp, i->pickupgroup);
09965       ast_channel_named_callgroups_set(tmp, i->named_callgroups);
09966       ast_channel_named_pickupgroups_set(tmp, i->named_pickupgroups);
09967    }
09968    if (!ast_strlen_zero(i->parkinglot))
09969       ast_channel_parkinglot_set(tmp, i->parkinglot);
09970    if (!ast_strlen_zero(i->language))
09971       ast_channel_language_set(tmp, i->language);
09972    if (!i->owner)
09973       i->owner = tmp;
09974    if (!ast_strlen_zero(i->accountcode))
09975       ast_channel_accountcode_set(tmp, i->accountcode);
09976    if (i->amaflags)
09977       ast_channel_amaflags_set(tmp, i->amaflags);
09978    i->subs[idx].owner = tmp;
09979    ast_channel_context_set(tmp, i->context);
09980    if (!analog_lib_handles(i->sig, i->radio, i->oprmode)) {
09981       ast_channel_call_forward_set(tmp, i->call_forward);
09982    }
09983    /* If we've been told "no ADSI" then enforce it */
09984    if (!i->adsi)
09985       ast_channel_adsicpe_set(tmp, AST_ADSI_UNAVAILABLE);
09986    if (!ast_strlen_zero(i->exten))
09987       ast_channel_exten_set(tmp, i->exten);
09988    if (!ast_strlen_zero(i->rdnis)) {
09989       ast_channel_redirecting(tmp)->from.number.valid = 1;
09990       ast_channel_redirecting(tmp)->from.number.str = ast_strdup(i->rdnis);
09991    }
09992    if (!ast_strlen_zero(i->dnid)) {
09993       ast_channel_dialed(tmp)->number.str = ast_strdup(i->dnid);
09994    }
09995 
09996    /* Don't use ast_set_callerid() here because it will
09997     * generate a needless NewCallerID event */
09998 #if defined(HAVE_PRI) || defined(HAVE_SS7)
09999    if (!ast_strlen_zero(i->cid_ani)) {
10000       ast_channel_caller(tmp)->ani.number.valid = 1;
10001       ast_channel_caller(tmp)->ani.number.str = ast_strdup(i->cid_ani);
10002    } else if (!ast_strlen_zero(i->cid_num)) {
10003       ast_channel_caller(tmp)->ani.number.valid = 1;
10004       ast_channel_caller(tmp)->ani.number.str = ast_strdup(i->cid_num);
10005    }
10006 #else
10007    if (!ast_strlen_zero(i->cid_num)) {
10008       ast_channel_caller(tmp)->ani.number.valid = 1;
10009       ast_channel_caller(tmp)->ani.number.str = ast_strdup(i->cid_num);
10010    }
10011 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
10012    ast_channel_caller(tmp)->id.name.presentation = i->callingpres;
10013    ast_channel_caller(tmp)->id.number.presentation = i->callingpres;
10014    ast_channel_caller(tmp)->id.number.plan = i->cid_ton;
10015    ast_channel_caller(tmp)->ani2 = i->cid_ani2;
10016    ast_channel_caller(tmp)->id.tag = ast_strdup(i->cid_tag);
10017    /* clear the fake event in case we posted one before we had ast_channel */
10018    i->fake_event = 0;
10019    /* Assure there is no confmute on this channel */
10020    dahdi_confmute(i, 0);
10021    i->muting = 0;
10022    /* Configure the new channel jb */
10023    ast_jb_configure(tmp, &global_jbconf);
10024 
10025    /* Set initial device state */
10026    ast_copy_string(device_name, ast_channel_name(tmp), sizeof(device_name));
10027    dashptr = strrchr(device_name, '-');
10028    if (dashptr) {
10029       *dashptr = '\0';
10030    }
10031    ast_set_flag(ast_channel_flags(tmp), AST_FLAG_DISABLE_DEVSTATE_CACHE);
10032    ast_devstate_changed_literal(AST_DEVICE_UNKNOWN, AST_DEVSTATE_NOT_CACHABLE, device_name);
10033 
10034    for (v = i->vars ; v ; v = v->next)
10035       pbx_builtin_setvar_helper(tmp, v->name, v->value);
10036 
10037    ast_module_ref(ast_module_info->self);
10038 
10039    dahdi_ami_channel_event(i, tmp);
10040    if (startpbx) {
10041 #ifdef HAVE_OPENR2
10042       if (i->mfcr2call) {
10043          pbx_builtin_setvar_helper(tmp, "MFCR2_CATEGORY", openr2_proto_get_category_string(i->mfcr2_recvd_category));
10044       }
10045 #endif
10046       if (ast_pbx_start(tmp)) {
10047          ast_log(LOG_WARNING, "Unable to start PBX on %s\n", ast_channel_name(tmp));
10048          ast_hangup(tmp);
10049          return NULL;
10050       }
10051    }
10052    return tmp;
10053 }
10054 
10055 
10056 static int my_getsigstr(struct ast_channel *chan, char *str, const char *term, int ms)
10057 {
10058    char c;
10059 
10060    *str = 0; /* start with empty output buffer */
10061    for (;;)
10062    {
10063       /* Wait for the first digit (up to specified ms). */
10064       c = ast_waitfordigit(chan, ms);
10065       /* if timeout, hangup or error, return as such */
10066       if (c < 1)
10067          return c;
10068       *str++ = c;
10069       *str = 0;
10070       if (strchr(term, c))
10071          return 1;
10072    }
10073 }
10074 
10075 static int dahdi_wink(struct dahdi_pvt *p, int idx)
10076 {
10077    int j;
10078    dahdi_set_hook(p->subs[idx].dfd, DAHDI_WINK);
10079    for (;;)
10080    {
10081       /* set bits of interest */
10082       j = DAHDI_IOMUX_SIGEVENT;
10083       /* wait for some happening */
10084       if (ioctl(p->subs[idx].dfd,DAHDI_IOMUX,&j) == -1) return(-1);
10085       /* exit loop if we have it */
10086       if (j & DAHDI_IOMUX_SIGEVENT) break;
10087    }
10088    /* get the event info */
10089    if (ioctl(p->subs[idx].dfd,DAHDI_GETEVENT,&j) == -1) return(-1);
10090    return 0;
10091 }
10092 
10093 /*! \brief enable or disable the chan_dahdi Do-Not-Disturb mode for a DAHDI channel
10094  * \param dahdichan "Physical" DAHDI channel (e.g: DAHDI/5)
10095  * \param flag on 1 to enable, 0 to disable, -1 return dnd value
10096  *
10097  * chan_dahdi has a DND (Do Not Disturb) mode for each dahdichan (physical
10098  * DAHDI channel). Use this to enable or disable it.
10099  *
10100  * \bug the use of the word "channel" for those dahdichans is really confusing.
10101  */
10102 static int dahdi_dnd(struct dahdi_pvt *dahdichan, int flag)
10103 {
10104    if (analog_lib_handles(dahdichan->sig, dahdichan->radio, dahdichan->oprmode)) {
10105       return analog_dnd(dahdichan->sig_pvt, flag);
10106    }
10107 
10108    if (flag == -1) {
10109       return dahdichan->dnd;
10110    }
10111 
10112    /* Do not disturb */
10113    dahdichan->dnd = flag;
10114    ast_verb(3, "%s DND on channel %d\n",
10115          flag? "Enabled" : "Disabled",
10116          dahdichan->channel);
10117    /*** DOCUMENTATION
10118       <managerEventInstance>
10119          <synopsis>Raised when the Do Not Disturb state is changed on a DAHDI channel.</synopsis>
10120          <syntax>
10121             <parameter name="Status">
10122                <enumlist>
10123                   <enum name="enabled"/>
10124                   <enum name="disabled"/>
10125                </enumlist>
10126             </parameter>
10127          </syntax>
10128       </managerEventInstance>
10129    ***/
10130    manager_event(EVENT_FLAG_SYSTEM, "DNDState",
10131          "Channel: DAHDI/%d\r\n"
10132          "Status: %s\r\n", dahdichan->channel,
10133          flag? "enabled" : "disabled");
10134 
10135    return 0;
10136 }
10137 
10138 static int canmatch_featurecode(const char *exten)
10139 {
10140    int extlen = strlen(exten);
10141    const char *pickup_ext;
10142    if (!extlen) {
10143       return 1;
10144    }
10145    pickup_ext = ast_pickup_ext();
10146    if (extlen < strlen(pickup_ext) && !strncmp(pickup_ext, exten, extlen)) {
10147       return 1;
10148    }
10149    /* hardcoded features are *60, *67, *69, *70, *72, *73, *78, *79, *82, *0 */
10150    if (exten[0] == '*' && extlen < 3) {
10151       if (extlen == 1) {
10152          return 1;
10153       }
10154       /* "*0" should be processed before it gets here */
10155       switch (exten[1]) {
10156       case '6':
10157       case '7':
10158       case '8':
10159          return 1;
10160       }
10161    }
10162    return 0;
10163 }
10164 
10165 static void *analog_ss_thread(void *data)
10166 {
10167    struct ast_channel *chan = data;
10168    struct dahdi_pvt *p = ast_channel_tech_pvt(chan);
10169    char exten[AST_MAX_EXTENSION] = "";
10170    char exten2[AST_MAX_EXTENSION] = "";
10171    unsigned char buf[256];
10172    char dtmfcid[300];
10173    char dtmfbuf[300];
10174    struct callerid_state *cs = NULL;
10175    char *name = NULL, *number = NULL;
10176    int distMatches;
10177    int curRingData[3];
10178    int receivedRingT;
10179    int counter1;
10180    int counter;
10181    int samples = 0;
10182    struct ast_smdi_md_message *smdi_msg = NULL;
10183    int flags = 0;
10184    int i;
10185    int timeout;
10186    int getforward = 0;
10187    char *s1, *s2;
10188    int len = 0;
10189    int res;
10190    int idx;
10191    struct ast_format tmpfmt;
10192 
10193    ast_mutex_lock(&ss_thread_lock);
10194    ss_thread_count++;
10195    ast_mutex_unlock(&ss_thread_lock);
10196    /* in the bizarre case where the channel has become a zombie before we
10197       even get started here, abort safely
10198    */
10199    if (!p) {
10200       ast_log(LOG_WARNING, "Channel became a zombie before simple switch could be started (%s)\n", ast_channel_name(chan));
10201       ast_hangup(chan);
10202       goto quit;
10203    }
10204    ast_verb(3, "Starting simple switch on '%s'\n", ast_channel_name(chan));
10205    idx = dahdi_get_index(chan, p, 1);
10206    if (idx < 0) {
10207       ast_log(LOG_WARNING, "Huh?\n");
10208       ast_hangup(chan);
10209       goto quit;
10210    }
10211    if (p->dsp)
10212       ast_dsp_digitreset(p->dsp);
10213    switch (p->sig) {
10214    case SIG_FEATD:
10215    case SIG_FEATDMF:
10216    case SIG_FEATDMF_TA:
10217    case SIG_E911:
10218    case SIG_FGC_CAMAMF:
10219    case SIG_FEATB:
10220    case SIG_EMWINK:
10221    case SIG_SF_FEATD:
10222    case SIG_SF_FEATDMF:
10223    case SIG_SF_FEATB:
10224    case SIG_SFWINK:
10225       if (dahdi_wink(p, idx))
10226          goto quit;
10227       /* Fall through */
10228    case SIG_EM:
10229    case SIG_EM_E1:
10230    case SIG_SF:
10231    case SIG_FGC_CAMA:
10232       res = tone_zone_play_tone(p->subs[idx].dfd, -1);
10233       if (p->dsp)
10234          ast_dsp_digitreset(p->dsp);
10235       /* set digit mode appropriately */
10236       if (p->dsp) {
10237          if (NEED_MFDETECT(p))
10238             ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
10239          else
10240             ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
10241       }
10242       memset(dtmfbuf, 0, sizeof(dtmfbuf));
10243       /* Wait for the first digit only if immediate=no */
10244       if (!p->immediate)
10245          /* Wait for the first digit (up to 5 seconds). */
10246          res = ast_waitfordigit(chan, 5000);
10247       else
10248          res = 0;
10249       if (res > 0) {
10250          /* save first char */
10251          dtmfbuf[0] = res;
10252          switch (p->sig) {
10253          case SIG_FEATD:
10254          case SIG_SF_FEATD:
10255             res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
10256             if (res > 0)
10257                res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
10258             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
10259             break;
10260          case SIG_FEATDMF_TA:
10261             res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
10262             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
10263             if (dahdi_wink(p, idx)) goto quit;
10264             dtmfbuf[0] = 0;
10265             /* Wait for the first digit (up to 5 seconds). */
10266             res = ast_waitfordigit(chan, 5000);
10267             if (res <= 0) break;
10268             dtmfbuf[0] = res;
10269             /* fall through intentionally */
10270          case SIG_FEATDMF:
10271          case SIG_E911:
10272          case SIG_FGC_CAMAMF:
10273          case SIG_SF_FEATDMF:
10274             res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
10275             /* if international caca, do it again to get real ANO */
10276             if ((p->sig == SIG_FEATDMF) && (dtmfbuf[1] != '0') && (strlen(dtmfbuf) != 14))
10277             {
10278                if (dahdi_wink(p, idx)) goto quit;
10279                dtmfbuf[0] = 0;
10280                /* Wait for the first digit (up to 5 seconds). */
10281                res = ast_waitfordigit(chan, 5000);
10282                if (res <= 0) break;
10283                dtmfbuf[0] = res;
10284                res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
10285             }
10286             if (res > 0) {
10287                /* if E911, take off hook */
10288                if (p->sig == SIG_E911)
10289                   dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
10290                res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "#", 3000);
10291             }
10292             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
10293             break;
10294          case SIG_FEATB:
10295          case SIG_SF_FEATB:
10296             res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
10297             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
10298             break;
10299          case SIG_EMWINK:
10300             /* if we received a '*', we are actually receiving Feature Group D
10301                dial syntax, so use that mode; otherwise, fall through to normal
10302                mode
10303             */
10304             if (res == '*') {
10305                res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
10306                if (res > 0)
10307                   res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
10308                if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
10309                break;
10310             }
10311          default:
10312             /* If we got the first digit, get the rest */
10313             len = 1;
10314             dtmfbuf[len] = '\0';
10315             while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, ast_channel_context(chan), dtmfbuf, 1, p->cid_num)) {
10316                if (ast_exists_extension(chan, ast_channel_context(chan), dtmfbuf, 1, p->cid_num)) {
10317                   timeout = matchdigittimeout;
10318                } else {
10319                   timeout = gendigittimeout;
10320                }
10321                res = ast_waitfordigit(chan, timeout);
10322                if (res < 0) {
10323                   ast_debug(1, "waitfordigit returned < 0...\n");
10324                   ast_hangup(chan);
10325                   goto quit;
10326                } else if (res) {
10327                   dtmfbuf[len++] = res;
10328                   dtmfbuf[len] = '\0';
10329                } else {
10330                   break;
10331                }
10332             }
10333             break;
10334          }
10335       }
10336       if (res == -1) {
10337          ast_log(LOG_WARNING, "getdtmf on channel %d: %s\n", p->channel, strerror(errno));
10338          ast_hangup(chan);
10339          goto quit;
10340       } else if (res < 0) {
10341          ast_debug(1, "Got hung up before digits finished\n");
10342          ast_hangup(chan);
10343          goto quit;
10344       }
10345 
10346       if (p->sig == SIG_FGC_CAMA) {
10347          char anibuf[100];
10348 
10349          if (ast_safe_sleep(chan,1000) == -1) {
10350             ast_hangup(chan);
10351             goto quit;
10352          }
10353          dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
10354          ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
10355          res = my_getsigstr(chan, anibuf, "#", 10000);
10356          if ((res > 0) && (strlen(anibuf) > 2)) {
10357             if (anibuf[strlen(anibuf) - 1] == '#')
10358                anibuf[strlen(anibuf) - 1] = 0;
10359             ast_set_callerid(chan, anibuf + 2, NULL, anibuf + 2);
10360          }
10361          ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
10362       }
10363 
10364       ast_copy_string(exten, dtmfbuf, sizeof(exten));
10365       if (ast_strlen_zero(exten))
10366          ast_copy_string(exten, "s", sizeof(exten));
10367       if (p->sig == SIG_FEATD || p->sig == SIG_EMWINK) {
10368          /* Look for Feature Group D on all E&M Wink and Feature Group D trunks */
10369          if (exten[0] == '*') {
10370             char *stringp=NULL;
10371             ast_copy_string(exten2, exten, sizeof(exten2));
10372             /* Parse out extension and callerid */
10373             stringp=exten2 +1;
10374             s1 = strsep(&stringp, "*");
10375             s2 = strsep(&stringp, "*");
10376             if (s2) {
10377                if (!ast_strlen_zero(p->cid_num))
10378                   ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
10379                else
10380                   ast_set_callerid(chan, s1, NULL, s1);
10381                ast_copy_string(exten, s2, sizeof(exten));
10382             } else
10383                ast_copy_string(exten, s1, sizeof(exten));
10384          } else if (p->sig == SIG_FEATD)
10385             ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d.  Assuming E&M Wink instead\n", p->channel);
10386       }
10387       if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
10388          if (exten[0] == '*') {
10389             char *stringp=NULL;
10390             ast_copy_string(exten2, exten, sizeof(exten2));
10391             /* Parse out extension and callerid */
10392             stringp=exten2 +1;
10393             s1 = strsep(&stringp, "#");
10394             s2 = strsep(&stringp, "#");
10395             if (s2) {
10396                if (!ast_strlen_zero(p->cid_num))
10397                   ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
10398                else
10399                   if (*(s1 + 2))
10400                      ast_set_callerid(chan, s1 + 2, NULL, s1 + 2);
10401                ast_copy_string(exten, s2 + 1, sizeof(exten));
10402             } else
10403                ast_copy_string(exten, s1 + 2, sizeof(exten));
10404          } else
10405             ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d.  Assuming E&M Wink instead\n", p->channel);
10406       }
10407       if ((p->sig == SIG_E911) || (p->sig == SIG_FGC_CAMAMF)) {
10408          if (exten[0] == '*') {
10409             char *stringp=NULL;
10410             ast_copy_string(exten2, exten, sizeof(exten2));
10411             /* Parse out extension and callerid */
10412             stringp=exten2 +1;
10413             s1 = strsep(&stringp, "#");
10414             s2 = strsep(&stringp, "#");
10415             if (s2 && (*(s2 + 1) == '0')) {
10416                if (*(s2 + 2))
10417                   ast_set_callerid(chan, s2 + 2, NULL, s2 + 2);
10418             }
10419             if (s1)  ast_copy_string(exten, s1, sizeof(exten));
10420             else ast_copy_string(exten, "911", sizeof(exten));
10421          } else
10422             ast_log(LOG_WARNING, "Got a non-E911/FGC CAMA input on channel %d.  Assuming E&M Wink instead\n", p->channel);
10423       }
10424       if (p->sig == SIG_FEATB) {
10425          if (exten[0] == '*') {
10426             char *stringp=NULL;
10427             ast_copy_string(exten2, exten, sizeof(exten2));
10428             /* Parse out extension and callerid */
10429             stringp=exten2 +1;
10430             s1 = strsep(&stringp, "#");
10431             ast_copy_string(exten, exten2 + 1, sizeof(exten));
10432          } else
10433             ast_log(LOG_WARNING, "Got a non-Feature Group B input on channel %d.  Assuming E&M Wink instead\n", p->channel);
10434       }
10435       if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
10436          dahdi_wink(p, idx);
10437          /* some switches require a minimum guard time between
10438             the last FGD wink and something that answers
10439             immediately. This ensures it */
10440          if (ast_safe_sleep(chan, 100)) {
10441             ast_hangup(chan);
10442             goto quit;
10443          }
10444       }
10445       dahdi_enable_ec(p);
10446       if (NEED_MFDETECT(p)) {
10447          if (p->dsp) {
10448             if (!p->hardwaredtmf)
10449                ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
10450             else {
10451                ast_dsp_free(p->dsp);
10452                p->dsp = NULL;
10453             }
10454          }
10455       }
10456 
10457       if (ast_exists_extension(chan, ast_channel_context(chan), exten, 1,
10458          S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL))) {
10459          ast_channel_exten_set(chan, exten);
10460          if (p->dsp) ast_dsp_digitreset(p->dsp);
10461          res = ast_pbx_run(chan);
10462          if (res) {
10463             ast_log(LOG_WARNING, "PBX exited non-zero\n");
10464             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10465          }
10466          goto quit;
10467       } else {
10468          ast_verb(2, "Unknown extension '%s' in context '%s' requested\n", exten, ast_channel_context(chan));
10469          sleep(2);
10470          res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_INFO);
10471          if (res < 0)
10472             ast_log(LOG_WARNING, "Unable to start special tone on %d\n", p->channel);
10473          else
10474             sleep(1);
10475          res = ast_streamfile(chan, "ss-noservice", ast_channel_language(chan));
10476          if (res >= 0)
10477             ast_waitstream(chan, "");
10478          res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10479          ast_hangup(chan);
10480          goto quit;
10481       }
10482       break;
10483    case SIG_FXOLS:
10484    case SIG_FXOGS:
10485    case SIG_FXOKS:
10486       /* Read the first digit */
10487       timeout = firstdigittimeout;
10488       /* If starting a threeway call, never timeout on the first digit so someone
10489          can use flash-hook as a "hold" feature */
10490       if (p->subs[SUB_THREEWAY].owner)
10491          timeout = 999999;
10492       while (len < AST_MAX_EXTENSION-1) {
10493          /* Read digit unless it's supposed to be immediate, in which case the
10494             only answer is 's' */
10495          if (p->immediate)
10496             res = 's';
10497          else
10498             res = ast_waitfordigit(chan, timeout);
10499          timeout = 0;
10500          if (res < 0) {
10501             ast_debug(1, "waitfordigit returned < 0...\n");
10502             res = tone_zone_play_tone(p->subs[idx].dfd, -1);
10503             ast_hangup(chan);
10504             goto quit;
10505          } else if (res) {
10506             ast_debug(1,"waitfordigit returned '%c' (%d), timeout = %d\n", res, res, timeout);
10507             exten[len++]=res;
10508             exten[len] = '\0';
10509          }
10510          if (!ast_ignore_pattern(ast_channel_context(chan), exten))
10511             tone_zone_play_tone(p->subs[idx].dfd, -1);
10512          else
10513             tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
10514          if (ast_exists_extension(chan, ast_channel_context(chan), exten, 1, p->cid_num) && !ast_parking_ext_valid(exten, chan, ast_channel_context(chan))) {
10515             if (!res || !ast_matchmore_extension(chan, ast_channel_context(chan), exten, 1, p->cid_num)) {
10516                if (getforward) {
10517                   /* Record this as the forwarding extension */
10518                   ast_copy_string(p->call_forward, exten, sizeof(p->call_forward));
10519                   ast_verb(3, "Setting call forward to '%s' on channel %d\n", p->call_forward, p->channel);
10520                   res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10521                   if (res)
10522                      break;
10523                   usleep(500000);
10524                   res = tone_zone_play_tone(p->subs[idx].dfd, -1);
10525                   sleep(1);
10526                   memset(exten, 0, sizeof(exten));
10527                   res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
10528                   len = 0;
10529                   getforward = 0;
10530                } else {
10531                   res = tone_zone_play_tone(p->subs[idx].dfd, -1);
10532                   ast_channel_exten_set(chan, exten);
10533                   if (!ast_strlen_zero(p->cid_num)) {
10534                      if (!p->hidecallerid)
10535                         ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
10536                      else
10537                         ast_set_callerid(chan, NULL, NULL, p->cid_num);
10538                   }
10539                   if (!ast_strlen_zero(p->cid_name)) {
10540                      if (!p->hidecallerid)
10541                         ast_set_callerid(chan, NULL, p->cid_name, NULL);
10542                   }
10543                   ast_setstate(chan, AST_STATE_RING);
10544                   dahdi_enable_ec(p);
10545                   res = ast_pbx_run(chan);
10546                   if (res) {
10547                      ast_log(LOG_WARNING, "PBX exited non-zero\n");
10548                      res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10549                   }
10550                   goto quit;
10551                }
10552             } else {
10553                /* It's a match, but they just typed a digit, and there is an ambiguous match,
10554                   so just set the timeout to matchdigittimeout and wait some more */
10555                timeout = matchdigittimeout;
10556             }
10557          } else if (res == 0) {
10558             ast_debug(1, "not enough digits (and no ambiguous match)...\n");
10559             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10560             dahdi_wait_event(p->subs[idx].dfd);
10561             ast_hangup(chan);
10562             goto quit;
10563          } else if (p->callwaiting && !strcmp(exten, "*70")) {
10564             ast_verb(3, "Disabling call waiting on %s\n", ast_channel_name(chan));
10565             /* Disable call waiting if enabled */
10566             p->callwaiting = 0;
10567             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10568             if (res) {
10569                ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
10570                   ast_channel_name(chan), strerror(errno));
10571             }
10572             len = 0;
10573             ioctl(p->subs[idx].dfd,DAHDI_CONFDIAG,&len);
10574             memset(exten, 0, sizeof(exten));
10575             timeout = firstdigittimeout;
10576 
10577          } else if (!strcmp(exten,ast_pickup_ext())) {
10578             /* Scan all channels and see if there are any
10579              * ringing channels that have call groups
10580              * that equal this channels pickup group
10581              */
10582             if (idx == SUB_REAL) {
10583                /* Switch us from Third call to Call Wait */
10584                if (p->subs[SUB_THREEWAY].owner) {
10585                   /* If you make a threeway call and the *8# a call, it should actually
10586                      look like a callwait */
10587                   alloc_sub(p, SUB_CALLWAIT);
10588                   swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
10589                   unalloc_sub(p, SUB_THREEWAY);
10590                }
10591                dahdi_enable_ec(p);
10592                if (ast_pickup_call(chan)) {
10593                   ast_debug(1, "No call pickup possible...\n");
10594                   res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10595                   dahdi_wait_event(p->subs[idx].dfd);
10596                }
10597                ast_hangup(chan);
10598                goto quit;
10599             } else {
10600                ast_log(LOG_WARNING, "Huh?  Got *8# on call not on real\n");
10601                ast_hangup(chan);
10602                goto quit;
10603             }
10604 
10605          } else if (!p->hidecallerid && !strcmp(exten, "*67")) {
10606             ast_verb(3, "Disabling Caller*ID on %s\n", ast_channel_name(chan));
10607             /* Disable Caller*ID if enabled */
10608             p->hidecallerid = 1;
10609             ast_party_number_free(&ast_channel_caller(chan)->id.number);
10610             ast_party_number_init(&ast_channel_caller(chan)->id.number);
10611             ast_party_name_free(&ast_channel_caller(chan)->id.name);
10612             ast_party_name_init(&ast_channel_caller(chan)->id.name);
10613             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10614             if (res) {
10615                ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
10616                   ast_channel_name(chan), strerror(errno));
10617             }
10618             len = 0;
10619             memset(exten, 0, sizeof(exten));
10620             timeout = firstdigittimeout;
10621          } else if (p->callreturn && !strcmp(exten, "*69")) {
10622             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10623             break;
10624          } else if (!strcmp(exten, "*78")) {
10625             dahdi_dnd(p, 1);
10626             /* Do not disturb */
10627             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10628             getforward = 0;
10629             memset(exten, 0, sizeof(exten));
10630             len = 0;
10631          } else if (!strcmp(exten, "*79")) {
10632             dahdi_dnd(p, 0);
10633             /* Do not disturb */
10634             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10635             getforward = 0;
10636             memset(exten, 0, sizeof(exten));
10637             len = 0;
10638          } else if (p->cancallforward && !strcmp(exten, "*72")) {
10639             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10640             getforward = 1;
10641             memset(exten, 0, sizeof(exten));
10642             len = 0;
10643          } else if (p->cancallforward && !strcmp(exten, "*73")) {
10644             ast_verb(3, "Cancelling call forwarding on channel %d\n", p->channel);
10645             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10646             memset(p->call_forward, 0, sizeof(p->call_forward));
10647             getforward = 0;
10648             memset(exten, 0, sizeof(exten));
10649             len = 0;
10650          } else if ((p->transfer || p->canpark) && ast_parking_ext_valid(exten, chan, ast_channel_context(chan)) &&
10651                   p->subs[SUB_THREEWAY].owner &&
10652                   ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
10653             /* This is a three way call, the main call being a real channel,
10654                and we're parking the first call. */
10655             ast_masq_park_call_exten(ast_bridged_channel(p->subs[SUB_THREEWAY].owner),
10656                chan, exten, ast_channel_context(chan), 0, NULL);
10657             ast_verb(3, "Parking call to '%s'\n", ast_channel_name(chan));
10658             break;
10659          } else if (p->hidecallerid && !strcmp(exten, "*82")) {
10660             ast_verb(3, "Enabling Caller*ID on %s\n", ast_channel_name(chan));
10661             /* Enable Caller*ID if enabled */
10662             p->hidecallerid = 0;
10663             ast_set_callerid(chan, p->cid_num, p->cid_name, NULL);
10664             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10665             if (res) {
10666                ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
10667                   ast_channel_name(chan), strerror(errno));
10668             }
10669             len = 0;
10670             memset(exten, 0, sizeof(exten));
10671             timeout = firstdigittimeout;
10672          } else if (!strcmp(exten, "*0")) {
10673             struct ast_channel *nbridge =
10674                p->subs[SUB_THREEWAY].owner;
10675             struct dahdi_pvt *pbridge = NULL;
10676             /* set up the private struct of the bridged one, if any */
10677             if (nbridge && ast_bridged_channel(nbridge))
10678                pbridge = ast_channel_tech_pvt(ast_bridged_channel(nbridge));
10679             if (nbridge && pbridge &&
10680                (ast_channel_tech(nbridge) == &dahdi_tech) &&
10681                (ast_channel_tech(ast_bridged_channel(nbridge)) == &dahdi_tech) &&
10682                ISTRUNK(pbridge)) {
10683                int func = DAHDI_FLASH;
10684                /* Clear out the dial buffer */
10685                p->dop.dialstr[0] = '\0';
10686                /* flash hookswitch */
10687                if ((ioctl(pbridge->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
10688                   ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
10689                      ast_channel_name(nbridge), strerror(errno));
10690                }
10691                swap_subs(p, SUB_REAL, SUB_THREEWAY);
10692                unalloc_sub(p, SUB_THREEWAY);
10693                p->owner = p->subs[SUB_REAL].owner;
10694                if (ast_bridged_channel(p->subs[SUB_REAL].owner))
10695                   ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
10696                ast_hangup(chan);
10697                goto quit;
10698             } else {
10699                tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10700                dahdi_wait_event(p->subs[idx].dfd);
10701                tone_zone_play_tone(p->subs[idx].dfd, -1);
10702                swap_subs(p, SUB_REAL, SUB_THREEWAY);
10703                unalloc_sub(p, SUB_THREEWAY);
10704                p->owner = p->subs[SUB_REAL].owner;
10705                ast_hangup(chan);
10706                goto quit;
10707             }
10708          } else if (!ast_canmatch_extension(chan, ast_channel_context(chan), exten, 1,
10709             S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL))
10710             && !canmatch_featurecode(exten)) {
10711             ast_debug(1, "Can't match %s from '%s' in context %s\n", exten,
10712                S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, "<Unknown Caller>"),
10713                ast_channel_context(chan));
10714             break;
10715          }
10716          if (!timeout)
10717             timeout = gendigittimeout;
10718          if (len && !ast_ignore_pattern(ast_channel_context(chan), exten))
10719             tone_zone_play_tone(p->subs[idx].dfd, -1);
10720       }
10721       break;
10722    case SIG_FXSLS:
10723    case SIG_FXSGS:
10724    case SIG_FXSKS:
10725       /* check for SMDI messages */
10726       if (p->use_smdi && p->smdi_iface) {
10727          smdi_msg = ast_smdi_md_message_wait(p->smdi_iface, SMDI_MD_WAIT_TIMEOUT);
10728 
10729          if (smdi_msg != NULL) {
10730             ast_channel_exten_set(chan, smdi_msg->fwd_st);
10731 
10732             if (smdi_msg->type == 'B')
10733                pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "b");
10734             else if (smdi_msg->type == 'N')
10735                pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "u");
10736 
10737             ast_debug(1, "Received SMDI message on %s\n", ast_channel_name(chan));
10738          } else {
10739             ast_log(LOG_WARNING, "SMDI enabled but no SMDI message present\n");
10740          }
10741       }
10742 
10743       if (p->use_callerid && (p->cid_signalling == CID_SIG_SMDI && smdi_msg)) {
10744          number = smdi_msg->calling_st;
10745 
10746       /* If we want caller id, we're in a prering state due to a polarity reversal
10747        * and we're set to use a polarity reversal to trigger the start of caller id,
10748        * grab the caller id and wait for ringing to start... */
10749       } else if (p->use_callerid && (ast_channel_state(chan) == AST_STATE_PRERING &&
10750                    (p->cid_start == CID_START_POLARITY || p->cid_start == CID_START_POLARITY_IN || p->cid_start == CID_START_DTMF_NOALERT))) {
10751          /* If set to use DTMF CID signalling, listen for DTMF */
10752          if (p->cid_signalling == CID_SIG_DTMF) {
10753             int k = 0;
10754             int off_ms;
10755             struct timeval start = ast_tvnow();
10756             int ms;
10757             cs = NULL;
10758             ast_debug(1, "Receiving DTMF cid on channel %s\n", ast_channel_name(chan));
10759             dahdi_setlinear(p->subs[idx].dfd, 0);
10760             /*
10761              * We are the only party interested in the Rx stream since
10762              * we have not answered yet.  We don't need or even want DTMF
10763              * emulation.  The DTMF digits can come so fast that emulation
10764              * can drop some of them.
10765              */
10766             ast_set_flag(ast_channel_flags(chan), AST_FLAG_END_DTMF_ONLY);
10767             off_ms = 4000;/* This is a typical OFF time between rings. */
10768             for (;;) {
10769                struct ast_frame *f;
10770 
10771                ms = ast_remaining_ms(start, off_ms);
10772                res = ast_waitfor(chan, ms);
10773                if (res <= 0) {
10774                   /*
10775                    * We do not need to restore the dahdi_setlinear()
10776                    * or AST_FLAG_END_DTMF_ONLY flag settings since we
10777                    * are hanging up the channel.
10778                    */
10779                   ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
10780                      "Exiting simple switch\n");
10781                   ast_hangup(chan);
10782                   goto quit;
10783                }
10784                f = ast_read(chan);
10785                if (!f)
10786                   break;
10787                if (f->frametype == AST_FRAME_DTMF) {
10788                   if (k < ARRAY_LEN(dtmfbuf) - 1) {
10789                      dtmfbuf[k++] = f->subclass.integer;
10790                   }
10791                   ast_debug(1, "CID got digit '%c'\n", f->subclass.integer);
10792                   start = ast_tvnow();
10793                }
10794                ast_frfree(f);
10795                if (ast_channel_state(chan) == AST_STATE_RING ||
10796                   ast_channel_state(chan) == AST_STATE_RINGING)
10797                   break; /* Got ring */
10798             }
10799             ast_clear_flag(ast_channel_flags(chan), AST_FLAG_END_DTMF_ONLY);
10800             dtmfbuf[k] = '\0';
10801             dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10802             /* Got cid and ring. */
10803             ast_debug(1, "CID got string '%s'\n", dtmfbuf);
10804             callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
10805             ast_debug(1, "CID is '%s', flags %d\n", dtmfcid, flags);
10806             /* If first byte is NULL, we have no cid */
10807             if (!ast_strlen_zero(dtmfcid))
10808                number = dtmfcid;
10809             else
10810                number = NULL;
10811          /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */
10812          } else if ((p->cid_signalling == CID_SIG_V23) || (p->cid_signalling == CID_SIG_V23_JP)) {
10813             cs = callerid_new(p->cid_signalling);
10814             if (cs) {
10815                int off_ms;
10816                struct timeval start;
10817                int ms;
10818                samples = 0;
10819 #if 1
10820                bump_gains(p);
10821 #endif
10822                /* Take out of linear mode for Caller*ID processing */
10823                dahdi_setlinear(p->subs[idx].dfd, 0);
10824 
10825                /* First we wait and listen for the Caller*ID */
10826                for (;;) {
10827                   i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10828                   if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10829                      ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10830                      callerid_free(cs);
10831                      ast_hangup(chan);
10832                      goto quit;
10833                   }
10834                   if (i & DAHDI_IOMUX_SIGEVENT) {
10835                      res = dahdi_get_event(p->subs[idx].dfd);
10836                      ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10837                      if (res == DAHDI_EVENT_NOALARM) {
10838                         p->inalarm = 0;
10839                      }
10840 
10841                      if (p->cid_signalling == CID_SIG_V23_JP) {
10842                         if (res == DAHDI_EVENT_RINGBEGIN) {
10843                            res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
10844                            usleep(1);
10845                         }
10846                      } else {
10847                         res = 0;
10848                         break;
10849                      }
10850                   } else if (i & DAHDI_IOMUX_READ) {
10851                      res = read(p->subs[idx].dfd, buf, sizeof(buf));
10852                      if (res < 0) {
10853                         if (errno != ELAST) {
10854                            ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10855                            callerid_free(cs);
10856                            ast_hangup(chan);
10857                            goto quit;
10858                         }
10859                         break;
10860                      }
10861                      samples += res;
10862 
10863                      if (p->cid_signalling == CID_SIG_V23_JP) {
10864                         res = callerid_feed_jp(cs, buf, res, ast_format_set(&tmpfmt, AST_LAW(p), 0));
10865                      } else {
10866                         res = callerid_feed(cs, buf, res, ast_format_set(&tmpfmt, AST_LAW(p), 0));
10867                      }
10868                      if (res < 0) {
10869                         /*
10870                          * The previous diagnostic message output likely
10871                          * explains why it failed.
10872                          */
10873                         ast_log(LOG_WARNING,
10874                            "Failed to decode CallerID on channel '%s'\n",
10875                            ast_channel_name(chan));
10876                         break;
10877                      } else if (res)
10878                         break;
10879                      else if (samples > (8000 * 10))
10880                         break;
10881                   }
10882                }
10883                if (res == 1) {
10884                   callerid_get(cs, &name, &number, &flags);
10885                   ast_log(LOG_NOTICE, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
10886                }
10887 
10888                if (p->cid_signalling == CID_SIG_V23_JP) {
10889                   res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
10890                   usleep(1);
10891                }
10892 
10893                /* Finished with Caller*ID, now wait for a ring to make sure there really is a call coming */
10894                start = ast_tvnow();
10895                off_ms = 4000;/* This is a typical OFF time between rings. */
10896                for (;;) {
10897                   struct ast_frame *f;
10898 
10899                   ms = ast_remaining_ms(start, off_ms);
10900                   res = ast_waitfor(chan, ms);
10901                   if (res <= 0) {
10902                      ast_log(LOG_WARNING, "CID timed out waiting for ring. "
10903                         "Exiting simple switch\n");
10904                      ast_hangup(chan);
10905                      goto quit;
10906                   }
10907                   if (!(f = ast_read(chan))) {
10908                      ast_log(LOG_WARNING, "Hangup received waiting for ring. Exiting simple switch\n");
10909                      ast_hangup(chan);
10910                      goto quit;
10911                   }
10912                   ast_frfree(f);
10913                   if (ast_channel_state(chan) == AST_STATE_RING ||
10914                      ast_channel_state(chan) == AST_STATE_RINGING)
10915                      break; /* Got ring */
10916                }
10917 
10918                /* We must have a ring by now, so, if configured, lets try to listen for
10919                 * distinctive ringing */
10920                if (p->usedistinctiveringdetection) {
10921                   len = 0;
10922                   distMatches = 0;
10923                   /* Clear the current ring data array so we don't have old data in it. */
10924                   for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
10925                      curRingData[receivedRingT] = 0;
10926                   receivedRingT = 0;
10927                   counter = 0;
10928                   counter1 = 0;
10929                   /* Check to see if context is what it should be, if not set to be. */
10930                   if (strcmp(p->context,p->defcontext) != 0) {
10931                      ast_copy_string(p->context, p->defcontext, sizeof(p->context));
10932                      ast_channel_context_set(chan, p->defcontext);
10933                   }
10934 
10935                   for (;;) {
10936                      i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10937                      if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10938                         ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10939                         callerid_free(cs);
10940                         ast_hangup(chan);
10941                         goto quit;
10942                      }
10943                      if (i & DAHDI_IOMUX_SIGEVENT) {
10944                         res = dahdi_get_event(p->subs[idx].dfd);
10945                         ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10946                         if (res == DAHDI_EVENT_NOALARM) {
10947                            p->inalarm = 0;
10948                         }
10949                         res = 0;
10950                         /* Let us detect distinctive ring */
10951 
10952                         curRingData[receivedRingT] = p->ringt;
10953 
10954                         if (p->ringt < p->ringt_base/2)
10955                            break;
10956                         /* Increment the ringT counter so we can match it against
10957                            values in chan_dahdi.conf for distinctive ring */
10958                         if (++receivedRingT == ARRAY_LEN(curRingData))
10959                            break;
10960                      } else if (i & DAHDI_IOMUX_READ) {
10961                         res = read(p->subs[idx].dfd, buf, sizeof(buf));
10962                         if (res < 0) {
10963                            if (errno != ELAST) {
10964                               ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10965                               callerid_free(cs);
10966                               ast_hangup(chan);
10967                               goto quit;
10968                            }
10969                            break;
10970                         }
10971                         if (p->ringt > 0) {
10972                            if (!(--p->ringt)) {
10973                               res = -1;
10974                               break;
10975                            }
10976                         }
10977                      }
10978                   }
10979                      /* this only shows up if you have n of the dring patterns filled in */
10980                   ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
10981                   for (counter = 0; counter < 3; counter++) {
10982                      /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this
10983                      channel */
10984                      distMatches = 0;
10985                      for (counter1 = 0; counter1 < 3; counter1++) {
10986                         ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
10987                         if (p->drings.ringnum[counter].ring[counter1] == -1) {
10988                            ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
10989                            curRingData[counter1]);
10990                            distMatches++;
10991                         } else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
10992                               curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
10993                            ast_verb(3, "Ring pattern matched in range: %d to %d\n",
10994                            (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
10995                            (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
10996                            distMatches++;
10997                         }
10998                      }
10999 
11000                      if (distMatches == 3) {
11001                         /* The ring matches, set the context to whatever is for distinctive ring.. */
11002                         ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context));
11003                         ast_channel_context_set(chan, S_OR(p->drings.ringContext[counter].contextData, p->defcontext));
11004                         ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
11005                         break;
11006                      }
11007                   }
11008                }
11009                /* Restore linear mode (if appropriate) for Caller*ID processing */
11010                dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
11011 #if 1
11012                restore_gains(p);
11013 #endif
11014             } else
11015                ast_log(LOG_WARNING, "Unable to get caller ID space\n");
11016          } else {
11017             ast_log(LOG_WARNING, "Channel %s in prering "
11018                "state, but I have nothing to do. "
11019                "Terminating simple switch, should be "
11020                "restarted by the actual ring.\n",
11021                ast_channel_name(chan));
11022             ast_hangup(chan);
11023             goto quit;
11024          }
11025       } else if (p->use_callerid && p->cid_start == CID_START_RING) {
11026          if (p->cid_signalling == CID_SIG_DTMF) {
11027             int k = 0;
11028             int off_ms;
11029             struct timeval start;
11030             int ms;
11031             cs = NULL;
11032             dahdi_setlinear(p->subs[idx].dfd, 0);
11033             off_ms = 2000;
11034             start = ast_tvnow();
11035             for (;;) {
11036                struct ast_frame *f;
11037 
11038                ms = ast_remaining_ms(start, off_ms);
11039                res = ast_waitfor(chan, ms);
11040                if (res <= 0) {
11041                   ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
11042                      "Exiting simple switch\n");
11043                   ast_hangup(chan);
11044                   goto quit;
11045                }
11046                f = ast_read(chan);
11047                if (!f) {
11048                   /* Hangup received waiting for DTMFCID. Exiting simple switch. */
11049                   ast_hangup(chan);
11050                   goto quit;
11051                }
11052                if (f->frametype == AST_FRAME_DTMF) {
11053                   dtmfbuf[k++] = f->subclass.integer;
11054                   ast_debug(1, "CID got digit '%c'\n", f->subclass.integer);
11055                   start = ast_tvnow();
11056                }
11057                ast_frfree(f);
11058 
11059                if (p->ringt_base == p->ringt)
11060                   break;
11061             }
11062             dtmfbuf[k] = '\0';
11063             dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
11064             /* Got cid and ring. */
11065             callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
11066             ast_debug(1, "CID is '%s', flags %d\n",
11067                dtmfcid, flags);
11068             /* If first byte is NULL, we have no cid */
11069             if (!ast_strlen_zero(dtmfcid))
11070                number = dtmfcid;
11071             else
11072                number = NULL;
11073             /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */
11074          } else {
11075             /* FSK Bell202 callerID */
11076             cs = callerid_new(p->cid_signalling);
11077             if (cs) {
11078 #if 1
11079                bump_gains(p);
11080 #endif
11081                samples = 0;
11082                len = 0;
11083                distMatches = 0;
11084                /* Clear the current ring data array so we don't have old data in it. */
11085                for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
11086                   curRingData[receivedRingT] = 0;
11087                receivedRingT = 0;
11088                counter = 0;
11089                counter1 = 0;
11090                /* Check to see if context is what it should be, if not set to be. */
11091                if (strcmp(p->context,p->defcontext) != 0) {
11092                   ast_copy_string(p->context, p->defcontext, sizeof(p->context));
11093                   ast_channel_context_set(chan, p->defcontext);
11094                }
11095 
11096                /* Take out of linear mode for Caller*ID processing */
11097                dahdi_setlinear(p->subs[idx].dfd, 0);
11098                for (;;) {
11099                   i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
11100                   if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
11101                      ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
11102                      callerid_free(cs);
11103                      ast_hangup(chan);
11104                      goto quit;
11105                   }
11106                   if (i & DAHDI_IOMUX_SIGEVENT) {
11107                      res = dahdi_get_event(p->subs[idx].dfd);
11108                      ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
11109                      if (res == DAHDI_EVENT_NOALARM) {
11110                         p->inalarm = 0;
11111                      }
11112                      /* If we get a PR event, they hung up while processing calerid */
11113                      if ( res == DAHDI_EVENT_POLARITY && p->hanguponpolarityswitch && p->polarity == POLARITY_REV) {
11114                         ast_debug(1, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p->channel);
11115                         p->polarity = POLARITY_IDLE;
11116                         callerid_free(cs);
11117                         ast_hangup(chan);
11118                         goto quit;
11119                      }
11120                      res = 0;
11121                      /* Let us detect callerid when the telco uses distinctive ring */
11122 
11123                      curRingData[receivedRingT] = p->ringt;
11124 
11125                      if (p->ringt < p->ringt_base/2)
11126                         break;
11127                      /* Increment the ringT counter so we can match it against
11128                         values in chan_dahdi.conf for distinctive ring */
11129                      if (++receivedRingT == ARRAY_LEN(curRingData))
11130                         break;
11131                   } else if (i & DAHDI_IOMUX_READ) {
11132                      res = read(p->subs[idx].dfd, buf, sizeof(buf));
11133                      if (res < 0) {
11134                         if (errno != ELAST) {
11135                            ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
11136                            callerid_free(cs);
11137                            ast_hangup(chan);
11138                            goto quit;
11139                         }
11140                         break;
11141                      }
11142                      if (p->ringt > 0) {
11143                         if (!(--p->ringt)) {
11144                            res = -1;
11145                            break;
11146                         }
11147                      }
11148                      samples += res;
11149                      res = callerid_feed(cs, buf, res, ast_format_set(&tmpfmt, AST_LAW(p), 0));
11150                      if (res < 0) {
11151                         /*
11152                          * The previous diagnostic message output likely
11153                          * explains why it failed.
11154                          */
11155                         ast_log(LOG_WARNING,
11156                            "Failed to decode CallerID on channel '%s'\n",
11157                            ast_channel_name(chan));
11158                         break;
11159                      } else if (res)
11160                         break;
11161                      else if (samples > (8000 * 10))
11162                         break;
11163                   }
11164                }
11165                if (res == 1) {
11166                   callerid_get(cs, &name, &number, &flags);
11167                   ast_debug(1, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
11168                }
11169                if (distinctiveringaftercid == 1) {
11170                   /* Clear the current ring data array so we don't have old data in it. */
11171                   for (receivedRingT = 0; receivedRingT < 3; receivedRingT++) {
11172                      curRingData[receivedRingT] = 0;
11173                   }
11174                   receivedRingT = 0;
11175                   ast_verb(3, "Detecting post-CID distinctive ring\n");
11176                   for (;;) {
11177                      i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
11178                      if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
11179                         ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
11180                         callerid_free(cs);
11181                         ast_hangup(chan);
11182                         goto quit;
11183                      }
11184                      if (i & DAHDI_IOMUX_SIGEVENT) {
11185                         res = dahdi_get_event(p->subs[idx].dfd);
11186                         ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
11187                         if (res == DAHDI_EVENT_NOALARM) {
11188                            p->inalarm = 0;
11189                         }
11190                         res = 0;
11191                         /* Let us detect callerid when the telco uses distinctive ring */
11192 
11193                         curRingData[receivedRingT] = p->ringt;
11194 
11195                         if (p->ringt < p->ringt_base/2)
11196                            break;
11197                         /* Increment the ringT counter so we can match it against
11198                            values in chan_dahdi.conf for distinctive ring */
11199                         if (++receivedRingT == ARRAY_LEN(curRingData))
11200                            break;
11201                      } else if (i & DAHDI_IOMUX_READ) {
11202                         res = read(p->subs[idx].dfd, buf, sizeof(buf));
11203                         if (res < 0) {
11204                            if (errno != ELAST) {
11205                               ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
11206                               callerid_free(cs);
11207                               ast_hangup(chan);
11208                               goto quit;
11209                            }
11210                            break;
11211                         }
11212                         if (p->ringt > 0) {
11213                            if (!(--p->ringt)) {
11214                               res = -1;
11215                               break;
11216                            }
11217                         }
11218                      }
11219                   }
11220                }
11221                if (p->usedistinctiveringdetection) {
11222                   /* this only shows up if you have n of the dring patterns filled in */
11223                   ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
11224 
11225                   for (counter = 0; counter < 3; counter++) {
11226                      /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this
11227                      channel */
11228                      /* this only shows up if you have n of the dring patterns filled in */
11229                      ast_verb(3, "Checking %d,%d,%d\n",
11230                            p->drings.ringnum[counter].ring[0],
11231                            p->drings.ringnum[counter].ring[1],
11232                            p->drings.ringnum[counter].ring[2]);
11233                      distMatches = 0;
11234                      for (counter1 = 0; counter1 < 3; counter1++) {
11235                         ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
11236                         if (p->drings.ringnum[counter].ring[counter1] == -1) {
11237                            ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
11238                            curRingData[counter1]);
11239                            distMatches++;
11240                         }
11241                         else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
11242                            curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
11243                            ast_verb(3, "Ring pattern matched in range: %d to %d\n",
11244                            (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
11245                            (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
11246                            distMatches++;
11247                         }
11248                      }
11249                      if (distMatches == 3) {
11250                         /* The ring matches, set the context to whatever is for distinctive ring.. */
11251                         ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context));
11252                         ast_channel_context_set(chan, S_OR(p->drings.ringContext[counter].contextData, p->defcontext));
11253                         ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
11254                         break;
11255                      }
11256                   }
11257                }
11258                /* Restore linear mode (if appropriate) for Caller*ID processing */
11259                dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
11260 #if 1
11261                restore_gains(p);
11262 #endif
11263                if (res < 0) {
11264                   ast_log(LOG_WARNING, "CallerID returned with error on channel '%s'\n", ast_channel_name(chan));
11265                }
11266             } else
11267                ast_log(LOG_WARNING, "Unable to get caller ID space\n");
11268          }
11269       } else
11270          cs = NULL;
11271 
11272       if (number)
11273          ast_shrink_phone_number(number);
11274       ast_set_callerid(chan, number, name, number);
11275 
11276       if (smdi_msg)
11277          ASTOBJ_UNREF(smdi_msg, ast_smdi_md_message_destroy);
11278 
11279       if (cs)
11280          callerid_free(cs);
11281 
11282       my_handle_notify_message(chan, p, flags, -1);
11283 
11284       ast_setstate(chan, AST_STATE_RING);
11285       ast_channel_rings_set(chan, 1);
11286       p->ringt = p->ringt_base;
11287       res = ast_pbx_run(chan);
11288       if (res) {
11289          ast_hangup(chan);
11290          ast_log(LOG_WARNING, "PBX exited non-zero\n");
11291       }
11292       goto quit;
11293    default:
11294       ast_log(LOG_WARNING, "Don't know how to handle simple switch with signalling %s on channel %d\n", sig2str(p->sig), p->channel);
11295       res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
11296       if (res < 0)
11297             ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
11298    }
11299    res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
11300    if (res < 0)
11301          ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
11302    ast_hangup(chan);
11303 quit:
11304    ast_mutex_lock(&ss_thread_lock);
11305    ss_thread_count--;
11306    ast_cond_signal(&ss_thread_complete);
11307    ast_mutex_unlock(&ss_thread_lock);
11308    return NULL;
11309 }
11310 
11311 struct mwi_thread_data {
11312    struct dahdi_pvt *pvt;
11313    unsigned char buf[READ_SIZE];
11314    size_t len;
11315 };
11316 
11317 static int calc_energy(const unsigned char *buf, int len, enum ast_format_id law)
11318 {
11319    int x;
11320    int sum = 0;
11321 
11322    if (!len)
11323       return 0;
11324 
11325    for (x = 0; x < len; x++)
11326       sum += abs(law == AST_FORMAT_ULAW ? AST_MULAW(buf[x]) : AST_ALAW(buf[x]));
11327 
11328    return sum / len;
11329 }
11330 
11331 static void *mwi_thread(void *data)
11332 {
11333    struct mwi_thread_data *mtd = data;
11334    struct callerid_state *cs;
11335    pthread_t threadid;
11336    int samples = 0;
11337    char *name, *number;
11338    int flags;
11339    int i, res;
11340    unsigned int spill_done = 0;
11341    int spill_result = -1;
11342    struct ast_format tmpfmt;
11343 
11344    if (!(cs = callerid_new(mtd->pvt->cid_signalling))) {
11345       goto quit_no_clean;
11346    }
11347 
11348    callerid_feed(cs, mtd->buf, mtd->len, ast_format_set(&tmpfmt, AST_LAW(mtd->pvt), 0));
11349 
11350    bump_gains(mtd->pvt);
11351 
11352    for (;;) {
11353       i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
11354       if ((res = ioctl(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_IOMUX, &i))) {
11355          ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
11356          goto quit;
11357       }
11358 
11359       if (i & DAHDI_IOMUX_SIGEVENT) {
11360          struct ast_channel *chan;
11361          struct ast_callid *callid = NULL;
11362          int callid_created;
11363 
11364          /* If we get an event, screen out events that we do not act on.
11365           * Otherwise, cancel and go to the simple switch to let it deal with it.
11366           */
11367          res = dahdi_get_event(mtd->pvt->subs[SUB_REAL].dfd);
11368 
11369          switch (res) {
11370          case DAHDI_EVENT_NEONMWI_ACTIVE:
11371          case DAHDI_EVENT_NEONMWI_INACTIVE:
11372          case DAHDI_EVENT_NONE:
11373          case DAHDI_EVENT_BITSCHANGED:
11374             break;
11375          case DAHDI_EVENT_NOALARM:
11376             if (analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) {
11377                struct analog_pvt *analog_p = mtd->pvt->sig_pvt;
11378 
11379                analog_p->inalarm = 0;
11380             }
11381             mtd->pvt->inalarm = 0;
11382             handle_clear_alarms(mtd->pvt);
11383             break;
11384          case DAHDI_EVENT_ALARM:
11385             if (analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) {
11386                struct analog_pvt *analog_p = mtd->pvt->sig_pvt;
11387 
11388                analog_p->inalarm = 1;
11389             }
11390             mtd->pvt->inalarm = 1;
11391             res = get_alarms(mtd->pvt);
11392             handle_alarms(mtd->pvt, res);
11393             break; /* What to do on channel alarm ???? -- fall thru intentionally?? */
11394          default:
11395             callid_created = ast_callid_threadstorage_auto(&callid);
11396             ast_log(LOG_NOTICE, "Got event %d (%s)...  Passing along to analog_ss_thread\n", res, event2str(res));
11397             callerid_free(cs);
11398 
11399             restore_gains(mtd->pvt);
11400             mtd->pvt->ringt = mtd->pvt->ringt_base;
11401 
11402             if ((chan = dahdi_new(mtd->pvt, AST_STATE_RING, 0, SUB_REAL, 0, NULL, callid))) {
11403                int result;
11404 
11405                if (analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) {
11406                   result = analog_ss_thread_start(mtd->pvt->sig_pvt, chan);
11407                } else {
11408                   result = ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan);
11409                }
11410                if (result) {
11411                   ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", mtd->pvt->channel);
11412                   res = tone_zone_play_tone(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11413                   if (res < 0)
11414                      ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", mtd->pvt->channel);
11415                   ast_hangup(chan);
11416                }
11417             } else {
11418                ast_log(LOG_WARNING, "Could not create channel to handle call\n");
11419             }
11420 
11421             ast_callid_threadstorage_auto_clean(callid, callid_created);
11422             goto quit_no_clean;
11423          }
11424       } else if (i & DAHDI_IOMUX_READ) {
11425          if ((res = read(mtd->pvt->subs[SUB_REAL].dfd, mtd->buf, sizeof(mtd->buf))) < 0) {
11426             if (errno != ELAST) {
11427                ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
11428                goto quit;
11429             }
11430             break;
11431          }
11432          samples += res;
11433          if (!spill_done) {
11434             if ((spill_result = callerid_feed(cs, mtd->buf, res, ast_format_set(&tmpfmt, AST_LAW(mtd->pvt), 0))) < 0) {
11435                /*
11436                 * The previous diagnostic message output likely
11437                 * explains why it failed.
11438                 */
11439                ast_log(LOG_WARNING, "Failed to decode CallerID\n");
11440                break;
11441             } else if (spill_result) {
11442                spill_done = 1;
11443             }
11444          } else {
11445             /* keep reading data until the energy level drops below the threshold
11446                so we don't get another 'trigger' on the remaining carrier signal
11447             */
11448             if (calc_energy(mtd->buf, res, AST_LAW(mtd->pvt)) <= mwilevel)
11449                break;
11450          }
11451          if (samples > (8000 * 4)) /*Termination case - time to give up*/
11452             break;
11453       }
11454    }
11455 
11456    if (spill_result == 1) {
11457       callerid_get(cs, &name, &number, &flags);
11458       if (flags & CID_MSGWAITING) {
11459          ast_log(LOG_NOTICE, "mwi: Have Messages on channel %d\n", mtd->pvt->channel);
11460          notify_message(mtd->pvt->mailbox, 1);
11461       } else if (flags & CID_NOMSGWAITING) {
11462          ast_log(LOG_NOTICE, "mwi: No Messages on channel %d\n", mtd->pvt->channel);
11463          notify_message(mtd->pvt->mailbox, 0);
11464       } else {
11465          ast_log(LOG_NOTICE, "mwi: Status unknown on channel %d\n", mtd->pvt->channel);
11466       }
11467    }
11468 
11469 
11470 quit:
11471    callerid_free(cs);
11472 
11473    restore_gains(mtd->pvt);
11474 
11475 quit_no_clean:
11476    mtd->pvt->mwimonitoractive = 0;
11477    ast_free(mtd);
11478 
11479    return NULL;
11480 }
11481 
11482 /*
11483 * The following three functions (mwi_send_init, mwi_send_process_buffer,
11484 * mwi_send_process_event) work with the do_monitor thread to generate mwi spills
11485 * that are sent out via FXS port on voicemail state change.  The execution of
11486 * the mwi send is state driven and can either generate a ring pulse prior to
11487 * sending the fsk spill or simply send an fsk spill.
11488 */
11489 static int mwi_send_init(struct dahdi_pvt * pvt)
11490 {
11491    int x;
11492    struct ast_format tmpfmt;
11493 
11494 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11495    /* Determine how this spill is to be sent */
11496    if (pvt->mwisend_rpas) {
11497       pvt->mwisend_data.mwisend_current = MWI_SEND_SA;
11498       pvt->mwisendactive = 1;
11499    } else if (pvt->mwisend_fsk) {
11500       pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
11501       pvt->mwisendactive = 1;
11502    } else {
11503       pvt->mwisendactive = 0;
11504       return 0;
11505    }
11506 #else
11507    if (mwisend_rpas) {
11508       pvt->mwisend_data.mwisend_current = MWI_SEND_SA;
11509    } else {
11510       pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
11511    }
11512    pvt->mwisendactive = 1;
11513 #endif
11514 
11515    if (pvt->cidspill) {
11516       ast_log(LOG_WARNING, "cidspill already exists when trying to send FSK MWI\n");
11517       ast_free(pvt->cidspill);
11518       pvt->cidspill = NULL;
11519       pvt->cidpos = 0;
11520       pvt->cidlen = 0;
11521    }
11522    pvt->cidspill = ast_calloc(1, MAX_CALLERID_SIZE);
11523    if (!pvt->cidspill) {
11524       pvt->mwisendactive = 0;
11525       return -1;
11526    }
11527    x = DAHDI_FLUSH_BOTH;
11528    ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
11529    x = 3000;
11530    ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_ONHOOKTRANSFER, &x);
11531 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11532    if (pvt->mwisend_fsk) {
11533 #endif
11534       pvt->cidlen = ast_callerid_vmwi_generate(pvt->cidspill, has_voicemail(pvt), CID_MWI_TYPE_MDMF_FULL,
11535                       ast_format_set(&tmpfmt, AST_LAW(pvt), 0), pvt->cid_name, pvt->cid_num, 0);
11536       pvt->cidpos = 0;
11537 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11538    }
11539 #endif
11540    return 0;
11541 }
11542 
11543 static int mwi_send_process_buffer(struct dahdi_pvt * pvt, int num_read)
11544 {
11545    struct timeval    now;
11546    int         res;
11547 
11548    /* sanity check to catch if this had been interrupted previously
11549    *  i.e. state says there is more to do but there is no spill allocated
11550    */
11551    if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current && !pvt->cidspill) {
11552       pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11553    } else if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current) {
11554       /* Normal processing -- Perform mwi send action */
11555       switch ( pvt->mwisend_data.mwisend_current) {
11556       case MWI_SEND_SA:
11557          /* Send the Ring Pulse Signal Alert */
11558          res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &AS_RP_cadence);
11559          if (res) {
11560             ast_log(LOG_WARNING, "Unable to set RP-AS ring cadence: %s\n", strerror(errno));
11561             goto quit;
11562          }
11563          res = dahdi_set_hook(pvt->subs[SUB_REAL].dfd, DAHDI_RING);
11564          pvt->mwisend_data.mwisend_current = MWI_SEND_SA_WAIT;
11565          break;
11566       case MWI_SEND_SA_WAIT:  /* do nothing until I get RINGEROFF event */
11567          break;
11568       case MWI_SEND_PAUSE:  /* Wait between alert and spill - min of 500 mS*/
11569 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11570          if (pvt->mwisend_fsk) {
11571 #endif
11572             gettimeofday(&now, NULL);
11573             if ((int)(now.tv_sec - pvt->mwisend_data.pause.tv_sec) * 1000000 + (int)now.tv_usec - (int)pvt->mwisend_data.pause.tv_usec > 500000) {
11574                pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
11575             }
11576 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11577          } else { /* support for mwisendtype=nofsk */
11578             pvt->mwisend_data.mwisend_current = MWI_SEND_CLEANUP;
11579          }
11580 #endif
11581          break;
11582       case MWI_SEND_SPILL:
11583          /* We read some number of bytes.  Write an equal amount of data */
11584          if(0 < num_read) {
11585             if (num_read > pvt->cidlen - pvt->cidpos)
11586                num_read = pvt->cidlen - pvt->cidpos;
11587             res = write(pvt->subs[SUB_REAL].dfd, pvt->cidspill + pvt->cidpos, num_read);
11588             if (res > 0) {
11589                pvt->cidpos += res;
11590                if (pvt->cidpos >= pvt->cidlen) {
11591                   pvt->mwisend_data.mwisend_current = MWI_SEND_CLEANUP;
11592                }
11593             } else {
11594                ast_log(LOG_WARNING, "MWI FSK Send Write failed: %s\n", strerror(errno));
11595                goto quit;
11596             }
11597          }
11598          break;
11599       case MWI_SEND_CLEANUP:
11600          /* For now, do nothing */
11601          pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11602          break;
11603       default:
11604          /* Should not get here, punt*/
11605          goto quit;
11606       }
11607    }
11608 
11609    if (MWI_SEND_DONE == pvt->mwisend_data.mwisend_current) {
11610       if (pvt->cidspill) {
11611          ast_free(pvt->cidspill);
11612          pvt->cidspill = NULL;
11613          pvt->cidpos = 0;
11614          pvt->cidlen = 0;
11615       }
11616       pvt->mwisendactive = 0;
11617    }
11618    return 0;
11619 quit:
11620    if (pvt->cidspill) {
11621       ast_free(pvt->cidspill);
11622       pvt->cidspill = NULL;
11623       pvt->cidpos = 0;
11624       pvt->cidlen = 0;
11625    }
11626    pvt->mwisendactive = 0;
11627    return -1;
11628 }
11629 
11630 static int mwi_send_process_event(struct dahdi_pvt * pvt, int event)
11631 {
11632    int handled = 0;
11633 
11634    if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current) {
11635       switch (event) {
11636       case DAHDI_EVENT_RINGEROFF:
11637          if(pvt->mwisend_data.mwisend_current == MWI_SEND_SA_WAIT) {
11638             handled = 1;
11639 
11640             if (dahdi_set_hook(pvt->subs[SUB_REAL].dfd, DAHDI_RINGOFF) ) {
11641                ast_log(LOG_WARNING, "Unable to finish RP-AS: %s mwi send aborted\n", strerror(errno));
11642                ast_free(pvt->cidspill);
11643                pvt->cidspill = NULL;
11644                pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11645                pvt->mwisendactive = 0;
11646             } else {
11647                pvt->mwisend_data.mwisend_current = MWI_SEND_PAUSE;
11648                gettimeofday(&pvt->mwisend_data.pause, NULL);
11649             }
11650          }
11651          break;
11652       /* Going off hook, I need to punt this spill */
11653       case DAHDI_EVENT_RINGOFFHOOK:
11654          if (pvt->cidspill) {
11655             ast_free(pvt->cidspill);
11656             pvt->cidspill = NULL;
11657             pvt->cidpos = 0;
11658             pvt->cidlen = 0;
11659          }
11660          pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11661          pvt->mwisendactive = 0;
11662          break;
11663       case DAHDI_EVENT_RINGERON:
11664       case DAHDI_EVENT_HOOKCOMPLETE:
11665          break;
11666       default:
11667          break;
11668       }
11669    }
11670    return handled;
11671 }
11672 
11673 /* destroy a DAHDI channel, identified by its number */
11674 static int dahdi_destroy_channel_bynum(int channel)
11675 {
11676    struct dahdi_pvt *cur;
11677 
11678    ast_mutex_lock(&iflock);
11679    for (cur = iflist; cur; cur = cur->next) {
11680       if (cur->channel == channel) {
11681          int x = DAHDI_FLASH;
11682 
11683          /* important to create an event for dahdi_wait_event to register so that all analog_ss_threads terminate */
11684          ioctl(cur->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
11685 
11686          destroy_channel(cur, 1);
11687          ast_mutex_unlock(&iflock);
11688          ast_module_unref(ast_module_info->self);
11689          return RESULT_SUCCESS;
11690       }
11691    }
11692    ast_mutex_unlock(&iflock);
11693    return RESULT_FAILURE;
11694 }
11695 
11696 static struct dahdi_pvt *handle_init_event(struct dahdi_pvt *i, int event)
11697 {
11698    int res;
11699    pthread_t threadid;
11700    struct ast_channel *chan;
11701    struct ast_callid *callid = NULL;
11702    int callid_created;
11703 
11704    /* Handle an event on a given channel for the monitor thread. */
11705 
11706    switch (event) {
11707    case DAHDI_EVENT_NONE:
11708    case DAHDI_EVENT_BITSCHANGED:
11709       break;
11710    case DAHDI_EVENT_WINKFLASH:
11711    case DAHDI_EVENT_RINGOFFHOOK:
11712       if (i->inalarm) break;
11713       if (i->radio) break;
11714       /* Got a ring/answer.  What kind of channel are we? */
11715       switch (i->sig) {
11716       case SIG_FXOLS:
11717       case SIG_FXOGS:
11718       case SIG_FXOKS:
11719          res = dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
11720          if (res && (errno == EBUSY)) {
11721             break;
11722          }
11723 
11724          callid_created = ast_callid_threadstorage_auto(&callid);
11725 
11726          /* Cancel VMWI spill */
11727          ast_free(i->cidspill);
11728          i->cidspill = NULL;
11729          restore_conference(i);
11730 
11731          if (i->immediate) {
11732             dahdi_enable_ec(i);
11733             /* The channel is immediately up.  Start right away */
11734             res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
11735             chan = dahdi_new(i, AST_STATE_RING, 1, SUB_REAL, 0, NULL, callid);
11736             if (!chan) {
11737                ast_log(LOG_WARNING, "Unable to start PBX on channel %d\n", i->channel);
11738                res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11739                if (res < 0)
11740                   ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11741             }
11742          } else {
11743             /* Check for callerid, digits, etc */
11744             chan = dahdi_new(i, AST_STATE_RESERVED, 0, SUB_REAL, 0, NULL, callid);
11745             if (chan) {
11746                if (has_voicemail(i))
11747                   res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
11748                else
11749                   res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
11750                if (res < 0)
11751                   ast_log(LOG_WARNING, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i->channel);
11752                if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
11753                   ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11754                   res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11755                   if (res < 0)
11756                      ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11757                   ast_hangup(chan);
11758                }
11759             } else
11760                ast_log(LOG_WARNING, "Unable to create channel\n");
11761          }
11762 
11763          ast_callid_threadstorage_auto_clean(callid, callid_created);
11764          break;
11765       case SIG_FXSLS:
11766       case SIG_FXSGS:
11767       case SIG_FXSKS:
11768             i->ringt = i->ringt_base;
11769             /* Fall through */
11770       case SIG_EMWINK:
11771       case SIG_FEATD:
11772       case SIG_FEATDMF:
11773       case SIG_FEATDMF_TA:
11774       case SIG_E911:
11775       case SIG_FGC_CAMA:
11776       case SIG_FGC_CAMAMF:
11777       case SIG_FEATB:
11778       case SIG_EM:
11779       case SIG_EM_E1:
11780       case SIG_SFWINK:
11781       case SIG_SF_FEATD:
11782       case SIG_SF_FEATDMF:
11783       case SIG_SF_FEATB:
11784       case SIG_SF:
11785          /* Check for callerid, digits, etc */
11786          callid_created = ast_callid_threadstorage_auto(&callid);
11787          if (i->cid_start == CID_START_POLARITY_IN) {
11788             chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL, callid);
11789          } else {
11790             chan = dahdi_new(i, AST_STATE_RING, 0, SUB_REAL, 0, NULL, callid);
11791          }
11792 
11793          if (!chan) {
11794             ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
11795          } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
11796             ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11797             res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11798             if (res < 0) {
11799                ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11800             }
11801             ast_hangup(chan);
11802          }
11803 
11804          ast_callid_threadstorage_auto_clean(callid, callid_created);
11805          break;
11806       default:
11807          ast_log(LOG_WARNING, "Don't know how to handle ring/answer with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
11808          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11809          if (res < 0)
11810             ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11811          return NULL;
11812       }
11813       break;
11814    case DAHDI_EVENT_NOALARM:
11815       switch (i->sig) {
11816 #if defined(HAVE_PRI)
11817       case SIG_PRI_LIB_HANDLE_CASES:
11818          ast_mutex_lock(&i->lock);
11819          sig_pri_chan_alarm_notify(i->sig_pvt, 1);
11820          ast_mutex_unlock(&i->lock);
11821          break;
11822 #endif   /* defined(HAVE_PRI) */
11823 #if defined(HAVE_SS7)
11824       case SIG_SS7:
11825          sig_ss7_set_alarm(i->sig_pvt, 0);
11826          break;
11827 #endif   /* defined(HAVE_SS7) */
11828       default:
11829          i->inalarm = 0;
11830          break;
11831       }
11832       handle_clear_alarms(i);
11833       break;
11834    case DAHDI_EVENT_ALARM:
11835       switch (i->sig) {
11836 #if defined(HAVE_PRI)
11837       case SIG_PRI_LIB_HANDLE_CASES:
11838          ast_mutex_lock(&i->lock);
11839          sig_pri_chan_alarm_notify(i->sig_pvt, 0);
11840          ast_mutex_unlock(&i->lock);
11841          break;
11842 #endif   /* defined(HAVE_PRI) */
11843 #if defined(HAVE_SS7)
11844       case SIG_SS7:
11845          sig_ss7_set_alarm(i->sig_pvt, 1);
11846          break;
11847 #endif   /* defined(HAVE_SS7) */
11848       default:
11849          i->inalarm = 1;
11850          break;
11851       }
11852       res = get_alarms(i);
11853       handle_alarms(i, res);
11854       /* fall thru intentionally */
11855    case DAHDI_EVENT_ONHOOK:
11856       if (i->radio)
11857          break;
11858       /* Back on hook.  Hang up. */
11859       switch (i->sig) {
11860       case SIG_FXOLS:
11861       case SIG_FXOGS:
11862       case SIG_FEATD:
11863       case SIG_FEATDMF:
11864       case SIG_FEATDMF_TA:
11865       case SIG_E911:
11866       case SIG_FGC_CAMA:
11867       case SIG_FGC_CAMAMF:
11868       case SIG_FEATB:
11869       case SIG_EM:
11870       case SIG_EM_E1:
11871       case SIG_EMWINK:
11872       case SIG_SF_FEATD:
11873       case SIG_SF_FEATDMF:
11874       case SIG_SF_FEATB:
11875       case SIG_SF:
11876       case SIG_SFWINK:
11877       case SIG_FXSLS:
11878       case SIG_FXSGS:
11879       case SIG_FXSKS:
11880       case SIG_FXOKS:
11881          dahdi_disable_ec(i);
11882          /* Diddle the battery for the zhone */
11883 #ifdef ZHONE_HACK
11884          dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
11885          usleep(1);
11886 #endif
11887          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
11888          dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
11889          break;
11890       case SIG_SS7:
11891       case SIG_PRI_LIB_HANDLE_CASES:
11892          dahdi_disable_ec(i);
11893          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
11894          break;
11895       default:
11896          ast_log(LOG_WARNING, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
11897          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
11898          return NULL;
11899       }
11900       break;
11901    case DAHDI_EVENT_POLARITY:
11902       switch (i->sig) {
11903       case SIG_FXSLS:
11904       case SIG_FXSKS:
11905       case SIG_FXSGS:
11906          /* We have already got a PR before the channel was
11907             created, but it wasn't handled. We need polarity
11908             to be REV for remote hangup detection to work.
11909             At least in Spain */
11910          callid_created = ast_callid_threadstorage_auto(&callid);
11911          if (i->hanguponpolarityswitch)
11912             i->polarity = POLARITY_REV;
11913          if (i->cid_start == CID_START_POLARITY || i->cid_start == CID_START_POLARITY_IN) {
11914             i->polarity = POLARITY_REV;
11915             ast_verb(2, "Starting post polarity "
11916                "CID detection on channel %d\n",
11917                i->channel);
11918             chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL, callid);
11919             if (!chan) {
11920                ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
11921             } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
11922                ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11923                ast_hangup(chan);
11924             }
11925          }
11926          ast_callid_threadstorage_auto_clean(callid, callid_created);
11927          break;
11928       default:
11929          ast_log(LOG_WARNING, "handle_init_event detected "
11930             "polarity reversal on non-FXO (SIG_FXS) "
11931             "interface %d\n", i->channel);
11932       }
11933       break;
11934    case DAHDI_EVENT_REMOVED: /* destroy channel, will actually do so in do_monitor */
11935       ast_log(LOG_NOTICE,
11936             "Got DAHDI_EVENT_REMOVED. Destroying channel %d\n",
11937             i->channel);
11938       return i;
11939    case DAHDI_EVENT_NEONMWI_ACTIVE:
11940       if (i->mwimonitor_neon) {
11941          notify_message(i->mailbox, 1);
11942          ast_log(LOG_NOTICE, "NEON MWI set for channel %d, mailbox %s \n", i->channel, i->mailbox);
11943       }
11944       break;
11945    case DAHDI_EVENT_NEONMWI_INACTIVE:
11946       if (i->mwimonitor_neon) {
11947          notify_message(i->mailbox, 0);
11948          ast_log(LOG_NOTICE, "NEON MWI cleared for channel %d, mailbox %s\n", i->channel, i->mailbox);
11949       }
11950       break;
11951    }
11952    return NULL;
11953 }
11954 
11955 static void monitor_pfds_clean(void *arg) {
11956    struct pollfd **pfds = arg;
11957    ast_free(*pfds);
11958 }
11959 
11960 static void *do_monitor(void *data)
11961 {
11962    int count, res, res2, spoint, pollres=0;
11963    struct dahdi_pvt *i;
11964    struct dahdi_pvt *last = NULL;
11965    struct dahdi_pvt *doomed;
11966    time_t thispass = 0, lastpass = 0;
11967    int found;
11968    char buf[1024];
11969    struct pollfd *pfds=NULL;
11970    int lastalloc = -1;
11971    /* This thread monitors all the frame relay interfaces which are not yet in use
11972       (and thus do not have a separate thread) indefinitely */
11973    /* From here on out, we die whenever asked */
11974 #if 0
11975    if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) {
11976       ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n");
11977       return NULL;
11978    }
11979    ast_debug(1, "Monitor starting...\n");
11980 #endif
11981    pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
11982 
11983    pthread_cleanup_push(monitor_pfds_clean, &pfds);
11984    for (;;) {
11985       /* Lock the interface list */
11986       ast_mutex_lock(&iflock);
11987       if (!pfds || (lastalloc != ifcount)) {
11988          if (pfds) {
11989             ast_free(pfds);
11990             pfds = NULL;
11991          }
11992          if (ifcount) {
11993             if (!(pfds = ast_calloc(1, ifcount * sizeof(*pfds)))) {
11994                ast_mutex_unlock(&iflock);
11995                return NULL;
11996             }
11997          }
11998          lastalloc = ifcount;
11999       }
12000       /* Build the stuff we're going to poll on, that is the socket of every
12001          dahdi_pvt that does not have an associated owner channel */
12002       count = 0;
12003       for (i = iflist; i; i = i->next) {
12004          ast_mutex_lock(&i->lock);
12005          if (pfds && (i->subs[SUB_REAL].dfd > -1) && i->sig && (!i->radio) && !(i->sig & SIG_MFCR2)) {
12006             if (analog_lib_handles(i->sig, i->radio, i->oprmode)) {
12007                struct analog_pvt *p = i->sig_pvt;
12008 
12009                if (!p) {
12010                   ast_log(LOG_ERROR, "No sig_pvt?\n");
12011                } else if (!p->owner && !p->subs[SUB_REAL].owner) {
12012                   /* This needs to be watched, as it lacks an owner */
12013                   pfds[count].fd = i->subs[SUB_REAL].dfd;
12014                   pfds[count].events = POLLPRI;
12015                   pfds[count].revents = 0;
12016                   /* Message waiting or r2 channels also get watched for reading */
12017                   if (i->cidspill || i->mwisendactive || i->mwimonitor_fsk || 
12018                      (i->cid_start == CID_START_DTMF_NOALERT && (i->sig == SIG_FXSLS || i->sig == SIG_FXSGS || i->sig == SIG_FXSKS))) {
12019                      pfds[count].events |= POLLIN;
12020                   }
12021                   count++;
12022                }
12023             } else {
12024                if (!i->owner && !i->subs[SUB_REAL].owner && !i->mwimonitoractive ) {
12025                   /* This needs to be watched, as it lacks an owner */
12026                   pfds[count].fd = i->subs[SUB_REAL].dfd;
12027                   pfds[count].events = POLLPRI;
12028                   pfds[count].revents = 0;
12029                   /* If we are monitoring for VMWI or sending CID, we need to
12030                      read from the channel as well */
12031                   if (i->cidspill || i->mwisendactive || i->mwimonitor_fsk ||
12032                      (i->cid_start == CID_START_DTMF_NOALERT && (i->sig == SIG_FXSLS || i->sig == SIG_FXSGS || i->sig == SIG_FXSKS))) {
12033                      pfds[count].events |= POLLIN;
12034                   }
12035                   count++;
12036                }
12037             }
12038          }
12039          ast_mutex_unlock(&i->lock);
12040       }
12041       /* Okay, now that we know what to do, release the interface lock */
12042       ast_mutex_unlock(&iflock);
12043 
12044       pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
12045       pthread_testcancel();
12046       /* Wait at least a second for something to happen */
12047       res = poll(pfds, count, 1000);
12048       pthread_testcancel();
12049       pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
12050 
12051       /* Okay, poll has finished.  Let's see what happened.  */
12052       if (res < 0) {
12053          if ((errno != EAGAIN) && (errno != EINTR))
12054             ast_log(LOG_WARNING, "poll return %d: %s\n", res, strerror(errno));
12055          continue;
12056       }
12057       /* Alright, lock the interface list again, and let's look and see what has
12058          happened */
12059       ast_mutex_lock(&iflock);
12060       found = 0;
12061       spoint = 0;
12062       lastpass = thispass;
12063       thispass = time(NULL);
12064       doomed = NULL;
12065       for (i = iflist;; i = i->next) {
12066          if (doomed) {
12067             int res;
12068             res = dahdi_destroy_channel_bynum(doomed->channel);
12069             if (res != RESULT_SUCCESS) {
12070                ast_log(LOG_WARNING, "Couldn't find channel to destroy, hopefully another destroy operation just happened.\n");
12071             }
12072             doomed = NULL;
12073          }
12074          if (!i) {
12075             break;
12076          }
12077 
12078          if (thispass != lastpass) {
12079             if (!found && ((i == last) || ((i == iflist) && !last))) {
12080                last = i;
12081                if (last) {
12082                   struct analog_pvt *analog_p = last->sig_pvt;
12083                   /* Only allow MWI to be initiated on a quiescent fxs port */
12084                   if (analog_p
12085                      && !last->mwisendactive
12086                      && (last->sig & __DAHDI_SIG_FXO)
12087                      && !analog_p->fxsoffhookstate
12088                      && !last->owner
12089                      && !ast_strlen_zero(last->mailbox)
12090                      && (thispass - analog_p->onhooktime > 3)) {
12091                      res = has_voicemail(last);
12092                      if (analog_p->msgstate != res) {
12093                         /* Set driver resources for signalling VMWI */
12094                         res2 = ioctl(last->subs[SUB_REAL].dfd, DAHDI_VMWI, &res);
12095                         if (res2) {
12096                            /* TODO: This message will ALWAYS be generated on some cards; any way to restrict it to those cards where it is interesting? */
12097                            ast_debug(3, "Unable to control message waiting led on channel %d: %s\n", last->channel, strerror(errno));
12098                         }
12099                         /* If enabled for FSK spill then initiate it */
12100                         if (mwi_send_init(last)) {
12101                            ast_log(LOG_WARNING, "Unable to initiate mwi send sequence on channel %d\n", last->channel);
12102                         }
12103                         analog_p->msgstate = res;
12104                         found ++;
12105                      }
12106                   }
12107                   last = last->next;
12108                }
12109             }
12110          }
12111          if ((i->subs[SUB_REAL].dfd > -1) && i->sig) {
12112             if (i->radio && !i->owner)
12113             {
12114                res = dahdi_get_event(i->subs[SUB_REAL].dfd);
12115                if (res)
12116                {
12117                   ast_debug(1, "Monitor doohicky got event %s on radio channel %d\n", event2str(res), i->channel);
12118                   /* Don't hold iflock while handling init events */
12119                   ast_mutex_unlock(&iflock);
12120                   if (analog_lib_handles(i->sig, i->radio, i->oprmode))
12121                      doomed = (struct dahdi_pvt *) analog_handle_init_event(i->sig_pvt, dahdievent_to_analogevent(res));
12122                   else
12123                      doomed = handle_init_event(i, res);
12124                   ast_mutex_lock(&iflock);
12125                }
12126                continue;
12127             }
12128             pollres = ast_fdisset(pfds, i->subs[SUB_REAL].dfd, count, &spoint);
12129             if (pollres & POLLIN) {
12130                if (i->owner || i->subs[SUB_REAL].owner) {
12131 #ifdef HAVE_PRI
12132                   if (!i->pri)
12133 #endif
12134                      ast_log(LOG_WARNING, "Whoa....  I'm owned but found (%d) in read...\n", i->subs[SUB_REAL].dfd);
12135                   continue;
12136                }
12137                if (!i->mwimonitor_fsk && !i->mwisendactive  && i->cid_start != CID_START_DTMF_NOALERT) {
12138                   ast_log(LOG_WARNING, "Whoa....  I'm not looking for MWI or sending MWI but am reading (%d)...\n", i->subs[SUB_REAL].dfd);
12139                   continue;
12140                }
12141                res = read(i->subs[SUB_REAL].dfd, buf, sizeof(buf));
12142                if (res > 0) {
12143                   if (i->mwimonitor_fsk) {
12144                      if (calc_energy((unsigned char *) buf, res, AST_LAW(i)) > mwilevel) {
12145                         pthread_attr_t attr;
12146                         pthread_t threadid;
12147                         struct mwi_thread_data *mtd;
12148 
12149                         pthread_attr_init(&attr);
12150                         pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
12151 
12152                         ast_debug(1, "Maybe some MWI on port %d!\n", i->channel);
12153                         if ((mtd = ast_calloc(1, sizeof(*mtd)))) {
12154                            mtd->pvt = i;
12155                            memcpy(mtd->buf, buf, res);
12156                            mtd->len = res;
12157                            i->mwimonitoractive = 1;
12158                            if (ast_pthread_create_background(&threadid, &attr, mwi_thread, mtd)) {
12159                               ast_log(LOG_WARNING, "Unable to start mwi thread on channel %d\n", i->channel);
12160                               i->mwimonitoractive = 0;
12161                               ast_free(mtd);
12162                            }
12163                         }
12164                      }
12165                   /* If configured to check for a DTMF CID spill that comes without alert (e.g no polarity reversal) */
12166                   } else if (i->cid_start == CID_START_DTMF_NOALERT) {
12167                      int energy;
12168                      struct timeval now;
12169                      /* State machine dtmfcid_holdoff_state allows for the line to settle
12170                       * before checking agin for dtmf energy.  Presently waits for 500 mS before checking again 
12171                      */
12172                      if (1 == i->dtmfcid_holdoff_state) {
12173                         gettimeofday(&i->dtmfcid_delay, NULL);
12174                         i->dtmfcid_holdoff_state = 2;
12175                      } else if (2 == i->dtmfcid_holdoff_state) {
12176                         gettimeofday(&now, NULL);
12177                         if ((int)(now.tv_sec - i->dtmfcid_delay.tv_sec) * 1000000 + (int)now.tv_usec - (int)i->dtmfcid_delay.tv_usec > 500000) {
12178                            i->dtmfcid_holdoff_state = 0;
12179                         }
12180                      } else {
12181                         energy = calc_energy((unsigned char *) buf, res, AST_LAW(i));
12182                         if (!i->mwisendactive && energy > dtmfcid_level) {
12183                            pthread_t threadid;
12184                            struct ast_channel *chan;
12185                            ast_mutex_unlock(&iflock);
12186                            if (analog_lib_handles(i->sig, i->radio, i->oprmode)) {
12187                               /* just in case this event changes or somehow destroys a channel, set doomed here too */
12188                               doomed = analog_handle_init_event(i->sig_pvt, ANALOG_EVENT_DTMFCID);  
12189                               i->dtmfcid_holdoff_state = 1;
12190                            } else {
12191                               struct ast_callid *callid = NULL;
12192                               int callid_created = ast_callid_threadstorage_auto(&callid);
12193                               chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL, callid);
12194                               if (!chan) {
12195                                  ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
12196                               } else {
12197                                  res = ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan);
12198                                  if (res) {
12199                                     ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
12200                                     ast_hangup(chan);
12201                                  } else {
12202                                     i->dtmfcid_holdoff_state = 1;
12203                                  }
12204                               }
12205                               ast_callid_threadstorage_auto_clean(callid, callid_created);
12206                            }
12207                            ast_mutex_lock(&iflock);
12208                         }
12209                      }
12210                   }
12211                   if (i->mwisendactive) {
12212                      mwi_send_process_buffer(i, res);
12213                   }
12214                } else {
12215                   ast_log(LOG_WARNING, "Read failed with %d: %s\n", res, strerror(errno));
12216                }
12217             }
12218             if (pollres & POLLPRI) {
12219                if (i->owner || i->subs[SUB_REAL].owner) {
12220 #ifdef HAVE_PRI
12221                   if (!i->pri)
12222 #endif
12223                      ast_log(LOG_WARNING, "Whoa....  I'm owned but found (%d)...\n", i->subs[SUB_REAL].dfd);
12224                   continue;
12225                }
12226                res = dahdi_get_event(i->subs[SUB_REAL].dfd);
12227                ast_debug(1, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel);
12228                /* Don't hold iflock while handling init events */
12229                ast_mutex_unlock(&iflock);
12230                if (0 == i->mwisendactive || 0 == mwi_send_process_event(i, res)) {
12231                   if (analog_lib_handles(i->sig, i->radio, i->oprmode))
12232                      doomed = (struct dahdi_pvt *) analog_handle_init_event(i->sig_pvt, dahdievent_to_analogevent(res));
12233                   else
12234                      doomed = handle_init_event(i, res);
12235                }
12236                ast_mutex_lock(&iflock);
12237             }
12238          }
12239       }
12240       ast_mutex_unlock(&iflock);
12241    }
12242    /* Never reached */
12243    pthread_cleanup_pop(1);
12244    return NULL;
12245 
12246 }
12247 
12248 static int restart_monitor(void)
12249 {
12250    /* If we're supposed to be stopped -- stay stopped */
12251    if (monitor_thread == AST_PTHREADT_STOP)
12252       return 0;
12253    ast_mutex_lock(&monlock);
12254    if (monitor_thread == pthread_self()) {
12255       ast_mutex_unlock(&monlock);
12256       ast_log(LOG_WARNING, "Cannot kill myself\n");
12257       return -1;
12258    }
12259    if (monitor_thread != AST_PTHREADT_NULL) {
12260       /* Wake up the thread */
12261       pthread_kill(monitor_thread, SIGURG);
12262    } else {
12263       /* Start a new monitor */
12264       if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) {
12265          ast_mutex_unlock(&monlock);
12266          ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
12267          return -1;
12268       }
12269    }
12270    ast_mutex_unlock(&monlock);
12271    return 0;
12272 }
12273 
12274 #if defined(HAVE_PRI)
12275 static int pri_resolve_span(int *span, int channel, int offset, struct dahdi_spaninfo *si)
12276 {
12277    int x;
12278    int trunkgroup;
12279    /* Get appropriate trunk group if there is one */
12280    trunkgroup = pris[*span].mastertrunkgroup;
12281    if (trunkgroup) {
12282       /* Select a specific trunk group */
12283       for (x = 0; x < NUM_SPANS; x++) {
12284          if (pris[x].pri.trunkgroup == trunkgroup) {
12285             *span = x;
12286             return 0;
12287          }
12288       }
12289       ast_log(LOG_WARNING, "Channel %d on span %d configured to use nonexistent trunk group %d\n", channel, *span, trunkgroup);
12290       *span = -1;
12291    } else {
12292       if (pris[*span].pri.trunkgroup) {
12293          ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is trunk group %d (please use spanmap)\n", *span, pris[*span].pri.trunkgroup);
12294          *span = -1;
12295       } else if (pris[*span].mastertrunkgroup) {
12296          ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is already part of trunk group %d\n", *span, pris[*span].mastertrunkgroup);
12297          *span = -1;
12298       } else {
12299          if (si->totalchans == 31) {
12300             /* E1 */
12301             pris[*span].dchannels[0] = 16 + offset;
12302          } else if (si->totalchans == 24) {
12303             /* T1 or J1 */
12304             pris[*span].dchannels[0] = 24 + offset;
12305          } else if (si->totalchans == 3) {
12306             /* BRI */
12307             pris[*span].dchannels[0] = 3 + offset;
12308          } else {
12309             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);
12310             *span = -1;
12311             return 0;
12312          }
12313          pris[*span].pri.span = *span + 1;
12314       }
12315    }
12316    return 0;
12317 }
12318 #endif   /* defined(HAVE_PRI) */
12319 
12320 #if defined(HAVE_PRI)
12321 static int pri_create_trunkgroup(int trunkgroup, int *channels)
12322 {
12323    struct dahdi_spaninfo si;
12324    struct dahdi_params p;
12325    int fd;
12326    int span;
12327    int ospan=0;
12328    int x,y;
12329    for (x = 0; x < NUM_SPANS; x++) {
12330       if (pris[x].pri.trunkgroup == trunkgroup) {
12331          ast_log(LOG_WARNING, "Trunk group %d already exists on span %d, Primary d-channel %d\n", trunkgroup, x + 1, pris[x].dchannels[0]);
12332          return -1;
12333       }
12334    }
12335    for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
12336       if (!channels[y])
12337          break;
12338       memset(&si, 0, sizeof(si));
12339       memset(&p, 0, sizeof(p));
12340       fd = open("/dev/dahdi/channel", O_RDWR);
12341       if (fd < 0) {
12342          ast_log(LOG_WARNING, "Failed to open channel: %s\n", strerror(errno));
12343          return -1;
12344       }
12345       x = channels[y];
12346       if (ioctl(fd, DAHDI_SPECIFY, &x)) {
12347          ast_log(LOG_WARNING, "Failed to specify channel %d: %s\n", channels[y], strerror(errno));
12348          close(fd);
12349          return -1;
12350       }
12351       if (ioctl(fd, DAHDI_GET_PARAMS, &p)) {
12352          ast_log(LOG_WARNING, "Failed to get channel parameters for channel %d: %s\n", channels[y], strerror(errno));
12353          close(fd);
12354          return -1;
12355       }
12356       if (ioctl(fd, DAHDI_SPANSTAT, &si)) {
12357          ast_log(LOG_WARNING, "Failed go get span information on channel %d (span %d): %s\n", channels[y], p.spanno, strerror(errno));
12358          close(fd);
12359          return -1;
12360       }
12361       span = p.spanno - 1;
12362       if (pris[span].pri.trunkgroup) {
12363          ast_log(LOG_WARNING, "Span %d is already provisioned for trunk group %d\n", span + 1, pris[span].pri.trunkgroup);
12364          close(fd);
12365          return -1;
12366       }
12367       if (pris[span].pri.pvts[0]) {
12368          ast_log(LOG_WARNING, "Span %d is already provisioned with channels (implicit PRI maybe?)\n", span + 1);
12369          close(fd);
12370          return -1;
12371       }
12372       if (!y) {
12373          pris[span].pri.trunkgroup = trunkgroup;
12374          ospan = span;
12375       }
12376       pris[ospan].dchannels[y] = channels[y];
12377       pris[span].pri.span = span + 1;
12378       close(fd);
12379    }
12380    return 0;
12381 }
12382 #endif   /* defined(HAVE_PRI) */
12383 
12384 #if defined(HAVE_PRI)
12385 static int pri_create_spanmap(int span, int trunkgroup, int logicalspan)
12386 {
12387    if (pris[span].mastertrunkgroup) {
12388       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);
12389       return -1;
12390    }
12391    pris[span].mastertrunkgroup = trunkgroup;
12392    pris[span].prilogicalspan = logicalspan;
12393    return 0;
12394 }
12395 #endif   /* defined(HAVE_PRI) */
12396 
12397 #if defined(HAVE_SS7)
12398 static unsigned int parse_pointcode(const char *pcstring)
12399 {
12400    unsigned int code1, code2, code3;
12401    int numvals;
12402 
12403    numvals = sscanf(pcstring, "%30d-%30d-%30d", &code1, &code2, &code3);
12404    if (numvals == 1)
12405       return code1;
12406    if (numvals == 3)
12407       return (code1 << 16) | (code2 << 8) | code3;
12408 
12409    return 0;
12410 }
12411 #endif   /* defined(HAVE_SS7) */
12412 
12413 #if defined(HAVE_SS7)
12414 static struct dahdi_ss7 * ss7_resolve_linkset(int linkset)
12415 {
12416    if ((linkset < 0) || (linkset >= NUM_SPANS))
12417       return NULL;
12418    else
12419       return &linksets[linkset - 1];
12420 }
12421 #endif   /* defined(HAVE_SS7) */
12422 
12423 #ifdef HAVE_OPENR2
12424 static void dahdi_r2_destroy_links(void)
12425 {
12426    int i = 0;
12427    if (!r2links) {
12428       return;
12429    }
12430    for (; i < r2links_count; i++) {
12431       if (r2links[i]->r2master != AST_PTHREADT_NULL) {
12432          pthread_cancel(r2links[i]->r2master);
12433          pthread_join(r2links[i]->r2master, NULL);
12434          openr2_context_delete(r2links[i]->protocol_context);
12435       }
12436       ast_free(r2links[i]);
12437    }
12438    ast_free(r2links);
12439    r2links = NULL;
12440    r2links_count = 0;
12441 }
12442 
12443 /* This is an artificial convenient capacity, to keep at most a full E1 of channels in a single thread */
12444 #define R2_LINK_CAPACITY 30
12445 static struct dahdi_mfcr2 *dahdi_r2_get_link(const struct dahdi_chan_conf *conf)
12446 {
12447    struct dahdi_mfcr2 *new_r2link = NULL;
12448    struct dahdi_mfcr2 **new_r2links = NULL;
12449 
12450    /* Only create a new R2 link if 
12451       1. This is the first link requested
12452       2. Configuration changed 
12453       3. We got more channels than supported per link */
12454    if (!r2links_count ||
12455        memcmp(&conf->mfcr2, &r2links[r2links_count - 1]->conf, sizeof(conf->mfcr2)) ||
12456       (r2links[r2links_count - 1]->numchans == R2_LINK_CAPACITY)) {
12457       new_r2link = ast_calloc(1, sizeof(**r2links));
12458       if (!new_r2link) {
12459          ast_log(LOG_ERROR, "Cannot allocate R2 link!\n");
12460          return NULL;
12461       }
12462       new_r2links = ast_realloc(r2links, ((r2links_count + 1) * sizeof(*r2links)));
12463       if (!new_r2links) {
12464          ast_log(LOG_ERROR, "Cannot allocate R2 link!\n");
12465          ast_free(new_r2link);
12466          return NULL;
12467       }
12468       r2links = new_r2links;
12469       new_r2link->r2master = AST_PTHREADT_NULL;
12470       r2links[r2links_count] = new_r2link;
12471       r2links_count++;
12472       ast_debug(1, "Created new R2 link!\n");
12473    }
12474    return r2links[r2links_count - 1];
12475 }
12476 
12477 static int dahdi_r2_set_context(struct dahdi_mfcr2 *r2_link, const struct dahdi_chan_conf *conf)
12478 {
12479    char tmplogdir[] = "/tmp";
12480    char logdir[OR2_MAX_PATH];
12481    int threshold = 0;
12482    int snres = 0;
12483    r2_link->protocol_context = openr2_context_new(NULL, &dahdi_r2_event_iface,
12484          &dahdi_r2_transcode_iface, conf->mfcr2.variant, conf->mfcr2.max_ani,
12485          conf->mfcr2.max_dnis);
12486    if (!r2_link->protocol_context) {
12487       return -1;
12488    }
12489    openr2_context_set_log_level(r2_link->protocol_context, conf->mfcr2.loglevel);
12490    openr2_context_set_ani_first(r2_link->protocol_context, conf->mfcr2.get_ani_first);
12491 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
12492    openr2_context_set_skip_category_request(r2_link->protocol_context, conf->mfcr2.skip_category_request);
12493 #endif
12494    openr2_context_set_mf_threshold(r2_link->protocol_context, threshold);
12495    openr2_context_set_mf_back_timeout(r2_link->protocol_context, conf->mfcr2.mfback_timeout);
12496    openr2_context_set_metering_pulse_timeout(r2_link->protocol_context, conf->mfcr2.metering_pulse_timeout);
12497    openr2_context_set_double_answer(r2_link->protocol_context, conf->mfcr2.double_answer);
12498    openr2_context_set_immediate_accept(r2_link->protocol_context, conf->mfcr2.immediate_accept);
12499 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2
12500    openr2_context_set_dtmf_dialing(r2_link->protocol_context, conf->mfcr2.dtmf_dialing, conf->mfcr2.dtmf_time_on, conf->mfcr2.dtmf_time_off);
12501    openr2_context_set_dtmf_detection(r2_link->protocol_context, conf->mfcr2.dtmf_detection);
12502 #endif
12503 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 3
12504    openr2_context_set_dtmf_detection_end_timeout(r2_link->protocol_context, conf->mfcr2.dtmf_end_timeout);
12505 #endif
12506    if (ast_strlen_zero(conf->mfcr2.logdir)) {
12507       if (openr2_context_set_log_directory(r2_link->protocol_context, tmplogdir)) {
12508          ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir);
12509       }
12510    } else {
12511       snres = snprintf(logdir, sizeof(logdir), "%s/%s/%s", ast_config_AST_LOG_DIR, "mfcr2", conf->mfcr2.logdir);
12512       if (snres >= sizeof(logdir)) {
12513          ast_log(LOG_ERROR, "MFC/R2 logging directory truncated, using %s\n", tmplogdir);
12514          if (openr2_context_set_log_directory(r2_link->protocol_context, tmplogdir)) {
12515             ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir);
12516          }
12517       } else {
12518          if (openr2_context_set_log_directory(r2_link->protocol_context, logdir)) {
12519             ast_log(LOG_ERROR, "Failed setting MFC/R2 log directory %s\n", logdir);
12520          }
12521       }
12522    }
12523    if (!ast_strlen_zero(conf->mfcr2.r2proto_file)) {
12524       if (openr2_context_configure_from_advanced_file(r2_link->protocol_context, conf->mfcr2.r2proto_file)) {
12525          ast_log(LOG_ERROR, "Failed to configure r2context from advanced configuration file %s\n", conf->mfcr2.r2proto_file);
12526       }
12527    }
12528    /* Save the configuration used to setup this link */
12529    memcpy(&r2_link->conf, conf, sizeof(r2_link->conf));
12530    return 0;
12531 }
12532 #endif
12533 
12534 /* converts a DAHDI sigtype to signalling as can be configured from
12535  * chan_dahdi.conf.
12536  * While both have basically the same values, this will later be the
12537  * place to add filters and sanity checks
12538  */
12539 static int sigtype_to_signalling(int sigtype)
12540 {
12541    return sigtype;
12542 }
12543 
12544 /*!
12545  * \internal
12546  * \brief Get file name and channel number from (subdir,number)
12547  *
12548  * \param subdir name of the subdirectory under /dev/dahdi/
12549  * \param channel name of device file under /dev/dahdi/<subdir>/
12550  * \param path buffer to put file name in
12551  * \param pathlen maximal length of path
12552  *
12553  * \retval minor number of dahdi channel.
12554  * \retval -errno on error.
12555  */
12556 static int device2chan(const char *subdir, int channel, char *path, int pathlen)
12557 {
12558    struct stat stbuf;
12559    int      num;
12560 
12561    snprintf(path, pathlen, "/dev/dahdi/%s/%d", subdir, channel);
12562    if (stat(path, &stbuf) < 0) {
12563       ast_log(LOG_ERROR, "stat(%s) failed: %s\n", path, strerror(errno));
12564       return -errno;
12565    }
12566    if (!S_ISCHR(stbuf.st_mode)) {
12567       ast_log(LOG_ERROR, "%s: Not a character device file\n", path);
12568       return -EINVAL;
12569    }
12570    num = minor(stbuf.st_rdev);
12571    ast_debug(1, "%s -> %d\n", path, num);
12572    return num;
12573 
12574 }
12575 
12576 /*!
12577  * \internal
12578  * \brief Initialize/create a channel interface.
12579  *
12580  * \param channel Channel interface number to initialize/create.
12581  * \param conf Configuration parameters to initialize interface with.
12582  * \param reloading What we are doing now:
12583  * 0 - initial module load,
12584  * 1 - module reload,
12585  * 2 - module restart
12586  *
12587  * \retval Interface-pointer initialized/created
12588  * \retval NULL if error
12589  */
12590 static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf, int reloading)
12591 {
12592    /* Make a dahdi_pvt structure for this interface */
12593    struct dahdi_pvt *tmp;/*!< Current channel structure initializing */
12594    char fn[80];
12595    struct dahdi_bufferinfo bi;
12596 
12597    int res;
12598 #if defined(HAVE_PRI)
12599    int span = 0;
12600 #endif   /* defined(HAVE_PRI) */
12601    int here = 0;/*!< TRUE if the channel interface already exists. */
12602    int x;
12603    struct analog_pvt *analog_p = NULL;
12604    struct dahdi_params p;
12605 #if defined(HAVE_PRI)
12606    struct dahdi_spaninfo si;
12607    struct sig_pri_chan *pri_chan = NULL;
12608 #endif   /* defined(HAVE_PRI) */
12609 #if defined(HAVE_SS7)
12610    struct sig_ss7_chan *ss7_chan = NULL;
12611 #endif   /* defined(HAVE_SS7) */
12612 
12613    /* Search channel interface list to see if it already exists. */
12614    for (tmp = iflist; tmp; tmp = tmp->next) {
12615       if (!tmp->destroy) {
12616          if (tmp->channel == channel) {
12617             /* The channel interface already exists. */
12618             here = 1;
12619             break;
12620          }
12621          if (tmp->channel > channel) {
12622             /* No way it can be in the sorted list. */
12623             tmp = NULL;
12624             break;
12625          }
12626       }
12627    }
12628 
12629    if (!here && reloading != 1) {
12630       tmp = ast_calloc(1, sizeof(*tmp));
12631       if (!tmp) {
12632          return NULL;
12633       }
12634       tmp->cc_params = ast_cc_config_params_init();
12635       if (!tmp->cc_params) {
12636          ast_free(tmp);
12637          return NULL;
12638       }
12639       ast_mutex_init(&tmp->lock);
12640       ifcount++;
12641       for (x = 0; x < 3; x++)
12642          tmp->subs[x].dfd = -1;
12643       tmp->channel = channel;
12644       tmp->priindication_oob = conf->chan.priindication_oob;
12645    }
12646 
12647    if (tmp) {
12648       int chan_sig = conf->chan.sig;
12649 
12650       /* If there are variables in tmp before it is updated to match the new config, clear them */
12651       if (reloading && tmp->vars) {
12652          ast_variables_destroy(tmp->vars);
12653          tmp->vars = NULL;
12654       }
12655 
12656       if (!here) {
12657          /* Can only get here if this is a new channel interface being created. */
12658          if ((channel != CHAN_PSEUDO)) {
12659             int count = 0;
12660 
12661             snprintf(fn, sizeof(fn), "%d", channel);
12662             /* Open non-blocking */
12663             tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
12664             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 */
12665                usleep(1);
12666                tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
12667                count++;
12668             }
12669             /* Allocate a DAHDI structure */
12670             if (tmp->subs[SUB_REAL].dfd < 0) {
12671                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);
12672                destroy_dahdi_pvt(tmp);
12673                return NULL;
12674             }
12675             memset(&p, 0, sizeof(p));
12676             res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
12677             if (res < 0) {
12678                ast_log(LOG_ERROR, "Unable to get parameters: %s\n", strerror(errno));
12679                destroy_dahdi_pvt(tmp);
12680                return NULL;
12681             }
12682             if (conf->is_sig_auto)
12683                chan_sig = sigtype_to_signalling(p.sigtype);
12684             if (p.sigtype != (chan_sig & 0x3ffff)) {
12685                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));
12686                destroy_dahdi_pvt(tmp);
12687                return NULL;
12688             }
12689             tmp->law_default = p.curlaw;
12690             tmp->law = p.curlaw;
12691             tmp->span = p.spanno;
12692 #if defined(HAVE_PRI)
12693             span = p.spanno - 1;
12694 #endif   /* defined(HAVE_PRI) */
12695          } else {
12696             chan_sig = 0;
12697          }
12698          tmp->sig = chan_sig;
12699          tmp->outsigmod = conf->chan.outsigmod;
12700 
12701          if (analog_lib_handles(chan_sig, tmp->radio, tmp->oprmode)) {
12702             analog_p = analog_new(dahdisig_to_analogsig(chan_sig), tmp);
12703             if (!analog_p) {
12704                destroy_dahdi_pvt(tmp);
12705                return NULL;
12706             }
12707             tmp->sig_pvt = analog_p;
12708          }
12709 #if defined(HAVE_SS7)
12710          if (chan_sig == SIG_SS7) {
12711             struct dahdi_ss7 *ss7;
12712             int clear = 0;
12713 
12714             if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &clear)) {
12715                ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
12716                destroy_dahdi_pvt(tmp);
12717                return NULL;
12718             }
12719 
12720             ss7 = ss7_resolve_linkset(cur_linkset);
12721             if (!ss7) {
12722                ast_log(LOG_ERROR, "Unable to find linkset %d\n", cur_linkset);
12723                destroy_dahdi_pvt(tmp);
12724                return NULL;
12725             }
12726             ss7->ss7.span = cur_linkset;
12727             if (cur_cicbeginswith < 0) {
12728                ast_log(LOG_ERROR, "Need to set cicbeginswith for the channels!\n");
12729                destroy_dahdi_pvt(tmp);
12730                return NULL;
12731             }
12732             ss7_chan = sig_ss7_chan_new(tmp, &ss7->ss7);
12733             if (!ss7_chan) {
12734                destroy_dahdi_pvt(tmp);
12735                return NULL;
12736             }
12737             tmp->sig_pvt = ss7_chan;
12738             tmp->ss7 = &ss7->ss7;
12739 
12740             ss7_chan->channel = tmp->channel;
12741             ss7_chan->cic = cur_cicbeginswith++;
12742 
12743             /* DB: Add CIC's DPC information */
12744             ss7_chan->dpc = cur_defaultdpc;
12745 
12746             ss7->ss7.pvts[ss7->ss7.numchans++] = ss7_chan;
12747 
12748             ast_copy_string(ss7->ss7.internationalprefix, conf->ss7.ss7.internationalprefix, sizeof(ss7->ss7.internationalprefix));
12749             ast_copy_string(ss7->ss7.nationalprefix, conf->ss7.ss7.nationalprefix, sizeof(ss7->ss7.nationalprefix));
12750             ast_copy_string(ss7->ss7.subscriberprefix, conf->ss7.ss7.subscriberprefix, sizeof(ss7->ss7.subscriberprefix));
12751             ast_copy_string(ss7->ss7.unknownprefix, conf->ss7.ss7.unknownprefix, sizeof(ss7->ss7.unknownprefix));
12752 
12753             ss7->ss7.called_nai = conf->ss7.ss7.called_nai;
12754             ss7->ss7.calling_nai = conf->ss7.ss7.calling_nai;
12755          }
12756 #endif   /* defined(HAVE_SS7) */
12757 #ifdef HAVE_OPENR2
12758          if (chan_sig == SIG_MFCR2) {
12759             struct dahdi_mfcr2 *r2_link;
12760             r2_link = dahdi_r2_get_link(conf);
12761             if (!r2_link) {
12762                ast_log(LOG_WARNING, "Cannot get another R2 DAHDI context!\n");
12763                destroy_dahdi_pvt(tmp);
12764                return NULL;
12765             }
12766             if (!r2_link->protocol_context && dahdi_r2_set_context(r2_link, conf)) {
12767                ast_log(LOG_ERROR, "Cannot create OpenR2 protocol context.\n");
12768                destroy_dahdi_pvt(tmp);
12769                return NULL;
12770             }
12771             if (r2_link->numchans == ARRAY_LEN(r2_link->pvts)) {
12772                ast_log(LOG_ERROR, "Cannot add more channels to this link!\n");
12773                destroy_dahdi_pvt(tmp);
12774                return NULL;
12775             }
12776             r2_link->pvts[r2_link->numchans++] = tmp;
12777             tmp->r2chan = openr2_chan_new_from_fd(r2_link->protocol_context,
12778                                         tmp->subs[SUB_REAL].dfd,
12779                                         NULL, NULL);
12780             if (!tmp->r2chan) {
12781                openr2_liberr_t err = openr2_context_get_last_error(r2_link->protocol_context);
12782                ast_log(LOG_ERROR, "Cannot create OpenR2 channel: %s\n", openr2_context_error_string(err));
12783                destroy_dahdi_pvt(tmp);
12784                return NULL;
12785             }
12786             tmp->mfcr2 = r2_link;
12787             if (conf->mfcr2.call_files) {
12788                openr2_chan_enable_call_files(tmp->r2chan);
12789             }
12790             openr2_chan_set_client_data(tmp->r2chan, tmp);
12791             /* cast seems to be needed to get rid of the annoying warning regarding format attribute  */
12792             openr2_chan_set_logging_func(tmp->r2chan, (openr2_logging_func_t)dahdi_r2_on_chan_log);
12793             openr2_chan_set_log_level(tmp->r2chan, conf->mfcr2.loglevel);
12794             tmp->mfcr2_category = conf->mfcr2.category;
12795             tmp->mfcr2_charge_calls = conf->mfcr2.charge_calls;
12796             tmp->mfcr2_allow_collect_calls = conf->mfcr2.allow_collect_calls;
12797             tmp->mfcr2_forced_release = conf->mfcr2.forced_release;
12798             tmp->mfcr2_accept_on_offer = conf->mfcr2.accept_on_offer;
12799             tmp->mfcr2call = 0;
12800             tmp->mfcr2_dnis_index = 0;
12801             tmp->mfcr2_ani_index = 0;
12802          }
12803 #endif
12804 #ifdef HAVE_PRI
12805          if (dahdi_sig_pri_lib_handles(chan_sig)) {
12806             int offset;
12807             int matchesdchan;
12808             int x,y;
12809             int myswitchtype = 0;
12810 
12811             offset = 0;
12812             if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &offset)) {
12813                ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
12814                destroy_dahdi_pvt(tmp);
12815                return NULL;
12816             }
12817             if (span >= NUM_SPANS) {
12818                ast_log(LOG_ERROR, "Channel %d does not lie on a span I know of (%d)\n", channel, span);
12819                destroy_dahdi_pvt(tmp);
12820                return NULL;
12821             } else {
12822                si.spanno = 0;
12823                if (ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SPANSTAT,&si) == -1) {
12824                   ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno));
12825                   destroy_dahdi_pvt(tmp);
12826                   return NULL;
12827                }
12828                /* Store the logical span first based upon the real span */
12829                tmp->logicalspan = pris[span].prilogicalspan;
12830                pri_resolve_span(&span, channel, (channel - p.chanpos), &si);
12831                if (span < 0) {
12832                   ast_log(LOG_WARNING, "Channel %d: Unable to find locate channel/trunk group!\n", channel);
12833                   destroy_dahdi_pvt(tmp);
12834                   return NULL;
12835                }
12836                myswitchtype = conf->pri.pri.switchtype;
12837                /* Make sure this isn't a d-channel */
12838                matchesdchan=0;
12839                for (x = 0; x < NUM_SPANS; x++) {
12840                   for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
12841                      if (pris[x].dchannels[y] == tmp->channel) {
12842                         matchesdchan = 1;
12843                         break;
12844                      }
12845                   }
12846                }
12847                if (!matchesdchan) {
12848                   if (pris[span].pri.nodetype && (pris[span].pri.nodetype != conf->pri.pri.nodetype)) {
12849                      ast_log(LOG_ERROR, "Span %d is already a %s node\n", span + 1, pri_node2str(pris[span].pri.nodetype));
12850                      destroy_dahdi_pvt(tmp);
12851                      return NULL;
12852                   }
12853                   if (pris[span].pri.switchtype && (pris[span].pri.switchtype != myswitchtype)) {
12854                      ast_log(LOG_ERROR, "Span %d is already a %s switch\n", span + 1, pri_switch2str(pris[span].pri.switchtype));
12855                      destroy_dahdi_pvt(tmp);
12856                      return NULL;
12857                   }
12858                   if ((pris[span].pri.dialplan) && (pris[span].pri.dialplan != conf->pri.pri.dialplan)) {
12859                      ast_log(LOG_ERROR, "Span %d is already a %s dialing plan\n", span + 1, pris[span].pri.dialplan == -1 ? "Dynamically set dialplan in ISDN" : pri_plan2str(pris[span].pri.dialplan));
12860                      destroy_dahdi_pvt(tmp);
12861                      return NULL;
12862                   }
12863                   if (!ast_strlen_zero(pris[span].pri.idledial) && strcmp(pris[span].pri.idledial, conf->pri.pri.idledial)) {
12864                      ast_log(LOG_ERROR, "Span %d already has idledial '%s'.\n", span + 1, conf->pri.pri.idledial);
12865                      destroy_dahdi_pvt(tmp);
12866                      return NULL;
12867                   }
12868                   if (!ast_strlen_zero(pris[span].pri.idleext) && strcmp(pris[span].pri.idleext, conf->pri.pri.idleext)) {
12869                      ast_log(LOG_ERROR, "Span %d already has idleext '%s'.\n", span + 1, conf->pri.pri.idleext);
12870                      destroy_dahdi_pvt(tmp);
12871                      return NULL;
12872                   }
12873                   if (pris[span].pri.minunused && (pris[span].pri.minunused != conf->pri.pri.minunused)) {
12874                      ast_log(LOG_ERROR, "Span %d already has minunused of %d.\n", span + 1, conf->pri.pri.minunused);
12875                      destroy_dahdi_pvt(tmp);
12876                      return NULL;
12877                   }
12878                   if (pris[span].pri.minidle && (pris[span].pri.minidle != conf->pri.pri.minidle)) {
12879                      ast_log(LOG_ERROR, "Span %d already has minidle of %d.\n", span + 1, conf->pri.pri.minidle);
12880                      destroy_dahdi_pvt(tmp);
12881                      return NULL;
12882                   }
12883                   if (pris[span].pri.numchans >= ARRAY_LEN(pris[span].pri.pvts)) {
12884                      ast_log(LOG_ERROR, "Unable to add channel %d: Too many channels in trunk group %d!\n", channel,
12885                         pris[span].pri.trunkgroup);
12886                      destroy_dahdi_pvt(tmp);
12887                      return NULL;
12888                   }
12889 
12890                   pri_chan = sig_pri_chan_new(tmp, &pris[span].pri, tmp->logicalspan, p.chanpos, pris[span].mastertrunkgroup);
12891                   if (!pri_chan) {
12892                      destroy_dahdi_pvt(tmp);
12893                      return NULL;
12894                   }
12895                   tmp->sig_pvt = pri_chan;
12896                   tmp->pri = &pris[span].pri;
12897 
12898                   tmp->priexclusive = conf->chan.priexclusive;
12899 
12900                   if (!tmp->pri->cc_params) {
12901                      tmp->pri->cc_params = ast_cc_config_params_init();
12902                      if (!tmp->pri->cc_params) {
12903                         destroy_dahdi_pvt(tmp);
12904                         return NULL;
12905                      }
12906                   }
12907                   ast_cc_copy_config_params(tmp->pri->cc_params,
12908                      conf->chan.cc_params);
12909 
12910                   pris[span].pri.sig = chan_sig;
12911                   pris[span].pri.nodetype = conf->pri.pri.nodetype;
12912                   pris[span].pri.switchtype = myswitchtype;
12913                   pris[span].pri.nsf = conf->pri.pri.nsf;
12914                   pris[span].pri.dialplan = conf->pri.pri.dialplan;
12915                   pris[span].pri.localdialplan = conf->pri.pri.localdialplan;
12916                   pris[span].pri.cpndialplan = conf->pri.pri.cpndialplan;
12917                   pris[span].pri.pvts[pris[span].pri.numchans++] = tmp->sig_pvt;
12918                   pris[span].pri.minunused = conf->pri.pri.minunused;
12919                   pris[span].pri.minidle = conf->pri.pri.minidle;
12920                   pris[span].pri.overlapdial = conf->pri.pri.overlapdial;
12921                   pris[span].pri.qsigchannelmapping = conf->pri.pri.qsigchannelmapping;
12922                   pris[span].pri.discardremoteholdretrieval = conf->pri.pri.discardremoteholdretrieval;
12923 #if defined(HAVE_PRI_SERVICE_MESSAGES)
12924                   pris[span].pri.enable_service_message_support = conf->pri.pri.enable_service_message_support;
12925 #endif   /* defined(HAVE_PRI_SERVICE_MESSAGES) */
12926 #ifdef HAVE_PRI_INBANDDISCONNECT
12927                   pris[span].pri.inbanddisconnect = conf->pri.pri.inbanddisconnect;
12928 #endif
12929 #if defined(HAVE_PRI_CALL_HOLD)
12930                   pris[span].pri.hold_disconnect_transfer =
12931                      conf->pri.pri.hold_disconnect_transfer;
12932 #endif   /* defined(HAVE_PRI_CALL_HOLD) */
12933 #if defined(HAVE_PRI_CCSS)
12934                   pris[span].pri.cc_ptmp_recall_mode =
12935                      conf->pri.pri.cc_ptmp_recall_mode;
12936                   pris[span].pri.cc_qsig_signaling_link_req =
12937                      conf->pri.pri.cc_qsig_signaling_link_req;
12938                   pris[span].pri.cc_qsig_signaling_link_rsp =
12939                      conf->pri.pri.cc_qsig_signaling_link_rsp;
12940 #endif   /* defined(HAVE_PRI_CCSS) */
12941 #if defined(HAVE_PRI_CALL_WAITING)
12942                   pris[span].pri.max_call_waiting_calls =
12943                      conf->pri.pri.max_call_waiting_calls;
12944                   pris[span].pri.allow_call_waiting_calls =
12945                      conf->pri.pri.allow_call_waiting_calls;
12946 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
12947                   pris[span].pri.transfer = conf->chan.transfer;
12948                   pris[span].pri.facilityenable = conf->pri.pri.facilityenable;
12949 #if defined(HAVE_PRI_L2_PERSISTENCE)
12950                   pris[span].pri.l2_persistence = conf->pri.pri.l2_persistence;
12951 #endif   /* defined(HAVE_PRI_L2_PERSISTENCE) */
12952                   pris[span].pri.colp_send = conf->pri.pri.colp_send;
12953 #if defined(HAVE_PRI_AOC_EVENTS)
12954                   pris[span].pri.aoc_passthrough_flag = conf->pri.pri.aoc_passthrough_flag;
12955                   pris[span].pri.aoce_delayhangup = conf->pri.pri.aoce_delayhangup;
12956 #endif   /* defined(HAVE_PRI_AOC_EVENTS) */
12957                   if (chan_sig == SIG_BRI_PTMP) {
12958                      pris[span].pri.layer1_ignored = conf->pri.pri.layer1_ignored;
12959                   } else {
12960                      /* Option does not apply to this line type. */
12961                      pris[span].pri.layer1_ignored = 0;
12962                   }
12963                   pris[span].pri.append_msn_to_user_tag = conf->pri.pri.append_msn_to_user_tag;
12964                   pris[span].pri.inband_on_setup_ack = conf->pri.pri.inband_on_setup_ack;
12965                   pris[span].pri.inband_on_proceeding = conf->pri.pri.inband_on_proceeding;
12966                   ast_copy_string(pris[span].pri.initial_user_tag, conf->chan.cid_tag, sizeof(pris[span].pri.initial_user_tag));
12967                   ast_copy_string(pris[span].pri.msn_list, conf->pri.pri.msn_list, sizeof(pris[span].pri.msn_list));
12968 #if defined(HAVE_PRI_MWI)
12969                   ast_copy_string(pris[span].pri.mwi_mailboxes,
12970                      conf->pri.pri.mwi_mailboxes,
12971                      sizeof(pris[span].pri.mwi_mailboxes));
12972                   ast_copy_string(pris[span].pri.mwi_vm_numbers,
12973                      conf->pri.pri.mwi_vm_numbers,
12974                      sizeof(pris[span].pri.mwi_vm_numbers));
12975 #endif   /* defined(HAVE_PRI_MWI) */
12976                   ast_copy_string(pris[span].pri.idledial, conf->pri.pri.idledial, sizeof(pris[span].pri.idledial));
12977                   ast_copy_string(pris[span].pri.idleext, conf->pri.pri.idleext, sizeof(pris[span].pri.idleext));
12978                   ast_copy_string(pris[span].pri.internationalprefix, conf->pri.pri.internationalprefix, sizeof(pris[span].pri.internationalprefix));
12979                   ast_copy_string(pris[span].pri.nationalprefix, conf->pri.pri.nationalprefix, sizeof(pris[span].pri.nationalprefix));
12980                   ast_copy_string(pris[span].pri.localprefix, conf->pri.pri.localprefix, sizeof(pris[span].pri.localprefix));
12981                   ast_copy_string(pris[span].pri.privateprefix, conf->pri.pri.privateprefix, sizeof(pris[span].pri.privateprefix));
12982                   ast_copy_string(pris[span].pri.unknownprefix, conf->pri.pri.unknownprefix, sizeof(pris[span].pri.unknownprefix));
12983                   pris[span].pri.moh_signaling = conf->pri.pri.moh_signaling;
12984                   pris[span].pri.resetinterval = conf->pri.pri.resetinterval;
12985 #if defined(HAVE_PRI_DISPLAY_TEXT)
12986                   pris[span].pri.display_flags_send = conf->pri.pri.display_flags_send;
12987                   pris[span].pri.display_flags_receive = conf->pri.pri.display_flags_receive;
12988 #endif   /* defined(HAVE_PRI_DISPLAY_TEXT) */
12989 #if defined(HAVE_PRI_MCID)
12990                   pris[span].pri.mcid_send = conf->pri.pri.mcid_send;
12991 #endif   /* defined(HAVE_PRI_MCID) */
12992 #if defined(HAVE_PRI_DATETIME_SEND)
12993                   pris[span].pri.datetime_send = conf->pri.pri.datetime_send;
12994 #endif   /* defined(HAVE_PRI_DATETIME_SEND) */
12995 
12996                   for (x = 0; x < PRI_MAX_TIMERS; x++) {
12997                      pris[span].pri.pritimers[x] = conf->pri.pri.pritimers[x];
12998                   }
12999 
13000 #if defined(HAVE_PRI_CALL_WAITING)
13001                   /* Channel initial config parameters. */
13002                   pris[span].pri.ch_cfg.stripmsd = conf->chan.stripmsd;
13003                   pris[span].pri.ch_cfg.hidecallerid = conf->chan.hidecallerid;
13004                   pris[span].pri.ch_cfg.hidecalleridname = conf->chan.hidecalleridname;
13005                   pris[span].pri.ch_cfg.immediate = conf->chan.immediate;
13006                   pris[span].pri.ch_cfg.priexclusive = conf->chan.priexclusive;
13007                   pris[span].pri.ch_cfg.priindication_oob = conf->chan.priindication_oob;
13008                   pris[span].pri.ch_cfg.use_callerid = conf->chan.use_callerid;
13009                   pris[span].pri.ch_cfg.use_callingpres = conf->chan.use_callingpres;
13010                   ast_copy_string(pris[span].pri.ch_cfg.context, conf->chan.context, sizeof(pris[span].pri.ch_cfg.context));
13011                   ast_copy_string(pris[span].pri.ch_cfg.mohinterpret, conf->chan.mohinterpret, sizeof(pris[span].pri.ch_cfg.mohinterpret));
13012 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
13013                } else {
13014                   ast_log(LOG_ERROR, "Channel %d is reserved for D-channel.\n", p.chanpos);
13015                   destroy_dahdi_pvt(tmp);
13016                   return NULL;
13017                }
13018             }
13019          }
13020 #endif
13021       } else {
13022          /* already exists in interface list */
13023          ast_log(LOG_WARNING, "Attempt to configure channel %d with signaling %s ignored because it is already configured to be %s.\n", tmp->channel, dahdi_sig2str(chan_sig), dahdi_sig2str(tmp->sig));
13024          chan_sig = tmp->sig;
13025          if (tmp->subs[SUB_REAL].dfd > -1) {
13026             memset(&p, 0, sizeof(p));
13027             res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
13028          }
13029       }
13030       /* Adjust starttime on loopstart and kewlstart trunks to reasonable values */
13031       switch (chan_sig) {
13032       case SIG_FXSKS:
13033       case SIG_FXSLS:
13034       case SIG_EM:
13035       case SIG_EM_E1:
13036       case SIG_EMWINK:
13037       case SIG_FEATD:
13038       case SIG_FEATDMF:
13039       case SIG_FEATDMF_TA:
13040       case SIG_FEATB:
13041       case SIG_E911:
13042       case SIG_SF:
13043       case SIG_SFWINK:
13044       case SIG_FGC_CAMA:
13045       case SIG_FGC_CAMAMF:
13046       case SIG_SF_FEATD:
13047       case SIG_SF_FEATDMF:
13048       case SIG_SF_FEATB:
13049          p.starttime = 250;
13050          break;
13051       }
13052 
13053       if (tmp->radio) {
13054          /* XXX Waiting to hear back from Jim if these should be adjustable XXX */
13055          p.channo = channel;
13056          p.rxwinktime = 1;
13057          p.rxflashtime = 1;
13058          p.starttime = 1;
13059          p.debouncetime = 5;
13060       } else {
13061          p.channo = channel;
13062          /* Override timing settings based on config file */
13063          if (conf->timing.prewinktime >= 0)
13064             p.prewinktime = conf->timing.prewinktime;
13065          if (conf->timing.preflashtime >= 0)
13066             p.preflashtime = conf->timing.preflashtime;
13067          if (conf->timing.winktime >= 0)
13068             p.winktime = conf->timing.winktime;
13069          if (conf->timing.flashtime >= 0)
13070             p.flashtime = conf->timing.flashtime;
13071          if (conf->timing.starttime >= 0)
13072             p.starttime = conf->timing.starttime;
13073          if (conf->timing.rxwinktime >= 0)
13074             p.rxwinktime = conf->timing.rxwinktime;
13075          if (conf->timing.rxflashtime >= 0)
13076             p.rxflashtime = conf->timing.rxflashtime;
13077          if (conf->timing.debouncetime >= 0)
13078             p.debouncetime = conf->timing.debouncetime;
13079       }
13080 
13081       /* don't set parms on a pseudo-channel */
13082       if (tmp->subs[SUB_REAL].dfd >= 0)
13083       {
13084          res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_PARAMS, &p);
13085          if (res < 0) {
13086             ast_log(LOG_ERROR, "Unable to set parameters: %s\n", strerror(errno));
13087             destroy_dahdi_pvt(tmp);
13088             return NULL;
13089          }
13090       }
13091 #if 1
13092       if (!here && (tmp->subs[SUB_REAL].dfd > -1)) {
13093          memset(&bi, 0, sizeof(bi));
13094          res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
13095          if (!res) {
13096             bi.txbufpolicy = conf->chan.buf_policy;
13097             bi.rxbufpolicy = conf->chan.buf_policy;
13098             bi.numbufs = conf->chan.buf_no;
13099             res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
13100             if (res < 0) {
13101                ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", channel, strerror(errno));
13102             }
13103          } else {
13104             ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", channel, strerror(errno));
13105          }
13106          tmp->buf_policy = conf->chan.buf_policy;
13107          tmp->buf_no = conf->chan.buf_no;
13108          tmp->usefaxbuffers = conf->chan.usefaxbuffers;
13109          tmp->faxbuf_policy = conf->chan.faxbuf_policy;
13110          tmp->faxbuf_no = conf->chan.faxbuf_no;
13111          /* This is not as gnarly as it may first appear.  If the ioctl above failed, we'd be setting
13112           * tmp->bufsize to zero which would cause subsequent faxbuffer-related ioctl calls to fail.
13113           * The reason the ioctl call above failed should to be determined before worrying about the
13114           * faxbuffer-related ioctl calls */
13115          tmp->bufsize = bi.bufsize;
13116       }
13117 #endif
13118       tmp->immediate = conf->chan.immediate;
13119       tmp->transfertobusy = conf->chan.transfertobusy;
13120       if (chan_sig & __DAHDI_SIG_FXS) {
13121          tmp->mwimonitor_fsk = conf->chan.mwimonitor_fsk;
13122          tmp->mwimonitor_neon = conf->chan.mwimonitor_neon;
13123          tmp->mwimonitor_rpas = conf->chan.mwimonitor_rpas;
13124       }
13125       tmp->ringt_base = ringt_base;
13126       tmp->firstradio = 0;
13127       if ((chan_sig == SIG_FXOKS) || (chan_sig == SIG_FXOLS) || (chan_sig == SIG_FXOGS))
13128          tmp->permcallwaiting = conf->chan.callwaiting;
13129       else
13130          tmp->permcallwaiting = 0;
13131       /* Flag to destroy the channel must be cleared on new mkif.  Part of changes for reload to work */
13132       tmp->destroy = 0;
13133       tmp->drings = conf->chan.drings;
13134 
13135       /* 10 is a nice default. */
13136       if (tmp->drings.ringnum[0].range == 0)
13137          tmp->drings.ringnum[0].range = 10;
13138       if (tmp->drings.ringnum[1].range == 0)
13139          tmp->drings.ringnum[1].range = 10;
13140       if (tmp->drings.ringnum[2].range == 0)
13141          tmp->drings.ringnum[2].range = 10;
13142 
13143       tmp->usedistinctiveringdetection = usedistinctiveringdetection;
13144       tmp->callwaitingcallerid = conf->chan.callwaitingcallerid;
13145       tmp->threewaycalling = conf->chan.threewaycalling;
13146       tmp->adsi = conf->chan.adsi;
13147       tmp->use_smdi = conf->chan.use_smdi;
13148       tmp->permhidecallerid = conf->chan.hidecallerid;
13149       tmp->hidecalleridname = conf->chan.hidecalleridname;
13150       tmp->callreturn = conf->chan.callreturn;
13151       tmp->echocancel = conf->chan.echocancel;
13152       tmp->echotraining = conf->chan.echotraining;
13153       tmp->pulse = conf->chan.pulse;
13154       if (tmp->echocancel.head.tap_length) {
13155          tmp->echocanbridged = conf->chan.echocanbridged;
13156       } else {
13157          if (conf->chan.echocanbridged)
13158             ast_log(LOG_NOTICE, "echocancelwhenbridged requires echocancel to be enabled; ignoring\n");
13159          tmp->echocanbridged = 0;
13160       }
13161       tmp->busydetect = conf->chan.busydetect;
13162       tmp->busycount = conf->chan.busycount;
13163       tmp->busy_cadence = conf->chan.busy_cadence;
13164       tmp->callprogress = conf->chan.callprogress;
13165       tmp->waitfordialtone = conf->chan.waitfordialtone;
13166       tmp->dialtone_detect = conf->chan.dialtone_detect;
13167       tmp->cancallforward = conf->chan.cancallforward;
13168       tmp->dtmfrelax = conf->chan.dtmfrelax;
13169       tmp->callwaiting = tmp->permcallwaiting;
13170       tmp->hidecallerid = tmp->permhidecallerid;
13171       tmp->channel = channel;
13172       tmp->stripmsd = conf->chan.stripmsd;
13173       tmp->use_callerid = conf->chan.use_callerid;
13174       tmp->cid_signalling = conf->chan.cid_signalling;
13175       tmp->cid_start = conf->chan.cid_start;
13176       tmp->dahditrcallerid = conf->chan.dahditrcallerid;
13177       tmp->restrictcid = conf->chan.restrictcid;
13178       tmp->use_callingpres = conf->chan.use_callingpres;
13179       if (tmp->usedistinctiveringdetection) {
13180          if (!tmp->use_callerid) {
13181             ast_log(LOG_NOTICE, "Distinctive Ring detect requires 'usecallerid' be on\n");
13182             tmp->use_callerid = 1;
13183          }
13184       }
13185 
13186       if (tmp->cid_signalling == CID_SIG_SMDI) {
13187          if (!tmp->use_smdi) {
13188             ast_log(LOG_WARNING, "SMDI callerid requires SMDI to be enabled, enabling...\n");
13189             tmp->use_smdi = 1;
13190          }
13191       }
13192       if (tmp->use_smdi) {
13193          tmp->smdi_iface = ast_smdi_interface_find(conf->smdi_port);
13194          if (!(tmp->smdi_iface)) {
13195             ast_log(LOG_ERROR, "Invalid SMDI port specfied, disabling SMDI support\n");
13196             tmp->use_smdi = 0;
13197          }
13198       }
13199 
13200       ast_copy_string(tmp->accountcode, conf->chan.accountcode, sizeof(tmp->accountcode));
13201       tmp->amaflags = conf->chan.amaflags;
13202       if (!here) {
13203          tmp->confno = -1;
13204          tmp->propconfno = -1;
13205       }
13206       tmp->canpark = conf->chan.canpark;
13207       tmp->transfer = conf->chan.transfer;
13208       ast_copy_string(tmp->defcontext,conf->chan.context,sizeof(tmp->defcontext));
13209       ast_copy_string(tmp->language, conf->chan.language, sizeof(tmp->language));
13210       ast_copy_string(tmp->mohinterpret, conf->chan.mohinterpret, sizeof(tmp->mohinterpret));
13211       ast_copy_string(tmp->mohsuggest, conf->chan.mohsuggest, sizeof(tmp->mohsuggest));
13212       ast_copy_string(tmp->context, conf->chan.context, sizeof(tmp->context));
13213       ast_copy_string(tmp->description, conf->chan.description, sizeof(tmp->description));
13214       ast_copy_string(tmp->parkinglot, conf->chan.parkinglot, sizeof(tmp->parkinglot));
13215       tmp->cid_ton = 0;
13216       if (analog_lib_handles(tmp->sig, tmp->radio, tmp->oprmode)) {
13217          ast_copy_string(tmp->cid_num, conf->chan.cid_num, sizeof(tmp->cid_num));
13218          ast_copy_string(tmp->cid_name, conf->chan.cid_name, sizeof(tmp->cid_name));
13219       } else {
13220          tmp->cid_num[0] = '\0';
13221          tmp->cid_name[0] = '\0';
13222       }
13223 #if defined(HAVE_PRI)
13224       if (dahdi_sig_pri_lib_handles(tmp->sig)) {
13225          tmp->cid_tag[0] = '\0';
13226       } else
13227 #endif   /* defined(HAVE_PRI) */
13228       {
13229          ast_copy_string(tmp->cid_tag, conf->chan.cid_tag, sizeof(tmp->cid_tag));
13230       }
13231       tmp->cid_subaddr[0] = '\0';
13232       ast_copy_string(tmp->mailbox, conf->chan.mailbox, sizeof(tmp->mailbox));
13233       if (channel != CHAN_PSEUDO && !ast_strlen_zero(tmp->mailbox)) {
13234          char *mailbox, *context;
13235          mailbox = context = ast_strdupa(tmp->mailbox);
13236          strsep(&context, "@");
13237          if (ast_strlen_zero(context))
13238             context = "default";
13239          tmp->mwi_event_sub = ast_event_subscribe(AST_EVENT_MWI, mwi_event_cb, "Dahdi MWI subscription", NULL,
13240             AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
13241             AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
13242             AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS,
13243             AST_EVENT_IE_END);
13244       }
13245 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
13246       tmp->mwisend_setting = conf->chan.mwisend_setting;
13247       tmp->mwisend_fsk  = conf->chan.mwisend_fsk;
13248       tmp->mwisend_rpas = conf->chan.mwisend_rpas;
13249 #endif
13250 
13251       tmp->group = conf->chan.group;
13252       tmp->callgroup = conf->chan.callgroup;
13253       tmp->pickupgroup= conf->chan.pickupgroup;
13254       ast_unref_namedgroups(tmp->named_callgroups);
13255       tmp->named_callgroups = ast_ref_namedgroups(conf->chan.named_callgroups);
13256       ast_unref_namedgroups(tmp->named_pickupgroups);
13257       tmp->named_pickupgroups = ast_ref_namedgroups(conf->chan.named_pickupgroups);
13258       if (conf->chan.vars) {
13259          struct ast_variable *v, *tmpvar;
13260                    for (v = conf->chan.vars ; v ; v = v->next) {
13261                          if ((tmpvar = ast_variable_new(v->name, v->value, v->file))) {
13262                                   tmpvar->next = tmp->vars;
13263                                    tmp->vars = tmpvar;
13264                            }
13265                   }
13266       }
13267       tmp->cid_rxgain = conf->chan.cid_rxgain;
13268       tmp->rxgain = conf->chan.rxgain;
13269       tmp->txgain = conf->chan.txgain;
13270       tmp->txdrc = conf->chan.txdrc;
13271       tmp->rxdrc = conf->chan.rxdrc;
13272       tmp->tonezone = conf->chan.tonezone;
13273       if (tmp->subs[SUB_REAL].dfd > -1) {
13274          set_actual_gain(tmp->subs[SUB_REAL].dfd, tmp->rxgain, tmp->txgain, tmp->rxdrc, tmp->txdrc, tmp->law);
13275          if (tmp->dsp)
13276             ast_dsp_set_digitmode(tmp->dsp, DSP_DIGITMODE_DTMF | tmp->dtmfrelax);
13277          update_conf(tmp);
13278          if (!here) {
13279             switch (chan_sig) {
13280             case SIG_PRI_LIB_HANDLE_CASES:
13281             case SIG_SS7:
13282             case SIG_MFCR2:
13283                break;
13284             default:
13285                /* Hang it up to be sure it's good */
13286                dahdi_set_hook(tmp->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
13287                break;
13288             }
13289          }
13290          ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SETTONEZONE,&tmp->tonezone);
13291          if ((res = get_alarms(tmp)) != DAHDI_ALARM_NONE) {
13292             /* the dchannel is down so put the channel in alarm */
13293             switch (tmp->sig) {
13294 #ifdef HAVE_PRI
13295             case SIG_PRI_LIB_HANDLE_CASES:
13296                sig_pri_set_alarm(tmp->sig_pvt, 1);
13297                break;
13298 #endif
13299 #if defined(HAVE_SS7)
13300             case SIG_SS7:
13301                sig_ss7_set_alarm(tmp->sig_pvt, 1);
13302                break;
13303 #endif   /* defined(HAVE_SS7) */
13304             default:
13305                /* The only sig submodule left should be sig_analog. */
13306                analog_p = tmp->sig_pvt;
13307                if (analog_p) {
13308                   analog_p->inalarm = 1;
13309                }
13310                tmp->inalarm = 1;
13311                break;
13312             }
13313             handle_alarms(tmp, res);
13314          }
13315       }
13316 
13317       tmp->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
13318       tmp->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
13319       tmp->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
13320       tmp->sendcalleridafter = conf->chan.sendcalleridafter;
13321       ast_cc_copy_config_params(tmp->cc_params, conf->chan.cc_params);
13322 
13323       if (!here) {
13324          tmp->locallyblocked = 0;
13325          tmp->remotelyblocked = 0;
13326          switch (tmp->sig) {
13327 #if defined(HAVE_PRI)
13328          case SIG_PRI_LIB_HANDLE_CASES:
13329             tmp->inservice = 1;/* Inservice until actually implemented. */
13330 #if defined(HAVE_PRI_SERVICE_MESSAGES)
13331             ((struct sig_pri_chan *) tmp->sig_pvt)->service_status = 0;
13332             if (chan_sig == SIG_PRI) {
13333                char db_chan_name[20];
13334                char db_answer[5];
13335 
13336                /*
13337                 * Initialize the active out-of-service status
13338                 * and delete any record if the feature is not enabled.
13339                 */
13340                snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, tmp->span, tmp->channel);
13341                if (!ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) {
13342                   unsigned *why;
13343 
13344                   why = &((struct sig_pri_chan *) tmp->sig_pvt)->service_status;
13345                   if (tmp->pri->enable_service_message_support) {
13346                      char state;
13347 
13348                      sscanf(db_answer, "%1c:%30u", &state, why);
13349 
13350                      /* Ensure that only the implemented bits could be set.*/
13351                      *why &= (SRVST_NEAREND | SRVST_FAREND);
13352                   }
13353                   if (!*why) {
13354                      ast_db_del(db_chan_name, SRVST_DBKEY);
13355                   }
13356                }
13357             }
13358 #endif   /* defined(HAVE_PRI_SERVICE_MESSAGES) */
13359             break;
13360 #endif   /* defined(HAVE_PRI) */
13361 #if defined(HAVE_SS7)
13362          case SIG_SS7:
13363             tmp->inservice = 0;
13364             break;
13365 #endif   /* defined(HAVE_SS7) */
13366          default:
13367              /* We default to in service on protocols that don't have a reset */
13368             tmp->inservice = 1;
13369             break;
13370          }
13371       }
13372 
13373       switch (tmp->sig) {
13374 #if defined(HAVE_PRI)
13375       case SIG_PRI_LIB_HANDLE_CASES:
13376          if (pri_chan) {
13377             pri_chan->channel = tmp->channel;
13378             pri_chan->hidecallerid = tmp->hidecallerid;
13379             pri_chan->hidecalleridname = tmp->hidecalleridname;
13380             pri_chan->immediate = tmp->immediate;
13381             pri_chan->inalarm = tmp->inalarm;
13382             pri_chan->priexclusive = tmp->priexclusive;
13383             pri_chan->priindication_oob = tmp->priindication_oob;
13384             pri_chan->use_callerid = tmp->use_callerid;
13385             pri_chan->use_callingpres = tmp->use_callingpres;
13386             ast_copy_string(pri_chan->context, tmp->context,
13387                sizeof(pri_chan->context));
13388             ast_copy_string(pri_chan->mohinterpret, tmp->mohinterpret,
13389                sizeof(pri_chan->mohinterpret));
13390             pri_chan->stripmsd = tmp->stripmsd;
13391          }
13392          break;
13393 #endif   /* defined(HAVE_PRI) */
13394 #if defined(HAVE_SS7)
13395       case SIG_SS7:
13396          if (ss7_chan) {
13397             ss7_chan->inalarm = tmp->inalarm;
13398 
13399             ss7_chan->stripmsd = tmp->stripmsd;
13400             ss7_chan->hidecallerid = tmp->hidecallerid;
13401             ss7_chan->use_callerid = tmp->use_callerid;
13402             ss7_chan->use_callingpres = tmp->use_callingpres;
13403             ss7_chan->immediate = tmp->immediate;
13404             ss7_chan->locallyblocked = tmp->locallyblocked;
13405             ss7_chan->remotelyblocked = tmp->remotelyblocked;
13406             ast_copy_string(ss7_chan->context, tmp->context,
13407                sizeof(ss7_chan->context));
13408             ast_copy_string(ss7_chan->mohinterpret, tmp->mohinterpret,
13409                sizeof(ss7_chan->mohinterpret));
13410          }
13411          break;
13412 #endif   /* defined(HAVE_SS7) */
13413       default:
13414          /* The only sig submodule left should be sig_analog. */
13415          analog_p = tmp->sig_pvt;
13416          if (analog_p) {
13417             analog_p->channel = tmp->channel;
13418             analog_p->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
13419             analog_p->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
13420             analog_p->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
13421             analog_p->permcallwaiting = conf->chan.callwaiting; /* permcallwaiting possibly modified in analog_config_complete */
13422             analog_p->callreturn = conf->chan.callreturn;
13423             analog_p->cancallforward = conf->chan.cancallforward;
13424             analog_p->canpark = conf->chan.canpark;
13425             analog_p->dahditrcallerid = conf->chan.dahditrcallerid;
13426             analog_p->immediate = conf->chan.immediate;
13427             analog_p->permhidecallerid = conf->chan.permhidecallerid;
13428             analog_p->pulse = conf->chan.pulse;
13429             analog_p->threewaycalling = conf->chan.threewaycalling;
13430             analog_p->transfer = conf->chan.transfer;
13431             analog_p->transfertobusy = conf->chan.transfertobusy;
13432             analog_p->use_callerid = tmp->use_callerid;
13433             analog_p->use_smdi = tmp->use_smdi;
13434             analog_p->smdi_iface = tmp->smdi_iface;
13435             analog_p->outsigmod = ANALOG_SIG_NONE;
13436             analog_p->echotraining = conf->chan.echotraining;
13437             analog_p->cid_signalling = conf->chan.cid_signalling;
13438             analog_p->stripmsd = conf->chan.stripmsd;
13439             switch (conf->chan.cid_start) {
13440             case CID_START_POLARITY:
13441                analog_p->cid_start = ANALOG_CID_START_POLARITY;
13442                break;
13443             case CID_START_POLARITY_IN:
13444                analog_p->cid_start = ANALOG_CID_START_POLARITY_IN;
13445                break;
13446             case CID_START_DTMF_NOALERT:
13447                analog_p->cid_start = ANALOG_CID_START_DTMF_NOALERT;
13448                break;
13449             default:
13450                analog_p->cid_start = ANALOG_CID_START_RING;
13451                break;
13452             }
13453             analog_p->callwaitingcallerid = conf->chan.callwaitingcallerid;
13454             analog_p->ringt = conf->chan.ringt;
13455             analog_p->ringt_base = ringt_base;
13456             analog_p->onhooktime = time(NULL);
13457             if (chan_sig & __DAHDI_SIG_FXO) {
13458                memset(&p, 0, sizeof(p));
13459                res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
13460                if (!res) {
13461                   analog_p->fxsoffhookstate = p.rxisoffhook;
13462                }
13463 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
13464                res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_VMWI_CONFIG, &tmp->mwisend_setting);
13465 #endif
13466             }
13467             analog_p->msgstate = -1;
13468 
13469             ast_copy_string(analog_p->mohsuggest, conf->chan.mohsuggest, sizeof(analog_p->mohsuggest));
13470             ast_copy_string(analog_p->cid_num, conf->chan.cid_num, sizeof(analog_p->cid_num));
13471             ast_copy_string(analog_p->cid_name, conf->chan.cid_name, sizeof(analog_p->cid_name));
13472 
13473             analog_config_complete(analog_p);
13474          }
13475          break;
13476       }
13477 #if defined(HAVE_PRI)
13478       if (tmp->channel == CHAN_PSEUDO) {
13479          /*
13480           * Save off pseudo channel buffer policy values for dynamic creation of
13481           * no B channel interfaces.
13482           */
13483          dahdi_pseudo_parms.buf_no = tmp->buf_no;
13484          dahdi_pseudo_parms.buf_policy = tmp->buf_policy;
13485          dahdi_pseudo_parms.faxbuf_no = tmp->faxbuf_no;
13486          dahdi_pseudo_parms.faxbuf_policy = tmp->faxbuf_policy;
13487       }
13488 #endif   /* defined(HAVE_PRI) */
13489    }
13490    if (tmp && !here) {
13491       /* Add the new channel interface to the sorted channel interface list. */
13492       dahdi_iflist_insert(tmp);
13493    }
13494    return tmp;
13495 }
13496 
13497 static int is_group_or_channel_match(struct dahdi_pvt *p, int span, ast_group_t groupmatch, int *groupmatched, int channelmatch, int *channelmatched)
13498 {
13499 #if defined(HAVE_PRI)
13500    if (0 < span) {
13501       /* The channel must be on the specified PRI span. */
13502       if (!p->pri || p->pri->span != span) {
13503          return 0;
13504       }
13505       if (!groupmatch && channelmatch == -1) {
13506          /* Match any group since it only needs to be on the PRI span. */
13507          *groupmatched = 1;
13508          return 1;
13509       }
13510    }
13511 #endif   /* defined(HAVE_PRI) */
13512    /* check group matching */
13513    if (groupmatch) {
13514       if ((p->group & groupmatch) != groupmatch)
13515          /* Doesn't match the specified group, try the next one */
13516          return 0;
13517       *groupmatched = 1;
13518    }
13519    /* Check to see if we have a channel match */
13520    if (channelmatch != -1) {
13521       if (p->channel != channelmatch)
13522          /* Doesn't match the specified channel, try the next one */
13523          return 0;
13524       *channelmatched = 1;
13525    }
13526 
13527    return 1;
13528 }
13529 
13530 static int available(struct dahdi_pvt **pvt, int is_specific_channel)
13531 {
13532    struct dahdi_pvt *p = *pvt;
13533 
13534    if (p->inalarm)
13535       return 0;
13536 
13537    if (analog_lib_handles(p->sig, p->radio, p->oprmode))
13538       return analog_available(p->sig_pvt);
13539 
13540    switch (p->sig) {
13541 #if defined(HAVE_PRI)
13542    case SIG_PRI_LIB_HANDLE_CASES:
13543       {
13544          struct sig_pri_chan *pvt_chan;
13545          int res;
13546 
13547          pvt_chan = p->sig_pvt;
13548          res = sig_pri_available(&pvt_chan, is_specific_channel);
13549          *pvt = pvt_chan->chan_pvt;
13550          return res;
13551       }
13552 #endif   /* defined(HAVE_PRI) */
13553 #if defined(HAVE_SS7)
13554    case SIG_SS7:
13555       return sig_ss7_available(p->sig_pvt);
13556 #endif   /* defined(HAVE_SS7) */
13557    default:
13558       break;
13559    }
13560 
13561    if (p->locallyblocked || p->remotelyblocked) {
13562       return 0;
13563    }
13564 
13565    /* If no owner definitely available */
13566    if (!p->owner) {
13567 #ifdef HAVE_OPENR2
13568       /* Trust MFC/R2 */
13569       if (p->mfcr2) {
13570          if (p->mfcr2call) {
13571             return 0;
13572          } else {
13573             return 1;
13574          }
13575       }
13576 #endif
13577       return 1;
13578    }
13579 
13580    return 0;
13581 }
13582 
13583 #if defined(HAVE_PRI)
13584 #if defined(HAVE_PRI_CALL_WAITING)
13585 /*!
13586  * \internal
13587  * \brief Init the private channel configuration using the span controller.
13588  * \since 1.8
13589  *
13590  * \param priv Channel to init the configuration.
13591  * \param pri sig_pri PRI control structure.
13592  *
13593  * \note Assumes the pri->lock is already obtained.
13594  *
13595  * \return Nothing
13596  */
13597 static void my_pri_init_config(void *priv, struct sig_pri_span *pri)
13598 {
13599    struct dahdi_pvt *pvt = priv;
13600 
13601    pvt->stripmsd = pri->ch_cfg.stripmsd;
13602    pvt->hidecallerid = pri->ch_cfg.hidecallerid;
13603    pvt->hidecalleridname = pri->ch_cfg.hidecalleridname;
13604    pvt->immediate = pri->ch_cfg.immediate;
13605    pvt->priexclusive = pri->ch_cfg.priexclusive;
13606    pvt->priindication_oob = pri->ch_cfg.priindication_oob;
13607    pvt->use_callerid = pri->ch_cfg.use_callerid;
13608    pvt->use_callingpres = pri->ch_cfg.use_callingpres;
13609    ast_copy_string(pvt->context, pri->ch_cfg.context, sizeof(pvt->context));
13610    ast_copy_string(pvt->mohinterpret, pri->ch_cfg.mohinterpret, sizeof(pvt->mohinterpret));
13611 }
13612 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
13613 #endif   /* defined(HAVE_PRI) */
13614 
13615 #if defined(HAVE_PRI)
13616 /*!
13617  * \internal
13618  * \brief Create a no B channel interface.
13619  * \since 1.8
13620  *
13621  * \param pri sig_pri span controller to add interface.
13622  *
13623  * \note Assumes the pri->lock is already obtained.
13624  *
13625  * \retval array-index into private pointer array on success.
13626  * \retval -1 on error.
13627  */
13628 static int dahdi_new_pri_nobch_channel(struct sig_pri_span *pri)
13629 {
13630    int pvt_idx;
13631    int res;
13632    unsigned idx;
13633    struct dahdi_pvt *pvt;
13634    struct sig_pri_chan *chan;
13635    struct dahdi_bufferinfo bi;
13636 
13637    static int nobch_channel = CHAN_PSEUDO;
13638 
13639    /* Find spot in the private pointer array for new interface. */
13640    for (pvt_idx = 0; pvt_idx < pri->numchans; ++pvt_idx) {
13641       if (!pri->pvts[pvt_idx]) {
13642          break;
13643       }
13644    }
13645    if (pri->numchans == pvt_idx) {
13646       if (ARRAY_LEN(pri->pvts) <= pvt_idx) {
13647          ast_log(LOG_ERROR, "Unable to add a no-B-channel interface!\n");
13648          return -1;
13649       }
13650 
13651       /* Add new spot to the private pointer array. */
13652       pri->pvts[pvt_idx] = NULL;
13653       ++pri->numchans;
13654    }
13655 
13656    pvt = ast_calloc(1, sizeof(*pvt));
13657    if (!pvt) {
13658       return -1;
13659    }
13660    pvt->cc_params = ast_cc_config_params_init();
13661    if (!pvt->cc_params) {
13662       ast_free(pvt);
13663       return -1;
13664    }
13665    ast_mutex_init(&pvt->lock);
13666    for (idx = 0; idx < ARRAY_LEN(pvt->subs); ++idx) {
13667       pvt->subs[idx].dfd = -1;
13668    }
13669    pvt->buf_no = dahdi_pseudo_parms.buf_no;
13670    pvt->buf_policy = dahdi_pseudo_parms.buf_policy;
13671    pvt->faxbuf_no = dahdi_pseudo_parms.faxbuf_no;
13672    pvt->faxbuf_policy = dahdi_pseudo_parms.faxbuf_policy;
13673 
13674    chan = sig_pri_chan_new(pvt, pri, 0, 0, 0);
13675    if (!chan) {
13676       destroy_dahdi_pvt(pvt);
13677       return -1;
13678    }
13679    chan->no_b_channel = 1;
13680 
13681    /*
13682     * Pseudo channel companding law.
13683     * Needed for outgoing call waiting calls.
13684     * XXX May need to make this determined by switchtype or user option.
13685     */
13686    pvt->law_default = DAHDI_LAW_ALAW;
13687 
13688    pvt->sig = pri->sig;
13689    pvt->outsigmod = -1;
13690    pvt->pri = pri;
13691    pvt->sig_pvt = chan;
13692    pri->pvts[pvt_idx] = chan;
13693 
13694    pvt->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo");
13695    if (pvt->subs[SUB_REAL].dfd < 0) {
13696       ast_log(LOG_ERROR, "Unable to open no B channel interface pseudo channel: %s\n",
13697          strerror(errno));
13698       destroy_dahdi_pvt(pvt);
13699       return -1;
13700    }
13701    memset(&bi, 0, sizeof(bi));
13702    res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
13703    if (!res) {
13704       pvt->bufsize = bi.bufsize;
13705       bi.txbufpolicy = pvt->buf_policy;
13706       bi.rxbufpolicy = pvt->buf_policy;
13707       bi.numbufs = pvt->buf_no;
13708       res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
13709       if (res < 0) {
13710          ast_log(LOG_WARNING,
13711             "Unable to set buffer policy on no B channel interface: %s\n",
13712             strerror(errno));
13713       }
13714    } else
13715       ast_log(LOG_WARNING,
13716          "Unable to check buffer policy on no B channel interface: %s\n",
13717          strerror(errno));
13718 
13719    --nobch_channel;
13720    if (CHAN_PSEUDO < nobch_channel) {
13721       nobch_channel = CHAN_PSEUDO - 1;
13722    }
13723    pvt->channel = nobch_channel;
13724    pvt->span = pri->span;
13725    chan->channel = pvt->channel;
13726 
13727    dahdi_nobch_insert(pri, pvt);
13728 
13729    return pvt_idx;
13730 }
13731 #endif   /* defined(HAVE_PRI) */
13732 
13733 /* This function can *ONLY* be used for copying pseudo (CHAN_PSEUDO) private
13734    structures; it makes no attempt to safely copy regular channel private
13735    structures that might contain reference-counted object pointers and other
13736    scary bits
13737 */
13738 static struct dahdi_pvt *duplicate_pseudo(struct dahdi_pvt *src)
13739 {
13740    struct dahdi_pvt *p;
13741    struct dahdi_bufferinfo bi;
13742    int res;
13743 
13744    p = ast_malloc(sizeof(*p));
13745    if (!p) {
13746       return NULL;
13747    }
13748    *p = *src;
13749 
13750    /* Must deep copy the cc_params. */
13751    p->cc_params = ast_cc_config_params_init();
13752    if (!p->cc_params) {
13753       ast_free(p);
13754       return NULL;
13755    }
13756    ast_cc_copy_config_params(p->cc_params, src->cc_params);
13757 
13758    p->which_iflist = DAHDI_IFLIST_NONE;
13759    p->next = NULL;
13760    p->prev = NULL;
13761    ast_mutex_init(&p->lock);
13762    p->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo");
13763    if (p->subs[SUB_REAL].dfd < 0) {
13764       ast_log(LOG_ERROR, "Unable to dup channel: %s\n", strerror(errno));
13765       destroy_dahdi_pvt(p);
13766       return NULL;
13767    }
13768    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
13769    if (!res) {
13770       bi.txbufpolicy = src->buf_policy;
13771       bi.rxbufpolicy = src->buf_policy;
13772       bi.numbufs = src->buf_no;
13773       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
13774       if (res < 0) {
13775          ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel: %s\n", strerror(errno));
13776       }
13777    } else
13778       ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel: %s\n", strerror(errno));
13779    p->destroy = 1;
13780    dahdi_iflist_insert(p);
13781    return p;
13782 }
13783 
13784 struct dahdi_starting_point {
13785    /*! Group matching mask.  Zero if not specified. */
13786    ast_group_t groupmatch;
13787    /*! DAHDI channel to match with.  -1 if not specified. */
13788    int channelmatch;
13789    /*! Round robin saved search location index. (Valid if roundrobin TRUE) */
13790    int rr_starting_point;
13791    /*! ISDN span where channels can be picked (Zero if not specified) */
13792    int span;
13793    /*! Analog channel distinctive ring cadance index. */
13794    int cadance;
13795    /*! Dialing option. c/r/d if present and valid. */
13796    char opt;
13797    /*! TRUE if to search the channel list backwards. */
13798    char backwards;
13799    /*! TRUE if search is done with round robin sequence. */
13800    char roundrobin;
13801 };
13802 static struct dahdi_pvt *determine_starting_point(const char *data, struct dahdi_starting_point *param)
13803 {
13804    char *dest;
13805    char *s;
13806    int x;
13807    int res = 0;
13808    struct dahdi_pvt *p;
13809    char *subdir = NULL;
13810    AST_DECLARE_APP_ARGS(args,
13811       AST_APP_ARG(group);  /* channel/group token */
13812       //AST_APP_ARG(ext);  /* extension token */
13813       //AST_APP_ARG(opts); /* options token */
13814       AST_APP_ARG(other);  /* Any remining unused arguments */
13815    );
13816 
13817    /*
13818     * data is ---v
13819     * Dial(DAHDI/pseudo[/extension[/options]])
13820     * Dial(DAHDI/<channel#>[c|r<cadance#>|d][/extension[/options]])
13821     * Dial(DAHDI/<subdir>!<channel#>[c|r<cadance#>|d][/extension[/options]])
13822     * Dial(DAHDI/i<span>[/extension[/options]])
13823     * Dial(DAHDI/[i<span>-](g|G|r|R)<group#(0-63)>[c|r<cadance#>|d][/extension[/options]])
13824     *
13825     * i - ISDN span channel restriction.
13826     *     Used by CC to ensure that the CC recall goes out the same span.
13827     *     Also to make ISDN channel names dialable when the sequence number
13828     *     is stripped off.  (Used by DTMF attended transfer feature.)
13829     *
13830     * g - channel group allocation search forward
13831     * G - channel group allocation search backward
13832     * r - channel group allocation round robin search forward
13833     * R - channel group allocation round robin search backward
13834     *
13835     * c - Wait for DTMF digit to confirm answer
13836     * r<cadance#> - Set distintive ring cadance number
13837     * d - Force bearer capability for ISDN/SS7 call to digital.
13838     */
13839 
13840    if (data) {
13841       dest = ast_strdupa(data);
13842    } else {
13843       ast_log(LOG_WARNING, "Channel requested with no data\n");
13844       return NULL;
13845    }
13846    AST_NONSTANDARD_APP_ARGS(args, dest, '/');
13847    if (!args.argc || ast_strlen_zero(args.group)) {
13848       ast_log(LOG_WARNING, "No channel/group specified\n");
13849       return NULL;
13850    }
13851 
13852    /* Initialize the output parameters */
13853    memset(param, 0, sizeof(*param));
13854    param->channelmatch = -1;
13855 
13856    if (strchr(args.group, '!') != NULL) {
13857       char *prev = args.group;
13858       while ((s = strchr(prev, '!')) != NULL) {
13859          *s++ = '/';
13860          prev = s;
13861       }
13862       *(prev - 1) = '\0';
13863       subdir = args.group;
13864       args.group = prev;
13865    } else if (args.group[0] == 'i') {
13866       /* Extract the ISDN span channel restriction specifier. */
13867       res = sscanf(args.group + 1, "%30d", &x);
13868       if (res < 1) {
13869          ast_log(LOG_WARNING, "Unable to determine ISDN span for data %s\n", data);
13870          return NULL;
13871       }
13872       param->span = x;
13873 
13874       /* Remove the ISDN span channel restriction specifier. */
13875       s = strchr(args.group, '-');
13876       if (!s) {
13877          /* Search all groups since we are ISDN span restricted. */
13878          return iflist;
13879       }
13880       args.group = s + 1;
13881       res = 0;
13882    }
13883    if (toupper(args.group[0]) == 'G' || toupper(args.group[0])=='R') {
13884       /* Retrieve the group number */
13885       s = args.group + 1;
13886       res = sscanf(s, "%30d%1c%30d", &x, &param->opt, &param->cadance);
13887       if (res < 1) {
13888          ast_log(LOG_WARNING, "Unable to determine group for data %s\n", data);
13889          return NULL;
13890       }
13891       param->groupmatch = ((ast_group_t) 1 << x);
13892 
13893       if (toupper(args.group[0]) == 'G') {
13894          if (args.group[0] == 'G') {
13895             param->backwards = 1;
13896             p = ifend;
13897          } else
13898             p = iflist;
13899       } else {
13900          if (ARRAY_LEN(round_robin) <= x) {
13901             ast_log(LOG_WARNING, "Round robin index %d out of range for data %s\n",
13902                x, data);
13903             return NULL;
13904          }
13905          if (args.group[0] == 'R') {
13906             param->backwards = 1;
13907             p = round_robin[x] ? round_robin[x]->prev : ifend;
13908             if (!p)
13909                p = ifend;
13910          } else {
13911             p = round_robin[x] ? round_robin[x]->next : iflist;
13912             if (!p)
13913                p = iflist;
13914          }
13915          param->roundrobin = 1;
13916          param->rr_starting_point = x;
13917       }
13918    } else {
13919       s = args.group;
13920       if (!strcasecmp(s, "pseudo")) {
13921          /* Special case for pseudo */
13922          x = CHAN_PSEUDO;
13923          param->channelmatch = x;
13924       } else {
13925          res = sscanf(s, "%30d%1c%30d", &x, &param->opt, &param->cadance);
13926          if (res < 1) {
13927             ast_log(LOG_WARNING, "Unable to determine channel for data %s\n", data);
13928             return NULL;
13929          } else {
13930             param->channelmatch = x;
13931          }
13932       }
13933       if (subdir) {
13934          char path[PATH_MAX];
13935          struct stat stbuf;
13936 
13937          snprintf(path, sizeof(path), "/dev/dahdi/%s/%d",
13938                subdir, param->channelmatch);
13939          if (stat(path, &stbuf) < 0) {
13940             ast_log(LOG_WARNING, "stat(%s) failed: %s\n",
13941                   path, strerror(errno));
13942             return NULL;
13943          }
13944          if (!S_ISCHR(stbuf.st_mode)) {
13945             ast_log(LOG_ERROR, "%s: Not a character device file\n",
13946                   path);
13947             return NULL;
13948          }
13949          param->channelmatch = minor(stbuf.st_rdev);
13950       }
13951 
13952       p = iflist;
13953    }
13954 
13955    if (param->opt == 'r' && res < 3) {
13956       ast_log(LOG_WARNING, "Distinctive ring missing identifier in '%s'\n", data);
13957       param->opt = '\0';
13958    }
13959 
13960    return p;
13961 }
13962 
13963 static struct ast_channel *dahdi_request(const char *type, struct ast_format_cap *cap, const struct ast_channel *requestor, const char *data, int *cause)
13964 {
13965    int callwait = 0;
13966    struct dahdi_pvt *p;
13967    struct ast_channel *tmp = NULL;
13968    struct dahdi_pvt *exitpvt;
13969    int channelmatched = 0;
13970    int groupmatched = 0;
13971 #if defined(HAVE_PRI) || defined(HAVE_SS7)
13972    int transcapdigital = 0;
13973 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
13974    struct dahdi_starting_point start;
13975    struct ast_callid *callid = NULL;
13976    int callid_created = ast_callid_threadstorage_auto(&callid);
13977 
13978    ast_mutex_lock(&iflock);
13979    p = determine_starting_point(data, &start);
13980    if (!p) {
13981       /* We couldn't determine a starting point, which likely means badly-formatted channel name. Abort! */
13982       ast_mutex_unlock(&iflock);
13983       ast_callid_threadstorage_auto_clean(callid, callid_created);
13984       return NULL;
13985    }
13986 
13987    /* Search for an unowned channel */
13988    exitpvt = p;
13989    while (p && !tmp) {
13990       if (start.roundrobin)
13991          round_robin[start.rr_starting_point] = p;
13992 
13993       if (is_group_or_channel_match(p, start.span, start.groupmatch, &groupmatched, start.channelmatch, &channelmatched)
13994          && available(&p, channelmatched)) {
13995          ast_debug(1, "Using channel %d\n", p->channel);
13996 
13997          callwait = (p->owner != NULL);
13998 #ifdef HAVE_OPENR2
13999          if (p->mfcr2) {
14000             ast_mutex_lock(&p->lock);
14001             if (p->mfcr2call) {
14002                ast_mutex_unlock(&p->lock);
14003                ast_debug(1, "Yay!, someone just beat us in the race for channel %d.\n", p->channel);
14004                goto next;
14005             }
14006             p->mfcr2call = 1;
14007             ast_mutex_unlock(&p->lock);
14008          }
14009 #endif
14010          if (p->channel == CHAN_PSEUDO) {
14011             p = duplicate_pseudo(p);
14012             if (!p) {
14013                break;
14014             }
14015          }
14016 
14017          p->distinctivering = 0;
14018          /* Make special notes */
14019          switch (start.opt) {
14020          case '\0':
14021             /* No option present. */
14022             break;
14023          case 'c':
14024             /* Confirm answer */
14025             p->confirmanswer = 1;
14026             break;
14027          case 'r':
14028             /* Distinctive ring */
14029             p->distinctivering = start.cadance;
14030             break;
14031          case 'd':
14032 #if defined(HAVE_PRI) || defined(HAVE_SS7)
14033             /* If this is an ISDN call, make it digital */
14034             transcapdigital = AST_TRANS_CAP_DIGITAL;
14035 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
14036             break;
14037          default:
14038             ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", start.opt, data);
14039             break;
14040          }
14041 
14042          p->outgoing = 1;
14043          if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
14044             tmp = analog_request(p->sig_pvt, &callwait, requestor);
14045 #ifdef HAVE_PRI
14046          } else if (dahdi_sig_pri_lib_handles(p->sig)) {
14047             /*
14048              * We already have the B channel reserved for this call.  We
14049              * just need to make sure that dahdi_hangup() has completed
14050              * cleaning up before continuing.
14051              */
14052             ast_mutex_lock(&p->lock);
14053             ast_mutex_unlock(&p->lock);
14054 
14055             sig_pri_extract_called_num_subaddr(p->sig_pvt, data, p->dnid,
14056                sizeof(p->dnid));
14057             tmp = sig_pri_request(p->sig_pvt, SIG_PRI_DEFLAW, requestor, transcapdigital);
14058 #endif
14059 #if defined(HAVE_SS7)
14060          } else if (p->sig == SIG_SS7) {
14061             tmp = sig_ss7_request(p->sig_pvt, SIG_SS7_DEFLAW, requestor, transcapdigital);
14062 #endif   /* defined(HAVE_SS7) */
14063          } else {
14064             tmp = dahdi_new(p, AST_STATE_RESERVED, 0, p->owner ? SUB_CALLWAIT : SUB_REAL, 0, requestor ? ast_channel_linkedid(requestor) : "", callid);
14065          }
14066          if (!tmp) {
14067             p->outgoing = 0;
14068 #if defined(HAVE_PRI)
14069             switch (p->sig) {
14070             case SIG_PRI_LIB_HANDLE_CASES:
14071 #if defined(HAVE_PRI_CALL_WAITING)
14072                if (((struct sig_pri_chan *) p->sig_pvt)->is_call_waiting) {
14073                   ((struct sig_pri_chan *) p->sig_pvt)->is_call_waiting = 0;
14074                   ast_atomic_fetchadd_int(&p->pri->num_call_waiting_calls, -1);
14075                }
14076 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
14077                /*
14078                 * This should be the last thing to clear when we are done with
14079                 * the channel.
14080                 */
14081                ((struct sig_pri_chan *) p->sig_pvt)->allocated = 0;
14082                break;
14083             default:
14084                break;
14085             }
14086 #endif   /* defined(HAVE_PRI) */
14087          } else {
14088             snprintf(p->dialstring, sizeof(p->dialstring), "DAHDI/%s", data);
14089          }
14090          break;
14091       }
14092 #ifdef HAVE_OPENR2
14093 next:
14094 #endif
14095       if (start.backwards) {
14096          p = p->prev;
14097          if (!p)
14098             p = ifend;
14099       } else {
14100          p = p->next;
14101          if (!p)
14102             p = iflist;
14103       }
14104       /* stop when you roll to the one that we started from */
14105       if (p == exitpvt)
14106          break;
14107    }
14108    ast_mutex_unlock(&iflock);
14109    restart_monitor();
14110    if (cause && !tmp) {
14111       if (callwait || channelmatched) {
14112          *cause = AST_CAUSE_BUSY;
14113       } else if (groupmatched) {
14114          *cause = AST_CAUSE_CONGESTION;
14115       } else {
14116          /*
14117           * We did not match any channel requested.
14118           * Dialplan error requesting non-existant channel?
14119           */
14120       }
14121    }
14122 
14123    ast_callid_threadstorage_auto_clean(callid, callid_created);
14124    return tmp;
14125 }
14126 
14127 /*!
14128  * \internal
14129  * \brief Determine the device state for a given DAHDI device if we can.
14130  * \since 1.8
14131  *
14132  * \param data DAHDI device name after "DAHDI/".
14133  *
14134  * \retval device_state enum ast_device_state value.
14135  * \retval AST_DEVICE_UNKNOWN if we could not determine the device's state.
14136  */
14137 static int dahdi_devicestate(const char *data)
14138 {
14139 #if defined(HAVE_PRI)
14140    const char *device;
14141    unsigned span;
14142    int res;
14143 
14144    device = data;
14145 
14146    if (*device != 'I') {
14147       /* The request is not for an ISDN span device. */
14148       return AST_DEVICE_UNKNOWN;
14149    }
14150    res = sscanf(device, "I%30u", &span);
14151    if (res != 1 || !span || NUM_SPANS < span) {
14152       /* Bad format for ISDN span device name. */
14153       return AST_DEVICE_UNKNOWN;
14154    }
14155    device = strchr(device, '/');
14156    if (!device) {
14157       /* Bad format for ISDN span device name. */
14158       return AST_DEVICE_UNKNOWN;
14159    }
14160 
14161    /*
14162     * Since there are currently no other span devstate's defined,
14163     * it must be congestion.
14164     */
14165 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
14166    ++device;
14167    if (!strcmp(device, "congestion"))
14168 #endif   /* defined(THRESHOLD_DEVSTATE_PLACEHOLDER) */
14169    {
14170       return pris[span - 1].pri.congestion_devstate;
14171    }
14172 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
14173    else if (!strcmp(device, "threshold")) {
14174       return pris[span - 1].pri.threshold_devstate;
14175    }
14176    return AST_DEVICE_UNKNOWN;
14177 #endif   /* defined(THRESHOLD_DEVSTATE_PLACEHOLDER) */
14178 #else
14179    return AST_DEVICE_UNKNOWN;
14180 #endif   /* defined(HAVE_PRI) */
14181 }
14182 
14183 /*!
14184  * \brief Callback made when dial failed to get a channel out of dahdi_request().
14185  * \since 1.8
14186  *
14187  * \param inbound Incoming asterisk channel.
14188  * \param dest Same dial string passed to dahdi_request().
14189  * \param callback Callback into CC core to announce a busy channel available for CC.
14190  *
14191  * \details
14192  * This callback acts like a forked dial with all prongs of the fork busy.
14193  * Essentially, for each channel that could have taken the call, indicate that
14194  * it is busy.
14195  *
14196  * \retval 0 on success.
14197  * \retval -1 on error.
14198  */
14199 static int dahdi_cc_callback(struct ast_channel *inbound, const char *dest, ast_cc_callback_fn callback)
14200 {
14201    struct dahdi_pvt *p;
14202    struct dahdi_pvt *exitpvt;
14203    struct dahdi_starting_point start;
14204    int groupmatched = 0;
14205    int channelmatched = 0;
14206 
14207    ast_mutex_lock(&iflock);
14208    p = determine_starting_point(dest, &start);
14209    if (!p) {
14210       ast_mutex_unlock(&iflock);
14211       return -1;
14212    }
14213    exitpvt = p;
14214    for (;;) {
14215       if (is_group_or_channel_match(p, start.span, start.groupmatch, &groupmatched, start.channelmatch, &channelmatched)) {
14216          /* We found a potential match. call the callback */
14217          struct ast_str *device_name;
14218          char *dash;
14219          const char *monitor_type;
14220          char dialstring[AST_CHANNEL_NAME];
14221          char full_device_name[AST_CHANNEL_NAME];
14222 
14223          switch (ast_get_cc_monitor_policy(p->cc_params)) {
14224          case AST_CC_MONITOR_NEVER:
14225             break;
14226          case AST_CC_MONITOR_NATIVE:
14227          case AST_CC_MONITOR_ALWAYS:
14228          case AST_CC_MONITOR_GENERIC:
14229 #if defined(HAVE_PRI)
14230             if (dahdi_sig_pri_lib_handles(p->sig)) {
14231                /*
14232                 * ISDN is in a trunk busy condition so we need to monitor
14233                 * the span congestion device state.
14234                 */
14235                snprintf(full_device_name, sizeof(full_device_name),
14236                   "DAHDI/I%d/congestion", p->pri->span);
14237             } else
14238 #endif   /* defined(HAVE_PRI) */
14239             {
14240 #if defined(HAVE_PRI)
14241                device_name = create_channel_name(p, 1, "");
14242 #else
14243                device_name = create_channel_name(p);
14244 #endif   /* defined(HAVE_PRI) */
14245                snprintf(full_device_name, sizeof(full_device_name), "DAHDI/%s",
14246                   device_name ? ast_str_buffer(device_name) : "");
14247                ast_free(device_name);
14248                /*
14249                 * The portion after the '-' in the channel name is either a random
14250                 * number, a sequence number, or a subchannel number. None are
14251                 * necessary so strip them off.
14252                 */
14253                dash = strrchr(full_device_name, '-');
14254                if (dash) {
14255                   *dash = '\0';
14256                }
14257             }
14258             snprintf(dialstring, sizeof(dialstring), "DAHDI/%s", dest);
14259 
14260             /*
14261              * Analog can only do generic monitoring.
14262              * ISDN is in a trunk busy condition and any "device" is going
14263              * to be busy until a B channel becomes available.  The generic
14264              * monitor can do this task.
14265              */
14266             monitor_type = AST_CC_GENERIC_MONITOR_TYPE;
14267             callback(inbound,
14268 #if defined(HAVE_PRI)
14269                p->pri ? p->pri->cc_params : p->cc_params,
14270 #else
14271                p->cc_params,
14272 #endif   /* defined(HAVE_PRI) */
14273                monitor_type, full_device_name, dialstring, NULL);
14274             break;
14275          }
14276       }
14277       p = start.backwards ? p->prev : p->next;
14278       if (!p) {
14279          p = start.backwards ? ifend : iflist;
14280       }
14281       if (p == exitpvt) {
14282          break;
14283       }
14284    }
14285    ast_mutex_unlock(&iflock);
14286    return 0;
14287 }
14288 
14289 #if defined(HAVE_SS7)
14290 static void dahdi_ss7_message(struct ss7 *ss7, char *s)
14291 {
14292    int i;
14293 
14294    if (ss7) {
14295       for (i = 0; i < NUM_SPANS; i++) {
14296          if (linksets[i].ss7.ss7 == ss7) {
14297             ast_verbose_callid(NULL, "[%d] %s", i + 1, s);
14298             return;
14299          }
14300       }
14301    }
14302    ast_verbose_callid(NULL, "%s", s);
14303 }
14304 #endif   /* defined(HAVE_SS7) */
14305 
14306 #if defined(HAVE_SS7)
14307 static void dahdi_ss7_error(struct ss7 *ss7, char *s)
14308 {
14309    int i;
14310 
14311    if (ss7) {
14312       for (i = 0; i < NUM_SPANS; i++) {
14313          if (linksets[i].ss7.ss7 == ss7) {
14314             ast_log_callid(LOG_ERROR, NULL, "[%d] %s", i + 1, s);
14315             return;
14316          }
14317       }
14318    }
14319    ast_log_callid(LOG_ERROR, NULL, "%s", s);
14320 }
14321 #endif   /* defined(HAVE_SS7) */
14322 
14323 #if defined(HAVE_OPENR2)
14324 static void *mfcr2_monitor(void *data)
14325 {
14326    struct dahdi_mfcr2 *mfcr2 = data;
14327    /* we should be using pthread_key_create
14328       and allocate pollers dynamically.
14329       I think do_monitor() could be leaking, since it
14330       could be cancelled at any time and is not
14331       using thread keys, why?, */
14332    struct pollfd pollers[ARRAY_LEN(mfcr2->pvts)];
14333    int res = 0;
14334    int i = 0;
14335    int oldstate = 0;
14336    int quit_loop = 0;
14337    int maxsleep = 20;
14338    int was_idle = 0;
14339    int pollsize = 0;
14340    /* now that we're ready to get calls, unblock our side and
14341       get current line state */
14342    for (i = 0; i < mfcr2->numchans; i++) {
14343       openr2_chan_set_idle(mfcr2->pvts[i]->r2chan);
14344       openr2_chan_handle_cas(mfcr2->pvts[i]->r2chan);
14345    }
14346    while (1) {
14347       /* we trust here that the mfcr2 channel list will not ever change once
14348          the module is loaded */
14349       pollsize = 0;
14350       for (i = 0; i < mfcr2->numchans; i++) {
14351          pollers[i].revents = 0;
14352          pollers[i].events = 0;
14353          if (mfcr2->pvts[i]->owner) {
14354             continue;
14355          }
14356          if (!mfcr2->pvts[i]->r2chan) {
14357             ast_debug(1, "Wow, no r2chan on channel %d\n", mfcr2->pvts[i]->channel);
14358             quit_loop = 1;
14359             break;
14360          }
14361          openr2_chan_enable_read(mfcr2->pvts[i]->r2chan);
14362          pollers[i].events = POLLIN | POLLPRI;
14363          pollers[i].fd = mfcr2->pvts[i]->subs[SUB_REAL].dfd;
14364          pollsize++;
14365       }
14366       if (quit_loop) {
14367          break;
14368       }
14369       if (pollsize == 0) {
14370          if (!was_idle) {
14371             ast_debug(1, "Monitor thread going idle since everybody has an owner\n");
14372             was_idle = 1;
14373          }
14374          poll(NULL, 0, maxsleep);
14375          continue;
14376       }
14377       was_idle = 0;
14378       /* probably poll() is a valid cancel point, lets just be on the safe side
14379          by calling pthread_testcancel */
14380       pthread_testcancel();
14381       res = poll(pollers, mfcr2->numchans, maxsleep);
14382       pthread_testcancel();
14383       if ((res < 0) && (errno != EINTR)) {
14384          ast_log(LOG_ERROR, "going out, poll failed: %s\n", strerror(errno));
14385          break;
14386       }
14387       /* do we want to allow to cancel while processing events? */
14388       pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate);
14389       for (i = 0; i < mfcr2->numchans; i++) {
14390          if (pollers[i].revents & POLLPRI || pollers[i].revents & POLLIN) {
14391             openr2_chan_process_event(mfcr2->pvts[i]->r2chan);
14392          }
14393       }
14394       pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
14395    }
14396    ast_log(LOG_NOTICE, "Quitting MFC/R2 monitor thread\n");
14397    return 0;
14398 }
14399 #endif /* HAVE_OPENR2 */
14400 
14401 #if defined(HAVE_PRI)
14402 static void dahdi_pri_message(struct pri *pri, char *s)
14403 {
14404    int x;
14405    int y;
14406    int dchan = -1;
14407    int span = -1;
14408    int dchancount = 0;
14409 
14410    if (pri) {
14411       for (x = 0; x < NUM_SPANS; x++) {
14412          for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
14413             if (pris[x].pri.dchans[y]) {
14414                dchancount++;
14415             }
14416 
14417             if (pris[x].pri.dchans[y] == pri) {
14418                dchan = y;
14419             }
14420          }
14421          if (dchan >= 0) {
14422             span = x;
14423             break;
14424          }
14425          dchancount = 0;
14426       }
14427       if (-1 < span) {
14428          if (1 < dchancount) {
14429             ast_verbose_callid(NULL, "[PRI Span: %d D-Channel: %d] %s", span + 1, dchan, s);
14430          } else {
14431             ast_verbose_callid(NULL, "PRI Span: %d %s", span + 1, s);
14432          }
14433       } else {
14434          ast_verbose_callid(NULL, "PRI Span: ? %s", s);
14435       }
14436    } else {
14437       ast_verbose_callid(NULL, "PRI Span: ? %s", s);
14438    }
14439 
14440    ast_mutex_lock(&pridebugfdlock);
14441 
14442    if (pridebugfd >= 0) {
14443       if (write(pridebugfd, s, strlen(s)) < 0) {
14444          ast_log_callid(LOG_WARNING, NULL, "write() failed: %s\n", strerror(errno));
14445       }
14446    }
14447 
14448    ast_mutex_unlock(&pridebugfdlock);
14449 }
14450 #endif   /* defined(HAVE_PRI) */
14451 
14452 #if defined(HAVE_PRI)
14453 static void dahdi_pri_error(struct pri *pri, char *s)
14454 {
14455    int x;
14456    int y;
14457    int dchan = -1;
14458    int span = -1;
14459    int dchancount = 0;
14460 
14461    if (pri) {
14462       for (x = 0; x < NUM_SPANS; x++) {
14463          for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
14464             if (pris[x].pri.dchans[y]) {
14465                dchancount++;
14466             }
14467 
14468             if (pris[x].pri.dchans[y] == pri) {
14469                dchan = y;
14470             }
14471          }
14472          if (dchan >= 0) {
14473             span = x;
14474             break;
14475          }
14476          dchancount = 0;
14477       }
14478       if (-1 < span) {
14479          if (1 < dchancount) {
14480             ast_log_callid(LOG_ERROR, NULL, "[PRI Span: %d D-Channel: %d] %s", span + 1, dchan, s);
14481          } else {
14482             ast_log_callid(LOG_ERROR, NULL, "PRI Span: %d %s", span + 1, s);
14483          }
14484       } else {
14485          ast_log_callid(LOG_ERROR, NULL, "PRI Span: ? %s", s);
14486       }
14487    } else {
14488       ast_log_callid(LOG_ERROR, NULL, "PRI Span: ? %s", s);
14489    }
14490 
14491    ast_mutex_lock(&pridebugfdlock);
14492 
14493    if (pridebugfd >= 0) {
14494       if (write(pridebugfd, s, strlen(s)) < 0) {
14495          ast_log_callid(LOG_WARNING, NULL, "write() failed: %s\n", strerror(errno));
14496       }
14497    }
14498 
14499    ast_mutex_unlock(&pridebugfdlock);
14500 }
14501 #endif   /* defined(HAVE_PRI) */
14502 
14503 #if defined(HAVE_PRI)
14504 static int prepare_pri(struct dahdi_pri *pri)
14505 {
14506    int i, res, x;
14507    struct dahdi_params p;
14508    struct dahdi_bufferinfo bi;
14509    struct dahdi_spaninfo si;
14510 
14511    for (i = 0; i < SIG_PRI_NUM_DCHANS; i++) {
14512       if (!pri->dchannels[i])
14513          break;
14514       pri->pri.fds[i] = open("/dev/dahdi/channel", O_RDWR);
14515       x = pri->dchannels[i];
14516       if ((pri->pri.fds[i] < 0) || (ioctl(pri->pri.fds[i],DAHDI_SPECIFY,&x) == -1)) {
14517          ast_log(LOG_ERROR, "Unable to open D-channel %d (%s)\n", x, strerror(errno));
14518          return -1;
14519       }
14520       memset(&p, 0, sizeof(p));
14521       res = ioctl(pri->pri.fds[i], DAHDI_GET_PARAMS, &p);
14522       if (res) {
14523          dahdi_close_pri_fd(pri, i);
14524          ast_log(LOG_ERROR, "Unable to get parameters for D-channel %d (%s)\n", x, strerror(errno));
14525          return -1;
14526       }
14527       if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC)) {
14528          dahdi_close_pri_fd(pri, i);
14529          ast_log(LOG_ERROR, "D-channel %d is not in HDLC/FCS mode.\n", x);
14530          return -1;
14531       }
14532       memset(&si, 0, sizeof(si));
14533       res = ioctl(pri->pri.fds[i], DAHDI_SPANSTAT, &si);
14534       if (res) {
14535          dahdi_close_pri_fd(pri, i);
14536          ast_log(LOG_ERROR, "Unable to get span state for D-channel %d (%s)\n", x, strerror(errno));
14537       }
14538       if (!si.alarms) {
14539          pri_event_noalarm(&pri->pri, i, 1);
14540       } else {
14541          pri_event_alarm(&pri->pri, i, 1);
14542       }
14543       memset(&bi, 0, sizeof(bi));
14544       bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
14545       bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
14546       bi.numbufs = 32;
14547       bi.bufsize = 1024;
14548       if (ioctl(pri->pri.fds[i], DAHDI_SET_BUFINFO, &bi)) {
14549          ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", x, strerror(errno));
14550          dahdi_close_pri_fd(pri, i);
14551          return -1;
14552       }
14553       pri->pri.dchan_logical_span[i] = pris[p.spanno - 1].prilogicalspan;
14554    }
14555    return 0;
14556 }
14557 #endif   /* defined(HAVE_PRI) */
14558 
14559 #if defined(HAVE_PRI)
14560 static char *complete_span_helper(const char *line, const char *word, int pos, int state, int rpos)
14561 {
14562    int which, span;
14563    char *ret = NULL;
14564 
14565    if (pos != rpos)
14566       return ret;
14567 
14568    for (which = span = 0; span < NUM_SPANS; span++) {
14569       if (pris[span].pri.pri && ++which > state) {
14570          if (ast_asprintf(&ret, "%d", span + 1) < 0) {   /* user indexes start from 1 */
14571             ret = NULL;
14572          }
14573          break;
14574       }
14575    }
14576    return ret;
14577 }
14578 #endif   /* defined(HAVE_PRI) */
14579 
14580 #if defined(HAVE_PRI)
14581 static char *complete_span_4(const char *line, const char *word, int pos, int state)
14582 {
14583    return complete_span_helper(line,word,pos,state,3);
14584 }
14585 #endif   /* defined(HAVE_PRI) */
14586 
14587 #if defined(HAVE_PRI)
14588 static char *handle_pri_set_debug_file(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14589 {
14590    int myfd;
14591    switch (cmd) {
14592    case CLI_INIT:
14593       e->command = "pri set debug file";
14594       e->usage = "Usage: pri set debug file [output-file]\n"
14595          "       Sends PRI debug output to the specified output file\n";
14596       return NULL;
14597    case CLI_GENERATE:
14598       return NULL;
14599    }
14600    if (a->argc < 5)
14601       return CLI_SHOWUSAGE;
14602 
14603    if (ast_strlen_zero(a->argv[4]))
14604       return CLI_SHOWUSAGE;
14605 
14606    myfd = open(a->argv[4], O_CREAT|O_WRONLY, AST_FILE_MODE);
14607    if (myfd < 0) {
14608       ast_cli(a->fd, "Unable to open '%s' for writing\n", a->argv[4]);
14609       return CLI_SUCCESS;
14610    }
14611 
14612    ast_mutex_lock(&pridebugfdlock);
14613 
14614    if (pridebugfd >= 0)
14615       close(pridebugfd);
14616 
14617    pridebugfd = myfd;
14618    ast_copy_string(pridebugfilename,a->argv[4],sizeof(pridebugfilename));
14619    ast_mutex_unlock(&pridebugfdlock);
14620    ast_cli(a->fd, "PRI debug output will be sent to '%s'\n", a->argv[4]);
14621    return CLI_SUCCESS;
14622 }
14623 #endif   /* defined(HAVE_PRI) */
14624 
14625 #if defined(HAVE_PRI)
14626 static char *handle_pri_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14627 {
14628    int span;
14629    int x;
14630    int debugmask = 0;
14631    int level = 0;
14632    switch (cmd) {
14633    case CLI_INIT:
14634       e->command = "pri set debug {on|off|hex|intense|0|1|2|3|4|5|6|7|8|9|10|11|12|13|14|15} span";
14635       e->usage =
14636          "Usage: pri set debug {<level>|on|off|hex|intense} span <span>\n"
14637          "       Enables debugging on a given PRI span\n"
14638          "  Level is a bitmap of the following values:\n"
14639          "  1 General debugging incl. state changes\n"
14640          "  2 Decoded Q.931 messages\n"
14641          "  4 Decoded Q.921 messages\n"
14642          "  8 Raw hex dumps of Q.921 frames\n"
14643          "       on - equivalent to 3\n"
14644          "       hex - equivalent to 8\n"
14645          "       intense - equivalent to 15\n";
14646       return NULL;
14647    case CLI_GENERATE:
14648       return complete_span_4(a->line, a->word, a->pos, a->n);
14649    }
14650    if (a->argc < 6) {
14651       return CLI_SHOWUSAGE;
14652    }
14653 
14654    if (!strcasecmp(a->argv[3], "on")) {
14655       level = 3;
14656    } else if (!strcasecmp(a->argv[3], "off")) {
14657       level = 0;
14658    } else if (!strcasecmp(a->argv[3], "intense")) {
14659       level = 15;
14660    } else if (!strcasecmp(a->argv[3], "hex")) {
14661       level = 8;
14662    } else {
14663       level = atoi(a->argv[3]);
14664    }
14665    span = atoi(a->argv[5]);
14666    if ((span < 1) || (span > NUM_SPANS)) {
14667       ast_cli(a->fd, "Invalid span %s.  Should be a number %d to %d\n", a->argv[5], 1, NUM_SPANS);
14668       return CLI_SUCCESS;
14669    }
14670    if (!pris[span-1].pri.pri) {
14671       ast_cli(a->fd, "No PRI running on span %d\n", span);
14672       return CLI_SUCCESS;
14673    }
14674 
14675    if (level & 1) debugmask |= SIG_PRI_DEBUG_NORMAL;
14676    if (level & 2) debugmask |= PRI_DEBUG_Q931_DUMP;
14677    if (level & 4) debugmask |= PRI_DEBUG_Q921_DUMP;
14678    if (level & 8) debugmask |= PRI_DEBUG_Q921_RAW;
14679 
14680    /* Set debug level in libpri */
14681    for (x = 0; x < SIG_PRI_NUM_DCHANS; x++) {
14682       if (pris[span - 1].pri.dchans[x]) {
14683          pri_set_debug(pris[span - 1].pri.dchans[x], debugmask);
14684       }
14685    }
14686    if (level == 0) {
14687       /* Close the debugging file if it's set */
14688       ast_mutex_lock(&pridebugfdlock);
14689       if (0 <= pridebugfd) {
14690          close(pridebugfd);
14691          pridebugfd = -1;
14692          ast_cli(a->fd, "Disabled PRI debug output to file '%s'\n",
14693             pridebugfilename);
14694       }
14695       ast_mutex_unlock(&pridebugfdlock);
14696    }
14697    pris[span - 1].pri.debug = (level) ? 1 : 0;
14698    ast_cli(a->fd, "%s debugging on span %d\n", (level) ? "Enabled" : "Disabled", span);
14699    return CLI_SUCCESS;
14700 }
14701 #endif   /* defined(HAVE_PRI) */
14702 
14703 #if defined(HAVE_PRI)
14704 #if defined(HAVE_PRI_SERVICE_MESSAGES)
14705 static char *handle_pri_service_generic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a, int changestatus)
14706 {
14707    unsigned *why;
14708    int channel;
14709    int trunkgroup;
14710    int x, y, fd = a->fd;
14711    int interfaceid = 0;
14712    char db_chan_name[20], db_answer[5];
14713    struct dahdi_pvt *tmp;
14714    struct dahdi_pri *pri;
14715 
14716    if (a->argc < 5 || a->argc > 6)
14717       return CLI_SHOWUSAGE;
14718    if (strchr(a->argv[4], ':')) {
14719       if (sscanf(a->argv[4], "%30d:%30d", &trunkgroup, &channel) != 2)
14720          return CLI_SHOWUSAGE;
14721       if ((trunkgroup < 1) || (channel < 1))
14722          return CLI_SHOWUSAGE;
14723       pri = NULL;
14724       for (x=0;x<NUM_SPANS;x++) {
14725          if (pris[x].pri.trunkgroup == trunkgroup) {
14726             pri = pris + x;
14727             break;
14728          }
14729       }
14730       if (!pri) {
14731          ast_cli(fd, "No such trunk group %d\n", trunkgroup);
14732          return CLI_FAILURE;
14733       }
14734    } else
14735       channel = atoi(a->argv[4]);
14736 
14737    if (a->argc == 6)
14738       interfaceid = atoi(a->argv[5]);
14739 
14740    /* either servicing a D-Channel */
14741    for (x = 0; x < NUM_SPANS; x++) {
14742       for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
14743          if (pris[x].dchannels[y] == channel) {
14744             pri = pris + x;
14745             if (pri->pri.enable_service_message_support) {
14746                ast_mutex_lock(&pri->pri.lock);
14747                pri_maintenance_service(pri->pri.pri, interfaceid, -1, changestatus);
14748                ast_mutex_unlock(&pri->pri.lock);
14749             } else {
14750                ast_cli(fd,
14751                   "\n\tThis operation has not been enabled in chan_dahdi.conf, set 'service_message_support=yes' to use this operation.\n"
14752                   "\tNote only 4ESS, 5ESS, and NI2 switch types are supported.\n\n");
14753             }
14754             return CLI_SUCCESS;
14755          }
14756       }
14757    }
14758 
14759    /* or servicing a B-Channel */
14760    ast_mutex_lock(&iflock);
14761    for (tmp = iflist; tmp; tmp = tmp->next) {
14762       if (tmp->pri && tmp->channel == channel) {
14763          ast_mutex_unlock(&iflock);
14764          ast_mutex_lock(&tmp->pri->lock);
14765          if (!tmp->pri->enable_service_message_support) {
14766             ast_mutex_unlock(&tmp->pri->lock);
14767             ast_cli(fd,
14768                "\n\tThis operation has not been enabled in chan_dahdi.conf, set 'service_message_support=yes' to use this operation.\n"
14769                "\tNote only 4ESS, 5ESS, and NI2 switch types are supported.\n\n");
14770             return CLI_SUCCESS;
14771          }
14772          snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, tmp->span, channel);
14773          why = &((struct sig_pri_chan *) tmp->sig_pvt)->service_status;
14774          switch(changestatus) {
14775          case 0: /* enable */
14776             /* Near end wants to be in service now. */
14777             ast_db_del(db_chan_name, SRVST_DBKEY);
14778             *why &= ~SRVST_NEAREND;
14779             if (*why) {
14780                snprintf(db_answer, sizeof(db_answer), "%s:%u", SRVST_TYPE_OOS, *why);
14781                ast_db_put(db_chan_name, SRVST_DBKEY, db_answer);
14782             } else {
14783                dahdi_pri_update_span_devstate(tmp->pri);
14784             }
14785             break;
14786          /* case 1:  -- loop */
14787          case 2: /* disable */
14788             /* Near end wants to be out-of-service now. */
14789             ast_db_del(db_chan_name, SRVST_DBKEY);
14790             *why |= SRVST_NEAREND;
14791             snprintf(db_answer, sizeof(db_answer), "%s:%u", SRVST_TYPE_OOS, *why);
14792             ast_db_put(db_chan_name, SRVST_DBKEY, db_answer);
14793             dahdi_pri_update_span_devstate(tmp->pri);
14794             break;
14795          /* case 3:  -- continuity */
14796          /* case 4:  -- shutdown */
14797          default:
14798             ast_log(LOG_WARNING, "Unsupported changestatus: '%d'\n", changestatus);
14799             break;
14800          }
14801          pri_maintenance_bservice(tmp->pri->pri, tmp->sig_pvt, changestatus);
14802          ast_mutex_unlock(&tmp->pri->lock);
14803          return CLI_SUCCESS;
14804       }
14805    }
14806    ast_mutex_unlock(&iflock);
14807 
14808    ast_cli(fd, "Unable to find given channel %d, possibly not a PRI\n", channel);
14809    return CLI_FAILURE;
14810 }
14811 
14812 static char *handle_pri_service_enable_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14813 {
14814    switch (cmd) {
14815    case CLI_INIT:
14816       e->command = "pri service enable channel";
14817       e->usage =
14818          "Usage: pri service enable channel <channel> [<interface id>]\n"
14819          "       Send an AT&T / NFAS / CCS ANSI T1.607 maintenance message\n"
14820          "  to restore a channel to service, with optional interface id\n"
14821          "  as agreed upon with remote switch operator\n";
14822       return NULL;
14823    case CLI_GENERATE:
14824       return NULL;
14825    }
14826    return handle_pri_service_generic(e, cmd, a, 0);
14827 }
14828 
14829 static char *handle_pri_service_disable_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14830 {
14831    switch (cmd) {
14832    case CLI_INIT:
14833       e->command = "pri service disable channel";
14834       e->usage =
14835          "Usage: pri service disable channel <chan num> [<interface id>]\n"
14836          "  Send an AT&T / NFAS / CCS ANSI T1.607 maintenance message\n"
14837          "  to remove a channel from service, with optional interface id\n"
14838          "  as agreed upon with remote switch operator\n";
14839       return NULL;
14840    case CLI_GENERATE:
14841       return NULL;
14842    }
14843    return handle_pri_service_generic(e, cmd, a, 2);
14844 }
14845 #endif   /* defined(HAVE_PRI_SERVICE_MESSAGES) */
14846 #endif   /* defined(HAVE_PRI) */
14847 
14848 #if defined(HAVE_PRI)
14849 static char *handle_pri_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14850 {
14851    int span;
14852 
14853    switch (cmd) {
14854    case CLI_INIT:
14855       e->command = "pri show channels";
14856       e->usage =
14857          "Usage: pri show channels\n"
14858          "       Displays PRI channel information such as the current mapping\n"
14859          "       of DAHDI B channels to Asterisk channel names and which calls\n"
14860          "       are on hold or call-waiting.  Calls on hold or call-waiting\n"
14861          "       are not associated with any B channel.\n";
14862       return NULL;
14863    case CLI_GENERATE:
14864       return NULL;
14865    }
14866 
14867    if (a->argc != 3)
14868       return CLI_SHOWUSAGE;
14869 
14870    sig_pri_cli_show_channels_header(a->fd);
14871    for (span = 0; span < NUM_SPANS; ++span) {
14872       if (pris[span].pri.pri) {
14873          sig_pri_cli_show_channels(a->fd, &pris[span].pri);
14874       }
14875    }
14876    return CLI_SUCCESS;
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 
14885    switch (cmd) {
14886    case CLI_INIT:
14887       e->command = "pri show spans";
14888       e->usage =
14889          "Usage: pri show spans\n"
14890          "       Displays PRI span information\n";
14891       return NULL;
14892    case CLI_GENERATE:
14893       return NULL;
14894    }
14895 
14896    if (a->argc != 3)
14897       return CLI_SHOWUSAGE;
14898 
14899    for (span = 0; span < NUM_SPANS; span++) {
14900       if (pris[span].pri.pri) {
14901          sig_pri_cli_show_spans(a->fd, span + 1, &pris[span].pri);
14902       }
14903    }
14904    return CLI_SUCCESS;
14905 }
14906 #endif   /* defined(HAVE_PRI) */
14907 
14908 #if defined(HAVE_PRI)
14909 #define container_of(ptr, type, member) \
14910    ((type *)((char *)(ptr) - offsetof(type, member)))
14911 /*!
14912  * \internal
14913  * \brief Destroy a D-Channel of a PRI span
14914  * \since 12
14915  *
14916  * \param pri the pri span
14917  *
14918  * \return TRUE if the span was valid and we attempted destroying.
14919  *
14920  * Shuts down a span and destroys its D-Channel. Further destruction
14921  * of the B-channels using dahdi_destroy_channel() would probably be required
14922  * for the B-Channels.
14923  */
14924 static int pri_destroy_dchan(struct sig_pri_span *pri)
14925 {
14926    int i;
14927    struct dahdi_pri* dahdi_pri;
14928 
14929    if (!pri->master || (pri->master == AST_PTHREADT_NULL)) {
14930       return 0;
14931    }
14932    pthread_cancel(pri->master);
14933    pthread_join(pri->master, NULL);
14934 
14935    /* The 'struct dahdi_pri' that contains our 'struct sig_pri_span' */
14936    dahdi_pri = container_of(pri, struct dahdi_pri, pri);
14937    for (i = 0; i < SIG_PRI_NUM_DCHANS; i++) {
14938       ast_debug(4, "closing pri_fd %d\n", i);
14939       dahdi_close_pri_fd(dahdi_pri, i);
14940    }
14941    pri->pri = NULL;
14942    ast_debug(1, "PRI span %d destroyed\n", pri->span);
14943    return 1;
14944 }
14945 
14946 static char *handle_pri_destroy_span(struct ast_cli_entry *e, int cmd,
14947       struct ast_cli_args *a)
14948 {
14949    int span;
14950    int i;
14951    int res;
14952 
14953    switch (cmd) {
14954    case CLI_INIT:
14955       e->command = "pri destroy span";
14956       e->usage =
14957          "Usage: pri destroy span <span>\n"
14958          "       Destorys D-channel of span and its B-channels.\n"
14959          "  DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n";
14960       return NULL;
14961    case CLI_GENERATE:
14962       return complete_span_4(a->line, a->word, a->pos, a->n);
14963    }
14964 
14965    if (a->argc < 4) {
14966       return CLI_SHOWUSAGE;
14967    }
14968    res = sscanf(a->argv[3], "%30d", &span);
14969    if ((res != 1) || span < 1 || span > NUM_SPANS) {
14970       ast_cli(a->fd,
14971          "Invalid span '%s'.  Should be a number from %d to %d\n",
14972          a->argv[3], 1, NUM_SPANS);
14973       return CLI_SUCCESS;
14974    }
14975    if (!pris[span - 1].pri.pri) {
14976       ast_cli(a->fd, "No PRI running on span %d\n", span);
14977       return CLI_SUCCESS;
14978    }
14979 
14980    for (i = 0; i < pris[span - 1].pri.numchans; i++) {
14981       int channel;
14982       struct sig_pri_chan *pvt = pris[span - 1].pri.pvts[i];
14983 
14984       if (!pvt) {
14985          continue;
14986       }
14987       channel = pvt->channel;
14988       ast_debug(2, "About to destroy B-channel %d.\n", channel);
14989       dahdi_destroy_channel_bynum(channel);
14990    }
14991    ast_debug(2, "About to destroy D-channel of span %d.\n", span);
14992    pri_destroy_dchan(&pris[span - 1].pri);
14993 
14994    return CLI_SUCCESS;
14995 }
14996 
14997 #endif   /* defined(HAVE_PRI) */
14998 
14999 #if defined(HAVE_PRI)
15000 static char *handle_pri_show_span(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15001 {
15002    int span;
15003 
15004    switch (cmd) {
15005    case CLI_INIT:
15006       e->command = "pri show span";
15007       e->usage =
15008          "Usage: pri show span <span>\n"
15009          "       Displays PRI Information on a given PRI span\n";
15010       return NULL;
15011    case CLI_GENERATE:
15012       return complete_span_4(a->line, a->word, a->pos, a->n);
15013    }
15014 
15015    if (a->argc < 4)
15016       return CLI_SHOWUSAGE;
15017    span = atoi(a->argv[3]);
15018    if ((span < 1) || (span > NUM_SPANS)) {
15019       ast_cli(a->fd, "Invalid span '%s'.  Should be a number from %d to %d\n", a->argv[3], 1, NUM_SPANS);
15020       return CLI_SUCCESS;
15021    }
15022    if (!pris[span-1].pri.pri) {
15023       ast_cli(a->fd, "No PRI running on span %d\n", span);
15024       return CLI_SUCCESS;
15025    }
15026 
15027    sig_pri_cli_show_span(a->fd, pris[span-1].dchannels, &pris[span-1].pri);
15028 
15029    return CLI_SUCCESS;
15030 }
15031 #endif   /* defined(HAVE_PRI) */
15032 
15033 #if defined(HAVE_PRI)
15034 static char *handle_pri_show_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15035 {
15036    int x;
15037    int span;
15038    int count=0;
15039    int debug;
15040 
15041    switch (cmd) {
15042    case CLI_INIT:
15043       e->command = "pri show debug";
15044       e->usage =
15045          "Usage: pri show debug\n"
15046          "  Show the debug state of pri spans\n";
15047       return NULL;
15048    case CLI_GENERATE:
15049       return NULL;
15050    }
15051 
15052    for (span = 0; span < NUM_SPANS; span++) {
15053       if (pris[span].pri.pri) {
15054          for (x = 0; x < SIG_PRI_NUM_DCHANS; x++) {
15055             if (pris[span].pri.dchans[x]) {
15056                debug = pri_get_debug(pris[span].pri.dchans[x]);
15057                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" );
15058                count++;
15059             }
15060          }
15061       }
15062 
15063    }
15064    ast_mutex_lock(&pridebugfdlock);
15065    if (pridebugfd >= 0)
15066       ast_cli(a->fd, "Logging PRI debug to file %s\n", pridebugfilename);
15067    ast_mutex_unlock(&pridebugfdlock);
15068 
15069    if (!count)
15070       ast_cli(a->fd, "No PRI running\n");
15071    return CLI_SUCCESS;
15072 }
15073 #endif   /* defined(HAVE_PRI) */
15074 
15075 #if defined(HAVE_PRI)
15076 static char *handle_pri_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15077 {
15078    switch (cmd) {
15079    case CLI_INIT:
15080       e->command = "pri show version";
15081       e->usage =
15082          "Usage: pri show version\n"
15083          "Show libpri version information\n";
15084       return NULL;
15085    case CLI_GENERATE:
15086       return NULL;
15087    }
15088 
15089    ast_cli(a->fd, "libpri version: %s\n", pri_get_version());
15090 
15091    return CLI_SUCCESS;
15092 }
15093 #endif   /* defined(HAVE_PRI) */
15094 
15095 #if defined(HAVE_PRI)
15096 static struct ast_cli_entry dahdi_pri_cli[] = {
15097    AST_CLI_DEFINE(handle_pri_debug, "Enables PRI debugging on a span"),
15098 #if defined(HAVE_PRI_SERVICE_MESSAGES)
15099    AST_CLI_DEFINE(handle_pri_service_enable_channel, "Return a channel to service"),
15100    AST_CLI_DEFINE(handle_pri_service_disable_channel, "Remove a channel from service"),
15101 #endif   /* defined(HAVE_PRI_SERVICE_MESSAGES) */
15102    AST_CLI_DEFINE(handle_pri_show_channels, "Displays PRI channel information"),
15103    AST_CLI_DEFINE(handle_pri_show_spans, "Displays PRI span information"),
15104    AST_CLI_DEFINE(handle_pri_show_span, "Displays PRI span information"),
15105    AST_CLI_DEFINE(handle_pri_destroy_span, "Destroy a PRI span"),
15106    AST_CLI_DEFINE(handle_pri_show_debug, "Displays current PRI debug settings"),
15107    AST_CLI_DEFINE(handle_pri_set_debug_file, "Sends PRI debug output to the specified file"),
15108    AST_CLI_DEFINE(handle_pri_version, "Displays libpri version"),
15109 };
15110 #endif   /* defined(HAVE_PRI) */
15111 
15112 #ifdef HAVE_OPENR2
15113 
15114 static char *handle_mfcr2_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15115 {
15116    switch (cmd) {
15117    case CLI_INIT:
15118       e->command = "mfcr2 show version";
15119       e->usage =
15120          "Usage: mfcr2 show version\n"
15121          "       Shows the version of the OpenR2 library being used.\n";
15122       return NULL;
15123    case CLI_GENERATE:
15124       return NULL;
15125    }
15126    ast_cli(a->fd, "OpenR2 version: %s, revision: %s\n", openr2_get_version(), openr2_get_revision());
15127    return CLI_SUCCESS;
15128 }
15129 
15130 static char *handle_mfcr2_show_variants(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15131 {
15132 #define FORMAT "%4s %40s\n"
15133    int i = 0;
15134    int numvariants = 0;
15135    const openr2_variant_entry_t *variants;
15136    switch (cmd) {
15137    case CLI_INIT:
15138       e->command = "mfcr2 show variants";
15139       e->usage =
15140          "Usage: mfcr2 show variants\n"
15141          "       Shows the list of MFC/R2 variants supported.\n";
15142       return NULL;
15143    case CLI_GENERATE:
15144       return NULL;
15145    }
15146    if (!(variants = openr2_proto_get_variant_list(&numvariants))) {
15147       ast_cli(a->fd, "Failed to get list of variants.\n");
15148       return CLI_FAILURE;
15149    }
15150    ast_cli(a->fd, FORMAT, "Variant Code", "Country");
15151    for (i = 0; i < numvariants; i++) {
15152       ast_cli(a->fd, FORMAT, variants[i].name, variants[i].country);
15153    }
15154    return CLI_SUCCESS;
15155 #undef FORMAT
15156 }
15157 
15158 static char *handle_mfcr2_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15159 {
15160 #define FORMAT "%4s %-7.7s %-7.7s %-8.8s %-9.9s %-16.16s %-8.8s %-8.8s\n"
15161    int filtertype = 0;
15162    int targetnum = 0;
15163    char channo[5];
15164    char anino[5];
15165    char dnisno[5];
15166    struct dahdi_pvt *p;
15167    openr2_context_t *r2context;
15168    openr2_variant_t r2variant;
15169    switch (cmd) {
15170    case CLI_INIT:
15171       e->command = "mfcr2 show channels [group|context]";
15172       e->usage =
15173          "Usage: mfcr2 show channels [group <group> | context <context>]\n"
15174          "       Shows the DAHDI channels configured with MFC/R2 signaling.\n";
15175       return NULL;
15176    case CLI_GENERATE:
15177       return NULL;
15178    }
15179    if (!((a->argc == 3) || (a->argc == 5))) {
15180       return CLI_SHOWUSAGE;
15181    }
15182    if (a->argc == 5) {
15183       if (!strcasecmp(a->argv[3], "group")) {
15184          targetnum = atoi(a->argv[4]);
15185          if ((targetnum < 0) || (targetnum > 63))
15186             return CLI_SHOWUSAGE;
15187          targetnum = 1 << targetnum;
15188          filtertype = 1;
15189       } else if (!strcasecmp(a->argv[3], "context")) {
15190          filtertype = 2;
15191       } else {
15192          return CLI_SHOWUSAGE;
15193       }
15194    }
15195    ast_cli(a->fd, FORMAT, "Chan", "Variant", "Max ANI", "Max DNIS", "ANI First", "Immediate Accept", "Tx CAS", "Rx CAS");
15196    ast_mutex_lock(&iflock);
15197    for (p = iflist; p; p = p->next) {
15198       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
15199          continue;
15200       }
15201       if (filtertype) {
15202          switch(filtertype) {
15203          case 1: /* mfcr2 show channels group <group> */
15204             if (p->group != targetnum) {
15205                continue;
15206             }
15207             break;
15208          case 2: /* mfcr2 show channels context <context> */
15209             if (strcasecmp(p->context, a->argv[4])) {
15210                continue;
15211             }
15212             break;
15213          default:
15214             ;
15215          }
15216       }
15217       r2context = openr2_chan_get_context(p->r2chan);
15218       r2variant = openr2_context_get_variant(r2context);
15219       snprintf(channo, sizeof(channo), "%d", p->channel);
15220       snprintf(anino, sizeof(anino), "%d", openr2_context_get_max_ani(r2context));
15221       snprintf(dnisno, sizeof(dnisno), "%d", openr2_context_get_max_dnis(r2context));
15222       ast_cli(a->fd, FORMAT, channo, openr2_proto_get_variant_string(r2variant),
15223             anino, dnisno, openr2_context_get_ani_first(r2context) ? "Yes" : "No",
15224             openr2_context_get_immediate_accept(r2context) ? "Yes" : "No",
15225             openr2_chan_get_tx_cas_string(p->r2chan), openr2_chan_get_rx_cas_string(p->r2chan));
15226    }
15227    ast_mutex_unlock(&iflock);
15228    return CLI_SUCCESS;
15229 #undef FORMAT
15230 }
15231 
15232 static char *handle_mfcr2_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15233 {
15234    struct dahdi_pvt *p = NULL;
15235    int channo = 0;
15236    char *toklevel = NULL;
15237    char *saveptr = NULL;
15238    char *logval = NULL;
15239    openr2_log_level_t loglevel = OR2_LOG_NOTHING;
15240    openr2_log_level_t tmplevel = OR2_LOG_NOTHING;
15241    switch (cmd) {
15242    case CLI_INIT:
15243       e->command = "mfcr2 set debug";
15244       e->usage =
15245          "Usage: mfcr2 set debug <loglevel> <channel>\n"
15246          "       Set a new logging level for the specified channel.\n"
15247          "       If no channel is specified the logging level will be applied to all channels.\n";
15248       return NULL;
15249    case CLI_GENERATE:
15250       return NULL;
15251    }
15252    if (a->argc < 4) {
15253       return CLI_SHOWUSAGE;
15254    }
15255    channo = (a->argc == 5) ? atoi(a->argv[4]) : -1;
15256    logval = ast_strdupa(a->argv[3]);
15257    toklevel = strtok_r(logval, ",", &saveptr);
15258    if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
15259       ast_cli(a->fd, "Invalid MFC/R2 logging level '%s'.\n", a->argv[3]);
15260       return CLI_FAILURE;
15261    } else if (OR2_LOG_NOTHING == tmplevel) {
15262       loglevel = tmplevel;
15263    } else {
15264       loglevel |= tmplevel;
15265       while ((toklevel = strtok_r(NULL, ",", &saveptr))) {
15266          if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
15267             ast_cli(a->fd, "Ignoring invalid logging level: '%s'.\n", toklevel);
15268             continue;
15269          }
15270          loglevel |= tmplevel;
15271       }
15272    }
15273    ast_mutex_lock(&iflock);
15274    for (p = iflist; p; p = p->next) {
15275       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
15276          continue;
15277       }
15278       if ((channo != -1) && (p->channel != channo )) {
15279          continue;
15280       }
15281       openr2_chan_set_log_level(p->r2chan, loglevel);
15282       if (channo != -1) {
15283          ast_cli(a->fd, "MFC/R2 debugging set to '%s' for channel %d.\n", a->argv[3], p->channel);
15284          break;
15285       }
15286    }
15287    if ((channo != -1) && !p) {
15288       ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
15289    }
15290    if (channo == -1) {
15291       ast_cli(a->fd, "MFC/R2 debugging set to '%s' for all channels.\n", a->argv[3]);
15292    }
15293    ast_mutex_unlock(&iflock);
15294    return CLI_SUCCESS;
15295 }
15296 
15297 static char *handle_mfcr2_call_files(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15298 {
15299    struct dahdi_pvt *p = NULL;
15300    int channo = 0;
15301    switch (cmd) {
15302    case CLI_INIT:
15303       e->command = "mfcr2 call files [on|off]";
15304       e->usage =
15305          "Usage: mfcr2 call files [on|off] <channel>\n"
15306          "       Enable call files creation on the specified channel.\n"
15307          "       If no channel is specified call files creation policy will be applied to all channels.\n";
15308       return NULL;
15309    case CLI_GENERATE:
15310       return NULL;
15311    }
15312    if (a->argc < 4) {
15313       return CLI_SHOWUSAGE;
15314    }
15315    channo = (a->argc == 5) ? atoi(a->argv[4]) : -1;
15316    ast_mutex_lock(&iflock);
15317    for (p = iflist; p; p = p->next) {
15318       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
15319          continue;
15320       }
15321       if ((channo != -1) && (p->channel != channo )) {
15322          continue;
15323       }
15324       if (ast_true(a->argv[3])) {
15325          openr2_chan_enable_call_files(p->r2chan);
15326       } else {
15327          openr2_chan_disable_call_files(p->r2chan);
15328       }
15329       if (channo != -1) {
15330          if (ast_true(a->argv[3])) {
15331             ast_cli(a->fd, "MFC/R2 call files enabled for channel %d.\n", p->channel);
15332          } else {
15333             ast_cli(a->fd, "MFC/R2 call files disabled for channel %d.\n", p->channel);
15334          }
15335          break;
15336       }
15337    }
15338    if ((channo != -1) && !p) {
15339       ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
15340    }
15341    if (channo == -1) {
15342       if (ast_true(a->argv[3])) {
15343          ast_cli(a->fd, "MFC/R2 Call files enabled for all channels.\n");
15344       } else {
15345          ast_cli(a->fd, "MFC/R2 Call files disabled for all channels.\n");
15346       }
15347    }
15348    ast_mutex_unlock(&iflock);
15349    return CLI_SUCCESS;
15350 }
15351 
15352 static char *handle_mfcr2_set_idle(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15353 {
15354    struct dahdi_pvt *p = NULL;
15355    int channo = 0;
15356    switch (cmd) {
15357    case CLI_INIT:
15358       e->command = "mfcr2 set idle";
15359       e->usage =
15360          "Usage: mfcr2 set idle <channel>\n"
15361          "       DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n"
15362          "       Force the given channel into IDLE state.\n"
15363          "       If no channel is specified, all channels will be set to IDLE.\n";
15364       return NULL;
15365    case CLI_GENERATE:
15366       return NULL;
15367    }
15368    channo = (a->argc == 4) ? atoi(a->argv[3]) : -1;
15369    ast_mutex_lock(&iflock);
15370    for (p = iflist; p; p = p->next) {
15371       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
15372          continue;
15373       }
15374       if ((channo != -1) && (p->channel != channo )) {
15375          continue;
15376       }
15377       openr2_chan_set_idle(p->r2chan);
15378       ast_mutex_lock(&p->lock);
15379       p->locallyblocked = 0;
15380       p->mfcr2call = 0;
15381       ast_mutex_unlock(&p->lock);
15382       if (channo != -1) {
15383          break;
15384       }
15385    }
15386    if ((channo != -1) && !p) {
15387       ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
15388    }
15389    ast_mutex_unlock(&iflock);
15390    return CLI_SUCCESS;
15391 }
15392 
15393 static char *handle_mfcr2_set_blocked(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15394 {
15395    struct dahdi_pvt *p = NULL;
15396    int channo = 0;
15397    switch (cmd) {
15398    case CLI_INIT:
15399       e->command = "mfcr2 set blocked";
15400       e->usage =
15401          "Usage: mfcr2 set blocked <channel>\n"
15402          "       DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n"
15403          "       Force the given channel into BLOCKED state.\n"
15404          "       If no channel is specified, all channels will be set to BLOCKED.\n";
15405       return NULL;
15406    case CLI_GENERATE:
15407       return NULL;
15408    }
15409    channo = (a->argc == 4) ? atoi(a->argv[3]) : -1;
15410    ast_mutex_lock(&iflock);
15411    for (p = iflist; p; p = p->next) {
15412       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
15413          continue;
15414       }
15415       if ((channo != -1) && (p->channel != channo )) {
15416          continue;
15417       }
15418       openr2_chan_set_blocked(p->r2chan);
15419       ast_mutex_lock(&p->lock);
15420       p->locallyblocked = 1;
15421       ast_mutex_unlock(&p->lock);
15422       if (channo != -1) {
15423          break;
15424       }
15425    }
15426    if ((channo != -1) && !p) {
15427       ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
15428    }
15429    ast_mutex_unlock(&iflock);
15430    return CLI_SUCCESS;
15431 }
15432 
15433 static struct ast_cli_entry dahdi_mfcr2_cli[] = {
15434    AST_CLI_DEFINE(handle_mfcr2_version, "Show OpenR2 library version"),
15435    AST_CLI_DEFINE(handle_mfcr2_show_variants, "Show supported MFC/R2 variants"),
15436    AST_CLI_DEFINE(handle_mfcr2_show_channels, "Show MFC/R2 channels"),
15437    AST_CLI_DEFINE(handle_mfcr2_set_debug, "Set MFC/R2 channel logging level"),
15438    AST_CLI_DEFINE(handle_mfcr2_call_files, "Enable/Disable MFC/R2 call files"),
15439    AST_CLI_DEFINE(handle_mfcr2_set_idle, "Reset MFC/R2 channel forcing it to IDLE"),
15440    AST_CLI_DEFINE(handle_mfcr2_set_blocked, "Reset MFC/R2 channel forcing it to BLOCKED"),
15441 };
15442 
15443 #endif /* HAVE_OPENR2 */
15444 
15445 static char *dahdi_destroy_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15446 {
15447    int channel;
15448    int ret;
15449    switch (cmd) {
15450    case CLI_INIT:
15451       e->command = "dahdi destroy channel";
15452       e->usage =
15453          "Usage: dahdi destroy channel <chan num>\n"
15454          "  DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.  Immediately removes a given channel, whether it is in use or not\n";
15455       return NULL;
15456    case CLI_GENERATE:
15457       return NULL;
15458    }
15459    if (a->argc != 4)
15460       return CLI_SHOWUSAGE;
15461 
15462    channel = atoi(a->argv[3]);
15463    ret = dahdi_destroy_channel_bynum(channel);
15464    return ( RESULT_SUCCESS == ret ) ? CLI_SUCCESS : CLI_FAILURE;
15465 }
15466 
15467 static void dahdi_softhangup_all(void)
15468 {
15469    struct dahdi_pvt *p;
15470 retry:
15471    ast_mutex_lock(&iflock);
15472    for (p = iflist; p; p = p->next) {
15473       ast_mutex_lock(&p->lock);
15474       if (p->owner && !p->restartpending) {
15475          if (ast_channel_trylock(p->owner)) {
15476             if (option_debug > 2)
15477                ast_verbose("Avoiding deadlock\n");
15478             /* Avoid deadlock since you're not supposed to lock iflock or pvt before a channel */
15479             ast_mutex_unlock(&p->lock);
15480             ast_mutex_unlock(&iflock);
15481             goto retry;
15482          }
15483          if (option_debug > 2)
15484             ast_verbose("Softhanging up on %s\n", ast_channel_name(p->owner));
15485          ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_EXPLICIT);
15486          p->restartpending = 1;
15487          num_restart_pending++;
15488          ast_channel_unlock(p->owner);
15489       }
15490       ast_mutex_unlock(&p->lock);
15491    }
15492    ast_mutex_unlock(&iflock);
15493 }
15494 
15495 static int setup_dahdi(int reload);
15496 static int dahdi_restart(void)
15497 {
15498 #if defined(HAVE_PRI) || defined(HAVE_SS7)
15499    int i, j;
15500 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
15501    int cancel_code;
15502    struct dahdi_pvt *p;
15503 
15504    ast_mutex_lock(&restart_lock);
15505    ast_verb(1, "Destroying channels and reloading DAHDI configuration.\n");
15506    dahdi_softhangup_all();
15507    ast_verb(4, "Initial softhangup of all DAHDI channels complete.\n");
15508 #ifdef HAVE_OPENR2
15509    dahdi_r2_destroy_links();
15510 #endif
15511 
15512 #if defined(HAVE_PRI)
15513    for (i = 0; i < NUM_SPANS; i++) {
15514       if (pris[i].pri.master && (pris[i].pri.master != AST_PTHREADT_NULL)) {
15515          cancel_code = pthread_cancel(pris[i].pri.master);
15516          pthread_kill(pris[i].pri.master, SIGURG);
15517          ast_debug(4, "Waiting to join thread of span %d with pid=%p, cancel_code=%d\n", i, (void *) pris[i].pri.master, cancel_code);
15518          pthread_join(pris[i].pri.master, NULL);
15519          ast_debug(4, "Joined thread of span %d\n", i);
15520       }
15521    }
15522 #endif
15523 
15524 #if defined(HAVE_SS7)
15525    for (i = 0; i < NUM_SPANS; i++) {
15526       if (linksets[i].ss7.master && (linksets[i].ss7.master != AST_PTHREADT_NULL)) {
15527          cancel_code = pthread_cancel(linksets[i].ss7.master);
15528          pthread_kill(linksets[i].ss7.master, SIGURG);
15529          ast_debug(4, "Waiting to join thread of span %d with pid=%p, cancel_code=%d\n", i, (void *) linksets[i].ss7.master, cancel_code);
15530          pthread_join(linksets[i].ss7.master, NULL);
15531          ast_debug(4, "Joined thread of span %d\n", i);
15532       }
15533    }
15534 #endif   /* defined(HAVE_SS7) */
15535 
15536    ast_mutex_lock(&monlock);
15537    if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
15538       cancel_code = pthread_cancel(monitor_thread);
15539       pthread_kill(monitor_thread, SIGURG);
15540       ast_debug(4, "Waiting to join monitor thread with pid=%p, cancel_code=%d\n", (void *) monitor_thread, cancel_code);
15541       pthread_join(monitor_thread, NULL);
15542       ast_debug(4, "Joined monitor thread\n");
15543    }
15544    monitor_thread = AST_PTHREADT_NULL; /* prepare to restart thread in setup_dahdi once channels are reconfigured */
15545 
15546    ast_mutex_lock(&ss_thread_lock);
15547    while (ss_thread_count > 0) { /* let ss_threads finish and run dahdi_hangup before dahvi_pvts are destroyed */
15548       int x = DAHDI_FLASH;
15549       ast_debug(3, "Waiting on %d analog_ss_thread(s) to finish\n", ss_thread_count);
15550 
15551       ast_mutex_lock(&iflock);
15552       for (p = iflist; p; p = p->next) {
15553          if (p->owner) {
15554             /* important to create an event for dahdi_wait_event to register so that all analog_ss_threads terminate */
15555             ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
15556          }
15557       }
15558       ast_mutex_unlock(&iflock);
15559       ast_cond_wait(&ss_thread_complete, &ss_thread_lock);
15560    }
15561 
15562    /* ensure any created channels before monitor threads were stopped are hungup */
15563    dahdi_softhangup_all();
15564    ast_verb(4, "Final softhangup of all DAHDI channels complete.\n");
15565    destroy_all_channels();
15566    memset(round_robin, 0, sizeof(round_robin));
15567    ast_debug(1, "Channels destroyed. Now re-reading config. %d active channels remaining.\n", ast_active_channels());
15568 
15569    ast_mutex_unlock(&monlock);
15570 
15571 #ifdef HAVE_PRI
15572    for (i = 0; i < NUM_SPANS; i++) {
15573       for (j = 0; j < SIG_PRI_NUM_DCHANS; j++)
15574          dahdi_close_pri_fd(&(pris[i]), j);
15575    }
15576 
15577    memset(pris, 0, sizeof(pris));
15578    for (i = 0; i < NUM_SPANS; i++) {
15579       sig_pri_init_pri(&pris[i].pri);
15580    }
15581    pri_set_error(dahdi_pri_error);
15582    pri_set_message(dahdi_pri_message);
15583 #endif
15584 #if defined(HAVE_SS7)
15585    for (i = 0; i < NUM_SPANS; i++) {
15586       for (j = 0; j < SIG_SS7_NUM_DCHANS; j++)
15587          dahdi_close_ss7_fd(&(linksets[i]), j);
15588    }
15589 
15590    memset(linksets, 0, sizeof(linksets));
15591    for (i = 0; i < NUM_SPANS; i++) {
15592       sig_ss7_init_linkset(&linksets[i].ss7);
15593    }
15594    ss7_set_error(dahdi_ss7_error);
15595    ss7_set_message(dahdi_ss7_message);
15596 #endif   /* defined(HAVE_SS7) */
15597 
15598    if (setup_dahdi(2) != 0) {
15599       ast_log(LOG_WARNING, "Reload channels from dahdi config failed!\n");
15600       ast_mutex_unlock(&ss_thread_lock);
15601       return 1;
15602    }
15603    ast_mutex_unlock(&ss_thread_lock);
15604    ast_mutex_unlock(&restart_lock);
15605    return 0;
15606 }
15607 
15608 static char *dahdi_restart_cmd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15609 {
15610    switch (cmd) {
15611    case CLI_INIT:
15612       e->command = "dahdi restart";
15613       e->usage =
15614          "Usage: dahdi restart\n"
15615          "  Restarts the DAHDI channels: destroys them all and then\n"
15616          "  re-reads them from chan_dahdi.conf.\n"
15617          "  Note that this will STOP any running CALL on DAHDI channels.\n"
15618          "";
15619       return NULL;
15620    case CLI_GENERATE:
15621       return NULL;
15622    }
15623    if (a->argc != 2)
15624       return CLI_SHOWUSAGE;
15625 
15626    if (dahdi_restart() != 0)
15627       return CLI_FAILURE;
15628    return CLI_SUCCESS;
15629 }
15630 
15631 static int action_dahdirestart(struct mansession *s, const struct message *m)
15632 {
15633    if (dahdi_restart() != 0) {
15634       astman_send_error(s, m, "Failed rereading DAHDI configuration");
15635       return 1;
15636    }
15637    astman_send_ack(s, m, "DAHDIRestart: Success");
15638    return 0;
15639 }
15640 
15641 static char *dahdi_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15642 {
15643 #define FORMAT "%7s %-15.15s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s %-32.32s\n"
15644 #define FORMAT2 "%7s %-15.15s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s %-32.32s\n"
15645    ast_group_t targetnum = 0;
15646    int filtertype = 0;
15647    struct dahdi_pvt *tmp = NULL;
15648    char tmps[20] = "";
15649    char statestr[20] = "";
15650    char blockstr[20] = "";
15651 
15652    switch (cmd) {
15653    case CLI_INIT:
15654       e->command = "dahdi show channels [group|context]";
15655       e->usage =
15656          "Usage: dahdi show channels [ group <group> | context <context> ]\n"
15657          "  Shows a list of available channels with optional filtering\n"
15658          "  <group> must be a number between 0 and 63\n";
15659       return NULL;
15660    case CLI_GENERATE:
15661       return NULL;
15662    }
15663 
15664    /* syntax: dahdi show channels [ group <group> | context <context> ] */
15665 
15666    if (!((a->argc == 3) || (a->argc == 5)))
15667       return CLI_SHOWUSAGE;
15668 
15669    if (a->argc == 5) {
15670       if (!strcasecmp(a->argv[3], "group")) {
15671          targetnum = atoi(a->argv[4]);
15672          if (63 < targetnum) {
15673             return CLI_SHOWUSAGE;
15674          }
15675          targetnum = ((ast_group_t) 1) << targetnum;
15676          filtertype = 1;
15677       } else if (!strcasecmp(a->argv[3], "context")) {
15678          filtertype = 2;
15679       }
15680    }
15681 
15682    ast_cli(a->fd, FORMAT2, "Chan", "Extension", "Context", "Language", "MOH Interpret", "Blocked", "State", "Description");
15683    ast_mutex_lock(&iflock);
15684    for (tmp = iflist; tmp; tmp = tmp->next) {
15685       if (filtertype) {
15686          switch(filtertype) {
15687          case 1: /* dahdi show channels group <group> */
15688             if (!(tmp->group & targetnum)) {
15689                continue;
15690             }
15691             break;
15692          case 2: /* dahdi show channels context <context> */
15693             if (strcasecmp(tmp->context, a->argv[4])) {
15694                continue;
15695             }
15696             break;
15697          default:
15698             break;
15699          }
15700       }
15701       if (tmp->channel > 0) {
15702          snprintf(tmps, sizeof(tmps), "%d", tmp->channel);
15703       } else
15704          ast_copy_string(tmps, "pseudo", sizeof(tmps));
15705 
15706       if (tmp->locallyblocked)
15707          blockstr[0] = 'L';
15708       else
15709          blockstr[0] = ' ';
15710 
15711       if (tmp->remotelyblocked)
15712          blockstr[1] = 'R';
15713       else
15714          blockstr[1] = ' ';
15715 
15716       blockstr[2] = '\0';
15717 
15718       snprintf(statestr, sizeof(statestr), "%s", "In Service");
15719 
15720       ast_cli(a->fd, FORMAT, tmps, tmp->exten, tmp->context, tmp->language, tmp->mohinterpret, blockstr, statestr, tmp->description);
15721    }
15722    ast_mutex_unlock(&iflock);
15723    return CLI_SUCCESS;
15724 #undef FORMAT
15725 #undef FORMAT2
15726 }
15727 
15728 static char *dahdi_show_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15729 {
15730    int channel;
15731    struct dahdi_pvt *tmp = NULL;
15732    struct dahdi_confinfo ci;
15733    struct dahdi_params ps;
15734    int x;
15735 
15736    switch (cmd) {
15737    case CLI_INIT:
15738       e->command = "dahdi show channel";
15739       e->usage =
15740          "Usage: dahdi show channel <chan num>\n"
15741          "  Detailed information about a given channel\n";
15742       return NULL;
15743    case CLI_GENERATE:
15744       return NULL;
15745    }
15746 
15747    if (a->argc != 4)
15748       return CLI_SHOWUSAGE;
15749 
15750    channel = atoi(a->argv[3]);
15751 
15752    ast_mutex_lock(&iflock);
15753    for (tmp = iflist; tmp; tmp = tmp->next) {
15754       if (tmp->channel == channel) {
15755          ast_cli(a->fd, "Channel: %d\n", tmp->channel);
15756          ast_cli(a->fd, "Description: %s\n", tmp->description);
15757          ast_cli(a->fd, "File Descriptor: %d\n", tmp->subs[SUB_REAL].dfd);
15758          ast_cli(a->fd, "Span: %d\n", tmp->span);
15759          ast_cli(a->fd, "Extension: %s\n", tmp->exten);
15760          ast_cli(a->fd, "Dialing: %s\n", tmp->dialing ? "yes" : "no");
15761          ast_cli(a->fd, "Context: %s\n", tmp->context);
15762          ast_cli(a->fd, "Caller ID: %s\n", tmp->cid_num);
15763          ast_cli(a->fd, "Calling TON: %d\n", tmp->cid_ton);
15764 #if defined(HAVE_PRI)
15765 #if defined(HAVE_PRI_SUBADDR)
15766          ast_cli(a->fd, "Caller ID subaddress: %s\n", tmp->cid_subaddr);
15767 #endif   /* defined(HAVE_PRI_SUBADDR) */
15768 #endif   /* defined(HAVE_PRI) */
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 ? ast_channel_name(tmp->owner) : "<None>");
15782          ast_cli(a->fd, "Real: %s%s%s\n", tmp->subs[SUB_REAL].owner ? ast_channel_name(tmp->subs[SUB_REAL].owner) : "<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 ? ast_channel_name(tmp->subs[SUB_CALLWAIT].owner) : "<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 ? ast_channel_name(tmp->subs[SUB_THREEWAY].owner) : "<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,%d,%d\n", tmp->busy_cadence.pattern[0], tmp->busy_cadence.pattern[1], (tmp->busy_cadence.length == 4) ? tmp->busy_cadence.pattern[2] : 0, (tmp->busy_cadence.length == 4) ? tmp->busy_cadence.pattern[3] : 0);
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_default == DAHDI_LAW_MULAW ? "ulaw" : tmp->law_default == 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, "Gains (RX/TX): %.2f/%.2f\n", tmp->rxgain, tmp->txgain);
15809          ast_cli(a->fd, "Dynamic Range Compression (RX/TX): %.2f/%.2f\n", tmp->rxdrc, tmp->txdrc);
15810          ast_cli(a->fd, "DND: %s\n", dahdi_dnd(tmp, -1) ? "yes" : "no");
15811          ast_cli(a->fd, "Echo Cancellation:\n");
15812 
15813          if (tmp->echocancel.head.tap_length) {
15814             ast_cli(a->fd, "\t%u taps\n", tmp->echocancel.head.tap_length);
15815             for (x = 0; x < tmp->echocancel.head.param_count; x++) {
15816                ast_cli(a->fd, "\t\t%s: %dd\n", tmp->echocancel.params[x].name, tmp->echocancel.params[x].value);
15817             }
15818             ast_cli(a->fd, "\t%scurrently %s\n", tmp->echocanbridged ? "" : "(unless TDM bridged) ", tmp->echocanon ? "ON" : "OFF");
15819          } else {
15820             ast_cli(a->fd, "\tnone\n");
15821          }
15822          ast_cli(a->fd, "Wait for dialtone: %dms\n", tmp->waitfordialtone);
15823          if (tmp->master)
15824             ast_cli(a->fd, "Master Channel: %d\n", tmp->master->channel);
15825          for (x = 0; x < MAX_SLAVES; x++) {
15826             if (tmp->slaves[x])
15827                ast_cli(a->fd, "Slave Channel: %d\n", tmp->slaves[x]->channel);
15828          }
15829 #ifdef HAVE_OPENR2
15830          if (tmp->mfcr2) {
15831             char calldir[OR2_MAX_PATH];
15832             openr2_context_t *r2context = openr2_chan_get_context(tmp->r2chan);
15833             openr2_variant_t r2variant = openr2_context_get_variant(r2context);
15834             ast_cli(a->fd, "MFC/R2 MF State: %s\n", openr2_chan_get_mf_state_string(tmp->r2chan));
15835             ast_cli(a->fd, "MFC/R2 MF Group: %s\n", openr2_chan_get_mf_group_string(tmp->r2chan));
15836             ast_cli(a->fd, "MFC/R2 State: %s\n", openr2_chan_get_r2_state_string(tmp->r2chan));
15837             ast_cli(a->fd, "MFC/R2 Call State: %s\n", openr2_chan_get_call_state_string(tmp->r2chan));
15838             ast_cli(a->fd, "MFC/R2 Call Files Enabled: %s\n", openr2_chan_get_call_files_enabled(tmp->r2chan) ? "Yes" : "No");
15839             ast_cli(a->fd, "MFC/R2 Variant: %s\n", openr2_proto_get_variant_string(r2variant));
15840             ast_cli(a->fd, "MFC/R2 Max ANI: %d\n", openr2_context_get_max_ani(r2context));
15841             ast_cli(a->fd, "MFC/R2 Max DNIS: %d\n", openr2_context_get_max_dnis(r2context));
15842 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2
15843             ast_cli(a->fd, "MFC/R2 DTMF Dialing: %s\n", openr2_context_get_dtmf_dialing(r2context, NULL, NULL) ? "Yes" : "No");
15844             ast_cli(a->fd, "MFC/R2 DTMF Detection: %s\n", openr2_context_get_dtmf_detection(r2context) ? "Yes" : "No");
15845 #endif
15846             ast_cli(a->fd, "MFC/R2 Get ANI First: %s\n", openr2_context_get_ani_first(r2context) ? "Yes" : "No");
15847 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
15848             ast_cli(a->fd, "MFC/R2 Skip Category Request: %s\n", openr2_context_get_skip_category_request(r2context) ? "Yes" : "No");
15849 #endif
15850             ast_cli(a->fd, "MFC/R2 Immediate Accept: %s\n", openr2_context_get_immediate_accept(r2context) ? "Yes" : "No");
15851             ast_cli(a->fd, "MFC/R2 Accept on Offer: %s\n", tmp->mfcr2_accept_on_offer ? "Yes" : "No");
15852             ast_cli(a->fd, "MFC/R2 Charge Calls: %s\n", tmp->mfcr2_charge_calls ? "Yes" : "No");
15853             ast_cli(a->fd, "MFC/R2 Allow Collect Calls: %s\n", tmp->mfcr2_allow_collect_calls ? "Yes" : "No");
15854             ast_cli(a->fd, "MFC/R2 Forced Release: %s\n", tmp->mfcr2_forced_release ? "Yes" : "No");
15855             ast_cli(a->fd, "MFC/R2 MF Back Timeout: %dms\n", openr2_context_get_mf_back_timeout(r2context));
15856             ast_cli(a->fd, "MFC/R2 R2 Metering Pulse Timeout: %dms\n", openr2_context_get_metering_pulse_timeout(r2context));
15857             ast_cli(a->fd, "MFC/R2 Rx CAS: %s\n", openr2_chan_get_rx_cas_string(tmp->r2chan));
15858             ast_cli(a->fd, "MFC/R2 Tx CAS: %s\n", openr2_chan_get_tx_cas_string(tmp->r2chan));
15859             ast_cli(a->fd, "MFC/R2 MF Tx Signal: %d\n", openr2_chan_get_tx_mf_signal(tmp->r2chan));
15860             ast_cli(a->fd, "MFC/R2 MF Rx Signal: %d\n", openr2_chan_get_rx_mf_signal(tmp->r2chan));
15861             ast_cli(a->fd, "MFC/R2 Call Files Directory: %s\n", openr2_context_get_log_directory(r2context, calldir, sizeof(calldir)));
15862          }
15863 #endif
15864 #if defined(HAVE_SS7)
15865          if (tmp->ss7) {
15866             struct sig_ss7_chan *chan = tmp->sig_pvt;
15867 
15868             ast_cli(a->fd, "CIC: %d\n", chan->cic);
15869          }
15870 #endif   /* defined(HAVE_SS7) */
15871 #ifdef HAVE_PRI
15872          if (tmp->pri) {
15873             struct sig_pri_chan *chan = tmp->sig_pvt;
15874 
15875             ast_cli(a->fd, "PRI Flags: ");
15876             if (chan->resetting != SIG_PRI_RESET_IDLE) {
15877                ast_cli(a->fd, "Resetting=%u ", chan->resetting);
15878             }
15879             if (chan->call)
15880                ast_cli(a->fd, "Call ");
15881             if (chan->allocated) {
15882                ast_cli(a->fd, "Allocated ");
15883             }
15884             ast_cli(a->fd, "\n");
15885             if (tmp->logicalspan)
15886                ast_cli(a->fd, "PRI Logical Span: %d\n", tmp->logicalspan);
15887             else
15888                ast_cli(a->fd, "PRI Logical Span: Implicit\n");
15889          }
15890 #endif
15891          memset(&ci, 0, sizeof(ci));
15892          ps.channo = tmp->channel;
15893          if (tmp->subs[SUB_REAL].dfd > -1) {
15894             memset(&ci, 0, sizeof(ci));
15895             if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
15896                ast_cli(a->fd, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci.confno, (unsigned)ci.confmode);
15897             }
15898             if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONFMUTE, &x)) {
15899                ast_cli(a->fd, "Actual Confmute: %s\n", x ? "Yes" : "No");
15900             }
15901             memset(&ps, 0, sizeof(ps));
15902             if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
15903                ast_log(LOG_WARNING, "Failed to get parameters on channel %d: %s\n", tmp->channel, strerror(errno));
15904             } else {
15905                ast_cli(a->fd, "Hookstate (FXS only): %s\n", ps.rxisoffhook ? "Offhook" : "Onhook");
15906             }
15907          }
15908          ast_mutex_unlock(&iflock);
15909          return CLI_SUCCESS;
15910       }
15911    }
15912    ast_mutex_unlock(&iflock);
15913 
15914    ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15915    return CLI_FAILURE;
15916 }
15917 
15918 static char *handle_dahdi_show_cadences(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15919 {
15920    int i, j;
15921    switch (cmd) {
15922    case CLI_INIT:
15923       e->command = "dahdi show cadences";
15924       e->usage =
15925          "Usage: dahdi show cadences\n"
15926          "       Shows all cadences currently defined\n";
15927       return NULL;
15928    case CLI_GENERATE:
15929       return NULL;
15930    }
15931    for (i = 0; i < num_cadence; i++) {
15932       char output[1024];
15933       char tmp[16], tmp2[64];
15934       snprintf(tmp, sizeof(tmp), "r%d: ", i + 1);
15935       term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output));
15936 
15937       for (j = 0; j < 16; j++) {
15938          if (cadences[i].ringcadence[j] == 0)
15939             break;
15940          snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]);
15941          if (cidrings[i] * 2 - 1 == j)
15942             term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1);
15943          else
15944             term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1);
15945          if (j != 0)
15946             strncat(output, ",", sizeof(output) - strlen(output) - 1);
15947          strncat(output, tmp2, sizeof(output) - strlen(output) - 1);
15948       }
15949       ast_cli(a->fd,"%s\n",output);
15950    }
15951    return CLI_SUCCESS;
15952 }
15953 
15954 /* Based on irqmiss.c */
15955 static char *dahdi_show_status(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15956 {
15957    #define FORMAT "%-40.40s %-7.7s %-6d %-6d %-6d %-3.3s %-4.4s %-8.8s %s\n"
15958    #define FORMAT2 "%-40.40s %-7.7s %-6.6s %-6.6s %-6.6s %-3.3s %-4.4s %-8.8s %s\n"
15959    int span;
15960    int res;
15961    char alarmstr[50];
15962 
15963    int ctl;
15964    struct dahdi_spaninfo s;
15965 
15966    switch (cmd) {
15967    case CLI_INIT:
15968       e->command = "dahdi show status";
15969       e->usage =
15970          "Usage: dahdi show status\n"
15971          "       Shows a list of DAHDI cards with status\n";
15972       return NULL;
15973    case CLI_GENERATE:
15974       return NULL;
15975    }
15976    ctl = open("/dev/dahdi/ctl", O_RDWR);
15977    if (ctl < 0) {
15978       ast_cli(a->fd, "No DAHDI found. Unable to open /dev/dahdi/ctl: %s\n", strerror(errno));
15979       return CLI_FAILURE;
15980    }
15981    ast_cli(a->fd, FORMAT2, "Description", "Alarms", "IRQ", "bpviol", "CRC", "Framing", "Coding", "Options", "LBO");
15982 
15983    for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
15984       s.spanno = span;
15985       res = ioctl(ctl, DAHDI_SPANSTAT, &s);
15986       if (res) {
15987          continue;
15988       }
15989       alarmstr[0] = '\0';
15990       if (s.alarms > 0) {
15991          if (s.alarms & DAHDI_ALARM_BLUE)
15992             strcat(alarmstr, "BLU/");
15993          if (s.alarms & DAHDI_ALARM_YELLOW)
15994             strcat(alarmstr, "YEL/");
15995          if (s.alarms & DAHDI_ALARM_RED)
15996             strcat(alarmstr, "RED/");
15997          if (s.alarms & DAHDI_ALARM_LOOPBACK)
15998             strcat(alarmstr, "LB/");
15999          if (s.alarms & DAHDI_ALARM_RECOVER)
16000             strcat(alarmstr, "REC/");
16001          if (s.alarms & DAHDI_ALARM_NOTOPEN)
16002             strcat(alarmstr, "NOP/");
16003          if (!strlen(alarmstr))
16004             strcat(alarmstr, "UUU/");
16005          if (strlen(alarmstr)) {
16006             /* Strip trailing / */
16007             alarmstr[strlen(alarmstr) - 1] = '\0';
16008          }
16009       } else {
16010          if (s.numchans)
16011             strcpy(alarmstr, "OK");
16012          else
16013             strcpy(alarmstr, "UNCONFIGURED");
16014       }
16015 
16016       ast_cli(a->fd, FORMAT, s.desc, alarmstr, s.irqmisses, s.bpvcount, s.crc4count,
16017          s.lineconfig & DAHDI_CONFIG_D4 ? "D4" :
16018          s.lineconfig & DAHDI_CONFIG_ESF ? "ESF" :
16019          s.lineconfig & DAHDI_CONFIG_CCS ? "CCS" :
16020          "CAS",
16021          s.lineconfig & DAHDI_CONFIG_B8ZS ? "B8ZS" :
16022          s.lineconfig & DAHDI_CONFIG_HDB3 ? "HDB3" :
16023          s.lineconfig & DAHDI_CONFIG_AMI ? "AMI" :
16024          "Unk",
16025          s.lineconfig & DAHDI_CONFIG_CRC4 ?
16026             s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" :
16027             s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "YEL" : "",
16028          lbostr[s.lbo]
16029          );
16030    }
16031    close(ctl);
16032 
16033    return CLI_SUCCESS;
16034 #undef FORMAT
16035 #undef FORMAT2
16036 }
16037 
16038 static char *dahdi_show_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16039 {
16040    int pseudo_fd = -1;
16041    struct dahdi_versioninfo vi;
16042 
16043    switch (cmd) {
16044    case CLI_INIT:
16045       e->command = "dahdi show version";
16046       e->usage =
16047          "Usage: dahdi show version\n"
16048          "       Shows the DAHDI version in use\n";
16049       return NULL;
16050    case CLI_GENERATE:
16051       return NULL;
16052    }
16053    if ((pseudo_fd = open("/dev/dahdi/ctl", O_RDONLY)) < 0) {
16054       ast_cli(a->fd, "Failed to open control file to get version.\n");
16055       return CLI_SUCCESS;
16056    }
16057 
16058    strcpy(vi.version, "Unknown");
16059    strcpy(vi.echo_canceller, "Unknown");
16060 
16061    if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi))
16062       ast_cli(a->fd, "Failed to get DAHDI version: %s\n", strerror(errno));
16063    else
16064       ast_cli(a->fd, "DAHDI Version: %s Echo Canceller: %s\n", vi.version, vi.echo_canceller);
16065 
16066    close(pseudo_fd);
16067 
16068    return CLI_SUCCESS;
16069 }
16070 
16071 static char *dahdi_set_hwgain(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16072 {
16073    int channel;
16074    int gain;
16075    int tx;
16076    struct dahdi_hwgain hwgain;
16077    struct dahdi_pvt *tmp = NULL;
16078 
16079    switch (cmd) {
16080    case CLI_INIT:
16081       e->command = "dahdi set hwgain {rx|tx}";
16082       e->usage =
16083          "Usage: dahdi set hwgain <rx|tx> <chan#> <gain>\n"
16084          "   Sets the hardware gain on a given channel.  Changes take effect\n"
16085          "   immediately whether the channel is in use or not.\n"
16086          "\n"
16087          "   <rx|tx> which direction do you want to change (relative to our module)\n"
16088          "   <chan num> is the channel number relative to the device\n"
16089          "   <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n"
16090          "\n"
16091          "   Please note:\n"
16092          "   * This is currently the only way to set hwgain by the channel driver.\n"
16093          "   * hwgain is only supportable by hardware with analog ports because\n"
16094          "     hwgain works on the analog side of an analog-digital conversion.\n";
16095       return NULL;
16096    case CLI_GENERATE:
16097       return NULL;
16098    }
16099 
16100    if (a->argc != 6)
16101       return CLI_SHOWUSAGE;
16102 
16103    if (!strcasecmp("rx", a->argv[3]))
16104       tx = 0; /* rx */
16105    else if (!strcasecmp("tx", a->argv[3]))
16106       tx = 1; /* tx */
16107    else
16108       return CLI_SHOWUSAGE;
16109 
16110    channel = atoi(a->argv[4]);
16111    gain = atof(a->argv[5])*10.0;
16112 
16113    ast_mutex_lock(&iflock);
16114 
16115    for (tmp = iflist; tmp; tmp = tmp->next) {
16116 
16117       if (tmp->channel != channel)
16118          continue;
16119 
16120       if (tmp->subs[SUB_REAL].dfd == -1)
16121          break;
16122 
16123       hwgain.newgain = gain;
16124       hwgain.tx = tx;
16125       if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_HWGAIN, &hwgain) < 0) {
16126          ast_cli(a->fd, "Unable to set the hardware gain for channel %d: %s\n", channel, strerror(errno));
16127          ast_mutex_unlock(&iflock);
16128          return CLI_FAILURE;
16129       }
16130       ast_cli(a->fd, "hardware %s gain set to %d (%.1f dB) on channel %d\n",
16131          tx ? "tx" : "rx", gain, (float)gain/10.0, channel);
16132       break;
16133    }
16134 
16135    ast_mutex_unlock(&iflock);
16136 
16137    if (tmp)
16138       return CLI_SUCCESS;
16139 
16140    ast_cli(a->fd, "Unable to find given channel %d\n", channel);
16141    return CLI_FAILURE;
16142 
16143 }
16144 
16145 static char *dahdi_set_swgain(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16146 {
16147    int channel;
16148    float gain;
16149    int tx;
16150    int res;
16151    struct dahdi_pvt *tmp = NULL;
16152 
16153    switch (cmd) {
16154    case CLI_INIT:
16155       e->command = "dahdi set swgain {rx|tx}";
16156       e->usage =
16157          "Usage: dahdi set swgain <rx|tx> <chan#> <gain>\n"
16158          "   Sets the software gain on a given channel and overrides the\n"
16159          "   value provided at module loadtime.  Changes take effect\n"
16160          "   immediately whether the channel is in use or not.\n"
16161          "\n"
16162          "   <rx|tx> which direction do you want to change (relative to our module)\n"
16163          "   <chan num> is the channel number relative to the device\n"
16164          "   <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
16165       return NULL;
16166    case CLI_GENERATE:
16167       return NULL;
16168    }
16169 
16170    if (a->argc != 6)
16171       return CLI_SHOWUSAGE;
16172 
16173    if (!strcasecmp("rx", a->argv[3]))
16174       tx = 0; /* rx */
16175    else if (!strcasecmp("tx", a->argv[3]))
16176       tx = 1; /* tx */
16177    else
16178       return CLI_SHOWUSAGE;
16179 
16180    channel = atoi(a->argv[4]);
16181    gain = atof(a->argv[5]);
16182 
16183    ast_mutex_lock(&iflock);
16184    for (tmp = iflist; tmp; tmp = tmp->next) {
16185 
16186       if (tmp->channel != channel)
16187          continue;
16188 
16189       if (tmp->subs[SUB_REAL].dfd == -1)
16190          break;
16191 
16192       if (tx)
16193          res = set_actual_txgain(tmp->subs[SUB_REAL].dfd, gain, tmp->txdrc, tmp->law);
16194       else
16195          res = set_actual_rxgain(tmp->subs[SUB_REAL].dfd, gain, tmp->rxdrc, tmp->law);
16196 
16197       if (res) {
16198          ast_cli(a->fd, "Unable to set the software gain for channel %d\n", channel);
16199          ast_mutex_unlock(&iflock);
16200          return CLI_FAILURE;
16201       }
16202 
16203       ast_cli(a->fd, "software %s gain set to %.1f on channel %d\n",
16204          tx ? "tx" : "rx", gain, channel);
16205 
16206       if (tx) {
16207          tmp->txgain = gain;
16208       } else {
16209          tmp->rxgain = gain;
16210       }
16211       break;
16212    }
16213    ast_mutex_unlock(&iflock);
16214 
16215    if (tmp)
16216       return CLI_SUCCESS;
16217 
16218    ast_cli(a->fd, "Unable to find given channel %d\n", channel);
16219    return CLI_FAILURE;
16220 
16221 }
16222 
16223 static char *dahdi_set_dnd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16224 {
16225    int channel;
16226    int on;
16227    struct dahdi_pvt *dahdi_chan = NULL;
16228 
16229    switch (cmd) {
16230    case CLI_INIT:
16231       e->command = "dahdi set dnd";
16232       e->usage =
16233          "Usage: dahdi set dnd <chan#> <on|off>\n"
16234          "  Sets/resets DND (Do Not Disturb) mode on a channel.\n"
16235          "  Changes take effect immediately.\n"
16236          "  <chan num> is the channel number\n"
16237          "  <on|off> Enable or disable DND mode?\n"
16238          ;
16239       return NULL;
16240    case CLI_GENERATE:
16241       return NULL;
16242    }
16243 
16244    if (a->argc != 5)
16245       return CLI_SHOWUSAGE;
16246 
16247    if ((channel = atoi(a->argv[3])) <= 0) {
16248       ast_cli(a->fd, "Expected channel number, got '%s'\n", a->argv[3]);
16249       return CLI_SHOWUSAGE;
16250    }
16251 
16252    if (ast_true(a->argv[4]))
16253       on = 1;
16254    else if (ast_false(a->argv[4]))
16255       on = 0;
16256    else {
16257       ast_cli(a->fd, "Expected 'on' or 'off', got '%s'\n", a->argv[4]);
16258       return CLI_SHOWUSAGE;
16259    }
16260 
16261    ast_mutex_lock(&iflock);
16262    for (dahdi_chan = iflist; dahdi_chan; dahdi_chan = dahdi_chan->next) {
16263       if (dahdi_chan->channel != channel)
16264          continue;
16265 
16266       /* Found the channel. Actually set it */
16267       dahdi_dnd(dahdi_chan, on);
16268       break;
16269    }
16270    ast_mutex_unlock(&iflock);
16271 
16272    if (!dahdi_chan) {
16273       ast_cli(a->fd, "Unable to find given channel %d\n", channel);
16274       return CLI_FAILURE;
16275    }
16276 
16277    return CLI_SUCCESS;
16278 }
16279 
16280 static struct ast_cli_entry dahdi_cli[] = {
16281    AST_CLI_DEFINE(handle_dahdi_show_cadences, "List cadences"),
16282    AST_CLI_DEFINE(dahdi_show_channels, "Show active DAHDI channels"),
16283    AST_CLI_DEFINE(dahdi_show_channel, "Show information on a channel"),
16284    AST_CLI_DEFINE(dahdi_destroy_channel, "Destroy a channel"),
16285    AST_CLI_DEFINE(dahdi_restart_cmd, "Fully restart DAHDI channels"),
16286    AST_CLI_DEFINE(dahdi_show_status, "Show all DAHDI cards status"),
16287    AST_CLI_DEFINE(dahdi_show_version, "Show the DAHDI version in use"),
16288    AST_CLI_DEFINE(dahdi_set_hwgain, "Set hardware gain on a channel"),
16289    AST_CLI_DEFINE(dahdi_set_swgain, "Set software gain on a channel"),
16290    AST_CLI_DEFINE(dahdi_set_dnd, "Sets/resets DND (Do Not Disturb) mode on a channel"),
16291 };
16292 
16293 #define TRANSFER  0
16294 #define HANGUP    1
16295 
16296 static int dahdi_fake_event(struct dahdi_pvt *p, int mode)
16297 {
16298    if (p) {
16299       switch (mode) {
16300       case TRANSFER:
16301          p->fake_event = DAHDI_EVENT_WINKFLASH;
16302          break;
16303       case HANGUP:
16304          p->fake_event = DAHDI_EVENT_ONHOOK;
16305          break;
16306       default:
16307          ast_log(LOG_WARNING, "I don't know how to handle transfer event with this: %d on channel %s\n",mode, ast_channel_name(p->owner));
16308       }
16309    }
16310    return 0;
16311 }
16312 static struct dahdi_pvt *find_channel(int channel)
16313 {
16314    struct dahdi_pvt *p;
16315 
16316    ast_mutex_lock(&iflock);
16317    for (p = iflist; p; p = p->next) {
16318       if (p->channel == channel) {
16319          break;
16320       }
16321    }
16322    ast_mutex_unlock(&iflock);
16323    return p;
16324 }
16325 
16326 /*!
16327  * \internal
16328  * \brief Get private struct using given numeric channel string.
16329  *
16330  * \param channel Numeric channel number string get private struct.
16331  *
16332  * \retval pvt on success.
16333  * \retval NULL on error.
16334  */
16335 static struct dahdi_pvt *find_channel_from_str(const char *channel)
16336 {
16337    int chan_num;
16338 
16339    if (sscanf(channel, "%30d", &chan_num) != 1) {
16340       /* Not numeric string. */
16341       return NULL;
16342    }
16343 
16344    return find_channel(chan_num);
16345 }
16346 
16347 static int action_dahdidndon(struct mansession *s, const struct message *m)
16348 {
16349    struct dahdi_pvt *p;
16350    const char *channel = astman_get_header(m, "DAHDIChannel");
16351 
16352    if (ast_strlen_zero(channel)) {
16353       astman_send_error(s, m, "No channel specified");
16354       return 0;
16355    }
16356    p = find_channel_from_str(channel);
16357    if (!p) {
16358       astman_send_error(s, m, "No such channel");
16359       return 0;
16360    }
16361    dahdi_dnd(p, 1);
16362    astman_send_ack(s, m, "DND Enabled");
16363    return 0;
16364 }
16365 
16366 static int action_dahdidndoff(struct mansession *s, const struct message *m)
16367 {
16368    struct dahdi_pvt *p;
16369    const char *channel = astman_get_header(m, "DAHDIChannel");
16370 
16371    if (ast_strlen_zero(channel)) {
16372       astman_send_error(s, m, "No channel specified");
16373       return 0;
16374    }
16375    p = find_channel_from_str(channel);
16376    if (!p) {
16377       astman_send_error(s, m, "No such channel");
16378       return 0;
16379    }
16380    dahdi_dnd(p, 0);
16381    astman_send_ack(s, m, "DND Disabled");
16382    return 0;
16383 }
16384 
16385 static int action_transfer(struct mansession *s, const struct message *m)
16386 {
16387    struct dahdi_pvt *p;
16388    const char *channel = astman_get_header(m, "DAHDIChannel");
16389 
16390    if (ast_strlen_zero(channel)) {
16391       astman_send_error(s, m, "No channel specified");
16392       return 0;
16393    }
16394    p = find_channel_from_str(channel);
16395    if (!p) {
16396       astman_send_error(s, m, "No such channel");
16397       return 0;
16398    }
16399    if (!analog_lib_handles(p->sig, 0, 0)) {
16400       astman_send_error(s, m, "Channel signaling is not analog");
16401       return 0;
16402    }
16403    dahdi_fake_event(p,TRANSFER);
16404    astman_send_ack(s, m, "DAHDITransfer");
16405    return 0;
16406 }
16407 
16408 static int action_transferhangup(struct mansession *s, const struct message *m)
16409 {
16410    struct dahdi_pvt *p;
16411    const char *channel = astman_get_header(m, "DAHDIChannel");
16412 
16413    if (ast_strlen_zero(channel)) {
16414       astman_send_error(s, m, "No channel specified");
16415       return 0;
16416    }
16417    p = find_channel_from_str(channel);
16418    if (!p) {
16419       astman_send_error(s, m, "No such channel");
16420       return 0;
16421    }
16422    if (!analog_lib_handles(p->sig, 0, 0)) {
16423       astman_send_error(s, m, "Channel signaling is not analog");
16424       return 0;
16425    }
16426    dahdi_fake_event(p,HANGUP);
16427    astman_send_ack(s, m, "DAHDIHangup");
16428    return 0;
16429 }
16430 
16431 static int action_dahdidialoffhook(struct mansession *s, const struct message *m)
16432 {
16433    struct dahdi_pvt *p;
16434    const char *channel = astman_get_header(m, "DAHDIChannel");
16435    const char *number = astman_get_header(m, "Number");
16436    int i;
16437 
16438    if (ast_strlen_zero(channel)) {
16439       astman_send_error(s, m, "No channel specified");
16440       return 0;
16441    }
16442    if (ast_strlen_zero(number)) {
16443       astman_send_error(s, m, "No number specified");
16444       return 0;
16445    }
16446    p = find_channel_from_str(channel);
16447    if (!p) {
16448       astman_send_error(s, m, "No such channel");
16449       return 0;
16450    }
16451    if (!p->owner) {
16452       astman_send_error(s, m, "Channel does not have it's owner");
16453       return 0;
16454    }
16455    for (i = 0; i < strlen(number); i++) {
16456       struct ast_frame f = { AST_FRAME_DTMF, .subclass.integer = number[i] };
16457       dahdi_queue_frame(p, &f);
16458    }
16459    astman_send_ack(s, m, "DAHDIDialOffhook");
16460    return 0;
16461 }
16462 
16463 static int action_dahdishowchannels(struct mansession *s, const struct message *m)
16464 {
16465    struct dahdi_pvt *tmp = NULL;
16466    const char *id = astman_get_header(m, "ActionID");
16467    const char *dahdichannel = astman_get_header(m, "DAHDIChannel");
16468    char idText[256] = "";
16469    int channels = 0;
16470    int dahdichanquery;
16471 
16472    if (!dahdichannel || sscanf(dahdichannel, "%30d", &dahdichanquery) != 1) {
16473       /* Not numeric string. */
16474       dahdichanquery = -1;
16475    }
16476 
16477    astman_send_ack(s, m, "DAHDI channel status will follow");
16478    if (!ast_strlen_zero(id))
16479       snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
16480 
16481    ast_mutex_lock(&iflock);
16482 
16483    for (tmp = iflist; tmp; tmp = tmp->next) {
16484       if (tmp->channel > 0) {
16485          int alm;
16486 
16487          /* If a specific channel is queried for, only deliver status for that channel */
16488          if (dahdichanquery > 0 && tmp->channel != dahdichanquery)
16489             continue;
16490 
16491          alm = get_alarms(tmp);
16492          channels++;
16493          if (tmp->owner) {
16494             /* Add data if we have a current call */
16495             astman_append(s,
16496                "Event: DAHDIShowChannels\r\n"
16497                "DAHDIChannel: %d\r\n"
16498                "Channel: %s\r\n"
16499                "Uniqueid: %s\r\n"
16500                "AccountCode: %s\r\n"
16501                "Signalling: %s\r\n"
16502                "SignallingCode: %d\r\n"
16503                "Context: %s\r\n"
16504                "DND: %s\r\n"
16505                "Alarm: %s\r\n"
16506                "Description: %s\r\n"
16507                "%s"
16508                "\r\n",
16509                tmp->channel,
16510                ast_channel_name(tmp->owner),
16511                ast_channel_uniqueid(tmp->owner),
16512                ast_channel_accountcode(tmp->owner),
16513                sig2str(tmp->sig),
16514                tmp->sig,
16515                tmp->context,
16516                dahdi_dnd(tmp, -1) ? "Enabled" : "Disabled",
16517                alarm2str(alm),
16518                tmp->description, idText);
16519          } else {
16520             astman_append(s,
16521                "Event: DAHDIShowChannels\r\n"
16522                "DAHDIChannel: %d\r\n"
16523                "Signalling: %s\r\n"
16524                "SignallingCode: %d\r\n"
16525                "Context: %s\r\n"
16526                "DND: %s\r\n"
16527                "Alarm: %s\r\n"
16528                "Description: %s\r\n"
16529                "%s"
16530                "\r\n",
16531                tmp->channel, sig2str(tmp->sig), tmp->sig,
16532                tmp->context,
16533                dahdi_dnd(tmp, -1) ? "Enabled" : "Disabled",
16534                alarm2str(alm),
16535                tmp->description, idText);
16536          }
16537       }
16538    }
16539 
16540    ast_mutex_unlock(&iflock);
16541 
16542    astman_append(s,
16543       "Event: DAHDIShowChannelsComplete\r\n"
16544       "%s"
16545       "Items: %d\r\n"
16546       "\r\n",
16547       idText,
16548       channels);
16549    return 0;
16550 }
16551 
16552 #if defined(HAVE_PRI)
16553 static int action_prishowspans(struct mansession *s, const struct message *m)
16554 {
16555    int count;
16556    int idx;
16557    int span_query;
16558    struct dahdi_pri *dspan;
16559    const char *id = astman_get_header(m, "ActionID");
16560    const char *span_str = astman_get_header(m, "Span");
16561    char action_id[256];
16562    const char *show_cmd = "PRIShowSpans";
16563 
16564    /* NOTE: Asking for span 0 gets all spans. */
16565    if (!ast_strlen_zero(span_str)) {
16566       span_query = atoi(span_str);
16567    } else {
16568       span_query = 0;
16569    }
16570 
16571    if (!ast_strlen_zero(id)) {
16572       snprintf(action_id, sizeof(action_id), "ActionID: %s\r\n", id);
16573    } else {
16574       action_id[0] = '\0';
16575    }
16576 
16577    astman_send_ack(s, m, "Span status will follow");
16578 
16579    count = 0;
16580    for (idx = 0; idx < ARRAY_LEN(pris); ++idx) {
16581       dspan = &pris[idx];
16582 
16583       /* If a specific span is asked for, only deliver status for that span. */
16584       if (0 < span_query && dspan->pri.span != span_query) {
16585          continue;
16586       }
16587 
16588       if (dspan->pri.pri) {
16589          count += sig_pri_ami_show_spans(s, show_cmd, &dspan->pri, dspan->dchannels,
16590             action_id);
16591       }
16592    }
16593 
16594    astman_append(s,
16595       "Event: %sComplete\r\n"
16596       "Items: %d\r\n"
16597       "%s"
16598       "\r\n",
16599       show_cmd,
16600       count,
16601       action_id);
16602    return 0;
16603 }
16604 #endif   /* defined(HAVE_PRI) */
16605 
16606 #if defined(HAVE_SS7)
16607 static int linkset_addsigchan(int sigchan)
16608 {
16609    struct dahdi_ss7 *link;
16610    int res;
16611    int curfd;
16612    struct dahdi_params params;
16613    struct dahdi_bufferinfo bi;
16614    struct dahdi_spaninfo si;
16615 
16616    if (sigchan < 0) {
16617       ast_log(LOG_ERROR, "Invalid sigchan!\n");
16618       return -1;
16619    }
16620    if (cur_ss7type < 0) {
16621       ast_log(LOG_ERROR, "Unspecified or invalid ss7type\n");
16622       return -1;
16623    }
16624    if (cur_pointcode < 0) {
16625       ast_log(LOG_ERROR, "Unspecified pointcode!\n");
16626       return -1;
16627    }
16628    if (cur_adjpointcode < 0) {
16629       ast_log(LOG_ERROR, "Unspecified adjpointcode!\n");
16630       return -1;
16631    }
16632    if (cur_defaultdpc < 0) {
16633       ast_log(LOG_ERROR, "Unspecified defaultdpc!\n");
16634       return -1;
16635    }
16636    if (cur_networkindicator < 0) {
16637       ast_log(LOG_ERROR, "Invalid networkindicator!\n");
16638       return -1;
16639    }
16640    link = ss7_resolve_linkset(cur_linkset);
16641    if (!link) {
16642       ast_log(LOG_ERROR, "Invalid linkset number.  Must be between 1 and %d\n", NUM_SPANS + 1);
16643       return -1;
16644    }
16645    if (link->ss7.numsigchans >= SIG_SS7_NUM_DCHANS) {
16646       ast_log(LOG_ERROR, "Too many sigchans on linkset %d\n", cur_linkset);
16647       return -1;
16648    }
16649 
16650    curfd = link->ss7.numsigchans;
16651 
16652    /* Open signaling channel */
16653    link->ss7.fds[curfd] = open("/dev/dahdi/channel", O_RDWR, 0600);
16654    if (link->ss7.fds[curfd] < 0) {
16655       ast_log(LOG_ERROR, "Unable to open SS7 sigchan %d (%s)\n", sigchan,
16656          strerror(errno));
16657       return -1;
16658    }
16659    if (ioctl(link->ss7.fds[curfd], DAHDI_SPECIFY, &sigchan) == -1) {
16660       dahdi_close_ss7_fd(link, curfd);
16661       ast_log(LOG_ERROR, "Unable to specify SS7 sigchan %d (%s)\n", sigchan,
16662          strerror(errno));
16663       return -1;
16664    }
16665 
16666    /* Get signaling channel parameters */
16667    memset(&params, 0, sizeof(params));
16668    res = ioctl(link->ss7.fds[curfd], DAHDI_GET_PARAMS, &params);
16669    if (res) {
16670       dahdi_close_ss7_fd(link, curfd);
16671       ast_log(LOG_ERROR, "Unable to get parameters for sigchan %d (%s)\n", sigchan,
16672          strerror(errno));
16673       return -1;
16674    }
16675    if (params.sigtype != DAHDI_SIG_HDLCFCS
16676       && params.sigtype != DAHDI_SIG_HARDHDLC
16677       && params.sigtype != DAHDI_SIG_MTP2) {
16678       dahdi_close_ss7_fd(link, curfd);
16679       ast_log(LOG_ERROR, "sigchan %d is not in HDLC/FCS mode.\n", sigchan);
16680       return -1;
16681    }
16682 
16683    /* Set signaling channel buffer policy. */
16684    memset(&bi, 0, sizeof(bi));
16685    bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
16686    bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
16687    bi.numbufs = 32;
16688    bi.bufsize = 512;
16689    if (ioctl(link->ss7.fds[curfd], DAHDI_SET_BUFINFO, &bi)) {
16690       ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n",
16691          sigchan, strerror(errno));
16692       dahdi_close_ss7_fd(link, curfd);
16693       return -1;
16694    }
16695 
16696    /* Get current signaling channel alarm status. */
16697    memset(&si, 0, sizeof(si));
16698    res = ioctl(link->ss7.fds[curfd], DAHDI_SPANSTAT, &si);
16699    if (res) {
16700       dahdi_close_ss7_fd(link, curfd);
16701       ast_log(LOG_ERROR, "Unable to get span state for sigchan %d (%s)\n", sigchan,
16702          strerror(errno));
16703    }
16704 
16705    res = sig_ss7_add_sigchan(&link->ss7, curfd, cur_ss7type,
16706       (params.sigtype == DAHDI_SIG_MTP2)
16707          ? SS7_TRANSPORT_DAHDIMTP2
16708          : SS7_TRANSPORT_DAHDIDCHAN,
16709       si.alarms, cur_networkindicator, cur_pointcode, cur_adjpointcode);
16710    if (res) {
16711       dahdi_close_ss7_fd(link, curfd);
16712       return -1;
16713    }
16714 
16715    ++link->ss7.numsigchans;
16716 
16717    return 0;
16718 }
16719 #endif   /* defined(HAVE_SS7) */
16720 
16721 #if defined(HAVE_SS7)
16722 static char *handle_ss7_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16723 {
16724    int span;
16725    switch (cmd) {
16726    case CLI_INIT:
16727       e->command = "ss7 set debug {on|off} linkset";
16728       e->usage =
16729          "Usage: ss7 set debug {on|off} linkset <linkset>\n"
16730          "       Enables debugging on a given SS7 linkset\n";
16731       return NULL;
16732    case CLI_GENERATE:
16733       return NULL;
16734    }
16735    if (a->argc < 6)
16736       return CLI_SHOWUSAGE;
16737    span = atoi(a->argv[5]);
16738    if ((span < 1) || (span > NUM_SPANS)) {
16739       ast_cli(a->fd, "Invalid linkset %s.  Should be a number from %d to %d\n", a->argv[5], 1, NUM_SPANS);
16740       return CLI_SUCCESS;
16741    }
16742    if (!linksets[span-1].ss7.ss7) {
16743       ast_cli(a->fd, "No SS7 running on linkset %d\n", span);
16744    } else {
16745       if (!strcasecmp(a->argv[3], "on")) {
16746          linksets[span - 1].ss7.debug = 1;
16747          ss7_set_debug(linksets[span-1].ss7.ss7, SIG_SS7_DEBUG);
16748          ast_cli(a->fd, "Enabled debugging on linkset %d\n", span);
16749       } else {
16750          linksets[span - 1].ss7.debug = 0;
16751          ss7_set_debug(linksets[span-1].ss7.ss7, 0);
16752          ast_cli(a->fd, "Disabled debugging on linkset %d\n", span);
16753       }
16754    }
16755 
16756    return CLI_SUCCESS;
16757 }
16758 #endif   /* defined(HAVE_SS7) */
16759 
16760 #if defined(HAVE_SS7)
16761 static char *handle_ss7_block_cic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16762 {
16763    int linkset, cic;
16764    int blocked = -1, i;
16765    switch (cmd) {
16766    case CLI_INIT:
16767       e->command = "ss7 block cic";
16768       e->usage =
16769          "Usage: ss7 block cic <linkset> <CIC>\n"
16770          "       Sends a remote blocking request for the given CIC on the specified linkset\n";
16771       return NULL;
16772    case CLI_GENERATE:
16773       return NULL;
16774    }
16775    if (a->argc == 5)
16776       linkset = atoi(a->argv[3]);
16777    else
16778       return CLI_SHOWUSAGE;
16779 
16780    if ((linkset < 1) || (linkset > NUM_SPANS)) {
16781       ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16782       return CLI_SUCCESS;
16783    }
16784 
16785    if (!linksets[linkset-1].ss7.ss7) {
16786       ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16787       return CLI_SUCCESS;
16788    }
16789 
16790    cic = atoi(a->argv[4]);
16791 
16792    if (cic < 1) {
16793       ast_cli(a->fd, "Invalid CIC specified!\n");
16794       return CLI_SUCCESS;
16795    }
16796 
16797    for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
16798       if (linksets[linkset-1].ss7.pvts[i]->cic == cic) {
16799          blocked = linksets[linkset-1].ss7.pvts[i]->locallyblocked;
16800          if (!blocked) {
16801             ast_mutex_lock(&linksets[linkset-1].ss7.lock);
16802             isup_blo(linksets[linkset-1].ss7.ss7, cic, linksets[linkset-1].ss7.pvts[i]->dpc);
16803             ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
16804          }
16805       }
16806    }
16807 
16808    if (blocked < 0) {
16809       ast_cli(a->fd, "Invalid CIC specified!\n");
16810       return CLI_SUCCESS;
16811    }
16812 
16813    if (!blocked)
16814       ast_cli(a->fd, "Sent blocking request for linkset %d on CIC %d\n", linkset, cic);
16815    else
16816       ast_cli(a->fd, "CIC %d already locally blocked\n", cic);
16817 
16818    /* Break poll on the linkset so it sends our messages */
16819    pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
16820 
16821    return CLI_SUCCESS;
16822 }
16823 #endif   /* defined(HAVE_SS7) */
16824 
16825 #if defined(HAVE_SS7)
16826 static char *handle_ss7_block_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16827 {
16828    int linkset;
16829    int i;
16830    switch (cmd) {
16831    case CLI_INIT:
16832       e->command = "ss7 block linkset";
16833       e->usage =
16834          "Usage: ss7 block linkset <linkset number>\n"
16835          "       Sends a remote blocking request for all CICs on the given linkset\n";
16836       return NULL;
16837    case CLI_GENERATE:
16838       return NULL;
16839    }
16840    if (a->argc == 4)
16841       linkset = atoi(a->argv[3]);
16842    else
16843       return CLI_SHOWUSAGE;
16844 
16845    if ((linkset < 1) || (linkset > NUM_SPANS)) {
16846       ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16847       return CLI_SUCCESS;
16848    }
16849 
16850    if (!linksets[linkset-1].ss7.ss7) {
16851       ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16852       return CLI_SUCCESS;
16853    }
16854 
16855    for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
16856       ast_cli(a->fd, "Sending remote blocking request on CIC %d\n", linksets[linkset-1].ss7.pvts[i]->cic);
16857       ast_mutex_lock(&linksets[linkset-1].ss7.lock);
16858       isup_blo(linksets[linkset-1].ss7.ss7, linksets[linkset-1].ss7.pvts[i]->cic, linksets[linkset-1].ss7.pvts[i]->dpc);
16859       ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
16860    }
16861 
16862    /* Break poll on the linkset so it sends our messages */
16863    pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
16864 
16865    return CLI_SUCCESS;
16866 }
16867 #endif   /* defined(HAVE_SS7) */
16868 
16869 #if defined(HAVE_SS7)
16870 static char *handle_ss7_unblock_cic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16871 {
16872    int linkset, cic;
16873    int i, blocked = -1;
16874    switch (cmd) {
16875    case CLI_INIT:
16876       e->command = "ss7 unblock cic";
16877       e->usage =
16878          "Usage: ss7 unblock cic <linkset> <CIC>\n"
16879          "       Sends a remote unblocking request for the given CIC on the specified linkset\n";
16880       return NULL;
16881    case CLI_GENERATE:
16882       return NULL;
16883    }
16884 
16885    if (a->argc == 5)
16886       linkset = atoi(a->argv[3]);
16887    else
16888       return CLI_SHOWUSAGE;
16889 
16890    if ((linkset < 1) || (linkset > NUM_SPANS)) {
16891       ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16892       return CLI_SUCCESS;
16893    }
16894 
16895    if (!linksets[linkset-1].ss7.ss7) {
16896       ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16897       return CLI_SUCCESS;
16898    }
16899 
16900    cic = atoi(a->argv[4]);
16901 
16902    if (cic < 1) {
16903       ast_cli(a->fd, "Invalid CIC specified!\n");
16904       return CLI_SUCCESS;
16905    }
16906 
16907    for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
16908       if (linksets[linkset-1].ss7.pvts[i]->cic == cic) {
16909          blocked = linksets[linkset-1].ss7.pvts[i]->locallyblocked;
16910          if (blocked) {
16911             ast_mutex_lock(&linksets[linkset-1].ss7.lock);
16912             isup_ubl(linksets[linkset-1].ss7.ss7, cic, linksets[linkset-1].ss7.pvts[i]->dpc);
16913             ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
16914          }
16915       }
16916    }
16917 
16918    if (blocked > 0)
16919       ast_cli(a->fd, "Sent unblocking request for linkset %d on CIC %d\n", linkset, cic);
16920 
16921    /* Break poll on the linkset so it sends our messages */
16922    pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
16923 
16924    return CLI_SUCCESS;
16925 }
16926 #endif   /* defined(HAVE_SS7) */
16927 
16928 #if defined(HAVE_SS7)
16929 static char *handle_ss7_unblock_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16930 {
16931    int linkset;
16932    int i;
16933    switch (cmd) {
16934    case CLI_INIT:
16935       e->command = "ss7 unblock linkset";
16936       e->usage =
16937          "Usage: ss7 unblock linkset <linkset number>\n"
16938          "       Sends a remote unblocking request for all CICs on the specified linkset\n";
16939       return NULL;
16940    case CLI_GENERATE:
16941       return NULL;
16942    }
16943 
16944    if (a->argc == 4)
16945       linkset = atoi(a->argv[3]);
16946    else
16947       return CLI_SHOWUSAGE;
16948 
16949    if ((linkset < 1) || (linkset > NUM_SPANS)) {
16950       ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16951       return CLI_SUCCESS;
16952    }
16953 
16954    if (!linksets[linkset-1].ss7.ss7) {
16955       ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16956       return CLI_SUCCESS;
16957    }
16958 
16959    for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
16960       ast_cli(a->fd, "Sending remote unblock request on CIC %d\n", linksets[linkset-1].ss7.pvts[i]->cic);
16961       ast_mutex_lock(&linksets[linkset-1].ss7.lock);
16962       isup_ubl(linksets[linkset-1].ss7.ss7, linksets[linkset-1].ss7.pvts[i]->cic, linksets[linkset-1].ss7.pvts[i]->dpc);
16963       ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
16964    }
16965 
16966    /* Break poll on the linkset so it sends our messages */
16967    pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
16968 
16969    return CLI_SUCCESS;
16970 }
16971 #endif   /* defined(HAVE_SS7) */
16972 
16973 #if defined(HAVE_SS7)
16974 static char *handle_ss7_show_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16975 {
16976    int linkset;
16977    struct sig_ss7_linkset *ss7;
16978    switch (cmd) {
16979    case CLI_INIT:
16980       e->command = "ss7 show linkset";
16981       e->usage =
16982          "Usage: ss7 show linkset <span>\n"
16983          "       Shows the status of an SS7 linkset.\n";
16984       return NULL;
16985    case CLI_GENERATE:
16986       return NULL;
16987    }
16988 
16989    if (a->argc < 4)
16990       return CLI_SHOWUSAGE;
16991    linkset = atoi(a->argv[3]);
16992    if ((linkset < 1) || (linkset > NUM_SPANS)) {
16993       ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16994       return CLI_SUCCESS;
16995    }
16996    ss7 = &linksets[linkset - 1].ss7;
16997    if (!ss7->ss7) {
16998       ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16999       return CLI_SUCCESS;
17000    }
17001 
17002    ast_cli(a->fd, "SS7 linkset %d status: %s\n", linkset, (ss7->state == LINKSET_STATE_UP) ? "Up" : "Down");
17003 
17004    return CLI_SUCCESS;
17005 }
17006 #endif   /* defined(HAVE_SS7) */
17007 
17008 #if defined(HAVE_SS7)
17009 static char *handle_ss7_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
17010 {
17011    int linkset;
17012 
17013    switch (cmd) {
17014    case CLI_INIT:
17015       e->command = "ss7 show channels";
17016       e->usage =
17017          "Usage: ss7 show channels\n"
17018          "       Displays SS7 channel information at a glance.\n";
17019       return NULL;
17020    case CLI_GENERATE:
17021       return NULL;
17022    }
17023 
17024    if (a->argc != 3)
17025       return CLI_SHOWUSAGE;
17026 
17027    sig_ss7_cli_show_channels_header(a->fd);
17028    for (linkset = 0; linkset < NUM_SPANS; ++linkset) {
17029       if (linksets[linkset].ss7.ss7) {
17030          sig_ss7_cli_show_channels(a->fd, &linksets[linkset].ss7);
17031       }
17032    }
17033    return CLI_SUCCESS;
17034 }
17035 #endif   /* defined(HAVE_SS7) */
17036 
17037 #if defined(HAVE_SS7)
17038 static char *handle_ss7_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
17039 {
17040    switch (cmd) {
17041    case CLI_INIT:
17042       e->command = "ss7 show version";
17043       e->usage =
17044          "Usage: ss7 show version\n"
17045          "  Show the libss7 version\n";
17046       return NULL;
17047    case CLI_GENERATE:
17048       return NULL;
17049    }
17050 
17051    ast_cli(a->fd, "libss7 version: %s\n", ss7_get_version());
17052 
17053    return CLI_SUCCESS;
17054 }
17055 #endif   /* defined(HAVE_SS7) */
17056 
17057 #if defined(HAVE_SS7)
17058 static struct ast_cli_entry dahdi_ss7_cli[] = {
17059    AST_CLI_DEFINE(handle_ss7_debug, "Enables SS7 debugging on a linkset"),
17060    AST_CLI_DEFINE(handle_ss7_block_cic, "Blocks the given CIC"),
17061    AST_CLI_DEFINE(handle_ss7_unblock_cic, "Unblocks the given CIC"),
17062    AST_CLI_DEFINE(handle_ss7_block_linkset, "Blocks all CICs on a linkset"),
17063    AST_CLI_DEFINE(handle_ss7_unblock_linkset, "Unblocks all CICs on a linkset"),
17064    AST_CLI_DEFINE(handle_ss7_show_linkset, "Shows the status of a linkset"),
17065    AST_CLI_DEFINE(handle_ss7_show_channels, "Displays SS7 channel information"),
17066    AST_CLI_DEFINE(handle_ss7_version, "Displays libss7 version"),
17067 };
17068 #endif   /* defined(HAVE_SS7) */
17069 
17070 #if defined(HAVE_PRI)
17071 #if defined(HAVE_PRI_CCSS)
17072 /*!
17073  * \internal
17074  * \brief CC agent initialization.
17075  * \since 1.8
17076  *
17077  * \param agent CC core agent control.
17078  * \param chan Original channel the agent will attempt to recall.
17079  *
17080  * \details
17081  * This callback is called when the CC core is initialized.  Agents should allocate
17082  * any private data necessary for the call and assign it to the private_data
17083  * on the agent.  Additionally, if any ast_cc_agent_flags are pertinent to the
17084  * specific agent type, they should be set in this function as well.
17085  *
17086  * \retval 0 on success.
17087  * \retval -1 on error.
17088  */
17089 static int dahdi_pri_cc_agent_init(struct ast_cc_agent *agent, struct ast_channel *chan)
17090 {
17091    struct dahdi_pvt *pvt;
17092    struct sig_pri_chan *pvt_chan;
17093    int res;
17094 
17095    ast_assert(!strcmp(ast_channel_tech(chan)->type, "DAHDI"));
17096 
17097    pvt = ast_channel_tech_pvt(chan);
17098    if (dahdi_sig_pri_lib_handles(pvt->sig)) {
17099       pvt_chan = pvt->sig_pvt;
17100    } else {
17101       pvt_chan = NULL;
17102    }
17103    if (!pvt_chan) {
17104       return -1;
17105    }
17106 
17107    ast_module_ref(ast_module_info->self);
17108 
17109    res = sig_pri_cc_agent_init(agent, pvt_chan);
17110    if (res) {
17111       ast_module_unref(ast_module_info->self);
17112    }
17113    return res;
17114 }
17115 #endif   /* defined(HAVE_PRI_CCSS) */
17116 #endif   /* defined(HAVE_PRI) */
17117 
17118 #if defined(HAVE_PRI)
17119 #if defined(HAVE_PRI_CCSS)
17120 /*!
17121  * \internal
17122  * \brief Destroy private data on the agent.
17123  * \since 1.8
17124  *
17125  * \param agent CC core agent control.
17126  *
17127  * \details
17128  * The core will call this function upon completion
17129  * or failure of CC.
17130  *
17131  * \return Nothing
17132  */
17133 static void dahdi_pri_cc_agent_destructor(struct ast_cc_agent *agent)
17134 {
17135    sig_pri_cc_agent_destructor(agent);
17136 
17137    ast_module_unref(ast_module_info->self);
17138 }
17139 #endif   /* defined(HAVE_PRI_CCSS) */
17140 #endif   /* defined(HAVE_PRI) */
17141 
17142 #if defined(HAVE_PRI)
17143 #if defined(HAVE_PRI_CCSS)
17144 static struct ast_cc_agent_callbacks dahdi_pri_cc_agent_callbacks = {
17145    .type = dahdi_pri_cc_type,
17146    .init = dahdi_pri_cc_agent_init,
17147    .start_offer_timer = sig_pri_cc_agent_start_offer_timer,
17148    .stop_offer_timer = sig_pri_cc_agent_stop_offer_timer,
17149    .respond = sig_pri_cc_agent_req_rsp,
17150    .status_request = sig_pri_cc_agent_status_req,
17151    .stop_ringing = sig_pri_cc_agent_stop_ringing,
17152    .party_b_free = sig_pri_cc_agent_party_b_free,
17153    .start_monitoring = sig_pri_cc_agent_start_monitoring,
17154    .callee_available = sig_pri_cc_agent_callee_available,
17155    .destructor = dahdi_pri_cc_agent_destructor,
17156 };
17157 #endif   /* defined(HAVE_PRI_CCSS) */
17158 #endif   /* defined(HAVE_PRI) */
17159 
17160 #if defined(HAVE_PRI)
17161 #if defined(HAVE_PRI_CCSS)
17162 static struct ast_cc_monitor_callbacks dahdi_pri_cc_monitor_callbacks = {
17163    .type = dahdi_pri_cc_type,
17164    .request_cc = sig_pri_cc_monitor_req_cc,
17165    .suspend = sig_pri_cc_monitor_suspend,
17166    .unsuspend = sig_pri_cc_monitor_unsuspend,
17167    .status_response = sig_pri_cc_monitor_status_rsp,
17168    .cancel_available_timer = sig_pri_cc_monitor_cancel_available_timer,
17169    .destructor = sig_pri_cc_monitor_destructor,
17170 };
17171 #endif   /* defined(HAVE_PRI_CCSS) */
17172 #endif   /* defined(HAVE_PRI) */
17173 
17174 static int __unload_module(void)
17175 {
17176    struct dahdi_pvt *p;
17177 #if defined(HAVE_PRI) || defined(HAVE_SS7)
17178    int i, j;
17179 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
17180 
17181 #ifdef HAVE_PRI
17182    for (i = 0; i < NUM_SPANS; i++) {
17183       if (pris[i].pri.master != AST_PTHREADT_NULL) {
17184          pthread_cancel(pris[i].pri.master);
17185          pthread_kill(pris[i].pri.master, SIGURG);
17186       }
17187    }
17188    ast_cli_unregister_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
17189    ast_unregister_application(dahdi_send_keypad_facility_app);
17190 #ifdef HAVE_PRI_PROG_W_CAUSE
17191    ast_unregister_application(dahdi_send_callrerouting_facility_app);
17192 #endif
17193 #endif
17194 #if defined(HAVE_SS7)
17195    for (i = 0; i < NUM_SPANS; i++) {
17196       if (linksets[i].ss7.master != AST_PTHREADT_NULL) {
17197          pthread_cancel(linksets[i].ss7.master);
17198          pthread_kill(linksets[i].ss7.master, SIGURG);
17199       }
17200    }
17201    ast_cli_unregister_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
17202 #endif   /* defined(HAVE_SS7) */
17203 #if defined(HAVE_OPENR2)
17204    dahdi_r2_destroy_links();
17205    ast_cli_unregister_multiple(dahdi_mfcr2_cli, ARRAY_LEN(dahdi_mfcr2_cli));
17206    ast_unregister_application(dahdi_accept_r2_call_app);
17207 #endif
17208 
17209    ast_cli_unregister_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli));
17210    ast_manager_unregister("DAHDIDialOffhook");
17211    ast_manager_unregister("DAHDIHangup");
17212    ast_manager_unregister("DAHDITransfer");
17213    ast_manager_unregister("DAHDIDNDoff");
17214    ast_manager_unregister("DAHDIDNDon");
17215    ast_manager_unregister("DAHDIShowChannels");
17216    ast_manager_unregister("DAHDIRestart");
17217 #if defined(HAVE_PRI)
17218    ast_manager_unregister("PRIShowSpans");
17219 #endif   /* defined(HAVE_PRI) */
17220    ast_data_unregister(NULL);
17221    ast_channel_unregister(&dahdi_tech);
17222 
17223    /* Hangup all interfaces if they have an owner */
17224    ast_mutex_lock(&iflock);
17225    for (p = iflist; p; p = p->next) {
17226       if (p->owner)
17227          ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
17228    }
17229    ast_mutex_unlock(&iflock);
17230 
17231    ast_mutex_lock(&monlock);
17232    if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
17233       pthread_cancel(monitor_thread);
17234       pthread_kill(monitor_thread, SIGURG);
17235       pthread_join(monitor_thread, NULL);
17236    }
17237    monitor_thread = AST_PTHREADT_STOP;
17238    ast_mutex_unlock(&monlock);
17239 
17240    destroy_all_channels();
17241 
17242 #if defined(HAVE_PRI)
17243    for (i = 0; i < NUM_SPANS; i++) {
17244       if (pris[i].pri.master && (pris[i].pri.master != AST_PTHREADT_NULL)) {
17245          pthread_join(pris[i].pri.master, NULL);
17246       }
17247       for (j = 0; j < SIG_PRI_NUM_DCHANS; j++) {
17248          dahdi_close_pri_fd(&(pris[i]), j);
17249       }
17250       sig_pri_stop_pri(&pris[i].pri);
17251    }
17252 #if defined(HAVE_PRI_CCSS)
17253    ast_cc_agent_unregister(&dahdi_pri_cc_agent_callbacks);
17254    ast_cc_monitor_unregister(&dahdi_pri_cc_monitor_callbacks);
17255 #endif   /* defined(HAVE_PRI_CCSS) */
17256    sig_pri_unload();
17257 #endif
17258 
17259 #if defined(HAVE_SS7)
17260    for (i = 0; i < NUM_SPANS; i++) {
17261       if (linksets[i].ss7.master && (linksets[i].ss7.master != AST_PTHREADT_NULL)) {
17262          pthread_join(linksets[i].ss7.master, NULL);
17263       }
17264       for (j = 0; j < SIG_SS7_NUM_DCHANS; j++) {
17265          dahdi_close_ss7_fd(&(linksets[i]), j);
17266       }
17267    }
17268 #endif   /* defined(HAVE_SS7) */
17269    ast_cond_destroy(&ss_thread_complete);
17270 
17271    dahdi_tech.capabilities = ast_format_cap_destroy(dahdi_tech.capabilities);
17272    return 0;
17273 }
17274 
17275 static int unload_module(void)
17276 {
17277 #if defined(HAVE_PRI) || defined(HAVE_SS7)
17278    int y;
17279 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
17280 #ifdef HAVE_PRI
17281    for (y = 0; y < NUM_SPANS; y++)
17282       ast_mutex_destroy(&pris[y].pri.lock);
17283 #endif
17284 #if defined(HAVE_SS7)
17285    for (y = 0; y < NUM_SPANS; y++)
17286       ast_mutex_destroy(&linksets[y].ss7.lock);
17287 #endif   /* defined(HAVE_SS7) */
17288    return __unload_module();
17289 }
17290 
17291 static void string_replace(char *str, int char1, int char2)
17292 {
17293    for (; *str; str++) {
17294       if (*str == char1) {
17295          *str = char2;
17296       }
17297    }
17298 }
17299 
17300 static char *parse_spanchan(char *chanstr, char **subdir)
17301 {
17302    char *p;
17303 
17304    if ((p = strrchr(chanstr, '!')) == NULL) {
17305       *subdir = NULL;
17306       return chanstr;
17307    }
17308    *p++ = '\0';
17309    string_replace(chanstr, '!', '/');
17310    *subdir = chanstr;
17311    return p;
17312 }
17313 
17314 static int build_channels(struct dahdi_chan_conf *conf, const char *value, int reload, int lineno, int *found_pseudo)
17315 {
17316    char *c, *chan;
17317    char *subdir;
17318    int x, start, finish;
17319    struct dahdi_pvt *tmp;
17320 
17321    if ((reload == 0) && (conf->chan.sig < 0) && !conf->is_sig_auto) {
17322       ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n");
17323       return -1;
17324    }
17325 
17326    c = ast_strdupa(value);
17327    c = parse_spanchan(c, &subdir);
17328 
17329    while ((chan = strsep(&c, ","))) {
17330       if (sscanf(chan, "%30d-%30d", &start, &finish) == 2) {
17331          /* Range */
17332       } else if (sscanf(chan, "%30d", &start)) {
17333          /* Just one */
17334          finish = start;
17335       } else if (!strcasecmp(chan, "pseudo")) {
17336          finish = start = CHAN_PSEUDO;
17337          if (found_pseudo)
17338             *found_pseudo = 1;
17339       } else {
17340          ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan);
17341          return -1;
17342       }
17343       if (finish < start) {
17344          ast_log(LOG_WARNING, "Sillyness: %d < %d\n", start, finish);
17345          x = finish;
17346          finish = start;
17347          start = x;
17348       }
17349 
17350       for (x = start; x <= finish; x++) {
17351          char fn[PATH_MAX];
17352          int real_channel = x;
17353 
17354          if (!ast_strlen_zero(subdir)) {
17355             real_channel = device2chan(subdir, x, fn, sizeof(fn));
17356             if (real_channel < 0) {
17357                if (conf->ignore_failed_channels) {
17358                   ast_log(LOG_WARNING, "Failed configuring %s!%d, (got %d). But moving on to others.\n",
17359                         subdir, x, real_channel);
17360                   continue;
17361                } else {
17362                   ast_log(LOG_ERROR, "Failed configuring %s!%d, (got %d).\n",
17363                         subdir, x, real_channel);
17364                   return -1;
17365                }
17366             }
17367          }
17368          tmp = mkintf(real_channel, conf, reload);
17369 
17370          if (tmp) {
17371             ast_verb(3, "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", real_channel, sig2str(tmp->sig));
17372          } else {
17373             ast_log(LOG_ERROR, "Unable to %s channel '%s'\n",
17374                   (reload == 1) ? "reconfigure" : "register", value);
17375             return -1;
17376          }
17377       }
17378    }
17379 
17380    return 0;
17381 }
17382 
17383 /** The length of the parameters list of 'dahdichan'.
17384  * \todo Move definition of MAX_CHANLIST_LEN to a proper place. */
17385 #define MAX_CHANLIST_LEN 80
17386 
17387 static void process_echocancel(struct dahdi_chan_conf *confp, const char *data, unsigned int line)
17388 {
17389    char *parse = ast_strdupa(data);
17390    char *params[DAHDI_MAX_ECHOCANPARAMS + 1];
17391    unsigned int param_count;
17392    unsigned int x;
17393 
17394    if (!(param_count = ast_app_separate_args(parse, ',', params, ARRAY_LEN(params))))
17395       return;
17396 
17397    memset(&confp->chan.echocancel, 0, sizeof(confp->chan.echocancel));
17398 
17399    /* first parameter is tap length, process it here */
17400 
17401    x = ast_strlen_zero(params[0]) ? 0 : atoi(params[0]);
17402 
17403    if ((x == 32) || (x == 64) || (x == 128) || (x == 256) || (x == 512) || (x == 1024))
17404       confp->chan.echocancel.head.tap_length = x;
17405    else if ((confp->chan.echocancel.head.tap_length = ast_true(params[0])))
17406       confp->chan.echocancel.head.tap_length = 128;
17407 
17408    /* now process any remaining parameters */
17409 
17410    for (x = 1; x < param_count; x++) {
17411       struct {
17412          char *name;
17413          char *value;
17414       } param;
17415 
17416       if (ast_app_separate_args(params[x], '=', (char **) &param, 2) < 1) {
17417          ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %u: '%s'\n", line, params[x]);
17418          continue;
17419       }
17420 
17421       if (ast_strlen_zero(param.name) || (strlen(param.name) > sizeof(confp->chan.echocancel.params[0].name)-1)) {
17422          ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %u: '%s'\n", line, param.name);
17423          continue;
17424       }
17425 
17426       strcpy(confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].name, param.name);
17427 
17428       if (param.value) {
17429          if (sscanf(param.value, "%30d", &confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].value) != 1) {
17430             ast_log(LOG_WARNING, "Invalid echocancel parameter value supplied at line %u: '%s'\n", line, param.value);
17431             continue;
17432          }
17433       }
17434       confp->chan.echocancel.head.param_count++;
17435    }
17436 }
17437 
17438 #if defined(HAVE_PRI)
17439 #if defined(HAVE_PRI_DISPLAY_TEXT)
17440 /*!
17441  * \internal
17442  * \brief Determine the configured display text options.
17443  * \since 10.0
17444  *
17445  * \param value Configuration value string.
17446  *
17447  * \return Configured display text option flags.
17448  */
17449 static unsigned long dahdi_display_text_option(const char *value)
17450 {
17451    char *val_str;
17452    char *opt_str;
17453    unsigned long options;
17454 
17455    options = 0;
17456    val_str = ast_strdupa(value);
17457 
17458    for (;;) {
17459       opt_str = strsep(&val_str, ",");
17460       if (!opt_str) {
17461          break;
17462       }
17463       opt_str = ast_strip(opt_str);
17464       if (!*opt_str) {
17465          continue;
17466       }
17467 
17468       if (!strcasecmp(opt_str, "block")) {
17469          options |= PRI_DISPLAY_OPTION_BLOCK;
17470       } else if (!strcasecmp(opt_str, "name_initial")) {
17471          options |= PRI_DISPLAY_OPTION_NAME_INITIAL;
17472       } else if (!strcasecmp(opt_str, "name_update")) {
17473          options |= PRI_DISPLAY_OPTION_NAME_UPDATE;
17474       } else if (!strcasecmp(opt_str, "name")) {
17475          options |= (PRI_DISPLAY_OPTION_NAME_INITIAL | PRI_DISPLAY_OPTION_NAME_UPDATE);
17476       } else if (!strcasecmp(opt_str, "text")) {
17477          options |= PRI_DISPLAY_OPTION_TEXT;
17478       }
17479    }
17480    return options;
17481 }
17482 #endif   /* defined(HAVE_PRI_DISPLAY_TEXT) */
17483 #endif   /* defined(HAVE_PRI) */
17484 
17485 #if defined(HAVE_PRI)
17486 #if defined(HAVE_PRI_DATETIME_SEND)
17487 /*!
17488  * \internal
17489  * \brief Determine the configured date/time send policy option.
17490  * \since 10.0
17491  *
17492  * \param value Configuration value string.
17493  *
17494  * \return Configured date/time send policy option.
17495  */
17496 static int dahdi_datetime_send_option(const char *value)
17497 {
17498    int option;
17499 
17500    option = PRI_DATE_TIME_SEND_DEFAULT;
17501 
17502    if (ast_false(value)) {
17503       option = PRI_DATE_TIME_SEND_NO;
17504    } else if (!strcasecmp(value, "date")) {
17505       option = PRI_DATE_TIME_SEND_DATE;
17506    } else if (!strcasecmp(value, "date_hh")) {
17507       option = PRI_DATE_TIME_SEND_DATE_HH;
17508    } else if (!strcasecmp(value, "date_hhmm")) {
17509       option = PRI_DATE_TIME_SEND_DATE_HHMM;
17510    } else if (!strcasecmp(value, "date_hhmmss")) {
17511       option = PRI_DATE_TIME_SEND_DATE_HHMMSS;
17512    }
17513 
17514    return option;
17515 }
17516 #endif   /* defined(HAVE_PRI_DATETIME_SEND) */
17517 #endif   /* defined(HAVE_PRI) */
17518 
17519 /*! process_dahdi() - ignore keyword 'channel' and similar */
17520 #define PROC_DAHDI_OPT_NOCHAN  (1 << 0)
17521 /*! process_dahdi() - No warnings on non-existing cofiguration keywords */
17522 #define PROC_DAHDI_OPT_NOWARN  (1 << 1)
17523 
17524 static void parse_busy_pattern(struct ast_variable *v, struct ast_dsp_busy_pattern *busy_cadence)
17525 {
17526    int count_pattern = 0;
17527    int norval = 0;
17528    char *temp = NULL;
17529 
17530    for (; ;) {
17531       /* Scans the string for the next value in the pattern. If none, it checks to see if any have been entered so far. */
17532       if(!sscanf(v->value, "%30d", &norval) && count_pattern == 0) { 
17533          ast_log(LOG_ERROR, "busypattern= expects either busypattern=tonelength,quietlength or busypattern=t1length, q1length, t2length, q2length at line %d.\n", v->lineno);
17534          break;
17535       }
17536 
17537       busy_cadence->pattern[count_pattern] = norval; 
17538       
17539       count_pattern++;
17540       if (count_pattern == 4) {
17541          break;
17542       }
17543 
17544       temp = strchr(v->value, ',');
17545       if (temp == NULL) {
17546          break;
17547       }
17548       v->value = temp + 1;
17549    }
17550    busy_cadence->length = count_pattern;
17551 
17552    if (count_pattern % 2 != 0) { 
17553       /* The pattern length must be divisible by two */
17554       ast_log(LOG_ERROR, "busypattern= expects either busypattern=tonelength,quietlength or busypattern=t1length, q1length, t2length, q2length at line %d.\n", v->lineno);
17555    }
17556    
17557 }
17558 
17559 static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct ast_variable *v, int reload, int options)
17560 {
17561    struct dahdi_pvt *tmp;
17562    int y;
17563    int found_pseudo = 0;
17564    struct ast_variable *dahdichan = NULL;
17565 
17566    for (; v; v = v->next) {
17567       if (!ast_jb_read_conf(&global_jbconf, v->name, v->value))
17568          continue;
17569 
17570       /* Create the interface list */
17571       if (!strcasecmp(v->name, "channel") || !strcasecmp(v->name, "channels")) {
17572          if (options & PROC_DAHDI_OPT_NOCHAN) {
17573             ast_log(LOG_WARNING, "Channel '%s' ignored.\n", v->value);
17574             continue;
17575          }
17576          if (build_channels(confp, v->value, reload, v->lineno, &found_pseudo)) {
17577             if (confp->ignore_failed_channels) {
17578                ast_log(LOG_WARNING, "Channel '%s' failure ignored: ignore_failed_channels.\n", v->value);
17579                continue;
17580             } else {
17581                return -1;
17582             }
17583          }
17584          ast_debug(1, "Channel '%s' configured.\n", v->value);
17585       } else if (!strcasecmp(v->name, "ignore_failed_channels")) {
17586          confp->ignore_failed_channels = ast_true(v->value);
17587       } else if (!strcasecmp(v->name, "buffers")) {
17588          if (parse_buffers_policy(v->value, &confp->chan.buf_no, &confp->chan.buf_policy)) {
17589             ast_log(LOG_WARNING, "Using default buffer policy.\n");
17590             confp->chan.buf_no = numbufs;
17591             confp->chan.buf_policy = DAHDI_POLICY_IMMEDIATE;
17592          }
17593       } else if (!strcasecmp(v->name, "faxbuffers")) {
17594          if (!parse_buffers_policy(v->value, &confp->chan.faxbuf_no, &confp->chan.faxbuf_policy)) {
17595             confp->chan.usefaxbuffers = 1;
17596          }
17597       } else if (!strcasecmp(v->name, "dahdichan")) {
17598          /* Only process the last dahdichan value. */
17599          dahdichan = v;
17600       } else if (!strcasecmp(v->name, "usedistinctiveringdetection")) {
17601          usedistinctiveringdetection = ast_true(v->value);
17602       } else if (!strcasecmp(v->name, "distinctiveringaftercid")) {
17603          distinctiveringaftercid = ast_true(v->value);
17604       } else if (!strcasecmp(v->name, "dring1context")) {
17605          ast_copy_string(confp->chan.drings.ringContext[0].contextData,v->value,sizeof(confp->chan.drings.ringContext[0].contextData));
17606       } else if (!strcasecmp(v->name, "dring2context")) {
17607          ast_copy_string(confp->chan.drings.ringContext[1].contextData,v->value,sizeof(confp->chan.drings.ringContext[1].contextData));
17608       } else if (!strcasecmp(v->name, "dring3context")) {
17609          ast_copy_string(confp->chan.drings.ringContext[2].contextData,v->value,sizeof(confp->chan.drings.ringContext[2].contextData));
17610       } else if (!strcasecmp(v->name, "dring1range")) {
17611          confp->chan.drings.ringnum[0].range = atoi(v->value);
17612       } else if (!strcasecmp(v->name, "dring2range")) {
17613          confp->chan.drings.ringnum[1].range = atoi(v->value);
17614       } else if (!strcasecmp(v->name, "dring3range")) {
17615          confp->chan.drings.ringnum[2].range = atoi(v->value);
17616       } else if (!strcasecmp(v->name, "dring1")) {
17617          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]);
17618       } else if (!strcasecmp(v->name, "dring2")) {
17619          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]);
17620       } else if (!strcasecmp(v->name, "dring3")) {
17621          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]);
17622       } else if (!strcasecmp(v->name, "usecallerid")) {
17623          confp->chan.use_callerid = ast_true(v->value);
17624       } else if (!strcasecmp(v->name, "cidsignalling")) {
17625          if (!strcasecmp(v->value, "bell"))
17626             confp->chan.cid_signalling = CID_SIG_BELL;
17627          else if (!strcasecmp(v->value, "v23"))
17628             confp->chan.cid_signalling = CID_SIG_V23;
17629          else if (!strcasecmp(v->value, "dtmf"))
17630             confp->chan.cid_signalling = CID_SIG_DTMF;
17631          else if (!strcasecmp(v->value, "smdi"))
17632             confp->chan.cid_signalling = CID_SIG_SMDI;
17633          else if (!strcasecmp(v->value, "v23_jp"))
17634             confp->chan.cid_signalling = CID_SIG_V23_JP;
17635          else if (ast_true(v->value))
17636             confp->chan.cid_signalling = CID_SIG_BELL;
17637       } else if (!strcasecmp(v->name, "cidstart")) {
17638          if (!strcasecmp(v->value, "ring"))
17639             confp->chan.cid_start = CID_START_RING;
17640          else if (!strcasecmp(v->value, "polarity_in"))
17641             confp->chan.cid_start = CID_START_POLARITY_IN;
17642          else if (!strcasecmp(v->value, "polarity"))
17643             confp->chan.cid_start = CID_START_POLARITY;
17644          else if (!strcasecmp(v->value, "dtmf"))
17645             confp->chan.cid_start = CID_START_DTMF_NOALERT;
17646          else if (ast_true(v->value))
17647             confp->chan.cid_start = CID_START_RING;
17648       } else if (!strcasecmp(v->name, "threewaycalling")) {
17649          confp->chan.threewaycalling = ast_true(v->value);
17650       } else if (!strcasecmp(v->name, "cancallforward")) {
17651          confp->chan.cancallforward = ast_true(v->value);
17652       } else if (!strcasecmp(v->name, "relaxdtmf")) {
17653          if (ast_true(v->value))
17654             confp->chan.dtmfrelax = DSP_DIGITMODE_RELAXDTMF;
17655          else
17656             confp->chan.dtmfrelax = 0;
17657       } else if (!strcasecmp(v->name, "mailbox")) {
17658          ast_copy_string(confp->chan.mailbox, v->value, sizeof(confp->chan.mailbox));
17659       } else if (!strcasecmp(v->name, "description")) {
17660          ast_copy_string(confp->chan.description, v->value, sizeof(confp->chan.description));
17661       } else if (!strcasecmp(v->name, "hasvoicemail")) {
17662          if (ast_true(v->value) && ast_strlen_zero(confp->chan.mailbox)) {
17663             ast_copy_string(confp->chan.mailbox, cat, sizeof(confp->chan.mailbox));
17664          }
17665       } else if (!strcasecmp(v->name, "adsi")) {
17666          confp->chan.adsi = ast_true(v->value);
17667       } else if (!strcasecmp(v->name, "usesmdi")) {
17668          confp->chan.use_smdi = ast_true(v->value);
17669       } else if (!strcasecmp(v->name, "smdiport")) {
17670          ast_copy_string(confp->smdi_port, v->value, sizeof(confp->smdi_port));
17671       } else if (!strcasecmp(v->name, "transfer")) {
17672          confp->chan.transfer = ast_true(v->value);
17673       } else if (!strcasecmp(v->name, "canpark")) {
17674          confp->chan.canpark = ast_true(v->value);
17675       } else if (!strcasecmp(v->name, "echocancelwhenbridged")) {
17676          confp->chan.echocanbridged = ast_true(v->value);
17677       } else if (!strcasecmp(v->name, "busydetect")) {
17678          confp->chan.busydetect = ast_true(v->value);
17679       } else if (!strcasecmp(v->name, "busycount")) {
17680          confp->chan.busycount = atoi(v->value);
17681       } else if (!strcasecmp(v->name, "busypattern")) {
17682          parse_busy_pattern(v, &confp->chan.busy_cadence);
17683       } else if (!strcasecmp(v->name, "callprogress")) {
17684          confp->chan.callprogress &= ~CALLPROGRESS_PROGRESS;
17685          if (ast_true(v->value))
17686             confp->chan.callprogress |= CALLPROGRESS_PROGRESS;
17687       } else if (!strcasecmp(v->name, "waitfordialtone")) {
17688          confp->chan.waitfordialtone = atoi(v->value);
17689       } else if (!strcasecmp(v->name, "dialtone_detect")) {
17690          if (!strcasecmp(v->value, "always")) {
17691             confp->chan.dialtone_detect = -1;
17692          } else if (ast_true(v->value)) {
17693             confp->chan.dialtone_detect = DEFAULT_DIALTONE_DETECT_TIMEOUT;
17694          } else if (ast_false(v->value)) {
17695             confp->chan.dialtone_detect = 0;
17696          } else {
17697             confp->chan.dialtone_detect = ast_strlen_zero(v->value) ? 0 : (8 * atoi(v->value)) / READ_SIZE;
17698          }
17699       } else if (!strcasecmp(v->name, "faxdetect")) {
17700          confp->chan.callprogress &= ~CALLPROGRESS_FAX;
17701          if (!strcasecmp(v->value, "incoming")) {
17702             confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING;
17703          } else if (!strcasecmp(v->value, "outgoing")) {
17704             confp->chan.callprogress |= CALLPROGRESS_FAX_OUTGOING;
17705          } else if (!strcasecmp(v->value, "both") || ast_true(v->value))
17706             confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING;
17707       } else if (!strcasecmp(v->name, "echocancel")) {
17708          process_echocancel(confp, v->value, v->lineno);
17709       } else if (!strcasecmp(v->name, "echotraining")) {
17710          if (sscanf(v->value, "%30d", &y) == 1) {
17711             if ((y < 10) || (y > 4000)) {
17712                ast_log(LOG_WARNING, "Echo training time must be within the range of 10 to 4000 ms at line %d.\n", v->lineno);
17713             } else {
17714                confp->chan.echotraining = y;
17715             }
17716          } else if (ast_true(v->value)) {
17717             confp->chan.echotraining = 400;
17718          } else
17719             confp->chan.echotraining = 0;
17720       } else if (!strcasecmp(v->name, "hidecallerid")) {
17721          confp->chan.hidecallerid = ast_true(v->value);
17722       } else if (!strcasecmp(v->name, "hidecalleridname")) {
17723          confp->chan.hidecalleridname = ast_true(v->value);
17724       } else if (!strcasecmp(v->name, "pulsedial")) {
17725          confp->chan.pulse = ast_true(v->value);
17726       } else if (!strcasecmp(v->name, "callreturn")) {
17727          confp->chan.callreturn = ast_true(v->value);
17728       } else if (!strcasecmp(v->name, "callwaiting")) {
17729          confp->chan.callwaiting = ast_true(v->value);
17730       } else if (!strcasecmp(v->name, "callwaitingcallerid")) {
17731          confp->chan.callwaitingcallerid = ast_true(v->value);
17732       } else if (!strcasecmp(v->name, "context")) {
17733          ast_copy_string(confp->chan.context, v->value, sizeof(confp->chan.context));
17734       } else if (!strcasecmp(v->name, "language")) {
17735          ast_copy_string(confp->chan.language, v->value, sizeof(confp->chan.language));
17736       } else if (!strcasecmp(v->name, "progzone")) {
17737          ast_copy_string(progzone, v->value, sizeof(progzone));
17738       } else if (!strcasecmp(v->name, "mohinterpret")
17739          ||!strcasecmp(v->name, "musiconhold") || !strcasecmp(v->name, "musicclass")) {
17740          ast_copy_string(confp->chan.mohinterpret, v->value, sizeof(confp->chan.mohinterpret));
17741       } else if (!strcasecmp(v->name, "mohsuggest")) {
17742          ast_copy_string(confp->chan.mohsuggest, v->value, sizeof(confp->chan.mohsuggest));
17743       } else if (!strcasecmp(v->name, "parkinglot")) {
17744          ast_copy_string(confp->chan.parkinglot, v->value, sizeof(confp->chan.parkinglot));
17745       } else if (!strcasecmp(v->name, "stripmsd")) {
17746          ast_log(LOG_NOTICE, "Configuration option \"%s\" has been deprecated. Please use dialplan instead\n", v->name);
17747          confp->chan.stripmsd = atoi(v->value);
17748       } else if (!strcasecmp(v->name, "jitterbuffers")) {
17749          numbufs = atoi(v->value);
17750       } else if (!strcasecmp(v->name, "group")) {
17751          confp->chan.group = ast_get_group(v->value);
17752       } else if (!strcasecmp(v->name, "callgroup")) {
17753          if (!strcasecmp(v->value, "none"))
17754             confp->chan.callgroup = 0;
17755          else
17756             confp->chan.callgroup = ast_get_group(v->value);
17757       } else if (!strcasecmp(v->name, "pickupgroup")) {
17758          if (!strcasecmp(v->value, "none"))
17759             confp->chan.pickupgroup = 0;
17760          else
17761             confp->chan.pickupgroup = ast_get_group(v->value);
17762       } else if (!strcasecmp(v->name, "namedcallgroup")) {
17763          confp->chan.named_callgroups = ast_get_namedgroups(v->value);
17764       } else if (!strcasecmp(v->name, "namedpickupgroup")) {
17765          confp->chan.named_pickupgroups = ast_get_namedgroups(v->value);
17766       } else if (!strcasecmp(v->name, "setvar")) {
17767          char *varname = ast_strdupa(v->value), *varval = NULL;
17768          struct ast_variable *tmpvar;
17769          if (varname && (varval = strchr(varname, '='))) {
17770             *varval++ = '\0';
17771             if ((tmpvar = ast_variable_new(varname, varval, ""))) {
17772                tmpvar->next = confp->chan.vars;
17773                confp->chan.vars = tmpvar;
17774             }
17775          }
17776       } else if (!strcasecmp(v->name, "immediate")) {
17777          confp->chan.immediate = ast_true(v->value);
17778       } else if (!strcasecmp(v->name, "transfertobusy")) {
17779          confp->chan.transfertobusy = ast_true(v->value);
17780       } else if (!strcasecmp(v->name, "mwimonitor")) {
17781          confp->chan.mwimonitor_neon = 0;
17782          confp->chan.mwimonitor_fsk = 0;
17783          confp->chan.mwimonitor_rpas = 0;
17784          if (strcasestr(v->value, "fsk")) {
17785             confp->chan.mwimonitor_fsk = 1;
17786          }
17787          if (strcasestr(v->value, "rpas")) {
17788             confp->chan.mwimonitor_rpas = 1;
17789          }
17790          if (strcasestr(v->value, "neon")) {
17791             confp->chan.mwimonitor_neon = 1;
17792          }
17793          /* If set to true or yes, assume that simple fsk is desired */
17794          if (ast_true(v->value)) {
17795             confp->chan.mwimonitor_fsk = 1;
17796          }
17797       } else if (!strcasecmp(v->name, "cid_rxgain")) {
17798          if (sscanf(v->value, "%30f", &confp->chan.cid_rxgain) != 1) {
17799             ast_log(LOG_WARNING, "Invalid cid_rxgain: %s at line %d.\n", v->value, v->lineno);
17800          }
17801       } else if (!strcasecmp(v->name, "rxgain")) {
17802          if (sscanf(v->value, "%30f", &confp->chan.rxgain) != 1) {
17803             ast_log(LOG_WARNING, "Invalid rxgain: %s at line %d.\n", v->value, v->lineno);
17804          }
17805       } else if (!strcasecmp(v->name, "txgain")) {
17806          if (sscanf(v->value, "%30f", &confp->chan.txgain) != 1) {
17807             ast_log(LOG_WARNING, "Invalid txgain: %s at line %d.\n", v->value, v->lineno);
17808          }
17809       } else if (!strcasecmp(v->name, "txdrc")) {
17810          if (sscanf(v->value, "%f", &confp->chan.txdrc) != 1) {
17811             ast_log(LOG_WARNING, "Invalid txdrc: %s\n", v->value);
17812          }
17813       } else if (!strcasecmp(v->name, "rxdrc")) {
17814          if (sscanf(v->value, "%f", &confp->chan.rxdrc) != 1) {
17815             ast_log(LOG_WARNING, "Invalid rxdrc: %s\n", v->value);
17816          }
17817       } else if (!strcasecmp(v->name, "tonezone")) {
17818          if (sscanf(v->value, "%30d", &confp->chan.tonezone) != 1) {
17819             ast_log(LOG_WARNING, "Invalid tonezone: %s at line %d.\n", v->value, v->lineno);
17820          }
17821       } else if (!strcasecmp(v->name, "callerid")) {
17822          if (!strcasecmp(v->value, "asreceived")) {
17823             confp->chan.cid_num[0] = '\0';
17824             confp->chan.cid_name[0] = '\0';
17825          } else {
17826             ast_callerid_split(v->value, confp->chan.cid_name, sizeof(confp->chan.cid_name), confp->chan.cid_num, sizeof(confp->chan.cid_num));
17827          }
17828       } else if (!strcasecmp(v->name, "fullname")) {
17829          ast_copy_string(confp->chan.cid_name, v->value, sizeof(confp->chan.cid_name));
17830       } else if (!strcasecmp(v->name, "cid_number")) {
17831          ast_copy_string(confp->chan.cid_num, v->value, sizeof(confp->chan.cid_num));
17832       } else if (!strcasecmp(v->name, "cid_tag")) {
17833          ast_copy_string(confp->chan.cid_tag, v->value, sizeof(confp->chan.cid_tag));
17834       } else if (!strcasecmp(v->name, "useincomingcalleridondahditransfer")) {
17835          confp->chan.dahditrcallerid = ast_true(v->value);
17836       } else if (!strcasecmp(v->name, "restrictcid")) {
17837          confp->chan.restrictcid = ast_true(v->value);
17838       } else if (!strcasecmp(v->name, "usecallingpres")) {
17839          confp->chan.use_callingpres = ast_true(v->value);
17840       } else if (!strcasecmp(v->name, "accountcode")) {
17841          ast_copy_string(confp->chan.accountcode, v->value, sizeof(confp->chan.accountcode));
17842       } else if (!strcasecmp(v->name, "amaflags")) {
17843          y = ast_cdr_amaflags2int(v->value);
17844          if (y < 0)
17845             ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d.\n", v->value, v->lineno);
17846          else
17847             confp->chan.amaflags = y;
17848       } else if (!strcasecmp(v->name, "polarityonanswerdelay")) {
17849          confp->chan.polarityonanswerdelay = atoi(v->value);
17850       } else if (!strcasecmp(v->name, "answeronpolarityswitch")) {
17851          confp->chan.answeronpolarityswitch = ast_true(v->value);
17852       } else if (!strcasecmp(v->name, "hanguponpolarityswitch")) {
17853          confp->chan.hanguponpolarityswitch = ast_true(v->value);
17854       } else if (!strcasecmp(v->name, "sendcalleridafter")) {
17855          confp->chan.sendcalleridafter = atoi(v->value);
17856       } else if (!strcasecmp(v->name, "mwimonitornotify")) {
17857          ast_copy_string(mwimonitornotify, v->value, sizeof(mwimonitornotify));
17858       } else if (ast_cc_is_config_param(v->name)) {
17859          ast_cc_set_param(confp->chan.cc_params, v->name, v->value);
17860       } else if (!strcasecmp(v->name, "mwisendtype")) {
17861 #ifndef HAVE_DAHDI_LINEREVERSE_VMWI  /* backward compatibility for older dahdi VMWI implementation */
17862          if (!strcasecmp(v->value, "rpas")) { /* Ring Pulse Alert Signal */
17863             mwisend_rpas = 1;
17864          } else {
17865             mwisend_rpas = 0;
17866          }
17867 #else
17868          /* Default is fsk, to turn it off you must specify nofsk */
17869          memset(&confp->chan.mwisend_setting, 0, sizeof(confp->chan.mwisend_setting));
17870          if (strcasestr(v->value, "nofsk")) {      /* NoFSK */
17871             confp->chan.mwisend_fsk = 0;
17872          } else {             /* Default FSK */
17873             confp->chan.mwisend_fsk = 1;
17874          }
17875          if (strcasestr(v->value, "rpas")) {       /* Ring Pulse Alert Signal, normally followed by FSK */
17876             confp->chan.mwisend_rpas = 1;
17877          } else {
17878             confp->chan.mwisend_rpas = 0;
17879          }
17880          if (strcasestr(v->value, "lrev")) {       /* Line Reversal */
17881             confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_LREV;
17882          }
17883          if (strcasestr(v->value, "hvdc")) {       /* HV 90VDC */
17884             confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_HVDC;
17885          }
17886          if ( (strcasestr(v->value, "neon")) || (strcasestr(v->value, "hvac")) ){   /* 90V DC pulses */
17887             confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_HVAC;
17888          }
17889 #endif
17890       } else if (reload != 1) {
17891           if (!strcasecmp(v->name, "signalling") || !strcasecmp(v->name, "signaling")) {
17892             int orig_radio = confp->chan.radio;
17893             int orig_outsigmod = confp->chan.outsigmod;
17894             int orig_auto = confp->is_sig_auto;
17895 
17896             confp->chan.radio = 0;
17897             confp->chan.outsigmod = -1;
17898             confp->is_sig_auto = 0;
17899             if (!strcasecmp(v->value, "em")) {
17900                confp->chan.sig = SIG_EM;
17901             } else if (!strcasecmp(v->value, "em_e1")) {
17902                confp->chan.sig = SIG_EM_E1;
17903             } else if (!strcasecmp(v->value, "em_w")) {
17904                confp->chan.sig = SIG_EMWINK;
17905             } else if (!strcasecmp(v->value, "fxs_ls")) {
17906                confp->chan.sig = SIG_FXSLS;
17907             } else if (!strcasecmp(v->value, "fxs_gs")) {
17908                confp->chan.sig = SIG_FXSGS;
17909             } else if (!strcasecmp(v->value, "fxs_ks")) {
17910                confp->chan.sig = SIG_FXSKS;
17911             } else if (!strcasecmp(v->value, "fxo_ls")) {
17912                confp->chan.sig = SIG_FXOLS;
17913             } else if (!strcasecmp(v->value, "fxo_gs")) {
17914                confp->chan.sig = SIG_FXOGS;
17915             } else if (!strcasecmp(v->value, "fxo_ks")) {
17916                confp->chan.sig = SIG_FXOKS;
17917             } else if (!strcasecmp(v->value, "fxs_rx")) {
17918                confp->chan.sig = SIG_FXSKS;
17919                confp->chan.radio = 1;
17920             } else if (!strcasecmp(v->value, "fxo_rx")) {
17921                confp->chan.sig = SIG_FXOLS;
17922                confp->chan.radio = 1;
17923             } else if (!strcasecmp(v->value, "fxs_tx")) {
17924                confp->chan.sig = SIG_FXSLS;
17925                confp->chan.radio = 1;
17926             } else if (!strcasecmp(v->value, "fxo_tx")) {
17927                confp->chan.sig = SIG_FXOGS;
17928                confp->chan.radio = 1;
17929             } else if (!strcasecmp(v->value, "em_rx")) {
17930                confp->chan.sig = SIG_EM;
17931                confp->chan.radio = 1;
17932             } else if (!strcasecmp(v->value, "em_tx")) {
17933                confp->chan.sig = SIG_EM;
17934                confp->chan.radio = 1;
17935             } else if (!strcasecmp(v->value, "em_rxtx")) {
17936                confp->chan.sig = SIG_EM;
17937                confp->chan.radio = 2;
17938             } else if (!strcasecmp(v->value, "em_txrx")) {
17939                confp->chan.sig = SIG_EM;
17940                confp->chan.radio = 2;
17941             } else if (!strcasecmp(v->value, "sf")) {
17942                confp->chan.sig = SIG_SF;
17943             } else if (!strcasecmp(v->value, "sf_w")) {
17944                confp->chan.sig = SIG_SFWINK;
17945             } else if (!strcasecmp(v->value, "sf_featd")) {
17946                confp->chan.sig = SIG_FEATD;
17947             } else if (!strcasecmp(v->value, "sf_featdmf")) {
17948                confp->chan.sig = SIG_FEATDMF;
17949             } else if (!strcasecmp(v->value, "sf_featb")) {
17950                confp->chan.sig = SIG_SF_FEATB;
17951             } else if (!strcasecmp(v->value, "sf")) {
17952                confp->chan.sig = SIG_SF;
17953             } else if (!strcasecmp(v->value, "sf_rx")) {
17954                confp->chan.sig = SIG_SF;
17955                confp->chan.radio = 1;
17956             } else if (!strcasecmp(v->value, "sf_tx")) {
17957                confp->chan.sig = SIG_SF;
17958                confp->chan.radio = 1;
17959             } else if (!strcasecmp(v->value, "sf_rxtx")) {
17960                confp->chan.sig = SIG_SF;
17961                confp->chan.radio = 2;
17962             } else if (!strcasecmp(v->value, "sf_txrx")) {
17963                confp->chan.sig = SIG_SF;
17964                confp->chan.radio = 2;
17965             } else if (!strcasecmp(v->value, "featd")) {
17966                confp->chan.sig = SIG_FEATD;
17967             } else if (!strcasecmp(v->value, "featdmf")) {
17968                confp->chan.sig = SIG_FEATDMF;
17969             } else if (!strcasecmp(v->value, "featdmf_ta")) {
17970                confp->chan.sig = SIG_FEATDMF_TA;
17971             } else if (!strcasecmp(v->value, "e911")) {
17972                confp->chan.sig = SIG_E911;
17973             } else if (!strcasecmp(v->value, "fgccama")) {
17974                confp->chan.sig = SIG_FGC_CAMA;
17975             } else if (!strcasecmp(v->value, "fgccamamf")) {
17976                confp->chan.sig = SIG_FGC_CAMAMF;
17977             } else if (!strcasecmp(v->value, "featb")) {
17978                confp->chan.sig = SIG_FEATB;
17979 #ifdef HAVE_PRI
17980             } else if (!strcasecmp(v->value, "pri_net")) {
17981                confp->chan.sig = SIG_PRI;
17982                confp->pri.pri.nodetype = PRI_NETWORK;
17983             } else if (!strcasecmp(v->value, "pri_cpe")) {
17984                confp->chan.sig = SIG_PRI;
17985                confp->pri.pri.nodetype = PRI_CPE;
17986             } else if (!strcasecmp(v->value, "bri_cpe")) {
17987                confp->chan.sig = SIG_BRI;
17988                confp->pri.pri.nodetype = PRI_CPE;
17989             } else if (!strcasecmp(v->value, "bri_net")) {
17990                confp->chan.sig = SIG_BRI;
17991                confp->pri.pri.nodetype = PRI_NETWORK;
17992             } else if (!strcasecmp(v->value, "bri_cpe_ptmp")) {
17993                confp->chan.sig = SIG_BRI_PTMP;
17994                confp->pri.pri.nodetype = PRI_CPE;
17995             } else if (!strcasecmp(v->value, "bri_net_ptmp")) {
17996 #if defined(HAVE_PRI_CALL_HOLD)
17997                confp->chan.sig = SIG_BRI_PTMP;
17998                confp->pri.pri.nodetype = PRI_NETWORK;
17999 #else
18000                ast_log(LOG_WARNING, "How cool would it be if someone implemented this mode!  For now, sucks for you. (line %d)\n", v->lineno);
18001 #endif   /* !defined(HAVE_PRI_CALL_HOLD) */
18002 #endif
18003 #if defined(HAVE_SS7)
18004             } else if (!strcasecmp(v->value, "ss7")) {
18005                confp->chan.sig = SIG_SS7;
18006 #endif   /* defined(HAVE_SS7) */
18007 #ifdef HAVE_OPENR2
18008             } else if (!strcasecmp(v->value, "mfcr2")) {
18009                confp->chan.sig = SIG_MFCR2;
18010 #endif
18011             } else if (!strcasecmp(v->value, "auto")) {
18012                confp->is_sig_auto = 1;
18013             } else {
18014                confp->chan.outsigmod = orig_outsigmod;
18015                confp->chan.radio = orig_radio;
18016                confp->is_sig_auto = orig_auto;
18017                ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
18018             }
18019           } else if (!strcasecmp(v->name, "outsignalling") || !strcasecmp(v->name, "outsignaling")) {
18020             if (!strcasecmp(v->value, "em")) {
18021                confp->chan.outsigmod = SIG_EM;
18022             } else if (!strcasecmp(v->value, "em_e1")) {
18023                confp->chan.outsigmod = SIG_EM_E1;
18024             } else if (!strcasecmp(v->value, "em_w")) {
18025                confp->chan.outsigmod = SIG_EMWINK;
18026             } else if (!strcasecmp(v->value, "sf")) {
18027                confp->chan.outsigmod = SIG_SF;
18028             } else if (!strcasecmp(v->value, "sf_w")) {
18029                confp->chan.outsigmod = SIG_SFWINK;
18030             } else if (!strcasecmp(v->value, "sf_featd")) {
18031                confp->chan.outsigmod = SIG_FEATD;
18032             } else if (!strcasecmp(v->value, "sf_featdmf")) {
18033                confp->chan.outsigmod = SIG_FEATDMF;
18034             } else if (!strcasecmp(v->value, "sf_featb")) {
18035                confp->chan.outsigmod = SIG_SF_FEATB;
18036             } else if (!strcasecmp(v->value, "sf")) {
18037                confp->chan.outsigmod = SIG_SF;
18038             } else if (!strcasecmp(v->value, "featd")) {
18039                confp->chan.outsigmod = SIG_FEATD;
18040             } else if (!strcasecmp(v->value, "featdmf")) {
18041                confp->chan.outsigmod = SIG_FEATDMF;
18042             } else if (!strcasecmp(v->value, "featdmf_ta")) {
18043                confp->chan.outsigmod = SIG_FEATDMF_TA;
18044             } else if (!strcasecmp(v->value, "e911")) {
18045                confp->chan.outsigmod = SIG_E911;
18046             } else if (!strcasecmp(v->value, "fgccama")) {
18047                confp->chan.outsigmod = SIG_FGC_CAMA;
18048             } else if (!strcasecmp(v->value, "fgccamamf")) {
18049                confp->chan.outsigmod = SIG_FGC_CAMAMF;
18050             } else if (!strcasecmp(v->value, "featb")) {
18051                confp->chan.outsigmod = SIG_FEATB;
18052             } else {
18053                ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
18054             }
18055 #ifdef HAVE_PRI
18056          } else if (!strcasecmp(v->name, "pridialplan")) {
18057             if (!strcasecmp(v->value, "national")) {
18058                confp->pri.pri.dialplan = PRI_NATIONAL_ISDN + 1;
18059             } else if (!strcasecmp(v->value, "unknown")) {
18060                confp->pri.pri.dialplan = PRI_UNKNOWN + 1;
18061             } else if (!strcasecmp(v->value, "private")) {
18062                confp->pri.pri.dialplan = PRI_PRIVATE + 1;
18063             } else if (!strcasecmp(v->value, "international")) {
18064                confp->pri.pri.dialplan = PRI_INTERNATIONAL_ISDN + 1;
18065             } else if (!strcasecmp(v->value, "local")) {
18066                confp->pri.pri.dialplan = PRI_LOCAL_ISDN + 1;
18067             } else if (!strcasecmp(v->value, "dynamic")) {
18068                confp->pri.pri.dialplan = -1;
18069             } else if (!strcasecmp(v->value, "redundant")) {
18070                confp->pri.pri.dialplan = -2;
18071             } else {
18072                ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno);
18073             }
18074          } else if (!strcasecmp(v->name, "prilocaldialplan")) {
18075             if (!strcasecmp(v->value, "national")) {
18076                confp->pri.pri.localdialplan = PRI_NATIONAL_ISDN + 1;
18077             } else if (!strcasecmp(v->value, "unknown")) {
18078                confp->pri.pri.localdialplan = PRI_UNKNOWN + 1;
18079             } else if (!strcasecmp(v->value, "private")) {
18080                confp->pri.pri.localdialplan = PRI_PRIVATE + 1;
18081             } else if (!strcasecmp(v->value, "international")) {
18082                confp->pri.pri.localdialplan = PRI_INTERNATIONAL_ISDN + 1;
18083             } else if (!strcasecmp(v->value, "local")) {
18084                confp->pri.pri.localdialplan = PRI_LOCAL_ISDN + 1;
18085             } else if (!strcasecmp(v->value, "from_channel")) {
18086                confp->pri.pri.localdialplan = 0;
18087             } else if (!strcasecmp(v->value, "dynamic")) {
18088                confp->pri.pri.localdialplan = -1;
18089             } else if (!strcasecmp(v->value, "redundant")) {
18090                confp->pri.pri.localdialplan = -2;
18091             } else {
18092                ast_log(LOG_WARNING, "Unknown PRI localdialplan '%s' at line %d.\n", v->value, v->lineno);
18093             }
18094          } else if (!strcasecmp(v->name, "pricpndialplan")) {
18095             if (!strcasecmp(v->value, "national")) {
18096                confp->pri.pri.cpndialplan = PRI_NATIONAL_ISDN + 1;
18097             } else if (!strcasecmp(v->value, "unknown")) {
18098                confp->pri.pri.cpndialplan = PRI_UNKNOWN + 1;
18099             } else if (!strcasecmp(v->value, "private")) {
18100                confp->pri.pri.cpndialplan = PRI_PRIVATE + 1;
18101             } else if (!strcasecmp(v->value, "international")) {
18102                confp->pri.pri.cpndialplan = PRI_INTERNATIONAL_ISDN + 1;
18103             } else if (!strcasecmp(v->value, "local")) {
18104                confp->pri.pri.cpndialplan = PRI_LOCAL_ISDN + 1;
18105             } else if (!strcasecmp(v->value, "from_channel")) {
18106                confp->pri.pri.cpndialplan = 0;
18107             } else if (!strcasecmp(v->value, "dynamic")) {
18108                confp->pri.pri.cpndialplan = -1;
18109             } else if (!strcasecmp(v->value, "redundant")) {
18110                confp->pri.pri.cpndialplan = -2;
18111             } else {
18112                ast_log(LOG_WARNING, "Unknown PRI cpndialplan '%s' at line %d.\n", v->value, v->lineno);
18113             }
18114          } else if (!strcasecmp(v->name, "switchtype")) {
18115             if (!strcasecmp(v->value, "national"))
18116                confp->pri.pri.switchtype = PRI_SWITCH_NI2;
18117             else if (!strcasecmp(v->value, "ni1"))
18118                confp->pri.pri.switchtype = PRI_SWITCH_NI1;
18119             else if (!strcasecmp(v->value, "dms100"))
18120                confp->pri.pri.switchtype = PRI_SWITCH_DMS100;
18121             else if (!strcasecmp(v->value, "4ess"))
18122                confp->pri.pri.switchtype = PRI_SWITCH_ATT4ESS;
18123             else if (!strcasecmp(v->value, "5ess"))
18124                confp->pri.pri.switchtype = PRI_SWITCH_LUCENT5E;
18125             else if (!strcasecmp(v->value, "euroisdn"))
18126                confp->pri.pri.switchtype = PRI_SWITCH_EUROISDN_E1;
18127             else if (!strcasecmp(v->value, "qsig"))
18128                confp->pri.pri.switchtype = PRI_SWITCH_QSIG;
18129             else {
18130                ast_log(LOG_ERROR, "Unknown switchtype '%s' at line %d.\n", v->value, v->lineno);
18131                return -1;
18132             }
18133          } else if (!strcasecmp(v->name, "msn")) {
18134             ast_copy_string(confp->pri.pri.msn_list, v->value,
18135                sizeof(confp->pri.pri.msn_list));
18136          } else if (!strcasecmp(v->name, "nsf")) {
18137             if (!strcasecmp(v->value, "sdn"))
18138                confp->pri.pri.nsf = PRI_NSF_SDN;
18139             else if (!strcasecmp(v->value, "megacom"))
18140                confp->pri.pri.nsf = PRI_NSF_MEGACOM;
18141             else if (!strcasecmp(v->value, "tollfreemegacom"))
18142                confp->pri.pri.nsf = PRI_NSF_TOLL_FREE_MEGACOM;
18143             else if (!strcasecmp(v->value, "accunet"))
18144                confp->pri.pri.nsf = PRI_NSF_ACCUNET;
18145             else if (!strcasecmp(v->value, "none"))
18146                confp->pri.pri.nsf = PRI_NSF_NONE;
18147             else {
18148                ast_log(LOG_WARNING, "Unknown network-specific facility '%s' at line %d.\n", v->value, v->lineno);
18149                confp->pri.pri.nsf = PRI_NSF_NONE;
18150             }
18151          } else if (!strcasecmp(v->name, "priindication")) {
18152             if (!strcasecmp(v->value, "outofband"))
18153                confp->chan.priindication_oob = 1;
18154             else if (!strcasecmp(v->value, "inband"))
18155                confp->chan.priindication_oob = 0;
18156             else
18157                ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d.\n",
18158                   v->value, v->lineno);
18159          } else if (!strcasecmp(v->name, "priexclusive")) {
18160             confp->chan.priexclusive = ast_true(v->value);
18161          } else if (!strcasecmp(v->name, "internationalprefix")) {
18162             ast_copy_string(confp->pri.pri.internationalprefix, v->value, sizeof(confp->pri.pri.internationalprefix));
18163          } else if (!strcasecmp(v->name, "nationalprefix")) {
18164             ast_copy_string(confp->pri.pri.nationalprefix, v->value, sizeof(confp->pri.pri.nationalprefix));
18165          } else if (!strcasecmp(v->name, "localprefix")) {
18166             ast_copy_string(confp->pri.pri.localprefix, v->value, sizeof(confp->pri.pri.localprefix));
18167          } else if (!strcasecmp(v->name, "privateprefix")) {
18168             ast_copy_string(confp->pri.pri.privateprefix, v->value, sizeof(confp->pri.pri.privateprefix));
18169          } else if (!strcasecmp(v->name, "unknownprefix")) {
18170             ast_copy_string(confp->pri.pri.unknownprefix, v->value, sizeof(confp->pri.pri.unknownprefix));
18171          } else if (!strcasecmp(v->name, "resetinterval")) {
18172             if (!strcasecmp(v->value, "never"))
18173                confp->pri.pri.resetinterval = -1;
18174             else if (atoi(v->value) >= 60)
18175                confp->pri.pri.resetinterval = atoi(v->value);
18176             else
18177                ast_log(LOG_WARNING, "'%s' is not a valid reset interval, should be >= 60 seconds or 'never' at line %d.\n",
18178                   v->value, v->lineno);
18179          } else if (!strcasecmp(v->name, "minunused")) {
18180             confp->pri.pri.minunused = atoi(v->value);
18181          } else if (!strcasecmp(v->name, "minidle")) {
18182             confp->pri.pri.minidle = atoi(v->value);
18183          } else if (!strcasecmp(v->name, "idleext")) {
18184             ast_copy_string(confp->pri.pri.idleext, v->value, sizeof(confp->pri.pri.idleext));
18185          } else if (!strcasecmp(v->name, "idledial")) {
18186             ast_copy_string(confp->pri.pri.idledial, v->value, sizeof(confp->pri.pri.idledial));
18187          } else if (!strcasecmp(v->name, "overlapdial")) {
18188             if (ast_true(v->value)) {
18189                confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
18190             } else if (!strcasecmp(v->value, "incoming")) {
18191                confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_INCOMING;
18192             } else if (!strcasecmp(v->value, "outgoing")) {
18193                confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_OUTGOING;
18194             } else if (!strcasecmp(v->value, "both") || ast_true(v->value)) {
18195                confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
18196             } else {
18197                confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_NONE;
18198             }
18199 #ifdef HAVE_PRI_PROG_W_CAUSE
18200          } else if (!strcasecmp(v->name, "qsigchannelmapping")) {
18201             if (!strcasecmp(v->value, "logical")) {
18202                confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_LOGICAL;
18203             } else if (!strcasecmp(v->value, "physical")) {
18204                confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL;
18205             } else {
18206                confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL;
18207             }
18208 #endif
18209          } else if (!strcasecmp(v->name, "discardremoteholdretrieval")) {
18210             confp->pri.pri.discardremoteholdretrieval = ast_true(v->value);
18211 #if defined(HAVE_PRI_SERVICE_MESSAGES)
18212          } else if (!strcasecmp(v->name, "service_message_support")) {
18213             /* assuming switchtype for this channel group has been configured already */
18214             if ((confp->pri.pri.switchtype == PRI_SWITCH_ATT4ESS 
18215                || confp->pri.pri.switchtype == PRI_SWITCH_LUCENT5E
18216                || confp->pri.pri.switchtype == PRI_SWITCH_NI2) && ast_true(v->value)) {
18217                confp->pri.pri.enable_service_message_support = 1;
18218             } else {
18219                confp->pri.pri.enable_service_message_support = 0;
18220             }
18221 #endif   /* defined(HAVE_PRI_SERVICE_MESSAGES) */
18222 #ifdef HAVE_PRI_INBANDDISCONNECT
18223          } else if (!strcasecmp(v->name, "inbanddisconnect")) {
18224             confp->pri.pri.inbanddisconnect = ast_true(v->value);
18225 #endif
18226          } else if (!strcasecmp(v->name, "pritimer")) {
18227 #ifdef PRI_GETSET_TIMERS
18228             char tmp[20];
18229             char *timerc;
18230             char *c;
18231             int timer;
18232             int timeridx;
18233 
18234             ast_copy_string(tmp, v->value, sizeof(tmp));
18235             c = tmp;
18236             timerc = strsep(&c, ",");
18237             if (!ast_strlen_zero(timerc) && !ast_strlen_zero(c)) {
18238                timeridx = pri_timer2idx(timerc);
18239                timer = atoi(c);
18240                if (timeridx < 0 || PRI_MAX_TIMERS <= timeridx) {
18241                   ast_log(LOG_WARNING,
18242                      "'%s' is not a valid ISDN timer at line %d.\n", timerc,
18243                      v->lineno);
18244                } else if (!timer) {
18245                   ast_log(LOG_WARNING,
18246                      "'%s' is not a valid value for ISDN timer '%s' at line %d.\n",
18247                      c, timerc, v->lineno);
18248                } else {
18249                   confp->pri.pri.pritimers[timeridx] = timer;
18250                }
18251             } else {
18252                ast_log(LOG_WARNING,
18253                   "'%s' is not a valid ISDN timer configuration string at line %d.\n",
18254                   v->value, v->lineno);
18255             }
18256 #endif /* PRI_GETSET_TIMERS */
18257          } else if (!strcasecmp(v->name, "facilityenable")) {
18258             confp->pri.pri.facilityenable = ast_true(v->value);
18259 #if defined(HAVE_PRI_AOC_EVENTS)
18260          } else if (!strcasecmp(v->name, "aoc_enable")) {
18261             confp->pri.pri.aoc_passthrough_flag = 0;
18262             if (strchr(v->value, 's') || strchr(v->value, 'S')) {
18263                confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_S;
18264             }
18265             if (strchr(v->value, 'd') || strchr(v->value, 'D')) {
18266                confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_D;
18267             }
18268             if (strchr(v->value, 'e') || strchr(v->value, 'E')) {
18269                confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_E;
18270             }
18271          } else if (!strcasecmp(v->name, "aoce_delayhangup")) {
18272             confp->pri.pri.aoce_delayhangup = ast_true(v->value);
18273 #endif   /* defined(HAVE_PRI_AOC_EVENTS) */
18274 #if defined(HAVE_PRI_CALL_HOLD)
18275          } else if (!strcasecmp(v->name, "hold_disconnect_transfer")) {
18276             confp->pri.pri.hold_disconnect_transfer = ast_true(v->value);
18277 #endif   /* defined(HAVE_PRI_CALL_HOLD) */
18278          } else if (!strcasecmp(v->name, "moh_signaling")
18279             || !strcasecmp(v->name, "moh_signalling")) {
18280             if (!strcasecmp(v->value, "moh")) {
18281                confp->pri.pri.moh_signaling = SIG_PRI_MOH_SIGNALING_MOH;
18282             } else if (!strcasecmp(v->value, "notify")) {
18283                confp->pri.pri.moh_signaling = SIG_PRI_MOH_SIGNALING_NOTIFY;
18284 #if defined(HAVE_PRI_CALL_HOLD)
18285             } else if (!strcasecmp(v->value, "hold")) {
18286                confp->pri.pri.moh_signaling = SIG_PRI_MOH_SIGNALING_HOLD;
18287 #endif   /* defined(HAVE_PRI_CALL_HOLD) */
18288             } else {
18289                confp->pri.pri.moh_signaling = SIG_PRI_MOH_SIGNALING_MOH;
18290             }
18291 #if defined(HAVE_PRI_CCSS)
18292          } else if (!strcasecmp(v->name, "cc_ptmp_recall_mode")) {
18293             if (!strcasecmp(v->value, "global")) {
18294                confp->pri.pri.cc_ptmp_recall_mode = 0;/* globalRecall */
18295             } else if (!strcasecmp(v->value, "specific")) {
18296                confp->pri.pri.cc_ptmp_recall_mode = 1;/* specificRecall */
18297             } else {
18298                confp->pri.pri.cc_ptmp_recall_mode = 1;/* specificRecall */
18299             }
18300          } else if (!strcasecmp(v->name, "cc_qsig_signaling_link_req")) {
18301             if (!strcasecmp(v->value, "release")) {
18302                confp->pri.pri.cc_qsig_signaling_link_req = 0;/* release */
18303             } else if (!strcasecmp(v->value, "retain")) {
18304                confp->pri.pri.cc_qsig_signaling_link_req = 1;/* retain */
18305             } else if (!strcasecmp(v->value, "do_not_care")) {
18306                confp->pri.pri.cc_qsig_signaling_link_req = 2;/* do-not-care */
18307             } else {
18308                confp->pri.pri.cc_qsig_signaling_link_req = 1;/* retain */
18309             }
18310          } else if (!strcasecmp(v->name, "cc_qsig_signaling_link_rsp")) {
18311             if (!strcasecmp(v->value, "release")) {
18312                confp->pri.pri.cc_qsig_signaling_link_rsp = 0;/* release */
18313             } else if (!strcasecmp(v->value, "retain")) {
18314                confp->pri.pri.cc_qsig_signaling_link_rsp = 1;/* retain */
18315             } else {
18316                confp->pri.pri.cc_qsig_signaling_link_rsp = 1;/* retain */
18317             }
18318 #endif   /* defined(HAVE_PRI_CCSS) */
18319 #if defined(HAVE_PRI_CALL_WAITING)
18320          } else if (!strcasecmp(v->name, "max_call_waiting_calls")) {
18321             confp->pri.pri.max_call_waiting_calls = atoi(v->value);
18322             if (confp->pri.pri.max_call_waiting_calls < 0) {
18323                /* Negative values are not allowed. */
18324                confp->pri.pri.max_call_waiting_calls = 0;
18325             }
18326          } else if (!strcasecmp(v->name, "allow_call_waiting_calls")) {
18327             confp->pri.pri.allow_call_waiting_calls = ast_true(v->value);
18328 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
18329 #if defined(HAVE_PRI_MWI)
18330          } else if (!strcasecmp(v->name, "mwi_mailboxes")) {
18331             ast_copy_string(confp->pri.pri.mwi_mailboxes, v->value,
18332                sizeof(confp->pri.pri.mwi_mailboxes));
18333          } else if (!strcasecmp(v->name, "mwi_vm_numbers")) {
18334             ast_copy_string(confp->pri.pri.mwi_vm_numbers, v->value,
18335                sizeof(confp->pri.pri.mwi_vm_numbers));
18336 #endif   /* defined(HAVE_PRI_MWI) */
18337          } else if (!strcasecmp(v->name, "append_msn_to_cid_tag")) {
18338             confp->pri.pri.append_msn_to_user_tag = ast_true(v->value);
18339          } else if (!strcasecmp(v->name, "inband_on_setup_ack")) {
18340             confp->pri.pri.inband_on_setup_ack = ast_true(v->value);
18341          } else if (!strcasecmp(v->name, "inband_on_proceeding")) {
18342             confp->pri.pri.inband_on_proceeding = ast_true(v->value);
18343 #if defined(HAVE_PRI_DISPLAY_TEXT)
18344          } else if (!strcasecmp(v->name, "display_send")) {
18345             confp->pri.pri.display_flags_send = dahdi_display_text_option(v->value);
18346          } else if (!strcasecmp(v->name, "display_receive")) {
18347             confp->pri.pri.display_flags_receive = dahdi_display_text_option(v->value);
18348 #endif   /* defined(HAVE_PRI_DISPLAY_TEXT) */
18349 #if defined(HAVE_PRI_MCID)
18350          } else if (!strcasecmp(v->name, "mcid_send")) {
18351             confp->pri.pri.mcid_send = ast_true(v->value);
18352 #endif   /* defined(HAVE_PRI_MCID) */
18353 #if defined(HAVE_PRI_DATETIME_SEND)
18354          } else if (!strcasecmp(v->name, "datetime_send")) {
18355             confp->pri.pri.datetime_send = dahdi_datetime_send_option(v->value);
18356 #endif   /* defined(HAVE_PRI_DATETIME_SEND) */
18357          } else if (!strcasecmp(v->name, "layer1_presence")) {
18358             if (!strcasecmp(v->value, "required")) {
18359                confp->pri.pri.layer1_ignored = 0;
18360             } else if (!strcasecmp(v->value, "ignore")) {
18361                confp->pri.pri.layer1_ignored = 1;
18362             } else {
18363                /* Default */
18364                confp->pri.pri.layer1_ignored = 0;
18365             }
18366 #if defined(HAVE_PRI_L2_PERSISTENCE)
18367          } else if (!strcasecmp(v->name, "layer2_persistence")) {
18368             if (!strcasecmp(v->value, "keep_up")) {
18369                confp->pri.pri.l2_persistence = PRI_L2_PERSISTENCE_KEEP_UP;
18370             } else if (!strcasecmp(v->value, "leave_down")) {
18371                confp->pri.pri.l2_persistence = PRI_L2_PERSISTENCE_LEAVE_DOWN;
18372             } else {
18373                confp->pri.pri.l2_persistence = PRI_L2_PERSISTENCE_DEFAULT;
18374             }
18375 #endif   /* defined(HAVE_PRI_L2_PERSISTENCE) */
18376          } else if (!strcasecmp(v->name, "colp_send")) {
18377             if (!strcasecmp(v->value, "block")) {
18378                confp->pri.pri.colp_send = SIG_PRI_COLP_BLOCK;
18379             } else if (!strcasecmp(v->value, "connect")) {
18380                confp->pri.pri.colp_send = SIG_PRI_COLP_CONNECT;
18381             } else if (!strcasecmp(v->value, "update")) {
18382                confp->pri.pri.colp_send = SIG_PRI_COLP_UPDATE;
18383             } else {
18384                confp->pri.pri.colp_send = SIG_PRI_COLP_UPDATE;
18385             }
18386 #endif /* HAVE_PRI */
18387 #if defined(HAVE_SS7)
18388          } else if (!strcasecmp(v->name, "ss7type")) {
18389             if (!strcasecmp(v->value, "itu")) {
18390                cur_ss7type = SS7_ITU;
18391             } else if (!strcasecmp(v->value, "ansi")) {
18392                cur_ss7type = SS7_ANSI;
18393             } else
18394                ast_log(LOG_WARNING, "'%s' is an unknown ss7 switch type at line %d.!\n", v->value, v->lineno);
18395          } else if (!strcasecmp(v->name, "linkset")) {
18396             cur_linkset = atoi(v->value);
18397          } else if (!strcasecmp(v->name, "pointcode")) {
18398             cur_pointcode = parse_pointcode(v->value);
18399          } else if (!strcasecmp(v->name, "adjpointcode")) {
18400             cur_adjpointcode = parse_pointcode(v->value);
18401          } else if (!strcasecmp(v->name, "defaultdpc")) {
18402             cur_defaultdpc = parse_pointcode(v->value);
18403          } else if (!strcasecmp(v->name, "cicbeginswith")) {
18404             cur_cicbeginswith = atoi(v->value);
18405          } else if (!strcasecmp(v->name, "networkindicator")) {
18406             if (!strcasecmp(v->value, "national"))
18407                cur_networkindicator = SS7_NI_NAT;
18408             else if (!strcasecmp(v->value, "national_spare"))
18409                cur_networkindicator = SS7_NI_NAT_SPARE;
18410             else if (!strcasecmp(v->value, "international"))
18411                cur_networkindicator = SS7_NI_INT;
18412             else if (!strcasecmp(v->value, "international_spare"))
18413                cur_networkindicator = SS7_NI_INT_SPARE;
18414             else
18415                cur_networkindicator = -1;
18416          } else if (!strcasecmp(v->name, "ss7_internationalprefix")) {
18417             ast_copy_string(confp->ss7.ss7.internationalprefix, v->value, sizeof(confp->ss7.ss7.internationalprefix));
18418          } else if (!strcasecmp(v->name, "ss7_nationalprefix")) {
18419             ast_copy_string(confp->ss7.ss7.nationalprefix, v->value, sizeof(confp->ss7.ss7.nationalprefix));
18420          } else if (!strcasecmp(v->name, "ss7_subscriberprefix")) {
18421             ast_copy_string(confp->ss7.ss7.subscriberprefix, v->value, sizeof(confp->ss7.ss7.subscriberprefix));
18422          } else if (!strcasecmp(v->name, "ss7_unknownprefix")) {
18423             ast_copy_string(confp->ss7.ss7.unknownprefix, v->value, sizeof(confp->ss7.ss7.unknownprefix));
18424          } else if (!strcasecmp(v->name, "ss7_called_nai")) {
18425             if (!strcasecmp(v->value, "national")) {
18426                confp->ss7.ss7.called_nai = SS7_NAI_NATIONAL;
18427             } else if (!strcasecmp(v->value, "international")) {
18428                confp->ss7.ss7.called_nai = SS7_NAI_INTERNATIONAL;
18429             } else if (!strcasecmp(v->value, "subscriber")) {
18430                confp->ss7.ss7.called_nai = SS7_NAI_SUBSCRIBER;
18431             } else if (!strcasecmp(v->value, "unknown")) {
18432                confp->ss7.ss7.called_nai = SS7_NAI_UNKNOWN;
18433             } else if (!strcasecmp(v->value, "dynamic")) {
18434                confp->ss7.ss7.called_nai = SS7_NAI_DYNAMIC;
18435             } else {
18436                ast_log(LOG_WARNING, "Unknown SS7 called_nai '%s' at line %d.\n", v->value, v->lineno);
18437             }
18438          } else if (!strcasecmp(v->name, "ss7_calling_nai")) {
18439             if (!strcasecmp(v->value, "national")) {
18440                confp->ss7.ss7.calling_nai = SS7_NAI_NATIONAL;
18441             } else if (!strcasecmp(v->value, "international")) {
18442                confp->ss7.ss7.calling_nai = SS7_NAI_INTERNATIONAL;
18443             } else if (!strcasecmp(v->value, "subscriber")) {
18444                confp->ss7.ss7.calling_nai = SS7_NAI_SUBSCRIBER;
18445             } else if (!strcasecmp(v->value, "unknown")) {
18446                confp->ss7.ss7.calling_nai = SS7_NAI_UNKNOWN;
18447             } else if (!strcasecmp(v->value, "dynamic")) {
18448                confp->ss7.ss7.calling_nai = SS7_NAI_DYNAMIC;
18449             } else {
18450                ast_log(LOG_WARNING, "Unknown SS7 calling_nai '%s' at line %d.\n", v->value, v->lineno);
18451             }
18452          } else if (!strcasecmp(v->name, "sigchan")) {
18453             int sigchan, res;
18454             sigchan = atoi(v->value);
18455             res = linkset_addsigchan(sigchan);
18456             if (res < 0)
18457                return -1;
18458 
18459          } else if (!strcasecmp(v->name, "ss7_explicitacm")) {
18460             struct dahdi_ss7 *link;
18461             link = ss7_resolve_linkset(cur_linkset);
18462             if (!link) {
18463                ast_log(LOG_ERROR, "Invalid linkset number.  Must be between 1 and %d\n", NUM_SPANS + 1);
18464                return -1;
18465             }
18466             if (ast_true(v->value))
18467                link->ss7.flags |= LINKSET_FLAG_EXPLICITACM;
18468 #endif   /* defined(HAVE_SS7) */
18469 #ifdef HAVE_OPENR2
18470          } else if (!strcasecmp(v->name, "mfcr2_advanced_protocol_file")) {
18471             ast_copy_string(confp->mfcr2.r2proto_file, v->value, sizeof(confp->mfcr2.r2proto_file));
18472             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);
18473          } else if (!strcasecmp(v->name, "mfcr2_logdir")) {
18474             ast_copy_string(confp->mfcr2.logdir, v->value, sizeof(confp->mfcr2.logdir));
18475          } else if (!strcasecmp(v->name, "mfcr2_variant")) {
18476             confp->mfcr2.variant = openr2_proto_get_variant(v->value);
18477             if (OR2_VAR_UNKNOWN == confp->mfcr2.variant) {
18478                ast_log(LOG_WARNING, "Unknown MFC/R2 variant '%s' at line %d, defaulting to ITU.\n", v->value, v->lineno);
18479                confp->mfcr2.variant = OR2_VAR_ITU;
18480             }
18481          } else if (!strcasecmp(v->name, "mfcr2_mfback_timeout")) {
18482             confp->mfcr2.mfback_timeout = atoi(v->value);
18483             if (!confp->mfcr2.mfback_timeout) {
18484                ast_log(LOG_WARNING, "MF timeout of 0? hum, I will protect you from your ignorance. Setting default.\n");
18485                confp->mfcr2.mfback_timeout = -1;
18486             } else if (confp->mfcr2.mfback_timeout > 0 && confp->mfcr2.mfback_timeout < 500) {
18487                ast_log(LOG_WARNING, "MF timeout less than 500ms is not recommended, you have been warned!\n");
18488             }
18489          } else if (!strcasecmp(v->name, "mfcr2_metering_pulse_timeout")) {
18490             confp->mfcr2.metering_pulse_timeout = atoi(v->value);
18491             if (confp->mfcr2.metering_pulse_timeout > 500) {
18492                ast_log(LOG_WARNING, "Metering pulse timeout greater than 500ms is not recommended, you have been warned!\n");
18493             }
18494 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2
18495          } else if (!strcasecmp(v->name, "mfcr2_dtmf_detection")) {
18496             confp->mfcr2.dtmf_detection = ast_true(v->value) ? 1 : 0;
18497          } else if (!strcasecmp(v->name, "mfcr2_dtmf_dialing")) {
18498             confp->mfcr2.dtmf_dialing = ast_true(v->value) ? 1 : 0;
18499          } else if (!strcasecmp(v->name, "mfcr2_dtmf_time_on")) {
18500             confp->mfcr2.dtmf_time_on = atoi(v->value);
18501          } else if (!strcasecmp(v->name, "mfcr2_dtmf_time_off")) {
18502             confp->mfcr2.dtmf_time_off = atoi(v->value);
18503 #endif
18504 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 3
18505          } else if (!strcasecmp(v->name, "mfcr2_dtmf_end_timeout")) {
18506             confp->mfcr2.dtmf_end_timeout = atoi(v->value);
18507 #endif
18508          } else if (!strcasecmp(v->name, "mfcr2_get_ani_first")) {
18509             confp->mfcr2.get_ani_first = ast_true(v->value) ? 1 : 0;
18510          } else if (!strcasecmp(v->name, "mfcr2_double_answer")) {
18511             confp->mfcr2.double_answer = ast_true(v->value) ? 1 : 0;
18512          } else if (!strcasecmp(v->name, "mfcr2_charge_calls")) {
18513             confp->mfcr2.charge_calls = ast_true(v->value) ? 1 : 0;
18514          } else if (!strcasecmp(v->name, "mfcr2_accept_on_offer")) {
18515             confp->mfcr2.accept_on_offer = ast_true(v->value) ? 1 : 0;
18516          } else if (!strcasecmp(v->name, "mfcr2_allow_collect_calls")) {
18517             confp->mfcr2.allow_collect_calls = ast_true(v->value) ? 1 : 0;
18518          } else if (!strcasecmp(v->name, "mfcr2_forced_release")) {
18519             confp->mfcr2.forced_release = ast_true(v->value) ? 1 : 0;
18520          } else if (!strcasecmp(v->name, "mfcr2_immediate_accept")) {
18521             confp->mfcr2.immediate_accept = ast_true(v->value) ? 1 : 0;
18522 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
18523          } else if (!strcasecmp(v->name, "mfcr2_skip_category")) {
18524             confp->mfcr2.skip_category_request = ast_true(v->value) ? 1 : 0;
18525 #endif
18526          } else if (!strcasecmp(v->name, "mfcr2_call_files")) {
18527             confp->mfcr2.call_files = ast_true(v->value) ? 1 : 0;
18528          } else if (!strcasecmp(v->name, "mfcr2_max_ani")) {
18529             confp->mfcr2.max_ani = atoi(v->value);
18530             if (confp->mfcr2.max_ani >= AST_MAX_EXTENSION){
18531                confp->mfcr2.max_ani = AST_MAX_EXTENSION - 1;
18532             }
18533          } else if (!strcasecmp(v->name, "mfcr2_max_dnis")) {
18534             confp->mfcr2.max_dnis = atoi(v->value);
18535             if (confp->mfcr2.max_dnis >= AST_MAX_EXTENSION){
18536                confp->mfcr2.max_dnis = AST_MAX_EXTENSION - 1;
18537             }
18538          } else if (!strcasecmp(v->name, "mfcr2_category")) {
18539             confp->mfcr2.category = openr2_proto_get_category(v->value);
18540             if (OR2_CALLING_PARTY_CATEGORY_UNKNOWN == confp->mfcr2.category) {
18541                confp->mfcr2.category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER;
18542                ast_log(LOG_WARNING, "Invalid MFC/R2 caller category '%s' at line %d. Using national subscriber as default.\n",
18543                      v->value, v->lineno);
18544             }
18545          } else if (!strcasecmp(v->name, "mfcr2_logging")) {
18546             openr2_log_level_t tmplevel;
18547             char *clevel;
18548             char *logval = ast_strdupa(v->value);
18549             while (logval) {
18550                clevel = strsep(&logval,",");
18551                if (-1 == (tmplevel = openr2_log_get_level(clevel))) {
18552                   ast_log(LOG_WARNING, "Ignoring invalid logging level: '%s' at line %d.\n", clevel, v->lineno);
18553                   continue;
18554                }
18555                confp->mfcr2.loglevel |= tmplevel;
18556             }
18557 #endif /* HAVE_OPENR2 */
18558          } else if (!strcasecmp(v->name, "cadence")) {
18559             /* setup to scan our argument */
18560             int element_count, c[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
18561             int i;
18562             struct dahdi_ring_cadence new_cadence;
18563             int cid_location = -1;
18564             int firstcadencepos = 0;
18565             char original_args[80];
18566             int cadence_is_ok = 1;
18567 
18568             ast_copy_string(original_args, v->value, sizeof(original_args));
18569             /* 16 cadences allowed (8 pairs) */
18570             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]);
18571 
18572             /* Cadence must be even (on/off) */
18573             if (element_count % 2 == 1) {
18574                ast_log(LOG_ERROR, "Must be a silence duration for each ring duration: %s at line %d.\n", original_args, v->lineno);
18575                cadence_is_ok = 0;
18576             }
18577 
18578             /* Ring cadences cannot be negative */
18579             for (i = 0; i < element_count; i++) {
18580                if (c[i] == 0) {
18581                   ast_log(LOG_ERROR, "Ring or silence duration cannot be zero: %s at line %d.\n", original_args, v->lineno);
18582                   cadence_is_ok = 0;
18583                   break;
18584                } else if (c[i] < 0) {
18585                   if (i % 2 == 1) {
18586                      /* Silence duration, negative possibly okay */
18587                      if (cid_location == -1) {
18588                         cid_location = i;
18589                         c[i] *= -1;
18590                      } else {
18591                         ast_log(LOG_ERROR, "CID location specified twice: %s at line %d.\n", original_args, v->lineno);
18592                         cadence_is_ok = 0;
18593                         break;
18594                      }
18595                   } else {
18596                      if (firstcadencepos == 0) {
18597                         firstcadencepos = i; /* only recorded to avoid duplicate specification */
18598                                  /* duration will be passed negative to the DAHDI driver */
18599                      } else {
18600                          ast_log(LOG_ERROR, "First cadence position specified twice: %s at line %d.\n", original_args, v->lineno);
18601                         cadence_is_ok = 0;
18602                         break;
18603                      }
18604                   }
18605                }
18606             }
18607 
18608             /* Substitute our scanned cadence */
18609             for (i = 0; i < 16; i++) {
18610                new_cadence.ringcadence[i] = c[i];
18611             }
18612 
18613             if (cadence_is_ok) {
18614                /* ---we scanned it without getting annoyed; now some sanity checks--- */
18615                if (element_count < 2) {
18616                   ast_log(LOG_ERROR, "Minimum cadence is ring,pause: %s at line %d.\n", original_args, v->lineno);
18617                } else {
18618                   if (cid_location == -1) {
18619                      /* user didn't say; default to first pause */
18620                      cid_location = 1;
18621                   } else {
18622                      /* convert element_index to cidrings value */
18623                      cid_location = (cid_location + 1) / 2;
18624                   }
18625                   /* ---we like their cadence; try to install it--- */
18626                   if (!user_has_defined_cadences++)
18627                      /* this is the first user-defined cadence; clear the default user cadences */
18628                      num_cadence = 0;
18629                   if ((num_cadence+1) >= NUM_CADENCE_MAX)
18630                      ast_log(LOG_ERROR, "Already %d cadences; can't add another: %s at line %d.\n", NUM_CADENCE_MAX, original_args, v->lineno);
18631                   else {
18632                      cadences[num_cadence] = new_cadence;
18633                      cidrings[num_cadence++] = cid_location;
18634                      ast_verb(3, "cadence 'r%d' added: %s\n",num_cadence,original_args);
18635                   }
18636                }
18637             }
18638          } else if (!strcasecmp(v->name, "ringtimeout")) {
18639             ringt_base = (atoi(v->value) * 8) / READ_SIZE;
18640          } else if (!strcasecmp(v->name, "prewink")) {
18641             confp->timing.prewinktime = atoi(v->value);
18642          } else if (!strcasecmp(v->name, "preflash")) {
18643             confp->timing.preflashtime = atoi(v->value);
18644          } else if (!strcasecmp(v->name, "wink")) {
18645             confp->timing.winktime = atoi(v->value);
18646          } else if (!strcasecmp(v->name, "flash")) {
18647             confp->timing.flashtime = atoi(v->value);
18648          } else if (!strcasecmp(v->name, "start")) {
18649             confp->timing.starttime = atoi(v->value);
18650          } else if (!strcasecmp(v->name, "rxwink")) {
18651             confp->timing.rxwinktime = atoi(v->value);
18652          } else if (!strcasecmp(v->name, "rxflash")) {
18653             confp->timing.rxflashtime = atoi(v->value);
18654          } else if (!strcasecmp(v->name, "debounce")) {
18655             confp->timing.debouncetime = atoi(v->value);
18656          } else if (!strcasecmp(v->name, "toneduration")) {
18657             int toneduration;
18658             int ctlfd;
18659             int res;
18660             struct dahdi_dialparams dps;
18661 
18662             ctlfd = open("/dev/dahdi/ctl", O_RDWR);
18663             if (ctlfd == -1) {
18664                ast_log(LOG_ERROR, "Unable to open /dev/dahdi/ctl to set toneduration at line %d.\n", v->lineno);
18665                return -1;
18666             }
18667 
18668             toneduration = atoi(v->value);
18669             if (toneduration > -1) {
18670                memset(&dps, 0, sizeof(dps));
18671 
18672                dps.dtmf_tonelen = dps.mfv1_tonelen = toneduration;
18673                res = ioctl(ctlfd, DAHDI_SET_DIALPARAMS, &dps);
18674                if (res < 0) {
18675                   ast_log(LOG_ERROR, "Invalid tone duration: %d ms at line %d: %s\n", toneduration, v->lineno, strerror(errno));
18676                   close(ctlfd);
18677                   return -1;
18678                }
18679             }
18680             close(ctlfd);
18681          } else if (!strcasecmp(v->name, "defaultcic")) {
18682             ast_copy_string(defaultcic, v->value, sizeof(defaultcic));
18683          } else if (!strcasecmp(v->name, "defaultozz")) {
18684             ast_copy_string(defaultozz, v->value, sizeof(defaultozz));
18685          } else if (!strcasecmp(v->name, "mwilevel")) {
18686             mwilevel = atoi(v->value);
18687          } else if (!strcasecmp(v->name, "dtmfcidlevel")) {
18688             dtmfcid_level = atoi(v->value);
18689          } else if (!strcasecmp(v->name, "reportalarms")) {
18690             if (!strcasecmp(v->value, "all"))
18691                report_alarms = REPORT_CHANNEL_ALARMS | REPORT_SPAN_ALARMS;
18692             if (!strcasecmp(v->value, "none"))
18693                report_alarms = 0;
18694             else if (!strcasecmp(v->value, "channels"))
18695                report_alarms = REPORT_CHANNEL_ALARMS;
18696             else if (!strcasecmp(v->value, "spans"))
18697                report_alarms = REPORT_SPAN_ALARMS;
18698           }
18699       } else if (!(options & PROC_DAHDI_OPT_NOWARN) )
18700          ast_log(LOG_WARNING, "Ignoring any changes to '%s' (on reload) at line %d.\n", v->name, v->lineno);
18701    }
18702 
18703    /* Since confp has already filled invidual dahdi_pvt objects with channels at this point, clear the variables in confp's pvt. */
18704    if (confp->chan.vars) {
18705       ast_variables_destroy(confp->chan.vars);
18706       confp->chan.vars = NULL;
18707    }
18708 
18709    if (dahdichan) {
18710       /* Process the deferred dahdichan value. */
18711       if (build_channels(confp, dahdichan->value, reload, dahdichan->lineno,
18712          &found_pseudo)) {
18713          if (confp->ignore_failed_channels) {
18714             ast_log(LOG_WARNING,
18715                "Dahdichan '%s' failure ignored: ignore_failed_channels.\n",
18716                dahdichan->value);
18717          } else {
18718             return -1;
18719          }
18720       }
18721    }
18722 
18723    /* mark the first channels of each DAHDI span to watch for their span alarms */
18724    for (tmp = iflist, y=-1; tmp; tmp = tmp->next) {
18725       if (!tmp->destroy && tmp->span != y) {
18726          tmp->manages_span_alarms = 1;
18727          y = tmp->span; 
18728       } else {
18729          tmp->manages_span_alarms = 0;
18730       }
18731    }
18732 
18733    /*< \todo why check for the pseudo in the per-channel section.
18734     * Any actual use for manual setup of the pseudo channel? */
18735    if (!found_pseudo && reload != 1 && !(options & PROC_DAHDI_OPT_NOCHAN)) {
18736       /* use the default configuration for a channel, so
18737          that any settings from real configured channels
18738          don't "leak" into the pseudo channel config
18739       */
18740       struct dahdi_chan_conf conf = dahdi_chan_conf_default();
18741 
18742       if (conf.chan.cc_params) {
18743          tmp = mkintf(CHAN_PSEUDO, &conf, reload);
18744       } else {
18745          tmp = NULL;
18746       }
18747       if (tmp) {
18748          ast_verb(3, "Automatically generated pseudo channel\n");
18749       } else {
18750          ast_log(LOG_WARNING, "Unable to register pseudo channel!\n");
18751       }
18752       ast_cc_config_params_destroy(conf.chan.cc_params);
18753    }
18754 
18755    /* Since named callgroup and named pickup group are ref'd to dahdi_pvt at this point, unref container in confp's pvt. */
18756    confp->chan.named_callgroups = ast_unref_namedgroups(confp->chan.named_callgroups);
18757    confp->chan.named_pickupgroups = ast_unref_namedgroups(confp->chan.named_pickupgroups);
18758 
18759    return 0;
18760 }
18761 
18762 /*!
18763  * \internal
18764  * \brief Deep copy struct dahdi_chan_conf.
18765  * \since 1.8
18766  *
18767  * \param dest Destination.
18768  * \param src Source.
18769  *
18770  * \return Nothing
18771  */
18772 static void deep_copy_dahdi_chan_conf(struct dahdi_chan_conf *dest, const struct dahdi_chan_conf *src)
18773 {
18774    struct ast_cc_config_params *cc_params;
18775 
18776    cc_params = dest->chan.cc_params;
18777    *dest = *src;
18778    dest->chan.cc_params = cc_params;
18779    ast_cc_copy_config_params(dest->chan.cc_params, src->chan.cc_params);
18780 }
18781 
18782 /*!
18783  * \internal
18784  * \brief Setup DAHDI channel driver.
18785  *
18786  * \param reload enum: load_module(0), reload(1), restart(2).
18787  * \param default_conf Default config parameters.  So cc_params can be properly destroyed.
18788  * \param base_conf Default config parameters per section.  So cc_params can be properly destroyed.
18789  * \param conf Local config parameters.  So cc_params can be properly destroyed.
18790  *
18791  * \retval 0 on success.
18792  * \retval -1 on error.
18793  */
18794 static int setup_dahdi_int(int reload, struct dahdi_chan_conf *default_conf, struct dahdi_chan_conf *base_conf, struct dahdi_chan_conf *conf)
18795 {
18796    struct ast_config *cfg;
18797    struct ast_config *ucfg;
18798    struct ast_variable *v;
18799    struct ast_flags config_flags = { reload == 1 ? CONFIG_FLAG_FILEUNCHANGED : 0 };
18800    const char *chans;
18801    const char *cat;
18802    int res;
18803 
18804 #ifdef HAVE_PRI
18805    char *c;
18806    int spanno;
18807    int i;
18808    int logicalspan;
18809    int trunkgroup;
18810    int dchannels[SIG_PRI_NUM_DCHANS];
18811 #endif
18812    int have_cfg_now;
18813    static int had_cfg_before = 1;/* So initial load will complain if we don't have cfg. */
18814 
18815    cfg = ast_config_load(config, config_flags);
18816    have_cfg_now = !!cfg;
18817    if (!cfg) {
18818       /* Error if we have no config file */
18819       if (had_cfg_before) {
18820          ast_log(LOG_ERROR, "Unable to load config %s\n", config);
18821          ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
18822       }
18823       cfg = ast_config_new();/* Dummy config */
18824       if (!cfg) {
18825          return 0;
18826       }
18827       ucfg = ast_config_load("users.conf", config_flags);
18828       if (ucfg == CONFIG_STATUS_FILEUNCHANGED) {
18829          ast_config_destroy(cfg);
18830          return 0;
18831       }
18832       if (ucfg == CONFIG_STATUS_FILEINVALID) {
18833          ast_log(LOG_ERROR, "File users.conf cannot be parsed.  Aborting.\n");
18834          ast_config_destroy(cfg);
18835          return 0;
18836       }
18837    } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
18838       ucfg = ast_config_load("users.conf", config_flags);
18839       if (ucfg == CONFIG_STATUS_FILEUNCHANGED) {
18840          return 0;
18841       }
18842       if (ucfg == CONFIG_STATUS_FILEINVALID) {
18843          ast_log(LOG_ERROR, "File users.conf cannot be parsed.  Aborting.\n");
18844          return 0;
18845       }
18846       ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
18847       cfg = ast_config_load(config, config_flags);
18848       have_cfg_now = !!cfg;
18849       if (!cfg) {
18850          if (had_cfg_before) {
18851             /* We should have been able to load the config. */
18852             ast_log(LOG_ERROR, "Bad. Unable to load config %s\n", config);
18853             ast_config_destroy(ucfg);
18854             return 0;
18855          }
18856          cfg = ast_config_new();/* Dummy config */
18857          if (!cfg) {
18858             ast_config_destroy(ucfg);
18859             return 0;
18860          }
18861       } else if (cfg == CONFIG_STATUS_FILEINVALID) {
18862          ast_log(LOG_ERROR, "File %s cannot be parsed.  Aborting.\n", config);
18863          ast_config_destroy(ucfg);
18864          return 0;
18865       }
18866    } else if (cfg == CONFIG_STATUS_FILEINVALID) {
18867       ast_log(LOG_ERROR, "File %s cannot be parsed.  Aborting.\n", config);
18868       return 0;
18869    } else {
18870       ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
18871       ucfg = ast_config_load("users.conf", config_flags);
18872       if (ucfg == CONFIG_STATUS_FILEINVALID) {
18873          ast_log(LOG_ERROR, "File users.conf cannot be parsed.  Aborting.\n");
18874          ast_config_destroy(cfg);
18875          return 0;
18876       }
18877    }
18878    had_cfg_before = have_cfg_now;
18879 
18880    /* It's a little silly to lock it, but we might as well just to be sure */
18881    ast_mutex_lock(&iflock);
18882 #ifdef HAVE_PRI
18883    if (reload != 1) {
18884       /* Process trunkgroups first */
18885       v = ast_variable_browse(cfg, "trunkgroups");
18886       while (v) {
18887          if (!strcasecmp(v->name, "trunkgroup")) {
18888             trunkgroup = atoi(v->value);
18889             if (trunkgroup > 0) {
18890                if ((c = strchr(v->value, ','))) {
18891                   i = 0;
18892                   memset(dchannels, 0, sizeof(dchannels));
18893                   while (c && (i < SIG_PRI_NUM_DCHANS)) {
18894                      dchannels[i] = atoi(c + 1);
18895                      if (dchannels[i] < 0) {
18896                         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);
18897                      } else
18898                         i++;
18899                      c = strchr(c + 1, ',');
18900                   }
18901                   if (i) {
18902                      if (pri_create_trunkgroup(trunkgroup, dchannels)) {
18903                         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);
18904                   } else
18905                         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");
18906                   } else
18907                      ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
18908                } else
18909                   ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
18910             } else
18911                ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of chan_dahdi.conf\n", v->lineno);
18912          } else if (!strcasecmp(v->name, "spanmap")) {
18913             spanno = atoi(v->value);
18914             if (spanno > 0) {
18915                if ((c = strchr(v->value, ','))) {
18916                   trunkgroup = atoi(c + 1);
18917                   if (trunkgroup > 0) {
18918                      if ((c = strchr(c + 1, ',')))
18919                         logicalspan = atoi(c + 1);
18920                      else
18921                         logicalspan = 0;
18922                      if (logicalspan >= 0) {
18923                         if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) {
18924                            ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
18925                      } else
18926                            ast_verb(2, "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
18927                      } else
18928                         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);
18929                   } else
18930                      ast_log(LOG_WARNING, "Trunk group must be a postive number at line %d of chan_dahdi.conf\n", v->lineno);
18931                } else
18932                   ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of chan_dahdi.conf\n", v->lineno);
18933             } else
18934                ast_log(LOG_WARNING, "Span number must be a postive integer at line %d of chan_dahdi.conf\n", v->lineno);
18935          } else {
18936             ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name);
18937          }
18938          v = v->next;
18939       }
18940    }
18941 #endif
18942 
18943    /* Copy the default jb config over global_jbconf */
18944    memcpy(&global_jbconf, &default_jbconf, sizeof(global_jbconf));
18945 
18946    mwimonitornotify[0] = '\0';
18947 
18948    v = ast_variable_browse(cfg, "channels");
18949    if ((res = process_dahdi(base_conf,
18950       "" /* Must be empty for the channels category.  Silly voicemail mailbox. */,
18951       v, reload, 0))) {
18952       ast_mutex_unlock(&iflock);
18953       ast_config_destroy(cfg);
18954       if (ucfg) {
18955          ast_config_destroy(ucfg);
18956       }
18957       return res;
18958    }
18959 
18960    /* Now get configuration from all normal sections in chan_dahdi.conf: */
18961    for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) {
18962       /* [channels] and [trunkgroups] are used. Let's also reserve
18963        * [globals] and [general] for future use
18964        */
18965       if (!strcasecmp(cat, "general") ||
18966          !strcasecmp(cat, "trunkgroups") ||
18967          !strcasecmp(cat, "globals") ||
18968          !strcasecmp(cat, "channels")) {
18969          continue;
18970       }
18971 
18972       chans = ast_variable_retrieve(cfg, cat, "dahdichan");
18973       if (ast_strlen_zero(chans)) {
18974          /* Section is useless without a dahdichan value present. */
18975          continue;
18976       }
18977 
18978       /* Copy base_conf to conf. */
18979       deep_copy_dahdi_chan_conf(conf, base_conf);
18980 
18981       if ((res = process_dahdi(conf, cat, ast_variable_browse(cfg, cat), reload, PROC_DAHDI_OPT_NOCHAN))) {
18982          ast_mutex_unlock(&iflock);
18983          ast_config_destroy(cfg);
18984          if (ucfg) {
18985             ast_config_destroy(ucfg);
18986          }
18987          return res;
18988       }
18989    }
18990 
18991    ast_config_destroy(cfg);
18992 
18993    if (ucfg) {
18994       /* Reset base_conf, so things don't leak from chan_dahdi.conf */
18995       deep_copy_dahdi_chan_conf(base_conf, default_conf);
18996       process_dahdi(base_conf,
18997          "" /* Must be empty for the general category.  Silly voicemail mailbox. */,
18998          ast_variable_browse(ucfg, "general"), 1, 0);
18999 
19000       for (cat = ast_category_browse(ucfg, NULL); cat ; cat = ast_category_browse(ucfg, cat)) {
19001          if (!strcasecmp(cat, "general")) {
19002             continue;
19003          }
19004 
19005          chans = ast_variable_retrieve(ucfg, cat, "dahdichan");
19006          if (ast_strlen_zero(chans)) {
19007             /* Section is useless without a dahdichan value present. */
19008             continue;
19009          }
19010 
19011          /* Copy base_conf to conf. */
19012          deep_copy_dahdi_chan_conf(conf, base_conf);
19013 
19014          if ((res = process_dahdi(conf, cat, ast_variable_browse(ucfg, cat), reload, PROC_DAHDI_OPT_NOCHAN | PROC_DAHDI_OPT_NOWARN))) {
19015             ast_config_destroy(ucfg);
19016             ast_mutex_unlock(&iflock);
19017             return res;
19018          }
19019       }
19020       ast_config_destroy(ucfg);
19021    }
19022    ast_mutex_unlock(&iflock);
19023 
19024 #ifdef HAVE_PRI
19025    if (reload != 1) {
19026       int x;
19027       for (x = 0; x < NUM_SPANS; x++) {
19028          if (pris[x].pri.pvts[0]) {
19029             prepare_pri(pris + x);
19030             if (sig_pri_start_pri(&pris[x].pri)) {
19031                ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1);
19032                return -1;
19033             } else
19034                ast_verb(2, "Starting D-Channel on span %d\n", x + 1);
19035          }
19036       }
19037    }
19038 #endif
19039 #if defined(HAVE_SS7)
19040    if (reload != 1) {
19041       int x;
19042       for (x = 0; x < NUM_SPANS; x++) {
19043          if (linksets[x].ss7.ss7) {
19044             if (ast_pthread_create(&linksets[x].ss7.master, NULL, ss7_linkset, &linksets[x].ss7)) {
19045                ast_log(LOG_ERROR, "Unable to start SS7 linkset on span %d\n", x + 1);
19046                return -1;
19047             } else
19048                ast_verb(2, "Starting SS7 linkset on span %d\n", x + 1);
19049          }
19050       }
19051    }
19052 #endif   /* defined(HAVE_SS7) */
19053 #ifdef HAVE_OPENR2
19054    if (reload != 1) {
19055       int x;
19056       for (x = 0; x < r2links_count; x++) {
19057          if (ast_pthread_create(&r2links[x]->r2master, NULL, mfcr2_monitor, r2links[x])) {
19058             ast_log(LOG_ERROR, "Unable to start R2 monitor on channel group %d\n", x + 1);
19059             return -1;
19060          } else {
19061             ast_verb(2, "Starting R2 monitor on channel group %d\n", x + 1);
19062          }
19063       }
19064    }
19065 #endif
19066    /* And start the monitor for the first time */
19067    restart_monitor();
19068    return 0;
19069 }
19070 
19071 /*!
19072  * \internal
19073  * \brief Setup DAHDI channel driver.
19074  *
19075  * \param reload enum: load_module(0), reload(1), restart(2).
19076  *
19077  * \retval 0 on success.
19078  * \retval -1 on error.
19079  */
19080 static int setup_dahdi(int reload)
19081 {
19082    int res;
19083    struct dahdi_chan_conf default_conf = dahdi_chan_conf_default();
19084    struct dahdi_chan_conf base_conf = dahdi_chan_conf_default();
19085    struct dahdi_chan_conf conf = dahdi_chan_conf_default();
19086 
19087    if (default_conf.chan.cc_params && base_conf.chan.cc_params && conf.chan.cc_params) {
19088       res = setup_dahdi_int(reload, &default_conf, &base_conf, &conf);
19089    } else {
19090       res = -1;
19091    }
19092    ast_cc_config_params_destroy(default_conf.chan.cc_params);
19093    ast_cc_config_params_destroy(base_conf.chan.cc_params);
19094    ast_cc_config_params_destroy(conf.chan.cc_params);
19095 
19096    return res;
19097 }
19098 
19099 /*!
19100  * \internal
19101  * \brief Callback used to generate the dahdi status tree.
19102  * \param[in] search The search pattern tree.
19103  * \retval NULL on error.
19104  * \retval non-NULL The generated tree.
19105  */
19106 static int dahdi_status_data_provider_get(const struct ast_data_search *search,
19107       struct ast_data *data_root)
19108 {
19109    int ctl, res, span;
19110    struct ast_data *data_span, *data_alarms;
19111    struct dahdi_spaninfo s;
19112 
19113    ctl = open("/dev/dahdi/ctl", O_RDWR);
19114    if (ctl < 0) {
19115       ast_log(LOG_ERROR, "No DAHDI found. Unable to open /dev/dahdi/ctl: %s\n", strerror(errno));
19116       return -1;
19117    }
19118    for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
19119       s.spanno = span;
19120       res = ioctl(ctl, DAHDI_SPANSTAT, &s);
19121       if (res) {
19122          continue;
19123       }
19124 
19125       data_span = ast_data_add_node(data_root, "span");
19126       if (!data_span) {
19127          continue;
19128       }
19129       ast_data_add_str(data_span, "description", s.desc);
19130 
19131       /* insert the alarms status */
19132       data_alarms = ast_data_add_node(data_span, "alarms");
19133       if (!data_alarms) {
19134          continue;
19135       }
19136 
19137       ast_data_add_bool(data_alarms, "BLUE", s.alarms & DAHDI_ALARM_BLUE);
19138       ast_data_add_bool(data_alarms, "YELLOW", s.alarms & DAHDI_ALARM_YELLOW);
19139       ast_data_add_bool(data_alarms, "RED", s.alarms & DAHDI_ALARM_RED);
19140       ast_data_add_bool(data_alarms, "LOOPBACK", s.alarms & DAHDI_ALARM_LOOPBACK);
19141       ast_data_add_bool(data_alarms, "RECOVER", s.alarms & DAHDI_ALARM_RECOVER);
19142       ast_data_add_bool(data_alarms, "NOTOPEN", s.alarms & DAHDI_ALARM_NOTOPEN);
19143 
19144       ast_data_add_int(data_span, "irqmisses", s.irqmisses);
19145       ast_data_add_int(data_span, "bpviol", s.bpvcount);
19146       ast_data_add_int(data_span, "crc4", s.crc4count);
19147       ast_data_add_str(data_span, "framing", s.lineconfig & DAHDI_CONFIG_D4 ? "D4" :
19148                      s.lineconfig & DAHDI_CONFIG_ESF ? "ESF" :
19149                      s.lineconfig & DAHDI_CONFIG_CCS ? "CCS" :
19150                      "CAS");
19151       ast_data_add_str(data_span, "coding",  s.lineconfig & DAHDI_CONFIG_B8ZS ? "B8ZS" :
19152                      s.lineconfig & DAHDI_CONFIG_HDB3 ? "HDB3" :
19153                      s.lineconfig & DAHDI_CONFIG_AMI ? "AMI" :
19154                      "Unknown");
19155       ast_data_add_str(data_span, "options", s.lineconfig & DAHDI_CONFIG_CRC4 ?
19156                      s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" :
19157                      s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "YEL" : "");
19158       ast_data_add_str(data_span, "lbo", lbostr[s.lbo]);
19159 
19160       /* if this span doesn't match remove it. */
19161       if (!ast_data_search_match(search, data_span)) {
19162          ast_data_remove_node(data_root, data_span);
19163       }
19164    }
19165    close(ctl);
19166 
19167    return 0;
19168 }
19169 
19170 /*!
19171  * \internal
19172  * \brief Callback used to generate the dahdi channels tree.
19173  * \param[in] search The search pattern tree.
19174  * \retval NULL on error.
19175  * \retval non-NULL The generated tree.
19176  */
19177 static int dahdi_channels_data_provider_get(const struct ast_data_search *search,
19178       struct ast_data *data_root)
19179 {
19180    struct dahdi_pvt *tmp;
19181    struct ast_data *data_channel;
19182 
19183    ast_mutex_lock(&iflock);
19184    for (tmp = iflist; tmp; tmp = tmp->next) {
19185       data_channel = ast_data_add_node(data_root, "channel");
19186       if (!data_channel) {
19187          continue;
19188       }
19189 
19190       ast_data_add_structure(dahdi_pvt, data_channel, tmp);
19191 
19192       /* if this channel doesn't match remove it. */
19193       if (!ast_data_search_match(search, data_channel)) {
19194          ast_data_remove_node(data_root, data_channel);
19195       }
19196    }
19197    ast_mutex_unlock(&iflock);
19198 
19199    return 0;
19200 }
19201 
19202 /*!
19203  * \internal
19204  * \brief Callback used to generate the dahdi channels tree.
19205  * \param[in] search The search pattern tree.
19206  * \retval NULL on error.
19207  * \retval non-NULL The generated tree.
19208  */
19209 static int dahdi_version_data_provider_get(const struct ast_data_search *search,
19210       struct ast_data *data_root)
19211 {
19212    int pseudo_fd = -1;
19213    struct dahdi_versioninfo vi = {
19214       .version = "Unknown",
19215       .echo_canceller = "Unknown"
19216    };
19217 
19218    if ((pseudo_fd = open("/dev/dahdi/ctl", O_RDONLY)) < 0) {
19219       ast_log(LOG_ERROR, "Failed to open control file to get version.\n");
19220       return -1;
19221    }
19222 
19223    if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi)) {
19224       ast_log(LOG_ERROR, "Failed to get DAHDI version: %s\n", strerror(errno));
19225    }
19226 
19227    close(pseudo_fd);
19228 
19229    ast_data_add_str(data_root, "value", vi.version);
19230    ast_data_add_str(data_root, "echocanceller", vi.echo_canceller);
19231 
19232    return 0;
19233 }
19234 
19235 static const struct ast_data_handler dahdi_status_data_provider = {
19236    .version = AST_DATA_HANDLER_VERSION,
19237    .get = dahdi_status_data_provider_get
19238 };
19239 
19240 static const struct ast_data_handler dahdi_channels_data_provider = {
19241    .version = AST_DATA_HANDLER_VERSION,
19242    .get = dahdi_channels_data_provider_get
19243 };
19244 
19245 static const struct ast_data_handler dahdi_version_data_provider = {
19246    .version = AST_DATA_HANDLER_VERSION,
19247    .get = dahdi_version_data_provider_get
19248 };
19249 
19250 static const struct ast_data_entry dahdi_data_providers[] = {
19251    AST_DATA_ENTRY("asterisk/channel/dahdi/status", &dahdi_status_data_provider),
19252    AST_DATA_ENTRY("asterisk/channel/dahdi/channels", &dahdi_channels_data_provider),
19253    AST_DATA_ENTRY("asterisk/channel/dahdi/version", &dahdi_version_data_provider)
19254 };
19255 
19256 static int load_module(void)
19257 {
19258    int res;
19259    struct ast_format tmpfmt;
19260 #if defined(HAVE_PRI) || defined(HAVE_SS7)
19261    int y;
19262 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
19263 
19264    if (!(dahdi_tech.capabilities = ast_format_cap_alloc())) {
19265       return AST_MODULE_LOAD_FAILURE;
19266    }
19267    ast_format_cap_add(dahdi_tech.capabilities, ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR, 0));
19268    ast_format_cap_add(dahdi_tech.capabilities, ast_format_set(&tmpfmt, AST_FORMAT_ULAW, 0));
19269    ast_format_cap_add(dahdi_tech.capabilities, ast_format_set(&tmpfmt, AST_FORMAT_ALAW, 0));
19270 
19271 #ifdef HAVE_PRI
19272    memset(pris, 0, sizeof(pris));
19273    for (y = 0; y < NUM_SPANS; y++) {
19274       sig_pri_init_pri(&pris[y].pri);
19275    }
19276    pri_set_error(dahdi_pri_error);
19277    pri_set_message(dahdi_pri_message);
19278    ast_register_application_xml(dahdi_send_keypad_facility_app, dahdi_send_keypad_facility_exec);
19279 #ifdef HAVE_PRI_PROG_W_CAUSE
19280    ast_register_application_xml(dahdi_send_callrerouting_facility_app, dahdi_send_callrerouting_facility_exec);
19281 #endif
19282 #if defined(HAVE_PRI_CCSS)
19283    if (ast_cc_agent_register(&dahdi_pri_cc_agent_callbacks)
19284       || ast_cc_monitor_register(&dahdi_pri_cc_monitor_callbacks)) {
19285       __unload_module();
19286       return AST_MODULE_LOAD_FAILURE;
19287    }
19288 #endif   /* defined(HAVE_PRI_CCSS) */
19289    if (sig_pri_load(
19290 #if defined(HAVE_PRI_CCSS)
19291       dahdi_pri_cc_type
19292 #else
19293       NULL
19294 #endif   /* defined(HAVE_PRI_CCSS) */
19295       )) {
19296       __unload_module();
19297       return AST_MODULE_LOAD_FAILURE;
19298    }
19299 #endif
19300 #if defined(HAVE_SS7)
19301    memset(linksets, 0, sizeof(linksets));
19302    for (y = 0; y < NUM_SPANS; y++) {
19303       sig_ss7_init_linkset(&linksets[y].ss7);
19304    }
19305    ss7_set_error(dahdi_ss7_error);
19306    ss7_set_message(dahdi_ss7_message);
19307 #endif   /* defined(HAVE_SS7) */
19308    res = setup_dahdi(0);
19309    /* Make sure we can register our DAHDI channel type */
19310    if (res)
19311       return AST_MODULE_LOAD_DECLINE;
19312    if (ast_channel_register(&dahdi_tech)) {
19313       ast_log(LOG_ERROR, "Unable to register channel class 'DAHDI'\n");
19314       __unload_module();
19315       return AST_MODULE_LOAD_FAILURE;
19316    }
19317 #ifdef HAVE_PRI
19318    ast_cli_register_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
19319 #endif
19320 #if defined(HAVE_SS7)
19321    ast_cli_register_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
19322 #endif   /* defined(HAVE_SS7) */
19323 #ifdef HAVE_OPENR2
19324    ast_cli_register_multiple(dahdi_mfcr2_cli, ARRAY_LEN(dahdi_mfcr2_cli));
19325    ast_register_application_xml(dahdi_accept_r2_call_app, dahdi_accept_r2_call_exec);
19326 #endif
19327 
19328    ast_cli_register_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli));
19329    /* register all the data providers */
19330    ast_data_register_multiple(dahdi_data_providers, ARRAY_LEN(dahdi_data_providers));
19331    memset(round_robin, 0, sizeof(round_robin));
19332    ast_manager_register_xml("DAHDITransfer", 0, action_transfer);
19333    ast_manager_register_xml("DAHDIHangup", 0, action_transferhangup);
19334    ast_manager_register_xml("DAHDIDialOffhook", 0, action_dahdidialoffhook);
19335    ast_manager_register_xml("DAHDIDNDon", 0, action_dahdidndon);
19336    ast_manager_register_xml("DAHDIDNDoff", 0, action_dahdidndoff);
19337    ast_manager_register_xml("DAHDIShowChannels", 0, action_dahdishowchannels);
19338    ast_manager_register_xml("DAHDIRestart", 0, action_dahdirestart);
19339 #if defined(HAVE_PRI)
19340    ast_manager_register_xml("PRIShowSpans", 0, action_prishowspans);
19341 #endif   /* defined(HAVE_PRI) */
19342 
19343    ast_cond_init(&ss_thread_complete, NULL);
19344 
19345    return res;
19346 }
19347 
19348 static int dahdi_sendtext(struct ast_channel *c, const char *text)
19349 {
19350 #define  END_SILENCE_LEN 400
19351 #define  HEADER_MS 50
19352 #define  TRAILER_MS 5
19353 #define  HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8)
19354 #define  ASCII_BYTES_PER_CHAR 80
19355 
19356    unsigned char *buf,*mybuf;
19357    struct dahdi_pvt *p = ast_channel_tech_pvt(c);
19358    struct pollfd fds[1];
19359    int size,res,fd,len,x;
19360    int bytes=0;
19361    int idx;
19362 
19363    /*
19364     * Initial carrier (imaginary)
19365     *
19366     * Note: The following float variables are used by the
19367     * PUT_CLID_MARKMS and PUT_CLID() macros.
19368     */
19369    float cr = 1.0;
19370    float ci = 0.0;
19371    float scont = 0.0;
19372 
19373    if (!text[0]) {
19374       return(0); /* if nothing to send, don't */
19375    }
19376    idx = dahdi_get_index(c, p, 0);
19377    if (idx < 0) {
19378       ast_log(LOG_WARNING, "Huh?  I don't exist?\n");
19379       return -1;
19380    }
19381    if ((!p->tdd) && (!p->mate)) {
19382 #if defined(HAVE_PRI)
19383 #if defined(HAVE_PRI_DISPLAY_TEXT)
19384       ast_mutex_lock(&p->lock);
19385       if (dahdi_sig_pri_lib_handles(p->sig)) {
19386          sig_pri_sendtext(p->sig_pvt, text);
19387       }
19388       ast_mutex_unlock(&p->lock);
19389 #endif   /* defined(HAVE_PRI_DISPLAY_TEXT) */
19390 #endif   /* defined(HAVE_PRI) */
19391       return(0);  /* if not in TDD mode, just return */
19392    }
19393    if (p->mate)
19394       buf = ast_malloc(((strlen(text) + 1) * ASCII_BYTES_PER_CHAR) + END_SILENCE_LEN + HEADER_LEN);
19395    else
19396       buf = ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN);
19397    if (!buf)
19398       return -1;
19399    mybuf = buf;
19400    if (p->mate) {
19401       struct ast_format tmp;
19402       /* PUT_CLI_MARKMS is a macro and requires a format ptr called codec to be present */
19403       struct ast_format *codec = &tmp;
19404       ast_format_set(codec, AST_LAW(p), 0);
19405       for (x = 0; x < HEADER_MS; x++) {   /* 50 ms of Mark */
19406          PUT_CLID_MARKMS;
19407       }
19408       /* Put actual message */
19409       for (x = 0; text[x]; x++) {
19410          PUT_CLID(text[x]);
19411       }
19412       for (x = 0; x < TRAILER_MS; x++) {  /* 5 ms of Mark */
19413          PUT_CLID_MARKMS;
19414       }
19415       len = bytes;
19416       buf = mybuf;
19417    } else {
19418       len = tdd_generate(p->tdd, buf, text);
19419       if (len < 1) {
19420          ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text));
19421          ast_free(mybuf);
19422          return -1;
19423       }
19424    }
19425    memset(buf + len, 0x7f, END_SILENCE_LEN);
19426    len += END_SILENCE_LEN;
19427    fd = p->subs[idx].dfd;
19428    while (len) {
19429       if (ast_check_hangup(c)) {
19430          ast_free(mybuf);
19431          return -1;
19432       }
19433       size = len;
19434       if (size > READ_SIZE)
19435          size = READ_SIZE;
19436       fds[0].fd = fd;
19437       fds[0].events = POLLOUT | POLLPRI;
19438       fds[0].revents = 0;
19439       res = poll(fds, 1, -1);
19440       if (!res) {
19441          ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
19442          continue;
19443       }
19444       /* if got exception */
19445       if (fds[0].revents & POLLPRI) {
19446          ast_free(mybuf);
19447          return -1;
19448       }
19449       if (!(fds[0].revents & POLLOUT)) {
19450          ast_debug(1, "write fd not ready on channel %d\n", p->channel);
19451          continue;
19452       }
19453       res = write(fd, buf, size);
19454       if (res != size) {
19455          if (res == -1) {
19456             ast_free(mybuf);
19457             return -1;
19458          }
19459          ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
19460          break;
19461       }
19462       len -= size;
19463       buf += size;
19464    }
19465    ast_free(mybuf);
19466    return(0);
19467 }
19468 
19469 
19470 static int reload(void)
19471 {
19472    int res = 0;
19473 
19474    res = setup_dahdi(1);
19475    if (res) {
19476       ast_log(LOG_WARNING, "Reload of chan_dahdi.so is unsuccessful!\n");
19477       return -1;
19478    }
19479    return 0;
19480 }
19481 
19482 /* This is a workaround so that menuselect displays a proper description
19483  * AST_MODULE_INFO(, , "DAHDI Telephony"
19484  */
19485 
19486 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, tdesc,
19487    .load = load_module,
19488    .unload = unload_module,
19489    .reload = reload,
19490    .load_pri = AST_MODPRI_CHANNEL_DRIVER,
19491       .nonoptreq = "res_smdi",
19492    );