Sat Apr 26 2014 22:01:30

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: 407818 $")
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_proceeding = 1,
01413 
01414 #if defined(HAVE_PRI_CCSS)
01415          .cc_ptmp_recall_mode = 1,/* specificRecall */
01416          .cc_qsig_signaling_link_req = 1,/* retain */
01417          .cc_qsig_signaling_link_rsp = 1,/* retain */
01418 #endif   /* defined(HAVE_PRI_CCSS) */
01419 
01420          .minunused = 2,
01421          .idleext = "",
01422          .idledial = "",
01423          .internationalprefix = "",
01424          .nationalprefix = "",
01425          .localprefix = "",
01426          .privateprefix = "",
01427          .unknownprefix = "",
01428          .colp_send = SIG_PRI_COLP_UPDATE,
01429          .resetinterval = -1,
01430       },
01431 #endif
01432 #if defined(HAVE_SS7)
01433       .ss7.ss7 = {
01434          .called_nai = SS7_NAI_NATIONAL,
01435          .calling_nai = SS7_NAI_NATIONAL,
01436          .internationalprefix = "",
01437          .nationalprefix = "",
01438          .subscriberprefix = "",
01439          .unknownprefix = ""
01440       },
01441 #endif   /* defined(HAVE_SS7) */
01442 #ifdef HAVE_OPENR2
01443       .mfcr2 = {
01444          .variant = OR2_VAR_ITU,
01445          .mfback_timeout = -1,
01446          .metering_pulse_timeout = -1,
01447          .max_ani = 10,
01448          .max_dnis = 4,
01449          .get_ani_first = -1,
01450 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
01451          .skip_category_request = -1,
01452 #endif
01453          .call_files = 0,
01454          .allow_collect_calls = 0,
01455          .charge_calls = 1,
01456          .accept_on_offer = 1,
01457          .forced_release = 0,
01458          .double_answer = 0,
01459          .immediate_accept = -1,
01460 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2
01461          .dtmf_dialing = -1,
01462          .dtmf_detection = -1,
01463          .dtmf_time_on = OR2_DEFAULT_DTMF_ON,
01464          .dtmf_time_off = OR2_DEFAULT_DTMF_OFF,
01465 #endif
01466 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 3
01467          .dtmf_end_timeout = -1,
01468 #endif
01469          .logdir = "",
01470          .r2proto_file = "",
01471          .loglevel = OR2_LOG_ERROR | OR2_LOG_WARNING,
01472          .category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER
01473       },
01474 #endif
01475       .chan = {
01476          .context = "default",
01477          .cid_num = "",
01478          .cid_name = "",
01479          .cid_tag = "",
01480          .mohinterpret = "default",
01481          .mohsuggest = "",
01482          .parkinglot = "",
01483          .transfertobusy = 1,
01484 
01485          .cid_signalling = CID_SIG_BELL,
01486          .cid_start = CID_START_RING,
01487          .dahditrcallerid = 0,
01488          .use_callerid = 1,
01489          .sig = -1,
01490          .outsigmod = -1,
01491 
01492          .cid_rxgain = +5.0,
01493 
01494          .tonezone = -1,
01495 
01496          .echocancel.head.tap_length = 1,
01497 
01498          .busycount = 3,
01499 
01500          .accountcode = "",
01501 
01502          .mailbox = "",
01503 
01504 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
01505          .mwisend_fsk = 1,
01506 #endif
01507          .polarityonanswerdelay = 600,
01508 
01509          .sendcalleridafter = DEFAULT_CIDRINGS,
01510 
01511          .buf_policy = DAHDI_POLICY_IMMEDIATE,
01512          .buf_no = numbufs,
01513          .usefaxbuffers = 0,
01514          .cc_params = ast_cc_config_params_init(),
01515       },
01516       .timing = {
01517          .prewinktime = -1,
01518          .preflashtime = -1,
01519          .winktime = -1,
01520          .flashtime = -1,
01521          .starttime = -1,
01522          .rxwinktime = -1,
01523          .rxflashtime = -1,
01524          .debouncetime = -1
01525       },
01526       .is_sig_auto = 1,
01527       .smdi_port = "/dev/ttyS0",
01528    };
01529 
01530    return conf;
01531 }
01532 
01533 
01534 static struct ast_channel *dahdi_request(const char *type, struct ast_format_cap *cap, const struct ast_channel *requestor, const char *data, int *cause);
01535 static int dahdi_digit_begin(struct ast_channel *ast, char digit);
01536 static int dahdi_digit_end(struct ast_channel *ast, char digit, unsigned int duration);
01537 static int dahdi_sendtext(struct ast_channel *c, const char *text);
01538 static int dahdi_call(struct ast_channel *ast, const char *rdest, int timeout);
01539 static int dahdi_hangup(struct ast_channel *ast);
01540 static int dahdi_answer(struct ast_channel *ast);
01541 static struct ast_frame *dahdi_read(struct ast_channel *ast);
01542 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame);
01543 static struct ast_frame *dahdi_exception(struct ast_channel *ast);
01544 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen);
01545 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
01546 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen);
01547 static int dahdi_queryoption(struct ast_channel *chan, int option, void *data, int *datalen);
01548 static int dahdi_func_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len);
01549 static int dahdi_func_write(struct ast_channel *chan, const char *function, char *data, const char *value);
01550 static int dahdi_devicestate(const char *data);
01551 static int dahdi_cc_callback(struct ast_channel *inbound, const char *dest, ast_cc_callback_fn callback);
01552 
01553 static struct ast_channel_tech dahdi_tech = {
01554    .type = "DAHDI",
01555    .description = tdesc,
01556    .requester = dahdi_request,
01557    .send_digit_begin = dahdi_digit_begin,
01558    .send_digit_end = dahdi_digit_end,
01559    .send_text = dahdi_sendtext,
01560    .call = dahdi_call,
01561    .hangup = dahdi_hangup,
01562    .answer = dahdi_answer,
01563    .read = dahdi_read,
01564    .write = dahdi_write,
01565    .bridge = dahdi_bridge,
01566    .exception = dahdi_exception,
01567    .indicate = dahdi_indicate,
01568    .fixup = dahdi_fixup,
01569    .setoption = dahdi_setoption,
01570    .queryoption = dahdi_queryoption,
01571    .func_channel_read = dahdi_func_read,
01572    .func_channel_write = dahdi_func_write,
01573    .devicestate = dahdi_devicestate,
01574    .cc_callback = dahdi_cc_callback,
01575 };
01576 
01577 #define GET_CHANNEL(p) ((p)->channel)
01578 
01579 #define SIG_PRI_LIB_HANDLE_CASES \
01580    SIG_PRI:                \
01581    case SIG_BRI:              \
01582    case SIG_BRI_PTMP
01583 
01584 /*!
01585  * \internal
01586  * \brief Determine if sig_pri handles the signaling.
01587  * \since 1.8
01588  *
01589  * \param signaling Signaling to determine if is for sig_pri.
01590  *
01591  * \return TRUE if the signaling is for sig_pri.
01592  */
01593 static inline int dahdi_sig_pri_lib_handles(int signaling)
01594 {
01595    int handles;
01596 
01597    switch (signaling) {
01598    case SIG_PRI_LIB_HANDLE_CASES:
01599       handles = 1;
01600       break;
01601    default:
01602       handles = 0;
01603       break;
01604    }
01605 
01606    return handles;
01607 }
01608 
01609 static int analog_lib_handles(int signalling, int radio, int oprmode)
01610 {
01611    switch (signalling) {
01612    case SIG_FXOLS:
01613    case SIG_FXOGS:
01614    case SIG_FXOKS:
01615    case SIG_FXSLS:
01616    case SIG_FXSGS:
01617    case SIG_FXSKS:
01618    case SIG_EMWINK:
01619    case SIG_EM:
01620    case SIG_EM_E1:
01621    case SIG_FEATD:
01622    case SIG_FEATDMF:
01623    case SIG_E911:
01624    case SIG_FGC_CAMA:
01625    case SIG_FGC_CAMAMF:
01626    case SIG_FEATB:
01627    case SIG_SFWINK:
01628    case SIG_SF:
01629    case SIG_SF_FEATD:
01630    case SIG_SF_FEATDMF:
01631    case SIG_FEATDMF_TA:
01632    case SIG_SF_FEATB:
01633       break;
01634    default:
01635       /* The rest of the function should cover the remainder of signalling types */
01636       return 0;
01637    }
01638 
01639    if (radio) {
01640       return 0;
01641    }
01642 
01643    if (oprmode) {
01644       return 0;
01645    }
01646 
01647    return 1;
01648 }
01649 
01650 static enum analog_sigtype dahdisig_to_analogsig(int sig)
01651 {
01652    switch (sig) {
01653    case SIG_FXOLS:
01654       return ANALOG_SIG_FXOLS;
01655    case SIG_FXOGS:
01656       return ANALOG_SIG_FXOGS;
01657    case SIG_FXOKS:
01658       return ANALOG_SIG_FXOKS;
01659    case SIG_FXSLS:
01660       return ANALOG_SIG_FXSLS;
01661    case SIG_FXSGS:
01662       return ANALOG_SIG_FXSGS;
01663    case SIG_FXSKS:
01664       return ANALOG_SIG_FXSKS;
01665    case SIG_EMWINK:
01666       return ANALOG_SIG_EMWINK;
01667    case SIG_EM:
01668       return ANALOG_SIG_EM;
01669    case SIG_EM_E1:
01670       return ANALOG_SIG_EM_E1;
01671    case SIG_FEATD:
01672       return ANALOG_SIG_FEATD;
01673    case SIG_FEATDMF:
01674       return ANALOG_SIG_FEATDMF;
01675    case SIG_E911:
01676       return SIG_E911;
01677    case SIG_FGC_CAMA:
01678       return ANALOG_SIG_FGC_CAMA;
01679    case SIG_FGC_CAMAMF:
01680       return ANALOG_SIG_FGC_CAMAMF;
01681    case SIG_FEATB:
01682       return ANALOG_SIG_FEATB;
01683    case SIG_SFWINK:
01684       return ANALOG_SIG_SFWINK;
01685    case SIG_SF:
01686       return ANALOG_SIG_SF;
01687    case SIG_SF_FEATD:
01688       return ANALOG_SIG_SF_FEATD;
01689    case SIG_SF_FEATDMF:
01690       return ANALOG_SIG_SF_FEATDMF;
01691    case SIG_FEATDMF_TA:
01692       return ANALOG_SIG_FEATDMF_TA;
01693    case SIG_SF_FEATB:
01694       return ANALOG_SIG_FEATB;
01695    default:
01696       return -1;
01697    }
01698 }
01699 
01700 
01701 static int analog_tone_to_dahditone(enum analog_tone tone)
01702 {
01703    switch (tone) {
01704    case ANALOG_TONE_RINGTONE:
01705       return DAHDI_TONE_RINGTONE;
01706    case ANALOG_TONE_STUTTER:
01707       return DAHDI_TONE_STUTTER;
01708    case ANALOG_TONE_CONGESTION:
01709       return DAHDI_TONE_CONGESTION;
01710    case ANALOG_TONE_DIALTONE:
01711       return DAHDI_TONE_DIALTONE;
01712    case ANALOG_TONE_DIALRECALL:
01713       return DAHDI_TONE_DIALRECALL;
01714    case ANALOG_TONE_INFO:
01715       return DAHDI_TONE_INFO;
01716    default:
01717       return -1;
01718    }
01719 }
01720 
01721 static int analogsub_to_dahdisub(enum analog_sub analogsub)
01722 {
01723    int index;
01724 
01725    switch (analogsub) {
01726    case ANALOG_SUB_REAL:
01727       index = SUB_REAL;
01728       break;
01729    case ANALOG_SUB_CALLWAIT:
01730       index = SUB_CALLWAIT;
01731       break;
01732    case ANALOG_SUB_THREEWAY:
01733       index = SUB_THREEWAY;
01734       break;
01735    default:
01736       ast_log(LOG_ERROR, "Unidentified sub!\n");
01737       index = SUB_REAL;
01738    }
01739 
01740    return index;
01741 }
01742 
01743 static enum analog_event dahdievent_to_analogevent(int event);
01744 static int bump_gains(struct dahdi_pvt *p);
01745 static int dahdi_setlinear(int dfd, int linear);
01746 
01747 static int my_start_cid_detect(void *pvt, int cid_signalling)
01748 {
01749    struct dahdi_pvt *p = pvt;
01750    int index = SUB_REAL;
01751    p->cs = callerid_new(cid_signalling);
01752    if (!p->cs) {
01753       ast_log(LOG_ERROR, "Unable to alloc callerid\n");
01754       return -1;
01755    }
01756    bump_gains(p);
01757    dahdi_setlinear(p->subs[index].dfd, 0);
01758 
01759    return 0;
01760 }
01761 
01762 static int my_stop_cid_detect(void *pvt)
01763 {
01764    struct dahdi_pvt *p = pvt;
01765    int index = SUB_REAL;
01766    if (p->cs)
01767       callerid_free(p->cs);
01768    dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
01769    return 0;
01770 }
01771 
01772 static int my_get_callerid(void *pvt, char *namebuf, char *numbuf, enum analog_event *ev, size_t timeout)
01773 {
01774    struct dahdi_pvt *p = pvt;
01775    struct analog_pvt *analog_p = p->sig_pvt;
01776    struct pollfd poller;
01777    char *name, *num;
01778    int index = SUB_REAL;
01779    int res;
01780    unsigned char buf[256];
01781    int flags;
01782    struct ast_format tmpfmt;
01783 
01784    poller.fd = p->subs[SUB_REAL].dfd;
01785    poller.events = POLLPRI | POLLIN;
01786    poller.revents = 0;
01787 
01788    res = poll(&poller, 1, timeout);
01789 
01790    if (poller.revents & POLLPRI) {
01791       *ev = dahdievent_to_analogevent(dahdi_get_event(p->subs[SUB_REAL].dfd));
01792       return 1;
01793    }
01794 
01795    if (poller.revents & POLLIN) {
01796       /*** NOTES ***/
01797       /* Change API: remove cid_signalling from get_callerid, add a new start_cid_detect and stop_cid_detect function
01798        * to enable slin mode and allocate cid detector. get_callerid should be able to be called any number of times until
01799        * either a timeout occurs or CID is detected (returns 0). returning 1 should be event received, and -1 should be
01800        * a failure and die, and returning 2 means no event was received. */
01801       res = read(p->subs[index].dfd, buf, sizeof(buf));
01802       if (res < 0) {
01803          ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
01804          return -1;
01805       }
01806 
01807       if (analog_p->ringt > 0) {
01808          if (!(--analog_p->ringt)) {
01809             /* only return if we timeout from a ring event */
01810             return -1;
01811          }
01812       }
01813 
01814       if (p->cid_signalling == CID_SIG_V23_JP) {
01815          res = callerid_feed_jp(p->cs, buf, res, ast_format_set(&tmpfmt, AST_LAW(p), 0));
01816       } else {
01817          res = callerid_feed(p->cs, buf, res, ast_format_set(&tmpfmt, AST_LAW(p), 0));
01818       }
01819       if (res < 0) {
01820          /*
01821           * The previous diagnostic message output likely
01822           * explains why it failed.
01823           */
01824          ast_log(LOG_WARNING, "Failed to decode CallerID\n");
01825          return -1;
01826       }
01827 
01828       if (res == 1) {
01829          callerid_get(p->cs, &name, &num, &flags);
01830          if (name)
01831             ast_copy_string(namebuf, name, ANALOG_MAX_CID);
01832          if (num)
01833             ast_copy_string(numbuf, num, ANALOG_MAX_CID);
01834 
01835          ast_debug(1, "CallerID number: %s, name: %s, flags=%d\n", num, name, flags);
01836          return 0;
01837       }
01838    }
01839 
01840    *ev = ANALOG_EVENT_NONE;
01841    return 2;
01842 }
01843 
01844 static const char *event2str(int event);
01845 static int restore_gains(struct dahdi_pvt *p);
01846 
01847 static int my_distinctive_ring(struct ast_channel *chan, void *pvt, int idx, int *ringdata)
01848 {
01849    unsigned char buf[256];
01850    int distMatches;
01851    int curRingData[RING_PATTERNS];
01852    int receivedRingT;
01853    int counter1;
01854    int counter;
01855    int i;
01856    int res;
01857    int checkaftercid = 0;
01858 
01859    struct dahdi_pvt *p = pvt;
01860    struct analog_pvt *analog_p = p->sig_pvt;
01861 
01862    if (ringdata == NULL) {
01863       ringdata = curRingData;
01864    } else {
01865       checkaftercid = 1;
01866    }
01867 
01868    /* We must have a ring by now, so, if configured, lets try to listen for
01869     * distinctive ringing */
01870    if ((checkaftercid && distinctiveringaftercid) || !checkaftercid) {
01871       /* Clear the current ring data array so we don't have old data in it. */
01872       for (receivedRingT = 0; receivedRingT < RING_PATTERNS; receivedRingT++)
01873          ringdata[receivedRingT] = 0;
01874       receivedRingT = 0;
01875       if (checkaftercid && distinctiveringaftercid)
01876          ast_verb(3, "Detecting post-CID distinctive ring\n");
01877       /* Check to see if context is what it should be, if not set to be. */
01878       else if (strcmp(p->context,p->defcontext) != 0) {
01879          ast_copy_string(p->context, p->defcontext, sizeof(p->context));
01880          ast_channel_context_set(chan, p->defcontext);
01881       }
01882 
01883       for (;;) {
01884          i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
01885          if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
01886             ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
01887             ast_hangup(chan);
01888             return 1;
01889          }
01890          if (i & DAHDI_IOMUX_SIGEVENT) {
01891             res = dahdi_get_event(p->subs[idx].dfd);
01892             if (res == DAHDI_EVENT_NOALARM) {
01893                p->inalarm = 0;
01894                analog_p->inalarm = 0;
01895             }
01896             ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
01897             res = 0;
01898             /* Let us detect distinctive ring */
01899 
01900             ringdata[receivedRingT] = analog_p->ringt;
01901 
01902             if (analog_p->ringt < analog_p->ringt_base/2)
01903                break;
01904             /* Increment the ringT counter so we can match it against
01905                values in chan_dahdi.conf for distinctive ring */
01906             if (++receivedRingT == RING_PATTERNS)
01907                break;
01908          } else if (i & DAHDI_IOMUX_READ) {
01909             res = read(p->subs[idx].dfd, buf, sizeof(buf));
01910             if (res < 0) {
01911                if (errno != ELAST) {
01912                   ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
01913                   ast_hangup(chan);
01914                   return 1;
01915                }
01916                break;
01917             }
01918             if (analog_p->ringt > 0) {
01919                if (!(--analog_p->ringt)) {
01920                   res = -1;
01921                   break;
01922                }
01923             }
01924          }
01925       }
01926    }
01927    if ((checkaftercid && usedistinctiveringdetection) || !checkaftercid) {
01928       /* this only shows up if you have n of the dring patterns filled in */
01929       ast_verb(3, "Detected ring pattern: %d,%d,%d\n",ringdata[0],ringdata[1],ringdata[2]);
01930       for (counter = 0; counter < 3; counter++) {
01931       /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this channel */
01932          distMatches = 0;
01933          /* this only shows up if you have n of the dring patterns filled in */
01934          ast_verb(3, "Checking %d,%d,%d\n",
01935                p->drings.ringnum[counter].ring[0],
01936                p->drings.ringnum[counter].ring[1],
01937                p->drings.ringnum[counter].ring[2]);
01938          for (counter1 = 0; counter1 < 3; counter1++) {
01939             ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
01940             if (p->drings.ringnum[counter].ring[counter1] == -1) {
01941                ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
01942                ringdata[counter1]);
01943                distMatches++;
01944             } else if (ringdata[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
01945                               ringdata[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
01946                ast_verb(3, "Ring pattern matched in range: %d to %d\n",
01947                (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
01948                (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
01949                distMatches++;
01950             }
01951          }
01952 
01953          if (distMatches == 3) {
01954             /* The ring matches, set the context to whatever is for distinctive ring.. */
01955             ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context));
01956             ast_channel_context_set(chan, S_OR(p->drings.ringContext[counter].contextData, p->defcontext));
01957             ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
01958             break;
01959          }
01960       }
01961    }
01962    /* Restore linear mode (if appropriate) for Caller*ID processing */
01963    dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
01964    restore_gains(p);
01965 
01966    return 0;
01967 }
01968 
01969 static int my_stop_callwait(void *pvt)
01970 {
01971    struct dahdi_pvt *p = pvt;
01972    p->callwaitingrepeat = 0;
01973    p->cidcwexpire = 0;
01974    p->cid_suppress_expire = 0;
01975 
01976    return 0;
01977 }
01978 
01979 static int send_callerid(struct dahdi_pvt *p);
01980 static int save_conference(struct dahdi_pvt *p);
01981 static int restore_conference(struct dahdi_pvt *p);
01982 
01983 static int my_callwait(void *pvt)
01984 {
01985    struct dahdi_pvt *p = pvt;
01986    struct ast_format tmpfmt;
01987    p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
01988    if (p->cidspill) {
01989       ast_log(LOG_WARNING, "Spill already exists?!?\n");
01990       ast_free(p->cidspill);
01991    }
01992 
01993    /*
01994     * SAS: Subscriber Alert Signal, 440Hz for 300ms
01995     * CAS: CPE Alert Signal, 2130Hz * 2750Hz sine waves
01996     */
01997    if (!(p->cidspill = ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE * 4)))
01998       return -1;
01999    save_conference(p);
02000    /* Silence */
02001    memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
02002    if (!p->callwaitrings && p->callwaitingcallerid) {
02003       ast_gen_cas(p->cidspill, 1, 2400 + 680, ast_format_set(&tmpfmt, AST_LAW(p), 0));
02004       p->callwaitcas = 1;
02005       p->cidlen = 2400 + 680 + READ_SIZE * 4;
02006    } else {
02007       ast_gen_cas(p->cidspill, 1, 2400, ast_format_set(&tmpfmt, AST_LAW(p), 0));
02008       p->callwaitcas = 0;
02009       p->cidlen = 2400 + READ_SIZE * 4;
02010    }
02011    p->cidpos = 0;
02012    send_callerid(p);
02013 
02014    return 0;
02015 }
02016 
02017 static int my_send_callerid(void *pvt, int cwcid, struct ast_party_caller *caller)
02018 {
02019    struct dahdi_pvt *p = pvt;
02020    struct ast_format tmpfmt;
02021 
02022    ast_debug(2, "Starting cid spill\n");
02023 
02024    if (p->cidspill) {
02025       ast_log(LOG_WARNING, "cidspill already exists??\n");
02026       ast_free(p->cidspill);
02027    }
02028 
02029    if ((p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) {
02030       if (cwcid == 0) {
02031          p->cidlen = ast_callerid_generate(p->cidspill,
02032             caller->id.name.str,
02033             caller->id.number.str,
02034             ast_format_set(&tmpfmt, AST_LAW(p), 0));
02035       } else {
02036          ast_verb(3, "CPE supports Call Waiting Caller*ID.  Sending '%s/%s'\n",
02037             caller->id.name.str, caller->id.number.str);
02038          p->callwaitcas = 0;
02039          p->cidcwexpire = 0;
02040          p->cidlen = ast_callerid_callwaiting_generate(p->cidspill,
02041             caller->id.name.str,
02042             caller->id.number.str,
02043             ast_format_set(&tmpfmt, AST_LAW(p), 0));
02044          p->cidlen += READ_SIZE * 4;
02045       }
02046       p->cidpos = 0;
02047       p->cid_suppress_expire = 0;
02048       send_callerid(p);
02049    }
02050    return 0;
02051 }
02052 
02053 static int my_dsp_reset_and_flush_digits(void *pvt)
02054 {
02055    struct dahdi_pvt *p = pvt;
02056    if (p->dsp)
02057       ast_dsp_digitreset(p->dsp);
02058 
02059    return 0;
02060 }
02061 
02062 static int my_dsp_set_digitmode(void *pvt, enum analog_dsp_digitmode mode)
02063 {
02064    struct dahdi_pvt *p = pvt;
02065 
02066    if (p->channel == CHAN_PSEUDO)
02067       ast_log(LOG_ERROR, "You have assumed incorrectly sir!\n");
02068 
02069    if (mode == ANALOG_DIGITMODE_DTMF) {
02070       /* If we do hardware dtmf, no need for a DSP */
02071       if (p->hardwaredtmf) {
02072          if (p->dsp) {
02073             ast_dsp_free(p->dsp);
02074             p->dsp = NULL;
02075          }
02076          return 0;
02077       }
02078 
02079       if (!p->dsp) {
02080          p->dsp = ast_dsp_new();
02081          if (!p->dsp) {
02082             ast_log(LOG_ERROR, "Unable to allocate DSP\n");
02083             return -1;
02084          }
02085       }
02086 
02087       ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
02088    } else if (mode == ANALOG_DIGITMODE_MF) {
02089       if (!p->dsp) {
02090          p->dsp = ast_dsp_new();
02091          if (!p->dsp) {
02092             ast_log(LOG_ERROR, "Unable to allocate DSP\n");
02093             return -1;
02094          }
02095       }
02096       ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
02097    }
02098    return 0;
02099 }
02100 
02101 static int dahdi_wink(struct dahdi_pvt *p, int index);
02102 
02103 static int my_wink(void *pvt, enum analog_sub sub)
02104 {
02105    struct dahdi_pvt *p = pvt;
02106    int index = analogsub_to_dahdisub(sub);
02107    if (index != SUB_REAL) {
02108       ast_log(LOG_ERROR, "We used a sub other than SUB_REAL (incorrect assumption sir)\n");
02109    }
02110    return dahdi_wink(p, index);
02111 }
02112 
02113 static void wakeup_sub(struct dahdi_pvt *p, int a);
02114 
02115 static int reset_conf(struct dahdi_pvt *p);
02116 
02117 static inline int dahdi_confmute(struct dahdi_pvt *p, int muted);
02118 
02119 static void my_handle_dtmf(void *pvt, struct ast_channel *ast, enum analog_sub analog_index, struct ast_frame **dest)
02120 {
02121    struct ast_frame *f = *dest;
02122    struct dahdi_pvt *p = pvt;
02123    int idx = analogsub_to_dahdisub(analog_index);
02124 
02125    ast_debug(1, "%s DTMF digit: 0x%02X '%c' on %s\n",
02126       f->frametype == AST_FRAME_DTMF_BEGIN ? "Begin" : "End",
02127       f->subclass.integer, f->subclass.integer, ast_channel_name(ast));
02128 
02129    if (f->subclass.integer == 'f') {
02130       if (f->frametype == AST_FRAME_DTMF_END) {
02131          /* Fax tone -- Handle and return NULL */
02132          if ((p->callprogress & CALLPROGRESS_FAX) && !p->faxhandled) {
02133             /* If faxbuffers are configured, use them for the fax transmission */
02134             if (p->usefaxbuffers && !p->bufferoverrideinuse) {
02135                struct dahdi_bufferinfo bi = {
02136                   .txbufpolicy = p->faxbuf_policy,
02137                   .bufsize = p->bufsize,
02138                   .numbufs = p->faxbuf_no
02139                };
02140                int res;
02141 
02142                if ((res = ioctl(p->subs[idx].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
02143                   ast_log(LOG_WARNING, "Channel '%s' unable to set buffer policy, reason: %s\n", ast_channel_name(ast), strerror(errno));
02144                } else {
02145                   p->bufferoverrideinuse = 1;
02146                }
02147             }
02148             p->faxhandled = 1;
02149             if (p->dsp) {
02150                p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
02151                ast_dsp_set_features(p->dsp, p->dsp_features);
02152                ast_debug(1, "Disabling FAX tone detection on %s after tone received\n", ast_channel_name(ast));
02153             }
02154             if (strcmp(ast_channel_exten(ast), "fax")) {
02155                const char *target_context = S_OR(ast_channel_macrocontext(ast), ast_channel_context(ast));
02156 
02157                /* We need to unlock 'ast' here because ast_exists_extension has the
02158                 * potential to start autoservice on the channel. Such action is prone
02159                 * to deadlock.
02160                 */
02161                ast_mutex_unlock(&p->lock);
02162                ast_channel_unlock(ast);
02163                if (ast_exists_extension(ast, target_context, "fax", 1,
02164                   S_COR(ast_channel_caller(ast)->id.number.valid, ast_channel_caller(ast)->id.number.str, NULL))) {
02165                   ast_channel_lock(ast);
02166                   ast_mutex_lock(&p->lock);
02167                   ast_verb(3, "Redirecting %s to fax extension\n", ast_channel_name(ast));
02168                   /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
02169                   pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast_channel_exten(ast));
02170                   if (ast_async_goto(ast, target_context, "fax", 1))
02171                      ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast_channel_name(ast), target_context);
02172                } else {
02173                   ast_channel_lock(ast);
02174                   ast_mutex_lock(&p->lock);
02175                   ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
02176                }
02177             } else {
02178                ast_debug(1, "Already in a fax extension, not redirecting\n");
02179             }
02180          } else {
02181             ast_debug(1, "Fax already handled\n");
02182          }
02183          dahdi_confmute(p, 0);
02184       }
02185       p->subs[idx].f.frametype = AST_FRAME_NULL;
02186       p->subs[idx].f.subclass.integer = 0;
02187       *dest = &p->subs[idx].f;
02188    }
02189 }
02190 
02191 static void my_lock_private(void *pvt)
02192 {
02193    struct dahdi_pvt *p = pvt;
02194    ast_mutex_lock(&p->lock);
02195 }
02196 
02197 static void my_unlock_private(void *pvt)
02198 {
02199    struct dahdi_pvt *p = pvt;
02200    ast_mutex_unlock(&p->lock);
02201 }
02202 
02203 static void my_deadlock_avoidance_private(void *pvt)
02204 {
02205    struct dahdi_pvt *p = pvt;
02206 
02207    DEADLOCK_AVOIDANCE(&p->lock);
02208 }
02209 
02210 /*!
02211  * \internal
02212  * \brief Post an AMI DAHDI channel association event.
02213  * \since 1.8
02214  *
02215  * \param p DAHDI private pointer
02216  * \param chan Channel associated with the private pointer
02217  *
02218  * \return Nothing
02219  */
02220 static void dahdi_ami_channel_event(struct dahdi_pvt *p, struct ast_channel *chan)
02221 {
02222    char ch_name[20];
02223 
02224    if (p->channel < CHAN_PSEUDO) {
02225       /* No B channel */
02226       snprintf(ch_name, sizeof(ch_name), "no-media (%d)", p->channel);
02227    } else if (p->channel == CHAN_PSEUDO) {
02228       /* Pseudo channel */
02229       strcpy(ch_name, "pseudo");
02230    } else {
02231       /* Real channel */
02232       snprintf(ch_name, sizeof(ch_name), "%d", p->channel);
02233    }
02234    /*** DOCUMENTATION
02235       <managerEventInstance>
02236          <synopsis>Raised when a DAHDI channel is created or an underlying technology is associated with a DAHDI channel.</synopsis>
02237       </managerEventInstance>
02238    ***/
02239    ast_manager_event(chan, EVENT_FLAG_CALL, "DAHDIChannel",
02240       "Channel: %s\r\n"
02241       "Uniqueid: %s\r\n"
02242       "DAHDISpan: %d\r\n"
02243       "DAHDIChannel: %s\r\n",
02244       ast_channel_name(chan),
02245       ast_channel_uniqueid(chan),
02246       p->span,
02247       ch_name);
02248 }
02249 
02250 #ifdef HAVE_PRI
02251 /*!
02252  * \internal
02253  * \brief Post an AMI DAHDI channel association event.
02254  * \since 1.8
02255  *
02256  * \param pvt DAHDI private pointer
02257  * \param chan Channel associated with the private pointer
02258  *
02259  * \return Nothing
02260  */
02261 static void my_ami_channel_event(void *pvt, struct ast_channel *chan)
02262 {
02263    struct dahdi_pvt *p = pvt;
02264 
02265    dahdi_ami_channel_event(p, chan);
02266 }
02267 #endif
02268 
02269 /* linear_mode = 0 - turn linear mode off, >0 - turn linear mode on
02270 *  returns the last value of the linear setting 
02271 */ 
02272 static int my_set_linear_mode(void *pvt, enum analog_sub sub, int linear_mode)
02273 {
02274    struct dahdi_pvt *p = pvt;
02275    int oldval;
02276    int idx = analogsub_to_dahdisub(sub);
02277    
02278    dahdi_setlinear(p->subs[idx].dfd, linear_mode);
02279    oldval = p->subs[idx].linear;
02280    p->subs[idx].linear = linear_mode ? 1 : 0;
02281    return oldval;
02282 }
02283 
02284 static void my_set_inthreeway(void *pvt, enum analog_sub sub, int inthreeway)
02285 {
02286    struct dahdi_pvt *p = pvt;
02287    int idx = analogsub_to_dahdisub(sub);
02288 
02289    p->subs[idx].inthreeway = inthreeway;
02290 }
02291 
02292 static int get_alarms(struct dahdi_pvt *p);
02293 static void handle_alarms(struct dahdi_pvt *p, int alms);
02294 static void my_get_and_handle_alarms(void *pvt)
02295 {
02296    int res;
02297    struct dahdi_pvt *p = pvt;
02298 
02299    res = get_alarms(p);
02300    handle_alarms(p, res);
02301 }
02302 
02303 static void *my_get_sigpvt_bridged_channel(struct ast_channel *chan)
02304 {
02305    struct ast_channel *bridged = ast_bridged_channel(chan);
02306 
02307    if (bridged && ast_channel_tech(bridged) == &dahdi_tech) {
02308       struct dahdi_pvt *p = ast_channel_tech_pvt(bridged);
02309 
02310       if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
02311          return p->sig_pvt;
02312       }
02313    }
02314    return NULL;
02315 }
02316 
02317 static int my_get_sub_fd(void *pvt, enum analog_sub sub)
02318 {
02319    struct dahdi_pvt *p = pvt;
02320    int dahdi_sub = analogsub_to_dahdisub(sub);
02321    return p->subs[dahdi_sub].dfd;
02322 }
02323 
02324 static void my_set_cadence(void *pvt, int *cid_rings, struct ast_channel *ast)
02325 {
02326    struct dahdi_pvt *p = pvt;
02327 
02328    /* Choose proper cadence */
02329    if ((p->distinctivering > 0) && (p->distinctivering <= num_cadence)) {
02330       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &cadences[p->distinctivering - 1]))
02331          ast_log(LOG_WARNING, "Unable to set distinctive ring cadence %d on '%s': %s\n", p->distinctivering, ast_channel_name(ast), strerror(errno));
02332       *cid_rings = cidrings[p->distinctivering - 1];
02333    } else {
02334       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, NULL))
02335          ast_log(LOG_WARNING, "Unable to reset default ring on '%s': %s\n", ast_channel_name(ast), strerror(errno));
02336       *cid_rings = p->sendcalleridafter;
02337    }
02338 }
02339 
02340 static void my_set_alarm(void *pvt, int in_alarm)
02341 {
02342    struct dahdi_pvt *p = pvt;
02343 
02344    p->inalarm = in_alarm;
02345 }
02346 
02347 static void my_set_dialing(void *pvt, int is_dialing)
02348 {
02349    struct dahdi_pvt *p = pvt;
02350 
02351    p->dialing = is_dialing;
02352 }
02353 
02354 static void my_set_outgoing(void *pvt, int is_outgoing)
02355 {
02356    struct dahdi_pvt *p = pvt;
02357 
02358    p->outgoing = is_outgoing;
02359 }
02360 
02361 #if defined(HAVE_PRI) || defined(HAVE_SS7)
02362 static void my_set_digital(void *pvt, int is_digital)
02363 {
02364    struct dahdi_pvt *p = pvt;
02365 
02366    p->digital = is_digital;
02367 }
02368 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
02369 
02370 #if defined(HAVE_SS7)
02371 static void my_set_inservice(void *pvt, int is_inservice)
02372 {
02373    struct dahdi_pvt *p = pvt;
02374 
02375    p->inservice = is_inservice;
02376 }
02377 #endif   /* defined(HAVE_SS7) */
02378 
02379 #if defined(HAVE_SS7)
02380 static void my_set_locallyblocked(void *pvt, int is_blocked)
02381 {
02382    struct dahdi_pvt *p = pvt;
02383 
02384    p->locallyblocked = is_blocked;
02385 }
02386 #endif   /* defined(HAVE_SS7) */
02387 
02388 #if defined(HAVE_SS7)
02389 static void my_set_remotelyblocked(void *pvt, int is_blocked)
02390 {
02391    struct dahdi_pvt *p = pvt;
02392 
02393    p->remotelyblocked = is_blocked;
02394 }
02395 #endif   /* defined(HAVE_SS7) */
02396 
02397 static void my_set_ringtimeout(void *pvt, int ringt)
02398 {
02399    struct dahdi_pvt *p = pvt;
02400    p->ringt = ringt;
02401 }
02402 
02403 static void my_set_waitingfordt(void *pvt, struct ast_channel *ast)
02404 {
02405    struct dahdi_pvt *p = pvt;
02406 
02407    if (p->waitfordialtone && CANPROGRESSDETECT(p) && p->dsp) {
02408       ast_debug(1, "Defer dialing for %dms or dialtone\n", p->waitfordialtone);
02409       gettimeofday(&p->waitingfordt, NULL);
02410       ast_setstate(ast, AST_STATE_OFFHOOK);
02411    }
02412 }
02413 
02414 static int my_check_waitingfordt(void *pvt)
02415 {
02416    struct dahdi_pvt *p = pvt;
02417 
02418    if (p->waitingfordt.tv_usec) {
02419       return 1;
02420    }
02421 
02422    return 0;
02423 }
02424 
02425 static void my_set_confirmanswer(void *pvt, int flag)
02426 {
02427    struct dahdi_pvt *p = pvt;
02428    p->confirmanswer = flag;
02429 }
02430 
02431 static int my_check_confirmanswer(void *pvt)
02432 {
02433    struct dahdi_pvt *p = pvt;
02434    if (p->confirmanswer) {
02435       return 1;
02436    }
02437 
02438    return 0;
02439 }
02440 
02441 static void my_set_callwaiting(void *pvt, int callwaiting_enable)
02442 {
02443    struct dahdi_pvt *p = pvt;
02444 
02445    p->callwaiting = callwaiting_enable;
02446 }
02447 
02448 static void my_cancel_cidspill(void *pvt)
02449 {
02450    struct dahdi_pvt *p = pvt;
02451 
02452    ast_free(p->cidspill);
02453    p->cidspill = NULL;
02454    restore_conference(p);
02455 }
02456 
02457 static int my_confmute(void *pvt, int mute)
02458 {
02459    struct dahdi_pvt *p = pvt;
02460    return dahdi_confmute(p, mute);
02461 }
02462 
02463 static void my_set_pulsedial(void *pvt, int flag)
02464 {
02465    struct dahdi_pvt *p = pvt;
02466    p->pulsedial = flag;
02467 }
02468 
02469 static void my_set_new_owner(void *pvt, struct ast_channel *new_owner)
02470 {
02471    struct dahdi_pvt *p = pvt;
02472 
02473    p->owner = new_owner;
02474 }
02475 
02476 static const char *my_get_orig_dialstring(void *pvt)
02477 {
02478    struct dahdi_pvt *p = pvt;
02479 
02480    return p->dialstring;
02481 }
02482 
02483 static void my_increase_ss_count(void)
02484 {
02485    ast_mutex_lock(&ss_thread_lock);
02486    ss_thread_count++;
02487    ast_mutex_unlock(&ss_thread_lock);
02488 }
02489 
02490 static void my_decrease_ss_count(void)
02491 {
02492    ast_mutex_lock(&ss_thread_lock);
02493    ss_thread_count--;
02494    ast_cond_signal(&ss_thread_complete);
02495    ast_mutex_unlock(&ss_thread_lock);
02496 }
02497 
02498 static void my_all_subchannels_hungup(void *pvt)
02499 {
02500    struct dahdi_pvt *p = pvt;
02501    int res, law;
02502 
02503    p->faxhandled = 0;
02504    p->didtdd = 0;
02505 
02506    if (p->dsp) {
02507       ast_dsp_free(p->dsp);
02508       p->dsp = NULL;
02509    }
02510 
02511    p->law = p->law_default;
02512    law = p->law_default;
02513    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
02514    if (res < 0)
02515       ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
02516 
02517    dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
02518 
02519 #if 1
02520    {
02521    int i;
02522    p->owner = NULL;
02523    /* Cleanup owners here */
02524    for (i = 0; i < 3; i++) {
02525       p->subs[i].owner = NULL;
02526    }
02527    }
02528 #endif
02529 
02530    reset_conf(p);
02531    if (num_restart_pending == 0) {
02532       restart_monitor();
02533    }
02534 }
02535 
02536 static int conf_del(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index);
02537 
02538 static int my_conf_del(void *pvt, enum analog_sub sub)
02539 {
02540    struct dahdi_pvt *p = pvt;
02541    int x = analogsub_to_dahdisub(sub);
02542 
02543    return conf_del(p, &p->subs[x], x);
02544 }
02545 
02546 static int conf_add(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index, int slavechannel);
02547 
02548 static int my_conf_add(void *pvt, enum analog_sub sub)
02549 {
02550    struct dahdi_pvt *p = pvt;
02551    int x = analogsub_to_dahdisub(sub);
02552 
02553    return conf_add(p, &p->subs[x], x, 0);
02554 }
02555 
02556 static int isslavenative(struct dahdi_pvt *p, struct dahdi_pvt **out);
02557 
02558 static int my_complete_conference_update(void *pvt, int needconference)
02559 {
02560    struct dahdi_pvt *p = pvt;
02561    int needconf = needconference;
02562    int x;
02563    int useslavenative;
02564    struct dahdi_pvt *slave = NULL;
02565 
02566    useslavenative = isslavenative(p, &slave);
02567 
02568    /* If we have a slave, add him to our conference now. or DAX
02569       if this is slave native */
02570    for (x = 0; x < MAX_SLAVES; x++) {
02571       if (p->slaves[x]) {
02572          if (useslavenative)
02573             conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
02574          else {
02575             conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
02576             needconf++;
02577          }
02578       }
02579    }
02580    /* If we're supposed to be in there, do so now */
02581    if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
02582       if (useslavenative)
02583          conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
02584       else {
02585          conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
02586          needconf++;
02587       }
02588    }
02589    /* If we have a master, add ourselves to his conference */
02590    if (p->master) {
02591       if (isslavenative(p->master, NULL)) {
02592          conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
02593       } else {
02594          conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
02595       }
02596    }
02597    if (!needconf) {
02598       /* Nobody is left (or should be left) in our conference.
02599          Kill it. */
02600       p->confno = -1;
02601    }
02602 
02603    return 0;
02604 }
02605 
02606 static int check_for_conference(struct dahdi_pvt *p);
02607 
02608 static int my_check_for_conference(void *pvt)
02609 {
02610    struct dahdi_pvt *p = pvt;
02611    return check_for_conference(p);
02612 }
02613 
02614 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)
02615 {
02616    struct dahdi_pvt *p = pvt;
02617    int da, db;
02618    int tchan;
02619    int tinthreeway;
02620 
02621    da = analogsub_to_dahdisub(a);
02622    db = analogsub_to_dahdisub(b);
02623 
02624    tchan = p->subs[da].chan;
02625    p->subs[da].chan = p->subs[db].chan;
02626    p->subs[db].chan = tchan;
02627 
02628    tinthreeway = p->subs[da].inthreeway;
02629    p->subs[da].inthreeway = p->subs[db].inthreeway;
02630    p->subs[db].inthreeway = tinthreeway;
02631 
02632    p->subs[da].owner = ast_a;
02633    p->subs[db].owner = ast_b;
02634 
02635    if (ast_a)
02636       ast_channel_set_fd(ast_a, 0, p->subs[da].dfd);
02637    if (ast_b)
02638       ast_channel_set_fd(ast_b, 0, p->subs[db].dfd);
02639 
02640    wakeup_sub(p, a);
02641    wakeup_sub(p, b);
02642 
02643    return;
02644 }
02645 
02646 /*!
02647  * \internal
02648  * \brief performs duties of dahdi_new, but also removes and possibly unbinds (if callid_created is 1) before returning
02649  * \note this variant of dahdi should only be used in conjunction with ast_callid_threadstorage_auto()
02650  *
02651  * \param callid_created value returned from ast_callid_threadstorage_auto()
02652  */
02653 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);
02654 
02655 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);
02656 
02657 static struct ast_channel *my_new_analog_ast_channel(void *pvt, int state, int startpbx, enum analog_sub sub, const struct ast_channel *requestor)
02658 {
02659    struct ast_callid *callid = NULL;
02660    int callid_created = ast_callid_threadstorage_auto(&callid);
02661    struct dahdi_pvt *p = pvt;
02662    int dsub = analogsub_to_dahdisub(sub);
02663 
02664    return dahdi_new_callid_clean(p, state, startpbx, dsub, 0, requestor ? ast_channel_linkedid(requestor) : "", callid, callid_created);
02665 }
02666 
02667 #if defined(HAVE_PRI) || defined(HAVE_SS7)
02668 static int dahdi_setlaw(int dfd, int law)
02669 {
02670    int res;
02671    res = ioctl(dfd, DAHDI_SETLAW, &law);
02672    if (res)
02673       return res;
02674    return 0;
02675 }
02676 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
02677 
02678 #if defined(HAVE_PRI)
02679 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)
02680 {
02681    struct dahdi_pvt *p = pvt;
02682    int audio;
02683    int newlaw = -1;
02684    struct ast_callid *callid = NULL;
02685    int callid_created = ast_callid_threadstorage_auto(&callid);
02686 
02687    switch (p->sig) {
02688    case SIG_PRI_LIB_HANDLE_CASES:
02689       if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
02690          /* PRI nobch pseudo channel.  Does not handle ioctl(DAHDI_AUDIOMODE) */
02691          break;
02692       }
02693       /* Fall through */
02694    default:
02695       /* Set to audio mode at this point */
02696       audio = 1;
02697       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &audio) == -1) {
02698          ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n",
02699             p->channel, audio, strerror(errno));
02700       }
02701       break;
02702    }
02703 
02704    if (law != SIG_PRI_DEFLAW) {
02705       dahdi_setlaw(p->subs[SUB_REAL].dfd, (law == SIG_PRI_ULAW) ? DAHDI_LAW_MULAW : DAHDI_LAW_ALAW);
02706    }
02707 
02708    ast_copy_string(p->exten, exten, sizeof(p->exten));
02709 
02710    switch (law) {
02711       case SIG_PRI_DEFLAW:
02712          newlaw = 0;
02713          break;
02714       case SIG_PRI_ALAW:
02715          newlaw = DAHDI_LAW_ALAW;
02716          break;
02717       case SIG_PRI_ULAW:
02718          newlaw = DAHDI_LAW_MULAW;
02719          break;
02720    }
02721 
02722    return dahdi_new_callid_clean(p, state, 0, SUB_REAL, newlaw, requestor ? ast_channel_linkedid(requestor) : "", callid, callid_created);
02723 }
02724 #endif   /* defined(HAVE_PRI) */
02725 
02726 static int set_actual_gain(int fd, float rxgain, float txgain, float rxdrc, float txdrc, int law);
02727 
02728 #if defined(HAVE_PRI) || defined(HAVE_SS7)
02729 /*!
02730  * \internal
02731  * \brief Open the PRI/SS7 channel media path.
02732  * \since 1.8
02733  *
02734  * \param p Channel private control structure.
02735  *
02736  * \return Nothing
02737  */
02738 static void my_pri_ss7_open_media(void *p)
02739 {
02740    struct dahdi_pvt *pvt = p;
02741    int res;
02742    int dfd;
02743    int set_val;
02744 
02745    dfd = pvt->subs[SUB_REAL].dfd;
02746 
02747    /* Open the media path. */
02748    set_val = 1;
02749    res = ioctl(dfd, DAHDI_AUDIOMODE, &set_val);
02750    if (res < 0) {
02751       ast_log(LOG_WARNING, "Unable to enable audio mode on channel %d (%s)\n",
02752          pvt->channel, strerror(errno));
02753    }
02754 
02755    /* Set correct companding law for this call. */
02756    res = dahdi_setlaw(dfd, pvt->law);
02757    if (res < 0) {
02758       ast_log(LOG_WARNING, "Unable to set law on channel %d\n", pvt->channel);
02759    }
02760 
02761    /* Set correct gain for this call. */
02762    if (pvt->digital) {
02763       res = set_actual_gain(dfd, 0, 0, pvt->rxdrc, pvt->txdrc, pvt->law);
02764    } else {
02765       res = set_actual_gain(dfd, pvt->rxgain, pvt->txgain, pvt->rxdrc, pvt->txdrc,
02766          pvt->law);
02767    }
02768    if (res < 0) {
02769       ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", pvt->channel);
02770    }
02771 
02772    if (pvt->dsp_features && pvt->dsp) {
02773       ast_dsp_set_features(pvt->dsp, pvt->dsp_features);
02774       pvt->dsp_features = 0;
02775    }
02776 }
02777 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
02778 
02779 #if defined(HAVE_PRI)
02780 /*!
02781  * \internal
02782  * \brief Ask DAHDI to dial the given dial string.
02783  * \since 1.8.11
02784  *
02785  * \param p Channel private control structure.
02786  * \param dial_string String to pass to DAHDI to dial.
02787  *
02788  * \note The channel private lock needs to be held when calling.
02789  *
02790  * \return Nothing
02791  */
02792 static void my_pri_dial_digits(void *p, const char *dial_string)
02793 {
02794    struct dahdi_dialoperation zo = {
02795       .op = DAHDI_DIAL_OP_APPEND,
02796    };
02797    struct dahdi_pvt *pvt = p;
02798    int res;
02799 
02800    snprintf(zo.dialstr, sizeof(zo.dialstr), "T%s", dial_string);
02801    ast_debug(1, "Channel %d: Sending '%s' to DAHDI_DIAL.\n", pvt->channel, zo.dialstr);
02802    res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo);
02803    if (res) {
02804       ast_log(LOG_WARNING, "Channel %d: Couldn't dial '%s': %s\n",
02805          pvt->channel, dial_string, strerror(errno));
02806    } else {
02807       pvt->dialing = 1;
02808    }
02809 }
02810 #endif   /* defined(HAVE_PRI) */
02811 
02812 static int unalloc_sub(struct dahdi_pvt *p, int x);
02813 
02814 static int my_unallocate_sub(void *pvt, enum analog_sub analogsub)
02815 {
02816    struct dahdi_pvt *p = pvt;
02817 
02818    return unalloc_sub(p, analogsub_to_dahdisub(analogsub));
02819 }
02820 
02821 static int alloc_sub(struct dahdi_pvt *p, int x);
02822 
02823 static int my_allocate_sub(void *pvt, enum analog_sub analogsub)
02824 {
02825    struct dahdi_pvt *p = pvt;
02826 
02827    return alloc_sub(p, analogsub_to_dahdisub(analogsub));
02828 }
02829 
02830 static int has_voicemail(struct dahdi_pvt *p);
02831 
02832 static int my_has_voicemail(void *pvt)
02833 {
02834    struct dahdi_pvt *p = pvt;
02835 
02836    return has_voicemail(p);
02837 }
02838 
02839 static int my_play_tone(void *pvt, enum analog_sub sub, enum analog_tone tone)
02840 {
02841    struct dahdi_pvt *p = pvt;
02842    int index;
02843 
02844    index = analogsub_to_dahdisub(sub);
02845 
02846    return tone_zone_play_tone(p->subs[index].dfd, analog_tone_to_dahditone(tone));
02847 }
02848 
02849 static enum analog_event dahdievent_to_analogevent(int event)
02850 {
02851    enum analog_event res;
02852 
02853    switch (event) {
02854    case DAHDI_EVENT_ONHOOK:
02855       res = ANALOG_EVENT_ONHOOK;
02856       break;
02857    case DAHDI_EVENT_RINGOFFHOOK:
02858       res = ANALOG_EVENT_RINGOFFHOOK;
02859       break;
02860    case DAHDI_EVENT_WINKFLASH:
02861       res = ANALOG_EVENT_WINKFLASH;
02862       break;
02863    case DAHDI_EVENT_ALARM:
02864       res = ANALOG_EVENT_ALARM;
02865       break;
02866    case DAHDI_EVENT_NOALARM:
02867       res = ANALOG_EVENT_NOALARM;
02868       break;
02869    case DAHDI_EVENT_DIALCOMPLETE:
02870       res = ANALOG_EVENT_DIALCOMPLETE;
02871       break;
02872    case DAHDI_EVENT_RINGERON:
02873       res = ANALOG_EVENT_RINGERON;
02874       break;
02875    case DAHDI_EVENT_RINGEROFF:
02876       res = ANALOG_EVENT_RINGEROFF;
02877       break;
02878    case DAHDI_EVENT_HOOKCOMPLETE:
02879       res = ANALOG_EVENT_HOOKCOMPLETE;
02880       break;
02881    case DAHDI_EVENT_PULSE_START:
02882       res = ANALOG_EVENT_PULSE_START;
02883       break;
02884    case DAHDI_EVENT_POLARITY:
02885       res = ANALOG_EVENT_POLARITY;
02886       break;
02887    case DAHDI_EVENT_RINGBEGIN:
02888       res = ANALOG_EVENT_RINGBEGIN;
02889       break;
02890    case DAHDI_EVENT_EC_DISABLED:
02891       res = ANALOG_EVENT_EC_DISABLED;
02892       break;
02893    case DAHDI_EVENT_REMOVED:
02894       res = ANALOG_EVENT_REMOVED;
02895       break;
02896    case DAHDI_EVENT_NEONMWI_ACTIVE:
02897       res = ANALOG_EVENT_NEONMWI_ACTIVE;
02898       break;
02899    case DAHDI_EVENT_NEONMWI_INACTIVE:
02900       res = ANALOG_EVENT_NEONMWI_INACTIVE;
02901       break;
02902 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
02903    case DAHDI_EVENT_TX_CED_DETECTED:
02904       res = ANALOG_EVENT_TX_CED_DETECTED;
02905       break;
02906    case DAHDI_EVENT_RX_CED_DETECTED:
02907       res = ANALOG_EVENT_RX_CED_DETECTED;
02908       break;
02909    case DAHDI_EVENT_EC_NLP_DISABLED:
02910       res = ANALOG_EVENT_EC_NLP_DISABLED;
02911       break;
02912    case DAHDI_EVENT_EC_NLP_ENABLED:
02913       res = ANALOG_EVENT_EC_NLP_ENABLED;
02914       break;
02915 #endif
02916    case DAHDI_EVENT_PULSEDIGIT:
02917       res = ANALOG_EVENT_PULSEDIGIT;
02918       break;
02919    case DAHDI_EVENT_DTMFDOWN:
02920       res = ANALOG_EVENT_DTMFDOWN;
02921       break;
02922    case DAHDI_EVENT_DTMFUP:
02923       res = ANALOG_EVENT_DTMFUP;
02924       break;
02925    default:
02926       switch(event & 0xFFFF0000) {
02927       case DAHDI_EVENT_PULSEDIGIT:
02928       case DAHDI_EVENT_DTMFDOWN:
02929       case DAHDI_EVENT_DTMFUP:
02930          /* The event includes a digit number in the low word.
02931           * Converting it to a 'enum analog_event' would remove
02932           * that information. Thus it is returned as-is.
02933           */
02934          return event;
02935       }
02936 
02937       res = ANALOG_EVENT_ERROR;
02938       break;
02939    }
02940 
02941    return res;
02942 }
02943 
02944 static inline int dahdi_wait_event(int fd);
02945 
02946 static int my_wait_event(void *pvt)
02947 {
02948    struct dahdi_pvt *p = pvt;
02949 
02950    return dahdi_wait_event(p->subs[SUB_REAL].dfd);
02951 }
02952 
02953 static int my_get_event(void *pvt)
02954 {
02955    struct dahdi_pvt *p = pvt;
02956    int res;
02957 
02958    if (p->fake_event) {
02959       res = p->fake_event;
02960       p->fake_event = 0;
02961    } else
02962       res = dahdi_get_event(p->subs[SUB_REAL].dfd);
02963 
02964    return dahdievent_to_analogevent(res);
02965 }
02966 
02967 static int my_is_off_hook(void *pvt)
02968 {
02969    struct dahdi_pvt *p = pvt;
02970    int res;
02971    struct dahdi_params par;
02972 
02973    memset(&par, 0, sizeof(par));
02974 
02975    if (p->subs[SUB_REAL].dfd > -1)
02976       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
02977    else {
02978       /* Assume not off hook on CVRS */
02979       res = 0;
02980       par.rxisoffhook = 0;
02981    }
02982    if (res) {
02983       ast_log(LOG_WARNING, "Unable to check hook state on channel %d: %s\n", p->channel, strerror(errno));
02984    }
02985 
02986    if ((p->sig == SIG_FXSKS) || (p->sig == SIG_FXSGS)) {
02987       /* When "onhook" that means no battery on the line, and thus
02988       it is out of service..., if it's on a TDM card... If it's a channel
02989       bank, there is no telling... */
02990       return (par.rxbits > -1) || par.rxisoffhook;
02991    }
02992 
02993    return par.rxisoffhook;
02994 }
02995 
02996 static void dahdi_enable_ec(struct dahdi_pvt *p);
02997 static void dahdi_disable_ec(struct dahdi_pvt *p);
02998 
02999 static int my_set_echocanceller(void *pvt, int enable)
03000 {
03001    struct dahdi_pvt *p = pvt;
03002 
03003    if (enable)
03004       dahdi_enable_ec(p);
03005    else
03006       dahdi_disable_ec(p);
03007 
03008    return 0;
03009 }
03010 
03011 static int dahdi_ring_phone(struct dahdi_pvt *p);
03012 
03013 static int my_ring(void *pvt)
03014 {
03015    struct dahdi_pvt *p = pvt;
03016 
03017    return dahdi_ring_phone(p);
03018 }
03019 
03020 static int my_flash(void *pvt)
03021 {
03022    struct dahdi_pvt *p = pvt;
03023    int func = DAHDI_FLASH;
03024    return ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &func);
03025 }
03026 
03027 static inline int dahdi_set_hook(int fd, int hs);
03028 
03029 static int my_off_hook(void *pvt)
03030 {
03031    struct dahdi_pvt *p = pvt;
03032    return dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
03033 }
03034 
03035 static void my_set_needringing(void *pvt, int value)
03036 {
03037    struct dahdi_pvt *p = pvt;
03038    p->subs[SUB_REAL].needringing = value;
03039 }
03040 
03041 static void my_set_polarity(void *pvt, int value)
03042 {
03043    struct dahdi_pvt *p = pvt;
03044 
03045    if (p->channel == CHAN_PSEUDO) {
03046       return;
03047    }
03048    p->polarity = value;
03049    ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETPOLARITY, &value);
03050 }
03051 
03052 static void my_start_polarityswitch(void *pvt)
03053 {
03054    struct dahdi_pvt *p = pvt;
03055 
03056    if (p->answeronpolarityswitch || p->hanguponpolarityswitch) {
03057       my_set_polarity(pvt, 0);
03058    }
03059 }
03060 
03061 static void my_answer_polarityswitch(void *pvt)
03062 {
03063    struct dahdi_pvt *p = pvt;
03064 
03065    if (!p->answeronpolarityswitch) {
03066       return;
03067    }
03068 
03069    my_set_polarity(pvt, 1);
03070 }
03071 
03072 static void my_hangup_polarityswitch(void *pvt)
03073 {
03074    struct dahdi_pvt *p = pvt;
03075 
03076    if (!p->hanguponpolarityswitch) {
03077       return;
03078    }
03079 
03080    if (p->answeronpolarityswitch) {
03081       my_set_polarity(pvt, 0);
03082    } else {
03083       my_set_polarity(pvt, 1);
03084    }
03085 }
03086 
03087 static int my_start(void *pvt)
03088 {
03089    struct dahdi_pvt *p = pvt;
03090    int x = DAHDI_START;
03091 
03092    return ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
03093 }
03094 
03095 static int my_dial_digits(void *pvt, enum analog_sub sub, struct analog_dialoperation *dop)
03096 {
03097    int index = analogsub_to_dahdisub(sub);
03098    int res;
03099    struct dahdi_pvt *p = pvt;
03100    struct dahdi_dialoperation ddop;
03101 
03102    if (dop->op != ANALOG_DIAL_OP_REPLACE) {
03103       ast_log(LOG_ERROR, "Fix the dial_digits callback!\n");
03104       return -1;
03105    }
03106 
03107    if (sub != ANALOG_SUB_REAL) {
03108       ast_log(LOG_ERROR, "Trying to dial_digits '%s' on channel %d subchannel %d\n",
03109          dop->dialstr, p->channel, sub);
03110       return -1;
03111    }
03112 
03113    ddop.op = DAHDI_DIAL_OP_REPLACE;
03114    ast_copy_string(ddop.dialstr, dop->dialstr, sizeof(ddop.dialstr));
03115 
03116    ast_debug(1, "Channel %d: Sending '%s' to DAHDI_DIAL.\n", p->channel, ddop.dialstr);
03117 
03118    res = ioctl(p->subs[index].dfd, DAHDI_DIAL, &ddop);
03119    if (res == -1) {
03120       ast_debug(1, "DAHDI_DIAL ioctl failed on %s: %s\n", ast_channel_name(p->owner), strerror(errno));
03121    }
03122 
03123    return res;
03124 }
03125 
03126 static void dahdi_train_ec(struct dahdi_pvt *p);
03127 
03128 static int my_train_echocanceller(void *pvt)
03129 {
03130    struct dahdi_pvt *p = pvt;
03131 
03132    dahdi_train_ec(p);
03133 
03134    return 0;
03135 }
03136 
03137 static int my_is_dialing(void *pvt, enum analog_sub sub)
03138 {
03139    struct dahdi_pvt *p = pvt;
03140    int index;
03141    int x;
03142 
03143    index = analogsub_to_dahdisub(sub);
03144 
03145    if (ioctl(p->subs[index].dfd, DAHDI_DIALING, &x)) {
03146       ast_debug(1, "DAHDI_DIALING ioctl failed!\n");
03147       return -1;
03148    }
03149 
03150    return x;
03151 }
03152 
03153 static int my_on_hook(void *pvt)
03154 {
03155    struct dahdi_pvt *p = pvt;
03156    return dahdi_set_hook(p->subs[ANALOG_SUB_REAL].dfd, DAHDI_ONHOOK);
03157 }
03158 
03159 #if defined(HAVE_PRI)
03160 static void my_pri_fixup_chans(void *chan_old, void *chan_new)
03161 {
03162    struct dahdi_pvt *old_chan = chan_old;
03163    struct dahdi_pvt *new_chan = chan_new;
03164 
03165    new_chan->owner = old_chan->owner;
03166    old_chan->owner = NULL;
03167    if (new_chan->owner) {
03168       ast_channel_tech_pvt_set(new_chan->owner, new_chan);
03169       ast_channel_internal_fd_set(new_chan->owner, 0, new_chan->subs[SUB_REAL].dfd);
03170       new_chan->subs[SUB_REAL].owner = old_chan->subs[SUB_REAL].owner;
03171       old_chan->subs[SUB_REAL].owner = NULL;
03172    }
03173    /* Copy any DSP that may be present */
03174    new_chan->dsp = old_chan->dsp;
03175    new_chan->dsp_features = old_chan->dsp_features;
03176    old_chan->dsp = NULL;
03177    old_chan->dsp_features = 0;
03178 
03179    /* Transfer flags from the old channel. */
03180    new_chan->dialing = old_chan->dialing;
03181    new_chan->digital = old_chan->digital;
03182    new_chan->outgoing = old_chan->outgoing;
03183    old_chan->dialing = 0;
03184    old_chan->digital = 0;
03185    old_chan->outgoing = 0;
03186 
03187    /* More stuff to transfer to the new channel. */
03188    new_chan->law = old_chan->law;
03189    strcpy(new_chan->dialstring, old_chan->dialstring);
03190 }
03191 #endif   /* defined(HAVE_PRI) */
03192 
03193 #if defined(HAVE_PRI)
03194 static int sig_pri_tone_to_dahditone(enum sig_pri_tone tone)
03195 {
03196    switch (tone) {
03197    case SIG_PRI_TONE_RINGTONE:
03198       return DAHDI_TONE_RINGTONE;
03199    case SIG_PRI_TONE_STUTTER:
03200       return DAHDI_TONE_STUTTER;
03201    case SIG_PRI_TONE_CONGESTION:
03202       return DAHDI_TONE_CONGESTION;
03203    case SIG_PRI_TONE_DIALTONE:
03204       return DAHDI_TONE_DIALTONE;
03205    case SIG_PRI_TONE_DIALRECALL:
03206       return DAHDI_TONE_DIALRECALL;
03207    case SIG_PRI_TONE_INFO:
03208       return DAHDI_TONE_INFO;
03209    case SIG_PRI_TONE_BUSY:
03210       return DAHDI_TONE_BUSY;
03211    default:
03212       return -1;
03213    }
03214 }
03215 #endif   /* defined(HAVE_PRI) */
03216 
03217 #if defined(HAVE_PRI)
03218 static int pri_destroy_dchan(struct sig_pri_span *pri);
03219 
03220 static void my_handle_dchan_exception(struct sig_pri_span *pri, int index)
03221 {
03222    int x;
03223 
03224    ioctl(pri->fds[index], DAHDI_GETEVENT, &x);
03225    switch (x) {
03226    case DAHDI_EVENT_NONE:
03227       break;
03228    case DAHDI_EVENT_ALARM:
03229    case DAHDI_EVENT_NOALARM:
03230       if (sig_pri_is_alarm_ignored(pri)) {
03231          break;
03232       }
03233       /* Fall through */
03234    default:
03235       ast_log(LOG_NOTICE, "PRI got event: %s (%d) on D-channel of span %d\n",
03236          event2str(x), x, pri->span);
03237       break;
03238    }
03239    /* Keep track of alarm state */
03240    switch (x) {
03241    case DAHDI_EVENT_ALARM:
03242       pri_event_alarm(pri, index, 0);
03243       break;
03244    case DAHDI_EVENT_NOALARM:
03245       pri_event_noalarm(pri, index, 0);
03246       break;
03247    case DAHDI_EVENT_REMOVED:
03248       pri_destroy_dchan(pri);
03249       break;
03250    default:
03251       break;
03252    }
03253 }
03254 #endif   /* defined(HAVE_PRI) */
03255 
03256 #if defined(HAVE_PRI)
03257 static int my_pri_play_tone(void *pvt, enum sig_pri_tone tone)
03258 {
03259    struct dahdi_pvt *p = pvt;
03260 
03261    return tone_zone_play_tone(p->subs[SUB_REAL].dfd, sig_pri_tone_to_dahditone(tone));
03262 }
03263 #endif   /* defined(HAVE_PRI) */
03264 
03265 #if defined(HAVE_PRI) || defined(HAVE_SS7)
03266 /*!
03267  * \internal
03268  * \brief Set the caller id information.
03269  * \since 1.8
03270  *
03271  * \param pvt DAHDI private structure
03272  * \param caller Caller-id information to set.
03273  *
03274  * \return Nothing
03275  */
03276 static void my_set_callerid(void *pvt, const struct ast_party_caller *caller)
03277 {
03278    struct dahdi_pvt *p = pvt;
03279 
03280    ast_copy_string(p->cid_num,
03281       S_COR(caller->id.number.valid, caller->id.number.str, ""),
03282       sizeof(p->cid_num));
03283    ast_copy_string(p->cid_name,
03284       S_COR(caller->id.name.valid, caller->id.name.str, ""),
03285       sizeof(p->cid_name));
03286    ast_copy_string(p->cid_subaddr,
03287       S_COR(caller->id.subaddress.valid, caller->id.subaddress.str, ""),
03288       sizeof(p->cid_subaddr));
03289    p->cid_ton = caller->id.number.plan;
03290    p->callingpres = ast_party_id_presentation(&caller->id);
03291    if (caller->id.tag) {
03292       ast_copy_string(p->cid_tag, caller->id.tag, sizeof(p->cid_tag));
03293    }
03294    ast_copy_string(p->cid_ani,
03295       S_COR(caller->ani.number.valid, caller->ani.number.str, ""),
03296       sizeof(p->cid_ani));
03297    p->cid_ani2 = caller->ani2;
03298 }
03299 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
03300 
03301 #if defined(HAVE_PRI) || defined(HAVE_SS7)
03302 /*!
03303  * \internal
03304  * \brief Set the Dialed Number Identifier.
03305  * \since 1.8
03306  *
03307  * \param pvt DAHDI private structure
03308  * \param dnid Dialed Number Identifier string.
03309  *
03310  * \return Nothing
03311  */
03312 static void my_set_dnid(void *pvt, const char *dnid)
03313 {
03314    struct dahdi_pvt *p = pvt;
03315 
03316    ast_copy_string(p->dnid, dnid, sizeof(p->dnid));
03317 }
03318 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
03319 
03320 #if defined(HAVE_PRI)
03321 /*!
03322  * \internal
03323  * \brief Set the Redirecting Directory Number Information Service (RDNIS).
03324  * \since 1.8
03325  *
03326  * \param pvt DAHDI private structure
03327  * \param rdnis Redirecting Directory Number Information Service (RDNIS) string.
03328  *
03329  * \return Nothing
03330  */
03331 static void my_set_rdnis(void *pvt, const char *rdnis)
03332 {
03333    struct dahdi_pvt *p = pvt;
03334 
03335    ast_copy_string(p->rdnis, rdnis, sizeof(p->rdnis));
03336 }
03337 #endif   /* defined(HAVE_PRI) */
03338 
03339 #if defined(HAVE_PRI)
03340 /*!
03341  * \internal
03342  * \brief Make a dialstring for native ISDN CC to recall properly.
03343  * \since 1.8
03344  *
03345  * \param priv Channel private control structure.
03346  * \param buf Where to put the modified dialstring.
03347  * \param buf_size Size of modified dialstring buffer.
03348  *
03349  * \details
03350  * original dialstring:
03351  * DAHDI/[i<span>-](g|G|r|R)<group#(0-63)>[c|r<cadance#>|d][/extension[/options]]
03352  *
03353  * The modified dialstring will have prefixed the channel-group section
03354  * with the ISDN channel restriction.
03355  *
03356  * buf:
03357  * DAHDI/i<span>-(g|G|r|R)<group#(0-63)>[c|r<cadance#>|d][/extension[/options]]
03358  *
03359  * The routine will check to see if the ISDN channel restriction is already
03360  * in the original dialstring.
03361  *
03362  * \return Nothing
03363  */
03364 static void my_pri_make_cc_dialstring(void *priv, char *buf, size_t buf_size)
03365 {
03366    char *dial;
03367    struct dahdi_pvt *pvt;
03368    AST_DECLARE_APP_ARGS(args,
03369       AST_APP_ARG(tech);   /* channel technology token */
03370       AST_APP_ARG(group);  /* channel/group token */
03371       //AST_APP_ARG(ext);  /* extension token */
03372       //AST_APP_ARG(opts); /* options token */
03373       //AST_APP_ARG(other);   /* Any remining unused arguments */
03374    );
03375 
03376    pvt = priv;
03377    dial = ast_strdupa(pvt->dialstring);
03378    AST_NONSTANDARD_APP_ARGS(args, dial, '/');
03379    if (!args.tech) {
03380       ast_copy_string(buf, pvt->dialstring, buf_size);
03381       return;
03382    }
03383    if (!args.group) {
03384       /* Append the ISDN span channel restriction to the dialstring. */
03385       snprintf(buf, buf_size, "%s/i%d-", args.tech, pvt->pri->span);
03386       return;
03387    }
03388    if (isdigit(args.group[0]) || args.group[0] == 'i' || strchr(args.group, '!')) {
03389       /* The ISDN span channel restriction is not needed or already
03390        * in the dialstring. */
03391       ast_copy_string(buf, pvt->dialstring, buf_size);
03392       return;
03393    }
03394    /* Insert the ISDN span channel restriction into the dialstring. */
03395    snprintf(buf, buf_size, "%s/i%d-%s", args.tech, pvt->pri->span, args.group);
03396 }
03397 #endif   /* defined(HAVE_PRI) */
03398 
03399 #if defined(HAVE_PRI)
03400 /*!
03401  * \internal
03402  * \brief Reevaluate the PRI span device state.
03403  * \since 1.8
03404  *
03405  * \param pri Asterisk D channel control structure.
03406  *
03407  * \return Nothing
03408  *
03409  * \note Assumes the pri->lock is already obtained.
03410  */
03411 static void dahdi_pri_update_span_devstate(struct sig_pri_span *pri)
03412 {
03413    unsigned idx;
03414    unsigned num_b_chans;   /* Number of B channels provisioned on the span. */
03415    unsigned in_use;     /* Number of B channels in use on the span. */
03416    unsigned in_alarm;      /* TRUE if the span is in alarm condition. */
03417    enum ast_device_state new_state;
03418 
03419    /* Count the number of B channels and the number of B channels in use. */
03420    num_b_chans = 0;
03421    in_use = 0;
03422    in_alarm = 1;
03423    for (idx = pri->numchans; idx--;) {
03424       if (pri->pvts[idx] && !pri->pvts[idx]->no_b_channel) {
03425          /* This is a B channel interface. */
03426          ++num_b_chans;
03427          if (!sig_pri_is_chan_available(pri->pvts[idx])) {
03428             ++in_use;
03429          }
03430          if (!pri->pvts[idx]->inalarm) {
03431             /* There is a channel that is not in alarm. */
03432             in_alarm = 0;
03433          }
03434       }
03435    }
03436 
03437    /* Update the span congestion device state and report any change. */
03438    if (in_alarm) {
03439       new_state = AST_DEVICE_UNAVAILABLE;
03440    } else {
03441       new_state = num_b_chans == in_use ? AST_DEVICE_BUSY : AST_DEVICE_NOT_INUSE;
03442    }
03443    if (pri->congestion_devstate != new_state) {
03444       pri->congestion_devstate = new_state;
03445       ast_devstate_changed(AST_DEVICE_UNKNOWN, AST_DEVSTATE_NOT_CACHABLE, "DAHDI/I%d/congestion", pri->span);
03446    }
03447 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
03448    /* Update the span threshold device state and report any change. */
03449    if (in_alarm) {
03450       new_state = AST_DEVICE_UNAVAILABLE;
03451    } else if (!in_use) {
03452       new_state = AST_DEVICE_NOT_INUSE;
03453    } else if (!pri->user_busy_threshold) {
03454       new_state = in_use < num_b_chans ? AST_DEVICE_INUSE : AST_DEVICE_BUSY;
03455    } else {
03456       new_state = in_use < pri->user_busy_threshold ? AST_DEVICE_INUSE
03457          : AST_DEVICE_BUSY;
03458    }
03459    if (pri->threshold_devstate != new_state) {
03460       pri->threshold_devstate = new_state;
03461       ast_devstate_changed(AST_DEVICE_UNKNOWN, AST_DEVSTATE_NOT_CACHABLE, "DAHDI/I%d/threshold", pri->span);
03462    }
03463 #endif   /* defined(THRESHOLD_DEVSTATE_PLACEHOLDER) */
03464 }
03465 #endif   /* defined(HAVE_PRI) */
03466 
03467 #if defined(HAVE_PRI)
03468 /*!
03469  * \internal
03470  * \brief Reference this module.
03471  * \since 1.8
03472  *
03473  * \return Nothing
03474  */
03475 static void my_module_ref(void)
03476 {
03477    ast_module_ref(ast_module_info->self);
03478 }
03479 #endif   /* defined(HAVE_PRI) */
03480 
03481 #if defined(HAVE_PRI)
03482 /*!
03483  * \internal
03484  * \brief Unreference this module.
03485  * \since 1.8
03486  *
03487  * \return Nothing
03488  */
03489 static void my_module_unref(void)
03490 {
03491    ast_module_unref(ast_module_info->self);
03492 }
03493 #endif   /* defined(HAVE_PRI) */
03494 
03495 #if defined(HAVE_PRI)
03496 #if defined(HAVE_PRI_CALL_WAITING)
03497 static void my_pri_init_config(void *priv, struct sig_pri_span *pri);
03498 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
03499 static int dahdi_new_pri_nobch_channel(struct sig_pri_span *pri);
03500 
03501 struct sig_pri_callback sig_pri_callbacks =
03502 {
03503    .handle_dchan_exception = my_handle_dchan_exception,
03504    .play_tone = my_pri_play_tone,
03505    .set_echocanceller = my_set_echocanceller,
03506    .dsp_reset_and_flush_digits = my_dsp_reset_and_flush_digits,
03507    .lock_private = my_lock_private,
03508    .unlock_private = my_unlock_private,
03509    .deadlock_avoidance_private = my_deadlock_avoidance_private,
03510    .new_ast_channel = my_new_pri_ast_channel,
03511    .fixup_chans = my_pri_fixup_chans,
03512    .set_alarm = my_set_alarm,
03513    .set_dialing = my_set_dialing,
03514    .set_outgoing = my_set_outgoing,
03515    .set_digital = my_set_digital,
03516    .set_callerid = my_set_callerid,
03517    .set_dnid = my_set_dnid,
03518    .set_rdnis = my_set_rdnis,
03519    .new_nobch_intf = dahdi_new_pri_nobch_channel,
03520 #if defined(HAVE_PRI_CALL_WAITING)
03521    .init_config = my_pri_init_config,
03522 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
03523    .get_orig_dialstring = my_get_orig_dialstring,
03524    .make_cc_dialstring = my_pri_make_cc_dialstring,
03525    .update_span_devstate = dahdi_pri_update_span_devstate,
03526    .module_ref = my_module_ref,
03527    .module_unref = my_module_unref,
03528    .dial_digits = my_pri_dial_digits,
03529    .open_media = my_pri_ss7_open_media,
03530    .ami_channel_event = my_ami_channel_event,
03531 };
03532 #endif   /* defined(HAVE_PRI) */
03533 
03534 #if defined(HAVE_SS7)
03535 /*!
03536  * \internal
03537  * \brief Handle the SS7 link exception.
03538  * \since 1.8
03539  *
03540  * \param linkset Controlling linkset for the channel.
03541  * \param which Link index of the signaling channel.
03542  *
03543  * \return Nothing
03544  */
03545 static void my_handle_link_exception(struct sig_ss7_linkset *linkset, int which)
03546 {
03547    int event;
03548 
03549    if (ioctl(linkset->fds[which], DAHDI_GETEVENT, &event)) {
03550       ast_log(LOG_ERROR, "SS7: Error in exception retrieval on span %d/%d!\n",
03551          linkset->span, which);
03552       return;
03553    }
03554    switch (event) {
03555    case DAHDI_EVENT_NONE:
03556       break;
03557    case DAHDI_EVENT_ALARM:
03558       ast_log(LOG_ERROR, "SS7 got event: %s(%d) on span %d/%d\n",
03559          event2str(event), event, linkset->span, which);
03560       sig_ss7_link_alarm(linkset, which);
03561       break;
03562    case DAHDI_EVENT_NOALARM:
03563       ast_log(LOG_ERROR, "SS7 got event: %s(%d) on span %d/%d\n",
03564          event2str(event), event, linkset->span, which);
03565       sig_ss7_link_noalarm(linkset, which);
03566       break;
03567    default:
03568       ast_log(LOG_NOTICE, "SS7 got event: %s(%d) on span %d/%d\n",
03569          event2str(event), event, linkset->span, which);
03570       break;
03571    }
03572 }
03573 #endif   /* defined(HAVE_SS7) */
03574 
03575 #if defined(HAVE_SS7)
03576 static void my_ss7_set_loopback(void *pvt, int enable)
03577 {
03578    struct dahdi_pvt *p = pvt;
03579 
03580    if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_LOOPBACK, &enable)) {
03581       ast_log(LOG_WARNING, "Unable to set loopback on channel %d: %s\n", p->channel,
03582          strerror(errno));
03583    }
03584 }
03585 #endif   /* defined(HAVE_SS7) */
03586 
03587 #if defined(HAVE_SS7)
03588 /*!
03589  * \internal
03590  * \brief Create a new asterisk channel structure for SS7.
03591  * \since 1.8
03592  *
03593  * \param pvt Private channel structure.
03594  * \param state Initial state of new channel.
03595  * \param law Combanding law to use.
03596  * \param exten Dialplan extension for incoming call.
03597  * \param requestor Channel requesting this new channel.
03598  *
03599  * \retval ast_channel on success.
03600  * \retval NULL on error.
03601  */
03602 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)
03603 {
03604    struct dahdi_pvt *p = pvt;
03605    int audio;
03606    int newlaw;
03607    struct ast_callid *callid = NULL;
03608    int callid_created = ast_callid_threadstorage_auto(&callid);
03609 
03610    /* Set to audio mode at this point */
03611    audio = 1;
03612    if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &audio) == -1)
03613       ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n",
03614          p->channel, audio, strerror(errno));
03615 
03616    if (law != SIG_SS7_DEFLAW) {
03617       dahdi_setlaw(p->subs[SUB_REAL].dfd,
03618          (law == SIG_SS7_ULAW) ? DAHDI_LAW_MULAW : DAHDI_LAW_ALAW);
03619    }
03620 
03621    ast_copy_string(p->exten, exten, sizeof(p->exten));
03622 
03623    newlaw = -1;
03624    switch (law) {
03625    case SIG_SS7_DEFLAW:
03626       newlaw = 0;
03627       break;
03628    case SIG_SS7_ALAW:
03629       newlaw = DAHDI_LAW_ALAW;
03630       break;
03631    case SIG_SS7_ULAW:
03632       newlaw = DAHDI_LAW_MULAW;
03633       break;
03634    }
03635    return dahdi_new_callid_clean(p, state, 0, SUB_REAL, newlaw, requestor ? ast_channel_linkedid(requestor) : "", callid, callid_created);
03636 }
03637 #endif   /* defined(HAVE_SS7) */
03638 
03639 #if defined(HAVE_SS7)
03640 static int sig_ss7_tone_to_dahditone(enum sig_ss7_tone tone)
03641 {
03642    switch (tone) {
03643    case SIG_SS7_TONE_RINGTONE:
03644       return DAHDI_TONE_RINGTONE;
03645    case SIG_SS7_TONE_STUTTER:
03646       return DAHDI_TONE_STUTTER;
03647    case SIG_SS7_TONE_CONGESTION:
03648       return DAHDI_TONE_CONGESTION;
03649    case SIG_SS7_TONE_DIALTONE:
03650       return DAHDI_TONE_DIALTONE;
03651    case SIG_SS7_TONE_DIALRECALL:
03652       return DAHDI_TONE_DIALRECALL;
03653    case SIG_SS7_TONE_INFO:
03654       return DAHDI_TONE_INFO;
03655    case SIG_SS7_TONE_BUSY:
03656       return DAHDI_TONE_BUSY;
03657    default:
03658       return -1;
03659    }
03660 }
03661 #endif   /* defined(HAVE_SS7) */
03662 
03663 #if defined(HAVE_SS7)
03664 static int my_ss7_play_tone(void *pvt, enum sig_ss7_tone tone)
03665 {
03666    struct dahdi_pvt *p = pvt;
03667 
03668    return tone_zone_play_tone(p->subs[SUB_REAL].dfd, sig_ss7_tone_to_dahditone(tone));
03669 }
03670 #endif   /* defined(HAVE_SS7) */
03671 
03672 #if defined(HAVE_SS7)
03673 struct sig_ss7_callback sig_ss7_callbacks =
03674 {
03675    .lock_private = my_lock_private,
03676    .unlock_private = my_unlock_private,
03677    .deadlock_avoidance_private = my_deadlock_avoidance_private,
03678 
03679    .set_echocanceller = my_set_echocanceller,
03680    .set_loopback = my_ss7_set_loopback,
03681 
03682    .new_ast_channel = my_new_ss7_ast_channel,
03683    .play_tone = my_ss7_play_tone,
03684 
03685    .handle_link_exception = my_handle_link_exception,
03686    .set_alarm = my_set_alarm,
03687    .set_dialing = my_set_dialing,
03688    .set_outgoing = my_set_outgoing,
03689    .set_digital = my_set_digital,
03690    .set_inservice = my_set_inservice,
03691    .set_locallyblocked = my_set_locallyblocked,
03692    .set_remotelyblocked = my_set_remotelyblocked,
03693    .set_callerid = my_set_callerid,
03694    .set_dnid = my_set_dnid,
03695    .open_media = my_pri_ss7_open_media,
03696 };
03697 #endif   /* defined(HAVE_SS7) */
03698 
03699 /*!
03700  * \brief Send MWI state change
03701  *
03702  * \arg mailbox_full This is the mailbox associated with the FXO line that the
03703  *      MWI state has changed on.
03704  * \arg thereornot This argument should simply be set to 1 or 0, to indicate
03705  *      whether there are messages waiting or not.
03706  *
03707  *  \return nothing
03708  *
03709  * This function does two things:
03710  *
03711  * 1) It generates an internal Asterisk event notifying any other module that
03712  *    cares about MWI that the state of a mailbox has changed.
03713  *
03714  * 2) It runs the script specified by the mwimonitornotify option to allow
03715  *    some custom handling of the state change.
03716  */
03717 static void notify_message(char *mailbox_full, int thereornot)
03718 {
03719    char s[sizeof(mwimonitornotify) + 80];
03720    struct ast_event *event;
03721    char *mailbox, *context;
03722 
03723    /* Strip off @default */
03724    context = mailbox = ast_strdupa(mailbox_full);
03725    strsep(&context, "@");
03726    if (ast_strlen_zero(context))
03727       context = "default";
03728 
03729    if (!(event = ast_event_new(AST_EVENT_MWI,
03730          AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
03731          AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
03732          AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot,
03733          AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot,
03734          AST_EVENT_IE_END))) {
03735       return;
03736    }
03737 
03738    ast_event_queue_and_cache(event);
03739 
03740    if (!ast_strlen_zero(mailbox) && !ast_strlen_zero(mwimonitornotify)) {
03741       snprintf(s, sizeof(s), "%s %s %d", mwimonitornotify, mailbox, thereornot);
03742       ast_safe_system(s);
03743    }
03744 }
03745 
03746 static void my_handle_notify_message(struct ast_channel *chan, void *pvt, int cid_flags, int neon_mwievent)
03747 {
03748    struct dahdi_pvt *p = pvt;
03749 
03750    if (neon_mwievent > -1 && !p->mwimonitor_neon)
03751       return;
03752 
03753    if (neon_mwievent == ANALOG_EVENT_NEONMWI_ACTIVE || cid_flags & CID_MSGWAITING) {
03754       ast_log(LOG_NOTICE, "MWI: Channel %d message waiting, mailbox %s\n", p->channel, p->mailbox);
03755       notify_message(p->mailbox, 1);
03756    } else if (neon_mwievent == ANALOG_EVENT_NEONMWI_INACTIVE || cid_flags & CID_NOMSGWAITING) {
03757       ast_log(LOG_NOTICE, "MWI: Channel %d no message waiting, mailbox %s\n", p->channel, p->mailbox);
03758       notify_message(p->mailbox, 0);
03759    }
03760    /* If the CID had Message waiting payload, assume that this for MWI only and hangup the call */
03761    /* If generated using Ring Pulse Alert, then ring has been answered as a call and needs to be hungup */
03762    if (neon_mwievent == -1 && p->mwimonitor_rpas) {
03763       ast_hangup(chan);
03764       return;
03765    }
03766 }
03767 
03768 static int my_have_progressdetect(void *pvt)
03769 {
03770    struct dahdi_pvt *p = pvt;
03771 
03772    if ((p->callprogress & CALLPROGRESS_PROGRESS)
03773       && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
03774       return 1;
03775    } else {
03776       /* Don't have progress detection. */
03777       return 0;
03778    }
03779 }
03780 
03781 struct analog_callback analog_callbacks =
03782 {
03783    .play_tone = my_play_tone,
03784    .get_event = my_get_event,
03785    .wait_event = my_wait_event,
03786    .is_off_hook = my_is_off_hook,
03787    .set_echocanceller = my_set_echocanceller,
03788    .ring = my_ring,
03789    .flash = my_flash,
03790    .off_hook = my_off_hook,
03791    .dial_digits = my_dial_digits,
03792    .train_echocanceller = my_train_echocanceller,
03793    .on_hook = my_on_hook,
03794    .is_dialing = my_is_dialing,
03795    .allocate_sub = my_allocate_sub,
03796    .unallocate_sub = my_unallocate_sub,
03797    .swap_subs = my_swap_subchannels,
03798    .has_voicemail = my_has_voicemail,
03799    .check_for_conference = my_check_for_conference,
03800    .conf_add = my_conf_add,
03801    .conf_del = my_conf_del,
03802    .complete_conference_update = my_complete_conference_update,
03803    .start = my_start,
03804    .all_subchannels_hungup = my_all_subchannels_hungup,
03805    .lock_private = my_lock_private,
03806    .unlock_private = my_unlock_private,
03807    .deadlock_avoidance_private = my_deadlock_avoidance_private,
03808    .handle_dtmf = my_handle_dtmf,
03809    .wink = my_wink,
03810    .new_ast_channel = my_new_analog_ast_channel,
03811    .dsp_set_digitmode = my_dsp_set_digitmode,
03812    .dsp_reset_and_flush_digits = my_dsp_reset_and_flush_digits,
03813    .send_callerid = my_send_callerid,
03814    .callwait = my_callwait,
03815    .stop_callwait = my_stop_callwait,
03816    .get_callerid = my_get_callerid,
03817    .start_cid_detect = my_start_cid_detect,
03818    .stop_cid_detect = my_stop_cid_detect,
03819    .handle_notify_message = my_handle_notify_message,
03820    .increase_ss_count = my_increase_ss_count,
03821    .decrease_ss_count = my_decrease_ss_count,
03822    .distinctive_ring = my_distinctive_ring,
03823    .set_linear_mode = my_set_linear_mode,
03824    .set_inthreeway = my_set_inthreeway,
03825    .get_and_handle_alarms = my_get_and_handle_alarms,
03826    .get_sigpvt_bridged_channel = my_get_sigpvt_bridged_channel,
03827    .get_sub_fd = my_get_sub_fd,
03828    .set_cadence = my_set_cadence,
03829    .set_alarm = my_set_alarm,
03830    .set_dialing = my_set_dialing,
03831    .set_outgoing = my_set_outgoing,
03832    .set_ringtimeout = my_set_ringtimeout,
03833    .set_waitingfordt = my_set_waitingfordt,
03834    .check_waitingfordt = my_check_waitingfordt,
03835    .set_confirmanswer = my_set_confirmanswer,
03836    .check_confirmanswer = my_check_confirmanswer,
03837    .set_callwaiting = my_set_callwaiting,
03838    .cancel_cidspill = my_cancel_cidspill,
03839    .confmute = my_confmute,
03840    .set_pulsedial = my_set_pulsedial,
03841    .set_new_owner = my_set_new_owner,
03842    .get_orig_dialstring = my_get_orig_dialstring,
03843    .set_needringing = my_set_needringing,
03844    .set_polarity = my_set_polarity,
03845    .start_polarityswitch = my_start_polarityswitch,
03846    .answer_polarityswitch = my_answer_polarityswitch,
03847    .hangup_polarityswitch = my_hangup_polarityswitch,
03848    .have_progressdetect = my_have_progressdetect,
03849 };
03850 
03851 /*! Round robin search locations. */
03852 static struct dahdi_pvt *round_robin[32];
03853 
03854 #define dahdi_get_index(ast, p, nullok)   _dahdi_get_index(ast, p, nullok, __PRETTY_FUNCTION__, __LINE__)
03855 static int _dahdi_get_index(struct ast_channel *ast, struct dahdi_pvt *p, int nullok, const char *fname, unsigned long line)
03856 {
03857    int res;
03858    if (p->subs[SUB_REAL].owner == ast)
03859       res = 0;
03860    else if (p->subs[SUB_CALLWAIT].owner == ast)
03861       res = 1;
03862    else if (p->subs[SUB_THREEWAY].owner == ast)
03863       res = 2;
03864    else {
03865       res = -1;
03866       if (!nullok)
03867          ast_log(LOG_WARNING,
03868             "Unable to get index for '%s' on channel %d (%s(), line %lu)\n",
03869             ast ? ast_channel_name(ast) : "", p->channel, fname, line);
03870    }
03871    return res;
03872 }
03873 
03874 /*!
03875  * \internal
03876  * \brief Obtain the specified subchannel owner lock if the owner exists.
03877  *
03878  * \param pvt Channel private struct.
03879  * \param sub_idx Subchannel owner to lock.
03880  *
03881  * \note Assumes the pvt->lock is already obtained.
03882  *
03883  * \note
03884  * Because deadlock avoidance may have been necessary, you need to confirm
03885  * the state of things before continuing.
03886  *
03887  * \return Nothing
03888  */
03889 static void dahdi_lock_sub_owner(struct dahdi_pvt *pvt, int sub_idx)
03890 {
03891    for (;;) {
03892       if (!pvt->subs[sub_idx].owner) {
03893          /* No subchannel owner pointer */
03894          break;
03895       }
03896       if (!ast_channel_trylock(pvt->subs[sub_idx].owner)) {
03897          /* Got subchannel owner lock */
03898          break;
03899       }
03900       /* We must unlock the private to avoid the possibility of a deadlock */
03901       DEADLOCK_AVOIDANCE(&pvt->lock);
03902    }
03903 }
03904 
03905 static void wakeup_sub(struct dahdi_pvt *p, int a)
03906 {
03907    dahdi_lock_sub_owner(p, a);
03908    if (p->subs[a].owner) {
03909       ast_queue_frame(p->subs[a].owner, &ast_null_frame);
03910       ast_channel_unlock(p->subs[a].owner);
03911    }
03912 }
03913 
03914 static void dahdi_queue_frame(struct dahdi_pvt *p, struct ast_frame *f)
03915 {
03916    for (;;) {
03917       if (p->owner) {
03918          if (ast_channel_trylock(p->owner)) {
03919             DEADLOCK_AVOIDANCE(&p->lock);
03920          } else {
03921             ast_queue_frame(p->owner, f);
03922             ast_channel_unlock(p->owner);
03923             break;
03924          }
03925       } else
03926          break;
03927    }
03928 }
03929 
03930 static void handle_clear_alarms(struct dahdi_pvt *p)
03931 {
03932 #if defined(HAVE_PRI)
03933    if (dahdi_sig_pri_lib_handles(p->sig) && sig_pri_is_alarm_ignored(p->pri)) {
03934       return;
03935    }
03936 #endif   /* defined(HAVE_PRI) */
03937 
03938    if (report_alarms & REPORT_CHANNEL_ALARMS) {
03939       ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel);
03940       /*** DOCUMENTATION
03941          <managerEventInstance>
03942             <synopsis>Raised when an alarm is cleared on a DAHDI channel.</synopsis>
03943          </managerEventInstance>
03944       ***/
03945       manager_event(EVENT_FLAG_SYSTEM, "AlarmClear", "Channel: %d\r\n", p->channel);
03946    }
03947    if (report_alarms & REPORT_SPAN_ALARMS && p->manages_span_alarms) {
03948       ast_log(LOG_NOTICE, "Alarm cleared on span %d\n", p->span);
03949       /*** DOCUMENTATION
03950          <managerEventInstance>
03951             <synopsis>Raised when an alarm is cleared on a DAHDI span.</synopsis>
03952          </managerEventInstance>
03953       ***/
03954       manager_event(EVENT_FLAG_SYSTEM, "SpanAlarmClear", "Span: %d\r\n", p->span);
03955    }
03956 }
03957 
03958 #ifdef HAVE_OPENR2
03959 
03960 static int dahdi_r2_answer(struct dahdi_pvt *p)
03961 {
03962    int res = 0;
03963    /* openr2 1.1.0 and older does not even define OR2_LIB_INTERFACE
03964    * and does not has support for openr2_chan_answer_call_with_mode
03965    *  */
03966 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
03967    const char *double_answer = pbx_builtin_getvar_helper(p->owner, "MFCR2_DOUBLE_ANSWER");
03968    int wants_double_answer = ast_true(double_answer) ? 1 : 0;
03969    if (!double_answer) {
03970       /* this still can result in double answer if the channel context
03971       * was configured that way */
03972       res = openr2_chan_answer_call(p->r2chan);
03973    } else if (wants_double_answer) {
03974       res = openr2_chan_answer_call_with_mode(p->r2chan, OR2_ANSWER_DOUBLE);
03975    } else {
03976       res = openr2_chan_answer_call_with_mode(p->r2chan, OR2_ANSWER_SIMPLE);
03977    }
03978 #else
03979    res = openr2_chan_answer_call(p->r2chan);
03980 #endif
03981    return res;
03982 }
03983 
03984 
03985 
03986 /* should be called with the ast_channel locked */
03987 static openr2_calling_party_category_t dahdi_r2_get_channel_category(struct ast_channel *c)
03988 {
03989    openr2_calling_party_category_t cat;
03990    const char *catstr = pbx_builtin_getvar_helper(c, "MFCR2_CATEGORY");
03991    struct dahdi_pvt *p = ast_channel_tech_pvt(c);
03992    if (ast_strlen_zero(catstr)) {
03993       ast_debug(1, "No MFC/R2 category specified for chan %s, using default %s\n",
03994             ast_channel_name(c), openr2_proto_get_category_string(p->mfcr2_category));
03995       return p->mfcr2_category;
03996    }
03997    if ((cat = openr2_proto_get_category(catstr)) == OR2_CALLING_PARTY_CATEGORY_UNKNOWN) {
03998       ast_log(LOG_WARNING, "Invalid category specified '%s' for chan %s, using default %s\n",
03999             catstr, ast_channel_name(c), openr2_proto_get_category_string(p->mfcr2_category));
04000       return p->mfcr2_category;
04001    }
04002    ast_debug(1, "Using category %s\n", catstr);
04003    return cat;
04004 }
04005 
04006 static void dahdi_r2_on_call_init(openr2_chan_t *r2chan)
04007 {
04008    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04009    ast_mutex_lock(&p->lock);
04010    if (p->mfcr2call) {
04011       ast_mutex_unlock(&p->lock);
04012       /* TODO: This can happen when some other thread just finished dahdi_request requesting this very same
04013          interface but has not yet seized the line (dahdi_call), and the far end wins and seize the line,
04014          can we avoid this somehow?, at this point when dahdi_call send the seize, it is likely that since
04015          the other end will see our seize as a forced release and drop the call, we will see an invalid
04016          pattern that will be seen and treated as protocol error. */
04017       ast_log(LOG_ERROR, "Collision of calls on chan %d detected!.\n", openr2_chan_get_number(r2chan));
04018       return;
04019    }
04020    p->mfcr2call = 1;
04021    /* better safe than sorry ... */
04022    p->cid_name[0] = '\0';
04023    p->cid_num[0] = '\0';
04024    p->cid_subaddr[0] = '\0';
04025    p->rdnis[0] = '\0';
04026    p->exten[0] = '\0';
04027    p->mfcr2_ani_index = '\0';
04028    p->mfcr2_dnis_index = '\0';
04029    p->mfcr2_dnis_matched = 0;
04030    p->mfcr2_answer_pending = 0;
04031    p->mfcr2_call_accepted = 0;
04032    ast_mutex_unlock(&p->lock);
04033    ast_verbose("New MFC/R2 call detected on chan %d.\n", openr2_chan_get_number(r2chan));
04034 }
04035 
04036 static void dahdi_r2_on_hardware_alarm(openr2_chan_t *r2chan, int alarm)
04037 {
04038    int res;
04039    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04040    ast_mutex_lock(&p->lock);
04041    p->inalarm = alarm ? 1 : 0;
04042    if (p->inalarm) {
04043       res = get_alarms(p);
04044       handle_alarms(p, res);
04045    } else {
04046       handle_clear_alarms(p);
04047    }
04048    ast_mutex_unlock(&p->lock);
04049 }
04050 
04051 static void dahdi_r2_on_os_error(openr2_chan_t *r2chan, int errorcode)
04052 {
04053    ast_log(LOG_ERROR, "OS error on chan %d: %s\n", openr2_chan_get_number(r2chan), strerror(errorcode));
04054 }
04055 
04056 static void dahdi_r2_on_protocol_error(openr2_chan_t *r2chan, openr2_protocol_error_t reason)
04057 {
04058    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04059    ast_log(LOG_ERROR, "MFC/R2 protocol error on chan %d: %s\n", openr2_chan_get_number(r2chan), openr2_proto_get_error(reason));
04060    if (p->owner) {
04061       ast_channel_hangupcause_set(p->owner, AST_CAUSE_PROTOCOL_ERROR);
04062       ast_channel_softhangup_internal_flag_add(p->owner, AST_SOFTHANGUP_DEV);
04063    }
04064    ast_mutex_lock(&p->lock);
04065    p->mfcr2call = 0;
04066    ast_mutex_unlock(&p->lock);
04067 }
04068 
04069 static void dahdi_r2_disconnect_call(struct dahdi_pvt *p, openr2_call_disconnect_cause_t cause)
04070 {
04071    if (openr2_chan_disconnect_call(p->r2chan, cause)) {
04072       ast_log(LOG_NOTICE, "Bad! failed to disconnect call on channel %d with reason %s, hope for the best!\n",
04073          p->channel, openr2_proto_get_disconnect_string(cause));
04074       /* force the chan to idle and release the call flag now since we will not see a clean on_call_end */
04075       openr2_chan_set_idle(p->r2chan);
04076       ast_mutex_lock(&p->lock);
04077       p->mfcr2call = 0;
04078       ast_mutex_unlock(&p->lock);
04079    }
04080 }
04081 
04082 static void dahdi_r2_on_call_offered(openr2_chan_t *r2chan, const char *ani, const char *dnis, openr2_calling_party_category_t category)
04083 {
04084    struct dahdi_pvt *p;
04085    struct ast_channel *c;
04086    struct ast_callid *callid = NULL;
04087    int callid_created = ast_callid_threadstorage_auto(&callid);
04088    ast_verbose("MFC/R2 call offered on chan %d. ANI = %s, DNIS = %s, Category = %s\n",
04089          openr2_chan_get_number(r2chan), ani ? ani : "(restricted)", dnis,
04090          openr2_proto_get_category_string(category));
04091    p = openr2_chan_get_client_data(r2chan);
04092    /* if collect calls are not allowed and this is a collect call, reject it! */
04093    if (!p->mfcr2_allow_collect_calls && category == OR2_CALLING_PARTY_CATEGORY_COLLECT_CALL) {
04094       ast_log(LOG_NOTICE, "Rejecting MFC/R2 collect call\n");
04095       dahdi_r2_disconnect_call(p, OR2_CAUSE_COLLECT_CALL_REJECTED);
04096       goto dahdi_r2_on_call_offered_cleanup;
04097    }
04098    ast_mutex_lock(&p->lock);
04099    p->mfcr2_recvd_category = category;
04100    /* if we're not supposed to use CID, clear whatever we have */
04101    if (!p->use_callerid) {
04102       ast_debug(1, "No CID allowed in configuration, CID is being cleared!\n");
04103       p->cid_num[0] = 0;
04104       p->cid_name[0] = 0;
04105    }
04106    /* if we're supposed to answer immediately, clear DNIS and set 's' exten */
04107    if (p->immediate || !openr2_context_get_max_dnis(openr2_chan_get_context(r2chan))) {
04108       ast_debug(1, "Setting exten => s because of immediate or 0 DNIS configured\n");
04109       p->exten[0] = 's';
04110       p->exten[1] = 0;
04111    }
04112    ast_mutex_unlock(&p->lock);
04113    if (!ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
04114       ast_log(LOG_NOTICE, "MFC/R2 call on channel %d requested non-existent extension '%s' in context '%s'. Rejecting call.\n",
04115             p->channel, p->exten, p->context);
04116       dahdi_r2_disconnect_call(p, OR2_CAUSE_UNALLOCATED_NUMBER);
04117       goto dahdi_r2_on_call_offered_cleanup;
04118    }
04119    if (!p->mfcr2_accept_on_offer) {
04120       /* The user wants us to start the PBX thread right away without accepting the call first */
04121       c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, NULL, callid);
04122       if (c) {
04123          /* Done here, don't disable reading now since we still need to generate MF tones to accept
04124             the call or reject it and detect the tone off condition of the other end, all of this
04125             will be done in the PBX thread now */
04126          goto dahdi_r2_on_call_offered_cleanup;
04127       }
04128       ast_log(LOG_WARNING, "Unable to create PBX channel in DAHDI channel %d\n", p->channel);
04129       dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER);
04130    } else if (p->mfcr2_charge_calls) {
04131       ast_debug(1, "Accepting MFC/R2 call with charge on chan %d\n", p->channel);
04132       openr2_chan_accept_call(r2chan, OR2_CALL_WITH_CHARGE);
04133    } else {
04134       ast_debug(1, "Accepting MFC/R2 call with no charge on chan %d\n", p->channel);
04135       openr2_chan_accept_call(r2chan, OR2_CALL_NO_CHARGE);
04136    }
04137 
04138 dahdi_r2_on_call_offered_cleanup:
04139    ast_callid_threadstorage_auto_clean(callid, callid_created);
04140 }
04141 
04142 static void dahdi_r2_on_call_end(openr2_chan_t *r2chan)
04143 {
04144    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04145    ast_verbose("MFC/R2 call end on channel %d\n", p->channel);
04146    ast_mutex_lock(&p->lock);
04147    p->mfcr2call = 0;
04148    ast_mutex_unlock(&p->lock);
04149 }
04150 
04151 static void dahdi_enable_ec(struct dahdi_pvt *p);
04152 static void dahdi_r2_on_call_accepted(openr2_chan_t *r2chan, openr2_call_mode_t mode)
04153 {
04154    struct dahdi_pvt *p = NULL;
04155    struct ast_channel *c = NULL;
04156    struct ast_callid *callid = NULL;
04157    int callid_created = ast_callid_threadstorage_auto(&callid);
04158    p = openr2_chan_get_client_data(r2chan);
04159    dahdi_enable_ec(p);
04160    p->mfcr2_call_accepted = 1;
04161    /* if it's an incoming call ... */
04162    if (OR2_DIR_BACKWARD == openr2_chan_get_direction(r2chan)) {
04163       ast_verbose("MFC/R2 call has been accepted on backward channel %d\n", openr2_chan_get_number(r2chan));
04164       /* If accept on offer is not set, it means at this point the PBX thread is already
04165          launched (was launched in the 'on call offered' handler) and therefore this callback
04166          is being executed already in the PBX thread rather than the monitor thread, don't launch
04167          any other thread, just disable the openr2 reading and answer the call if needed */
04168       if (!p->mfcr2_accept_on_offer) {
04169          openr2_chan_disable_read(r2chan);
04170          if (p->mfcr2_answer_pending) {
04171             ast_debug(1, "Answering MFC/R2 call after accepting it on chan %d\n", openr2_chan_get_number(r2chan));
04172             dahdi_r2_answer(p);
04173          }
04174          goto dahdi_r2_on_call_accepted_cleanup;
04175       }
04176       c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, NULL, callid);
04177       if (c) {
04178          /* chan_dahdi will take care of reading from now on in the PBX thread, tell the
04179             library to forget about it */
04180          openr2_chan_disable_read(r2chan);
04181          goto dahdi_r2_on_call_accepted_cleanup;
04182       }
04183       ast_log(LOG_WARNING, "Unable to create PBX channel in DAHDI channel %d\n", p->channel);
04184       /* failed to create the channel, bail out and report it as an out of order line */
04185       dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER);
04186       goto dahdi_r2_on_call_accepted_cleanup;
04187    }
04188    /* this is an outgoing call, no need to launch the PBX thread, most likely we're in one already */
04189    ast_verbose("MFC/R2 call has been accepted on forward channel %d\n", p->channel);
04190    p->subs[SUB_REAL].needringing = 1;
04191    p->dialing = 0;
04192    /* chan_dahdi will take care of reading from now on in the PBX thread, tell the library to forget about it */
04193    openr2_chan_disable_read(r2chan);
04194 
04195 dahdi_r2_on_call_accepted_cleanup:
04196    ast_callid_threadstorage_auto_clean(callid, callid_created);
04197 }
04198 
04199 static void dahdi_r2_on_call_answered(openr2_chan_t *r2chan)
04200 {
04201    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04202    ast_verbose("MFC/R2 call has been answered on channel %d\n", openr2_chan_get_number(r2chan));
04203    p->subs[SUB_REAL].needanswer = 1;
04204 }
04205 
04206 static void dahdi_r2_on_call_read(openr2_chan_t *r2chan, const unsigned char *buf, int buflen)
04207 {
04208    /*ast_debug(1, "Read data from dahdi channel %d\n", openr2_chan_get_number(r2chan));*/
04209 }
04210 
04211 static int dahdi_r2_cause_to_ast_cause(openr2_call_disconnect_cause_t cause)
04212 {
04213    switch (cause) {
04214    case OR2_CAUSE_BUSY_NUMBER:
04215       return AST_CAUSE_BUSY;
04216    case OR2_CAUSE_NETWORK_CONGESTION:
04217       return AST_CAUSE_CONGESTION;
04218    case OR2_CAUSE_OUT_OF_ORDER:
04219       return AST_CAUSE_DESTINATION_OUT_OF_ORDER;
04220    case OR2_CAUSE_UNALLOCATED_NUMBER:
04221       return AST_CAUSE_UNREGISTERED;
04222    case OR2_CAUSE_NO_ANSWER:
04223       return AST_CAUSE_NO_ANSWER;
04224    case OR2_CAUSE_NORMAL_CLEARING:
04225       return AST_CAUSE_NORMAL_CLEARING;
04226    case OR2_CAUSE_UNSPECIFIED:
04227    default:
04228       return AST_CAUSE_NOTDEFINED;
04229    }
04230 }
04231 
04232 static void dahdi_r2_on_call_disconnect(openr2_chan_t *r2chan, openr2_call_disconnect_cause_t cause)
04233 {
04234    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04235    char cause_str[50];
04236    struct ast_control_pvt_cause_code *cause_code;
04237    int datalen = sizeof(*cause_code);
04238 
04239    ast_verbose("MFC/R2 call disconnected on channel %d\n", openr2_chan_get_number(r2chan));
04240    ast_mutex_lock(&p->lock);
04241    if (!p->owner) {
04242       ast_mutex_unlock(&p->lock);
04243       /* no owner, therefore we can't use dahdi_hangup to disconnect, do it right now */
04244       dahdi_r2_disconnect_call(p, OR2_CAUSE_NORMAL_CLEARING);
04245       return;
04246    }
04247 
04248    snprintf(cause_str, sizeof(cause_str), "R2 DISCONNECT (%s)", openr2_proto_get_disconnect_string(cause));
04249    datalen += strlen(cause_str);
04250    cause_code = ast_alloca(datalen);
04251    memset(cause_code, 0, datalen);
04252    cause_code->ast_cause = dahdi_r2_cause_to_ast_cause(cause);
04253    ast_copy_string(cause_code->chan_name, ast_channel_name(p->owner), AST_CHANNEL_NAME);
04254    ast_copy_string(cause_code->code, cause_str, datalen + 1 - sizeof(*cause_code));
04255    ast_queue_control_data(p->owner, AST_CONTROL_PVT_CAUSE_CODE, cause_code, datalen);
04256    ast_channel_hangupcause_hash_set(p->owner, cause_code, datalen);
04257 
04258    /* when we have an owner we don't call dahdi_r2_disconnect_call here, that will
04259       be done in dahdi_hangup */
04260    if (ast_channel_state(p->owner) == AST_STATE_UP) {
04261       ast_channel_softhangup_internal_flag_add(p->owner, AST_SOFTHANGUP_DEV);
04262       ast_mutex_unlock(&p->lock);
04263    } else if (openr2_chan_get_direction(r2chan) == OR2_DIR_FORWARD) {
04264       /* being the forward side we must report what happened to the call to whoever requested it */
04265       switch (cause) {
04266       case OR2_CAUSE_BUSY_NUMBER:
04267          p->subs[SUB_REAL].needbusy = 1;
04268          break;
04269       case OR2_CAUSE_NETWORK_CONGESTION:
04270       case OR2_CAUSE_OUT_OF_ORDER:
04271       case OR2_CAUSE_UNALLOCATED_NUMBER:
04272       case OR2_CAUSE_NO_ANSWER:
04273       case OR2_CAUSE_UNSPECIFIED:
04274       case OR2_CAUSE_NORMAL_CLEARING:
04275          p->subs[SUB_REAL].needcongestion = 1;
04276          break;
04277       default:
04278          ast_channel_softhangup_internal_flag_add(p->owner, AST_SOFTHANGUP_DEV);
04279       }
04280       ast_mutex_unlock(&p->lock);
04281    } else {
04282       ast_mutex_unlock(&p->lock);
04283       /* being the backward side and not UP yet, we only need to request hangup */
04284       /* TODO: what about doing this same thing when were AST_STATE_UP? */
04285       ast_queue_hangup_with_cause(p->owner, dahdi_r2_cause_to_ast_cause(cause));
04286    }
04287 }
04288 
04289 static void dahdi_r2_write_log(openr2_log_level_t level, char *logmessage)
04290 {
04291    switch (level) {
04292    case OR2_LOG_NOTICE:
04293       ast_verbose("%s", logmessage);
04294       break;
04295    case OR2_LOG_WARNING:
04296       ast_log(LOG_WARNING, "%s", logmessage);
04297       break;
04298    case OR2_LOG_ERROR:
04299       ast_log(LOG_ERROR, "%s", logmessage);
04300       break;
04301    case OR2_LOG_STACK_TRACE:
04302    case OR2_LOG_MF_TRACE:
04303    case OR2_LOG_CAS_TRACE:
04304    case OR2_LOG_DEBUG:
04305    case OR2_LOG_EX_DEBUG:
04306       ast_debug(1, "%s", logmessage);
04307       break;
04308    default:
04309       ast_log(LOG_WARNING, "We should handle logging level %d here.\n", level);
04310       ast_debug(1, "%s", logmessage);
04311       break;
04312    }
04313 }
04314 
04315 static void dahdi_r2_on_line_blocked(openr2_chan_t *r2chan)
04316 {
04317    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04318    ast_mutex_lock(&p->lock);
04319    p->remotelyblocked = 1;
04320    ast_mutex_unlock(&p->lock);
04321    ast_log(LOG_NOTICE, "Far end blocked on chan %d\n", openr2_chan_get_number(r2chan));
04322 }
04323 
04324 static void dahdi_r2_on_line_idle(openr2_chan_t *r2chan)
04325 {
04326    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04327    ast_mutex_lock(&p->lock);
04328    p->remotelyblocked = 0;
04329    ast_mutex_unlock(&p->lock);
04330    ast_log(LOG_NOTICE, "Far end unblocked on chan %d\n", openr2_chan_get_number(r2chan));
04331 }
04332 
04333 static void dahdi_r2_on_context_log(openr2_context_t *r2context, openr2_log_level_t level, const char *fmt, va_list ap)
04334    __attribute__((format (printf, 3, 0)));
04335 static void dahdi_r2_on_context_log(openr2_context_t *r2context, openr2_log_level_t level, const char *fmt, va_list ap)
04336 {
04337 #define CONTEXT_TAG "Context - "
04338    char logmsg[256];
04339    char completemsg[sizeof(logmsg) + sizeof(CONTEXT_TAG) - 1];
04340    vsnprintf(logmsg, sizeof(logmsg), fmt, ap);
04341    snprintf(completemsg, sizeof(completemsg), CONTEXT_TAG "%s", logmsg);
04342    dahdi_r2_write_log(level, completemsg);
04343 #undef CONTEXT_TAG
04344 }
04345 
04346 static void dahdi_r2_on_chan_log(openr2_chan_t *r2chan, openr2_log_level_t level, const char *fmt, va_list ap)
04347    __attribute__((format (printf, 3, 0)));
04348 static void dahdi_r2_on_chan_log(openr2_chan_t *r2chan, openr2_log_level_t level, const char *fmt, va_list ap)
04349 {
04350 #define CHAN_TAG "Chan "
04351    char logmsg[256];
04352    char completemsg[sizeof(logmsg) + sizeof(CHAN_TAG) - 1];
04353    vsnprintf(logmsg, sizeof(logmsg), fmt, ap);
04354    snprintf(completemsg, sizeof(completemsg), CHAN_TAG "%d - %s", openr2_chan_get_number(r2chan), logmsg);
04355    dahdi_r2_write_log(level, completemsg);
04356 }
04357 
04358 static int dahdi_r2_on_dnis_digit_received(openr2_chan_t *r2chan, char digit)
04359 {
04360    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04361    /* if 'immediate' is set, let's stop requesting DNIS */
04362    if (p->immediate) {
04363       return 0;
04364    }
04365    p->exten[p->mfcr2_dnis_index] = digit;
04366    p->rdnis[p->mfcr2_dnis_index] = digit;
04367    p->mfcr2_dnis_index++;
04368    p->exten[p->mfcr2_dnis_index] = 0;
04369    p->rdnis[p->mfcr2_dnis_index] = 0;
04370    /* if the DNIS is a match and cannot match more, stop requesting DNIS */
04371    if ((p->mfcr2_dnis_matched ||
04372        (ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num) && (p->mfcr2_dnis_matched = 1))) &&
04373        !ast_matchmore_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
04374       return 0;
04375    }
04376    /* otherwise keep going */
04377    return 1;
04378 }
04379 
04380 static void dahdi_r2_on_ani_digit_received(openr2_chan_t *r2chan, char digit)
04381 {
04382    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04383    p->cid_num[p->mfcr2_ani_index] = digit;
04384    p->cid_name[p->mfcr2_ani_index] = digit;
04385    p->mfcr2_ani_index++;
04386    p->cid_num[p->mfcr2_ani_index] = 0;
04387    p->cid_name[p->mfcr2_ani_index] = 0;
04388 }
04389 
04390 static void dahdi_r2_on_billing_pulse_received(openr2_chan_t *r2chan)
04391 {
04392    ast_verbose("MFC/R2 billing pulse received on channel %d\n", openr2_chan_get_number(r2chan));
04393 }
04394 
04395 static openr2_event_interface_t dahdi_r2_event_iface = {
04396    .on_call_init = dahdi_r2_on_call_init,
04397    .on_call_offered = dahdi_r2_on_call_offered,
04398    .on_call_accepted = dahdi_r2_on_call_accepted,
04399    .on_call_answered = dahdi_r2_on_call_answered,
04400    .on_call_disconnect = dahdi_r2_on_call_disconnect,
04401    .on_call_end = dahdi_r2_on_call_end,
04402    .on_call_read = dahdi_r2_on_call_read,
04403    .on_hardware_alarm = dahdi_r2_on_hardware_alarm,
04404    .on_os_error = dahdi_r2_on_os_error,
04405    .on_protocol_error = dahdi_r2_on_protocol_error,
04406    .on_line_blocked = dahdi_r2_on_line_blocked,
04407    .on_line_idle = dahdi_r2_on_line_idle,
04408    /* cast seems to be needed to get rid of the annoying warning regarding format attribute  */
04409    .on_context_log = (openr2_handle_context_logging_func)dahdi_r2_on_context_log,
04410    .on_dnis_digit_received = dahdi_r2_on_dnis_digit_received,
04411    .on_ani_digit_received = dahdi_r2_on_ani_digit_received,
04412    /* so far we do nothing with billing pulses */
04413    .on_billing_pulse_received = dahdi_r2_on_billing_pulse_received
04414 };
04415 
04416 static inline int16_t dahdi_r2_alaw_to_linear(uint8_t sample)
04417 {
04418    return AST_ALAW(sample);
04419 }
04420 
04421 static inline uint8_t dahdi_r2_linear_to_alaw(int sample)
04422 {
04423    return AST_LIN2A(sample);
04424 }
04425 
04426 static openr2_transcoder_interface_t dahdi_r2_transcode_iface = {
04427    dahdi_r2_alaw_to_linear,
04428    dahdi_r2_linear_to_alaw
04429 };
04430 
04431 #endif /* HAVE_OPENR2 */
04432 
04433 static void swap_subs(struct dahdi_pvt *p, int a, int b)
04434 {
04435    int tchan;
04436    int tinthreeway;
04437    struct ast_channel *towner;
04438 
04439    ast_debug(1, "Swapping %d and %d\n", a, b);
04440 
04441    tchan = p->subs[a].chan;
04442    towner = p->subs[a].owner;
04443    tinthreeway = p->subs[a].inthreeway;
04444 
04445    p->subs[a].chan = p->subs[b].chan;
04446    p->subs[a].owner = p->subs[b].owner;
04447    p->subs[a].inthreeway = p->subs[b].inthreeway;
04448 
04449    p->subs[b].chan = tchan;
04450    p->subs[b].owner = towner;
04451    p->subs[b].inthreeway = tinthreeway;
04452 
04453    if (p->subs[a].owner)
04454       ast_channel_set_fd(p->subs[a].owner, 0, p->subs[a].dfd);
04455    if (p->subs[b].owner)
04456       ast_channel_set_fd(p->subs[b].owner, 0, p->subs[b].dfd);
04457    wakeup_sub(p, a);
04458    wakeup_sub(p, b);
04459 }
04460 
04461 static int dahdi_open(char *fn)
04462 {
04463    int fd;
04464    int isnum;
04465    int chan = 0;
04466    int bs;
04467    int x;
04468    isnum = 1;
04469    for (x = 0; x < strlen(fn); x++) {
04470       if (!isdigit(fn[x])) {
04471          isnum = 0;
04472          break;
04473       }
04474    }
04475    if (isnum) {
04476       chan = atoi(fn);
04477       if (chan < 1) {
04478          ast_log(LOG_WARNING, "Invalid channel number '%s'\n", fn);
04479          return -1;
04480       }
04481       fn = "/dev/dahdi/channel";
04482    }
04483    fd = open(fn, O_RDWR | O_NONBLOCK);
04484    if (fd < 0) {
04485       ast_log(LOG_WARNING, "Unable to open '%s': %s\n", fn, strerror(errno));
04486       return -1;
04487    }
04488    if (chan) {
04489       if (ioctl(fd, DAHDI_SPECIFY, &chan)) {
04490          x = errno;
04491          close(fd);
04492          errno = x;
04493          ast_log(LOG_WARNING, "Unable to specify channel %d: %s\n", chan, strerror(errno));
04494          return -1;
04495       }
04496    }
04497    bs = READ_SIZE;
04498    if (ioctl(fd, DAHDI_SET_BLOCKSIZE, &bs) == -1) {
04499       ast_log(LOG_WARNING, "Unable to set blocksize '%d': %s\n", bs,  strerror(errno));
04500       x = errno;
04501       close(fd);
04502       errno = x;
04503       return -1;
04504    }
04505    return fd;
04506 }
04507 
04508 static void dahdi_close(int fd)
04509 {
04510    if (fd > 0)
04511       close(fd);
04512 }
04513 
04514 static void dahdi_close_sub(struct dahdi_pvt *chan_pvt, int sub_num)
04515 {
04516    dahdi_close(chan_pvt->subs[sub_num].dfd);
04517    chan_pvt->subs[sub_num].dfd = -1;
04518 }
04519 
04520 #if defined(HAVE_PRI)
04521 static void dahdi_close_pri_fd(struct dahdi_pri *pri, int fd_num)
04522 {
04523    dahdi_close(pri->pri.fds[fd_num]);
04524    pri->pri.fds[fd_num] = -1;
04525 }
04526 #endif   /* defined(HAVE_PRI) */
04527 
04528 #if defined(HAVE_SS7)
04529 static void dahdi_close_ss7_fd(struct dahdi_ss7 *ss7, int fd_num)
04530 {
04531    dahdi_close(ss7->ss7.fds[fd_num]);
04532    ss7->ss7.fds[fd_num] = -1;
04533 }
04534 #endif   /* defined(HAVE_SS7) */
04535 
04536 static int dahdi_setlinear(int dfd, int linear)
04537 {
04538    return ioctl(dfd, DAHDI_SETLINEAR, &linear);
04539 }
04540 
04541 
04542 static int alloc_sub(struct dahdi_pvt *p, int x)
04543 {
04544    struct dahdi_bufferinfo bi;
04545    int res;
04546    if (p->subs[x].dfd >= 0) {
04547       ast_log(LOG_WARNING, "%s subchannel of %d already in use\n", subnames[x], p->channel);
04548       return -1;
04549    }
04550 
04551    p->subs[x].dfd = dahdi_open("/dev/dahdi/pseudo");
04552    if (p->subs[x].dfd <= -1) {
04553       ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno));
04554       return -1;
04555    }
04556 
04557    res = ioctl(p->subs[x].dfd, DAHDI_GET_BUFINFO, &bi);
04558    if (!res) {
04559       bi.txbufpolicy = p->buf_policy;
04560       bi.rxbufpolicy = p->buf_policy;
04561       bi.numbufs = p->buf_no;
04562       res = ioctl(p->subs[x].dfd, DAHDI_SET_BUFINFO, &bi);
04563       if (res < 0) {
04564          ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", x, strerror(errno));
04565       }
04566    } else
04567       ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", x, strerror(errno));
04568 
04569    if (ioctl(p->subs[x].dfd, DAHDI_CHANNO, &p->subs[x].chan) == 1) {
04570       ast_log(LOG_WARNING, "Unable to get channel number for pseudo channel on FD %d: %s\n", p->subs[x].dfd, strerror(errno));
04571       dahdi_close_sub(p, x);
04572       p->subs[x].dfd = -1;
04573       return -1;
04574    }
04575    ast_debug(1, "Allocated %s subchannel on FD %d channel %d\n", subnames[x], p->subs[x].dfd, p->subs[x].chan);
04576    return 0;
04577 }
04578 
04579 static int unalloc_sub(struct dahdi_pvt *p, int x)
04580 {
04581    if (!x) {
04582       ast_log(LOG_WARNING, "Trying to unalloc the real channel %d?!?\n", p->channel);
04583       return -1;
04584    }
04585    ast_debug(1, "Released sub %d of channel %d\n", x, p->channel);
04586    dahdi_close_sub(p, x);
04587    p->subs[x].linear = 0;
04588    p->subs[x].chan = 0;
04589    p->subs[x].owner = NULL;
04590    p->subs[x].inthreeway = 0;
04591    p->polarity = POLARITY_IDLE;
04592    memset(&p->subs[x].curconf, 0, sizeof(p->subs[x].curconf));
04593    return 0;
04594 }
04595 
04596 static int digit_to_dtmfindex(char digit)
04597 {
04598    if (isdigit(digit))
04599       return DAHDI_TONE_DTMF_BASE + (digit - '0');
04600    else if (digit >= 'A' && digit <= 'D')
04601       return DAHDI_TONE_DTMF_A + (digit - 'A');
04602    else if (digit >= 'a' && digit <= 'd')
04603       return DAHDI_TONE_DTMF_A + (digit - 'a');
04604    else if (digit == '*')
04605       return DAHDI_TONE_DTMF_s;
04606    else if (digit == '#')
04607       return DAHDI_TONE_DTMF_p;
04608    else
04609       return -1;
04610 }
04611 
04612 static int dahdi_digit_begin(struct ast_channel *chan, char digit)
04613 {
04614    struct dahdi_pvt *pvt;
04615    int idx;
04616    int dtmf = -1;
04617    int res;
04618 
04619    pvt = ast_channel_tech_pvt(chan);
04620 
04621    ast_mutex_lock(&pvt->lock);
04622 
04623    idx = dahdi_get_index(chan, pvt, 0);
04624 
04625    if ((idx != SUB_REAL) || !pvt->owner)
04626       goto out;
04627 
04628 #ifdef HAVE_PRI
04629    switch (pvt->sig) {
04630    case SIG_PRI_LIB_HANDLE_CASES:
04631       res = sig_pri_digit_begin(pvt->sig_pvt, chan, digit);
04632       if (!res)
04633          goto out;
04634       break;
04635    default:
04636       break;
04637    }
04638 #endif
04639    if ((dtmf = digit_to_dtmfindex(digit)) == -1)
04640       goto out;
04641 
04642    if (pvt->pulse || ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &dtmf)) {
04643       struct dahdi_dialoperation zo = {
04644          .op = DAHDI_DIAL_OP_APPEND,
04645       };
04646 
04647       zo.dialstr[0] = 'T';
04648       zo.dialstr[1] = digit;
04649       zo.dialstr[2] = '\0';
04650       if ((res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo)))
04651          ast_log(LOG_WARNING, "Channel %s couldn't dial digit %c: %s\n",
04652             ast_channel_name(chan), digit, strerror(errno));
04653       else
04654          pvt->dialing = 1;
04655    } else {
04656       ast_debug(1, "Channel %s started VLDTMF digit '%c'\n",
04657          ast_channel_name(chan), digit);
04658       pvt->dialing = 1;
04659       pvt->begindigit = digit;
04660    }
04661 
04662 out:
04663    ast_mutex_unlock(&pvt->lock);
04664 
04665    return 0;
04666 }
04667 
04668 static int dahdi_digit_end(struct ast_channel *chan, char digit, unsigned int duration)
04669 {
04670    struct dahdi_pvt *pvt;
04671    int res = 0;
04672    int idx;
04673    int x;
04674 
04675    pvt = ast_channel_tech_pvt(chan);
04676 
04677    ast_mutex_lock(&pvt->lock);
04678 
04679    idx = dahdi_get_index(chan, pvt, 0);
04680 
04681    if ((idx != SUB_REAL) || !pvt->owner || pvt->pulse)
04682       goto out;
04683 
04684 #ifdef HAVE_PRI
04685    /* This means that the digit was already sent via PRI signalling */
04686    if (dahdi_sig_pri_lib_handles(pvt->sig) && !pvt->begindigit) {
04687       goto out;
04688    }
04689 #endif
04690 
04691    if (pvt->begindigit) {
04692       x = -1;
04693       ast_debug(1, "Channel %s ending VLDTMF digit '%c'\n",
04694          ast_channel_name(chan), digit);
04695       res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &x);
04696       pvt->dialing = 0;
04697       pvt->begindigit = 0;
04698    }
04699 
04700 out:
04701    ast_mutex_unlock(&pvt->lock);
04702 
04703    return res;
04704 }
04705 
04706 static const char * const events[] = {
04707    "No event",
04708    "On hook",
04709    "Ring/Answered",
04710    "Wink/Flash",
04711    "Alarm",
04712    "No more alarm",
04713    "HDLC Abort",
04714    "HDLC Overrun",
04715    "HDLC Bad FCS",
04716    "Dial Complete",
04717    "Ringer On",
04718    "Ringer Off",
04719    "Hook Transition Complete",
04720    "Bits Changed",
04721    "Pulse Start",
04722    "Timer Expired",
04723    "Timer Ping",
04724    "Polarity Reversal",
04725    "Ring Begin",
04726 };
04727 
04728 static struct {
04729    int alarm;
04730    char *name;
04731 } alarms[] = {
04732    { DAHDI_ALARM_RED, "Red Alarm" },
04733    { DAHDI_ALARM_YELLOW, "Yellow Alarm" },
04734    { DAHDI_ALARM_BLUE, "Blue Alarm" },
04735    { DAHDI_ALARM_RECOVER, "Recovering" },
04736    { DAHDI_ALARM_LOOPBACK, "Loopback" },
04737    { DAHDI_ALARM_NOTOPEN, "Not Open" },
04738    { DAHDI_ALARM_NONE, "None" },
04739 };
04740 
04741 static char *alarm2str(int alm)
04742 {
04743    int x;
04744    for (x = 0; x < ARRAY_LEN(alarms); x++) {
04745       if (alarms[x].alarm & alm)
04746          return alarms[x].name;
04747    }
04748    return alm ? "Unknown Alarm" : "No Alarm";
04749 }
04750 
04751 static const char *event2str(int event)
04752 {
04753    static char buf[256];
04754    if ((event < (ARRAY_LEN(events))) && (event > -1))
04755       return events[event];
04756    sprintf(buf, "Event %d", event); /* safe */
04757    return buf;
04758 }
04759 
04760 static char *dahdi_sig2str(int sig)
04761 {
04762    static char buf[256];
04763    switch (sig) {
04764    case SIG_EM:
04765       return "E & M Immediate";
04766    case SIG_EMWINK:
04767       return "E & M Wink";
04768    case SIG_EM_E1:
04769       return "E & M E1";
04770    case SIG_FEATD:
04771       return "Feature Group D (DTMF)";
04772    case SIG_FEATDMF:
04773       return "Feature Group D (MF)";
04774    case SIG_FEATDMF_TA:
04775       return "Feature Groud D (MF) Tandem Access";
04776    case SIG_FEATB:
04777       return "Feature Group B (MF)";
04778    case SIG_E911:
04779       return "E911 (MF)";
04780    case SIG_FGC_CAMA:
04781       return "FGC/CAMA (Dialpulse)";
04782    case SIG_FGC_CAMAMF:
04783       return "FGC/CAMA (MF)";
04784    case SIG_FXSLS:
04785       return "FXS Loopstart";
04786    case SIG_FXSGS:
04787       return "FXS Groundstart";
04788    case SIG_FXSKS:
04789       return "FXS Kewlstart";
04790    case SIG_FXOLS:
04791       return "FXO Loopstart";
04792    case SIG_FXOGS:
04793       return "FXO Groundstart";
04794    case SIG_FXOKS:
04795       return "FXO Kewlstart";
04796    case SIG_PRI:
04797       return "ISDN PRI";
04798    case SIG_BRI:
04799       return "ISDN BRI Point to Point";
04800    case SIG_BRI_PTMP:
04801       return "ISDN BRI Point to MultiPoint";
04802    case SIG_SS7:
04803       return "SS7";
04804    case SIG_MFCR2:
04805       return "MFC/R2";
04806    case SIG_SF:
04807       return "SF (Tone) Immediate";
04808    case SIG_SFWINK:
04809       return "SF (Tone) Wink";
04810    case SIG_SF_FEATD:
04811       return "SF (Tone) with Feature Group D (DTMF)";
04812    case SIG_SF_FEATDMF:
04813       return "SF (Tone) with Feature Group D (MF)";
04814    case SIG_SF_FEATB:
04815       return "SF (Tone) with Feature Group B (MF)";
04816    case 0:
04817       return "Pseudo";
04818    default:
04819       snprintf(buf, sizeof(buf), "Unknown signalling %d", sig);
04820       return buf;
04821    }
04822 }
04823 
04824 #define sig2str dahdi_sig2str
04825 
04826 static int conf_add(struct dahdi_pvt *p, struct dahdi_subchannel *c, int idx, int slavechannel)
04827 {
04828    /* If the conference already exists, and we're already in it
04829       don't bother doing anything */
04830    struct dahdi_confinfo zi;
04831 
04832    memset(&zi, 0, sizeof(zi));
04833    zi.chan = 0;
04834 
04835    if (slavechannel > 0) {
04836       /* If we have only one slave, do a digital mon */
04837       zi.confmode = DAHDI_CONF_DIGITALMON;
04838       zi.confno = slavechannel;
04839    } else {
04840       if (!idx) {
04841          /* Real-side and pseudo-side both participate in conference */
04842          zi.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER |
04843             DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER;
04844       } else
04845          zi.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER;
04846       zi.confno = p->confno;
04847    }
04848    if ((zi.confno == c->curconf.confno) && (zi.confmode == c->curconf.confmode))
04849       return 0;
04850    if (c->dfd < 0)
04851       return 0;
04852    if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
04853       ast_log(LOG_WARNING, "Failed to add %d to conference %d/%d: %s\n", c->dfd, zi.confmode, zi.confno, strerror(errno));
04854       return -1;
04855    }
04856    if (slavechannel < 1) {
04857       p->confno = zi.confno;
04858    }
04859    c->curconf = zi;
04860    ast_debug(1, "Added %d to conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
04861    return 0;
04862 }
04863 
04864 static int isourconf(struct dahdi_pvt *p, struct dahdi_subchannel *c)
04865 {
04866    /* If they're listening to our channel, they're ours */
04867    if ((p->channel == c->curconf.confno) && (c->curconf.confmode == DAHDI_CONF_DIGITALMON))
04868       return 1;
04869    /* If they're a talker on our (allocated) conference, they're ours */
04870    if ((p->confno > 0) && (p->confno == c->curconf.confno) && (c->curconf.confmode & DAHDI_CONF_TALKER))
04871       return 1;
04872    return 0;
04873 }
04874 
04875 static int conf_del(struct dahdi_pvt *p, struct dahdi_subchannel *c, int idx)
04876 {
04877    struct dahdi_confinfo zi;
04878    if (/* Can't delete if there's no dfd */
04879       (c->dfd < 0) ||
04880       /* Don't delete from the conference if it's not our conference */
04881       !isourconf(p, c)
04882       /* Don't delete if we don't think it's conferenced at all (implied) */
04883       ) return 0;
04884    memset(&zi, 0, sizeof(zi));
04885    if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
04886       ast_log(LOG_WARNING, "Failed to drop %d from conference %d/%d: %s\n", c->dfd, c->curconf.confmode, c->curconf.confno, strerror(errno));
04887       return -1;
04888    }
04889    ast_debug(1, "Removed %d from conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
04890    memcpy(&c->curconf, &zi, sizeof(c->curconf));
04891    return 0;
04892 }
04893 
04894 static int isslavenative(struct dahdi_pvt *p, struct dahdi_pvt **out)
04895 {
04896    int x;
04897    int useslavenative;
04898    struct dahdi_pvt *slave = NULL;
04899    /* Start out optimistic */
04900    useslavenative = 1;
04901    /* Update conference state in a stateless fashion */
04902    for (x = 0; x < 3; x++) {
04903       /* Any three-way calling makes slave native mode *definitely* out
04904          of the question */
04905       if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway)
04906          useslavenative = 0;
04907    }
04908    /* If we don't have any 3-way calls, check to see if we have
04909       precisely one slave */
04910    if (useslavenative) {
04911       for (x = 0; x < MAX_SLAVES; x++) {
04912          if (p->slaves[x]) {
04913             if (slave) {
04914                /* Whoops already have a slave!  No
04915                   slave native and stop right away */
04916                slave = NULL;
04917                useslavenative = 0;
04918                break;
04919             } else {
04920                /* We have one slave so far */
04921                slave = p->slaves[x];
04922             }
04923          }
04924       }
04925    }
04926    /* If no slave, slave native definitely out */
04927    if (!slave)
04928       useslavenative = 0;
04929    else if (slave->law != p->law) {
04930       useslavenative = 0;
04931       slave = NULL;
04932    }
04933    if (out)
04934       *out = slave;
04935    return useslavenative;
04936 }
04937 
04938 static int reset_conf(struct dahdi_pvt *p)
04939 {
04940    p->confno = -1;
04941    memset(&p->subs[SUB_REAL].curconf, 0, sizeof(p->subs[SUB_REAL].curconf));
04942    if (p->subs[SUB_REAL].dfd > -1) {
04943       struct dahdi_confinfo zi;
04944 
04945       memset(&zi, 0, sizeof(zi));
04946       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &zi))
04947          ast_log(LOG_WARNING, "Failed to reset conferencing on channel %d: %s\n", p->channel, strerror(errno));
04948    }
04949    return 0;
04950 }
04951 
04952 static int update_conf(struct dahdi_pvt *p)
04953 {
04954    int needconf = 0;
04955    int x;
04956    int useslavenative;
04957    struct dahdi_pvt *slave = NULL;
04958 
04959    useslavenative = isslavenative(p, &slave);
04960    /* Start with the obvious, general stuff */
04961    for (x = 0; x < 3; x++) {
04962       /* Look for three way calls */
04963       if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) {
04964          conf_add(p, &p->subs[x], x, 0);
04965          needconf++;
04966       } else {
04967          conf_del(p, &p->subs[x], x);
04968       }
04969    }
04970    /* If we have a slave, add him to our conference now. or DAX
04971       if this is slave native */
04972    for (x = 0; x < MAX_SLAVES; x++) {
04973       if (p->slaves[x]) {
04974          if (useslavenative)
04975             conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
04976          else {
04977             conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
04978             needconf++;
04979          }
04980       }
04981    }
04982    /* If we're supposed to be in there, do so now */
04983    if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
04984       if (useslavenative)
04985          conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
04986       else {
04987          conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
04988          needconf++;
04989       }
04990    }
04991    /* If we have a master, add ourselves to his conference */
04992    if (p->master) {
04993       if (isslavenative(p->master, NULL)) {
04994          conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
04995       } else {
04996          conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
04997       }
04998    }
04999    if (!needconf) {
05000       /* Nobody is left (or should be left) in our conference.
05001          Kill it. */
05002       p->confno = -1;
05003    }
05004    ast_debug(1, "Updated conferencing on %d, with %d conference users\n", p->channel, needconf);
05005    return 0;
05006 }
05007 
05008 static void dahdi_enable_ec(struct dahdi_pvt *p)
05009 {
05010    int res;
05011    if (!p)
05012       return;
05013    if (p->echocanon) {
05014       ast_debug(1, "Echo cancellation already on\n");
05015       return;
05016    }
05017    if (p->digital) {
05018       ast_debug(1, "Echo cancellation isn't required on digital connection\n");
05019       return;
05020    }
05021    if (p->echocancel.head.tap_length) {
05022 #if defined(HAVE_PRI) || defined(HAVE_SS7)
05023       switch (p->sig) {
05024 #if defined(HAVE_PRI)
05025       case SIG_PRI_LIB_HANDLE_CASES:
05026          if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
05027             /*
05028              * PRI nobch pseudo channel.  Does not need ec anyway.
05029              * Does not handle ioctl(DAHDI_AUDIOMODE)
05030              */
05031             return;
05032          }
05033          /* Fall through */
05034 #endif   /* defined(HAVE_PRI) */
05035 #if defined(HAVE_SS7)
05036       case SIG_SS7:
05037 #endif   /* defined(HAVE_SS7) */
05038          {
05039             int x = 1;
05040 
05041             res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x);
05042             if (res)
05043                ast_log(LOG_WARNING,
05044                   "Unable to enable audio mode on channel %d (%s)\n",
05045                   p->channel, strerror(errno));
05046          }
05047          break;
05048       default:
05049          break;
05050       }
05051 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
05052       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &p->echocancel);
05053       if (res) {
05054          ast_log(LOG_WARNING, "Unable to enable echo cancellation on channel %d (%s)\n", p->channel, strerror(errno));
05055       } else {
05056          p->echocanon = 1;
05057          ast_debug(1, "Enabled echo cancellation on channel %d\n", p->channel);
05058       }
05059    } else
05060       ast_debug(1, "No echo cancellation requested\n");
05061 }
05062 
05063 static void dahdi_train_ec(struct dahdi_pvt *p)
05064 {
05065    int x;
05066    int res;
05067 
05068    if (p && p->echocanon && p->echotraining) {
05069       x = p->echotraining;
05070       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOTRAIN, &x);
05071       if (res)
05072          ast_log(LOG_WARNING, "Unable to request echo training on channel %d: %s\n", p->channel, strerror(errno));
05073       else
05074          ast_debug(1, "Engaged echo training on channel %d\n", p->channel);
05075    } else {
05076       ast_debug(1, "No echo training requested\n");
05077    }
05078 }
05079 
05080 static void dahdi_disable_ec(struct dahdi_pvt *p)
05081 {
05082    int res;
05083 
05084    if (p->echocanon) {
05085       struct dahdi_echocanparams ecp = { .tap_length = 0 };
05086 
05087       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &ecp);
05088 
05089       if (res)
05090          ast_log(LOG_WARNING, "Unable to disable echo cancellation on channel %d: %s\n", p->channel, strerror(errno));
05091       else
05092          ast_debug(1, "Disabled echo cancellation on channel %d\n", p->channel);
05093    }
05094 
05095    p->echocanon = 0;
05096 }
05097 
05098 /* perform a dynamic range compression transform on the given sample */
05099 static int drc_sample(int sample, float drc)
05100 {
05101    float neg;
05102    float shallow, steep;
05103    float max = SHRT_MAX;
05104    
05105    neg = (sample < 0 ? -1 : 1);
05106    steep = drc*sample;
05107    shallow = neg*(max-max/drc)+(float)sample/drc;
05108    if (abs(steep) < abs(shallow)) {
05109       sample = steep;
05110    }
05111    else {
05112       sample = shallow;
05113    }
05114 
05115    return sample;
05116 }
05117 
05118 
05119 static void fill_txgain(struct dahdi_gains *g, float gain, float drc, int law)
05120 {
05121    int j;
05122    int k;
05123 
05124    float linear_gain = pow(10.0, gain / 20.0);
05125 
05126    switch (law) {
05127    case DAHDI_LAW_ALAW:
05128       for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
05129          if (gain || drc) {
05130             k = AST_ALAW(j);
05131             if (drc) {
05132                k = drc_sample(k, drc);
05133             }
05134             k = (float)k * linear_gain;
05135             if (k > 32767) {
05136                k = 32767;
05137             } else if (k < -32768) {
05138                k = -32768;
05139             }
05140             g->txgain[j] = AST_LIN2A(k);
05141          } else {
05142             g->txgain[j] = j;
05143          }
05144       }
05145       break;
05146    case DAHDI_LAW_MULAW:
05147       for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
05148          if (gain || drc) {
05149             k = AST_MULAW(j);
05150             if (drc) {
05151                k = drc_sample(k, drc);
05152             }
05153             k = (float)k * linear_gain;
05154             if (k > 32767) {
05155                k = 32767;
05156             } else if (k < -32768) {
05157                k = -32768;
05158             }
05159             g->txgain[j] = AST_LIN2MU(k);
05160 
05161          } else {
05162             g->txgain[j] = j;
05163          }
05164       }
05165       break;
05166    }
05167 }
05168 
05169 static void fill_rxgain(struct dahdi_gains *g, float gain, float drc, int law)
05170 {
05171    int j;
05172    int k;
05173    float linear_gain = pow(10.0, gain / 20.0);
05174 
05175    switch (law) {
05176    case DAHDI_LAW_ALAW:
05177       for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
05178          if (gain || drc) {
05179             k = AST_ALAW(j);
05180             if (drc) {
05181                k = drc_sample(k, drc);
05182             }
05183             k = (float)k * linear_gain;
05184             if (k > 32767) {
05185                k = 32767;
05186             } else if (k < -32768) {
05187                k = -32768;
05188             }
05189             g->rxgain[j] = AST_LIN2A(k);
05190          } else {
05191             g->rxgain[j] = j;
05192          }
05193       }
05194       break;
05195    case DAHDI_LAW_MULAW:
05196       for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
05197          if (gain || drc) {
05198             k = AST_MULAW(j);
05199             if (drc) {
05200                k = drc_sample(k, drc);
05201             }
05202             k = (float)k * linear_gain;
05203             if (k > 32767) {
05204                k = 32767;
05205             } else if (k < -32768) {
05206                k = -32768;
05207             }
05208             g->rxgain[j] = AST_LIN2MU(k);
05209          } else {
05210             g->rxgain[j] = j;
05211          }
05212       }
05213       break;
05214    }
05215 }
05216 
05217 static int set_actual_txgain(int fd, float gain, float drc, int law)
05218 {
05219    struct dahdi_gains g;
05220    int res;
05221 
05222    memset(&g, 0, sizeof(g));
05223    res = ioctl(fd, DAHDI_GETGAINS, &g);
05224    if (res) {
05225       ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
05226       return res;
05227    }
05228 
05229    fill_txgain(&g, gain, drc, law);
05230 
05231    return ioctl(fd, DAHDI_SETGAINS, &g);
05232 }
05233 
05234 static int set_actual_rxgain(int fd, float gain, float drc, int law)
05235 {
05236    struct dahdi_gains g;
05237    int res;
05238 
05239    memset(&g, 0, sizeof(g));
05240    res = ioctl(fd, DAHDI_GETGAINS, &g);
05241    if (res) {
05242       ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
05243       return res;
05244    }
05245 
05246    fill_rxgain(&g, gain, drc, law);
05247 
05248    return ioctl(fd, DAHDI_SETGAINS, &g);
05249 }
05250 
05251 static int set_actual_gain(int fd, float rxgain, float txgain, float rxdrc, float txdrc, int law)
05252 {
05253    return set_actual_txgain(fd, txgain, txdrc, law) | set_actual_rxgain(fd, rxgain, rxdrc, law);
05254 }
05255 
05256 static int bump_gains(struct dahdi_pvt *p)
05257 {
05258    int res;
05259 
05260    /* Bump receive gain by value stored in cid_rxgain */
05261    res = set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain + p->cid_rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
05262    if (res) {
05263       ast_log(LOG_WARNING, "Unable to bump gain: %s\n", strerror(errno));
05264       return -1;
05265    }
05266 
05267    return 0;
05268 }
05269 
05270 static int restore_gains(struct dahdi_pvt *p)
05271 {
05272    int res;
05273 
05274    res = set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
05275    if (res) {
05276       ast_log(LOG_WARNING, "Unable to restore gains: %s\n", strerror(errno));
05277       return -1;
05278    }
05279 
05280    return 0;
05281 }
05282 
05283 static inline int dahdi_set_hook(int fd, int hs)
05284 {
05285    int x, res;
05286 
05287    x = hs;
05288    res = ioctl(fd, DAHDI_HOOK, &x);
05289 
05290    if (res < 0) {
05291       if (errno == EINPROGRESS)
05292          return 0;
05293       ast_log(LOG_WARNING, "DAHDI hook failed returned %d (trying %d): %s\n", res, hs, strerror(errno));
05294       /* will expectedly fail if phone is off hook during operation, such as during a restart */
05295    }
05296 
05297    return res;
05298 }
05299 
05300 static inline int dahdi_confmute(struct dahdi_pvt *p, int muted)
05301 {
05302    int x, res;
05303 
05304    x = muted;
05305 #if defined(HAVE_PRI) || defined(HAVE_SS7)
05306    switch (p->sig) {
05307 #if defined(HAVE_PRI)
05308    case SIG_PRI_LIB_HANDLE_CASES:
05309       if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
05310          /* PRI nobch pseudo channel.  Does not handle ioctl(DAHDI_AUDIOMODE) */
05311          break;
05312       }
05313       /* Fall through */
05314 #endif   /* defined(HAVE_PRI) */
05315 #if defined(HAVE_SS7)
05316    case SIG_SS7:
05317 #endif   /* defined(HAVE_SS7) */
05318       {
05319          int y = 1;
05320 
05321          res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &y);
05322          if (res)
05323             ast_log(LOG_WARNING, "Unable to set audio mode on %d: %s\n",
05324                p->channel, strerror(errno));
05325       }
05326       break;
05327    default:
05328       break;
05329    }
05330 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
05331    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_CONFMUTE, &x);
05332    if (res < 0)
05333       ast_log(LOG_WARNING, "DAHDI confmute(%d) failed on channel %d: %s\n", muted, p->channel, strerror(errno));
05334    return res;
05335 }
05336 
05337 static int save_conference(struct dahdi_pvt *p)
05338 {
05339    struct dahdi_confinfo c;
05340    int res;
05341    if (p->saveconf.confmode) {
05342       ast_log(LOG_WARNING, "Can't save conference -- already in use\n");
05343       return -1;
05344    }
05345    p->saveconf.chan = 0;
05346    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &p->saveconf);
05347    if (res) {
05348       ast_log(LOG_WARNING, "Unable to get conference info: %s\n", strerror(errno));
05349       p->saveconf.confmode = 0;
05350       return -1;
05351    }
05352    memset(&c, 0, sizeof(c));
05353    c.confmode = DAHDI_CONF_NORMAL;
05354    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &c);
05355    if (res) {
05356       ast_log(LOG_WARNING, "Unable to set conference info: %s\n", strerror(errno));
05357       return -1;
05358    }
05359    ast_debug(1, "Disabled conferencing\n");
05360    return 0;
05361 }
05362 
05363 static int restore_conference(struct dahdi_pvt *p)
05364 {
05365    int res;
05366    if (p->saveconf.confmode) {
05367       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &p->saveconf);
05368       p->saveconf.confmode = 0;
05369       if (res) {
05370          ast_log(LOG_WARNING, "Unable to restore conference info: %s\n", strerror(errno));
05371          return -1;
05372       }
05373       ast_debug(1, "Restored conferencing\n");
05374    }
05375    return 0;
05376 }
05377 
05378 static int send_cwcidspill(struct dahdi_pvt *p)
05379 {
05380    struct ast_format tmpfmt;
05381 
05382    p->callwaitcas = 0;
05383    p->cidcwexpire = 0;
05384    p->cid_suppress_expire = 0;
05385    if (!(p->cidspill = ast_malloc(MAX_CALLERID_SIZE)))
05386       return -1;
05387    p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, p->callwait_name, p->callwait_num, ast_format_set(&tmpfmt, AST_LAW(p), 0));
05388    /* Make sure we account for the end */
05389    p->cidlen += READ_SIZE * 4;
05390    p->cidpos = 0;
05391    send_callerid(p);
05392    ast_verb(3, "CPE supports Call Waiting Caller*ID.  Sending '%s/%s'\n", p->callwait_name, p->callwait_num);
05393    return 0;
05394 }
05395 
05396 static int has_voicemail(struct dahdi_pvt *p)
05397 {
05398    int new_msgs;
05399    struct ast_event *event;
05400    char *mailbox, *context;
05401 
05402    mailbox = context = ast_strdupa(p->mailbox);
05403    strsep(&context, "@");
05404    if (ast_strlen_zero(context))
05405       context = "default";
05406 
05407    event = ast_event_get_cached(AST_EVENT_MWI,
05408       AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
05409       AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
05410       AST_EVENT_IE_END);
05411 
05412    if (event) {
05413       new_msgs = ast_event_get_ie_uint(event, AST_EVENT_IE_NEWMSGS);
05414       ast_event_destroy(event);
05415    } else
05416       new_msgs = ast_app_has_voicemail(p->mailbox, NULL);
05417 
05418    return new_msgs;
05419 }
05420 
05421 
05422 
05423 static int send_callerid(struct dahdi_pvt *p)
05424 {
05425    /* Assumes spill in p->cidspill, p->cidlen in length and we're p->cidpos into it */
05426    int res;
05427    /* Take out of linear mode if necessary */
05428    if (p->subs[SUB_REAL].linear) {
05429       p->subs[SUB_REAL].linear = 0;
05430       dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
05431    }
05432    while (p->cidpos < p->cidlen) {
05433       res = write(p->subs[SUB_REAL].dfd, p->cidspill + p->cidpos, p->cidlen - p->cidpos);
05434       ast_debug(4, "writing callerid at pos %d of %d, res = %d\n", p->cidpos, p->cidlen, res);
05435       if (res < 0) {
05436          if (errno == EAGAIN)
05437             return 0;
05438          else {
05439             ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
05440             return -1;
05441          }
05442       }
05443       if (!res)
05444          return 0;
05445       p->cidpos += res;
05446    }
05447    p->cid_suppress_expire = CALLWAITING_SUPPRESS_SAMPLES;
05448    ast_free(p->cidspill);
05449    p->cidspill = NULL;
05450    if (p->callwaitcas) {
05451       /* Wait for CID/CW to expire */
05452       p->cidcwexpire = CIDCW_EXPIRE_SAMPLES;
05453       p->cid_suppress_expire = p->cidcwexpire;
05454    } else
05455       restore_conference(p);
05456    return 0;
05457 }
05458 
05459 static int dahdi_callwait(struct ast_channel *ast)
05460 {
05461    struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
05462    struct ast_format tmpfmt;
05463    p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
05464    if (p->cidspill) {
05465       ast_log(LOG_WARNING, "Spill already exists?!?\n");
05466       ast_free(p->cidspill);
05467    }
05468 
05469    /*
05470     * SAS: Subscriber Alert Signal, 440Hz for 300ms
05471     * CAS: CPE Alert Signal, 2130Hz * 2750Hz sine waves
05472     */
05473    if (!(p->cidspill = ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE * 4)))
05474       return -1;
05475    save_conference(p);
05476    /* Silence */
05477    memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
05478    if (!p->callwaitrings && p->callwaitingcallerid) {
05479       ast_gen_cas(p->cidspill, 1, 2400 + 680, ast_format_set(&tmpfmt, AST_LAW(p), 0));
05480       p->callwaitcas = 1;
05481       p->cidlen = 2400 + 680 + READ_SIZE * 4;
05482    } else {
05483       ast_gen_cas(p->cidspill, 1, 2400, ast_format_set(&tmpfmt, AST_LAW(p), 0));
05484       p->callwaitcas = 0;
05485       p->cidlen = 2400 + READ_SIZE * 4;
05486    }
05487    p->cidpos = 0;
05488    send_callerid(p);
05489 
05490    return 0;
05491 }
05492 
05493 static int dahdi_call(struct ast_channel *ast, const char *rdest, int timeout)
05494 {
05495    struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
05496    int x, res, mysig;
05497    char *dest;
05498    AST_DECLARE_APP_ARGS(args,
05499       AST_APP_ARG(group);  /* channel/group token */
05500       AST_APP_ARG(ext); /* extension token */
05501       //AST_APP_ARG(opts); /* options token */
05502       AST_APP_ARG(other);  /* Any remining unused arguments */
05503    );
05504 
05505    ast_mutex_lock(&p->lock);
05506    ast_copy_string(p->dialdest, rdest, sizeof(p->dialdest));
05507 
05508    /* Split the dialstring */
05509    dest = ast_strdupa(rdest);
05510    AST_NONSTANDARD_APP_ARGS(args, dest, '/');
05511    if (!args.ext) {
05512       args.ext = "";
05513    }
05514 
05515 #if defined(HAVE_PRI)
05516    if (dahdi_sig_pri_lib_handles(p->sig)) {
05517       char *subaddr;
05518 
05519       sig_pri_extract_called_num_subaddr(p->sig_pvt, rdest, p->exten, sizeof(p->exten));
05520 
05521       /* Remove any subaddress for uniformity with incoming calls. */
05522       subaddr = strchr(p->exten, ':');
05523       if (subaddr) {
05524          *subaddr = '\0';
05525       }
05526    } else
05527 #endif   /* defined(HAVE_PRI) */
05528    {
05529       ast_copy_string(p->exten, args.ext, sizeof(p->exten));
05530    }
05531 
05532    if ((ast_channel_state(ast) == AST_STATE_BUSY)) {
05533       p->subs[SUB_REAL].needbusy = 1;
05534       ast_mutex_unlock(&p->lock);
05535       return 0;
05536    }
05537    if ((ast_channel_state(ast) != AST_STATE_DOWN) && (ast_channel_state(ast) != AST_STATE_RESERVED)) {
05538       ast_log(LOG_WARNING, "dahdi_call called on %s, neither down nor reserved\n", ast_channel_name(ast));
05539       ast_mutex_unlock(&p->lock);
05540       return -1;
05541    }
05542    p->waitingfordt.tv_sec = 0;
05543    p->dialednone = 0;
05544    if ((p->radio || (p->oprmode < 0)))  /* if a radio channel, up immediately */
05545    {
05546       /* Special pseudo -- automatically up */
05547       ast_setstate(ast, AST_STATE_UP);
05548       ast_mutex_unlock(&p->lock);
05549       return 0;
05550    }
05551    x = DAHDI_FLUSH_READ | DAHDI_FLUSH_WRITE;
05552    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
05553    if (res)
05554       ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", p->channel, strerror(errno));
05555    p->outgoing = 1;
05556 
05557    if (IS_DIGITAL(ast_channel_transfercapability(ast))){
05558       set_actual_gain(p->subs[SUB_REAL].dfd, 0, 0, p->rxdrc, p->txdrc, p->law);
05559    } else {
05560       set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
05561    }  
05562 
05563 #ifdef HAVE_PRI
05564    if (dahdi_sig_pri_lib_handles(p->sig)) {
05565       res = sig_pri_call(p->sig_pvt, ast, rdest, timeout,
05566          (p->law == DAHDI_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW);
05567       ast_mutex_unlock(&p->lock);
05568       return res;
05569    }
05570 #endif
05571 
05572 #if defined(HAVE_SS7)
05573    if (p->sig == SIG_SS7) {
05574       res = sig_ss7_call(p->sig_pvt, ast, rdest);
05575       ast_mutex_unlock(&p->lock);
05576       return res;
05577    }
05578 #endif   /* defined(HAVE_SS7) */
05579 
05580    /* If this is analog signalling we can exit here */
05581    if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
05582       p->callwaitrings = 0;
05583       res = analog_call(p->sig_pvt, ast, rdest, timeout);
05584       ast_mutex_unlock(&p->lock);
05585       return res;
05586    }
05587 
05588    mysig = p->outsigmod > -1 ? p->outsigmod : p->sig;
05589    switch (mysig) {
05590    case 0:
05591       /* Special pseudo -- automatically up*/
05592       ast_setstate(ast, AST_STATE_UP);
05593       break;
05594    case SIG_MFCR2:
05595       break;
05596    default:
05597       ast_debug(1, "not yet implemented\n");
05598       ast_mutex_unlock(&p->lock);
05599       return -1;
05600    }
05601 
05602 #ifdef HAVE_OPENR2
05603    if (p->mfcr2) {
05604       openr2_calling_party_category_t chancat;
05605       int callres = 0;
05606       char *c, *l;
05607 
05608       /* We'll get it in a moment -- but use dialdest to store pre-setup_ack digits */
05609       p->dialdest[0] = '\0';
05610 
05611       c = args.ext;
05612       if (!p->hidecallerid) {
05613          l = ast_channel_connected(ast)->id.number.valid ? ast_channel_connected(ast)->id.number.str : NULL;
05614       } else {
05615          l = NULL;
05616       }
05617       if (strlen(c) < p->stripmsd) {
05618          ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
05619          ast_mutex_unlock(&p->lock);
05620          return -1;
05621       }
05622       p->dialing = 1;
05623       chancat = dahdi_r2_get_channel_category(ast);
05624       callres = openr2_chan_make_call(p->r2chan, l, (c + p->stripmsd), chancat);
05625       if (-1 == callres) {
05626          ast_mutex_unlock(&p->lock);
05627          ast_log(LOG_ERROR, "unable to make new MFC/R2 call!\n");
05628          return -1;
05629       }
05630       p->mfcr2_call_accepted = 0;
05631       p->mfcr2_progress_sent = 0;
05632       ast_setstate(ast, AST_STATE_DIALING);
05633    }
05634 #endif /* HAVE_OPENR2 */
05635    ast_mutex_unlock(&p->lock);
05636    return 0;
05637 }
05638 
05639 /*!
05640  * \internal
05641  * \brief Insert the given chan_dahdi interface structure into the interface list.
05642  * \since 1.8
05643  *
05644  * \param pvt chan_dahdi private interface structure to insert.
05645  *
05646  * \details
05647  * The interface list is a doubly linked list sorted by the chan_dahdi channel number.
05648  * Any duplicates are inserted after the existing entries.
05649  *
05650  * \note The new interface must not already be in the list.
05651  *
05652  * \return Nothing
05653  */
05654 static void dahdi_iflist_insert(struct dahdi_pvt *pvt)
05655 {
05656    struct dahdi_pvt *cur;
05657 
05658    pvt->which_iflist = DAHDI_IFLIST_MAIN;
05659 
05660    /* Find place in middle of list for the new interface. */
05661    for (cur = iflist; cur; cur = cur->next) {
05662       if (pvt->channel < cur->channel) {
05663          /* New interface goes before the current interface. */
05664          pvt->prev = cur->prev;
05665          pvt->next = cur;
05666          if (cur->prev) {
05667             /* Insert into the middle of the list. */
05668             cur->prev->next = pvt;
05669          } else {
05670             /* Insert at head of list. */
05671             iflist = pvt;
05672          }
05673          cur->prev = pvt;
05674          return;
05675       }
05676    }
05677 
05678    /* New interface goes onto the end of the list */
05679    pvt->prev = ifend;
05680    pvt->next = NULL;
05681    if (ifend) {
05682       ifend->next = pvt;
05683    }
05684    ifend = pvt;
05685    if (!iflist) {
05686       /* List was empty */
05687       iflist = pvt;
05688    }
05689 }
05690 
05691 /*!
05692  * \internal
05693  * \brief Extract the given chan_dahdi interface structure from the interface list.
05694  * \since 1.8
05695  *
05696  * \param pvt chan_dahdi private interface structure to extract.
05697  *
05698  * \note
05699  * The given interface structure can be either in the interface list or a stand alone
05700  * structure that has not been put in the list if the next and prev pointers are NULL.
05701  *
05702  * \return Nothing
05703  */
05704 static void dahdi_iflist_extract(struct dahdi_pvt *pvt)
05705 {
05706    /* Extract from the forward chain. */
05707    if (pvt->prev) {
05708       pvt->prev->next = pvt->next;
05709    } else if (iflist == pvt) {
05710       /* Node is at the head of the list. */
05711       iflist = pvt->next;
05712    }
05713 
05714    /* Extract from the reverse chain. */
05715    if (pvt->next) {
05716       pvt->next->prev = pvt->prev;
05717    } else if (ifend == pvt) {
05718       /* Node is at the end of the list. */
05719       ifend = pvt->prev;
05720    }
05721 
05722    /* Node is no longer in the list. */
05723    pvt->which_iflist = DAHDI_IFLIST_NONE;
05724    pvt->prev = NULL;
05725    pvt->next = NULL;
05726 }
05727 
05728 #if defined(HAVE_PRI)
05729 /*!
05730  * \internal
05731  * \brief Insert the given chan_dahdi interface structure into the no B channel list.
05732  * \since 1.8
05733  *
05734  * \param pri sig_pri span control structure holding no B channel list.
05735  * \param pvt chan_dahdi private interface structure to insert.
05736  *
05737  * \details
05738  * The interface list is a doubly linked list sorted by the chan_dahdi channel number.
05739  * Any duplicates are inserted after the existing entries.
05740  *
05741  * \note The new interface must not already be in the list.
05742  *
05743  * \return Nothing
05744  */
05745 static void dahdi_nobch_insert(struct sig_pri_span *pri, struct dahdi_pvt *pvt)
05746 {
05747    struct dahdi_pvt *cur;
05748 
05749    pvt->which_iflist = DAHDI_IFLIST_NO_B_CHAN;
05750 
05751    /* Find place in middle of list for the new interface. */
05752    for (cur = pri->no_b_chan_iflist; cur; cur = cur->next) {
05753       if (pvt->channel < cur->channel) {
05754          /* New interface goes before the current interface. */
05755          pvt->prev = cur->prev;
05756          pvt->next = cur;
05757          if (cur->prev) {
05758             /* Insert into the middle of the list. */
05759             cur->prev->next = pvt;
05760          } else {
05761             /* Insert at head of list. */
05762             pri->no_b_chan_iflist = pvt;
05763          }
05764          cur->prev = pvt;
05765          return;
05766       }
05767    }
05768 
05769    /* New interface goes onto the end of the list */
05770    pvt->prev = pri->no_b_chan_end;
05771    pvt->next = NULL;
05772    if (pri->no_b_chan_end) {
05773       ((struct dahdi_pvt *) pri->no_b_chan_end)->next = pvt;
05774    }
05775    pri->no_b_chan_end = pvt;
05776    if (!pri->no_b_chan_iflist) {
05777       /* List was empty */
05778       pri->no_b_chan_iflist = pvt;
05779    }
05780 }
05781 #endif   /* defined(HAVE_PRI) */
05782 
05783 #if defined(HAVE_PRI)
05784 /*!
05785  * \internal
05786  * \brief Extract the given chan_dahdi interface structure from the no B channel list.
05787  * \since 1.8
05788  *
05789  * \param pri sig_pri span control structure holding no B channel list.
05790  * \param pvt chan_dahdi private interface structure to extract.
05791  *
05792  * \note
05793  * The given interface structure can be either in the interface list or a stand alone
05794  * structure that has not been put in the list if the next and prev pointers are NULL.
05795  *
05796  * \return Nothing
05797  */
05798 static void dahdi_nobch_extract(struct sig_pri_span *pri, struct dahdi_pvt *pvt)
05799 {
05800    /* Extract from the forward chain. */
05801    if (pvt->prev) {
05802       pvt->prev->next = pvt->next;
05803    } else if (pri->no_b_chan_iflist == pvt) {
05804       /* Node is at the head of the list. */
05805       pri->no_b_chan_iflist = pvt->next;
05806    }
05807 
05808    /* Extract from the reverse chain. */
05809    if (pvt->next) {
05810       pvt->next->prev = pvt->prev;
05811    } else if (pri->no_b_chan_end == pvt) {
05812       /* Node is at the end of the list. */
05813       pri->no_b_chan_end = pvt->prev;
05814    }
05815 
05816    /* Node is no longer in the list. */
05817    pvt->which_iflist = DAHDI_IFLIST_NONE;
05818    pvt->prev = NULL;
05819    pvt->next = NULL;
05820 }
05821 #endif   /* defined(HAVE_PRI) */
05822 
05823 #if defined(HAVE_PRI)
05824 /*!
05825  * \internal
05826  * \brief Unlink the channel interface from the PRI private pointer array.
05827  * \since 1.8
05828  *
05829  * \param pvt chan_dahdi private interface structure to unlink.
05830  *
05831  * \return Nothing
05832  */
05833 static void dahdi_unlink_pri_pvt(struct dahdi_pvt *pvt)
05834 {
05835    unsigned idx;
05836    struct sig_pri_span *pri;
05837 
05838    pri = pvt->pri;
05839    if (!pri) {
05840       /* Not PRI signaling so cannot be in a PRI private pointer array. */
05841       return;
05842    }
05843    ast_mutex_lock(&pri->lock);
05844    for (idx = 0; idx < pri->numchans; ++idx) {
05845       if (pri->pvts[idx] == pvt->sig_pvt) {
05846          pri->pvts[idx] = NULL;
05847          ast_mutex_unlock(&pri->lock);
05848          return;
05849       }
05850    }
05851    ast_mutex_unlock(&pri->lock);
05852 }
05853 #endif   /* defined(HAVE_PRI) */
05854 
05855 #if defined(HAVE_SS7)
05856 /*!
05857  * \internal
05858  * \brief Unlink the channel interface from the SS7 private pointer array.
05859  * \since 1.8
05860  *
05861  * \param pvt chan_dahdi private interface structure to unlink.
05862  *
05863  * \return Nothing
05864  */
05865 static void dahdi_unlink_ss7_pvt(struct dahdi_pvt *pvt)
05866 {
05867    unsigned idx;
05868    struct sig_ss7_linkset *ss7;
05869 
05870    ss7 = pvt->ss7;
05871    if (!ss7) {
05872       /* Not SS7 signaling so cannot be in a SS7 private pointer array. */
05873       return;
05874    }
05875    ast_mutex_lock(&ss7->lock);
05876    for (idx = 0; idx < ss7->numchans; ++idx) {
05877       if (ss7->pvts[idx] == pvt->sig_pvt) {
05878          ss7->pvts[idx] = NULL;
05879          ast_mutex_unlock(&ss7->lock);
05880          return;
05881       }
05882    }
05883    ast_mutex_unlock(&ss7->lock);
05884 }
05885 #endif   /* defined(HAVE_SS7) */
05886 
05887 static struct dahdi_pvt *find_next_iface_in_span(struct dahdi_pvt *cur)
05888 {
05889    if (cur->next && cur->next->span == cur->span) {
05890       return cur->next;
05891    } else if (cur->prev && cur->prev->span == cur->span) {
05892       return cur->prev;
05893    }
05894 
05895    return NULL;
05896 }
05897 
05898 static void destroy_dahdi_pvt(struct dahdi_pvt *pvt)
05899 {
05900    struct dahdi_pvt *p = pvt;
05901 
05902    if (p->manages_span_alarms) {
05903       struct dahdi_pvt *next = find_next_iface_in_span(p);
05904       if (next) {
05905          next->manages_span_alarms = 1;
05906       }
05907    }
05908 
05909    /* Remove channel from the list */
05910 #if defined(HAVE_PRI)
05911    dahdi_unlink_pri_pvt(p);
05912 #endif   /* defined(HAVE_PRI) */
05913 #if defined(HAVE_SS7)
05914    dahdi_unlink_ss7_pvt(p);
05915 #endif   /* defined(HAVE_SS7) */
05916    switch (pvt->which_iflist) {
05917    case DAHDI_IFLIST_NONE:
05918       break;
05919    case DAHDI_IFLIST_MAIN:
05920       dahdi_iflist_extract(p);
05921       break;
05922 #if defined(HAVE_PRI)
05923    case DAHDI_IFLIST_NO_B_CHAN:
05924       if (p->pri) {
05925          dahdi_nobch_extract(p->pri, p);
05926       }
05927       break;
05928 #endif   /* defined(HAVE_PRI) */
05929    }
05930 
05931    if (p->sig_pvt) {
05932       if (analog_lib_handles(p->sig, 0, 0)) {
05933          analog_delete(p->sig_pvt);
05934       }
05935       switch (p->sig) {
05936 #if defined(HAVE_PRI)
05937       case SIG_PRI_LIB_HANDLE_CASES:
05938          sig_pri_chan_delete(p->sig_pvt);
05939          break;
05940 #endif   /* defined(HAVE_PRI) */
05941 #if defined(HAVE_SS7)
05942       case SIG_SS7:
05943          sig_ss7_chan_delete(p->sig_pvt);
05944          break;
05945 #endif   /* defined(HAVE_SS7) */
05946       default:
05947          break;
05948       }
05949    }
05950    ast_free(p->cidspill);
05951    if (p->use_smdi)
05952       ast_smdi_interface_unref(p->smdi_iface);
05953    if (p->mwi_event_sub)
05954       ast_event_unsubscribe(p->mwi_event_sub);
05955    if (p->vars) {
05956       ast_variables_destroy(p->vars);
05957    }
05958    if (p->cc_params) {
05959       ast_cc_config_params_destroy(p->cc_params);
05960    }
05961 
05962    p->named_callgroups = ast_unref_namedgroups(p->named_callgroups);
05963    p->named_pickupgroups = ast_unref_namedgroups(p->named_pickupgroups);
05964 
05965    ast_mutex_destroy(&p->lock);
05966    dahdi_close_sub(p, SUB_REAL);
05967    if (p->owner)
05968       ast_channel_tech_pvt_set(p->owner, NULL);
05969    ast_free(p);
05970 }
05971 
05972 static void destroy_channel(struct dahdi_pvt *cur, int now)
05973 {
05974    int i;
05975 
05976    if (!now) {
05977       /* Do not destroy the channel now if it is owned by someone. */
05978       if (cur->owner) {
05979          return;
05980       }
05981       for (i = 0; i < 3; i++) {
05982          if (cur->subs[i].owner) {
05983             return;
05984          }
05985       }
05986    }
05987    destroy_dahdi_pvt(cur);
05988 }
05989 
05990 static void destroy_all_channels(void)
05991 {
05992    int chan;
05993 #if defined(HAVE_PRI)
05994    unsigned span;
05995    struct sig_pri_span *pri;
05996 #endif   /* defined(HAVE_PRI) */
05997    struct dahdi_pvt *p;
05998 
05999    while (num_restart_pending) {
06000       usleep(1);
06001    }
06002 
06003    ast_mutex_lock(&iflock);
06004    /* Destroy all the interfaces and free their memory */
06005    while (iflist) {
06006       p = iflist;
06007 
06008       chan = p->channel;
06009 #if defined(HAVE_PRI_SERVICE_MESSAGES)
06010       {
06011          char db_chan_name[20];
06012          char db_answer[5];
06013          char state;
06014          int why = -1;
06015 
06016          snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, p->span, chan);
06017          if (!ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) {
06018             sscanf(db_answer, "%1c:%30d", &state, &why);
06019          }
06020          if (!why) {
06021             /* SRVST persistence is not required */
06022             ast_db_del(db_chan_name, SRVST_DBKEY);
06023          }
06024       }
06025 #endif   /* defined(HAVE_PRI_SERVICE_MESSAGES) */
06026       /* Free associated memory */
06027       destroy_dahdi_pvt(p);
06028       ast_verb(3, "Unregistered channel %d\n", chan);
06029    }
06030    ifcount = 0;
06031    ast_mutex_unlock(&iflock);
06032 
06033 #if defined(HAVE_PRI)
06034    /* Destroy all of the no B channel interface lists */
06035    for (span = 0; span < NUM_SPANS; ++span) {
06036       if (!pris[span].dchannels[0]) {
06037          break;
06038       }
06039       pri = &pris[span].pri;
06040       ast_mutex_lock(&pri->lock);
06041       while (pri->no_b_chan_iflist) {
06042          p = pri->no_b_chan_iflist;
06043 
06044          /* Free associated memory */
06045          destroy_dahdi_pvt(p);
06046       }
06047       ast_mutex_unlock(&pri->lock);
06048    }
06049 #endif   /* defined(HAVE_PRI) */
06050 }
06051 
06052 #if defined(HAVE_PRI)
06053 static char *dahdi_send_keypad_facility_app = "DAHDISendKeypadFacility";
06054 
06055 static int dahdi_send_keypad_facility_exec(struct ast_channel *chan, const char *digits)
06056 {
06057    /* Data will be our digit string */
06058    struct dahdi_pvt *p;
06059 
06060    if (ast_strlen_zero(digits)) {
06061       ast_debug(1, "No digit string sent to application!\n");
06062       return -1;
06063    }
06064 
06065    p = (struct dahdi_pvt *)ast_channel_tech_pvt(chan);
06066 
06067    if (!p) {
06068       ast_debug(1, "Unable to find technology private\n");
06069       return -1;
06070    }
06071 
06072    pri_send_keypad_facility_exec(p->sig_pvt, digits);
06073 
06074    return 0;
06075 }
06076 #endif   /* defined(HAVE_PRI) */
06077 
06078 #if defined(HAVE_PRI)
06079 #if defined(HAVE_PRI_PROG_W_CAUSE)
06080 static char *dahdi_send_callrerouting_facility_app = "DAHDISendCallreroutingFacility";
06081 
06082 static int dahdi_send_callrerouting_facility_exec(struct ast_channel *chan, const char *data)
06083 {
06084    /* Data will be our digit string */
06085    struct dahdi_pvt *pvt;
06086    char *parse;
06087    int res;
06088    AST_DECLARE_APP_ARGS(args,
06089       AST_APP_ARG(destination);
06090       AST_APP_ARG(original);
06091       AST_APP_ARG(reason);
06092    );
06093 
06094    if (ast_strlen_zero(data)) {
06095       ast_debug(1, "No data sent to application!\n");
06096       return -1;
06097    }
06098    if (ast_channel_tech(chan) != &dahdi_tech) {
06099       ast_debug(1, "Only DAHDI technology accepted!\n");
06100       return -1;
06101    }
06102    pvt = (struct dahdi_pvt *) ast_channel_tech_pvt(chan);
06103    if (!pvt) {
06104       ast_debug(1, "Unable to find technology private\n");
06105       return -1;
06106    }
06107    switch (pvt->sig) {
06108    case SIG_PRI_LIB_HANDLE_CASES:
06109       break;
06110    default:
06111       ast_debug(1, "callrerouting attempted on non-ISDN channel %s\n",
06112          ast_channel_name(chan));
06113       return -1;
06114    }
06115 
06116    parse = ast_strdupa(data);
06117    AST_STANDARD_APP_ARGS(args, parse);
06118 
06119    if (ast_strlen_zero(args.destination)) {
06120       ast_log(LOG_WARNING, "callrerouting facility requires at least destination number argument\n");
06121       return -1;
06122    }
06123 
06124    if (ast_strlen_zero(args.original)) {
06125       ast_log(LOG_WARNING, "Callrerouting Facility without original called number argument\n");
06126       args.original = NULL;
06127    }
06128 
06129    if (ast_strlen_zero(args.reason)) {
06130       ast_log(LOG_NOTICE, "Callrerouting Facility without diversion reason argument, defaulting to unknown\n");
06131       args.reason = NULL;
06132    }
06133 
06134    res = pri_send_callrerouting_facility_exec(pvt->sig_pvt, ast_channel_state(chan),
06135       args.destination, args.original, args.reason);
06136    if (!res) {
06137       /*
06138        * Wait up to 5 seconds for a reply before hanging up this call
06139        * leg if the peer does not disconnect first.
06140        */
06141       ast_safe_sleep(chan, 5000);
06142    }
06143 
06144    return -1;
06145 }
06146 #endif   /* defined(HAVE_PRI_PROG_W_CAUSE) */
06147 #endif   /* defined(HAVE_PRI) */
06148 
06149 #if defined(HAVE_OPENR2)
06150 static const char * const dahdi_accept_r2_call_app = "DAHDIAcceptR2Call";
06151 
06152 static int dahdi_accept_r2_call_exec(struct ast_channel *chan, const char *data)
06153 {
06154    /* data is whether to accept with charge or no charge */
06155    openr2_call_mode_t accept_mode;
06156    int res, timeout, maxloops;
06157    struct ast_frame *f;
06158    struct dahdi_pvt *p;
06159    char *parse;
06160    AST_DECLARE_APP_ARGS(args,
06161          AST_APP_ARG(charge);
06162    );
06163 
06164    if (ast_strlen_zero(data)) {
06165       ast_debug(1, "No data sent to application!\n");
06166       return -1;
06167    }
06168 
06169    if (ast_channel_tech(chan) != &dahdi_tech) {
06170       ast_debug(1, "Only DAHDI technology accepted!\n");
06171       return -1;
06172    }
06173 
06174    p = (struct dahdi_pvt *)ast_channel_tech_pvt(chan);
06175    if (!p) {
06176       ast_debug(1, "Unable to find technology private!\n");
06177       return -1;
06178    }
06179 
06180    parse = ast_strdupa(data);
06181    AST_STANDARD_APP_ARGS(args, parse);
06182 
06183    if (ast_strlen_zero(args.charge)) {
06184       ast_log(LOG_WARNING, "DAHDIAcceptR2Call requires 'yes' or 'no' for the charge parameter\n");
06185       return -1;
06186    }
06187 
06188    ast_mutex_lock(&p->lock);
06189    if (!p->mfcr2 || !p->mfcr2call) {
06190       ast_mutex_unlock(&p->lock);
06191       ast_debug(1, "Channel %s does not seems to be an R2 active channel!\n", ast_channel_name(chan));
06192       return -1;
06193    }
06194 
06195    if (p->mfcr2_call_accepted) {
06196       ast_mutex_unlock(&p->lock);
06197       ast_debug(1, "MFC/R2 call already accepted on channel %s!\n", ast_channel_name(chan));
06198       return 0;
06199    }
06200    accept_mode = ast_true(args.charge) ? OR2_CALL_WITH_CHARGE : OR2_CALL_NO_CHARGE;
06201    if (openr2_chan_accept_call(p->r2chan, accept_mode)) {
06202       ast_mutex_unlock(&p->lock);
06203       ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n");
06204       return -1;
06205    }
06206    ast_mutex_unlock(&p->lock);
06207 
06208    res = 0;
06209    timeout = 100;
06210    maxloops = 50; /* wait up to 5 seconds */
06211    /* we need to read() until the call is accepted */
06212    while (maxloops > 0) {
06213       maxloops--;
06214       if (ast_check_hangup(chan)) {
06215          break;
06216       }
06217       res = ast_waitfor(chan, timeout);
06218       if (res < 0) {
06219          ast_debug(1, "ast_waitfor failed on channel %s, going out ...\n", ast_channel_name(chan));
06220          res = -1;
06221          break;
06222       }
06223       if (res == 0) {
06224          continue;
06225       }
06226       res = 0;
06227       f = ast_read(chan);
06228       if (!f) {
06229          ast_debug(1, "No frame read on channel %s, going out ...\n", ast_channel_name(chan));
06230          res = -1;
06231          break;
06232       }
06233       if (f->frametype == AST_FRAME_CONTROL && f->subclass.integer == AST_CONTROL_HANGUP) {
06234          ast_debug(1, "Got HANGUP frame on channel %s, going out ...\n", ast_channel_name(chan));
06235          ast_frfree(f);
06236          res = -1;
06237          break;
06238       }
06239       ast_frfree(f);
06240       ast_mutex_lock(&p->lock);
06241       if (p->mfcr2_call_accepted) {
06242          ast_mutex_unlock(&p->lock);
06243          ast_debug(1, "Accepted MFC/R2 call!\n");
06244          break;
06245       }
06246       ast_mutex_unlock(&p->lock);
06247    }
06248    if (res == -1) {
06249       ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n");
06250    }
06251    return res;
06252 }
06253 
06254 static openr2_call_disconnect_cause_t dahdi_ast_cause_to_r2_cause(int cause)
06255 {
06256    openr2_call_disconnect_cause_t r2cause = OR2_CAUSE_NORMAL_CLEARING;
06257    switch (cause) {
06258    case AST_CAUSE_USER_BUSY:
06259    case AST_CAUSE_CALL_REJECTED:
06260    case AST_CAUSE_INTERWORKING: /* I don't know wtf is this but is used sometimes when ekiga rejects a call */
06261       r2cause = OR2_CAUSE_BUSY_NUMBER;
06262       break;
06263 
06264    case AST_CAUSE_NORMAL_CIRCUIT_CONGESTION:
06265    case AST_CAUSE_SWITCH_CONGESTION:
06266       r2cause = OR2_CAUSE_NETWORK_CONGESTION;
06267       break;
06268 
06269    case AST_CAUSE_UNALLOCATED:
06270       r2cause = OR2_CAUSE_UNALLOCATED_NUMBER;
06271       break;
06272 
06273    case AST_CAUSE_NETWORK_OUT_OF_ORDER:
06274    case AST_CAUSE_DESTINATION_OUT_OF_ORDER:
06275       r2cause = OR2_CAUSE_OUT_OF_ORDER;
06276       break;
06277 
06278    case AST_CAUSE_NO_ANSWER:
06279    case AST_CAUSE_NO_USER_RESPONSE:
06280       r2cause = OR2_CAUSE_NO_ANSWER;
06281       break;
06282 
06283    default:
06284       r2cause = OR2_CAUSE_NORMAL_CLEARING;
06285       break;
06286    }
06287    ast_debug(1, "ast cause %d resulted in openr2 cause %d/%s\n",
06288          cause, r2cause, openr2_proto_get_disconnect_string(r2cause));
06289    return r2cause;
06290 }
06291 #endif
06292 
06293 static int revert_fax_buffers(struct dahdi_pvt *p, struct ast_channel *ast)
06294 {
06295    if (p->bufferoverrideinuse) {
06296       /* faxbuffers are in use, revert them */
06297       struct dahdi_bufferinfo bi = {
06298          .txbufpolicy = p->buf_policy,
06299          .rxbufpolicy = p->buf_policy,
06300          .bufsize = p->bufsize,
06301          .numbufs = p->buf_no
06302       };
06303       int bpres;
06304 
06305       if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
06306          ast_log(LOG_WARNING, "Channel '%s' unable to revert buffer policy: %s\n", ast_channel_name(ast), strerror(errno));
06307       }
06308       p->bufferoverrideinuse = 0;
06309       return bpres;
06310    }
06311 
06312    return -1;
06313 }
06314 
06315 static int dahdi_hangup(struct ast_channel *ast)
06316 {
06317    int res = 0;
06318    int idx,x;
06319    int law;
06320    /*static int restore_gains(struct dahdi_pvt *p);*/
06321    struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
06322    struct dahdi_params par;
06323 
06324    ast_debug(1, "dahdi_hangup(%s)\n", ast_channel_name(ast));
06325    if (!ast_channel_tech_pvt(ast)) {
06326       ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
06327       return 0;
06328    }
06329 
06330    ast_mutex_lock(&p->lock);
06331    p->exten[0] = '\0';
06332    if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
06333       dahdi_confmute(p, 0);
06334       restore_gains(p);
06335       p->ignoredtmf = 0;
06336       p->waitingfordt.tv_sec = 0;
06337 
06338       res = analog_hangup(p->sig_pvt, ast);
06339       revert_fax_buffers(p, ast);
06340 
06341       goto hangup_out;
06342    } else {
06343       p->cid_num[0] = '\0';
06344       p->cid_name[0] = '\0';
06345       p->cid_subaddr[0] = '\0';
06346    }
06347 
06348 #if defined(HAVE_PRI)
06349    if (dahdi_sig_pri_lib_handles(p->sig)) {
06350       x = 1;
06351       ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
06352 
06353       dahdi_confmute(p, 0);
06354       p->muting = 0;
06355       restore_gains(p);
06356       if (p->dsp) {
06357          ast_dsp_free(p->dsp);
06358          p->dsp = NULL;
06359       }
06360       p->ignoredtmf = 0;
06361 
06362       /* Real channel, do some fixup */
06363       p->subs[SUB_REAL].owner = NULL;
06364       p->subs[SUB_REAL].needbusy = 0;
06365       dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
06366 
06367       p->owner = NULL;
06368       p->cid_tag[0] = '\0';
06369       p->ringt = 0;/* Probably not used in this mode.  Reset anyway. */
06370       p->distinctivering = 0;/* Probably not used in this mode. Reset anyway. */
06371       p->confirmanswer = 0;/* Probably not used in this mode. Reset anyway. */
06372       p->outgoing = 0;
06373       p->digital = 0;
06374       p->faxhandled = 0;
06375       p->pulsedial = 0;/* Probably not used in this mode. Reset anyway. */
06376 
06377       revert_fax_buffers(p, ast);
06378 
06379       p->law = p->law_default;
06380       law = p->law_default;
06381       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
06382       if (res < 0) {
06383          ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n",
06384             p->channel, strerror(errno));
06385       }
06386 
06387       sig_pri_hangup(p->sig_pvt, ast);
06388 
06389       tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06390       dahdi_disable_ec(p);
06391 
06392       x = 0;
06393       ast_channel_setoption(ast, AST_OPTION_TDD, &x, sizeof(char), 0);
06394       p->didtdd = 0;/* Probably not used in this mode. Reset anyway. */
06395 
06396       p->rdnis[0] = '\0';
06397       update_conf(p);
06398       reset_conf(p);
06399 
06400       /* Restore data mode */
06401       x = 0;
06402       ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
06403 
06404       if (num_restart_pending == 0) {
06405          restart_monitor();
06406       }
06407       goto hangup_out;
06408    }
06409 #endif   /* defined(HAVE_PRI) */
06410 
06411 #if defined(HAVE_SS7)
06412    if (p->sig == SIG_SS7) {
06413       x = 1;
06414       ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
06415 
06416       dahdi_confmute(p, 0);
06417       p->muting = 0;
06418       restore_gains(p);
06419       if (p->dsp) {
06420          ast_dsp_free(p->dsp);
06421          p->dsp = NULL;
06422       }
06423       p->ignoredtmf = 0;
06424 
06425       /* Real channel, do some fixup */
06426       p->subs[SUB_REAL].owner = NULL;
06427       p->subs[SUB_REAL].needbusy = 0;
06428       dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
06429 
06430       p->owner = NULL;
06431       p->ringt = 0;/* Probably not used in this mode.  Reset anyway. */
06432       p->distinctivering = 0;/* Probably not used in this mode. Reset anyway. */
06433       p->confirmanswer = 0;/* Probably not used in this mode. Reset anyway. */
06434       p->outgoing = 0;
06435       p->digital = 0;
06436       p->faxhandled = 0;
06437       p->pulsedial = 0;/* Probably not used in this mode. Reset anyway. */
06438 
06439       revert_fax_buffers(p, ast);
06440 
06441       p->law = p->law_default;
06442       law = p->law_default;
06443       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
06444       if (res < 0) {
06445          ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n",
06446             p->channel, strerror(errno));
06447       }
06448 
06449       sig_ss7_hangup(p->sig_pvt, ast);
06450 
06451       tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06452       dahdi_disable_ec(p);
06453 
06454       x = 0;
06455       ast_channel_setoption(ast, AST_OPTION_TDD, &x, sizeof(char), 0);
06456       p->didtdd = 0;/* Probably not used in this mode. Reset anyway. */
06457 
06458       update_conf(p);
06459       reset_conf(p);
06460 
06461       /* Restore data mode */
06462       x = 0;
06463       ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
06464 
06465       if (num_restart_pending == 0) {
06466          restart_monitor();
06467       }
06468       goto hangup_out;
06469    }
06470 #endif   /* defined(HAVE_SS7) */
06471 
06472    idx = dahdi_get_index(ast, p, 1);
06473 
06474    dahdi_confmute(p, 0);
06475    p->muting = 0;
06476    restore_gains(p);
06477    if (p->origcid_num) {
06478       ast_copy_string(p->cid_num, p->origcid_num, sizeof(p->cid_num));
06479       ast_free(p->origcid_num);
06480       p->origcid_num = NULL;
06481    }
06482    if (p->origcid_name) {
06483       ast_copy_string(p->cid_name, p->origcid_name, sizeof(p->cid_name));
06484       ast_free(p->origcid_name);
06485       p->origcid_name = NULL;
06486    }
06487    if (p->dsp)
06488       ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
06489 
06490    ast_debug(1, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n",
06491       p->channel, idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
06492    p->ignoredtmf = 0;
06493 
06494    if (idx > -1) {
06495       /* Real channel, do some fixup */
06496       p->subs[idx].owner = NULL;
06497       p->subs[idx].needanswer = 0;
06498       p->subs[idx].needflash = 0;
06499       p->subs[idx].needringing = 0;
06500       p->subs[idx].needbusy = 0;
06501       p->subs[idx].needcongestion = 0;
06502       p->subs[idx].linear = 0;
06503       p->polarity = POLARITY_IDLE;
06504       dahdi_setlinear(p->subs[idx].dfd, 0);
06505       if (idx == SUB_REAL) {
06506          if ((p->subs[SUB_CALLWAIT].dfd > -1) && (p->subs[SUB_THREEWAY].dfd > -1)) {
06507             ast_debug(1, "Normal call hung up with both three way call and a call waiting call in place?\n");
06508             if (p->subs[SUB_CALLWAIT].inthreeway) {
06509                /* We had flipped over to answer a callwait and now it's gone */
06510                ast_debug(1, "We were flipped over to the callwait, moving back and unowning.\n");
06511                /* Move to the call-wait, but un-own us until they flip back. */
06512                swap_subs(p, SUB_CALLWAIT, SUB_REAL);
06513                unalloc_sub(p, SUB_CALLWAIT);
06514                p->owner = NULL;
06515             } else {
06516                /* The three way hung up, but we still have a call wait */
06517                ast_debug(1, "We were in the threeway and have a callwait still.  Ditching the threeway.\n");
06518                swap_subs(p, SUB_THREEWAY, SUB_REAL);
06519                unalloc_sub(p, SUB_THREEWAY);
06520                if (p->subs[SUB_REAL].inthreeway) {
06521                   /* This was part of a three way call.  Immediately make way for
06522                      another call */
06523                   ast_debug(1, "Call was complete, setting owner to former third call\n");
06524                   p->owner = p->subs[SUB_REAL].owner;
06525                } else {
06526                   /* This call hasn't been completed yet...  Set owner to NULL */
06527                   ast_debug(1, "Call was incomplete, setting owner to NULL\n");
06528                   p->owner = NULL;
06529                }
06530                p->subs[SUB_REAL].inthreeway = 0;
06531             }
06532          } else if (p->subs[SUB_CALLWAIT].dfd > -1) {
06533             /* Move to the call-wait and switch back to them. */
06534             swap_subs(p, SUB_CALLWAIT, SUB_REAL);
06535             unalloc_sub(p, SUB_CALLWAIT);
06536             p->owner = p->subs[SUB_REAL].owner;
06537             if (ast_channel_state(p->owner) != AST_STATE_UP)
06538                p->subs[SUB_REAL].needanswer = 1;
06539             if (ast_bridged_channel(p->subs[SUB_REAL].owner))
06540                ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
06541          } else if (p->subs[SUB_THREEWAY].dfd > -1) {
06542             swap_subs(p, SUB_THREEWAY, SUB_REAL);
06543             unalloc_sub(p, SUB_THREEWAY);
06544             if (p->subs[SUB_REAL].inthreeway) {
06545                /* This was part of a three way call.  Immediately make way for
06546                   another call */
06547                ast_debug(1, "Call was complete, setting owner to former third call\n");
06548                p->owner = p->subs[SUB_REAL].owner;
06549             } else {
06550                /* This call hasn't been completed yet...  Set owner to NULL */
06551                ast_debug(1, "Call was incomplete, setting owner to NULL\n");
06552                p->owner = NULL;
06553             }
06554             p->subs[SUB_REAL].inthreeway = 0;
06555          }
06556       } else if (idx == SUB_CALLWAIT) {
06557          /* Ditch the holding callwait call, and immediately make it availabe */
06558          if (p->subs[SUB_CALLWAIT].inthreeway) {
06559             /* This is actually part of a three way, placed on hold.  Place the third part
06560                on music on hold now */
06561             if (p->subs[SUB_THREEWAY].owner && ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
06562                ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
06563                   S_OR(p->mohsuggest, NULL),
06564                   !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
06565             }
06566             p->subs[SUB_THREEWAY].inthreeway = 0;
06567             /* Make it the call wait now */
06568             swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
06569             unalloc_sub(p, SUB_THREEWAY);
06570          } else
06571             unalloc_sub(p, SUB_CALLWAIT);
06572       } else if (idx == SUB_THREEWAY) {
06573          if (p->subs[SUB_CALLWAIT].inthreeway) {
06574             /* The other party of the three way call is currently in a call-wait state.
06575                Start music on hold for them, and take the main guy out of the third call */
06576             if (p->subs[SUB_CALLWAIT].owner && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
06577                ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
06578                   S_OR(p->mohsuggest, NULL),
06579                   !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
06580             }
06581             p->subs[SUB_CALLWAIT].inthreeway = 0;
06582          }
06583          p->subs[SUB_REAL].inthreeway = 0;
06584          /* If this was part of a three way call index, let us make
06585             another three way call */
06586          unalloc_sub(p, SUB_THREEWAY);
06587       } else {
06588          /* This wasn't any sort of call, but how are we an index? */
06589          ast_log(LOG_WARNING, "Index found but not any type of call?\n");
06590       }
06591    }
06592 
06593    if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) {
06594       p->owner = NULL;
06595       p->ringt = 0;
06596       p->distinctivering = 0;
06597       p->confirmanswer = 0;
06598       p->outgoing = 0;
06599       p->digital = 0;
06600       p->faxhandled = 0;
06601       p->pulsedial = 0;
06602       if (p->dsp) {
06603          ast_dsp_free(p->dsp);
06604          p->dsp = NULL;
06605       }
06606 
06607       revert_fax_buffers(p, ast);
06608 
06609       p->law = p->law_default;
06610       law = p->law_default;
06611       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
06612       if (res < 0)
06613          ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
06614       /* Perform low level hangup if no owner left */
06615 #ifdef HAVE_OPENR2
06616       if (p->mfcr2 && p->mfcr2call && openr2_chan_get_direction(p->r2chan) != OR2_DIR_STOPPED) {
06617          ast_debug(1, "disconnecting MFC/R2 call on chan %d\n", p->channel);
06618          /* If it's an incoming call, check the mfcr2_forced_release setting */
06619          if (openr2_chan_get_direction(p->r2chan) == OR2_DIR_BACKWARD && p->mfcr2_forced_release) {
06620             dahdi_r2_disconnect_call(p, OR2_CAUSE_FORCED_RELEASE);
06621          } else {
06622             const char *r2causestr = pbx_builtin_getvar_helper(ast, "MFCR2_CAUSE");
06623             int r2cause_user = r2causestr ? atoi(r2causestr) : 0;
06624             openr2_call_disconnect_cause_t r2cause = r2cause_user ? dahdi_ast_cause_to_r2_cause(r2cause_user)
06625                                                              : dahdi_ast_cause_to_r2_cause(ast_channel_hangupcause(ast));
06626             dahdi_r2_disconnect_call(p, r2cause);
06627          }
06628       } else if (p->mfcr2call) {
06629          ast_debug(1, "Clearing call request on channel %d\n", p->channel);
06630          /* since ast_request() was called but not ast_call() we have not yet dialed
06631          and the openr2 stack will not call on_call_end callback, we need to unset
06632          the mfcr2call flag and bump the monitor count so the monitor thread can take
06633          care of this channel events from now on */
06634          p->mfcr2call = 0;
06635       }
06636 #endif
06637       switch (p->sig) {
06638       case SIG_SS7:
06639       case SIG_MFCR2:
06640       case SIG_PRI_LIB_HANDLE_CASES:
06641       case 0:
06642          break;
06643       default:
06644          res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
06645          break;
06646       }
06647       if (res < 0) {
06648          ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast_channel_name(ast));
06649       }
06650       switch (p->sig) {
06651       case SIG_FXOGS:
06652       case SIG_FXOLS:
06653       case SIG_FXOKS:
06654          memset(&par, 0, sizeof(par));
06655          res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
06656          if (!res) {
06657             struct analog_pvt *analog_p = p->sig_pvt;
06658 #if 0
06659             ast_debug(1, "Hanging up channel %d, offhook = %d\n", p->channel, par.rxisoffhook);
06660 #endif
06661             /* If they're off hook, try playing congestion */
06662             if ((par.rxisoffhook) && (!(p->radio || (p->oprmode < 0))))
06663                tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
06664             else
06665                tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06666             analog_p->fxsoffhookstate = par.rxisoffhook;
06667          }
06668          break;
06669       case SIG_FXSGS:
06670       case SIG_FXSLS:
06671       case SIG_FXSKS:
06672          /* Make sure we're not made available for at least two seconds assuming
06673          we were actually used for an inbound or outbound call. */
06674          if (ast_channel_state(ast) != AST_STATE_RESERVED) {
06675             time(&p->guardtime);
06676             p->guardtime += 2;
06677          }
06678          break;
06679       default:
06680          tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06681          break;
06682       }
06683       if (p->sig)
06684          dahdi_disable_ec(p);
06685       x = 0;
06686       ast_channel_setoption(ast,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0);
06687       ast_channel_setoption(ast,AST_OPTION_TDD,&x,sizeof(char),0);
06688       p->didtdd = 0;
06689       p->callwaitcas = 0;
06690       p->callwaiting = p->permcallwaiting;
06691       p->hidecallerid = p->permhidecallerid;
06692       p->waitingfordt.tv_sec = 0;
06693       p->dialing = 0;
06694       p->rdnis[0] = '\0';
06695       update_conf(p);
06696       reset_conf(p);
06697       /* Restore data mode */
06698       switch (p->sig) {
06699       case SIG_PRI_LIB_HANDLE_CASES:
06700       case SIG_SS7:
06701          x = 0;
06702          ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
06703          break;
06704       default:
06705          break;
06706       }
06707       if (num_restart_pending == 0)
06708          restart_monitor();
06709    }
06710 
06711    p->callwaitingrepeat = 0;
06712    p->cidcwexpire = 0;
06713    p->cid_suppress_expire = 0;
06714    p->oprmode = 0;
06715 hangup_out:
06716    ast_channel_tech_pvt_set(ast, NULL);
06717    ast_free(p->cidspill);
06718    p->cidspill = NULL;
06719 
06720    ast_mutex_unlock(&p->lock);
06721    ast_verb(3, "Hungup '%s'\n", ast_channel_name(ast));
06722 
06723    ast_mutex_lock(&iflock);
06724    if (p->restartpending) {
06725       num_restart_pending--;
06726    }
06727 
06728    if (p->destroy) {
06729       destroy_channel(p, 0);
06730    }
06731    ast_mutex_unlock(&iflock);
06732 
06733    ast_module_unref(ast_module_info->self);
06734    return 0;
06735 }
06736 
06737 static int dahdi_answer(struct ast_channel *ast)
06738 {
06739    struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
06740    int res = 0;
06741    int idx;
06742    ast_setstate(ast, AST_STATE_UP);/*! \todo XXX this is redundantly set by the analog and PRI submodules! */
06743    ast_mutex_lock(&p->lock);
06744    idx = dahdi_get_index(ast, p, 0);
06745    if (idx < 0)
06746       idx = SUB_REAL;
06747    /* nothing to do if a radio channel */
06748    if ((p->radio || (p->oprmode < 0))) {
06749       ast_mutex_unlock(&p->lock);
06750       return 0;
06751    }
06752 
06753    if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
06754       res = analog_answer(p->sig_pvt, ast);
06755       ast_mutex_unlock(&p->lock);
06756       return res;
06757    }
06758 
06759    switch (p->sig) {
06760 #if defined(HAVE_PRI)
06761    case SIG_PRI_LIB_HANDLE_CASES:
06762       res = sig_pri_answer(p->sig_pvt, ast);
06763       break;
06764 #endif   /* defined(HAVE_PRI) */
06765 #if defined(HAVE_SS7)
06766    case SIG_SS7:
06767       res = sig_ss7_answer(p->sig_pvt, ast);
06768       break;
06769 #endif   /* defined(HAVE_SS7) */
06770 #ifdef HAVE_OPENR2
06771    case SIG_MFCR2:
06772       if (!p->mfcr2_call_accepted) {
06773          /* The call was not accepted on offer nor the user, so it must be accepted now before answering,
06774             openr2_chan_answer_call will be called when the callback on_call_accepted is executed */
06775          p->mfcr2_answer_pending = 1;
06776          if (p->mfcr2_charge_calls) {
06777             ast_debug(1, "Accepting MFC/R2 call with charge before answering on chan %d\n", p->channel);
06778             openr2_chan_accept_call(p->r2chan, OR2_CALL_WITH_CHARGE);
06779          } else {
06780             ast_debug(1, "Accepting MFC/R2 call with no charge before answering on chan %d\n", p->channel);
06781             openr2_chan_accept_call(p->r2chan, OR2_CALL_NO_CHARGE);
06782          }
06783       } else {
06784          ast_debug(1, "Answering MFC/R2 call on chan %d\n", p->channel);
06785          dahdi_r2_answer(p);
06786       }
06787       break;
06788 #endif
06789    case 0:
06790       ast_mutex_unlock(&p->lock);
06791       return 0;
06792    default:
06793       ast_log(LOG_WARNING, "Don't know how to answer signalling %d (channel %d)\n", p->sig, p->channel);
06794       res = -1;
06795       break;
06796    }
06797    ast_mutex_unlock(&p->lock);
06798    return res;
06799 }
06800 
06801 static void disable_dtmf_detect(struct dahdi_pvt *p)
06802 {
06803    int val = 0;
06804 
06805    p->ignoredtmf = 1;
06806 
06807    ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
06808 
06809    if (!p->hardwaredtmf && p->dsp) {
06810       p->dsp_features &= ~DSP_FEATURE_DIGIT_DETECT;
06811       ast_dsp_set_features(p->dsp, p->dsp_features);
06812    }
06813 }
06814 
06815 static void enable_dtmf_detect(struct dahdi_pvt *p)
06816 {
06817    int val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
06818 
06819    if (p->channel == CHAN_PSEUDO)
06820       return;
06821 
06822    p->ignoredtmf = 0;
06823 
06824    ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
06825 
06826    if (!p->hardwaredtmf && p->dsp) {
06827       p->dsp_features |= DSP_FEATURE_DIGIT_DETECT;
06828       ast_dsp_set_features(p->dsp, p->dsp_features);
06829    }
06830 }
06831 
06832 static int dahdi_queryoption(struct ast_channel *chan, int option, void *data, int *datalen)
06833 {
06834    char *cp;
06835    struct dahdi_pvt *p = ast_channel_tech_pvt(chan);
06836 
06837    /* all supported options require data */
06838    if (!p || !data || (*datalen < 1)) {
06839       errno = EINVAL;
06840       return -1;
06841    }
06842 
06843    switch (option) {
06844    case AST_OPTION_DIGIT_DETECT:
06845       cp = (char *) data;
06846       *cp = p->ignoredtmf ? 0 : 1;
06847       ast_debug(1, "Reporting digit detection %sabled on %s\n", *cp ? "en" : "dis", ast_channel_name(chan));
06848       break;
06849    case AST_OPTION_FAX_DETECT:
06850       cp = (char *) data;
06851       *cp = (p->dsp_features & DSP_FEATURE_FAX_DETECT) ? 0 : 1;
06852       ast_debug(1, "Reporting fax tone detection %sabled on %s\n", *cp ? "en" : "dis", ast_channel_name(chan));
06853       break;
06854    case AST_OPTION_CC_AGENT_TYPE:
06855 #if defined(HAVE_PRI)
06856 #if defined(HAVE_PRI_CCSS)
06857       if (dahdi_sig_pri_lib_handles(p->sig)) {
06858          ast_copy_string((char *) data, dahdi_pri_cc_type, *datalen);
06859          break;
06860       }
06861 #endif   /* defined(HAVE_PRI_CCSS) */
06862 #endif   /* defined(HAVE_PRI) */
06863       return -1;
06864    default:
06865       return -1;
06866    }
06867 
06868    errno = 0;
06869 
06870    return 0;
06871 }
06872 
06873 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen)
06874 {
06875    char *cp;
06876    signed char *scp;
06877    int x;
06878    int idx;
06879    struct dahdi_pvt *p = ast_channel_tech_pvt(chan), *pp;
06880    struct oprmode *oprmode;
06881 
06882 
06883    /* all supported options require data */
06884    if (!p || !data || (datalen < 1)) {
06885       errno = EINVAL;
06886       return -1;
06887    }
06888 
06889    switch (option) {
06890    case AST_OPTION_TXGAIN:
06891       scp = (signed char *) data;
06892       idx = dahdi_get_index(chan, p, 0);
06893       if (idx < 0) {
06894          ast_log(LOG_WARNING, "No index in TXGAIN?\n");
06895          return -1;
06896       }
06897       ast_debug(1, "Setting actual tx gain on %s to %f\n", ast_channel_name(chan), p->txgain + (float) *scp);
06898       return set_actual_txgain(p->subs[idx].dfd, p->txgain + (float) *scp, p->txdrc, p->law);
06899    case AST_OPTION_RXGAIN:
06900       scp = (signed char *) data;
06901       idx = dahdi_get_index(chan, p, 0);
06902       if (idx < 0) {
06903          ast_log(LOG_WARNING, "No index in RXGAIN?\n");
06904          return -1;
06905       }
06906       ast_debug(1, "Setting actual rx gain on %s to %f\n", ast_channel_name(chan), p->rxgain + (float) *scp);
06907       return set_actual_rxgain(p->subs[idx].dfd, p->rxgain + (float) *scp, p->rxdrc, p->law);
06908    case AST_OPTION_TONE_VERIFY:
06909       if (!p->dsp)
06910          break;
06911       cp = (char *) data;
06912       switch (*cp) {
06913       case 1:
06914          ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",ast_channel_name(chan));
06915          ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | p->dtmfrelax);  /* set mute mode if desired */
06916          break;
06917       case 2:
06918          ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",ast_channel_name(chan));
06919          ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX | p->dtmfrelax);  /* set mute mode if desired */
06920          break;
06921       default:
06922          ast_debug(1, "Set option TONE VERIFY, mode: OFF(0) on %s\n",ast_channel_name(chan));
06923          ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);  /* set mute mode if desired */
06924          break;
06925       }
06926       break;
06927    case AST_OPTION_TDD:
06928       /* turn on or off TDD */
06929       cp = (char *) data;
06930       p->mate = 0;
06931       if (!*cp) { /* turn it off */
06932          ast_debug(1, "Set option TDD MODE, value: OFF(0) on %s\n",ast_channel_name(chan));
06933          if (p->tdd)
06934             tdd_free(p->tdd);
06935          p->tdd = 0;
06936          break;
06937       }
06938       ast_debug(1, "Set option TDD MODE, value: %s(%d) on %s\n",
06939          (*cp == 2) ? "MATE" : "ON", (int) *cp, ast_channel_name(chan));
06940       dahdi_disable_ec(p);
06941       /* otherwise, turn it on */
06942       if (!p->didtdd) { /* if havent done it yet */
06943          unsigned char mybuf[41000];/*! \todo XXX This is an abuse of the stack!! */
06944          unsigned char *buf;
06945          int size, res, fd, len;
06946          struct pollfd fds[1];
06947 
06948          buf = mybuf;
06949          memset(buf, 0x7f, sizeof(mybuf)); /* set to silence */
06950          ast_tdd_gen_ecdisa(buf + 16000, 16000);  /* put in tone */
06951          len = 40000;
06952          idx = dahdi_get_index(chan, p, 0);
06953          if (idx < 0) {
06954             ast_log(LOG_WARNING, "No index in TDD?\n");
06955             return -1;
06956          }
06957          fd = p->subs[idx].dfd;
06958          while (len) {
06959             if (ast_check_hangup(chan))
06960                return -1;
06961             size = len;
06962             if (size > READ_SIZE)
06963                size = READ_SIZE;
06964             fds[0].fd = fd;
06965             fds[0].events = POLLPRI | POLLOUT;
06966             fds[0].revents = 0;
06967             res = poll(fds, 1, -1);
06968             if (!res) {
06969                ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
06970                continue;
06971             }
06972             /* if got exception */
06973             if (fds[0].revents & POLLPRI)
06974                return -1;
06975             if (!(fds[0].revents & POLLOUT)) {
06976                ast_debug(1, "write fd not ready on channel %d\n", p->channel);
06977                continue;
06978             }
06979             res = write(fd, buf, size);
06980             if (res != size) {
06981                if (res == -1) return -1;
06982                ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
06983                break;
06984             }
06985             len -= size;
06986             buf += size;
06987          }
06988          p->didtdd = 1; /* set to have done it now */
06989       }
06990       if (*cp == 2) { /* Mate mode */
06991          if (p->tdd)
06992             tdd_free(p->tdd);
06993          p->tdd = 0;
06994          p->mate = 1;
06995          break;
06996       }
06997       if (!p->tdd) { /* if we don't have one yet */
06998          p->tdd = tdd_new(); /* allocate one */
06999       }
07000       break;
07001    case AST_OPTION_RELAXDTMF:  /* Relax DTMF decoding (or not) */
07002       if (!p->dsp)
07003          break;
07004       cp = (char *) data;
07005       ast_debug(1, "Set option RELAX DTMF, value: %s(%d) on %s\n",
07006          *cp ? "ON" : "OFF", (int) *cp, ast_channel_name(chan));
07007       ast_dsp_set_digitmode(p->dsp, ((*cp) ? DSP_DIGITMODE_RELAXDTMF : DSP_DIGITMODE_DTMF) | p->dtmfrelax);
07008       break;
07009    case AST_OPTION_AUDIO_MODE:  /* Set AUDIO mode (or not) */
07010 #if defined(HAVE_PRI)
07011       if (dahdi_sig_pri_lib_handles(p->sig)
07012          && ((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
07013          /* PRI nobch pseudo channel.  Does not handle ioctl(DAHDI_AUDIOMODE) */
07014          break;
07015       }
07016 #endif   /* defined(HAVE_PRI) */
07017 
07018       cp = (char *) data;
07019       if (!*cp) {
07020          ast_debug(1, "Set option AUDIO MODE, value: OFF(0) on %s\n", ast_channel_name(chan));
07021          x = 0;
07022          dahdi_disable_ec(p);
07023       } else {
07024          ast_debug(1, "Set option AUDIO MODE, value: ON(1) on %s\n", ast_channel_name(chan));
07025          x = 1;
07026       }
07027       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x) == -1)
07028          ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, x, strerror(errno));
07029       break;
07030    case AST_OPTION_OPRMODE:  /* Operator services mode */
07031       oprmode = (struct oprmode *) data;
07032       /* We don't support operator mode across technologies */
07033       if (strcasecmp(ast_channel_tech(chan)->type, ast_channel_tech(oprmode->peer)->type)) {
07034          ast_log(LOG_NOTICE, "Operator mode not supported on %s to %s calls.\n",
07035                ast_channel_tech(chan)->type, ast_channel_tech(oprmode->peer)->type);
07036          errno = EINVAL;
07037          return -1;
07038       }
07039       pp = ast_channel_tech_pvt(oprmode->peer);
07040       p->oprmode = pp->oprmode = 0;
07041       /* setup peers */
07042       p->oprpeer = pp;
07043       pp->oprpeer = p;
07044       /* setup modes, if any */
07045       if (oprmode->mode)
07046       {
07047          pp->oprmode = oprmode->mode;
07048          p->oprmode = -oprmode->mode;
07049       }
07050       ast_debug(1, "Set Operator Services mode, value: %d on %s/%s\n",
07051          oprmode->mode, ast_channel_name(chan),ast_channel_name(oprmode->peer));
07052       break;
07053    case AST_OPTION_ECHOCAN:
07054       cp = (char *) data;
07055       if (*cp) {
07056          ast_debug(1, "Enabling echo cancellation on %s\n", ast_channel_name(chan));
07057          dahdi_enable_ec(p);
07058       } else {
07059          ast_debug(1, "Disabling echo cancellation on %s\n", ast_channel_name(chan));
07060          dahdi_disable_ec(p);
07061       }
07062       break;
07063    case AST_OPTION_DIGIT_DETECT:
07064       cp = (char *) data;
07065       ast_debug(1, "%sabling digit detection on %s\n", *cp ? "En" : "Dis", ast_channel_name(chan));
07066       if (*cp) {
07067          enable_dtmf_detect(p);
07068       } else {
07069          disable_dtmf_detect(p);
07070       }
07071       break;
07072    case AST_OPTION_FAX_DETECT:
07073       cp = (char *) data;
07074       if (p->dsp) {
07075          ast_debug(1, "%sabling fax tone detection on %s\n", *cp ? "En" : "Dis", ast_channel_name(chan));
07076          if (*cp) {
07077             p->dsp_features |= DSP_FEATURE_FAX_DETECT;
07078          } else {
07079             p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
07080          }
07081          ast_dsp_set_features(p->dsp, p->dsp_features);
07082       }
07083       break;
07084    default:
07085       return -1;
07086    }
07087    errno = 0;
07088 
07089    return 0;
07090 }
07091 
07092 static int dahdi_func_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len)
07093 {
07094    struct dahdi_pvt *p = ast_channel_tech_pvt(chan);
07095    int res = 0;
07096 
07097    if (!p) {
07098       /* No private structure! */
07099       *buf = '\0';
07100       return -1;
07101    }
07102 
07103    if (!strcasecmp(data, "rxgain")) {
07104       ast_mutex_lock(&p->lock);
07105       snprintf(buf, len, "%f", p->rxgain);
07106       ast_mutex_unlock(&p->lock);
07107    } else if (!strcasecmp(data, "txgain")) {
07108       ast_mutex_lock(&p->lock);
07109       snprintf(buf, len, "%f", p->txgain);
07110       ast_mutex_unlock(&p->lock);
07111    } else if (!strcasecmp(data, "dahdi_channel")) {
07112       ast_mutex_lock(&p->lock);
07113       snprintf(buf, len, "%d", p->channel);
07114       ast_mutex_unlock(&p->lock);
07115    } else if (!strcasecmp(data, "dahdi_span")) {
07116       ast_mutex_lock(&p->lock);
07117       snprintf(buf, len, "%d", p->span);
07118       ast_mutex_unlock(&p->lock);
07119    } else if (!strcasecmp(data, "dahdi_type")) {
07120       ast_mutex_lock(&p->lock);
07121       switch (p->sig) {
07122 #if defined(HAVE_OPENR2)
07123       case SIG_MFCR2:
07124          ast_copy_string(buf, "mfc/r2", len);
07125          break;
07126 #endif   /* defined(HAVE_OPENR2) */
07127 #if defined(HAVE_PRI)
07128       case SIG_PRI_LIB_HANDLE_CASES:
07129          ast_copy_string(buf, "pri", len);
07130          break;
07131 #endif   /* defined(HAVE_PRI) */
07132       case 0:
07133          ast_copy_string(buf, "pseudo", len);
07134          break;
07135 #if defined(HAVE_SS7)
07136       case SIG_SS7:
07137          ast_copy_string(buf, "ss7", len);
07138          break;
07139 #endif   /* defined(HAVE_SS7) */
07140       default:
07141          /* The only thing left is analog ports. */
07142          ast_copy_string(buf, "analog", len);
07143          break;
07144       }
07145       ast_mutex_unlock(&p->lock);
07146 #if defined(HAVE_PRI)
07147 #if defined(HAVE_PRI_REVERSE_CHARGE)
07148    } else if (!strcasecmp(data, "reversecharge")) {
07149       ast_mutex_lock(&p->lock);
07150       switch (p->sig) {
07151       case SIG_PRI_LIB_HANDLE_CASES:
07152          snprintf(buf, len, "%d", ((struct sig_pri_chan *) p->sig_pvt)->reverse_charging_indication);
07153          break;
07154       default:
07155          *buf = '\0';
07156          res = -1;
07157          break;
07158       }
07159       ast_mutex_unlock(&p->lock);
07160 #endif
07161 #if defined(HAVE_PRI_SETUP_KEYPAD)
07162    } else if (!strcasecmp(data, "keypad_digits")) {
07163       ast_mutex_lock(&p->lock);
07164       switch (p->sig) {
07165       case SIG_PRI_LIB_HANDLE_CASES:
07166          ast_copy_string(buf, ((struct sig_pri_chan *) p->sig_pvt)->keypad_digits,
07167             len);
07168          break;
07169       default:
07170          *buf = '\0';
07171          res = -1;
07172          break;
07173       }
07174       ast_mutex_unlock(&p->lock);
07175 #endif   /* defined(HAVE_PRI_SETUP_KEYPAD) */
07176    } else if (!strcasecmp(data, "no_media_path")) {
07177       ast_mutex_lock(&p->lock);
07178       switch (p->sig) {
07179       case SIG_PRI_LIB_HANDLE_CASES:
07180          /*
07181           * TRUE if the call is on hold or is call waiting because
07182           * there is no media path available.
07183           */
07184          snprintf(buf, len, "%d", ((struct sig_pri_chan *) p->sig_pvt)->no_b_channel);
07185          break;
07186       default:
07187          *buf = '\0';
07188          res = -1;
07189          break;
07190       }
07191       ast_mutex_unlock(&p->lock);
07192 #endif   /* defined(HAVE_PRI) */
07193    } else {
07194       *buf = '\0';
07195       res = -1;
07196    }
07197 
07198    return res;
07199 }
07200 
07201 
07202 static int parse_buffers_policy(const char *parse, int *num_buffers, int *policy)
07203 {
07204    int res;
07205    char policy_str[21] = "";
07206 
07207    if ((res = sscanf(parse, "%30d,%20s", num_buffers, policy_str)) != 2) {
07208       ast_log(LOG_WARNING, "Parsing buffer string '%s' failed.\n", parse);
07209       return 1;
07210    }
07211    if (*num_buffers < 0) {
07212       ast_log(LOG_WARNING, "Invalid buffer count given '%d'.\n", *num_buffers);
07213       return -1;
07214    }
07215    if (!strcasecmp(policy_str, "full")) {
07216       *policy = DAHDI_POLICY_WHEN_FULL;
07217    } else if (!strcasecmp(policy_str, "immediate")) {
07218       *policy = DAHDI_POLICY_IMMEDIATE;
07219 #if defined(HAVE_DAHDI_HALF_FULL)
07220    } else if (!strcasecmp(policy_str, "half")) {
07221       *policy = DAHDI_POLICY_HALF_FULL;
07222 #endif
07223    } else {
07224       ast_log(LOG_WARNING, "Invalid policy name given '%s'.\n", policy_str);
07225       return -1;
07226    }
07227 
07228    return 0;
07229 }
07230 
07231 static int dahdi_func_write(struct ast_channel *chan, const char *function, char *data, const char *value)
07232 {
07233    struct dahdi_pvt *p = ast_channel_tech_pvt(chan);
07234    int res = 0;
07235 
07236    if (!p) {
07237       /* No private structure! */
07238       return -1;
07239    }
07240 
07241    if (!strcasecmp(data, "buffers")) {
07242       int num_bufs, policy;
07243 
07244       if (!(parse_buffers_policy(value, &num_bufs, &policy))) {
07245          struct dahdi_bufferinfo bi = {
07246             .txbufpolicy = policy,
07247             .rxbufpolicy = policy,
07248             .bufsize = p->bufsize,
07249             .numbufs = num_bufs,
07250          };
07251          int bpres;
07252 
07253          if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
07254             ast_log(LOG_WARNING, "Channel '%d' unable to override buffer policy: %s\n", p->channel, strerror(errno));
07255          } else {
07256             p->bufferoverrideinuse = 1;
07257          }
07258       } else {
07259          res = -1;
07260       }
07261    } else if (!strcasecmp(data, "echocan_mode")) {
07262       if (!strcasecmp(value, "on")) {
07263          ast_mutex_lock(&p->lock);
07264          dahdi_enable_ec(p);
07265          ast_mutex_unlock(&p->lock);
07266       } else if (!strcasecmp(value, "off")) {
07267          ast_mutex_lock(&p->lock);
07268          dahdi_disable_ec(p);
07269          ast_mutex_unlock(&p->lock);
07270 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
07271       } else if (!strcasecmp(value, "fax")) {
07272          int blah = 1;
07273 
07274          ast_mutex_lock(&p->lock);
07275          if (!p->echocanon) {
07276             dahdi_enable_ec(p);
07277          }
07278          if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_FAX_MODE, &blah)) {
07279             ast_log(LOG_WARNING, "Unable to place echocan into fax mode on channel %d: %s\n", p->channel, strerror(errno));
07280          }
07281          ast_mutex_unlock(&p->lock);
07282       } else if (!strcasecmp(value, "voice")) {
07283          int blah = 0;
07284 
07285          ast_mutex_lock(&p->lock);
07286          if (!p->echocanon) {
07287             dahdi_enable_ec(p);
07288          }
07289          if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_FAX_MODE, &blah)) {
07290             ast_log(LOG_WARNING, "Unable to place echocan into voice mode on channel %d: %s\n", p->channel, strerror(errno));
07291          }
07292          ast_mutex_unlock(&p->lock);
07293 #endif
07294       } else {
07295          ast_log(LOG_WARNING, "Unsupported value '%s' provided for '%s' item.\n", value, data);
07296          res = -1;
07297       }
07298    } else {
07299       res = -1;
07300    }
07301 
07302    return res;
07303 }
07304 
07305 static void dahdi_unlink(struct dahdi_pvt *slave, struct dahdi_pvt *master, int needlock)
07306 {
07307    /* Unlink a specific slave or all slaves/masters from a given master */
07308    int x;
07309    int hasslaves;
07310    if (!master)
07311       return;
07312    if (needlock) {
07313       ast_mutex_lock(&master->lock);
07314       if (slave) {
07315          while (ast_mutex_trylock(&slave->lock)) {
07316             DEADLOCK_AVOIDANCE(&master->lock);
07317          }
07318       }
07319    }
07320    hasslaves = 0;
07321    for (x = 0; x < MAX_SLAVES; x++) {
07322       if (master->slaves[x]) {
07323          if (!slave || (master->slaves[x] == slave)) {
07324             /* Take slave out of the conference */
07325             ast_debug(1, "Unlinking slave %d from %d\n", master->slaves[x]->channel, master->channel);
07326             conf_del(master, &master->slaves[x]->subs[SUB_REAL], SUB_REAL);
07327             conf_del(master->slaves[x], &master->subs[SUB_REAL], SUB_REAL);
07328             master->slaves[x]->master = NULL;
07329             master->slaves[x] = NULL;
07330          } else
07331             hasslaves = 1;
07332       }
07333       if (!hasslaves)
07334          master->inconference = 0;
07335    }
07336    if (!slave) {
07337       if (master->master) {
07338          /* Take master out of the conference */
07339          conf_del(master->master, &master->subs[SUB_REAL], SUB_REAL);
07340          conf_del(master, &master->master->subs[SUB_REAL], SUB_REAL);
07341          hasslaves = 0;
07342          for (x = 0; x < MAX_SLAVES; x++) {
07343             if (master->master->slaves[x] == master)
07344                master->master->slaves[x] = NULL;
07345             else if (master->master->slaves[x])
07346                hasslaves = 1;
07347          }
07348          if (!hasslaves)
07349             master->master->inconference = 0;
07350       }
07351       master->master = NULL;
07352    }
07353    update_conf(master);
07354    if (needlock) {
07355       if (slave)
07356          ast_mutex_unlock(&slave->lock);
07357       ast_mutex_unlock(&master->lock);
07358    }
07359 }
07360 
07361 static void dahdi_link(struct dahdi_pvt *slave, struct dahdi_pvt *master) {
07362    int x;
07363    if (!slave || !master) {
07364       ast_log(LOG_WARNING, "Tried to link to/from NULL??\n");
07365       return;
07366    }
07367    for (x = 0; x < MAX_SLAVES; x++) {
07368       if (!master->slaves[x]) {
07369          master->slaves[x] = slave;
07370          break;
07371       }
07372    }
07373    if (x >= MAX_SLAVES) {
07374       ast_log(LOG_WARNING, "Replacing slave %d with new slave, %d\n", master->slaves[MAX_SLAVES - 1]->channel, slave->channel);
07375       master->slaves[MAX_SLAVES - 1] = slave;
07376    }
07377    if (slave->master)
07378       ast_log(LOG_WARNING, "Replacing master %d with new master, %d\n", slave->master->channel, master->channel);
07379    slave->master = master;
07380 
07381    ast_debug(1, "Making %d slave to master %d at %d\n", slave->channel, master->channel, x);
07382 }
07383 
07384 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)
07385 {
07386    struct ast_channel *who;
07387    struct dahdi_pvt *p0, *p1, *op0, *op1;
07388    struct dahdi_pvt *master = NULL, *slave = NULL;
07389    struct ast_frame *f;
07390    int inconf = 0;
07391    int nothingok = 1;
07392    int ofd0, ofd1;
07393    int oi0, oi1, i0 = -1, i1 = -1, t0, t1;
07394    int os0 = -1, os1 = -1;
07395    int priority = 0;
07396    struct ast_channel *oc0, *oc1;
07397    enum ast_bridge_result res;
07398    struct timeval start = ast_tvnow();
07399 #ifdef PRI_2BCT
07400    int triedtopribridge = 0;
07401    q931_call *q931c0;
07402    q931_call *q931c1;
07403 #endif
07404 
07405    /* For now, don't attempt to native bridge if either channel needs DTMF detection.
07406       There is code below to handle it properly until DTMF is actually seen,
07407       but due to currently unresolved issues it's ignored...
07408    */
07409 
07410    if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1))
07411       return AST_BRIDGE_FAILED_NOWARN;
07412 
07413    ast_channel_lock_both(c0, c1);
07414 
07415    p0 = ast_channel_tech_pvt(c0);
07416    p1 = ast_channel_tech_pvt(c1);
07417    /* cant do pseudo-channels here */
07418    if (!p0 || (!p0->sig) || !p1 || (!p1->sig)) {
07419       ast_channel_unlock(c0);
07420       ast_channel_unlock(c1);
07421       return AST_BRIDGE_FAILED_NOWARN;
07422    }
07423 
07424    oi0 = dahdi_get_index(c0, p0, 0);
07425    oi1 = dahdi_get_index(c1, p1, 0);
07426    if ((oi0 < 0) || (oi1 < 0)) {
07427       ast_channel_unlock(c0);
07428       ast_channel_unlock(c1);
07429       return AST_BRIDGE_FAILED;
07430    }
07431 
07432    op0 = p0 = ast_channel_tech_pvt(c0);
07433    op1 = p1 = ast_channel_tech_pvt(c1);
07434    ofd0 = ast_channel_fd(c0, 0);
07435    ofd1 = ast_channel_fd(c1, 0);
07436    oc0 = p0->owner;
07437    oc1 = p1->owner;
07438 
07439    if (ast_mutex_trylock(&p0->lock)) {
07440       /* Don't block, due to potential for deadlock */
07441       ast_channel_unlock(c0);
07442       ast_channel_unlock(c1);
07443       ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
07444       return AST_BRIDGE_RETRY;
07445    }
07446    if (ast_mutex_trylock(&p1->lock)) {
07447       /* Don't block, due to potential for deadlock */
07448       ast_mutex_unlock(&p0->lock);
07449       ast_channel_unlock(c0);
07450       ast_channel_unlock(c1);
07451       ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
07452       return AST_BRIDGE_RETRY;
07453    }
07454 
07455    if ((p0->callwaiting && p0->callwaitingcallerid)
07456       || (p1->callwaiting && p1->callwaitingcallerid)) {
07457       /*
07458        * Call Waiting Caller ID requires DTMF detection to know if it
07459        * can send the CID spill.
07460        *
07461        * For now, don't attempt to native bridge if either channel
07462        * needs DTMF detection.  There is code below to handle it
07463        * properly until DTMF is actually seen, but due to currently
07464        * unresolved issues it's ignored...
07465        */
07466       ast_mutex_unlock(&p0->lock);
07467       ast_mutex_unlock(&p1->lock);
07468       ast_channel_unlock(c0);
07469       ast_channel_unlock(c1);
07470       return AST_BRIDGE_FAILED_NOWARN;
07471    }
07472 
07473 #if defined(HAVE_PRI)
07474    if ((dahdi_sig_pri_lib_handles(p0->sig)
07475          && ((struct sig_pri_chan *) p0->sig_pvt)->no_b_channel)
07476       || (dahdi_sig_pri_lib_handles(p1->sig)
07477          && ((struct sig_pri_chan *) p1->sig_pvt)->no_b_channel)) {
07478       /*
07479        * PRI nobch channels (hold and call waiting) are equivalent to
07480        * pseudo channels and cannot be done here.
07481        */
07482       ast_mutex_unlock(&p0->lock);
07483       ast_mutex_unlock(&p1->lock);
07484       ast_channel_unlock(c0);
07485       ast_channel_unlock(c1);
07486       return AST_BRIDGE_FAILED_NOWARN;
07487    }
07488 #endif   /* defined(HAVE_PRI) */
07489 
07490    if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
07491       if (p0->owner && p1->owner) {
07492          /* If we don't have a call-wait in a 3-way, and we aren't in a 3-way, we can be master */
07493          if (!p0->subs[SUB_CALLWAIT].inthreeway && !p1->subs[SUB_REAL].inthreeway) {
07494             master = p0;
07495             slave = p1;
07496             inconf = 1;
07497          } else if (!p1->subs[SUB_CALLWAIT].inthreeway && !p0->subs[SUB_REAL].inthreeway) {
07498             master = p1;
07499             slave = p0;
07500             inconf = 1;
07501          } else {
07502             ast_log(LOG_WARNING, "Huh?  Both calls are callwaits or 3-ways?  That's clever...?\n");
07503             ast_log(LOG_WARNING, "p0: chan %d/%d/CW%d/3W%d, p1: chan %d/%d/CW%d/3W%d\n",
07504                p0->channel,
07505                oi0, (p0->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
07506                p0->subs[SUB_REAL].inthreeway, p0->channel,
07507                oi0, (p1->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
07508                p1->subs[SUB_REAL].inthreeway);
07509          }
07510          nothingok = 0;
07511       }
07512    } else if ((oi0 == SUB_REAL) && (oi1 == SUB_THREEWAY)) {
07513       if (p1->subs[SUB_THREEWAY].inthreeway) {
07514          master = p1;
07515          slave = p0;
07516          nothingok = 0;
07517       }
07518    } else if ((oi0 == SUB_THREEWAY) && (oi1 == SUB_REAL)) {
07519       if (p0->subs[SUB_THREEWAY].inthreeway) {
07520          master = p0;
07521          slave = p1;
07522          nothingok = 0;
07523       }
07524    } else if ((oi0 == SUB_REAL) && (oi1 == SUB_CALLWAIT)) {
07525       /* We have a real and a call wait.  If we're in a three way call, put us in it, otherwise,
07526          don't put us in anything */
07527       if (p1->subs[SUB_CALLWAIT].inthreeway) {
07528          master = p1;
07529          slave = p0;
07530          nothingok = 0;
07531       }
07532    } else if ((oi0 == SUB_CALLWAIT) && (oi1 == SUB_REAL)) {
07533       /* Same as previous */
07534       if (p0->subs[SUB_CALLWAIT].inthreeway) {
07535          master = p0;
07536          slave = p1;
07537          nothingok = 0;
07538       }
07539    }
07540    ast_debug(1, "master: %d, slave: %d, nothingok: %d\n",
07541       master ? master->channel : 0, slave ? slave->channel : 0, nothingok);
07542    if (master && slave) {
07543       /* Stop any tones, or play ringtone as appropriate.  If they're bridged
07544          in an active threeway call with a channel that is ringing, we should
07545          indicate ringing. */
07546       if ((oi1 == SUB_THREEWAY) &&
07547          p1->subs[SUB_THREEWAY].inthreeway &&
07548          p1->subs[SUB_REAL].owner &&
07549          p1->subs[SUB_REAL].inthreeway &&
07550          (ast_channel_state(p1->subs[SUB_REAL].owner) == AST_STATE_RINGING)) {
07551          ast_debug(1,
07552             "Playing ringback on %d/%d(%s) since %d/%d(%s) is in a ringing three-way\n",
07553             p0->channel, oi0, ast_channel_name(c0), p1->channel, oi1, ast_channel_name(c1));
07554          tone_zone_play_tone(p0->subs[oi0].dfd, DAHDI_TONE_RINGTONE);
07555          os1 = ast_channel_state(p1->subs[SUB_REAL].owner);
07556       } else {
07557          ast_debug(1, "Stopping tones on %d/%d(%s) talking to %d/%d(%s)\n",
07558             p0->channel, oi0, ast_channel_name(c0), p1->channel, oi1, ast_channel_name(c1));
07559          tone_zone_play_tone(p0->subs[oi0].dfd, -1);
07560       }
07561       if ((oi0 == SUB_THREEWAY) &&
07562          p0->subs[SUB_THREEWAY].inthreeway &&
07563          p0->subs[SUB_REAL].owner &&
07564          p0->subs[SUB_REAL].inthreeway &&
07565          (ast_channel_state(p0->subs[SUB_REAL].owner) == AST_STATE_RINGING)) {
07566          ast_debug(1,
07567             "Playing ringback on %d/%d(%s) since %d/%d(%s) is in a ringing three-way\n",
07568             p1->channel, oi1, ast_channel_name(c1), p0->channel, oi0, ast_channel_name(c0));
07569          tone_zone_play_tone(p1->subs[oi1].dfd, DAHDI_TONE_RINGTONE);
07570          os0 = ast_channel_state(p0->subs[SUB_REAL].owner);
07571       } else {
07572          ast_debug(1, "Stopping tones on %d/%d(%s) talking to %d/%d(%s)\n",
07573             p1->channel, oi1, ast_channel_name(c1), p0->channel, oi0, ast_channel_name(c0));
07574          tone_zone_play_tone(p1->subs[oi1].dfd, -1);
07575       }
07576       if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
07577          if (!p0->echocanbridged || !p1->echocanbridged) {
07578             /* Disable echo cancellation if appropriate */
07579             dahdi_disable_ec(p0);
07580             dahdi_disable_ec(p1);
07581          }
07582       }
07583       dahdi_link(slave, master);
07584       master->inconference = inconf;
07585    } else if (!nothingok)
07586       ast_log(LOG_WARNING, "Can't link %d/%s with %d/%s\n", p0->channel, subnames[oi0], p1->channel, subnames[oi1]);
07587 
07588    update_conf(p0);
07589    update_conf(p1);
07590    t0 = p0->subs[SUB_REAL].inthreeway;
07591    t1 = p1->subs[SUB_REAL].inthreeway;
07592 
07593    ast_mutex_unlock(&p0->lock);
07594    ast_mutex_unlock(&p1->lock);
07595 
07596    ast_channel_unlock(c0);
07597    ast_channel_unlock(c1);
07598 
07599    /* Native bridge failed */
07600    if ((!master || !slave) && !nothingok) {
07601       dahdi_enable_ec(p0);
07602       dahdi_enable_ec(p1);
07603       return AST_BRIDGE_FAILED;
07604    }
07605 
07606    ast_verb(3, "Native bridging %s and %s\n", ast_channel_name(c0), ast_channel_name(c1));
07607 
07608    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
07609       disable_dtmf_detect(op0);
07610 
07611    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
07612       disable_dtmf_detect(op1);
07613 
07614    for (;;) {
07615       struct ast_channel *c0_priority[2] = {c0, c1};
07616       struct ast_channel *c1_priority[2] = {c1, c0};
07617       int ms;
07618 
07619       /* Here's our main loop...  Start by locking things, looking for private parts,
07620          and then balking if anything is wrong */
07621 
07622       ast_channel_lock_both(c0, c1);
07623 
07624       p0 = ast_channel_tech_pvt(c0);
07625       p1 = ast_channel_tech_pvt(c1);
07626 
07627       if (op0 == p0)
07628          i0 = dahdi_get_index(c0, p0, 1);
07629       if (op1 == p1)
07630          i1 = dahdi_get_index(c1, p1, 1);
07631 
07632       ast_channel_unlock(c0);
07633       ast_channel_unlock(c1);
07634       ms = ast_remaining_ms(start, timeoutms);
07635       if (!ms ||
07636          (op0 != p0) ||
07637          (op1 != p1) ||
07638          (ofd0 != ast_channel_fd(c0, 0)) ||
07639          (ofd1 != ast_channel_fd(c1, 0)) ||
07640          (p0->subs[SUB_REAL].owner && (os0 > -1) && (os0 != ast_channel_state(p0->subs[SUB_REAL].owner))) ||
07641          (p1->subs[SUB_REAL].owner && (os1 > -1) && (os1 != ast_channel_state(p1->subs[SUB_REAL].owner))) ||
07642          (oc0 != p0->owner) ||
07643          (oc1 != p1->owner) ||
07644          (t0 != p0->subs[SUB_REAL].inthreeway) ||
07645          (t1 != p1->subs[SUB_REAL].inthreeway) ||
07646          (oi0 != i0) ||
07647          (oi1 != i1)) {
07648          ast_debug(1, "Something changed out on %d/%d to %d/%d, returning -3 to restart\n",
07649             op0->channel, oi0, op1->channel, oi1);
07650          res = AST_BRIDGE_RETRY;
07651          goto return_from_bridge;
07652       }
07653 
07654 #ifdef PRI_2BCT
07655       if (!triedtopribridge) {
07656          triedtopribridge = 1;
07657          if (p0->pri && p0->pri == p1->pri && p0->pri->transfer) {
07658             ast_mutex_lock(&p0->pri->lock);
07659             switch (p0->sig) {
07660             case SIG_PRI_LIB_HANDLE_CASES:
07661                q931c0 = ((struct sig_pri_chan *) (p0->sig_pvt))->call;
07662                break;
07663             default:
07664                q931c0 = NULL;
07665                break;
07666             }
07667             switch (p1->sig) {
07668             case SIG_PRI_LIB_HANDLE_CASES:
07669                q931c1 = ((struct sig_pri_chan *) (p1->sig_pvt))->call;
07670                break;
07671             default:
07672                q931c1 = NULL;
07673                break;
07674             }
07675             if (q931c0 && q931c1) {
07676                pri_channel_bridge(q931c0, q931c1);
07677             }
07678             ast_mutex_unlock(&p0->pri->lock);
07679          }
07680       }
07681 #endif
07682 
07683       who = ast_waitfor_n(priority ? c0_priority : c1_priority, 2, &ms);
07684       if (!who) {
07685          ast_debug(1, "Ooh, empty read...\n");
07686          continue;
07687       }
07688       f = ast_read(who);
07689       switch (f ? f->frametype : AST_FRAME_CONTROL) {
07690       case AST_FRAME_CONTROL:
07691          if (f && f->subclass.integer == AST_CONTROL_PVT_CAUSE_CODE) {
07692             ast_channel_hangupcause_hash_set((who == c0) ? c1 : c0, f->data.ptr, f->datalen);
07693             break;
07694          }
07695          *fo = f;
07696          *rc = who;
07697          res = AST_BRIDGE_COMPLETE;
07698          goto return_from_bridge;
07699       case AST_FRAME_DTMF_END:
07700          if ((who == c0) && p0->pulsedial) {
07701             ast_write(c1, f);
07702          } else if ((who == c1) && p1->pulsedial) {
07703             ast_write(c0, f);
07704          } else {
07705             *fo = f;
07706             *rc = who;
07707             res = AST_BRIDGE_COMPLETE;
07708             goto return_from_bridge;
07709          }
07710          break;
07711       case AST_FRAME_TEXT:
07712          if (who == c0) {
07713             ast_write(c1, f);
07714          } else {
07715             ast_write(c0, f);
07716          }
07717          break;
07718       case AST_FRAME_VOICE:
07719          /* Native bridge handles voice frames in hardware. */
07720       case AST_FRAME_NULL:
07721          break;
07722       default:
07723          ast_debug(1, "Chan '%s' is discarding frame of frametype:%d\n",
07724             ast_channel_name(who), f->frametype);
07725          break;
07726       }
07727       ast_frfree(f);
07728 
07729       /* Swap who gets priority */
07730       priority = !priority;
07731    }
07732 
07733 return_from_bridge:
07734    if (op0 == p0)
07735       dahdi_enable_ec(p0);
07736 
07737    if (op1 == p1)
07738       dahdi_enable_ec(p1);
07739 
07740    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
07741       enable_dtmf_detect(op0);
07742 
07743    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
07744       enable_dtmf_detect(op1);
07745 
07746    dahdi_unlink(slave, master, 1);
07747 
07748    return res;
07749 }
07750 
07751 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
07752 {
07753    struct dahdi_pvt *p = ast_channel_tech_pvt(newchan);
07754    int x;
07755 
07756    ast_mutex_lock(&p->lock);
07757 
07758    ast_debug(1, "New owner for channel %d is %s\n", p->channel, ast_channel_name(newchan));
07759    if (p->owner == oldchan) {
07760       p->owner = newchan;
07761    }
07762    for (x = 0; x < 3; x++) {
07763       if (p->subs[x].owner == oldchan) {
07764          if (!x) {
07765             dahdi_unlink(NULL, p, 0);
07766          }
07767          p->subs[x].owner = newchan;
07768       }
07769    }
07770    if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
07771       analog_fixup(oldchan, newchan, p->sig_pvt);
07772 #if defined(HAVE_PRI)
07773    } else if (dahdi_sig_pri_lib_handles(p->sig)) {
07774       sig_pri_fixup(oldchan, newchan, p->sig_pvt);
07775 #endif   /* defined(HAVE_PRI) */
07776 #if defined(HAVE_SS7)
07777    } else if (p->sig == SIG_SS7) {
07778       sig_ss7_fixup(oldchan, newchan, p->sig_pvt);
07779 #endif   /* defined(HAVE_SS7) */
07780    }
07781    update_conf(p);
07782 
07783    ast_mutex_unlock(&p->lock);
07784 
07785    if (ast_channel_state(newchan) == AST_STATE_RINGING) {
07786       dahdi_indicate(newchan, AST_CONTROL_RINGING, NULL, 0);
07787    }
07788    return 0;
07789 }
07790 
07791 static int dahdi_ring_phone(struct dahdi_pvt *p)
07792 {
07793    int x;
07794    int res;
07795    /* Make sure our transmit state is on hook */
07796    x = 0;
07797    x = DAHDI_ONHOOK;
07798    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
07799    do {
07800       x = DAHDI_RING;
07801       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
07802       if (res) {
07803          switch (errno) {
07804          case EBUSY:
07805          case EINTR:
07806             /* Wait just in case */
07807             usleep(10000);
07808             continue;
07809          case EINPROGRESS:
07810             res = 0;
07811             break;
07812          default:
07813             ast_log(LOG_WARNING, "Couldn't ring the phone: %s\n", strerror(errno));
07814             res = 0;
07815          }
07816       }
07817    } while (res);
07818    return res;
07819 }
07820 
07821 static void *analog_ss_thread(void *data);
07822 
07823 static int attempt_transfer(struct dahdi_pvt *p)
07824 {
07825    /* In order to transfer, we need at least one of the channels to
07826       actually be in a call bridge.  We can't conference two applications
07827       together (but then, why would we want to?) */
07828    if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
07829       /* The three-way person we're about to transfer to could still be in MOH, so
07830          stop if now if appropriate */
07831       if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner))
07832          ast_queue_control(p->subs[SUB_THREEWAY].owner, AST_CONTROL_UNHOLD);
07833       if (ast_channel_state(p->subs[SUB_REAL].owner) == AST_STATE_RINGING) {
07834          ast_indicate(ast_bridged_channel(p->subs[SUB_REAL].owner), AST_CONTROL_RINGING);
07835       }
07836       if (ast_channel_state(p->subs[SUB_THREEWAY].owner) == AST_STATE_RING) {
07837          tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE);
07838       }
07839        if (ast_channel_masquerade(p->subs[SUB_THREEWAY].owner, ast_bridged_channel(p->subs[SUB_REAL].owner))) {
07840          ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
07841                ast_channel_name(ast_bridged_channel(p->subs[SUB_REAL].owner)), ast_channel_name(p->subs[SUB_THREEWAY].owner));
07842          return -1;
07843       }
07844       /* Orphan the channel after releasing the lock */
07845       ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
07846       unalloc_sub(p, SUB_THREEWAY);
07847    } else if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
07848       ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
07849       if (ast_channel_state(p->subs[SUB_THREEWAY].owner) == AST_STATE_RINGING) {
07850          ast_indicate(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), AST_CONTROL_RINGING);
07851       }
07852       if (ast_channel_state(p->subs[SUB_REAL].owner) == AST_STATE_RING) {
07853          tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
07854       }
07855       if (ast_channel_masquerade(p->subs[SUB_REAL].owner, ast_bridged_channel(p->subs[SUB_THREEWAY].owner))) {
07856          ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
07857                ast_channel_name(ast_bridged_channel(p->subs[SUB_THREEWAY].owner)), ast_channel_name(p->subs[SUB_REAL].owner));
07858          return -1;
07859       }
07860       /* Three-way is now the REAL */
07861       swap_subs(p, SUB_THREEWAY, SUB_REAL);
07862       ast_channel_unlock(p->subs[SUB_REAL].owner);
07863       unalloc_sub(p, SUB_THREEWAY);
07864       /* Tell the caller not to hangup */
07865       return 1;
07866    } else {
07867       ast_debug(1, "Neither %s nor %s are in a bridge, nothing to transfer\n",
07868          ast_channel_name(p->subs[SUB_REAL].owner), ast_channel_name(p->subs[SUB_THREEWAY].owner));
07869       ast_channel_softhangup_internal_flag_add(p->subs[SUB_THREEWAY].owner, AST_SOFTHANGUP_DEV);
07870       return -1;
07871    }
07872    return 0;
07873 }
07874 
07875 static int check_for_conference(struct dahdi_pvt *p)
07876 {
07877    struct dahdi_confinfo ci;
07878    /* Fine if we already have a master, etc */
07879    if (p->master || (p->confno > -1))
07880       return 0;
07881    memset(&ci, 0, sizeof(ci));
07882    if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
07883       ast_log(LOG_WARNING, "Failed to get conference info on channel %d: %s\n", p->channel, strerror(errno));
07884       return 0;
07885    }
07886    /* If we have no master and don't have a confno, then
07887       if we're in a conference, it's probably a MeetMe room or
07888       some such, so don't let us 3-way out! */
07889    if ((p->subs[SUB_REAL].curconf.confno != ci.confno) || (p->subs[SUB_REAL].curconf.confmode != ci.confmode)) {
07890       ast_verb(3, "Avoiding 3-way call when in an external conference\n");
07891       return 1;
07892    }
07893    return 0;
07894 }
07895 
07896 /*! Checks channel for alarms
07897  * \param p a channel to check for alarms.
07898  * \returns the alarms on the span to which the channel belongs, or alarms on
07899  *          the channel if no span alarms.
07900  */
07901 static int get_alarms(struct dahdi_pvt *p)
07902 {
07903    int res;
07904    struct dahdi_spaninfo zi;
07905    struct dahdi_params params;
07906 
07907    memset(&zi, 0, sizeof(zi));
07908    zi.spanno = p->span;
07909 
07910    if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SPANSTAT, &zi)) >= 0) {
07911       if (zi.alarms != DAHDI_ALARM_NONE)
07912          return zi.alarms;
07913    } else {
07914       ast_log(LOG_WARNING, "Unable to determine alarm on channel %d: %s\n", p->channel, strerror(errno));
07915       return 0;
07916    }
07917 
07918    /* No alarms on the span. Check for channel alarms. */
07919    memset(&params, 0, sizeof(params));
07920    if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &params)) >= 0)
07921       return params.chan_alarms;
07922 
07923    ast_log(LOG_WARNING, "Unable to determine alarm on channel %d\n", p->channel);
07924 
07925    return DAHDI_ALARM_NONE;
07926 }
07927 
07928 static void dahdi_handle_dtmf(struct ast_channel *ast, int idx, struct ast_frame **dest)
07929 {
07930    struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
07931    struct ast_frame *f = *dest;
07932 
07933    ast_debug(1, "%s DTMF digit: 0x%02X '%c' on %s\n",
07934       f->frametype == AST_FRAME_DTMF_BEGIN ? "Begin" : "End",
07935       f->subclass.integer, f->subclass.integer, ast_channel_name(ast));
07936 
07937    if (p->confirmanswer) {
07938       if (f->frametype == AST_FRAME_DTMF_END) {
07939          ast_debug(1, "Confirm answer on %s!\n", ast_channel_name(ast));
07940          /* Upon receiving a DTMF digit, consider this an answer confirmation instead
07941             of a DTMF digit */
07942          p->subs[idx].f.frametype = AST_FRAME_CONTROL;
07943          p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
07944          /* Reset confirmanswer so DTMF's will behave properly for the duration of the call */
07945          p->confirmanswer = 0;
07946       } else {
07947          p->subs[idx].f.frametype = AST_FRAME_NULL;
07948          p->subs[idx].f.subclass.integer = 0;
07949       }
07950       *dest = &p->subs[idx].f;
07951    } else if (p->callwaitcas) {
07952       if (f->frametype == AST_FRAME_DTMF_END) {
07953          if ((f->subclass.integer == 'A') || (f->subclass.integer == 'D')) {
07954             ast_debug(1, "Got some DTMF, but it's for the CAS\n");
07955             ast_free(p->cidspill);
07956             p->cidspill = NULL;
07957             send_cwcidspill(p);
07958          }
07959          p->callwaitcas = 0;
07960       }
07961       p->subs[idx].f.frametype = AST_FRAME_NULL;
07962       p->subs[idx].f.subclass.integer = 0;
07963       *dest = &p->subs[idx].f;
07964    } else if (f->subclass.integer == 'f') {
07965       if (f->frametype == AST_FRAME_DTMF_END) {
07966          /* Fax tone -- Handle and return NULL */
07967          if ((p->callprogress & CALLPROGRESS_FAX) && !p->faxhandled) {
07968             /* If faxbuffers are configured, use them for the fax transmission */
07969             if (p->usefaxbuffers && !p->bufferoverrideinuse) {
07970                struct dahdi_bufferinfo bi = {
07971                   .txbufpolicy = p->faxbuf_policy,
07972                   .bufsize = p->bufsize,
07973                   .numbufs = p->faxbuf_no
07974                };
07975                int res;
07976 
07977                if ((res = ioctl(p->subs[idx].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
07978                   ast_log(LOG_WARNING, "Channel '%s' unable to set buffer policy, reason: %s\n", ast_channel_name(ast), strerror(errno));
07979                } else {
07980                   p->bufferoverrideinuse = 1;
07981                }
07982             }
07983             p->faxhandled = 1;
07984             if (p->dsp) {
07985                p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
07986                ast_dsp_set_features(p->dsp, p->dsp_features);
07987                ast_debug(1, "Disabling FAX tone detection on %s after tone received\n", ast_channel_name(ast));
07988             }
07989             if (strcmp(ast_channel_exten(ast), "fax")) {
07990                const char *target_context = S_OR(ast_channel_macrocontext(ast), ast_channel_context(ast));
07991 
07992                /* We need to unlock 'ast' here because ast_exists_extension has the
07993                 * potential to start autoservice on the channel. Such action is prone
07994                 * to deadlock.
07995                 */
07996                ast_mutex_unlock(&p->lock);
07997                ast_channel_unlock(ast);
07998                if (ast_exists_extension(ast, target_context, "fax", 1,
07999                   S_COR(ast_channel_caller(ast)->id.number.valid, ast_channel_caller(ast)->id.number.str, NULL))) {
08000                   ast_channel_lock(ast);
08001                   ast_mutex_lock(&p->lock);
08002                   ast_verb(3, "Redirecting %s to fax extension\n", ast_channel_name(ast));
08003                   /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
08004                   pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast_channel_exten(ast));
08005                   if (ast_async_goto(ast, target_context, "fax", 1))
08006                      ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast_channel_name(ast), target_context);
08007                } else {
08008                   ast_channel_lock(ast);
08009                   ast_mutex_lock(&p->lock);
08010                   ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
08011                }
08012             } else {
08013                ast_debug(1, "Already in a fax extension, not redirecting\n");
08014             }
08015          } else {
08016             ast_debug(1, "Fax already handled\n");
08017          }
08018          dahdi_confmute(p, 0);
08019       }
08020       p->subs[idx].f.frametype = AST_FRAME_NULL;
08021       p->subs[idx].f.subclass.integer = 0;
08022       *dest = &p->subs[idx].f;
08023    }
08024 }
08025 
08026 static void handle_alarms(struct dahdi_pvt *p, int alms)
08027 {
08028    const char *alarm_str;
08029 
08030 #if defined(HAVE_PRI)
08031    if (dahdi_sig_pri_lib_handles(p->sig) && sig_pri_is_alarm_ignored(p->pri)) {
08032       return;
08033    }
08034 #endif   /* defined(HAVE_PRI) */
08035 
08036    alarm_str = alarm2str(alms);
08037    if (report_alarms & REPORT_CHANNEL_ALARMS) {
08038       ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", p->channel, alarm_str);
08039       /*** DOCUMENTATION
08040          <managerEventInstance>
08041             <synopsis>Raised when an alarm is set on a DAHDI channel.</synopsis>
08042          </managerEventInstance>
08043       ***/
08044       manager_event(EVENT_FLAG_SYSTEM, "Alarm",
08045                  "Alarm: %s\r\n"
08046                  "Channel: %d\r\n",
08047                  alarm_str, p->channel);
08048    }
08049 
08050    if (report_alarms & REPORT_SPAN_ALARMS && p->manages_span_alarms) {
08051       ast_log(LOG_WARNING, "Detected alarm on span %d: %s\n", p->span, alarm_str);
08052       /*** DOCUMENTATION
08053          <managerEventInstance>
08054             <synopsis>Raised when an alarm is set on a DAHDI span.</synopsis>
08055          </managerEventInstance>
08056       ***/
08057       manager_event(EVENT_FLAG_SYSTEM, "SpanAlarm",
08058                  "Alarm: %s\r\n"
08059                  "Span: %d\r\n",
08060                  alarm_str, p->span);
08061    }
08062 }
08063 
08064 static struct ast_frame *dahdi_handle_event(struct ast_channel *ast)
08065 {
08066    int res, x;
08067    int idx, mysig;
08068    char *c;
08069    struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
08070    pthread_t threadid;
08071    struct ast_channel *chan;
08072    struct ast_frame *f;
08073 
08074    idx = dahdi_get_index(ast, p, 0);
08075    if (idx < 0) {
08076       return &ast_null_frame;
08077    }
08078    mysig = p->sig;
08079    if (p->outsigmod > -1)
08080       mysig = p->outsigmod;
08081    p->subs[idx].f.frametype = AST_FRAME_NULL;
08082    p->subs[idx].f.subclass.integer = 0;
08083    p->subs[idx].f.datalen = 0;
08084    p->subs[idx].f.samples = 0;
08085    p->subs[idx].f.mallocd = 0;
08086    p->subs[idx].f.offset = 0;
08087    p->subs[idx].f.src = "dahdi_handle_event";
08088    p->subs[idx].f.data.ptr = NULL;
08089    f = &p->subs[idx].f;
08090 
08091    if (p->fake_event) {
08092       res = p->fake_event;
08093       p->fake_event = 0;
08094    } else
08095       res = dahdi_get_event(p->subs[idx].dfd);
08096 
08097    ast_debug(1, "Got event %s(%d) on channel %d (index %d)\n", event2str(res), res, p->channel, idx);
08098 
08099    if (res & (DAHDI_EVENT_PULSEDIGIT | DAHDI_EVENT_DTMFUP)) {
08100       p->pulsedial = (res & DAHDI_EVENT_PULSEDIGIT) ? 1 : 0;
08101       ast_debug(1, "Detected %sdigit '%c'\n", p->pulsedial ? "pulse ": "", res & 0xff);
08102 #if defined(HAVE_PRI)
08103       if (dahdi_sig_pri_lib_handles(p->sig)
08104          && ((struct sig_pri_chan *) p->sig_pvt)->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING
08105          && p->pri
08106          && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
08107          /* absorb event */
08108       } else
08109 #endif   /* defined(HAVE_PRI) */
08110       {
08111          /* Unmute conference */
08112          dahdi_confmute(p, 0);
08113          p->subs[idx].f.frametype = AST_FRAME_DTMF_END;
08114          p->subs[idx].f.subclass.integer = res & 0xff;
08115          dahdi_handle_dtmf(ast, idx, &f);
08116       }
08117       return f;
08118    }
08119 
08120    if (res & DAHDI_EVENT_DTMFDOWN) {
08121       ast_debug(1, "DTMF Down '%c'\n", res & 0xff);
08122 #if defined(HAVE_PRI)
08123       if (dahdi_sig_pri_lib_handles(p->sig)
08124          && ((struct sig_pri_chan *) p->sig_pvt)->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING
08125          && p->pri
08126          && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
08127          /* absorb event */
08128       } else
08129 #endif   /* defined(HAVE_PRI) */
08130       {
08131          /* Mute conference */
08132          dahdi_confmute(p, 1);
08133          p->subs[idx].f.frametype = AST_FRAME_DTMF_BEGIN;
08134          p->subs[idx].f.subclass.integer = res & 0xff;
08135          dahdi_handle_dtmf(ast, idx, &f);
08136       }
08137       return &p->subs[idx].f;
08138    }
08139 
08140    switch (res) {
08141    case DAHDI_EVENT_EC_DISABLED:
08142       ast_verb(3, "Channel %d echo canceler disabled.\n", p->channel);
08143       p->echocanon = 0;
08144       break;
08145 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
08146    case DAHDI_EVENT_TX_CED_DETECTED:
08147       ast_verb(3, "Channel %d detected a CED tone towards the network.\n", p->channel);
08148       break;
08149    case DAHDI_EVENT_RX_CED_DETECTED:
08150       ast_verb(3, "Channel %d detected a CED tone from the network.\n", p->channel);
08151       break;
08152    case DAHDI_EVENT_EC_NLP_DISABLED:
08153       ast_verb(3, "Channel %d echo canceler disabled its NLP.\n", p->channel);
08154       break;
08155    case DAHDI_EVENT_EC_NLP_ENABLED:
08156       ast_verb(3, "Channel %d echo canceler enabled its NLP.\n", p->channel);
08157       break;
08158 #endif
08159    case DAHDI_EVENT_BITSCHANGED:
08160 #ifdef HAVE_OPENR2
08161       if (p->sig != SIG_MFCR2) {
08162          ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig));
08163       } else {
08164          ast_debug(1, "bits changed in chan %d\n", p->channel);
08165          openr2_chan_handle_cas(p->r2chan);
08166       }
08167 #else
08168       ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig));
08169 #endif
08170       break;
08171    case DAHDI_EVENT_PULSE_START:
08172       /* Stop tone if there's a pulse start and the PBX isn't started */
08173       if (!ast_channel_pbx(ast))
08174          tone_zone_play_tone(p->subs[idx].dfd, -1);
08175       break;
08176    case DAHDI_EVENT_DIALCOMPLETE:
08177       /* DAHDI has completed dialing all digits sent using DAHDI_DIAL. */
08178 #if defined(HAVE_PRI)
08179       if (dahdi_sig_pri_lib_handles(p->sig)) {
08180          if (p->inalarm) {
08181             break;
08182          }
08183          if (ioctl(p->subs[idx].dfd, DAHDI_DIALING, &x) == -1) {
08184             ast_debug(1, "DAHDI_DIALING ioctl failed on %s: %s\n",
08185                ast_channel_name(ast), strerror(errno));
08186             return NULL;
08187          }
08188          if (x) {
08189             /* Still dialing in DAHDI driver */
08190             break;
08191          }
08192          /*
08193           * The ast channel is locked and the private may be locked more
08194           * than once.
08195           */
08196          sig_pri_dial_complete(p->sig_pvt, ast);
08197          break;
08198       }
08199 #endif   /* defined(HAVE_PRI) */
08200 #ifdef HAVE_OPENR2
08201       if ((p->sig & SIG_MFCR2) && p->r2chan && ast_channel_state(ast) != AST_STATE_UP) {
08202          /* we don't need to do anything for this event for R2 signaling
08203             if the call is being setup */
08204          break;
08205       }
08206 #endif
08207       if (p->inalarm) break;
08208       if ((p->radio || (p->oprmode < 0))) break;
08209       if (ioctl(p->subs[idx].dfd,DAHDI_DIALING,&x) == -1) {
08210          ast_debug(1, "DAHDI_DIALING ioctl failed on %s: %s\n",ast_channel_name(ast), strerror(errno));
08211          return NULL;
08212       }
08213       if (!x) { /* if not still dialing in driver */
08214          dahdi_enable_ec(p);
08215          if (p->echobreak) {
08216             dahdi_train_ec(p);
08217             ast_copy_string(p->dop.dialstr, p->echorest, sizeof(p->dop.dialstr));
08218             p->dop.op = DAHDI_DIAL_OP_REPLACE;
08219             res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
08220             p->echobreak = 0;
08221          } else {
08222             p->dialing = 0;
08223             if ((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) {
08224                /* if thru with dialing after offhook */
08225                if (ast_channel_state(ast) == AST_STATE_DIALING_OFFHOOK) {
08226                   ast_setstate(ast, AST_STATE_UP);
08227                   p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08228                   p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
08229                   break;
08230                } else { /* if to state wait for offhook to dial rest */
08231                   /* we now wait for off hook */
08232                   ast_setstate(ast,AST_STATE_DIALING_OFFHOOK);
08233                }
08234             }
08235             if (ast_channel_state(ast) == AST_STATE_DIALING) {
08236                if ((p->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
08237                   ast_debug(1, "Done dialing, but waiting for progress detection before doing more...\n");
08238                } else if (p->confirmanswer || (!p->dialednone
08239                   && ((mysig == SIG_EM) || (mysig == SIG_EM_E1)
08240                      || (mysig == SIG_EMWINK) || (mysig == SIG_FEATD)
08241                      || (mysig == SIG_FEATDMF_TA) || (mysig == SIG_FEATDMF)
08242                      || (mysig == SIG_E911) || (mysig == SIG_FGC_CAMA)
08243                      || (mysig == SIG_FGC_CAMAMF) || (mysig == SIG_FEATB)
08244                      || (mysig == SIG_SF) || (mysig == SIG_SFWINK)
08245                      || (mysig == SIG_SF_FEATD) || (mysig == SIG_SF_FEATDMF)
08246                      || (mysig == SIG_SF_FEATB)))) {
08247                   ast_setstate(ast, AST_STATE_RINGING);
08248                } else if (!p->answeronpolarityswitch) {
08249                   ast_setstate(ast, AST_STATE_UP);
08250                   p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08251                   p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
08252                   /* If aops=0 and hops=1, this is necessary */
08253                   p->polarity = POLARITY_REV;
08254                } else {
08255                   /* Start clean, so we can catch the change to REV polarity when party answers */
08256                   p->polarity = POLARITY_IDLE;
08257                }
08258             }
08259          }
08260       }
08261       break;
08262    case DAHDI_EVENT_ALARM:
08263       switch (p->sig) {
08264 #if defined(HAVE_PRI)
08265       case SIG_PRI_LIB_HANDLE_CASES:
08266          sig_pri_chan_alarm_notify(p->sig_pvt, 0);
08267          break;
08268 #endif   /* defined(HAVE_PRI) */
08269 #if defined(HAVE_SS7)
08270       case SIG_SS7:
08271          sig_ss7_set_alarm(p->sig_pvt, 1);
08272          break;
08273 #endif   /* defined(HAVE_SS7) */
08274       default:
08275          p->inalarm = 1;
08276          break;
08277       }
08278       res = get_alarms(p);
08279       handle_alarms(p, res);
08280 #ifdef HAVE_PRI
08281       if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
08282          /* fall through intentionally */
08283       } else {
08284          break;
08285       }
08286 #endif
08287 #if defined(HAVE_SS7)
08288       if (p->sig == SIG_SS7)
08289          break;
08290 #endif   /* defined(HAVE_SS7) */
08291 #ifdef HAVE_OPENR2
08292       if (p->sig == SIG_MFCR2)
08293          break;
08294 #endif
08295    case DAHDI_EVENT_ONHOOK:
08296       if (p->radio) {
08297          p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08298          p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_UNKEY;
08299          break;
08300       }
08301       if (p->oprmode < 0)
08302       {
08303          if (p->oprmode != -1) break;
08304          if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
08305          {
08306             /* Make sure it starts ringing */
08307             dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
08308             dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RING);
08309             save_conference(p->oprpeer);
08310             tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
08311          }
08312          break;
08313       }
08314       switch (p->sig) {
08315       case SIG_FXOLS:
08316       case SIG_FXOGS:
08317       case SIG_FXOKS:
08318          /* Check for some special conditions regarding call waiting */
08319          if (idx == SUB_REAL) {
08320             /* The normal line was hung up */
08321             if (p->subs[SUB_CALLWAIT].owner) {
08322                /* There's a call waiting call, so ring the phone, but make it unowned in the mean time */
08323                swap_subs(p, SUB_CALLWAIT, SUB_REAL);
08324                ast_verb(3, "Channel %d still has (callwait) call, ringing phone\n", p->channel);
08325                unalloc_sub(p, SUB_CALLWAIT);
08326 #if 0
08327                p->subs[idx].needanswer = 0;
08328                p->subs[idx].needringing = 0;
08329 #endif
08330                p->callwaitingrepeat = 0;
08331                p->cidcwexpire = 0;
08332                p->cid_suppress_expire = 0;
08333                p->owner = NULL;
08334                /* Don't start streaming audio yet if the incoming call isn't up yet */
08335                if (ast_channel_state(p->subs[SUB_REAL].owner) != AST_STATE_UP)
08336                   p->dialing = 1;
08337                dahdi_ring_phone(p);
08338             } else if (p->subs[SUB_THREEWAY].owner) {
08339                unsigned int mssinceflash;
08340                /* Here we have to retain the lock on both the main channel, the 3-way channel, and
08341                   the private structure -- not especially easy or clean */
08342                while (p->subs[SUB_THREEWAY].owner && ast_channel_trylock(p->subs[SUB_THREEWAY].owner)) {
08343                   /* Yuck, didn't get the lock on the 3-way, gotta release everything and re-grab! */
08344                   DLA_UNLOCK(&p->lock);
08345                   CHANNEL_DEADLOCK_AVOIDANCE(ast);
08346                   /* We can grab ast and p in that order, without worry.  We should make sure
08347                      nothing seriously bad has happened though like some sort of bizarre double
08348                      masquerade! */
08349                   DLA_LOCK(&p->lock);
08350                   if (p->owner != ast) {
08351                      ast_log(LOG_WARNING, "This isn't good...\n");
08352                      return NULL;
08353                   }
08354                }
08355                if (!p->subs[SUB_THREEWAY].owner) {
08356                   ast_log(LOG_NOTICE, "Whoa, threeway disappeared kinda randomly.\n");
08357                   return NULL;
08358                }
08359                mssinceflash = ast_tvdiff_ms(ast_tvnow(), p->flashtime);
08360                ast_debug(1, "Last flash was %d ms ago\n", mssinceflash);
08361                if (mssinceflash < MIN_MS_SINCE_FLASH) {
08362                   /* It hasn't been long enough since the last flashook.  This is probably a bounce on
08363                      hanging up.  Hangup both channels now */
08364                   if (p->subs[SUB_THREEWAY].owner)
08365                      ast_queue_hangup_with_cause(p->subs[SUB_THREEWAY].owner, AST_CAUSE_NO_ANSWER);
08366                   ast_channel_softhangup_internal_flag_add(p->subs[SUB_THREEWAY].owner, AST_SOFTHANGUP_DEV);
08367                   ast_debug(1, "Looks like a bounced flash, hanging up both calls on %d\n", p->channel);
08368                   ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08369                } else if ((ast_channel_pbx(ast)) || (ast_channel_state(ast) == AST_STATE_UP)) {
08370                   if (p->transfer) {
08371                      /* In any case this isn't a threeway call anymore */
08372                      p->subs[SUB_REAL].inthreeway = 0;
08373                      p->subs[SUB_THREEWAY].inthreeway = 0;
08374                      /* Only attempt transfer if the phone is ringing; why transfer to busy tone eh? */
08375                      if (!p->transfertobusy && ast_channel_state(ast) == AST_STATE_BUSY) {
08376                         ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08377                         /* Swap subs and dis-own channel */
08378                         swap_subs(p, SUB_THREEWAY, SUB_REAL);
08379                         p->owner = NULL;
08380                         /* Ring the phone */
08381                         dahdi_ring_phone(p);
08382                      } else {
08383                         if ((res = attempt_transfer(p)) < 0) {
08384                            ast_channel_softhangup_internal_flag_add(p->subs[SUB_THREEWAY].owner, AST_SOFTHANGUP_DEV);
08385                            if (p->subs[SUB_THREEWAY].owner)
08386                               ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08387                         } else if (res) {
08388                            /* Don't actually hang up at this point */
08389                            if (p->subs[SUB_THREEWAY].owner)
08390                               ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08391                            break;
08392                         }
08393                      }
08394                   } else {
08395                      ast_channel_softhangup_internal_flag_add(p->subs[SUB_THREEWAY].owner, AST_SOFTHANGUP_DEV);
08396                      if (p->subs[SUB_THREEWAY].owner)
08397                         ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08398                   }
08399                } else {
08400                   ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08401                   /* Swap subs and dis-own channel */
08402                   swap_subs(p, SUB_THREEWAY, SUB_REAL);
08403                   p->owner = NULL;
08404                   /* Ring the phone */
08405                   dahdi_ring_phone(p);
08406                }
08407             }
08408          } else {
08409             ast_log(LOG_WARNING, "Got a hangup and my index is %d?\n", idx);
08410          }
08411          /* Fall through */
08412       default:
08413          dahdi_disable_ec(p);
08414          return NULL;
08415       }
08416       break;
08417    case DAHDI_EVENT_RINGOFFHOOK:
08418       if (p->inalarm) break;
08419       if (p->oprmode < 0)
08420       {
08421          if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
08422          {
08423             /* Make sure it stops ringing */
08424             dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
08425             tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, -1);
08426             restore_conference(p->oprpeer);
08427          }
08428          break;
08429       }
08430       if (p->radio)
08431       {
08432          p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08433          p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_KEY;
08434          break;
08435       }
08436       /* for E911, its supposed to wait for offhook then dial
08437          the second half of the dial string */
08438       if (((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) && (ast_channel_state(ast) == AST_STATE_DIALING_OFFHOOK)) {
08439          c = strchr(p->dialdest, '/');
08440          if (c)
08441             c++;
08442          else
08443             c = p->dialdest;
08444          if (*c) snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*0%s#", c);
08445          else ast_copy_string(p->dop.dialstr,"M*2#", sizeof(p->dop.dialstr));
08446          if (strlen(p->dop.dialstr) > 4) {
08447             memset(p->echorest, 'w', sizeof(p->echorest) - 1);
08448             strcpy(p->echorest + (p->echotraining / 401) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
08449             p->echorest[sizeof(p->echorest) - 1] = '\0';
08450             p->echobreak = 1;
08451             p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
08452          } else
08453             p->echobreak = 0;
08454          if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
08455             int saveerr = errno;
08456 
08457             x = DAHDI_ONHOOK;
08458             ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
08459             ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
08460             return NULL;
08461             }
08462          p->dialing = 1;
08463          return &p->subs[idx].f;
08464       }
08465       switch (p->sig) {
08466       case SIG_FXOLS:
08467       case SIG_FXOGS:
08468       case SIG_FXOKS:
08469          switch (ast_channel_state(ast)) {
08470          case AST_STATE_RINGING:
08471             dahdi_enable_ec(p);
08472             dahdi_train_ec(p);
08473             p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08474             p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
08475             /* Make sure it stops ringing */
08476             p->subs[SUB_REAL].needringing = 0;
08477             dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
08478             ast_debug(1, "channel %d answered\n", p->channel);
08479 
08480             /* Cancel any running CallerID spill */
08481             ast_free(p->cidspill);
08482             p->cidspill = NULL;
08483             restore_conference(p);
08484 
08485             p->dialing = 0;
08486             p->callwaitcas = 0;
08487             if (p->confirmanswer) {
08488                /* Ignore answer if "confirm answer" is enabled */
08489                p->subs[idx].f.frametype = AST_FRAME_NULL;
08490                p->subs[idx].f.subclass.integer = 0;
08491             } else if (!ast_strlen_zero(p->dop.dialstr)) {
08492                /* nick@dccinc.com 4/3/03 - fxo should be able to do deferred dialing */
08493                res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
08494                if (res < 0) {
08495                   ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
08496                   p->dop.dialstr[0] = '\0';
08497                   return NULL;
08498                } else {
08499                   ast_debug(1, "Sent FXO deferred digit string: %s\n", p->dop.dialstr);
08500                   p->subs[idx].f.frametype = AST_FRAME_NULL;
08501                   p->subs[idx].f.subclass.integer = 0;
08502                   p->dialing = 1;
08503                }
08504                p->dop.dialstr[0] = '\0';
08505                ast_setstate(ast, AST_STATE_DIALING);
08506             } else
08507                ast_setstate(ast, AST_STATE_UP);
08508             return &p->subs[idx].f;
08509          case AST_STATE_DOWN:
08510             ast_setstate(ast, AST_STATE_RING);
08511             ast_channel_rings_set(ast, 1);
08512             p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08513             p->subs[idx].f.subclass.integer = AST_CONTROL_OFFHOOK;
08514             ast_debug(1, "channel %d picked up\n", p->channel);
08515             return &p->subs[idx].f;
08516          case AST_STATE_UP:
08517             /* Make sure it stops ringing */
08518             dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
08519             /* Okay -- probably call waiting*/
08520             if (ast_bridged_channel(p->owner))
08521                ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
08522             p->subs[idx].needunhold = 1;
08523             break;
08524          case AST_STATE_RESERVED:
08525             /* Start up dialtone */
08526             if (has_voicemail(p))
08527                res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
08528             else
08529                res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
08530             break;
08531          default:
08532             ast_log(LOG_WARNING, "FXO phone off hook in weird state %d??\n", ast_channel_state(ast));
08533          }
08534          break;
08535       case SIG_FXSLS:
08536       case SIG_FXSGS:
08537       case SIG_FXSKS:
08538          if (ast_channel_state(ast) == AST_STATE_RING) {
08539             p->ringt = p->ringt_base;
08540          }
08541 
08542          /* If we get a ring then we cannot be in
08543           * reversed polarity. So we reset to idle */
08544          ast_debug(1, "Setting IDLE polarity due "
08545             "to ring. Old polarity was %d\n",
08546             p->polarity);
08547          p->polarity = POLARITY_IDLE;
08548 
08549          /* Fall through */
08550       case SIG_EM:
08551       case SIG_EM_E1:
08552       case SIG_EMWINK:
08553       case SIG_FEATD:
08554       case SIG_FEATDMF:
08555       case SIG_FEATDMF_TA:
08556       case SIG_E911:
08557       case SIG_FGC_CAMA:
08558       case SIG_FGC_CAMAMF:
08559       case SIG_FEATB:
08560       case SIG_SF:
08561       case SIG_SFWINK:
08562       case SIG_SF_FEATD:
08563       case SIG_SF_FEATDMF:
08564       case SIG_SF_FEATB:
08565          if (ast_channel_state(ast) == AST_STATE_PRERING)
08566             ast_setstate(ast, AST_STATE_RING);
08567          if ((ast_channel_state(ast) == AST_STATE_DOWN) || (ast_channel_state(ast) == AST_STATE_RING)) {
08568             ast_debug(1, "Ring detected\n");
08569             p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08570             p->subs[idx].f.subclass.integer = AST_CONTROL_RING;
08571          } else if (p->outgoing && ((ast_channel_state(ast) == AST_STATE_RINGING) || (ast_channel_state(ast) == AST_STATE_DIALING))) {
08572             ast_debug(1, "Line answered\n");
08573             if (p->confirmanswer) {
08574                p->subs[idx].f.frametype = AST_FRAME_NULL;
08575                p->subs[idx].f.subclass.integer = 0;
08576             } else {
08577                p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08578                p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
08579                ast_setstate(ast, AST_STATE_UP);
08580             }
08581          } else if (ast_channel_state(ast) != AST_STATE_RING)
08582             ast_log(LOG_WARNING, "Ring/Off-hook in strange state %d on channel %d\n", ast_channel_state(ast), p->channel);
08583          break;
08584       default:
08585          ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
08586       }
08587       break;
08588    case DAHDI_EVENT_RINGBEGIN:
08589       switch (p->sig) {
08590       case SIG_FXSLS:
08591       case SIG_FXSGS:
08592       case SIG_FXSKS:
08593          if (ast_channel_state(ast) == AST_STATE_RING) {
08594             p->ringt = p->ringt_base;
08595          }
08596          break;
08597       }
08598       break;
08599    case DAHDI_EVENT_RINGERON:
08600       break;
08601    case DAHDI_EVENT_NOALARM:
08602       switch (p->sig) {
08603 #if defined(HAVE_PRI)
08604       case SIG_PRI_LIB_HANDLE_CASES:
08605          sig_pri_chan_alarm_notify(p->sig_pvt, 1);
08606          break;
08607 #endif   /* defined(HAVE_PRI) */
08608 #if defined(HAVE_SS7)
08609       case SIG_SS7:
08610          sig_ss7_set_alarm(p->sig_pvt, 0);
08611          break;
08612 #endif   /* defined(HAVE_SS7) */
08613       default:
08614          p->inalarm = 0;
08615          break;
08616       }
08617       handle_clear_alarms(p);
08618       break;
08619    case DAHDI_EVENT_WINKFLASH:
08620       if (p->inalarm) break;
08621       if (p->radio) break;
08622       if (p->oprmode < 0) break;
08623       if (p->oprmode > 1)
08624       {
08625          struct dahdi_params par;
08626 
08627          memset(&par, 0, sizeof(par));
08628          if (ioctl(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par) != -1)
08629          {
08630             if (!par.rxisoffhook)
08631             {
08632                /* Make sure it stops ringing */
08633                dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
08634                dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RING);
08635                save_conference(p);
08636                tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
08637             }
08638          }
08639          break;
08640       }
08641       /* Remember last time we got a flash-hook */
08642       p->flashtime = ast_tvnow();
08643       switch (mysig) {
08644       case SIG_FXOLS:
08645       case SIG_FXOGS:
08646       case SIG_FXOKS:
08647          ast_debug(1, "Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n",
08648             idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
08649 
08650          /* Cancel any running CallerID spill */
08651          ast_free(p->cidspill);
08652          p->cidspill = NULL;
08653          restore_conference(p);
08654          p->callwaitcas = 0;
08655 
08656          if (idx != SUB_REAL) {
08657             ast_log(LOG_WARNING, "Got flash hook with index %d on channel %d?!?\n", idx, p->channel);
08658             goto winkflashdone;
08659          }
08660 
08661          if (p->subs[SUB_CALLWAIT].owner) {
08662             /* Swap to call-wait */
08663             swap_subs(p, SUB_REAL, SUB_CALLWAIT);
08664             tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
08665             p->owner = p->subs[SUB_REAL].owner;
08666             ast_debug(1, "Making %s the new owner\n", ast_channel_name(p->owner));
08667             if (ast_channel_state(p->owner) == AST_STATE_RINGING) {
08668                ast_setstate(p->owner, AST_STATE_UP);
08669                p->subs[SUB_REAL].needanswer = 1;
08670             }
08671             p->callwaitingrepeat = 0;
08672             p->cidcwexpire = 0;
08673             p->cid_suppress_expire = 0;
08674             /* Start music on hold if appropriate */
08675             if (!p->subs[SUB_CALLWAIT].inthreeway && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
08676                ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
08677                   S_OR(p->mohsuggest, NULL),
08678                   !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
08679             }
08680             p->subs[SUB_CALLWAIT].needhold = 1;
08681             if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
08682                ast_queue_control_data(p->subs[SUB_REAL].owner, AST_CONTROL_HOLD,
08683                   S_OR(p->mohsuggest, NULL),
08684                   !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
08685             }
08686             p->subs[SUB_REAL].needunhold = 1;
08687          } else if (!p->subs[SUB_THREEWAY].owner) {
08688             if (!p->threewaycalling) {
08689                /* Just send a flash if no 3-way calling */
08690                p->subs[SUB_REAL].needflash = 1;
08691                goto winkflashdone;
08692             } else if (!check_for_conference(p)) {
08693                struct ast_callid *callid = NULL;
08694                int callid_created;
08695                char cid_num[256];
08696                char cid_name[256];
08697 
08698                cid_num[0] = 0;
08699                cid_name[0] = 0;
08700                if (p->dahditrcallerid && p->owner) {
08701                   if (ast_channel_caller(p->owner)->id.number.valid
08702                      && ast_channel_caller(p->owner)->id.number.str) {
08703                      ast_copy_string(cid_num, ast_channel_caller(p->owner)->id.number.str,
08704                         sizeof(cid_num));
08705                   }
08706                   if (ast_channel_caller(p->owner)->id.name.valid
08707                      && ast_channel_caller(p->owner)->id.name.str) {
08708                      ast_copy_string(cid_name, ast_channel_caller(p->owner)->id.name.str,
08709                         sizeof(cid_name));
08710                   }
08711                }
08712                /* XXX This section needs much more error checking!!! XXX */
08713                /* Start a 3-way call if feasible */
08714                if (!((ast_channel_pbx(ast)) ||
08715                   (ast_channel_state(ast) == AST_STATE_UP) ||
08716                   (ast_channel_state(ast) == AST_STATE_RING))) {
08717                   ast_debug(1, "Flash when call not up or ringing\n");
08718                   goto winkflashdone;
08719                }
08720                if (alloc_sub(p, SUB_THREEWAY)) {
08721                   ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n");
08722                   goto winkflashdone;
08723                }
08724                callid_created = ast_callid_threadstorage_auto(&callid);
08725                /*
08726                 * Make new channel
08727                 *
08728                 * We cannot hold the p or ast locks while creating a new
08729                 * channel.
08730                 */
08731                ast_mutex_unlock(&p->lock);
08732                ast_channel_unlock(ast);
08733                chan = dahdi_new(p, AST_STATE_RESERVED, 0, SUB_THREEWAY, 0, NULL, callid);
08734                ast_channel_lock(ast);
08735                ast_mutex_lock(&p->lock);
08736                if (p->dahditrcallerid) {
08737                   if (!p->origcid_num)
08738                      p->origcid_num = ast_strdup(p->cid_num);
08739                   if (!p->origcid_name)
08740                      p->origcid_name = ast_strdup(p->cid_name);
08741                   ast_copy_string(p->cid_num, cid_num, sizeof(p->cid_num));
08742                   ast_copy_string(p->cid_name, cid_name, sizeof(p->cid_name));
08743                }
08744                /* Swap things around between the three-way and real call */
08745                swap_subs(p, SUB_THREEWAY, SUB_REAL);
08746                /* Disable echo canceller for better dialing */
08747                dahdi_disable_ec(p);
08748                res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALRECALL);
08749                if (res)
08750                   ast_log(LOG_WARNING, "Unable to start dial recall tone on channel %d\n", p->channel);
08751                p->owner = chan;
08752                if (!chan) {
08753                   ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", p->channel);
08754                } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
08755                   ast_log(LOG_WARNING, "Unable to start simple switch on channel %d\n", p->channel);
08756                   res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
08757                   dahdi_enable_ec(p);
08758                   ast_hangup(chan);
08759                } else {
08760                   ast_verb(3, "Started three way call on channel %d\n", p->channel);
08761 
08762                   /* Start music on hold if appropriate */
08763                   if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
08764                      ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
08765                         S_OR(p->mohsuggest, NULL),
08766                         !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
08767                   }
08768                   p->subs[SUB_THREEWAY].needhold = 1;
08769                }
08770                ast_callid_threadstorage_auto_clean(callid, callid_created);
08771             }
08772          } else {
08773             /* Already have a 3 way call */
08774             if (p->subs[SUB_THREEWAY].inthreeway) {
08775                /* Call is already up, drop the last person */
08776                ast_debug(1, "Got flash with three way call up, dropping last call on %d\n", p->channel);
08777                /* If the primary call isn't answered yet, use it */
08778                if ((ast_channel_state(p->subs[SUB_REAL].owner) != AST_STATE_UP) && (ast_channel_state(p->subs[SUB_THREEWAY].owner) == AST_STATE_UP)) {
08779                   /* Swap back -- we're dropping the real 3-way that isn't finished yet*/
08780                   swap_subs(p, SUB_THREEWAY, SUB_REAL);
08781                   p->owner = p->subs[SUB_REAL].owner;
08782                }
08783                /* Drop the last call and stop the conference */
08784                ast_verb(3, "Dropping three-way call on %s\n", ast_channel_name(p->subs[SUB_THREEWAY].owner));
08785                ast_channel_softhangup_internal_flag_add(p->subs[SUB_THREEWAY].owner, AST_SOFTHANGUP_DEV);
08786                p->subs[SUB_REAL].inthreeway = 0;
08787                p->subs[SUB_THREEWAY].inthreeway = 0;
08788             } else {
08789                /* Lets see what we're up to */
08790                if (((ast_channel_pbx(ast)) || (ast_channel_state(ast) == AST_STATE_UP)) &&
08791                   (p->transfertobusy || (ast_channel_state(ast) != AST_STATE_BUSY))) {
08792                   int otherindex = SUB_THREEWAY;
08793 
08794                   ast_verb(3, "Building conference call with %s and %s\n",
08795                      ast_channel_name(p->subs[SUB_THREEWAY].owner),
08796                      ast_channel_name(p->subs[SUB_REAL].owner));
08797                   /* Put them in the threeway, and flip */
08798                   p->subs[SUB_THREEWAY].inthreeway = 1;
08799                   p->subs[SUB_REAL].inthreeway = 1;
08800                   if (ast_channel_state(ast) == AST_STATE_UP) {
08801                      swap_subs(p, SUB_THREEWAY, SUB_REAL);
08802                      otherindex = SUB_REAL;
08803                   }
08804                   if (p->subs[otherindex].owner && ast_bridged_channel(p->subs[otherindex].owner))
08805                      ast_queue_control(p->subs[otherindex].owner, AST_CONTROL_UNHOLD);
08806                   p->subs[otherindex].needunhold = 1;
08807                   p->owner = p->subs[SUB_REAL].owner;
08808                } else {
08809                   ast_verb(3, "Dumping incomplete call on on %s\n", ast_channel_name(p->subs[SUB_THREEWAY].owner));
08810                   swap_subs(p, SUB_THREEWAY, SUB_REAL);
08811                   ast_channel_softhangup_internal_flag_add(p->subs[SUB_THREEWAY].owner, AST_SOFTHANGUP_DEV);
08812                   p->owner = p->subs[SUB_REAL].owner;
08813                   if (p->subs[SUB_REAL].owner && ast_bridged_channel(p->subs[SUB_REAL].owner))
08814                      ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
08815                   p->subs[SUB_REAL].needunhold = 1;
08816                   dahdi_enable_ec(p);
08817                }
08818             }
08819          }
08820 winkflashdone:
08821          update_conf(p);
08822          break;
08823       case SIG_EM:
08824       case SIG_EM_E1:
08825       case SIG_FEATD:
08826       case SIG_SF:
08827       case SIG_SFWINK:
08828       case SIG_SF_FEATD:
08829       case SIG_FXSLS:
08830       case SIG_FXSGS:
08831          if (p->dialing)
08832             ast_debug(1, "Ignoring wink on channel %d\n", p->channel);
08833          else
08834             ast_debug(1, "Got wink in weird state %d on channel %d\n", ast_channel_state(ast), p->channel);
08835          break;
08836       case SIG_FEATDMF_TA:
08837          switch (p->whichwink) {
08838          case 0:
08839             ast_debug(1, "ANI2 set to '%d' and ANI is '%s'\n", ast_channel_caller(p->owner)->ani2,
08840                S_COR(ast_channel_caller(p->owner)->ani.number.valid,
08841                   ast_channel_caller(p->owner)->ani.number.str, ""));
08842             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%d%s#",
08843                ast_channel_caller(p->owner)->ani2,
08844                S_COR(ast_channel_caller(p->owner)->ani.number.valid,
08845                   ast_channel_caller(p->owner)->ani.number.str, ""));
08846             break;
08847          case 1:
08848             ast_copy_string(p->dop.dialstr, p->finaldial, sizeof(p->dop.dialstr));
08849             break;
08850          case 2:
08851             ast_log(LOG_WARNING, "Received unexpected wink on channel of type SIG_FEATDMF_TA\n");
08852             return NULL;
08853          }
08854          p->whichwink++;
08855          /* Fall through */
08856       case SIG_FEATDMF:
08857       case SIG_E911:
08858       case SIG_FGC_CAMAMF:
08859       case SIG_FGC_CAMA:
08860       case SIG_FEATB:
08861       case SIG_SF_FEATDMF:
08862       case SIG_SF_FEATB:
08863       case SIG_EMWINK:
08864          /* FGD MF and EMWINK *Must* wait for wink */
08865          if (!ast_strlen_zero(p->dop.dialstr)) {
08866             res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
08867             if (res < 0) {
08868                ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
08869                p->dop.dialstr[0] = '\0';
08870                return NULL;
08871             } else
08872                ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
08873          }
08874          p->dop.dialstr[0] = '\0';
08875          break;
08876       default:
08877          ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
08878       }
08879       break;
08880    case DAHDI_EVENT_HOOKCOMPLETE:
08881       if (p->inalarm) break;
08882       if ((p->radio || (p->oprmode < 0))) break;
08883       if (p->waitingfordt.tv_sec) break;
08884       switch (mysig) {
08885       case SIG_FXSLS:  /* only interesting for FXS */
08886       case SIG_FXSGS:
08887       case SIG_FXSKS:
08888       case SIG_EM:
08889       case SIG_EM_E1:
08890       case SIG_EMWINK:
08891       case SIG_FEATD:
08892       case SIG_SF:
08893       case SIG_SFWINK:
08894       case SIG_SF_FEATD:
08895          if (!ast_strlen_zero(p->dop.dialstr)) {
08896             res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
08897             if (res < 0) {
08898                ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
08899                p->dop.dialstr[0] = '\0';
08900                return NULL;
08901             } else
08902                ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
08903          }
08904          p->dop.dialstr[0] = '\0';
08905          p->dop.op = DAHDI_DIAL_OP_REPLACE;
08906          break;
08907       case SIG_FEATDMF:
08908       case SIG_FEATDMF_TA:
08909       case SIG_E911:
08910       case SIG_FGC_CAMA:
08911       case SIG_FGC_CAMAMF:
08912       case SIG_FEATB:
08913       case SIG_SF_FEATDMF:
08914       case SIG_SF_FEATB:
08915          ast_debug(1, "Got hook complete in MF FGD, waiting for wink now on channel %d\n",p->channel);
08916          break;
08917       default:
08918          break;
08919       }
08920       break;
08921    case DAHDI_EVENT_POLARITY:
08922       /*
08923        * If we get a Polarity Switch event, check to see
08924        * if we should change the polarity state and
08925        * mark the channel as UP or if this is an indication
08926        * of remote end disconnect.
08927        */
08928       if (p->polarity == POLARITY_IDLE) {
08929          p->polarity = POLARITY_REV;
08930          if (p->answeronpolarityswitch &&
08931             ((ast_channel_state(ast) == AST_STATE_DIALING) ||
08932             (ast_channel_state(ast) == AST_STATE_RINGING))) {
08933             ast_debug(1, "Answering on polarity switch!\n");
08934             ast_setstate(p->owner, AST_STATE_UP);
08935             if (p->hanguponpolarityswitch) {
08936                p->polaritydelaytv = ast_tvnow();
08937             }
08938          } else
08939             ast_debug(1, "Ignore switch to REVERSED Polarity on channel %d, state %d\n", p->channel, ast_channel_state(ast));
08940       }
08941       /* Removed else statement from here as it was preventing hangups from ever happening*/
08942       /* Added AST_STATE_RING in if statement below to deal with calling party hangups that take place when ringing */
08943       if (p->hanguponpolarityswitch &&
08944          (p->polarityonanswerdelay > 0) &&
08945          (p->polarity == POLARITY_REV) &&
08946          ((ast_channel_state(ast) == AST_STATE_UP) || (ast_channel_state(ast) == AST_STATE_RING)) ) {
08947          /* Added log_debug information below to provide a better indication of what is going on */
08948          ast_debug(1, "Polarity Reversal event occured - DEBUG 1: channel %d, state %d, 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) );
08949 
08950          if (ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) > p->polarityonanswerdelay) {
08951             ast_debug(1, "Polarity Reversal detected and now Hanging up on channel %d\n", p->channel);
08952             ast_softhangup(p->owner, AST_SOFTHANGUP_EXPLICIT);
08953             p->polarity = POLARITY_IDLE;
08954          } else
08955             ast_debug(1, "Polarity Reversal detected but NOT hanging up (too close to answer event) on channel %d, state %d\n", p->channel, ast_channel_state(ast));
08956 
08957       } else {
08958          p->polarity = POLARITY_IDLE;
08959          ast_debug(1, "Ignoring Polarity switch to IDLE on channel %d, state %d\n", p->channel, ast_channel_state(ast));
08960       }
08961       /* Added more log_debug information below to provide a better indication of what is going on */
08962       ast_debug(1, "Polarity Reversal event occured - DEBUG 2: channel %d, state %d, 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) );
08963       break;
08964    default:
08965       ast_debug(1, "Dunno what to do with event %d on channel %d\n", res, p->channel);
08966    }
08967    return &p->subs[idx].f;
08968 }
08969 
08970 static struct ast_frame *__dahdi_exception(struct ast_channel *ast)
08971 {
08972    int res;
08973    int idx;
08974    struct ast_frame *f;
08975    int usedindex = -1;
08976    struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
08977 
08978    if ((idx = dahdi_get_index(ast, p, 0)) < 0) {
08979       idx = SUB_REAL;
08980    }
08981 
08982    p->subs[idx].f.frametype = AST_FRAME_NULL;
08983    p->subs[idx].f.datalen = 0;
08984    p->subs[idx].f.samples = 0;
08985    p->subs[idx].f.mallocd = 0;
08986    p->subs[idx].f.offset = 0;
08987    p->subs[idx].f.subclass.integer = 0;
08988    p->subs[idx].f.delivery = ast_tv(0,0);
08989    p->subs[idx].f.src = "dahdi_exception";
08990    p->subs[idx].f.data.ptr = NULL;
08991 
08992 
08993    if ((!p->owner) && (!(p->radio || (p->oprmode < 0)))) {
08994       /* If nobody owns us, absorb the event appropriately, otherwise
08995          we loop indefinitely.  This occurs when, during call waiting, the
08996          other end hangs up our channel so that it no longer exists, but we
08997          have neither FLASH'd nor ONHOOK'd to signify our desire to
08998          change to the other channel. */
08999       if (p->fake_event) {
09000          res = p->fake_event;
09001          p->fake_event = 0;
09002       } else
09003          res = dahdi_get_event(p->subs[SUB_REAL].dfd);
09004       /* Switch to real if there is one and this isn't something really silly... */
09005       if ((res != DAHDI_EVENT_RINGEROFF) && (res != DAHDI_EVENT_RINGERON) &&
09006          (res != DAHDI_EVENT_HOOKCOMPLETE)) {
09007          ast_debug(1, "Restoring owner of channel %d on event %d\n", p->channel, res);
09008          p->owner = p->subs[SUB_REAL].owner;
09009          if (p->owner && ast_bridged_channel(p->owner))
09010             ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
09011          p->subs[SUB_REAL].needunhold = 1;
09012       }
09013       switch (res) {
09014       case DAHDI_EVENT_ONHOOK:
09015          dahdi_disable_ec(p);
09016          if (p->owner) {
09017             ast_verb(3, "Channel %s still has call, ringing phone\n", ast_channel_name(p->owner));
09018             dahdi_ring_phone(p);
09019             p->callwaitingrepeat = 0;
09020             p->cidcwexpire = 0;
09021             p->cid_suppress_expire = 0;
09022          } else
09023             ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
09024          update_conf(p);
09025          break;
09026       case DAHDI_EVENT_RINGOFFHOOK:
09027          dahdi_enable_ec(p);
09028          dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
09029          if (p->owner && (ast_channel_state(p->owner) == AST_STATE_RINGING)) {
09030             p->subs[SUB_REAL].needanswer = 1;
09031             p->dialing = 0;
09032          }
09033          break;
09034       case DAHDI_EVENT_HOOKCOMPLETE:
09035       case DAHDI_EVENT_RINGERON:
09036       case DAHDI_EVENT_RINGEROFF:
09037          /* Do nothing */
09038          break;
09039       case DAHDI_EVENT_WINKFLASH:
09040          p->flashtime = ast_tvnow();
09041          if (p->owner) {
09042             ast_verb(3, "Channel %d flashed to other channel %s\n", p->channel, ast_channel_name(p->owner));
09043             if (ast_channel_state(p->owner) != AST_STATE_UP) {
09044                /* Answer if necessary */
09045                usedindex = dahdi_get_index(p->owner, p, 0);
09046                if (usedindex > -1) {
09047                   p->subs[usedindex].needanswer = 1;
09048                }
09049                ast_setstate(p->owner, AST_STATE_UP);
09050             }
09051             p->callwaitingrepeat = 0;
09052             p->cidcwexpire = 0;
09053             p->cid_suppress_expire = 0;
09054             if (ast_bridged_channel(p->owner))
09055                ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
09056             p->subs[SUB_REAL].needunhold = 1;
09057          } else
09058             ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
09059          update_conf(p);
09060          break;
09061       default:
09062          ast_log(LOG_WARNING, "Don't know how to absorb event %s\n", event2str(res));
09063       }
09064       f = &p->subs[idx].f;
09065       return f;
09066    }
09067    if (!(p->radio || (p->oprmode < 0)))
09068       ast_debug(1, "Exception on %d, channel %d\n", ast_channel_fd(ast, 0), p->channel);
09069    /* If it's not us, return NULL immediately */
09070    if (ast != p->owner) {
09071       if (p->owner) {
09072          ast_log(LOG_WARNING, "We're %s, not %s\n", ast_channel_name(ast), ast_channel_name(p->owner));
09073       }
09074       f = &p->subs[idx].f;
09075       return f;
09076    }
09077 
09078    f = dahdi_handle_event(ast);
09079    if (!f) {
09080       const char *name = ast_strdupa(ast_channel_name(ast));
09081 
09082       /* Tell the CDR this DAHDI device hung up */
09083       ast_mutex_unlock(&p->lock);
09084       ast_channel_unlock(ast);
09085       ast_set_hangupsource(ast, name, 0);
09086       ast_channel_lock(ast);
09087       ast_mutex_lock(&p->lock);
09088    }
09089    return f;
09090 }
09091 
09092 static struct ast_frame *dahdi_exception(struct ast_channel *ast)
09093 {
09094    struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
09095    struct ast_frame *f;
09096    ast_mutex_lock(&p->lock);
09097    if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
09098       struct analog_pvt *analog_p = p->sig_pvt;
09099       f = analog_exception(analog_p, ast);
09100    } else {
09101       f = __dahdi_exception(ast);
09102    }
09103    ast_mutex_unlock(&p->lock);
09104    return f;
09105 }
09106 
09107 static struct ast_frame *dahdi_read(struct ast_channel *ast)
09108 {
09109    struct dahdi_pvt *p;
09110    int res;
09111    int idx;
09112    void *readbuf;
09113    struct ast_frame *f;
09114 
09115    /*
09116     * For analog channels, we must do deadlock avoidance because
09117     * analog ports can have more than one Asterisk channel using
09118     * the same private structure.
09119     */
09120    p = ast_channel_tech_pvt(ast);
09121    while (ast_mutex_trylock(&p->lock)) {
09122       CHANNEL_DEADLOCK_AVOIDANCE(ast);
09123 
09124       /*
09125        * Check to see if the channel is still associated with the same
09126        * private structure.  While the Asterisk channel was unlocked
09127        * the following events may have occured:
09128        *
09129        * 1) A masquerade may have associated the channel with another
09130        * technology or private structure.
09131        *
09132        * 2) For PRI calls, call signaling could change the channel
09133        * association to another B channel (private structure).
09134        */
09135       if (ast_channel_tech_pvt(ast) != p) {
09136          /* The channel is no longer associated.  Quit gracefully. */
09137          return &ast_null_frame;
09138       }
09139    }
09140 
09141    idx = dahdi_get_index(ast, p, 0);
09142 
09143    /* Hang up if we don't really exist */
09144    if (idx < 0)   {
09145       ast_log(LOG_WARNING, "We don't exist?\n");
09146       ast_mutex_unlock(&p->lock);
09147       return NULL;
09148    }
09149 
09150    if ((p->radio || (p->oprmode < 0)) && p->inalarm) {
09151       ast_mutex_unlock(&p->lock);
09152       return NULL;
09153    }
09154 
09155    p->subs[idx].f.frametype = AST_FRAME_NULL;
09156    p->subs[idx].f.datalen = 0;
09157    p->subs[idx].f.samples = 0;
09158    p->subs[idx].f.mallocd = 0;
09159    p->subs[idx].f.offset = 0;
09160    p->subs[idx].f.subclass.integer = 0;
09161    p->subs[idx].f.delivery = ast_tv(0,0);
09162    p->subs[idx].f.src = "dahdi_read";
09163    p->subs[idx].f.data.ptr = NULL;
09164 
09165    /* make sure it sends initial key state as first frame */
09166    if ((p->radio || (p->oprmode < 0)) && (!p->firstradio))
09167    {
09168       struct dahdi_params ps;
09169 
09170       memset(&ps, 0, sizeof(ps));
09171       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
09172          ast_mutex_unlock(&p->lock);
09173          return NULL;
09174       }
09175       p->firstradio = 1;
09176       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09177       if (ps.rxisoffhook)
09178       {
09179          p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_KEY;
09180       }
09181       else
09182       {
09183          p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_UNKEY;
09184       }
09185       ast_mutex_unlock(&p->lock);
09186       return &p->subs[idx].f;
09187    }
09188    if (p->ringt > 0) {
09189       if (!(--p->ringt)) {
09190          ast_mutex_unlock(&p->lock);
09191          return NULL;
09192       }
09193    }
09194 
09195 #ifdef HAVE_OPENR2
09196    if (p->mfcr2) {
09197       openr2_chan_process_event(p->r2chan);
09198       if (OR2_DIR_FORWARD == openr2_chan_get_direction(p->r2chan)) {
09199          struct ast_frame fr = { AST_FRAME_CONTROL, { AST_CONTROL_PROGRESS } };
09200          /* if the call is already accepted and we already delivered AST_CONTROL_RINGING
09201           * now enqueue a progress frame to bridge the media up */
09202          if (p->mfcr2_call_accepted &&
09203             !p->mfcr2_progress_sent && 
09204             ast_channel_state(ast) == AST_STATE_RINGING) {
09205             ast_debug(1, "Enqueuing progress frame after R2 accept in chan %d\n", p->channel);
09206             ast_queue_frame(p->owner, &fr);
09207             p->mfcr2_progress_sent = 1;
09208          }
09209       }
09210    }
09211 #endif
09212 
09213    if (p->subs[idx].needringing) {
09214       /* Send ringing frame if requested */
09215       p->subs[idx].needringing = 0;
09216       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09217       p->subs[idx].f.subclass.integer = AST_CONTROL_RINGING;
09218       ast_setstate(ast, AST_STATE_RINGING);
09219       ast_mutex_unlock(&p->lock);
09220       return &p->subs[idx].f;
09221    }
09222 
09223    if (p->subs[idx].needbusy) {
09224       /* Send busy frame if requested */
09225       p->subs[idx].needbusy = 0;
09226       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09227       p->subs[idx].f.subclass.integer = AST_CONTROL_BUSY;
09228       ast_mutex_unlock(&p->lock);
09229       return &p->subs[idx].f;
09230    }
09231 
09232    if (p->subs[idx].needcongestion) {
09233       /* Send congestion frame if requested */
09234       p->subs[idx].needcongestion = 0;
09235       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09236       p->subs[idx].f.subclass.integer = AST_CONTROL_CONGESTION;
09237       ast_mutex_unlock(&p->lock);
09238       return &p->subs[idx].f;
09239    }
09240 
09241    if (p->subs[idx].needanswer) {
09242       /* Send answer frame if requested */
09243       p->subs[idx].needanswer = 0;
09244       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09245       p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
09246       ast_mutex_unlock(&p->lock);
09247       return &p->subs[idx].f;
09248    }
09249 #ifdef HAVE_OPENR2
09250    if (p->mfcr2 && openr2_chan_get_read_enabled(p->r2chan)) {
09251       /* openr2 took care of reading and handling any event
09252         (needanswer, needbusy etc), if we continue we will read()
09253         twice, lets just return a null frame. This should only
09254         happen when openr2 is dialing out */
09255       ast_mutex_unlock(&p->lock);
09256       return &ast_null_frame;
09257    }
09258 #endif
09259 
09260    if (p->subs[idx].needflash) {
09261       /* Send answer frame if requested */
09262       p->subs[idx].needflash = 0;
09263       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09264       p->subs[idx].f.subclass.integer = AST_CONTROL_FLASH;
09265       ast_mutex_unlock(&p->lock);
09266       return &p->subs[idx].f;
09267    }
09268 
09269    if (p->subs[idx].needhold) {
09270       /* Send answer frame if requested */
09271       p->subs[idx].needhold = 0;
09272       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09273       p->subs[idx].f.subclass.integer = AST_CONTROL_HOLD;
09274       ast_mutex_unlock(&p->lock);
09275       ast_debug(1, "Sending hold on '%s'\n", ast_channel_name(ast));
09276       return &p->subs[idx].f;
09277    }
09278 
09279    if (p->subs[idx].needunhold) {
09280       /* Send answer frame if requested */
09281       p->subs[idx].needunhold = 0;
09282       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09283       p->subs[idx].f.subclass.integer = AST_CONTROL_UNHOLD;
09284       ast_mutex_unlock(&p->lock);
09285       ast_debug(1, "Sending unhold on '%s'\n", ast_channel_name(ast));
09286       return &p->subs[idx].f;
09287    }
09288 
09289    /*
09290     * If we have a fake_event, fake an exception to handle it only
09291     * if this channel owns the private.
09292     */
09293    if (p->fake_event && p->owner == ast) {
09294       if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
09295          struct analog_pvt *analog_p = p->sig_pvt;
09296 
09297          f = analog_exception(analog_p, ast);
09298       } else {
09299          f = __dahdi_exception(ast);
09300       }
09301       ast_mutex_unlock(&p->lock);
09302       return f;
09303    }
09304 
09305    if (ast_channel_rawreadformat(ast)->id == AST_FORMAT_SLINEAR) {
09306       if (!p->subs[idx].linear) {
09307          p->subs[idx].linear = 1;
09308          res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09309          if (res)
09310             ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to linear mode.\n", p->channel, idx);
09311       }
09312    } else if ((ast_channel_rawreadformat(ast)->id == AST_FORMAT_ULAW) ||
09313       (ast_channel_rawreadformat(ast)->id == AST_FORMAT_ALAW)) {
09314       if (p->subs[idx].linear) {
09315          p->subs[idx].linear = 0;
09316          res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09317          if (res)
09318             ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to companded mode.\n", p->channel, idx);
09319       }
09320    } else {
09321       ast_log(LOG_WARNING, "Don't know how to read frames in format %s\n", ast_getformatname(ast_channel_rawreadformat(ast)));
09322       ast_mutex_unlock(&p->lock);
09323       return NULL;
09324    }
09325    readbuf = ((unsigned char *)p->subs[idx].buffer) + AST_FRIENDLY_OFFSET;
09326    CHECK_BLOCKING(ast);
09327    res = read(p->subs[idx].dfd, readbuf, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
09328    ast_clear_flag(ast_channel_flags(ast), AST_FLAG_BLOCKING);
09329    /* Check for hangup */
09330    if (res < 0) {
09331       f = NULL;
09332       if (res == -1) {
09333          if (errno == EAGAIN) {
09334             /* Return "NULL" frame if there is nobody there */
09335             ast_mutex_unlock(&p->lock);
09336             return &p->subs[idx].f;
09337          } else if (errno == ELAST) {
09338             if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
09339                struct analog_pvt *analog_p = p->sig_pvt;
09340                f = analog_exception(analog_p, ast);
09341             } else {
09342                f = __dahdi_exception(ast);
09343             }
09344          } else
09345             ast_log(LOG_WARNING, "dahdi_rec: %s\n", strerror(errno));
09346       }
09347       ast_mutex_unlock(&p->lock);
09348       return f;
09349    }
09350    if (res != (p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE)) {
09351       ast_debug(1, "Short read (%d/%d), must be an event...\n", res, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
09352       if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
09353          struct analog_pvt *analog_p = p->sig_pvt;
09354          f = analog_exception(analog_p, ast);
09355       } else {
09356          f = __dahdi_exception(ast);
09357       }
09358       ast_mutex_unlock(&p->lock);
09359       return f;
09360    }
09361    if (p->tdd) { /* if in TDD mode, see if we receive that */
09362       int c;
09363 
09364       c = tdd_feed(p->tdd,readbuf,READ_SIZE);
09365       if (c < 0) {
09366          ast_debug(1,"tdd_feed failed\n");
09367          ast_mutex_unlock(&p->lock);
09368          return NULL;
09369       }
09370       if (c) { /* if a char to return */
09371          p->subs[idx].f.subclass.integer = 0;
09372          p->subs[idx].f.frametype = AST_FRAME_TEXT;
09373          p->subs[idx].f.mallocd = 0;
09374          p->subs[idx].f.offset = AST_FRIENDLY_OFFSET;
09375          p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET;
09376          p->subs[idx].f.datalen = 1;
09377          *((char *) p->subs[idx].f.data.ptr) = c;
09378          ast_mutex_unlock(&p->lock);
09379          return &p->subs[idx].f;
09380       }
09381    }
09382    if (idx == SUB_REAL) {
09383       /* Ensure the CW timers decrement only on a single subchannel */
09384       if (p->cidcwexpire) {
09385          if (!--p->cidcwexpire) {
09386             /* Expired CID/CW */
09387             ast_verb(3, "CPE does not support Call Waiting Caller*ID.\n");
09388             restore_conference(p);
09389          }
09390       }
09391       if (p->cid_suppress_expire) {
09392          --p->cid_suppress_expire;
09393       }
09394       if (p->callwaitingrepeat) {
09395          if (!--p->callwaitingrepeat) {
09396             /* Expired, Repeat callwaiting tone */
09397             ++p->callwaitrings;
09398             dahdi_callwait(ast);
09399          }
09400       }
09401    }
09402    if (p->subs[idx].linear) {
09403       p->subs[idx].f.datalen = READ_SIZE * 2;
09404    } else
09405       p->subs[idx].f.datalen = READ_SIZE;
09406 
09407    /* Handle CallerID Transmission */
09408    if ((p->owner == ast) && p->cidspill) {
09409       send_callerid(p);
09410    }
09411 
09412    p->subs[idx].f.frametype = AST_FRAME_VOICE;
09413    ast_format_copy(&p->subs[idx].f.subclass.format, ast_channel_rawreadformat(ast));
09414    p->subs[idx].f.samples = READ_SIZE;
09415    p->subs[idx].f.mallocd = 0;
09416    p->subs[idx].f.offset = AST_FRIENDLY_OFFSET;
09417    p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET / sizeof(p->subs[idx].buffer[0]);
09418 #if 0
09419    ast_debug(1, "Read %d of voice on %s\n", p->subs[idx].f.datalen, ast->name);
09420 #endif
09421    if (p->dialing ||  p->radio || /* Transmitting something */
09422       (idx && (ast_channel_state(ast) != AST_STATE_UP)) || /* Three-way or callwait that isn't up */
09423       ((idx == SUB_CALLWAIT) && !p->subs[SUB_CALLWAIT].inthreeway) /* Inactive and non-confed call-wait */
09424       ) {
09425       /* Whoops, we're still dialing, or in a state where we shouldn't transmit....
09426          don't send anything */
09427       p->subs[idx].f.frametype = AST_FRAME_NULL;
09428       p->subs[idx].f.subclass.integer = 0;
09429       p->subs[idx].f.samples = 0;
09430       p->subs[idx].f.mallocd = 0;
09431       p->subs[idx].f.offset = 0;
09432       p->subs[idx].f.data.ptr = NULL;
09433       p->subs[idx].f.datalen= 0;
09434    }
09435    if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect || p->callprogress || p->waitingfordt.tv_sec || p->dialtone_detect) && !idx) {
09436       /* Perform busy detection etc on the dahdi line */
09437       int mute;
09438 
09439       f = ast_dsp_process(ast, p->dsp, &p->subs[idx].f);
09440 
09441       /* Check if DSP code thinks we should be muting this frame and mute the conference if so */
09442       mute = ast_dsp_was_muted(p->dsp);
09443       if (p->muting != mute) {
09444          p->muting = mute;
09445          dahdi_confmute(p, mute);
09446       }
09447 
09448       if (f) {
09449          if ((p->dsp_features & DSP_FEATURE_WAITDIALTONE) && (p->dialtone_detect > 0)
09450             && !p->outgoing && ast_channel_state(ast) == AST_STATE_UP) {
09451             if (++p->dialtone_scanning_time_elapsed >= p->dialtone_detect) {
09452                p->dsp_features &= ~DSP_FEATURE_WAITDIALTONE;
09453                ast_dsp_set_features(p->dsp, p->dsp_features);
09454             }
09455          }
09456          if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass.integer == AST_CONTROL_BUSY)) {
09457             if ((ast_channel_state(ast) == AST_STATE_UP) && !p->outgoing) {
09458                /*
09459                 * Treat this as a "hangup" instead of a "busy" on the
09460                 * assumption that a busy means the incoming call went away.
09461                 */
09462                ast_frfree(f);
09463                f = NULL;
09464             }
09465          } else if (p->dialtone_detect && !p->outgoing && f->frametype == AST_FRAME_VOICE) {
09466             if ((ast_dsp_get_tstate(p->dsp) == DSP_TONE_STATE_DIALTONE) && (ast_dsp_get_tcount(p->dsp) > 9)) {
09467                /* Dialtone detected on inbound call; hangup the channel */
09468                ast_frfree(f);
09469                f = NULL;
09470             }
09471          } else if (f->frametype == AST_FRAME_DTMF_BEGIN
09472             || f->frametype == AST_FRAME_DTMF_END) {
09473 #ifdef HAVE_PRI
09474             if (dahdi_sig_pri_lib_handles(p->sig)
09475                && ((struct sig_pri_chan *) p->sig_pvt)->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING
09476                && p->pri
09477                && ((!p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING))
09478                   || (p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)))) {
09479                /* Don't accept in-band DTMF when in overlap dial mode */
09480                ast_debug(1, "Absorbing inband %s DTMF digit: 0x%02X '%c' on %s\n",
09481                   f->frametype == AST_FRAME_DTMF_BEGIN ? "begin" : "end",
09482                   f->subclass.integer, f->subclass.integer, ast_channel_name(ast));
09483 
09484                f->frametype = AST_FRAME_NULL;
09485                f->subclass.integer = 0;
09486             }
09487 #endif
09488             /* DSP clears us of being pulse */
09489             p->pulsedial = 0;
09490          } else if (p->waitingfordt.tv_sec) {
09491             if (ast_tvdiff_ms(ast_tvnow(), p->waitingfordt) >= p->waitfordialtone ) {
09492                p->waitingfordt.tv_sec = 0;
09493                ast_log(LOG_WARNING, "Never saw dialtone on channel %d\n", p->channel);
09494                ast_frfree(f);
09495                f = NULL;
09496             } else if (f->frametype == AST_FRAME_VOICE) {
09497                f->frametype = AST_FRAME_NULL;
09498                f->subclass.integer = 0;
09499                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) {
09500                   p->waitingfordt.tv_sec = 0;
09501                   p->dsp_features &= ~DSP_FEATURE_WAITDIALTONE;
09502                   ast_dsp_set_features(p->dsp, p->dsp_features);
09503                   ast_debug(1, "Got 10 samples of dialtone!\n");
09504                   if (!ast_strlen_zero(p->dop.dialstr)) { /* Dial deferred digits */
09505                      res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
09506                      if (res < 0) {
09507                         ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d\n", p->channel);
09508                         p->dop.dialstr[0] = '\0';
09509                         ast_mutex_unlock(&p->lock);
09510                         ast_frfree(f);
09511                         return NULL;
09512                      } else {
09513                         ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
09514                         p->dialing = 1;
09515                         p->dop.dialstr[0] = '\0';
09516                         p->dop.op = DAHDI_DIAL_OP_REPLACE;
09517                         ast_setstate(ast, AST_STATE_DIALING);
09518                      }
09519                   }
09520                }
09521             }
09522          }
09523       }
09524    } else
09525       f = &p->subs[idx].f;
09526 
09527    if (f) {
09528       switch (f->frametype) {
09529       case AST_FRAME_DTMF_BEGIN:
09530       case AST_FRAME_DTMF_END:
09531          if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
09532             analog_handle_dtmf(p->sig_pvt, ast, idx, &f);
09533          } else {
09534             dahdi_handle_dtmf(ast, idx, &f);
09535          }
09536          break;
09537       case AST_FRAME_VOICE:
09538          if (p->cidspill || p->cid_suppress_expire) {
09539             /* We are/were sending a caller id spill.  Suppress any echo. */
09540             p->subs[idx].f.frametype = AST_FRAME_NULL;
09541             p->subs[idx].f.subclass.integer = 0;
09542             p->subs[idx].f.samples = 0;
09543             p->subs[idx].f.mallocd = 0;
09544             p->subs[idx].f.offset = 0;
09545             p->subs[idx].f.data.ptr = NULL;
09546             p->subs[idx].f.datalen= 0;
09547          }
09548          break;
09549       default:
09550          break;
09551       }
09552    }
09553 
09554    ast_mutex_unlock(&p->lock);
09555    return f;
09556 }
09557 
09558 static int my_dahdi_write(struct dahdi_pvt *p, unsigned char *buf, int len, int idx, int linear)
09559 {
09560    int sent=0;
09561    int size;
09562    int res;
09563    int fd;
09564    fd = p->subs[idx].dfd;
09565    while (len) {
09566       size = len;
09567       if (size > (linear ? READ_SIZE * 2 : READ_SIZE))
09568          size = (linear ? READ_SIZE * 2 : READ_SIZE);
09569       res = write(fd, buf, size);
09570       if (res != size) {
09571          ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
09572          return sent;
09573       }
09574       len -= size;
09575       buf += size;
09576    }
09577    return sent;
09578 }
09579 
09580 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame)
09581 {
09582    struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
09583    int res;
09584    int idx;
09585    idx = dahdi_get_index(ast, p, 0);
09586    if (idx < 0) {
09587       ast_log(LOG_WARNING, "%s doesn't really exist?\n", ast_channel_name(ast));
09588       return -1;
09589    }
09590 
09591    /* Write a frame of (presumably voice) data */
09592    if (frame->frametype != AST_FRAME_VOICE) {
09593       if (frame->frametype != AST_FRAME_IMAGE)
09594          ast_log(LOG_WARNING, "Don't know what to do with frame type '%d'\n", frame->frametype);
09595       return 0;
09596    }
09597    if ((frame->subclass.format.id != AST_FORMAT_SLINEAR) &&
09598       (frame->subclass.format.id != AST_FORMAT_ULAW) &&
09599       (frame->subclass.format.id != AST_FORMAT_ALAW)) {
09600       ast_log(LOG_WARNING, "Cannot handle frames in %s format\n", ast_getformatname(&frame->subclass.format));
09601       return -1;
09602    }
09603    if (p->dialing) {
09604       ast_debug(1, "Dropping frame since I'm still dialing on %s...\n",ast_channel_name(ast));
09605       return 0;
09606    }
09607    if (!p->owner) {
09608       ast_debug(1, "Dropping frame since there is no active owner on %s...\n",ast_channel_name(ast));
09609       return 0;
09610    }
09611    if (p->cidspill) {
09612       ast_debug(1, "Dropping frame since I've still got a callerid spill on %s...\n",
09613          ast_channel_name(ast));
09614       return 0;
09615    }
09616    /* Return if it's not valid data */
09617    if (!frame->data.ptr || !frame->datalen)
09618       return 0;
09619 
09620    if (frame->subclass.format.id == AST_FORMAT_SLINEAR) {
09621       if (!p->subs[idx].linear) {
09622          p->subs[idx].linear = 1;
09623          res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09624          if (res)
09625             ast_log(LOG_WARNING, "Unable to set linear mode on channel %d\n", p->channel);
09626       }
09627       res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 1);
09628    } else {
09629       /* x-law already */
09630       if (p->subs[idx].linear) {
09631          p->subs[idx].linear = 0;
09632          res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09633          if (res)
09634             ast_log(LOG_WARNING, "Unable to set companded mode on channel %d\n", p->channel);
09635       }
09636       res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 0);
09637    }
09638    if (res < 0) {
09639       ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
09640       return -1;
09641    }
09642    return 0;
09643 }
09644 
09645 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen)
09646 {
09647    struct dahdi_pvt *p = ast_channel_tech_pvt(chan);
09648    int res=-1;
09649    int idx;
09650    int func = DAHDI_FLASH;
09651 
09652    ast_mutex_lock(&p->lock);
09653    ast_debug(1, "Requested indication %d on channel %s\n", condition, ast_channel_name(chan));
09654    switch (p->sig) {
09655 #if defined(HAVE_PRI)
09656    case SIG_PRI_LIB_HANDLE_CASES:
09657       res = sig_pri_indicate(p->sig_pvt, chan, condition, data, datalen);
09658       ast_mutex_unlock(&p->lock);
09659       return res;
09660 #endif   /* defined(HAVE_PRI) */
09661 #if defined(HAVE_SS7)
09662    case SIG_SS7:
09663       res = sig_ss7_indicate(p->sig_pvt, chan, condition, data, datalen);
09664       ast_mutex_unlock(&p->lock);
09665       return res;
09666 #endif   /* defined(HAVE_SS7) */
09667    default:
09668       break;
09669    }
09670 #ifdef HAVE_OPENR2
09671    if (p->mfcr2 && !p->mfcr2_call_accepted) {
09672       ast_mutex_unlock(&p->lock);
09673       /* if this is an R2 call and the call is not yet accepted, we don't want the
09674          tone indications to mess up with the MF tones */
09675       return 0;
09676    }
09677 #endif
09678    idx = dahdi_get_index(chan, p, 0);
09679    if (idx == SUB_REAL) {
09680       switch (condition) {
09681       case AST_CONTROL_BUSY:
09682          res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_BUSY);
09683          break;
09684       case AST_CONTROL_RINGING:
09685          res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_RINGTONE);
09686 
09687          if (ast_channel_state(chan) != AST_STATE_UP) {
09688             if ((ast_channel_state(chan) != AST_STATE_RING) ||
09689                ((p->sig != SIG_FXSKS) &&
09690              (p->sig != SIG_FXSLS) &&
09691              (p->sig != SIG_FXSGS)))
09692             ast_setstate(chan, AST_STATE_RINGING);
09693          }
09694          break;
09695       case AST_CONTROL_INCOMPLETE:
09696          ast_debug(1, "Received AST_CONTROL_INCOMPLETE on %s\n", ast_channel_name(chan));
09697          /* act as a progress or proceeding, allowing the caller to enter additional numbers */
09698          res = 0;
09699          break;
09700       case AST_CONTROL_PROCEEDING:
09701          ast_debug(1, "Received AST_CONTROL_PROCEEDING on %s\n", ast_channel_name(chan));
09702          /* don't continue in ast_indicate */
09703          res = 0;
09704          break;
09705       case AST_CONTROL_PROGRESS:
09706          ast_debug(1, "Received AST_CONTROL_PROGRESS on %s\n", ast_channel_name(chan));
09707          /* don't continue in ast_indicate */
09708          res = 0;
09709          break;
09710       case AST_CONTROL_CONGESTION:
09711          /* There are many cause codes that generate an AST_CONTROL_CONGESTION. */
09712          switch (ast_channel_hangupcause(chan)) {
09713          case AST_CAUSE_USER_BUSY:
09714          case AST_CAUSE_NORMAL_CLEARING:
09715          case 0:/* Cause has not been set. */
09716             /* Supply a more appropriate cause. */
09717             ast_channel_hangupcause_set(chan, AST_CAUSE_CONGESTION);
09718             break;
09719          default:
09720             break;
09721          }
09722          break;
09723       case AST_CONTROL_HOLD:
09724          ast_moh_start(chan, data, p->mohinterpret);
09725          break;
09726       case AST_CONTROL_UNHOLD:
09727          ast_moh_stop(chan);
09728          break;
09729       case AST_CONTROL_RADIO_KEY:
09730          if (p->radio)
09731             res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
09732          res = 0;
09733          break;
09734       case AST_CONTROL_RADIO_UNKEY:
09735          if (p->radio)
09736             res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_RINGOFF);
09737          res = 0;
09738          break;
09739       case AST_CONTROL_FLASH:
09740          /* flash hookswitch */
09741          if (ISTRUNK(p) && (p->sig != SIG_PRI)) {
09742             /* Clear out the dial buffer */
09743             p->dop.dialstr[0] = '\0';
09744             if ((ioctl(p->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
09745                ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
09746                   ast_channel_name(chan), strerror(errno));
09747             } else
09748                res = 0;
09749          } else
09750             res = 0;
09751          break;
09752       case AST_CONTROL_SRCUPDATE:
09753          res = 0;
09754          break;
09755       case -1:
09756          res = tone_zone_play_tone(p->subs[idx].dfd, -1);
09757          break;
09758       }
09759    } else {
09760       res = 0;
09761    }
09762    ast_mutex_unlock(&p->lock);
09763    return res;
09764 }
09765 
09766 #if defined(HAVE_PRI)
09767 static struct ast_str *create_channel_name(struct dahdi_pvt *i, int is_outgoing, char *address)
09768 #else
09769 static struct ast_str *create_channel_name(struct dahdi_pvt *i)
09770 #endif   /* defined(HAVE_PRI) */
09771 {
09772    struct ast_str *chan_name;
09773    int x, y;
09774 
09775    /* Create the new channel name tail. */
09776    if (!(chan_name = ast_str_create(32))) {
09777       return NULL;
09778    }
09779    if (i->channel == CHAN_PSEUDO) {
09780       ast_str_set(&chan_name, 0, "pseudo-%ld", ast_random());
09781 #if defined(HAVE_PRI)
09782    } else if (i->pri) {
09783       ast_mutex_lock(&i->pri->lock);
09784       y = ++i->pri->new_chan_seq;
09785       if (is_outgoing) {
09786          ast_str_set(&chan_name, 0, "i%d/%s-%x", i->pri->span, address, y);
09787          address[0] = '\0';
09788       } else if (ast_strlen_zero(i->cid_subaddr)) {
09789          /* Put in caller-id number only since there is no subaddress. */
09790          ast_str_set(&chan_name, 0, "i%d/%s-%x", i->pri->span, i->cid_num, y);
09791       } else {
09792          /* Put in caller-id number and subaddress. */
09793          ast_str_set(&chan_name, 0, "i%d/%s:%s-%x", i->pri->span, i->cid_num,
09794             i->cid_subaddr, y);
09795       }
09796       ast_mutex_unlock(&i->pri->lock);
09797 #endif   /* defined(HAVE_PRI) */
09798    } else {
09799       y = 1;
09800       do {
09801          ast_str_set(&chan_name, 0, "%d-%d", i->channel, y);
09802          for (x = 0; x < 3; ++x) {
09803             if (i->subs[x].owner && !strcasecmp(ast_str_buffer(chan_name),
09804                ast_channel_name(i->subs[x].owner) + 6)) {
09805                break;
09806             }
09807          }
09808          ++y;
09809       } while (x < 3);
09810    }
09811    return chan_name;
09812 }
09813 
09814 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)
09815 {
09816    struct ast_channel *new_channel = dahdi_new(i, state, startpbx, idx, law, linkedid, callid);
09817 
09818    ast_callid_threadstorage_auto_clean(callid, callid_created);
09819 
09820    return new_channel;
09821 }
09822 
09823 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)
09824 {
09825    struct ast_channel *tmp;
09826    struct ast_format deflaw;
09827    int x;
09828    int features;
09829    struct ast_str *chan_name;
09830    struct ast_variable *v;
09831    char *dashptr;
09832    char device_name[AST_CHANNEL_NAME];
09833 
09834    if (i->subs[idx].owner) {
09835       ast_log(LOG_WARNING, "Channel %d already has a %s call\n", i->channel,subnames[idx]);
09836       return NULL;
09837    }
09838 
09839    ast_format_clear(&deflaw);
09840 #if defined(HAVE_PRI)
09841    /*
09842     * The dnid has been stuffed with the called-number[:subaddress]
09843     * by dahdi_request() for outgoing calls.
09844     */
09845    chan_name = create_channel_name(i, i->outgoing, i->dnid);
09846 #else
09847    chan_name = create_channel_name(i);
09848 #endif   /* defined(HAVE_PRI) */
09849    if (!chan_name) {
09850       return NULL;
09851    }
09852 
09853    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));
09854    ast_free(chan_name);
09855    if (!tmp) {
09856       return NULL;
09857    }
09858 
09859    if (callid) {
09860       ast_channel_callid_set(tmp, callid);
09861    }
09862 
09863    ast_channel_tech_set(tmp, &dahdi_tech);
09864 #if defined(HAVE_PRI)
09865    if (i->pri) {
09866       ast_cc_copy_config_params(i->cc_params, i->pri->cc_params);
09867    }
09868 #endif   /* defined(HAVE_PRI) */
09869    ast_channel_cc_params_init(tmp, i->cc_params);
09870    if (law) {
09871       i->law = law;
09872       if (law == DAHDI_LAW_ALAW) {
09873          ast_format_set(&deflaw, AST_FORMAT_ALAW, 0);
09874       } else {
09875          ast_format_set(&deflaw, AST_FORMAT_ULAW, 0);
09876       }
09877    } else {
09878       switch (i->sig) {
09879       case SIG_PRI_LIB_HANDLE_CASES:
09880          /* Make sure companding law is known. */
09881          i->law = (i->law_default == DAHDI_LAW_ALAW)
09882             ? DAHDI_LAW_ALAW : DAHDI_LAW_MULAW;
09883          break;
09884       default:
09885          i->law = i->law_default;
09886          break;
09887       }
09888       if (i->law_default == DAHDI_LAW_ALAW) {
09889          ast_format_set(&deflaw, AST_FORMAT_ALAW, 0);
09890       } else {
09891          ast_format_set(&deflaw, AST_FORMAT_ULAW, 0);
09892       }
09893    }
09894    ast_channel_set_fd(tmp, 0, i->subs[idx].dfd);
09895    ast_format_cap_add(ast_channel_nativeformats(tmp), &deflaw);
09896    /* Start out assuming ulaw since it's smaller :) */
09897    ast_format_copy(ast_channel_rawreadformat(tmp), &deflaw);
09898    ast_format_copy(ast_channel_readformat(tmp), &deflaw);
09899    ast_format_copy(ast_channel_rawwriteformat(tmp), &deflaw);
09900    ast_format_copy(ast_channel_writeformat(tmp), &deflaw);
09901    i->subs[idx].linear = 0;
09902    dahdi_setlinear(i->subs[idx].dfd, i->subs[idx].linear);
09903    features = 0;
09904    if (idx == SUB_REAL) {
09905       if (i->busydetect && CANBUSYDETECT(i))
09906          features |= DSP_FEATURE_BUSY_DETECT;
09907       if ((i->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(i))
09908          features |= DSP_FEATURE_CALL_PROGRESS;
09909       if ((i->waitfordialtone || i->dialtone_detect) && CANPROGRESSDETECT(i))
09910          features |= DSP_FEATURE_WAITDIALTONE;
09911       if ((!i->outgoing && (i->callprogress & CALLPROGRESS_FAX_INCOMING)) ||
09912          (i->outgoing && (i->callprogress & CALLPROGRESS_FAX_OUTGOING))) {
09913          features |= DSP_FEATURE_FAX_DETECT;
09914       }
09915       x = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
09916       if (ioctl(i->subs[idx].dfd, DAHDI_TONEDETECT, &x)) {
09917          i->hardwaredtmf = 0;
09918          features |= DSP_FEATURE_DIGIT_DETECT;
09919       } else if (NEED_MFDETECT(i)) {
09920          i->hardwaredtmf = 1;
09921          features |= DSP_FEATURE_DIGIT_DETECT;
09922       }
09923    }
09924    if (features) {
09925       if (i->dsp) {
09926          ast_debug(1, "Already have a dsp on %s?\n", ast_channel_name(tmp));
09927       } else {
09928          if (i->channel != CHAN_PSEUDO)
09929             i->dsp = ast_dsp_new();
09930          else
09931             i->dsp = NULL;
09932          if (i->dsp) {
09933             i->dsp_features = features;
09934 #if defined(HAVE_PRI) || defined(HAVE_SS7)
09935             /* We cannot do progress detection until receive PROGRESS message */
09936             if (i->outgoing && (dahdi_sig_pri_lib_handles(i->sig) || (i->sig == SIG_SS7))) {
09937                /* Remember requested DSP features, don't treat
09938                   talking as ANSWER */
09939                i->dsp_features = features & ~DSP_PROGRESS_TALK;
09940                features = 0;
09941             }
09942 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
09943             ast_dsp_set_features(i->dsp, features);
09944             ast_dsp_set_digitmode(i->dsp, DSP_DIGITMODE_DTMF | i->dtmfrelax);
09945             if (!ast_strlen_zero(progzone))
09946                ast_dsp_set_call_progress_zone(i->dsp, progzone);
09947             if (i->busydetect && CANBUSYDETECT(i)) {
09948                ast_dsp_set_busy_count(i->dsp, i->busycount);
09949                ast_dsp_set_busy_pattern(i->dsp, &i->busy_cadence);
09950             }
09951          }
09952       }
09953    }
09954 
09955    i->dialtone_scanning_time_elapsed = 0;
09956 
09957    if (state == AST_STATE_RING)
09958       ast_channel_rings_set(tmp, 1);
09959    ast_channel_tech_pvt_set(tmp, i);
09960    if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) {
09961       /* Only FXO signalled stuff can be picked up */
09962       ast_channel_callgroup_set(tmp, i->callgroup);
09963       ast_channel_pickupgroup_set(tmp, i->pickupgroup);
09964       ast_channel_named_callgroups_set(tmp, i->named_callgroups);
09965       ast_channel_named_pickupgroups_set(tmp, i->named_pickupgroups);
09966    }
09967    if (!ast_strlen_zero(i->parkinglot))
09968       ast_channel_parkinglot_set(tmp, i->parkinglot);
09969    if (!ast_strlen_zero(i->language))
09970       ast_channel_language_set(tmp, i->language);
09971    if (!i->owner)
09972       i->owner = tmp;
09973    if (!ast_strlen_zero(i->accountcode))
09974       ast_channel_accountcode_set(tmp, i->accountcode);
09975    if (i->amaflags)
09976       ast_channel_amaflags_set(tmp, i->amaflags);
09977    i->subs[idx].owner = tmp;
09978    ast_channel_context_set(tmp, i->context);
09979    if (!analog_lib_handles(i->sig, i->radio, i->oprmode)) {
09980       ast_channel_call_forward_set(tmp, i->call_forward);
09981    }
09982    /* If we've been told "no ADSI" then enforce it */
09983    if (!i->adsi)
09984       ast_channel_adsicpe_set(tmp, AST_ADSI_UNAVAILABLE);
09985    if (!ast_strlen_zero(i->exten))
09986       ast_channel_exten_set(tmp, i->exten);
09987    if (!ast_strlen_zero(i->rdnis)) {
09988       ast_channel_redirecting(tmp)->from.number.valid = 1;
09989       ast_channel_redirecting(tmp)->from.number.str = ast_strdup(i->rdnis);
09990    }
09991    if (!ast_strlen_zero(i->dnid)) {
09992       ast_channel_dialed(tmp)->number.str = ast_strdup(i->dnid);
09993    }
09994 
09995    /* Don't use ast_set_callerid() here because it will
09996     * generate a needless NewCallerID event */
09997 #if defined(HAVE_PRI) || defined(HAVE_SS7)
09998    if (!ast_strlen_zero(i->cid_ani)) {
09999       ast_channel_caller(tmp)->ani.number.valid = 1;
10000       ast_channel_caller(tmp)->ani.number.str = ast_strdup(i->cid_ani);
10001    } else if (!ast_strlen_zero(i->cid_num)) {
10002       ast_channel_caller(tmp)->ani.number.valid = 1;
10003       ast_channel_caller(tmp)->ani.number.str = ast_strdup(i->cid_num);
10004    }
10005 #else
10006    if (!ast_strlen_zero(i->cid_num)) {
10007       ast_channel_caller(tmp)->ani.number.valid = 1;
10008       ast_channel_caller(tmp)->ani.number.str = ast_strdup(i->cid_num);
10009    }
10010 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
10011    ast_channel_caller(tmp)->id.name.presentation = i->callingpres;
10012    ast_channel_caller(tmp)->id.number.presentation = i->callingpres;
10013    ast_channel_caller(tmp)->id.number.plan = i->cid_ton;
10014    ast_channel_caller(tmp)->ani2 = i->cid_ani2;
10015    ast_channel_caller(tmp)->id.tag = ast_strdup(i->cid_tag);
10016    /* clear the fake event in case we posted one before we had ast_channel */
10017    i->fake_event = 0;
10018    /* Assure there is no confmute on this channel */
10019    dahdi_confmute(i, 0);
10020    i->muting = 0;
10021    /* Configure the new channel jb */
10022    ast_jb_configure(tmp, &global_jbconf);
10023 
10024    /* Set initial device state */
10025    ast_copy_string(device_name, ast_channel_name(tmp), sizeof(device_name));
10026    dashptr = strrchr(device_name, '-');
10027    if (dashptr) {
10028       *dashptr = '\0';
10029    }
10030    ast_set_flag(ast_channel_flags(tmp), AST_FLAG_DISABLE_DEVSTATE_CACHE);
10031    ast_devstate_changed_literal(AST_DEVICE_UNKNOWN, AST_DEVSTATE_NOT_CACHABLE, device_name);
10032 
10033    for (v = i->vars ; v ; v = v->next)
10034       pbx_builtin_setvar_helper(tmp, v->name, v->value);
10035 
10036    ast_module_ref(ast_module_info->self);
10037 
10038    dahdi_ami_channel_event(i, tmp);
10039    if (startpbx) {
10040 #ifdef HAVE_OPENR2
10041       if (i->mfcr2call) {
10042          pbx_builtin_setvar_helper(tmp, "MFCR2_CATEGORY", openr2_proto_get_category_string(i->mfcr2_recvd_category));
10043       }
10044 #endif
10045       if (ast_pbx_start(tmp)) {
10046          ast_log(LOG_WARNING, "Unable to start PBX on %s\n", ast_channel_name(tmp));
10047          ast_hangup(tmp);
10048          return NULL;
10049       }
10050    }
10051    return tmp;
10052 }
10053 
10054 
10055 static int my_getsigstr(struct ast_channel *chan, char *str, const char *term, int ms)
10056 {
10057    char c;
10058 
10059    *str = 0; /* start with empty output buffer */
10060    for (;;)
10061    {
10062       /* Wait for the first digit (up to specified ms). */
10063       c = ast_waitfordigit(chan, ms);
10064       /* if timeout, hangup or error, return as such */
10065       if (c < 1)
10066          return c;
10067       *str++ = c;
10068       *str = 0;
10069       if (strchr(term, c))
10070          return 1;
10071    }
10072 }
10073 
10074 static int dahdi_wink(struct dahdi_pvt *p, int idx)
10075 {
10076    int j;
10077    dahdi_set_hook(p->subs[idx].dfd, DAHDI_WINK);
10078    for (;;)
10079    {
10080       /* set bits of interest */
10081       j = DAHDI_IOMUX_SIGEVENT;
10082       /* wait for some happening */
10083       if (ioctl(p->subs[idx].dfd,DAHDI_IOMUX,&j) == -1) return(-1);
10084       /* exit loop if we have it */
10085       if (j & DAHDI_IOMUX_SIGEVENT) break;
10086    }
10087    /* get the event info */
10088    if (ioctl(p->subs[idx].dfd,DAHDI_GETEVENT,&j) == -1) return(-1);
10089    return 0;
10090 }
10091 
10092 /*! \brief enable or disable the chan_dahdi Do-Not-Disturb mode for a DAHDI channel
10093  * \param dahdichan "Physical" DAHDI channel (e.g: DAHDI/5)
10094  * \param flag on 1 to enable, 0 to disable, -1 return dnd value
10095  *
10096  * chan_dahdi has a DND (Do Not Disturb) mode for each dahdichan (physical
10097  * DAHDI channel). Use this to enable or disable it.
10098  *
10099  * \bug the use of the word "channel" for those dahdichans is really confusing.
10100  */
10101 static int dahdi_dnd(struct dahdi_pvt *dahdichan, int flag)
10102 {
10103    if (analog_lib_handles(dahdichan->sig, dahdichan->radio, dahdichan->oprmode)) {
10104       return analog_dnd(dahdichan->sig_pvt, flag);
10105    }
10106 
10107    if (flag == -1) {
10108       return dahdichan->dnd;
10109    }
10110 
10111    /* Do not disturb */
10112    dahdichan->dnd = flag;
10113    ast_verb(3, "%s DND on channel %d\n",
10114          flag? "Enabled" : "Disabled",
10115          dahdichan->channel);
10116    /*** DOCUMENTATION
10117       <managerEventInstance>
10118          <synopsis>Raised when the Do Not Disturb state is changed on a DAHDI channel.</synopsis>
10119          <syntax>
10120             <parameter name="Status">
10121                <enumlist>
10122                   <enum name="enabled"/>
10123                   <enum name="disabled"/>
10124                </enumlist>
10125             </parameter>
10126          </syntax>
10127       </managerEventInstance>
10128    ***/
10129    manager_event(EVENT_FLAG_SYSTEM, "DNDState",
10130          "Channel: DAHDI/%d\r\n"
10131          "Status: %s\r\n", dahdichan->channel,
10132          flag? "enabled" : "disabled");
10133 
10134    return 0;
10135 }
10136 
10137 static int canmatch_featurecode(const char *exten)
10138 {
10139    int extlen = strlen(exten);
10140    const char *pickup_ext;
10141    if (!extlen) {
10142       return 1;
10143    }
10144    pickup_ext = ast_pickup_ext();
10145    if (extlen < strlen(pickup_ext) && !strncmp(pickup_ext, exten, extlen)) {
10146       return 1;
10147    }
10148    /* hardcoded features are *60, *67, *69, *70, *72, *73, *78, *79, *82, *0 */
10149    if (exten[0] == '*' && extlen < 3) {
10150       if (extlen == 1) {
10151          return 1;
10152       }
10153       /* "*0" should be processed before it gets here */
10154       switch (exten[1]) {
10155       case '6':
10156       case '7':
10157       case '8':
10158          return 1;
10159       }
10160    }
10161    return 0;
10162 }
10163 
10164 static void *analog_ss_thread(void *data)
10165 {
10166    struct ast_channel *chan = data;
10167    struct dahdi_pvt *p = ast_channel_tech_pvt(chan);
10168    char exten[AST_MAX_EXTENSION] = "";
10169    char exten2[AST_MAX_EXTENSION] = "";
10170    unsigned char buf[256];
10171    char dtmfcid[300];
10172    char dtmfbuf[300];
10173    struct callerid_state *cs = NULL;
10174    char *name = NULL, *number = NULL;
10175    int distMatches;
10176    int curRingData[3];
10177    int receivedRingT;
10178    int counter1;
10179    int counter;
10180    int samples = 0;
10181    struct ast_smdi_md_message *smdi_msg = NULL;
10182    int flags = 0;
10183    int i;
10184    int timeout;
10185    int getforward = 0;
10186    char *s1, *s2;
10187    int len = 0;
10188    int res;
10189    int idx;
10190    struct ast_format tmpfmt;
10191 
10192    ast_mutex_lock(&ss_thread_lock);
10193    ss_thread_count++;
10194    ast_mutex_unlock(&ss_thread_lock);
10195    /* in the bizarre case where the channel has become a zombie before we
10196       even get started here, abort safely
10197    */
10198    if (!p) {
10199       ast_log(LOG_WARNING, "Channel became a zombie before simple switch could be started (%s)\n", ast_channel_name(chan));
10200       ast_hangup(chan);
10201       goto quit;
10202    }
10203    ast_verb(3, "Starting simple switch on '%s'\n", ast_channel_name(chan));
10204    idx = dahdi_get_index(chan, p, 1);
10205    if (idx < 0) {
10206       ast_log(LOG_WARNING, "Huh?\n");
10207       ast_hangup(chan);
10208       goto quit;
10209    }
10210    if (p->dsp)
10211       ast_dsp_digitreset(p->dsp);
10212    switch (p->sig) {
10213    case SIG_FEATD:
10214    case SIG_FEATDMF:
10215    case SIG_FEATDMF_TA:
10216    case SIG_E911:
10217    case SIG_FGC_CAMAMF:
10218    case SIG_FEATB:
10219    case SIG_EMWINK:
10220    case SIG_SF_FEATD:
10221    case SIG_SF_FEATDMF:
10222    case SIG_SF_FEATB:
10223    case SIG_SFWINK:
10224       if (dahdi_wink(p, idx))
10225          goto quit;
10226       /* Fall through */
10227    case SIG_EM:
10228    case SIG_EM_E1:
10229    case SIG_SF:
10230    case SIG_FGC_CAMA:
10231       res = tone_zone_play_tone(p->subs[idx].dfd, -1);
10232       if (p->dsp)
10233          ast_dsp_digitreset(p->dsp);
10234       /* set digit mode appropriately */
10235       if (p->dsp) {
10236          if (NEED_MFDETECT(p))
10237             ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
10238          else
10239             ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
10240       }
10241       memset(dtmfbuf, 0, sizeof(dtmfbuf));
10242       /* Wait for the first digit only if immediate=no */
10243       if (!p->immediate)
10244          /* Wait for the first digit (up to 5 seconds). */
10245          res = ast_waitfordigit(chan, 5000);
10246       else
10247          res = 0;
10248       if (res > 0) {
10249          /* save first char */
10250          dtmfbuf[0] = res;
10251          switch (p->sig) {
10252          case SIG_FEATD:
10253          case SIG_SF_FEATD:
10254             res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
10255             if (res > 0)
10256                res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
10257             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
10258             break;
10259          case SIG_FEATDMF_TA:
10260             res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
10261             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
10262             if (dahdi_wink(p, idx)) goto quit;
10263             dtmfbuf[0] = 0;
10264             /* Wait for the first digit (up to 5 seconds). */
10265             res = ast_waitfordigit(chan, 5000);
10266             if (res <= 0) break;
10267             dtmfbuf[0] = res;
10268             /* fall through intentionally */
10269          case SIG_FEATDMF:
10270          case SIG_E911:
10271          case SIG_FGC_CAMAMF:
10272          case SIG_SF_FEATDMF:
10273             res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
10274             /* if international caca, do it again to get real ANO */
10275             if ((p->sig == SIG_FEATDMF) && (dtmfbuf[1] != '0') && (strlen(dtmfbuf) != 14))
10276             {
10277                if (dahdi_wink(p, idx)) goto quit;
10278                dtmfbuf[0] = 0;
10279                /* Wait for the first digit (up to 5 seconds). */
10280                res = ast_waitfordigit(chan, 5000);
10281                if (res <= 0) break;
10282                dtmfbuf[0] = res;
10283                res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
10284             }
10285             if (res > 0) {
10286                /* if E911, take off hook */
10287                if (p->sig == SIG_E911)
10288                   dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
10289                res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "#", 3000);
10290             }
10291             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
10292             break;
10293          case SIG_FEATB:
10294          case SIG_SF_FEATB:
10295             res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
10296             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
10297             break;
10298          case SIG_EMWINK:
10299             /* if we received a '*', we are actually receiving Feature Group D
10300                dial syntax, so use that mode; otherwise, fall through to normal
10301                mode
10302             */
10303             if (res == '*') {
10304                res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
10305                if (res > 0)
10306                   res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
10307                if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
10308                break;
10309             }
10310          default:
10311             /* If we got the first digit, get the rest */
10312             len = 1;
10313             dtmfbuf[len] = '\0';
10314             while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, ast_channel_context(chan), dtmfbuf, 1, p->cid_num)) {
10315                if (ast_exists_extension(chan, ast_channel_context(chan), dtmfbuf, 1, p->cid_num)) {
10316                   timeout = matchdigittimeout;
10317                } else {
10318                   timeout = gendigittimeout;
10319                }
10320                res = ast_waitfordigit(chan, timeout);
10321                if (res < 0) {
10322                   ast_debug(1, "waitfordigit returned < 0...\n");
10323                   ast_hangup(chan);
10324                   goto quit;
10325                } else if (res) {
10326                   dtmfbuf[len++] = res;
10327                   dtmfbuf[len] = '\0';
10328                } else {
10329                   break;
10330                }
10331             }
10332             break;
10333          }
10334       }
10335       if (res == -1) {
10336          ast_log(LOG_WARNING, "getdtmf on channel %d: %s\n", p->channel, strerror(errno));
10337          ast_hangup(chan);
10338          goto quit;
10339       } else if (res < 0) {
10340          ast_debug(1, "Got hung up before digits finished\n");
10341          ast_hangup(chan);
10342          goto quit;
10343       }
10344 
10345       if (p->sig == SIG_FGC_CAMA) {
10346          char anibuf[100];
10347 
10348          if (ast_safe_sleep(chan,1000) == -1) {
10349             ast_hangup(chan);
10350             goto quit;
10351          }
10352          dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
10353          ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
10354          res = my_getsigstr(chan, anibuf, "#", 10000);
10355          if ((res > 0) && (strlen(anibuf) > 2)) {
10356             if (anibuf[strlen(anibuf) - 1] == '#')
10357                anibuf[strlen(anibuf) - 1] = 0;
10358             ast_set_callerid(chan, anibuf + 2, NULL, anibuf + 2);
10359          }
10360          ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
10361       }
10362 
10363       ast_copy_string(exten, dtmfbuf, sizeof(exten));
10364       if (ast_strlen_zero(exten))
10365          ast_copy_string(exten, "s", sizeof(exten));
10366       if (p->sig == SIG_FEATD || p->sig == SIG_EMWINK) {
10367          /* Look for Feature Group D on all E&M Wink and Feature Group D trunks */
10368          if (exten[0] == '*') {
10369             char *stringp=NULL;
10370             ast_copy_string(exten2, exten, sizeof(exten2));
10371             /* Parse out extension and callerid */
10372             stringp=exten2 +1;
10373             s1 = strsep(&stringp, "*");
10374             s2 = strsep(&stringp, "*");
10375             if (s2) {
10376                if (!ast_strlen_zero(p->cid_num))
10377                   ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
10378                else
10379                   ast_set_callerid(chan, s1, NULL, s1);
10380                ast_copy_string(exten, s2, sizeof(exten));
10381             } else
10382                ast_copy_string(exten, s1, sizeof(exten));
10383          } else if (p->sig == SIG_FEATD)
10384             ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d.  Assuming E&M Wink instead\n", p->channel);
10385       }
10386       if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
10387          if (exten[0] == '*') {
10388             char *stringp=NULL;
10389             ast_copy_string(exten2, exten, sizeof(exten2));
10390             /* Parse out extension and callerid */
10391             stringp=exten2 +1;
10392             s1 = strsep(&stringp, "#");
10393             s2 = strsep(&stringp, "#");
10394             if (s2) {
10395                if (!ast_strlen_zero(p->cid_num))
10396                   ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
10397                else
10398                   if (*(s1 + 2))
10399                      ast_set_callerid(chan, s1 + 2, NULL, s1 + 2);
10400                ast_copy_string(exten, s2 + 1, sizeof(exten));
10401             } else
10402                ast_copy_string(exten, s1 + 2, sizeof(exten));
10403          } else
10404             ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d.  Assuming E&M Wink instead\n", p->channel);
10405       }
10406       if ((p->sig == SIG_E911) || (p->sig == SIG_FGC_CAMAMF)) {
10407          if (exten[0] == '*') {
10408             char *stringp=NULL;
10409             ast_copy_string(exten2, exten, sizeof(exten2));
10410             /* Parse out extension and callerid */
10411             stringp=exten2 +1;
10412             s1 = strsep(&stringp, "#");
10413             s2 = strsep(&stringp, "#");
10414             if (s2 && (*(s2 + 1) == '0')) {
10415                if (*(s2 + 2))
10416                   ast_set_callerid(chan, s2 + 2, NULL, s2 + 2);
10417             }
10418             if (s1)  ast_copy_string(exten, s1, sizeof(exten));
10419             else ast_copy_string(exten, "911", sizeof(exten));
10420          } else
10421             ast_log(LOG_WARNING, "Got a non-E911/FGC CAMA input on channel %d.  Assuming E&M Wink instead\n", p->channel);
10422       }
10423       if (p->sig == SIG_FEATB) {
10424          if (exten[0] == '*') {
10425             char *stringp=NULL;
10426             ast_copy_string(exten2, exten, sizeof(exten2));
10427             /* Parse out extension and callerid */
10428             stringp=exten2 +1;
10429             s1 = strsep(&stringp, "#");
10430             ast_copy_string(exten, exten2 + 1, sizeof(exten));
10431          } else
10432             ast_log(LOG_WARNING, "Got a non-Feature Group B input on channel %d.  Assuming E&M Wink instead\n", p->channel);
10433       }
10434       if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
10435          dahdi_wink(p, idx);
10436          /* some switches require a minimum guard time between
10437             the last FGD wink and something that answers
10438             immediately. This ensures it */
10439          if (ast_safe_sleep(chan, 100)) {
10440             ast_hangup(chan);
10441             goto quit;
10442          }
10443       }
10444       dahdi_enable_ec(p);
10445       if (NEED_MFDETECT(p)) {
10446          if (p->dsp) {
10447             if (!p->hardwaredtmf)
10448                ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
10449             else {
10450                ast_dsp_free(p->dsp);
10451                p->dsp = NULL;
10452             }
10453          }
10454       }
10455 
10456       if (ast_exists_extension(chan, ast_channel_context(chan), exten, 1,
10457          S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL))) {
10458          ast_channel_exten_set(chan, exten);
10459          if (p->dsp) ast_dsp_digitreset(p->dsp);
10460          res = ast_pbx_run(chan);
10461          if (res) {
10462             ast_log(LOG_WARNING, "PBX exited non-zero\n");
10463             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10464          }
10465          goto quit;
10466       } else {
10467          ast_verb(2, "Unknown extension '%s' in context '%s' requested\n", exten, ast_channel_context(chan));
10468          sleep(2);
10469          res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_INFO);
10470          if (res < 0)
10471             ast_log(LOG_WARNING, "Unable to start special tone on %d\n", p->channel);
10472          else
10473             sleep(1);
10474          res = ast_streamfile(chan, "ss-noservice", ast_channel_language(chan));
10475          if (res >= 0)
10476             ast_waitstream(chan, "");
10477          res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10478          ast_hangup(chan);
10479          goto quit;
10480       }
10481       break;
10482    case SIG_FXOLS:
10483    case SIG_FXOGS:
10484    case SIG_FXOKS:
10485       /* Read the first digit */
10486       timeout = firstdigittimeout;
10487       /* If starting a threeway call, never timeout on the first digit so someone
10488          can use flash-hook as a "hold" feature */
10489       if (p->subs[SUB_THREEWAY].owner)
10490          timeout = 999999;
10491       while (len < AST_MAX_EXTENSION-1) {
10492          /* Read digit unless it's supposed to be immediate, in which case the
10493             only answer is 's' */
10494          if (p->immediate)
10495             res = 's';
10496          else
10497             res = ast_waitfordigit(chan, timeout);
10498          timeout = 0;
10499          if (res < 0) {
10500             ast_debug(1, "waitfordigit returned < 0...\n");
10501             res = tone_zone_play_tone(p->subs[idx].dfd, -1);
10502             ast_hangup(chan);
10503             goto quit;
10504          } else if (res) {
10505             ast_debug(1,"waitfordigit returned '%c' (%d), timeout = %d\n", res, res, timeout);
10506             exten[len++]=res;
10507             exten[len] = '\0';
10508          }
10509          if (!ast_ignore_pattern(ast_channel_context(chan), exten))
10510             tone_zone_play_tone(p->subs[idx].dfd, -1);
10511          else
10512             tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
10513          if (ast_exists_extension(chan, ast_channel_context(chan), exten, 1, p->cid_num) && !ast_parking_ext_valid(exten, chan, ast_channel_context(chan))) {
10514             if (!res || !ast_matchmore_extension(chan, ast_channel_context(chan), exten, 1, p->cid_num)) {
10515                if (getforward) {
10516                   /* Record this as the forwarding extension */
10517                   ast_copy_string(p->call_forward, exten, sizeof(p->call_forward));
10518                   ast_verb(3, "Setting call forward to '%s' on channel %d\n", p->call_forward, p->channel);
10519                   res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10520                   if (res)
10521                      break;
10522                   usleep(500000);
10523                   res = tone_zone_play_tone(p->subs[idx].dfd, -1);
10524                   sleep(1);
10525                   memset(exten, 0, sizeof(exten));
10526                   res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
10527                   len = 0;
10528                   getforward = 0;
10529                } else {
10530                   res = tone_zone_play_tone(p->subs[idx].dfd, -1);
10531                   ast_channel_exten_set(chan, exten);
10532                   if (!ast_strlen_zero(p->cid_num)) {
10533                      if (!p->hidecallerid)
10534                         ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
10535                      else
10536                         ast_set_callerid(chan, NULL, NULL, p->cid_num);
10537                   }
10538                   if (!ast_strlen_zero(p->cid_name)) {
10539                      if (!p->hidecallerid)
10540                         ast_set_callerid(chan, NULL, p->cid_name, NULL);
10541                   }
10542                   ast_setstate(chan, AST_STATE_RING);
10543                   dahdi_enable_ec(p);
10544                   res = ast_pbx_run(chan);
10545                   if (res) {
10546                      ast_log(LOG_WARNING, "PBX exited non-zero\n");
10547                      res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10548                   }
10549                   goto quit;
10550                }
10551             } else {
10552                /* It's a match, but they just typed a digit, and there is an ambiguous match,
10553                   so just set the timeout to matchdigittimeout and wait some more */
10554                timeout = matchdigittimeout;
10555             }
10556          } else if (res == 0) {
10557             ast_debug(1, "not enough digits (and no ambiguous match)...\n");
10558             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10559             dahdi_wait_event(p->subs[idx].dfd);
10560             ast_hangup(chan);
10561             goto quit;
10562          } else if (p->callwaiting && !strcmp(exten, "*70")) {
10563             ast_verb(3, "Disabling call waiting on %s\n", ast_channel_name(chan));
10564             /* Disable call waiting if enabled */
10565             p->callwaiting = 0;
10566             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10567             if (res) {
10568                ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
10569                   ast_channel_name(chan), strerror(errno));
10570             }
10571             len = 0;
10572             ioctl(p->subs[idx].dfd,DAHDI_CONFDIAG,&len);
10573             memset(exten, 0, sizeof(exten));
10574             timeout = firstdigittimeout;
10575 
10576          } else if (!strcmp(exten,ast_pickup_ext())) {
10577             /* Scan all channels and see if there are any
10578              * ringing channels that have call groups
10579              * that equal this channels pickup group
10580              */
10581             if (idx == SUB_REAL) {
10582                /* Switch us from Third call to Call Wait */
10583                if (p->subs[SUB_THREEWAY].owner) {
10584                   /* If you make a threeway call and the *8# a call, it should actually
10585                      look like a callwait */
10586                   alloc_sub(p, SUB_CALLWAIT);
10587                   swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
10588                   unalloc_sub(p, SUB_THREEWAY);
10589                }
10590                dahdi_enable_ec(p);
10591                if (ast_pickup_call(chan)) {
10592                   ast_debug(1, "No call pickup possible...\n");
10593                   res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10594                   dahdi_wait_event(p->subs[idx].dfd);
10595                }
10596                ast_hangup(chan);
10597                goto quit;
10598             } else {
10599                ast_log(LOG_WARNING, "Huh?  Got *8# on call not on real\n");
10600                ast_hangup(chan);
10601                goto quit;
10602             }
10603 
10604          } else if (!p->hidecallerid && !strcmp(exten, "*67")) {
10605             ast_verb(3, "Disabling Caller*ID on %s\n", ast_channel_name(chan));
10606             /* Disable Caller*ID if enabled */
10607             p->hidecallerid = 1;
10608             ast_party_number_free(&ast_channel_caller(chan)->id.number);
10609             ast_party_number_init(&ast_channel_caller(chan)->id.number);
10610             ast_party_name_free(&ast_channel_caller(chan)->id.name);
10611             ast_party_name_init(&ast_channel_caller(chan)->id.name);
10612             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10613             if (res) {
10614                ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
10615                   ast_channel_name(chan), strerror(errno));
10616             }
10617             len = 0;
10618             memset(exten, 0, sizeof(exten));
10619             timeout = firstdigittimeout;
10620          } else if (p->callreturn && !strcmp(exten, "*69")) {
10621             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10622             break;
10623          } else if (!strcmp(exten, "*78")) {
10624             dahdi_dnd(p, 1);
10625             /* Do not disturb */
10626             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10627             getforward = 0;
10628             memset(exten, 0, sizeof(exten));
10629             len = 0;
10630          } else if (!strcmp(exten, "*79")) {
10631             dahdi_dnd(p, 0);
10632             /* Do not disturb */
10633             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10634             getforward = 0;
10635             memset(exten, 0, sizeof(exten));
10636             len = 0;
10637          } else if (p->cancallforward && !strcmp(exten, "*72")) {
10638             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10639             getforward = 1;
10640             memset(exten, 0, sizeof(exten));
10641             len = 0;
10642          } else if (p->cancallforward && !strcmp(exten, "*73")) {
10643             ast_verb(3, "Cancelling call forwarding on channel %d\n", p->channel);
10644             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10645             memset(p->call_forward, 0, sizeof(p->call_forward));
10646             getforward = 0;
10647             memset(exten, 0, sizeof(exten));
10648             len = 0;
10649          } else if ((p->transfer || p->canpark) && ast_parking_ext_valid(exten, chan, ast_channel_context(chan)) &&
10650                   p->subs[SUB_THREEWAY].owner &&
10651                   ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
10652             /* This is a three way call, the main call being a real channel,
10653                and we're parking the first call. */
10654             ast_masq_park_call_exten(ast_bridged_channel(p->subs[SUB_THREEWAY].owner),
10655                chan, exten, ast_channel_context(chan), 0, NULL);
10656             ast_verb(3, "Parking call to '%s'\n", ast_channel_name(chan));
10657             break;
10658          } else if (p->hidecallerid && !strcmp(exten, "*82")) {
10659             ast_verb(3, "Enabling Caller*ID on %s\n", ast_channel_name(chan));
10660             /* Enable Caller*ID if enabled */
10661             p->hidecallerid = 0;
10662             ast_set_callerid(chan, p->cid_num, p->cid_name, NULL);
10663             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10664             if (res) {
10665                ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
10666                   ast_channel_name(chan), strerror(errno));
10667             }
10668             len = 0;
10669             memset(exten, 0, sizeof(exten));
10670             timeout = firstdigittimeout;
10671          } else if (!strcmp(exten, "*0")) {
10672             struct ast_channel *nbridge =
10673                p->subs[SUB_THREEWAY].owner;
10674             struct dahdi_pvt *pbridge = NULL;
10675             /* set up the private struct of the bridged one, if any */
10676             if (nbridge && ast_bridged_channel(nbridge))
10677                pbridge = ast_channel_tech_pvt(ast_bridged_channel(nbridge));
10678             if (nbridge && pbridge &&
10679                (ast_channel_tech(nbridge) == &dahdi_tech) &&
10680                (ast_channel_tech(ast_bridged_channel(nbridge)) == &dahdi_tech) &&
10681                ISTRUNK(pbridge)) {
10682                int func = DAHDI_FLASH;
10683                /* Clear out the dial buffer */
10684                p->dop.dialstr[0] = '\0';
10685                /* flash hookswitch */
10686                if ((ioctl(pbridge->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
10687                   ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
10688                      ast_channel_name(nbridge), strerror(errno));
10689                }
10690                swap_subs(p, SUB_REAL, SUB_THREEWAY);
10691                unalloc_sub(p, SUB_THREEWAY);
10692                p->owner = p->subs[SUB_REAL].owner;
10693                if (ast_bridged_channel(p->subs[SUB_REAL].owner))
10694                   ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
10695                ast_hangup(chan);
10696                goto quit;
10697             } else {
10698                tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10699                dahdi_wait_event(p->subs[idx].dfd);
10700                tone_zone_play_tone(p->subs[idx].dfd, -1);
10701                swap_subs(p, SUB_REAL, SUB_THREEWAY);
10702                unalloc_sub(p, SUB_THREEWAY);
10703                p->owner = p->subs[SUB_REAL].owner;
10704                ast_hangup(chan);
10705                goto quit;
10706             }
10707          } else if (!ast_canmatch_extension(chan, ast_channel_context(chan), exten, 1,
10708             S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL))
10709             && !canmatch_featurecode(exten)) {
10710             ast_debug(1, "Can't match %s from '%s' in context %s\n", exten,
10711                S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, "<Unknown Caller>"),
10712                ast_channel_context(chan));
10713             break;
10714          }
10715          if (!timeout)
10716             timeout = gendigittimeout;
10717          if (len && !ast_ignore_pattern(ast_channel_context(chan), exten))
10718             tone_zone_play_tone(p->subs[idx].dfd, -1);
10719       }
10720       break;
10721    case SIG_FXSLS:
10722    case SIG_FXSGS:
10723    case SIG_FXSKS:
10724       /* check for SMDI messages */
10725       if (p->use_smdi && p->smdi_iface) {
10726          smdi_msg = ast_smdi_md_message_wait(p->smdi_iface, SMDI_MD_WAIT_TIMEOUT);
10727 
10728          if (smdi_msg != NULL) {
10729             ast_channel_exten_set(chan, smdi_msg->fwd_st);
10730 
10731             if (smdi_msg->type == 'B')
10732                pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "b");
10733             else if (smdi_msg->type == 'N')
10734                pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "u");
10735 
10736             ast_debug(1, "Received SMDI message on %s\n", ast_channel_name(chan));
10737          } else {
10738             ast_log(LOG_WARNING, "SMDI enabled but no SMDI message present\n");
10739          }
10740       }
10741 
10742       if (p->use_callerid && (p->cid_signalling == CID_SIG_SMDI && smdi_msg)) {
10743          number = smdi_msg->calling_st;
10744 
10745       /* If we want caller id, we're in a prering state due to a polarity reversal
10746        * and we're set to use a polarity reversal to trigger the start of caller id,
10747        * grab the caller id and wait for ringing to start... */
10748       } else if (p->use_callerid && (ast_channel_state(chan) == AST_STATE_PRERING &&
10749                    (p->cid_start == CID_START_POLARITY || p->cid_start == CID_START_POLARITY_IN || p->cid_start == CID_START_DTMF_NOALERT))) {
10750          /* If set to use DTMF CID signalling, listen for DTMF */
10751          if (p->cid_signalling == CID_SIG_DTMF) {
10752             int k = 0;
10753             int off_ms;
10754             struct timeval start = ast_tvnow();
10755             int ms;
10756             cs = NULL;
10757             ast_debug(1, "Receiving DTMF cid on channel %s\n", ast_channel_name(chan));
10758             dahdi_setlinear(p->subs[idx].dfd, 0);
10759             /*
10760              * We are the only party interested in the Rx stream since
10761              * we have not answered yet.  We don't need or even want DTMF
10762              * emulation.  The DTMF digits can come so fast that emulation
10763              * can drop some of them.
10764              */
10765             ast_set_flag(ast_channel_flags(chan), AST_FLAG_END_DTMF_ONLY);
10766             off_ms = 4000;/* This is a typical OFF time between rings. */
10767             for (;;) {
10768                struct ast_frame *f;
10769 
10770                ms = ast_remaining_ms(start, off_ms);
10771                res = ast_waitfor(chan, ms);
10772                if (res <= 0) {
10773                   /*
10774                    * We do not need to restore the dahdi_setlinear()
10775                    * or AST_FLAG_END_DTMF_ONLY flag settings since we
10776                    * are hanging up the channel.
10777                    */
10778                   ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
10779                      "Exiting simple switch\n");
10780                   ast_hangup(chan);
10781                   goto quit;
10782                }
10783                f = ast_read(chan);
10784                if (!f)
10785                   break;
10786                if (f->frametype == AST_FRAME_DTMF) {
10787                   if (k < ARRAY_LEN(dtmfbuf) - 1) {
10788                      dtmfbuf[k++] = f->subclass.integer;
10789                   }
10790                   ast_debug(1, "CID got digit '%c'\n", f->subclass.integer);
10791                   start = ast_tvnow();
10792                }
10793                ast_frfree(f);
10794                if (ast_channel_state(chan) == AST_STATE_RING ||
10795                   ast_channel_state(chan) == AST_STATE_RINGING)
10796                   break; /* Got ring */
10797             }
10798             ast_clear_flag(ast_channel_flags(chan), AST_FLAG_END_DTMF_ONLY);
10799             dtmfbuf[k] = '\0';
10800             dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10801             /* Got cid and ring. */
10802             ast_debug(1, "CID got string '%s'\n", dtmfbuf);
10803             callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
10804             ast_debug(1, "CID is '%s', flags %d\n", dtmfcid, flags);
10805             /* If first byte is NULL, we have no cid */
10806             if (!ast_strlen_zero(dtmfcid))
10807                number = dtmfcid;
10808             else
10809                number = NULL;
10810          /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */
10811          } else if ((p->cid_signalling == CID_SIG_V23) || (p->cid_signalling == CID_SIG_V23_JP)) {
10812             cs = callerid_new(p->cid_signalling);
10813             if (cs) {
10814                int off_ms;
10815                struct timeval start;
10816                int ms;
10817                samples = 0;
10818 #if 1
10819                bump_gains(p);
10820 #endif
10821                /* Take out of linear mode for Caller*ID processing */
10822                dahdi_setlinear(p->subs[idx].dfd, 0);
10823 
10824                /* First we wait and listen for the Caller*ID */
10825                for (;;) {
10826                   i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10827                   if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10828                      ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10829                      callerid_free(cs);
10830                      ast_hangup(chan);
10831                      goto quit;
10832                   }
10833                   if (i & DAHDI_IOMUX_SIGEVENT) {
10834                      res = dahdi_get_event(p->subs[idx].dfd);
10835                      ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10836                      if (res == DAHDI_EVENT_NOALARM) {
10837                         p->inalarm = 0;
10838                      }
10839 
10840                      if (p->cid_signalling == CID_SIG_V23_JP) {
10841                         if (res == DAHDI_EVENT_RINGBEGIN) {
10842                            res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
10843                            usleep(1);
10844                         }
10845                      } else {
10846                         res = 0;
10847                         break;
10848                      }
10849                   } else if (i & DAHDI_IOMUX_READ) {
10850                      res = read(p->subs[idx].dfd, buf, sizeof(buf));
10851                      if (res < 0) {
10852                         if (errno != ELAST) {
10853                            ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10854                            callerid_free(cs);
10855                            ast_hangup(chan);
10856                            goto quit;
10857                         }
10858                         break;
10859                      }
10860                      samples += res;
10861 
10862                      if (p->cid_signalling == CID_SIG_V23_JP) {
10863                         res = callerid_feed_jp(cs, buf, res, ast_format_set(&tmpfmt, AST_LAW(p), 0));
10864                      } else {
10865                         res = callerid_feed(cs, buf, res, ast_format_set(&tmpfmt, AST_LAW(p), 0));
10866                      }
10867                      if (res < 0) {
10868                         /*
10869                          * The previous diagnostic message output likely
10870                          * explains why it failed.
10871                          */
10872                         ast_log(LOG_WARNING,
10873                            "Failed to decode CallerID on channel '%s'\n",
10874                            ast_channel_name(chan));
10875                         break;
10876                      } else if (res)
10877                         break;
10878                      else if (samples > (8000 * 10))
10879                         break;
10880                   }
10881                }
10882                if (res == 1) {
10883                   callerid_get(cs, &name, &number, &flags);
10884                   ast_log(LOG_NOTICE, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
10885                }
10886 
10887                if (p->cid_signalling == CID_SIG_V23_JP) {
10888                   res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
10889                   usleep(1);
10890                }
10891 
10892                /* Finished with Caller*ID, now wait for a ring to make sure there really is a call coming */
10893                start = ast_tvnow();
10894                off_ms = 4000;/* This is a typical OFF time between rings. */
10895                for (;;) {
10896                   struct ast_frame *f;
10897 
10898                   ms = ast_remaining_ms(start, off_ms);
10899                   res = ast_waitfor(chan, ms);
10900                   if (res <= 0) {
10901                      ast_log(LOG_WARNING, "CID timed out waiting for ring. "
10902                         "Exiting simple switch\n");
10903                      ast_hangup(chan);
10904                      goto quit;
10905                   }
10906                   if (!(f = ast_read(chan))) {
10907                      ast_log(LOG_WARNING, "Hangup received waiting for ring. Exiting simple switch\n");
10908                      ast_hangup(chan);
10909                      goto quit;
10910                   }
10911                   ast_frfree(f);
10912                   if (ast_channel_state(chan) == AST_STATE_RING ||
10913                      ast_channel_state(chan) == AST_STATE_RINGING)
10914                      break; /* Got ring */
10915                }
10916 
10917                /* We must have a ring by now, so, if configured, lets try to listen for
10918                 * distinctive ringing */
10919                if (p->usedistinctiveringdetection) {
10920                   len = 0;
10921                   distMatches = 0;
10922                   /* Clear the current ring data array so we don't have old data in it. */
10923                   for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
10924                      curRingData[receivedRingT] = 0;
10925                   receivedRingT = 0;
10926                   counter = 0;
10927                   counter1 = 0;
10928                   /* Check to see if context is what it should be, if not set to be. */
10929                   if (strcmp(p->context,p->defcontext) != 0) {
10930                      ast_copy_string(p->context, p->defcontext, sizeof(p->context));
10931                      ast_channel_context_set(chan, p->defcontext);
10932                   }
10933 
10934                   for (;;) {
10935                      i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10936                      if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10937                         ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10938                         callerid_free(cs);
10939                         ast_hangup(chan);
10940                         goto quit;
10941                      }
10942                      if (i & DAHDI_IOMUX_SIGEVENT) {
10943                         res = dahdi_get_event(p->subs[idx].dfd);
10944                         ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10945                         if (res == DAHDI_EVENT_NOALARM) {
10946                            p->inalarm = 0;
10947                         }
10948                         res = 0;
10949                         /* Let us detect distinctive ring */
10950 
10951                         curRingData[receivedRingT] = p->ringt;
10952 
10953                         if (p->ringt < p->ringt_base/2)
10954                            break;
10955                         /* Increment the ringT counter so we can match it against
10956                            values in chan_dahdi.conf for distinctive ring */
10957                         if (++receivedRingT == ARRAY_LEN(curRingData))
10958                            break;
10959                      } else if (i & DAHDI_IOMUX_READ) {
10960                         res = read(p->subs[idx].dfd, buf, sizeof(buf));
10961                         if (res < 0) {
10962                            if (errno != ELAST) {
10963                               ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10964                               callerid_free(cs);
10965                               ast_hangup(chan);
10966                               goto quit;
10967                            }
10968                            break;
10969                         }
10970                         if (p->ringt > 0) {
10971                            if (!(--p->ringt)) {
10972                               res = -1;
10973                               break;
10974                            }
10975                         }
10976                      }
10977                   }
10978                      /* this only shows up if you have n of the dring patterns filled in */
10979                   ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
10980                   for (counter = 0; counter < 3; counter++) {
10981                      /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this
10982                      channel */
10983                      distMatches = 0;
10984                      for (counter1 = 0; counter1 < 3; counter1++) {
10985                         ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
10986                         if (p->drings.ringnum[counter].ring[counter1] == -1) {
10987                            ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
10988                            curRingData[counter1]);
10989                            distMatches++;
10990                         } else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
10991                               curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
10992                            ast_verb(3, "Ring pattern matched in range: %d to %d\n",
10993                            (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
10994                            (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
10995                            distMatches++;
10996                         }
10997                      }
10998 
10999                      if (distMatches == 3) {
11000                         /* The ring matches, set the context to whatever is for distinctive ring.. */
11001                         ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context));
11002                         ast_channel_context_set(chan, S_OR(p->drings.ringContext[counter].contextData, p->defcontext));
11003                         ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
11004                         break;
11005                      }
11006                   }
11007                }
11008                /* Restore linear mode (if appropriate) for Caller*ID processing */
11009                dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
11010 #if 1
11011                restore_gains(p);
11012 #endif
11013             } else
11014                ast_log(LOG_WARNING, "Unable to get caller ID space\n");
11015          } else {
11016             ast_log(LOG_WARNING, "Channel %s in prering "
11017                "state, but I have nothing to do. "
11018                "Terminating simple switch, should be "
11019                "restarted by the actual ring.\n",
11020                ast_channel_name(chan));
11021             ast_hangup(chan);
11022             goto quit;
11023          }
11024       } else if (p->use_callerid && p->cid_start == CID_START_RING) {
11025          if (p->cid_signalling == CID_SIG_DTMF) {
11026             int k = 0;
11027             int off_ms;
11028             struct timeval start;
11029             int ms;
11030             cs = NULL;
11031             dahdi_setlinear(p->subs[idx].dfd, 0);
11032             off_ms = 2000;
11033             start = ast_tvnow();
11034             for (;;) {
11035                struct ast_frame *f;
11036 
11037                ms = ast_remaining_ms(start, off_ms);
11038                res = ast_waitfor(chan, ms);
11039                if (res <= 0) {
11040                   ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
11041                      "Exiting simple switch\n");
11042                   ast_hangup(chan);
11043                   goto quit;
11044                }
11045                f = ast_read(chan);
11046                if (!f) {
11047                   /* Hangup received waiting for DTMFCID. Exiting simple switch. */
11048                   ast_hangup(chan);
11049                   goto quit;
11050                }
11051                if (f->frametype == AST_FRAME_DTMF) {
11052                   dtmfbuf[k++] = f->subclass.integer;
11053                   ast_debug(1, "CID got digit '%c'\n", f->subclass.integer);
11054                   start = ast_tvnow();
11055                }
11056                ast_frfree(f);
11057 
11058                if (p->ringt_base == p->ringt)
11059                   break;
11060             }
11061             dtmfbuf[k] = '\0';
11062             dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
11063             /* Got cid and ring. */
11064             callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
11065             ast_debug(1, "CID is '%s', flags %d\n",
11066                dtmfcid, flags);
11067             /* If first byte is NULL, we have no cid */
11068             if (!ast_strlen_zero(dtmfcid))
11069                number = dtmfcid;
11070             else
11071                number = NULL;
11072             /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */
11073          } else {
11074             /* FSK Bell202 callerID */
11075             cs = callerid_new(p->cid_signalling);
11076             if (cs) {
11077 #if 1
11078                bump_gains(p);
11079 #endif
11080                samples = 0;
11081                len = 0;
11082                distMatches = 0;
11083                /* Clear the current ring data array so we don't have old data in it. */
11084                for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
11085                   curRingData[receivedRingT] = 0;
11086                receivedRingT = 0;
11087                counter = 0;
11088                counter1 = 0;
11089                /* Check to see if context is what it should be, if not set to be. */
11090                if (strcmp(p->context,p->defcontext) != 0) {
11091                   ast_copy_string(p->context, p->defcontext, sizeof(p->context));
11092                   ast_channel_context_set(chan, p->defcontext);
11093                }
11094 
11095                /* Take out of linear mode for Caller*ID processing */
11096                dahdi_setlinear(p->subs[idx].dfd, 0);
11097                for (;;) {
11098                   i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
11099                   if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
11100                      ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
11101                      callerid_free(cs);
11102                      ast_hangup(chan);
11103                      goto quit;
11104                   }
11105                   if (i & DAHDI_IOMUX_SIGEVENT) {
11106                      res = dahdi_get_event(p->subs[idx].dfd);
11107                      ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
11108                      if (res == DAHDI_EVENT_NOALARM) {
11109                         p->inalarm = 0;
11110                      }
11111                      /* If we get a PR event, they hung up while processing calerid */
11112                      if ( res == DAHDI_EVENT_POLARITY && p->hanguponpolarityswitch && p->polarity == POLARITY_REV) {
11113                         ast_debug(1, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p->channel);
11114                         p->polarity = POLARITY_IDLE;
11115                         callerid_free(cs);
11116                         ast_hangup(chan);
11117                         goto quit;
11118                      }
11119                      res = 0;
11120                      /* Let us detect callerid when the telco uses distinctive ring */
11121 
11122                      curRingData[receivedRingT] = p->ringt;
11123 
11124                      if (p->ringt < p->ringt_base/2)
11125                         break;
11126                      /* Increment the ringT counter so we can match it against
11127                         values in chan_dahdi.conf for distinctive ring */
11128                      if (++receivedRingT == ARRAY_LEN(curRingData))
11129                         break;
11130                   } else if (i & DAHDI_IOMUX_READ) {
11131                      res = read(p->subs[idx].dfd, buf, sizeof(buf));
11132                      if (res < 0) {
11133                         if (errno != ELAST) {
11134                            ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
11135                            callerid_free(cs);
11136                            ast_hangup(chan);
11137                            goto quit;
11138                         }
11139                         break;
11140                      }
11141                      if (p->ringt > 0) {
11142                         if (!(--p->ringt)) {
11143                            res = -1;
11144                            break;
11145                         }
11146                      }
11147                      samples += res;
11148                      res = callerid_feed(cs, buf, res, ast_format_set(&tmpfmt, AST_LAW(p), 0));
11149                      if (res < 0) {
11150                         /*
11151                          * The previous diagnostic message output likely
11152                          * explains why it failed.
11153                          */
11154                         ast_log(LOG_WARNING,
11155                            "Failed to decode CallerID on channel '%s'\n",
11156                            ast_channel_name(chan));
11157                         break;
11158                      } else if (res)
11159                         break;
11160                      else if (samples > (8000 * 10))
11161                         break;
11162                   }
11163                }
11164                if (res == 1) {
11165                   callerid_get(cs, &name, &number, &flags);
11166                   ast_debug(1, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
11167                }
11168                if (distinctiveringaftercid == 1) {
11169                   /* Clear the current ring data array so we don't have old data in it. */
11170                   for (receivedRingT = 0; receivedRingT < 3; receivedRingT++) {
11171                      curRingData[receivedRingT] = 0;
11172                   }
11173                   receivedRingT = 0;
11174                   ast_verb(3, "Detecting post-CID distinctive ring\n");
11175                   for (;;) {
11176                      i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
11177                      if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
11178                         ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
11179                         callerid_free(cs);
11180                         ast_hangup(chan);
11181                         goto quit;
11182                      }
11183                      if (i & DAHDI_IOMUX_SIGEVENT) {
11184                         res = dahdi_get_event(p->subs[idx].dfd);
11185                         ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
11186                         if (res == DAHDI_EVENT_NOALARM) {
11187                            p->inalarm = 0;
11188                         }
11189                         res = 0;
11190                         /* Let us detect callerid when the telco uses distinctive ring */
11191 
11192                         curRingData[receivedRingT] = p->ringt;
11193 
11194                         if (p->ringt < p->ringt_base/2)
11195                            break;
11196                         /* Increment the ringT counter so we can match it against
11197                            values in chan_dahdi.conf for distinctive ring */
11198                         if (++receivedRingT == ARRAY_LEN(curRingData))
11199                            break;
11200                      } else if (i & DAHDI_IOMUX_READ) {
11201                         res = read(p->subs[idx].dfd, buf, sizeof(buf));
11202                         if (res < 0) {
11203                            if (errno != ELAST) {
11204                               ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
11205                               callerid_free(cs);
11206                               ast_hangup(chan);
11207                               goto quit;
11208                            }
11209                            break;
11210                         }
11211                         if (p->ringt > 0) {
11212                            if (!(--p->ringt)) {
11213                               res = -1;
11214                               break;
11215                            }
11216                         }
11217                      }
11218                   }
11219                }
11220                if (p->usedistinctiveringdetection) {
11221                   /* this only shows up if you have n of the dring patterns filled in */
11222                   ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
11223 
11224                   for (counter = 0; counter < 3; counter++) {
11225                      /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this
11226                      channel */
11227                      /* this only shows up if you have n of the dring patterns filled in */
11228                      ast_verb(3, "Checking %d,%d,%d\n",
11229                            p->drings.ringnum[counter].ring[0],
11230                            p->drings.ringnum[counter].ring[1],
11231                            p->drings.ringnum[counter].ring[2]);
11232                      distMatches = 0;
11233                      for (counter1 = 0; counter1 < 3; counter1++) {
11234                         ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
11235                         if (p->drings.ringnum[counter].ring[counter1] == -1) {
11236                            ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
11237                            curRingData[counter1]);
11238                            distMatches++;
11239                         }
11240                         else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
11241                            curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
11242                            ast_verb(3, "Ring pattern matched in range: %d to %d\n",
11243                            (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
11244                            (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
11245                            distMatches++;
11246                         }
11247                      }
11248                      if (distMatches == 3) {
11249                         /* The ring matches, set the context to whatever is for distinctive ring.. */
11250                         ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context));
11251                         ast_channel_context_set(chan, S_OR(p->drings.ringContext[counter].contextData, p->defcontext));
11252                         ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
11253                         break;
11254                      }
11255                   }
11256                }
11257                /* Restore linear mode (if appropriate) for Caller*ID processing */
11258                dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
11259 #if 1
11260                restore_gains(p);
11261 #endif
11262                if (res < 0) {
11263                   ast_log(LOG_WARNING, "CallerID returned with error on channel '%s'\n", ast_channel_name(chan));
11264                }
11265             } else
11266                ast_log(LOG_WARNING, "Unable to get caller ID space\n");
11267          }
11268       } else
11269          cs = NULL;
11270 
11271       if (number)
11272          ast_shrink_phone_number(number);
11273       ast_set_callerid(chan, number, name, number);
11274 
11275       if (smdi_msg)
11276          ASTOBJ_UNREF(smdi_msg, ast_smdi_md_message_destroy);
11277 
11278       if (cs)
11279          callerid_free(cs);
11280 
11281       my_handle_notify_message(chan, p, flags, -1);
11282 
11283       ast_setstate(chan, AST_STATE_RING);
11284       ast_channel_rings_set(chan, 1);
11285       p->ringt = p->ringt_base;
11286       res = ast_pbx_run(chan);
11287       if (res) {
11288          ast_hangup(chan);
11289          ast_log(LOG_WARNING, "PBX exited non-zero\n");
11290       }
11291       goto quit;
11292    default:
11293       ast_log(LOG_WARNING, "Don't know how to handle simple switch with signalling %s on channel %d\n", sig2str(p->sig), p->channel);
11294       res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
11295       if (res < 0)
11296             ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
11297    }
11298    res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
11299    if (res < 0)
11300          ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
11301    ast_hangup(chan);
11302 quit:
11303    ast_mutex_lock(&ss_thread_lock);
11304    ss_thread_count--;
11305    ast_cond_signal(&ss_thread_complete);
11306    ast_mutex_unlock(&ss_thread_lock);
11307    return NULL;
11308 }
11309 
11310 struct mwi_thread_data {
11311    struct dahdi_pvt *pvt;
11312    unsigned char buf[READ_SIZE];
11313    size_t len;
11314 };
11315 
11316 static int calc_energy(const unsigned char *buf, int len, enum ast_format_id law)
11317 {
11318    int x;
11319    int sum = 0;
11320 
11321    if (!len)
11322       return 0;
11323 
11324    for (x = 0; x < len; x++)
11325       sum += abs(law == AST_FORMAT_ULAW ? AST_MULAW(buf[x]) : AST_ALAW(buf[x]));
11326 
11327    return sum / len;
11328 }
11329 
11330 static void *mwi_thread(void *data)
11331 {
11332    struct mwi_thread_data *mtd = data;
11333    struct callerid_state *cs;
11334    pthread_t threadid;
11335    int samples = 0;
11336    char *name, *number;
11337    int flags;
11338    int i, res;
11339    unsigned int spill_done = 0;
11340    int spill_result = -1;
11341    struct ast_format tmpfmt;
11342 
11343    if (!(cs = callerid_new(mtd->pvt->cid_signalling))) {
11344       goto quit_no_clean;
11345    }
11346 
11347    callerid_feed(cs, mtd->buf, mtd->len, ast_format_set(&tmpfmt, AST_LAW(mtd->pvt), 0));
11348 
11349    bump_gains(mtd->pvt);
11350 
11351    for (;;) {
11352       i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
11353       if ((res = ioctl(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_IOMUX, &i))) {
11354          ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
11355          goto quit;
11356       }
11357 
11358       if (i & DAHDI_IOMUX_SIGEVENT) {
11359          struct ast_channel *chan;
11360          struct ast_callid *callid = NULL;
11361          int callid_created;
11362 
11363          /* If we get an event, screen out events that we do not act on.
11364           * Otherwise, cancel and go to the simple switch to let it deal with it.
11365           */
11366          res = dahdi_get_event(mtd->pvt->subs[SUB_REAL].dfd);
11367 
11368          switch (res) {
11369          case DAHDI_EVENT_NEONMWI_ACTIVE:
11370          case DAHDI_EVENT_NEONMWI_INACTIVE:
11371          case DAHDI_EVENT_NONE:
11372          case DAHDI_EVENT_BITSCHANGED:
11373             break;
11374          case DAHDI_EVENT_NOALARM:
11375             if (analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) {
11376                struct analog_pvt *analog_p = mtd->pvt->sig_pvt;
11377 
11378                analog_p->inalarm = 0;
11379             }
11380             mtd->pvt->inalarm = 0;
11381             handle_clear_alarms(mtd->pvt);
11382             break;
11383          case DAHDI_EVENT_ALARM:
11384             if (analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) {
11385                struct analog_pvt *analog_p = mtd->pvt->sig_pvt;
11386 
11387                analog_p->inalarm = 1;
11388             }
11389             mtd->pvt->inalarm = 1;
11390             res = get_alarms(mtd->pvt);
11391             handle_alarms(mtd->pvt, res);
11392             break; /* What to do on channel alarm ???? -- fall thru intentionally?? */
11393          default:
11394             callid_created = ast_callid_threadstorage_auto(&callid);
11395             ast_log(LOG_NOTICE, "Got event %d (%s)...  Passing along to analog_ss_thread\n", res, event2str(res));
11396             callerid_free(cs);
11397 
11398             restore_gains(mtd->pvt);
11399             mtd->pvt->ringt = mtd->pvt->ringt_base;
11400 
11401             if ((chan = dahdi_new(mtd->pvt, AST_STATE_RING, 0, SUB_REAL, 0, NULL, callid))) {
11402                int result;
11403 
11404                if (analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) {
11405                   result = analog_ss_thread_start(mtd->pvt->sig_pvt, chan);
11406                } else {
11407                   result = ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan);
11408                }
11409                if (result) {
11410                   ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", mtd->pvt->channel);
11411                   res = tone_zone_play_tone(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11412                   if (res < 0)
11413                      ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", mtd->pvt->channel);
11414                   ast_hangup(chan);
11415                }
11416             } else {
11417                ast_log(LOG_WARNING, "Could not create channel to handle call\n");
11418             }
11419 
11420             ast_callid_threadstorage_auto_clean(callid, callid_created);
11421             goto quit_no_clean;
11422          }
11423       } else if (i & DAHDI_IOMUX_READ) {
11424          if ((res = read(mtd->pvt->subs[SUB_REAL].dfd, mtd->buf, sizeof(mtd->buf))) < 0) {
11425             if (errno != ELAST) {
11426                ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
11427                goto quit;
11428             }
11429             break;
11430          }
11431          samples += res;
11432          if (!spill_done) {
11433             if ((spill_result = callerid_feed(cs, mtd->buf, res, ast_format_set(&tmpfmt, AST_LAW(mtd->pvt), 0))) < 0) {
11434                /*
11435                 * The previous diagnostic message output likely
11436                 * explains why it failed.
11437                 */
11438                ast_log(LOG_WARNING, "Failed to decode CallerID\n");
11439                break;
11440             } else if (spill_result) {
11441                spill_done = 1;
11442             }
11443          } else {
11444             /* keep reading data until the energy level drops below the threshold
11445                so we don't get another 'trigger' on the remaining carrier signal
11446             */
11447             if (calc_energy(mtd->buf, res, AST_LAW(mtd->pvt)) <= mwilevel)
11448                break;
11449          }
11450          if (samples > (8000 * 4)) /*Termination case - time to give up*/
11451             break;
11452       }
11453    }
11454 
11455    if (spill_result == 1) {
11456       callerid_get(cs, &name, &number, &flags);
11457       if (flags & CID_MSGWAITING) {
11458          ast_log(LOG_NOTICE, "mwi: Have Messages on channel %d\n", mtd->pvt->channel);
11459          notify_message(mtd->pvt->mailbox, 1);
11460       } else if (flags & CID_NOMSGWAITING) {
11461          ast_log(LOG_NOTICE, "mwi: No Messages on channel %d\n", mtd->pvt->channel);
11462          notify_message(mtd->pvt->mailbox, 0);
11463       } else {
11464          ast_log(LOG_NOTICE, "mwi: Status unknown on channel %d\n", mtd->pvt->channel);
11465       }
11466    }
11467 
11468 
11469 quit:
11470    callerid_free(cs);
11471 
11472    restore_gains(mtd->pvt);
11473 
11474 quit_no_clean:
11475    mtd->pvt->mwimonitoractive = 0;
11476    ast_free(mtd);
11477 
11478    return NULL;
11479 }
11480 
11481 /*
11482 * The following three functions (mwi_send_init, mwi_send_process_buffer,
11483 * mwi_send_process_event) work with the do_monitor thread to generate mwi spills
11484 * that are sent out via FXS port on voicemail state change.  The execution of
11485 * the mwi send is state driven and can either generate a ring pulse prior to
11486 * sending the fsk spill or simply send an fsk spill.
11487 */
11488 static int mwi_send_init(struct dahdi_pvt * pvt)
11489 {
11490    int x;
11491    struct ast_format tmpfmt;
11492 
11493 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11494    /* Determine how this spill is to be sent */
11495    if (pvt->mwisend_rpas) {
11496       pvt->mwisend_data.mwisend_current = MWI_SEND_SA;
11497       pvt->mwisendactive = 1;
11498    } else if (pvt->mwisend_fsk) {
11499       pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
11500       pvt->mwisendactive = 1;
11501    } else {
11502       pvt->mwisendactive = 0;
11503       return 0;
11504    }
11505 #else
11506    if (mwisend_rpas) {
11507       pvt->mwisend_data.mwisend_current = MWI_SEND_SA;
11508    } else {
11509       pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
11510    }
11511    pvt->mwisendactive = 1;
11512 #endif
11513 
11514    if (pvt->cidspill) {
11515       ast_log(LOG_WARNING, "cidspill already exists when trying to send FSK MWI\n");
11516       ast_free(pvt->cidspill);
11517       pvt->cidspill = NULL;
11518       pvt->cidpos = 0;
11519       pvt->cidlen = 0;
11520    }
11521    pvt->cidspill = ast_calloc(1, MAX_CALLERID_SIZE);
11522    if (!pvt->cidspill) {
11523       pvt->mwisendactive = 0;
11524       return -1;
11525    }
11526    x = DAHDI_FLUSH_BOTH;
11527    ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
11528    x = 3000;
11529    ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_ONHOOKTRANSFER, &x);
11530 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11531    if (pvt->mwisend_fsk) {
11532 #endif
11533       pvt->cidlen = ast_callerid_vmwi_generate(pvt->cidspill, has_voicemail(pvt), CID_MWI_TYPE_MDMF_FULL,
11534                       ast_format_set(&tmpfmt, AST_LAW(pvt), 0), pvt->cid_name, pvt->cid_num, 0);
11535       pvt->cidpos = 0;
11536 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11537    }
11538 #endif
11539    return 0;
11540 }
11541 
11542 static int mwi_send_process_buffer(struct dahdi_pvt * pvt, int num_read)
11543 {
11544    struct timeval    now;
11545    int         res;
11546 
11547    /* sanity check to catch if this had been interrupted previously
11548    *  i.e. state says there is more to do but there is no spill allocated
11549    */
11550    if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current && !pvt->cidspill) {
11551       pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11552    } else if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current) {
11553       /* Normal processing -- Perform mwi send action */
11554       switch ( pvt->mwisend_data.mwisend_current) {
11555       case MWI_SEND_SA:
11556          /* Send the Ring Pulse Signal Alert */
11557          res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &AS_RP_cadence);
11558          if (res) {
11559             ast_log(LOG_WARNING, "Unable to set RP-AS ring cadence: %s\n", strerror(errno));
11560             goto quit;
11561          }
11562          res = dahdi_set_hook(pvt->subs[SUB_REAL].dfd, DAHDI_RING);
11563          pvt->mwisend_data.mwisend_current = MWI_SEND_SA_WAIT;
11564          break;
11565       case MWI_SEND_SA_WAIT:  /* do nothing until I get RINGEROFF event */
11566          break;
11567       case MWI_SEND_PAUSE:  /* Wait between alert and spill - min of 500 mS*/
11568 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11569          if (pvt->mwisend_fsk) {
11570 #endif
11571             gettimeofday(&now, NULL);
11572             if ((int)(now.tv_sec - pvt->mwisend_data.pause.tv_sec) * 1000000 + (int)now.tv_usec - (int)pvt->mwisend_data.pause.tv_usec > 500000) {
11573                pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
11574             }
11575 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11576          } else { /* support for mwisendtype=nofsk */
11577             pvt->mwisend_data.mwisend_current = MWI_SEND_CLEANUP;
11578          }
11579 #endif
11580          break;
11581       case MWI_SEND_SPILL:
11582          /* We read some number of bytes.  Write an equal amount of data */
11583          if(0 < num_read) {
11584             if (num_read > pvt->cidlen - pvt->cidpos)
11585                num_read = pvt->cidlen - pvt->cidpos;
11586             res = write(pvt->subs[SUB_REAL].dfd, pvt->cidspill + pvt->cidpos, num_read);
11587             if (res > 0) {
11588                pvt->cidpos += res;
11589                if (pvt->cidpos >= pvt->cidlen) {
11590                   pvt->mwisend_data.mwisend_current = MWI_SEND_CLEANUP;
11591                }
11592             } else {
11593                ast_log(LOG_WARNING, "MWI FSK Send Write failed: %s\n", strerror(errno));
11594                goto quit;
11595             }
11596          }
11597          break;
11598       case MWI_SEND_CLEANUP:
11599          /* For now, do nothing */
11600          pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11601          break;
11602       default:
11603          /* Should not get here, punt*/
11604          goto quit;
11605       }
11606    }
11607 
11608    if (MWI_SEND_DONE == pvt->mwisend_data.mwisend_current) {
11609       if (pvt->cidspill) {
11610          ast_free(pvt->cidspill);
11611          pvt->cidspill = NULL;
11612          pvt->cidpos = 0;
11613          pvt->cidlen = 0;
11614       }
11615       pvt->mwisendactive = 0;
11616    }
11617    return 0;
11618 quit:
11619    if (pvt->cidspill) {
11620       ast_free(pvt->cidspill);
11621       pvt->cidspill = NULL;
11622       pvt->cidpos = 0;
11623       pvt->cidlen = 0;
11624    }
11625    pvt->mwisendactive = 0;
11626    return -1;
11627 }
11628 
11629 static int mwi_send_process_event(struct dahdi_pvt * pvt, int event)
11630 {
11631    int handled = 0;
11632 
11633    if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current) {
11634       switch (event) {
11635       case DAHDI_EVENT_RINGEROFF:
11636          if(pvt->mwisend_data.mwisend_current == MWI_SEND_SA_WAIT) {
11637             handled = 1;
11638 
11639             if (dahdi_set_hook(pvt->subs[SUB_REAL].dfd, DAHDI_RINGOFF) ) {
11640                ast_log(LOG_WARNING, "Unable to finish RP-AS: %s mwi send aborted\n", strerror(errno));
11641                ast_free(pvt->cidspill);
11642                pvt->cidspill = NULL;
11643                pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11644                pvt->mwisendactive = 0;
11645             } else {
11646                pvt->mwisend_data.mwisend_current = MWI_SEND_PAUSE;
11647                gettimeofday(&pvt->mwisend_data.pause, NULL);
11648             }
11649          }
11650          break;
11651       /* Going off hook, I need to punt this spill */
11652       case DAHDI_EVENT_RINGOFFHOOK:
11653          if (pvt->cidspill) {
11654             ast_free(pvt->cidspill);
11655             pvt->cidspill = NULL;
11656             pvt->cidpos = 0;
11657             pvt->cidlen = 0;
11658          }
11659          pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11660          pvt->mwisendactive = 0;
11661          break;
11662       case DAHDI_EVENT_RINGERON:
11663       case DAHDI_EVENT_HOOKCOMPLETE:
11664          break;
11665       default:
11666          break;
11667       }
11668    }
11669    return handled;
11670 }
11671 
11672 /* destroy a DAHDI channel, identified by its number */
11673 static int dahdi_destroy_channel_bynum(int channel)
11674 {
11675    struct dahdi_pvt *cur;
11676 
11677    ast_mutex_lock(&iflock);
11678    for (cur = iflist; cur; cur = cur->next) {
11679       if (cur->channel == channel) {
11680          int x = DAHDI_FLASH;
11681 
11682          /* important to create an event for dahdi_wait_event to register so that all analog_ss_threads terminate */
11683          ioctl(cur->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
11684 
11685          destroy_channel(cur, 1);
11686          ast_mutex_unlock(&iflock);
11687          ast_module_unref(ast_module_info->self);
11688          return RESULT_SUCCESS;
11689       }
11690    }
11691    ast_mutex_unlock(&iflock);
11692    return RESULT_FAILURE;
11693 }
11694 
11695 static struct dahdi_pvt *handle_init_event(struct dahdi_pvt *i, int event)
11696 {
11697    int res;
11698    pthread_t threadid;
11699    struct ast_channel *chan;
11700    struct ast_callid *callid = NULL;
11701    int callid_created;
11702 
11703    /* Handle an event on a given channel for the monitor thread. */
11704 
11705    switch (event) {
11706    case DAHDI_EVENT_NONE:
11707    case DAHDI_EVENT_BITSCHANGED:
11708       break;
11709    case DAHDI_EVENT_WINKFLASH:
11710    case DAHDI_EVENT_RINGOFFHOOK:
11711       if (i->inalarm) break;
11712       if (i->radio) break;
11713       /* Got a ring/answer.  What kind of channel are we? */
11714       switch (i->sig) {
11715       case SIG_FXOLS:
11716       case SIG_FXOGS:
11717       case SIG_FXOKS:
11718          res = dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
11719          if (res && (errno == EBUSY)) {
11720             break;
11721          }
11722 
11723          callid_created = ast_callid_threadstorage_auto(&callid);
11724 
11725          /* Cancel VMWI spill */
11726          ast_free(i->cidspill);
11727          i->cidspill = NULL;
11728          restore_conference(i);
11729 
11730          if (i->immediate) {
11731             dahdi_enable_ec(i);
11732             /* The channel is immediately up.  Start right away */
11733             res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
11734             chan = dahdi_new(i, AST_STATE_RING, 1, SUB_REAL, 0, NULL, callid);
11735             if (!chan) {
11736                ast_log(LOG_WARNING, "Unable to start PBX on channel %d\n", i->channel);
11737                res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11738                if (res < 0)
11739                   ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11740             }
11741          } else {
11742             /* Check for callerid, digits, etc */
11743             chan = dahdi_new(i, AST_STATE_RESERVED, 0, SUB_REAL, 0, NULL, callid);
11744             if (chan) {
11745                if (has_voicemail(i))
11746                   res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
11747                else
11748                   res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
11749                if (res < 0)
11750                   ast_log(LOG_WARNING, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i->channel);
11751                if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
11752                   ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11753                   res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11754                   if (res < 0)
11755                      ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11756                   ast_hangup(chan);
11757                }
11758             } else
11759                ast_log(LOG_WARNING, "Unable to create channel\n");
11760          }
11761 
11762          ast_callid_threadstorage_auto_clean(callid, callid_created);
11763          break;
11764       case SIG_FXSLS:
11765       case SIG_FXSGS:
11766       case SIG_FXSKS:
11767             i->ringt = i->ringt_base;
11768             /* Fall through */
11769       case SIG_EMWINK:
11770       case SIG_FEATD:
11771       case SIG_FEATDMF:
11772       case SIG_FEATDMF_TA:
11773       case SIG_E911:
11774       case SIG_FGC_CAMA:
11775       case SIG_FGC_CAMAMF:
11776       case SIG_FEATB:
11777       case SIG_EM:
11778       case SIG_EM_E1:
11779       case SIG_SFWINK:
11780       case SIG_SF_FEATD:
11781       case SIG_SF_FEATDMF:
11782       case SIG_SF_FEATB:
11783       case SIG_SF:
11784          /* Check for callerid, digits, etc */
11785          callid_created = ast_callid_threadstorage_auto(&callid);
11786          if (i->cid_start == CID_START_POLARITY_IN) {
11787             chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL, callid);
11788          } else {
11789             chan = dahdi_new(i, AST_STATE_RING, 0, SUB_REAL, 0, NULL, callid);
11790          }
11791 
11792          if (!chan) {
11793             ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
11794          } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
11795             ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11796             res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11797             if (res < 0) {
11798                ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11799             }
11800             ast_hangup(chan);
11801          }
11802 
11803          ast_callid_threadstorage_auto_clean(callid, callid_created);
11804          break;
11805       default:
11806          ast_log(LOG_WARNING, "Don't know how to handle ring/answer with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
11807          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11808          if (res < 0)
11809             ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11810          return NULL;
11811       }
11812       break;
11813    case DAHDI_EVENT_NOALARM:
11814       switch (i->sig) {
11815 #if defined(HAVE_PRI)
11816       case SIG_PRI_LIB_HANDLE_CASES:
11817          ast_mutex_lock(&i->lock);
11818          sig_pri_chan_alarm_notify(i->sig_pvt, 1);
11819          ast_mutex_unlock(&i->lock);
11820          break;
11821 #endif   /* defined(HAVE_PRI) */
11822 #if defined(HAVE_SS7)
11823       case SIG_SS7:
11824          sig_ss7_set_alarm(i->sig_pvt, 0);
11825          break;
11826 #endif   /* defined(HAVE_SS7) */
11827       default:
11828          i->inalarm = 0;
11829          break;
11830       }
11831       handle_clear_alarms(i);
11832       break;
11833    case DAHDI_EVENT_ALARM:
11834       switch (i->sig) {
11835 #if defined(HAVE_PRI)
11836       case SIG_PRI_LIB_HANDLE_CASES:
11837          ast_mutex_lock(&i->lock);
11838          sig_pri_chan_alarm_notify(i->sig_pvt, 0);
11839          ast_mutex_unlock(&i->lock);
11840          break;
11841 #endif   /* defined(HAVE_PRI) */
11842 #if defined(HAVE_SS7)
11843       case SIG_SS7:
11844          sig_ss7_set_alarm(i->sig_pvt, 1);
11845          break;
11846 #endif   /* defined(HAVE_SS7) */
11847       default:
11848          i->inalarm = 1;
11849          break;
11850       }
11851       res = get_alarms(i);
11852       handle_alarms(i, res);
11853       /* fall thru intentionally */
11854    case DAHDI_EVENT_ONHOOK:
11855       if (i->radio)
11856          break;
11857       /* Back on hook.  Hang up. */
11858       switch (i->sig) {
11859       case SIG_FXOLS:
11860       case SIG_FXOGS:
11861       case SIG_FEATD:
11862       case SIG_FEATDMF:
11863       case SIG_FEATDMF_TA:
11864       case SIG_E911:
11865       case SIG_FGC_CAMA:
11866       case SIG_FGC_CAMAMF:
11867       case SIG_FEATB:
11868       case SIG_EM:
11869       case SIG_EM_E1:
11870       case SIG_EMWINK:
11871       case SIG_SF_FEATD:
11872       case SIG_SF_FEATDMF:
11873       case SIG_SF_FEATB:
11874       case SIG_SF:
11875       case SIG_SFWINK:
11876       case SIG_FXSLS:
11877       case SIG_FXSGS:
11878       case SIG_FXSKS:
11879       case SIG_FXOKS:
11880          dahdi_disable_ec(i);
11881          /* Diddle the battery for the zhone */
11882 #ifdef ZHONE_HACK
11883          dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
11884          usleep(1);
11885 #endif
11886          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
11887          dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
11888          break;
11889       case SIG_SS7:
11890       case SIG_PRI_LIB_HANDLE_CASES:
11891          dahdi_disable_ec(i);
11892          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
11893          break;
11894       default:
11895          ast_log(LOG_WARNING, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
11896          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
11897          return NULL;
11898       }
11899       break;
11900    case DAHDI_EVENT_POLARITY:
11901       switch (i->sig) {
11902       case SIG_FXSLS:
11903       case SIG_FXSKS:
11904       case SIG_FXSGS:
11905          /* We have already got a PR before the channel was
11906             created, but it wasn't handled. We need polarity
11907             to be REV for remote hangup detection to work.
11908             At least in Spain */
11909          callid_created = ast_callid_threadstorage_auto(&callid);
11910          if (i->hanguponpolarityswitch)
11911             i->polarity = POLARITY_REV;
11912          if (i->cid_start == CID_START_POLARITY || i->cid_start == CID_START_POLARITY_IN) {
11913             i->polarity = POLARITY_REV;
11914             ast_verb(2, "Starting post polarity "
11915                "CID detection on channel %d\n",
11916                i->channel);
11917             chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL, callid);
11918             if (!chan) {
11919                ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
11920             } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
11921                ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11922                ast_hangup(chan);
11923             }
11924          }
11925          ast_callid_threadstorage_auto_clean(callid, callid_created);
11926          break;
11927       default:
11928          ast_log(LOG_WARNING, "handle_init_event detected "
11929             "polarity reversal on non-FXO (SIG_FXS) "
11930             "interface %d\n", i->channel);
11931       }
11932       break;
11933    case DAHDI_EVENT_REMOVED: /* destroy channel, will actually do so in do_monitor */
11934       ast_log(LOG_NOTICE,
11935             "Got DAHDI_EVENT_REMOVED. Destroying channel %d\n",
11936             i->channel);
11937       return i;
11938    case DAHDI_EVENT_NEONMWI_ACTIVE:
11939       if (i->mwimonitor_neon) {
11940          notify_message(i->mailbox, 1);
11941          ast_log(LOG_NOTICE, "NEON MWI set for channel %d, mailbox %s \n", i->channel, i->mailbox);
11942       }
11943       break;
11944    case DAHDI_EVENT_NEONMWI_INACTIVE:
11945       if (i->mwimonitor_neon) {
11946          notify_message(i->mailbox, 0);
11947          ast_log(LOG_NOTICE, "NEON MWI cleared for channel %d, mailbox %s\n", i->channel, i->mailbox);
11948       }
11949       break;
11950    }
11951    return NULL;
11952 }
11953 
11954 static void monitor_pfds_clean(void *arg) {
11955    struct pollfd **pfds = arg;
11956    ast_free(*pfds);
11957 }
11958 
11959 static void *do_monitor(void *data)
11960 {
11961    int count, res, res2, spoint, pollres=0;
11962    struct dahdi_pvt *i;
11963    struct dahdi_pvt *last = NULL;
11964    struct dahdi_pvt *doomed;
11965    time_t thispass = 0, lastpass = 0;
11966    int found;
11967    char buf[1024];
11968    struct pollfd *pfds=NULL;
11969    int lastalloc = -1;
11970    /* This thread monitors all the frame relay interfaces which are not yet in use
11971       (and thus do not have a separate thread) indefinitely */
11972    /* From here on out, we die whenever asked */
11973 #if 0
11974    if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) {
11975       ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n");
11976       return NULL;
11977    }
11978    ast_debug(1, "Monitor starting...\n");
11979 #endif
11980    pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
11981 
11982    pthread_cleanup_push(monitor_pfds_clean, &pfds);
11983    for (;;) {
11984       /* Lock the interface list */
11985       ast_mutex_lock(&iflock);
11986       if (!pfds || (lastalloc != ifcount)) {
11987          if (pfds) {
11988             ast_free(pfds);
11989             pfds = NULL;
11990          }
11991          if (ifcount) {
11992             if (!(pfds = ast_calloc(1, ifcount * sizeof(*pfds)))) {
11993                ast_mutex_unlock(&iflock);
11994                return NULL;
11995             }
11996          }
11997          lastalloc = ifcount;
11998       }
11999       /* Build the stuff we're going to poll on, that is the socket of every
12000          dahdi_pvt that does not have an associated owner channel */
12001       count = 0;
12002       for (i = iflist; i; i = i->next) {
12003          ast_mutex_lock(&i->lock);
12004          if (pfds && (i->subs[SUB_REAL].dfd > -1) && i->sig && (!i->radio) && !(i->sig & SIG_MFCR2)) {
12005             if (analog_lib_handles(i->sig, i->radio, i->oprmode)) {
12006                struct analog_pvt *p = i->sig_pvt;
12007 
12008                if (!p) {
12009                   ast_log(LOG_ERROR, "No sig_pvt?\n");
12010                } else if (!p->owner && !p->subs[SUB_REAL].owner) {
12011                   /* This needs to be watched, as it lacks an owner */
12012                   pfds[count].fd = i->subs[SUB_REAL].dfd;
12013                   pfds[count].events = POLLPRI;
12014                   pfds[count].revents = 0;
12015                   /* Message waiting or r2 channels also get watched for reading */
12016                   if (i->cidspill || i->mwisendactive || i->mwimonitor_fsk || 
12017                      (i->cid_start == CID_START_DTMF_NOALERT && (i->sig == SIG_FXSLS || i->sig == SIG_FXSGS || i->sig == SIG_FXSKS))) {
12018                      pfds[count].events |= POLLIN;
12019                   }
12020                   count++;
12021                }
12022             } else {
12023                if (!i->owner && !i->subs[SUB_REAL].owner && !i->mwimonitoractive ) {
12024                   /* This needs to be watched, as it lacks an owner */
12025                   pfds[count].fd = i->subs[SUB_REAL].dfd;
12026                   pfds[count].events = POLLPRI;
12027                   pfds[count].revents = 0;
12028                   /* If we are monitoring for VMWI or sending CID, we need to
12029                      read from the channel as well */
12030                   if (i->cidspill || i->mwisendactive || i->mwimonitor_fsk ||
12031                      (i->cid_start == CID_START_DTMF_NOALERT && (i->sig == SIG_FXSLS || i->sig == SIG_FXSGS || i->sig == SIG_FXSKS))) {
12032                      pfds[count].events |= POLLIN;
12033                   }
12034                   count++;
12035                }
12036             }
12037          }
12038          ast_mutex_unlock(&i->lock);
12039       }
12040       /* Okay, now that we know what to do, release the interface lock */
12041       ast_mutex_unlock(&iflock);
12042 
12043       pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
12044       pthread_testcancel();
12045       /* Wait at least a second for something to happen */
12046       res = poll(pfds, count, 1000);
12047       pthread_testcancel();
12048       pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
12049 
12050       /* Okay, poll has finished.  Let's see what happened.  */
12051       if (res < 0) {
12052          if ((errno != EAGAIN) && (errno != EINTR))
12053             ast_log(LOG_WARNING, "poll return %d: %s\n", res, strerror(errno));
12054          continue;
12055       }
12056       /* Alright, lock the interface list again, and let's look and see what has
12057          happened */
12058       ast_mutex_lock(&iflock);
12059       found = 0;
12060       spoint = 0;
12061       lastpass = thispass;
12062       thispass = time(NULL);
12063       doomed = NULL;
12064       for (i = iflist;; i = i->next) {
12065          if (doomed) {
12066             int res;
12067             res = dahdi_destroy_channel_bynum(doomed->channel);
12068             if (res != RESULT_SUCCESS) {
12069                ast_log(LOG_WARNING, "Couldn't find channel to destroy, hopefully another destroy operation just happened.\n");
12070             }
12071             doomed = NULL;
12072          }
12073          if (!i) {
12074             break;
12075          }
12076 
12077          if (thispass != lastpass) {
12078             if (!found && ((i == last) || ((i == iflist) && !last))) {
12079                last = i;
12080                if (last) {
12081                   struct analog_pvt *analog_p = last->sig_pvt;
12082                   /* Only allow MWI to be initiated on a quiescent fxs port */
12083                   if (analog_p
12084                      && !last->mwisendactive
12085                      && (last->sig & __DAHDI_SIG_FXO)
12086                      && !analog_p->fxsoffhookstate
12087                      && !last->owner
12088                      && !ast_strlen_zero(last->mailbox)
12089                      && (thispass - analog_p->onhooktime > 3)) {
12090                      res = has_voicemail(last);
12091                      if (analog_p->msgstate != res) {
12092                         /* Set driver resources for signalling VMWI */
12093                         res2 = ioctl(last->subs[SUB_REAL].dfd, DAHDI_VMWI, &res);
12094                         if (res2) {
12095                            /* TODO: This message will ALWAYS be generated on some cards; any way to restrict it to those cards where it is interesting? */
12096                            ast_debug(3, "Unable to control message waiting led on channel %d: %s\n", last->channel, strerror(errno));
12097                         }
12098                         /* If enabled for FSK spill then initiate it */
12099                         if (mwi_send_init(last)) {
12100                            ast_log(LOG_WARNING, "Unable to initiate mwi send sequence on channel %d\n", last->channel);
12101                         }
12102                         analog_p->msgstate = res;
12103                         found ++;
12104                      }
12105                   }
12106                   last = last->next;
12107                }
12108             }
12109          }
12110          if ((i->subs[SUB_REAL].dfd > -1) && i->sig) {
12111             if (i->radio && !i->owner)
12112             {
12113                res = dahdi_get_event(i->subs[SUB_REAL].dfd);
12114                if (res)
12115                {
12116                   ast_debug(1, "Monitor doohicky got event %s on radio channel %d\n", event2str(res), i->channel);
12117                   /* Don't hold iflock while handling init events */
12118                   ast_mutex_unlock(&iflock);
12119                   if (analog_lib_handles(i->sig, i->radio, i->oprmode))
12120                      doomed = (struct dahdi_pvt *) analog_handle_init_event(i->sig_pvt, dahdievent_to_analogevent(res));
12121                   else
12122                      doomed = handle_init_event(i, res);
12123                   ast_mutex_lock(&iflock);
12124                }
12125                continue;
12126             }
12127             pollres = ast_fdisset(pfds, i->subs[SUB_REAL].dfd, count, &spoint);
12128             if (pollres & POLLIN) {
12129                if (i->owner || i->subs[SUB_REAL].owner) {
12130 #ifdef HAVE_PRI
12131                   if (!i->pri)
12132 #endif
12133                      ast_log(LOG_WARNING, "Whoa....  I'm owned but found (%d) in read...\n", i->subs[SUB_REAL].dfd);
12134                   continue;
12135                }
12136                if (!i->mwimonitor_fsk && !i->mwisendactive  && i->cid_start != CID_START_DTMF_NOALERT) {
12137                   ast_log(LOG_WARNING, "Whoa....  I'm not looking for MWI or sending MWI but am reading (%d)...\n", i->subs[SUB_REAL].dfd);
12138                   continue;
12139                }
12140                res = read(i->subs[SUB_REAL].dfd, buf, sizeof(buf));
12141                if (res > 0) {
12142                   if (i->mwimonitor_fsk) {
12143                      if (calc_energy((unsigned char *) buf, res, AST_LAW(i)) > mwilevel) {
12144                         pthread_attr_t attr;
12145                         pthread_t threadid;
12146                         struct mwi_thread_data *mtd;
12147 
12148                         pthread_attr_init(&attr);
12149                         pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
12150 
12151                         ast_debug(1, "Maybe some MWI on port %d!\n", i->channel);
12152                         if ((mtd = ast_calloc(1, sizeof(*mtd)))) {
12153                            mtd->pvt = i;
12154                            memcpy(mtd->buf, buf, res);
12155                            mtd->len = res;
12156                            i->mwimonitoractive = 1;
12157                            if (ast_pthread_create_background(&threadid, &attr, mwi_thread, mtd)) {
12158                               ast_log(LOG_WARNING, "Unable to start mwi thread on channel %d\n", i->channel);
12159                               i->mwimonitoractive = 0;
12160                               ast_free(mtd);
12161                            }
12162                         }
12163                      }
12164                   /* If configured to check for a DTMF CID spill that comes without alert (e.g no polarity reversal) */
12165                   } else if (i->cid_start == CID_START_DTMF_NOALERT) {
12166                      int energy;
12167                      struct timeval now;
12168                      /* State machine dtmfcid_holdoff_state allows for the line to settle
12169                       * before checking agin for dtmf energy.  Presently waits for 500 mS before checking again 
12170                      */
12171                      if (1 == i->dtmfcid_holdoff_state) {
12172                         gettimeofday(&i->dtmfcid_delay, NULL);
12173                         i->dtmfcid_holdoff_state = 2;
12174                      } else if (2 == i->dtmfcid_holdoff_state) {
12175                         gettimeofday(&now, NULL);
12176                         if ((int)(now.tv_sec - i->dtmfcid_delay.tv_sec) * 1000000 + (int)now.tv_usec - (int)i->dtmfcid_delay.tv_usec > 500000) {
12177                            i->dtmfcid_holdoff_state = 0;
12178                         }
12179                      } else {
12180                         energy = calc_energy((unsigned char *) buf, res, AST_LAW(i));
12181                         if (!i->mwisendactive && energy > dtmfcid_level) {
12182                            pthread_t threadid;
12183                            struct ast_channel *chan;
12184                            ast_mutex_unlock(&iflock);
12185                            if (analog_lib_handles(i->sig, i->radio, i->oprmode)) {
12186                               /* just in case this event changes or somehow destroys a channel, set doomed here too */
12187                               doomed = analog_handle_init_event(i->sig_pvt, ANALOG_EVENT_DTMFCID);  
12188                               i->dtmfcid_holdoff_state = 1;
12189                            } else {
12190                               struct ast_callid *callid = NULL;
12191                               int callid_created = ast_callid_threadstorage_auto(&callid);
12192                               chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL, callid);
12193                               if (!chan) {
12194                                  ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
12195                               } else {
12196                                  res = ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan);
12197                                  if (res) {
12198                                     ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
12199                                     ast_hangup(chan);
12200                                  } else {
12201                                     i->dtmfcid_holdoff_state = 1;
12202                                  }
12203                               }
12204                               ast_callid_threadstorage_auto_clean(callid, callid_created);
12205                            }
12206                            ast_mutex_lock(&iflock);
12207                         }
12208                      }
12209                   }
12210                   if (i->mwisendactive) {
12211                      mwi_send_process_buffer(i, res);
12212                   }
12213                } else {
12214                   ast_log(LOG_WARNING, "Read failed with %d: %s\n", res, strerror(errno));
12215                }
12216             }
12217             if (pollres & POLLPRI) {
12218                if (i->owner || i->subs[SUB_REAL].owner) {
12219 #ifdef HAVE_PRI
12220                   if (!i->pri)
12221 #endif
12222                      ast_log(LOG_WARNING, "Whoa....  I'm owned but found (%d)...\n", i->subs[SUB_REAL].dfd);
12223                   continue;
12224                }
12225                res = dahdi_get_event(i->subs[SUB_REAL].dfd);
12226                ast_debug(1, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel);
12227                /* Don't hold iflock while handling init events */
12228                ast_mutex_unlock(&iflock);
12229                if (0 == i->mwisendactive || 0 == mwi_send_process_event(i, res)) {
12230                   if (analog_lib_handles(i->sig, i->radio, i->oprmode))
12231                      doomed = (struct dahdi_pvt *) analog_handle_init_event(i->sig_pvt, dahdievent_to_analogevent(res));
12232                   else
12233                      doomed = handle_init_event(i, res);
12234                }
12235                ast_mutex_lock(&iflock);
12236             }
12237          }
12238       }
12239       ast_mutex_unlock(&iflock);
12240    }
12241    /* Never reached */
12242    pthread_cleanup_pop(1);
12243    return NULL;
12244 
12245 }
12246 
12247 static int restart_monitor(void)
12248 {
12249    /* If we're supposed to be stopped -- stay stopped */
12250    if (monitor_thread == AST_PTHREADT_STOP)
12251       return 0;
12252    ast_mutex_lock(&monlock);
12253    if (monitor_thread == pthread_self()) {
12254       ast_mutex_unlock(&monlock);
12255       ast_log(LOG_WARNING, "Cannot kill myself\n");
12256       return -1;
12257    }
12258    if (monitor_thread != AST_PTHREADT_NULL) {
12259       /* Wake up the thread */
12260       pthread_kill(monitor_thread, SIGURG);
12261    } else {
12262       /* Start a new monitor */
12263       if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) {
12264          ast_mutex_unlock(&monlock);
12265          ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
12266          return -1;
12267       }
12268    }
12269    ast_mutex_unlock(&monlock);
12270    return 0;
12271 }
12272 
12273 #if defined(HAVE_PRI)
12274 static int pri_resolve_span(int *span, int channel, int offset, struct dahdi_spaninfo *si)
12275 {
12276    int x;
12277    int trunkgroup;
12278    /* Get appropriate trunk group if there is one */
12279    trunkgroup = pris[*span].mastertrunkgroup;
12280    if (trunkgroup) {
12281       /* Select a specific trunk group */
12282       for (x = 0; x < NUM_SPANS; x++) {
12283          if (pris[x].pri.trunkgroup == trunkgroup) {
12284             *span = x;
12285             return 0;
12286          }
12287       }
12288       ast_log(LOG_WARNING, "Channel %d on span %d configured to use nonexistent trunk group %d\n", channel, *span, trunkgroup);
12289       *span = -1;
12290    } else {
12291       if (pris[*span].pri.trunkgroup) {
12292          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);
12293          *span = -1;
12294       } else if (pris[*span].mastertrunkgroup) {
12295          ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is already part of trunk group %d\n", *span, pris[*span].mastertrunkgroup);
12296          *span = -1;
12297       } else {
12298          if (si->totalchans == 31) {
12299             /* E1 */
12300             pris[*span].dchannels[0] = 16 + offset;
12301          } else if (si->totalchans == 24) {
12302             /* T1 or J1 */
12303             pris[*span].dchannels[0] = 24 + offset;
12304          } else if (si->totalchans == 3) {
12305             /* BRI */
12306             pris[*span].dchannels[0] = 3 + offset;
12307          } else {
12308             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);
12309             *span = -1;
12310             return 0;
12311          }
12312          pris[*span].pri.span = *span + 1;
12313       }
12314    }
12315    return 0;
12316 }
12317 #endif   /* defined(HAVE_PRI) */
12318 
12319 #if defined(HAVE_PRI)
12320 static int pri_create_trunkgroup(int trunkgroup, int *channels)
12321 {
12322    struct dahdi_spaninfo si;
12323    struct dahdi_params p;
12324    int fd;
12325    int span;
12326    int ospan=0;
12327    int x,y;
12328    for (x = 0; x < NUM_SPANS; x++) {
12329       if (pris[x].pri.trunkgroup == trunkgroup) {
12330          ast_log(LOG_WARNING, "Trunk group %d already exists on span %d, Primary d-channel %d\n", trunkgroup, x + 1, pris[x].dchannels[0]);
12331          return -1;
12332       }
12333    }
12334    for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
12335       if (!channels[y])
12336          break;
12337       memset(&si, 0, sizeof(si));
12338       memset(&p, 0, sizeof(p));
12339       fd = open("/dev/dahdi/channel", O_RDWR);
12340       if (fd < 0) {
12341          ast_log(LOG_WARNING, "Failed to open channel: %s\n", strerror(errno));
12342          return -1;
12343       }
12344       x = channels[y];
12345       if (ioctl(fd, DAHDI_SPECIFY, &x)) {
12346          ast_log(LOG_WARNING, "Failed to specify channel %d: %s\n", channels[y], strerror(errno));
12347          close(fd);
12348          return -1;
12349       }
12350       if (ioctl(fd, DAHDI_GET_PARAMS, &p)) {
12351          ast_log(LOG_WARNING, "Failed to get channel parameters for channel %d: %s\n", channels[y], strerror(errno));
12352          close(fd);
12353          return -1;
12354       }
12355       if (ioctl(fd, DAHDI_SPANSTAT, &si)) {
12356          ast_log(LOG_WARNING, "Failed go get span information on channel %d (span %d): %s\n", channels[y], p.spanno, strerror(errno));
12357          close(fd);
12358          return -1;
12359       }
12360       span = p.spanno - 1;
12361       if (pris[span].pri.trunkgroup) {
12362          ast_log(LOG_WARNING, "Span %d is already provisioned for trunk group %d\n", span + 1, pris[span].pri.trunkgroup);
12363          close(fd);
12364          return -1;
12365       }
12366       if (pris[span].pri.pvts[0]) {
12367          ast_log(LOG_WARNING, "Span %d is already provisioned with channels (implicit PRI maybe?)\n", span + 1);
12368          close(fd);
12369          return -1;
12370       }
12371       if (!y) {
12372          pris[span].pri.trunkgroup = trunkgroup;
12373          ospan = span;
12374       }
12375       pris[ospan].dchannels[y] = channels[y];
12376       pris[span].pri.span = span + 1;
12377       close(fd);
12378    }
12379    return 0;
12380 }
12381 #endif   /* defined(HAVE_PRI) */
12382 
12383 #if defined(HAVE_PRI)
12384 static int pri_create_spanmap(int span, int trunkgroup, int logicalspan)
12385 {
12386    if (pris[span].mastertrunkgroup) {
12387       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);
12388       return -1;
12389    }
12390    pris[span].mastertrunkgroup = trunkgroup;
12391    pris[span].prilogicalspan = logicalspan;
12392    return 0;
12393 }
12394 #endif   /* defined(HAVE_PRI) */
12395 
12396 #if defined(HAVE_SS7)
12397 static unsigned int parse_pointcode(const char *pcstring)
12398 {
12399    unsigned int code1, code2, code3;
12400    int numvals;
12401 
12402    numvals = sscanf(pcstring, "%30d-%30d-%30d", &code1, &code2, &code3);
12403    if (numvals == 1)
12404       return code1;
12405    if (numvals == 3)
12406       return (code1 << 16) | (code2 << 8) | code3;
12407 
12408    return 0;
12409 }
12410 #endif   /* defined(HAVE_SS7) */
12411 
12412 #if defined(HAVE_SS7)
12413 static struct dahdi_ss7 * ss7_resolve_linkset(int linkset)
12414 {
12415    if ((linkset < 0) || (linkset >= NUM_SPANS))
12416       return NULL;
12417    else
12418       return &linksets[linkset - 1];
12419 }
12420 #endif   /* defined(HAVE_SS7) */
12421 
12422 #ifdef HAVE_OPENR2
12423 static void dahdi_r2_destroy_links(void)
12424 {
12425    int i = 0;
12426    if (!r2links) {
12427       return;
12428    }
12429    for (; i < r2links_count; i++) {
12430       if (r2links[i]->r2master != AST_PTHREADT_NULL) {
12431          pthread_cancel(r2links[i]->r2master);
12432          pthread_join(r2links[i]->r2master, NULL);
12433          openr2_context_delete(r2links[i]->protocol_context);
12434       }
12435       ast_free(r2links[i]);
12436    }
12437    ast_free(r2links);
12438    r2links = NULL;
12439    r2links_count = 0;
12440 }
12441 
12442 /* This is an artificial convenient capacity, to keep at most a full E1 of channels in a single thread */
12443 #define R2_LINK_CAPACITY 30
12444 static struct dahdi_mfcr2 *dahdi_r2_get_link(const struct dahdi_chan_conf *conf)
12445 {
12446    struct dahdi_mfcr2 *new_r2link = NULL;
12447    struct dahdi_mfcr2 **new_r2links = NULL;
12448 
12449    /* Only create a new R2 link if 
12450       1. This is the first link requested
12451       2. Configuration changed 
12452       3. We got more channels than supported per link */
12453    if (!r2links_count ||
12454        memcmp(&conf->mfcr2, &r2links[r2links_count - 1]->conf, sizeof(conf->mfcr2)) ||
12455       (r2links[r2links_count - 1]->numchans == R2_LINK_CAPACITY)) {
12456       new_r2link = ast_calloc(1, sizeof(**r2links));
12457       if (!new_r2link) {
12458          ast_log(LOG_ERROR, "Cannot allocate R2 link!\n");
12459          return NULL;
12460       }
12461       new_r2links = ast_realloc(r2links, ((r2links_count + 1) * sizeof(*r2links)));
12462       if (!new_r2links) {
12463          ast_log(LOG_ERROR, "Cannot allocate R2 link!\n");
12464          ast_free(new_r2link);
12465          return NULL;
12466       }
12467       r2links = new_r2links;
12468       new_r2link->r2master = AST_PTHREADT_NULL;
12469       r2links[r2links_count] = new_r2link;
12470       r2links_count++;
12471       ast_debug(1, "Created new R2 link!\n");
12472    }
12473    return r2links[r2links_count - 1];
12474 }
12475 
12476 static int dahdi_r2_set_context(struct dahdi_mfcr2 *r2_link, const struct dahdi_chan_conf *conf)
12477 {
12478    char tmplogdir[] = "/tmp";
12479    char logdir[OR2_MAX_PATH];
12480    int threshold = 0;
12481    int snres = 0;
12482    r2_link->protocol_context = openr2_context_new(NULL, &dahdi_r2_event_iface,
12483          &dahdi_r2_transcode_iface, conf->mfcr2.variant, conf->mfcr2.max_ani,
12484          conf->mfcr2.max_dnis);
12485    if (!r2_link->protocol_context) {
12486       return -1;
12487    }
12488    openr2_context_set_log_level(r2_link->protocol_context, conf->mfcr2.loglevel);
12489    openr2_context_set_ani_first(r2_link->protocol_context, conf->mfcr2.get_ani_first);
12490 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
12491    openr2_context_set_skip_category_request(r2_link->protocol_context, conf->mfcr2.skip_category_request);
12492 #endif
12493    openr2_context_set_mf_threshold(r2_link->protocol_context, threshold);
12494    openr2_context_set_mf_back_timeout(r2_link->protocol_context, conf->mfcr2.mfback_timeout);
12495    openr2_context_set_metering_pulse_timeout(r2_link->protocol_context, conf->mfcr2.metering_pulse_timeout);
12496    openr2_context_set_double_answer(r2_link->protocol_context, conf->mfcr2.double_answer);
12497    openr2_context_set_immediate_accept(r2_link->protocol_context, conf->mfcr2.immediate_accept);
12498 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2
12499    openr2_context_set_dtmf_dialing(r2_link->protocol_context, conf->mfcr2.dtmf_dialing, conf->mfcr2.dtmf_time_on, conf->mfcr2.dtmf_time_off);
12500    openr2_context_set_dtmf_detection(r2_link->protocol_context, conf->mfcr2.dtmf_detection);
12501 #endif
12502 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 3
12503    openr2_context_set_dtmf_detection_end_timeout(r2_link->protocol_context, conf->mfcr2.dtmf_end_timeout);
12504 #endif
12505    if (ast_strlen_zero(conf->mfcr2.logdir)) {
12506       if (openr2_context_set_log_directory(r2_link->protocol_context, tmplogdir)) {
12507          ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir);
12508       }
12509    } else {
12510       snres = snprintf(logdir, sizeof(logdir), "%s/%s/%s", ast_config_AST_LOG_DIR, "mfcr2", conf->mfcr2.logdir);
12511       if (snres >= sizeof(logdir)) {
12512          ast_log(LOG_ERROR, "MFC/R2 logging directory truncated, using %s\n", tmplogdir);
12513          if (openr2_context_set_log_directory(r2_link->protocol_context, tmplogdir)) {
12514             ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir);
12515          }
12516       } else {
12517          if (openr2_context_set_log_directory(r2_link->protocol_context, logdir)) {
12518             ast_log(LOG_ERROR, "Failed setting MFC/R2 log directory %s\n", logdir);
12519          }
12520       }
12521    }
12522    if (!ast_strlen_zero(conf->mfcr2.r2proto_file)) {
12523       if (openr2_context_configure_from_advanced_file(r2_link->protocol_context, conf->mfcr2.r2proto_file)) {
12524          ast_log(LOG_ERROR, "Failed to configure r2context from advanced configuration file %s\n", conf->mfcr2.r2proto_file);
12525       }
12526    }
12527    /* Save the configuration used to setup this link */
12528    memcpy(&r2_link->conf, conf, sizeof(r2_link->conf));
12529    return 0;
12530 }
12531 #endif
12532 
12533 /* converts a DAHDI sigtype to signalling as can be configured from
12534  * chan_dahdi.conf.
12535  * While both have basically the same values, this will later be the
12536  * place to add filters and sanity checks
12537  */
12538 static int sigtype_to_signalling(int sigtype)
12539 {
12540    return sigtype;
12541 }
12542 
12543 /*!
12544  * \internal
12545  * \brief Get file name and channel number from (subdir,number)
12546  *
12547  * \param subdir name of the subdirectory under /dev/dahdi/
12548  * \param channel name of device file under /dev/dahdi/<subdir>/
12549  * \param path buffer to put file name in
12550  * \param pathlen maximal length of path
12551  *
12552  * \retval minor number of dahdi channel.
12553  * \retval -errno on error.
12554  */
12555 static int device2chan(const char *subdir, int channel, char *path, int pathlen)
12556 {
12557    struct stat stbuf;
12558    int      num;
12559 
12560    snprintf(path, pathlen, "/dev/dahdi/%s/%d", subdir, channel);
12561    if (stat(path, &stbuf) < 0) {
12562       ast_log(LOG_ERROR, "stat(%s) failed: %s\n", path, strerror(errno));
12563       return -errno;
12564    }
12565    if (!S_ISCHR(stbuf.st_mode)) {
12566       ast_log(LOG_ERROR, "%s: Not a character device file\n", path);
12567       return -EINVAL;
12568    }
12569    num = minor(stbuf.st_rdev);
12570    ast_debug(1, "%s -> %d\n", path, num);
12571    return num;
12572 
12573 }
12574 
12575 /*!
12576  * \internal
12577  * \brief Initialize/create a channel interface.
12578  *
12579  * \param channel Channel interface number to initialize/create.
12580  * \param conf Configuration parameters to initialize interface with.
12581  * \param reloading What we are doing now:
12582  * 0 - initial module load,
12583  * 1 - module reload,
12584  * 2 - module restart
12585  *
12586  * \retval Interface-pointer initialized/created
12587  * \retval NULL if error
12588  */
12589 static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf, int reloading)
12590 {
12591    /* Make a dahdi_pvt structure for this interface */
12592    struct dahdi_pvt *tmp;/*!< Current channel structure initializing */
12593    char fn[80];
12594    struct dahdi_bufferinfo bi;
12595 
12596    int res;
12597 #if defined(HAVE_PRI)
12598    int span = 0;
12599 #endif   /* defined(HAVE_PRI) */
12600    int here = 0;/*!< TRUE if the channel interface already exists. */
12601    int x;
12602    struct analog_pvt *analog_p = NULL;
12603    struct dahdi_params p;
12604 #if defined(HAVE_PRI)
12605    struct dahdi_spaninfo si;
12606    struct sig_pri_chan *pri_chan = NULL;
12607 #endif   /* defined(HAVE_PRI) */
12608 #if defined(HAVE_SS7)
12609    struct sig_ss7_chan *ss7_chan = NULL;
12610 #endif   /* defined(HAVE_SS7) */
12611 
12612    /* Search channel interface list to see if it already exists. */
12613    for (tmp = iflist; tmp; tmp = tmp->next) {
12614       if (!tmp->destroy) {
12615          if (tmp->channel == channel) {
12616             /* The channel interface already exists. */
12617             here = 1;
12618             break;
12619          }
12620          if (tmp->channel > channel) {
12621             /* No way it can be in the sorted list. */
12622             tmp = NULL;
12623             break;
12624          }
12625       }
12626    }
12627 
12628    if (!here && reloading != 1) {
12629       tmp = ast_calloc(1, sizeof(*tmp));
12630       if (!tmp) {
12631          return NULL;
12632       }
12633       tmp->cc_params = ast_cc_config_params_init();
12634       if (!tmp->cc_params) {
12635          ast_free(tmp);
12636          return NULL;
12637       }
12638       ast_mutex_init(&tmp->lock);
12639       ifcount++;
12640       for (x = 0; x < 3; x++)
12641          tmp->subs[x].dfd = -1;
12642       tmp->channel = channel;
12643       tmp->priindication_oob = conf->chan.priindication_oob;
12644    }
12645 
12646    if (tmp) {
12647       int chan_sig = conf->chan.sig;
12648 
12649       /* If there are variables in tmp before it is updated to match the new config, clear them */
12650       if (reloading && tmp->vars) {
12651          ast_variables_destroy(tmp->vars);
12652          tmp->vars = NULL;
12653       }
12654 
12655       if (!here) {
12656          /* Can only get here if this is a new channel interface being created. */
12657          if ((channel != CHAN_PSEUDO)) {
12658             int count = 0;
12659 
12660             snprintf(fn, sizeof(fn), "%d", channel);
12661             /* Open non-blocking */
12662             tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
12663             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 */
12664                usleep(1);
12665                tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
12666                count++;
12667             }
12668             /* Allocate a DAHDI structure */
12669             if (tmp->subs[SUB_REAL].dfd < 0) {
12670                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);
12671                destroy_dahdi_pvt(tmp);
12672                return NULL;
12673             }
12674             memset(&p, 0, sizeof(p));
12675             res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
12676             if (res < 0) {
12677                ast_log(LOG_ERROR, "Unable to get parameters: %s\n", strerror(errno));
12678                destroy_dahdi_pvt(tmp);
12679                return NULL;
12680             }
12681             if (conf->is_sig_auto)
12682                chan_sig = sigtype_to_signalling(p.sigtype);
12683             if (p.sigtype != (chan_sig & 0x3ffff)) {
12684                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));
12685                destroy_dahdi_pvt(tmp);
12686                return NULL;
12687             }
12688             tmp->law_default = p.curlaw;
12689             tmp->law = p.curlaw;
12690             tmp->span = p.spanno;
12691 #if defined(HAVE_PRI)
12692             span = p.spanno - 1;
12693 #endif   /* defined(HAVE_PRI) */
12694          } else {
12695             chan_sig = 0;
12696          }
12697          tmp->sig = chan_sig;
12698          tmp->outsigmod = conf->chan.outsigmod;
12699 
12700          if (analog_lib_handles(chan_sig, tmp->radio, tmp->oprmode)) {
12701             analog_p = analog_new(dahdisig_to_analogsig(chan_sig), tmp);
12702             if (!analog_p) {
12703                destroy_dahdi_pvt(tmp);
12704                return NULL;
12705             }
12706             tmp->sig_pvt = analog_p;
12707          }
12708 #if defined(HAVE_SS7)
12709          if (chan_sig == SIG_SS7) {
12710             struct dahdi_ss7 *ss7;
12711             int clear = 0;
12712 
12713             if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &clear)) {
12714                ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
12715                destroy_dahdi_pvt(tmp);
12716                return NULL;
12717             }
12718 
12719             ss7 = ss7_resolve_linkset(cur_linkset);
12720             if (!ss7) {
12721                ast_log(LOG_ERROR, "Unable to find linkset %d\n", cur_linkset);
12722                destroy_dahdi_pvt(tmp);
12723                return NULL;
12724             }
12725             ss7->ss7.span = cur_linkset;
12726             if (cur_cicbeginswith < 0) {
12727                ast_log(LOG_ERROR, "Need to set cicbeginswith for the channels!\n");
12728                destroy_dahdi_pvt(tmp);
12729                return NULL;
12730             }
12731             ss7_chan = sig_ss7_chan_new(tmp, &ss7->ss7);
12732             if (!ss7_chan) {
12733                destroy_dahdi_pvt(tmp);
12734                return NULL;
12735             }
12736             tmp->sig_pvt = ss7_chan;
12737             tmp->ss7 = &ss7->ss7;
12738 
12739             ss7_chan->channel = tmp->channel;
12740             ss7_chan->cic = cur_cicbeginswith++;
12741 
12742             /* DB: Add CIC's DPC information */
12743             ss7_chan->dpc = cur_defaultdpc;
12744 
12745             ss7->ss7.pvts[ss7->ss7.numchans++] = ss7_chan;
12746 
12747             ast_copy_string(ss7->ss7.internationalprefix, conf->ss7.ss7.internationalprefix, sizeof(ss7->ss7.internationalprefix));
12748             ast_copy_string(ss7->ss7.nationalprefix, conf->ss7.ss7.nationalprefix, sizeof(ss7->ss7.nationalprefix));
12749             ast_copy_string(ss7->ss7.subscriberprefix, conf->ss7.ss7.subscriberprefix, sizeof(ss7->ss7.subscriberprefix));
12750             ast_copy_string(ss7->ss7.unknownprefix, conf->ss7.ss7.unknownprefix, sizeof(ss7->ss7.unknownprefix));
12751 
12752             ss7->ss7.called_nai = conf->ss7.ss7.called_nai;
12753             ss7->ss7.calling_nai = conf->ss7.ss7.calling_nai;
12754          }
12755 #endif   /* defined(HAVE_SS7) */
12756 #ifdef HAVE_OPENR2
12757          if (chan_sig == SIG_MFCR2) {
12758             struct dahdi_mfcr2 *r2_link;
12759             r2_link = dahdi_r2_get_link(conf);
12760             if (!r2_link) {
12761                ast_log(LOG_WARNING, "Cannot get another R2 DAHDI context!\n");
12762                destroy_dahdi_pvt(tmp);
12763                return NULL;
12764             }
12765             if (!r2_link->protocol_context && dahdi_r2_set_context(r2_link, conf)) {
12766                ast_log(LOG_ERROR, "Cannot create OpenR2 protocol context.\n");
12767                destroy_dahdi_pvt(tmp);
12768                return NULL;
12769             }
12770             if (r2_link->numchans == ARRAY_LEN(r2_link->pvts)) {
12771                ast_log(LOG_ERROR, "Cannot add more channels to this link!\n");
12772                destroy_dahdi_pvt(tmp);
12773                return NULL;
12774             }
12775             r2_link->pvts[r2_link->numchans++] = tmp;
12776             tmp->r2chan = openr2_chan_new_from_fd(r2_link->protocol_context,
12777                                         tmp->subs[SUB_REAL].dfd,
12778                                         NULL, NULL);
12779             if (!tmp->r2chan) {
12780                openr2_liberr_t err = openr2_context_get_last_error(r2_link->protocol_context);
12781                ast_log(LOG_ERROR, "Cannot create OpenR2 channel: %s\n", openr2_context_error_string(err));
12782                destroy_dahdi_pvt(tmp);
12783                return NULL;
12784             }
12785             tmp->mfcr2 = r2_link;
12786             if (conf->mfcr2.call_files) {
12787                openr2_chan_enable_call_files(tmp->r2chan);
12788             }
12789             openr2_chan_set_client_data(tmp->r2chan, tmp);
12790             /* cast seems to be needed to get rid of the annoying warning regarding format attribute  */
12791             openr2_chan_set_logging_func(tmp->r2chan, (openr2_logging_func_t)dahdi_r2_on_chan_log);
12792             openr2_chan_set_log_level(tmp->r2chan, conf->mfcr2.loglevel);
12793             tmp->mfcr2_category = conf->mfcr2.category;
12794             tmp->mfcr2_charge_calls = conf->mfcr2.charge_calls;
12795             tmp->mfcr2_allow_collect_calls = conf->mfcr2.allow_collect_calls;
12796             tmp->mfcr2_forced_release = conf->mfcr2.forced_release;
12797             tmp->mfcr2_accept_on_offer = conf->mfcr2.accept_on_offer;
12798             tmp->mfcr2call = 0;
12799             tmp->mfcr2_dnis_index = 0;
12800             tmp->mfcr2_ani_index = 0;
12801          }
12802 #endif
12803 #ifdef HAVE_PRI
12804          if (dahdi_sig_pri_lib_handles(chan_sig)) {
12805             int offset;
12806             int matchesdchan;
12807             int x,y;
12808             int myswitchtype = 0;
12809 
12810             offset = 0;
12811             if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &offset)) {
12812                ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
12813                destroy_dahdi_pvt(tmp);
12814                return NULL;
12815             }
12816             if (span >= NUM_SPANS) {
12817                ast_log(LOG_ERROR, "Channel %d does not lie on a span I know of (%d)\n", channel, span);
12818                destroy_dahdi_pvt(tmp);
12819                return NULL;
12820             } else {
12821                si.spanno = 0;
12822                if (ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SPANSTAT,&si) == -1) {
12823                   ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno));
12824                   destroy_dahdi_pvt(tmp);
12825                   return NULL;
12826                }
12827                /* Store the logical span first based upon the real span */
12828                tmp->logicalspan = pris[span].prilogicalspan;
12829                pri_resolve_span(&span, channel, (channel - p.chanpos), &si);
12830                if (span < 0) {
12831                   ast_log(LOG_WARNING, "Channel %d: Unable to find locate channel/trunk group!\n", channel);
12832                   destroy_dahdi_pvt(tmp);
12833                   return NULL;
12834                }
12835                myswitchtype = conf->pri.pri.switchtype;
12836                /* Make sure this isn't a d-channel */
12837                matchesdchan=0;
12838                for (x = 0; x < NUM_SPANS; x++) {
12839                   for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
12840                      if (pris[x].dchannels[y] == tmp->channel) {
12841                         matchesdchan = 1;
12842                         break;
12843                      }
12844                   }
12845                }
12846                if (!matchesdchan) {
12847                   if (pris[span].pri.nodetype && (pris[span].pri.nodetype != conf->pri.pri.nodetype)) {
12848                      ast_log(LOG_ERROR, "Span %d is already a %s node\n", span + 1, pri_node2str(pris[span].pri.nodetype));
12849                      destroy_dahdi_pvt(tmp);
12850                      return NULL;
12851                   }
12852                   if (pris[span].pri.switchtype && (pris[span].pri.switchtype != myswitchtype)) {
12853                      ast_log(LOG_ERROR, "Span %d is already a %s switch\n", span + 1, pri_switch2str(pris[span].pri.switchtype));
12854                      destroy_dahdi_pvt(tmp);
12855                      return NULL;
12856                   }
12857                   if ((pris[span].pri.dialplan) && (pris[span].pri.dialplan != conf->pri.pri.dialplan)) {
12858                      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));
12859                      destroy_dahdi_pvt(tmp);
12860                      return NULL;
12861                   }
12862                   if (!ast_strlen_zero(pris[span].pri.idledial) && strcmp(pris[span].pri.idledial, conf->pri.pri.idledial)) {
12863                      ast_log(LOG_ERROR, "Span %d already has idledial '%s'.\n", span + 1, conf->pri.pri.idledial);
12864                      destroy_dahdi_pvt(tmp);
12865                      return NULL;
12866                   }
12867                   if (!ast_strlen_zero(pris[span].pri.idleext) && strcmp(pris[span].pri.idleext, conf->pri.pri.idleext)) {
12868                      ast_log(LOG_ERROR, "Span %d already has idleext '%s'.\n", span + 1, conf->pri.pri.idleext);
12869                      destroy_dahdi_pvt(tmp);
12870                      return NULL;
12871                   }
12872                   if (pris[span].pri.minunused && (pris[span].pri.minunused != conf->pri.pri.minunused)) {
12873                      ast_log(LOG_ERROR, "Span %d already has minunused of %d.\n", span + 1, conf->pri.pri.minunused);
12874                      destroy_dahdi_pvt(tmp);
12875                      return NULL;
12876                   }
12877                   if (pris[span].pri.minidle && (pris[span].pri.minidle != conf->pri.pri.minidle)) {
12878                      ast_log(LOG_ERROR, "Span %d already has minidle of %d.\n", span + 1, conf->pri.pri.minidle);
12879                      destroy_dahdi_pvt(tmp);
12880                      return NULL;
12881                   }
12882                   if (pris[span].pri.numchans >= ARRAY_LEN(pris[span].pri.pvts)) {
12883                      ast_log(LOG_ERROR, "Unable to add channel %d: Too many channels in trunk group %d!\n", channel,
12884                         pris[span].pri.trunkgroup);
12885                      destroy_dahdi_pvt(tmp);
12886                      return NULL;
12887                   }
12888 
12889                   pri_chan = sig_pri_chan_new(tmp, &pris[span].pri, tmp->logicalspan, p.chanpos, pris[span].mastertrunkgroup);
12890                   if (!pri_chan) {
12891                      destroy_dahdi_pvt(tmp);
12892                      return NULL;
12893                   }
12894                   tmp->sig_pvt = pri_chan;
12895                   tmp->pri = &pris[span].pri;
12896 
12897                   tmp->priexclusive = conf->chan.priexclusive;
12898 
12899                   if (!tmp->pri->cc_params) {
12900                      tmp->pri->cc_params = ast_cc_config_params_init();
12901                      if (!tmp->pri->cc_params) {
12902                         destroy_dahdi_pvt(tmp);
12903                         return NULL;
12904                      }
12905                   }
12906                   ast_cc_copy_config_params(tmp->pri->cc_params,
12907                      conf->chan.cc_params);
12908 
12909                   pris[span].pri.sig = chan_sig;
12910                   pris[span].pri.nodetype = conf->pri.pri.nodetype;
12911                   pris[span].pri.switchtype = myswitchtype;
12912                   pris[span].pri.nsf = conf->pri.pri.nsf;
12913                   pris[span].pri.dialplan = conf->pri.pri.dialplan;
12914                   pris[span].pri.localdialplan = conf->pri.pri.localdialplan;
12915                   pris[span].pri.cpndialplan = conf->pri.pri.cpndialplan;
12916                   pris[span].pri.pvts[pris[span].pri.numchans++] = tmp->sig_pvt;
12917                   pris[span].pri.minunused = conf->pri.pri.minunused;
12918                   pris[span].pri.minidle = conf->pri.pri.minidle;
12919                   pris[span].pri.overlapdial = conf->pri.pri.overlapdial;
12920                   pris[span].pri.qsigchannelmapping = conf->pri.pri.qsigchannelmapping;
12921                   pris[span].pri.discardremoteholdretrieval = conf->pri.pri.discardremoteholdretrieval;
12922 #if defined(HAVE_PRI_SERVICE_MESSAGES)
12923                   pris[span].pri.enable_service_message_support = conf->pri.pri.enable_service_message_support;
12924 #endif   /* defined(HAVE_PRI_SERVICE_MESSAGES) */
12925 #ifdef HAVE_PRI_INBANDDISCONNECT
12926                   pris[span].pri.inbanddisconnect = conf->pri.pri.inbanddisconnect;
12927 #endif
12928 #if defined(HAVE_PRI_CALL_HOLD)
12929                   pris[span].pri.hold_disconnect_transfer =
12930                      conf->pri.pri.hold_disconnect_transfer;
12931 #endif   /* defined(HAVE_PRI_CALL_HOLD) */
12932 #if defined(HAVE_PRI_CCSS)
12933                   pris[span].pri.cc_ptmp_recall_mode =
12934                      conf->pri.pri.cc_ptmp_recall_mode;
12935                   pris[span].pri.cc_qsig_signaling_link_req =
12936                      conf->pri.pri.cc_qsig_signaling_link_req;
12937                   pris[span].pri.cc_qsig_signaling_link_rsp =
12938                      conf->pri.pri.cc_qsig_signaling_link_rsp;
12939 #endif   /* defined(HAVE_PRI_CCSS) */
12940 #if defined(HAVE_PRI_CALL_WAITING)
12941                   pris[span].pri.max_call_waiting_calls =
12942                      conf->pri.pri.max_call_waiting_calls;
12943                   pris[span].pri.allow_call_waiting_calls =
12944                      conf->pri.pri.allow_call_waiting_calls;
12945 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
12946                   pris[span].pri.transfer = conf->chan.transfer;
12947                   pris[span].pri.facilityenable = conf->pri.pri.facilityenable;
12948 #if defined(HAVE_PRI_L2_PERSISTENCE)
12949                   pris[span].pri.l2_persistence = conf->pri.pri.l2_persistence;
12950 #endif   /* defined(HAVE_PRI_L2_PERSISTENCE) */
12951                   pris[span].pri.colp_send = conf->pri.pri.colp_send;
12952 #if defined(HAVE_PRI_AOC_EVENTS)
12953                   pris[span].pri.aoc_passthrough_flag = conf->pri.pri.aoc_passthrough_flag;
12954                   pris[span].pri.aoce_delayhangup = conf->pri.pri.aoce_delayhangup;
12955 #endif   /* defined(HAVE_PRI_AOC_EVENTS) */
12956                   if (chan_sig == SIG_BRI_PTMP) {
12957                      pris[span].pri.layer1_ignored = conf->pri.pri.layer1_ignored;
12958                   } else {
12959                      /* Option does not apply to this line type. */
12960                      pris[span].pri.layer1_ignored = 0;
12961                   }
12962                   pris[span].pri.append_msn_to_user_tag = conf->pri.pri.append_msn_to_user_tag;
12963                   pris[span].pri.inband_on_proceeding = conf->pri.pri.inband_on_proceeding;
12964                   ast_copy_string(pris[span].pri.initial_user_tag, conf->chan.cid_tag, sizeof(pris[span].pri.initial_user_tag));
12965                   ast_copy_string(pris[span].pri.msn_list, conf->pri.pri.msn_list, sizeof(pris[span].pri.msn_list));
12966 #if defined(HAVE_PRI_MWI)
12967                   ast_copy_string(pris[span].pri.mwi_mailboxes,
12968                      conf->pri.pri.mwi_mailboxes,
12969                      sizeof(pris[span].pri.mwi_mailboxes));
12970                   ast_copy_string(pris[span].pri.mwi_vm_numbers,
12971                      conf->pri.pri.mwi_vm_numbers,
12972                      sizeof(pris[span].pri.mwi_vm_numbers));
12973 #endif   /* defined(HAVE_PRI_MWI) */
12974                   ast_copy_string(pris[span].pri.idledial, conf->pri.pri.idledial, sizeof(pris[span].pri.idledial));
12975                   ast_copy_string(pris[span].pri.idleext, conf->pri.pri.idleext, sizeof(pris[span].pri.idleext));
12976                   ast_copy_string(pris[span].pri.internationalprefix, conf->pri.pri.internationalprefix, sizeof(pris[span].pri.internationalprefix));
12977                   ast_copy_string(pris[span].pri.nationalprefix, conf->pri.pri.nationalprefix, sizeof(pris[span].pri.nationalprefix));
12978                   ast_copy_string(pris[span].pri.localprefix, conf->pri.pri.localprefix, sizeof(pris[span].pri.localprefix));
12979                   ast_copy_string(pris[span].pri.privateprefix, conf->pri.pri.privateprefix, sizeof(pris[span].pri.privateprefix));
12980                   ast_copy_string(pris[span].pri.unknownprefix, conf->pri.pri.unknownprefix, sizeof(pris[span].pri.unknownprefix));
12981                   pris[span].pri.moh_signaling = conf->pri.pri.moh_signaling;
12982                   pris[span].pri.resetinterval = conf->pri.pri.resetinterval;
12983 #if defined(HAVE_PRI_DISPLAY_TEXT)
12984                   pris[span].pri.display_flags_send = conf->pri.pri.display_flags_send;
12985                   pris[span].pri.display_flags_receive = conf->pri.pri.display_flags_receive;
12986 #endif   /* defined(HAVE_PRI_DISPLAY_TEXT) */
12987 #if defined(HAVE_PRI_MCID)
12988                   pris[span].pri.mcid_send = conf->pri.pri.mcid_send;
12989 #endif   /* defined(HAVE_PRI_MCID) */
12990 #if defined(HAVE_PRI_DATETIME_SEND)
12991                   pris[span].pri.datetime_send = conf->pri.pri.datetime_send;
12992 #endif   /* defined(HAVE_PRI_DATETIME_SEND) */
12993 
12994                   for (x = 0; x < PRI_MAX_TIMERS; x++) {
12995                      pris[span].pri.pritimers[x] = conf->pri.pri.pritimers[x];
12996                   }
12997 
12998 #if defined(HAVE_PRI_CALL_WAITING)
12999                   /* Channel initial config parameters. */
13000                   pris[span].pri.ch_cfg.stripmsd = conf->chan.stripmsd;
13001                   pris[span].pri.ch_cfg.hidecallerid = conf->chan.hidecallerid;
13002                   pris[span].pri.ch_cfg.hidecalleridname = conf->chan.hidecalleridname;
13003                   pris[span].pri.ch_cfg.immediate = conf->chan.immediate;
13004                   pris[span].pri.ch_cfg.priexclusive = conf->chan.priexclusive;
13005                   pris[span].pri.ch_cfg.priindication_oob = conf->chan.priindication_oob;
13006                   pris[span].pri.ch_cfg.use_callerid = conf->chan.use_callerid;
13007                   pris[span].pri.ch_cfg.use_callingpres = conf->chan.use_callingpres;
13008                   ast_copy_string(pris[span].pri.ch_cfg.context, conf->chan.context, sizeof(pris[span].pri.ch_cfg.context));
13009                   ast_copy_string(pris[span].pri.ch_cfg.mohinterpret, conf->chan.mohinterpret, sizeof(pris[span].pri.ch_cfg.mohinterpret));
13010 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
13011                } else {
13012                   ast_log(LOG_ERROR, "Channel %d is reserved for D-channel.\n", p.chanpos);
13013                   destroy_dahdi_pvt(tmp);
13014                   return NULL;
13015                }
13016             }
13017          }
13018 #endif
13019       } else {
13020          /* already exists in interface list */
13021          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));
13022          chan_sig = tmp->sig;
13023          if (tmp->subs[SUB_REAL].dfd > -1) {
13024             memset(&p, 0, sizeof(p));
13025             res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
13026          }
13027       }
13028       /* Adjust starttime on loopstart and kewlstart trunks to reasonable values */
13029       switch (chan_sig) {
13030       case SIG_FXSKS:
13031       case SIG_FXSLS:
13032       case SIG_EM:
13033       case SIG_EM_E1:
13034       case SIG_EMWINK:
13035       case SIG_FEATD:
13036       case SIG_FEATDMF:
13037       case SIG_FEATDMF_TA:
13038       case SIG_FEATB:
13039       case SIG_E911:
13040       case SIG_SF:
13041       case SIG_SFWINK:
13042       case SIG_FGC_CAMA:
13043       case SIG_FGC_CAMAMF:
13044       case SIG_SF_FEATD:
13045       case SIG_SF_FEATDMF:
13046       case SIG_SF_FEATB:
13047          p.starttime = 250;
13048          break;
13049       }
13050 
13051       if (tmp->radio) {
13052          /* XXX Waiting to hear back from Jim if these should be adjustable XXX */
13053          p.channo = channel;
13054          p.rxwinktime = 1;
13055          p.rxflashtime = 1;
13056          p.starttime = 1;
13057          p.debouncetime = 5;
13058       } else {
13059          p.channo = channel;
13060          /* Override timing settings based on config file */
13061          if (conf->timing.prewinktime >= 0)
13062             p.prewinktime = conf->timing.prewinktime;
13063          if (conf->timing.preflashtime >= 0)
13064             p.preflashtime = conf->timing.preflashtime;
13065          if (conf->timing.winktime >= 0)
13066             p.winktime = conf->timing.winktime;
13067          if (conf->timing.flashtime >= 0)
13068             p.flashtime = conf->timing.flashtime;
13069          if (conf->timing.starttime >= 0)
13070             p.starttime = conf->timing.starttime;
13071          if (conf->timing.rxwinktime >= 0)
13072             p.rxwinktime = conf->timing.rxwinktime;
13073          if (conf->timing.rxflashtime >= 0)
13074             p.rxflashtime = conf->timing.rxflashtime;
13075          if (conf->timing.debouncetime >= 0)
13076             p.debouncetime = conf->timing.debouncetime;
13077       }
13078 
13079       /* don't set parms on a pseudo-channel */
13080       if (tmp->subs[SUB_REAL].dfd >= 0)
13081       {
13082          res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_PARAMS, &p);
13083          if (res < 0) {
13084             ast_log(LOG_ERROR, "Unable to set parameters: %s\n", strerror(errno));
13085             destroy_dahdi_pvt(tmp);
13086             return NULL;
13087          }
13088       }
13089 #if 1
13090       if (!here && (tmp->subs[SUB_REAL].dfd > -1)) {
13091          memset(&bi, 0, sizeof(bi));
13092          res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
13093          if (!res) {
13094             bi.txbufpolicy = conf->chan.buf_policy;
13095             bi.rxbufpolicy = conf->chan.buf_policy;
13096             bi.numbufs = conf->chan.buf_no;
13097             res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
13098             if (res < 0) {
13099                ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", channel, strerror(errno));
13100             }
13101          } else {
13102             ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", channel, strerror(errno));
13103          }
13104          tmp->buf_policy = conf->chan.buf_policy;
13105          tmp->buf_no = conf->chan.buf_no;
13106          tmp->usefaxbuffers = conf->chan.usefaxbuffers;
13107          tmp->faxbuf_policy = conf->chan.faxbuf_policy;
13108          tmp->faxbuf_no = conf->chan.faxbuf_no;
13109          /* This is not as gnarly as it may first appear.  If the ioctl above failed, we'd be setting
13110           * tmp->bufsize to zero which would cause subsequent faxbuffer-related ioctl calls to fail.
13111           * The reason the ioctl call above failed should to be determined before worrying about the
13112           * faxbuffer-related ioctl calls */
13113          tmp->bufsize = bi.bufsize;
13114       }
13115 #endif
13116       tmp->immediate = conf->chan.immediate;
13117       tmp->transfertobusy = conf->chan.transfertobusy;
13118       if (chan_sig & __DAHDI_SIG_FXS) {
13119          tmp->mwimonitor_fsk = conf->chan.mwimonitor_fsk;
13120          tmp->mwimonitor_neon = conf->chan.mwimonitor_neon;
13121          tmp->mwimonitor_rpas = conf->chan.mwimonitor_rpas;
13122       }
13123       tmp->ringt_base = ringt_base;
13124       tmp->firstradio = 0;
13125       if ((chan_sig == SIG_FXOKS) || (chan_sig == SIG_FXOLS) || (chan_sig == SIG_FXOGS))
13126          tmp->permcallwaiting = conf->chan.callwaiting;
13127       else
13128          tmp->permcallwaiting = 0;
13129       /* Flag to destroy the channel must be cleared on new mkif.  Part of changes for reload to work */
13130       tmp->destroy = 0;
13131       tmp->drings = conf->chan.drings;
13132 
13133       /* 10 is a nice default. */
13134       if (tmp->drings.ringnum[0].range == 0)
13135          tmp->drings.ringnum[0].range = 10;
13136       if (tmp->drings.ringnum[1].range == 0)
13137          tmp->drings.ringnum[1].range = 10;
13138       if (tmp->drings.ringnum[2].range == 0)
13139          tmp->drings.ringnum[2].range = 10;
13140 
13141       tmp->usedistinctiveringdetection = usedistinctiveringdetection;
13142       tmp->callwaitingcallerid = conf->chan.callwaitingcallerid;
13143       tmp->threewaycalling = conf->chan.threewaycalling;
13144       tmp->adsi = conf->chan.adsi;
13145       tmp->use_smdi = conf->chan.use_smdi;
13146       tmp->permhidecallerid = conf->chan.hidecallerid;
13147       tmp->hidecalleridname = conf->chan.hidecalleridname;
13148       tmp->callreturn = conf->chan.callreturn;
13149       tmp->echocancel = conf->chan.echocancel;
13150       tmp->echotraining = conf->chan.echotraining;
13151       tmp->pulse = conf->chan.pulse;
13152       if (tmp->echocancel.head.tap_length) {
13153          tmp->echocanbridged = conf->chan.echocanbridged;
13154       } else {
13155          if (conf->chan.echocanbridged)
13156             ast_log(LOG_NOTICE, "echocancelwhenbridged requires echocancel to be enabled; ignoring\n");
13157          tmp->echocanbridged = 0;
13158       }
13159       tmp->busydetect = conf->chan.busydetect;
13160       tmp->busycount = conf->chan.busycount;
13161       tmp->busy_cadence = conf->chan.busy_cadence;
13162       tmp->callprogress = conf->chan.callprogress;
13163       tmp->waitfordialtone = conf->chan.waitfordialtone;
13164       tmp->dialtone_detect = conf->chan.dialtone_detect;
13165       tmp->cancallforward = conf->chan.cancallforward;
13166       tmp->dtmfrelax = conf->chan.dtmfrelax;
13167       tmp->callwaiting = tmp->permcallwaiting;
13168       tmp->hidecallerid = tmp->permhidecallerid;
13169       tmp->channel = channel;
13170       tmp->stripmsd = conf->chan.stripmsd;
13171       tmp->use_callerid = conf->chan.use_callerid;
13172       tmp->cid_signalling = conf->chan.cid_signalling;
13173       tmp->cid_start = conf->chan.cid_start;
13174       tmp->dahditrcallerid = conf->chan.dahditrcallerid;
13175       tmp->restrictcid = conf->chan.restrictcid;
13176       tmp->use_callingpres = conf->chan.use_callingpres;
13177       if (tmp->usedistinctiveringdetection) {
13178          if (!tmp->use_callerid) {
13179             ast_log(LOG_NOTICE, "Distinctive Ring detect requires 'usecallerid' be on\n");
13180             tmp->use_callerid = 1;
13181          }
13182       }
13183 
13184       if (tmp->cid_signalling == CID_SIG_SMDI) {
13185          if (!tmp->use_smdi) {
13186             ast_log(LOG_WARNING, "SMDI callerid requires SMDI to be enabled, enabling...\n");
13187             tmp->use_smdi = 1;
13188          }
13189       }
13190       if (tmp->use_smdi) {
13191          tmp->smdi_iface = ast_smdi_interface_find(conf->smdi_port);
13192          if (!(tmp->smdi_iface)) {
13193             ast_log(LOG_ERROR, "Invalid SMDI port specfied, disabling SMDI support\n");
13194             tmp->use_smdi = 0;
13195          }
13196       }
13197 
13198       ast_copy_string(tmp->accountcode, conf->chan.accountcode, sizeof(tmp->accountcode));
13199       tmp->amaflags = conf->chan.amaflags;
13200       if (!here) {
13201          tmp->confno = -1;
13202          tmp->propconfno = -1;
13203       }
13204       tmp->canpark = conf->chan.canpark;
13205       tmp->transfer = conf->chan.transfer;
13206       ast_copy_string(tmp->defcontext,conf->chan.context,sizeof(tmp->defcontext));
13207       ast_copy_string(tmp->language, conf->chan.language, sizeof(tmp->language));
13208       ast_copy_string(tmp->mohinterpret, conf->chan.mohinterpret, sizeof(tmp->mohinterpret));
13209       ast_copy_string(tmp->mohsuggest, conf->chan.mohsuggest, sizeof(tmp->mohsuggest));
13210       ast_copy_string(tmp->context, conf->chan.context, sizeof(tmp->context));
13211       ast_copy_string(tmp->description, conf->chan.description, sizeof(tmp->description));
13212       ast_copy_string(tmp->parkinglot, conf->chan.parkinglot, sizeof(tmp->parkinglot));
13213       tmp->cid_ton = 0;
13214       if (analog_lib_handles(tmp->sig, tmp->radio, tmp->oprmode)) {
13215          ast_copy_string(tmp->cid_num, conf->chan.cid_num, sizeof(tmp->cid_num));
13216          ast_copy_string(tmp->cid_name, conf->chan.cid_name, sizeof(tmp->cid_name));
13217       } else {
13218          tmp->cid_num[0] = '\0';
13219          tmp->cid_name[0] = '\0';
13220       }
13221 #if defined(HAVE_PRI)
13222       if (dahdi_sig_pri_lib_handles(tmp->sig)) {
13223          tmp->cid_tag[0] = '\0';
13224       } else
13225 #endif   /* defined(HAVE_PRI) */
13226       {
13227          ast_copy_string(tmp->cid_tag, conf->chan.cid_tag, sizeof(tmp->cid_tag));
13228       }
13229       tmp->cid_subaddr[0] = '\0';
13230       ast_copy_string(tmp->mailbox, conf->chan.mailbox, sizeof(tmp->mailbox));
13231       if (channel != CHAN_PSEUDO && !ast_strlen_zero(tmp->mailbox)) {
13232          char *mailbox, *context;
13233          mailbox = context = ast_strdupa(tmp->mailbox);
13234          strsep(&context, "@");
13235          if (ast_strlen_zero(context))
13236             context = "default";
13237          tmp->mwi_event_sub = ast_event_subscribe(AST_EVENT_MWI, mwi_event_cb, "Dahdi MWI subscription", NULL,
13238             AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
13239             AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
13240             AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS,
13241             AST_EVENT_IE_END);
13242       }
13243 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
13244       tmp->mwisend_setting = conf->chan.mwisend_setting;
13245       tmp->mwisend_fsk  = conf->chan.mwisend_fsk;
13246       tmp->mwisend_rpas = conf->chan.mwisend_rpas;
13247 #endif
13248 
13249       tmp->group = conf->chan.group;
13250       tmp->callgroup = conf->chan.callgroup;
13251       tmp->pickupgroup= conf->chan.pickupgroup;
13252       ast_unref_namedgroups(tmp->named_callgroups);
13253       tmp->named_callgroups = ast_ref_namedgroups(conf->chan.named_callgroups);
13254       ast_unref_namedgroups(tmp->named_pickupgroups);
13255       tmp->named_pickupgroups = ast_ref_namedgroups(conf->chan.named_pickupgroups);
13256       if (conf->chan.vars) {
13257          struct ast_variable *v, *tmpvar;
13258                    for (v = conf->chan.vars ; v ; v = v->next) {
13259                          if ((tmpvar = ast_variable_new(v->name, v->value, v->file))) {
13260                                   tmpvar->next = tmp->vars;
13261                                    tmp->vars = tmpvar;
13262                            }
13263                   }
13264       }
13265       tmp->cid_rxgain = conf->chan.cid_rxgain;
13266       tmp->rxgain = conf->chan.rxgain;
13267       tmp->txgain = conf->chan.txgain;
13268       tmp->txdrc = conf->chan.txdrc;
13269       tmp->rxdrc = conf->chan.rxdrc;
13270       tmp->tonezone = conf->chan.tonezone;
13271       if (tmp->subs[SUB_REAL].dfd > -1) {
13272          set_actual_gain(tmp->subs[SUB_REAL].dfd, tmp->rxgain, tmp->txgain, tmp->rxdrc, tmp->txdrc, tmp->law);
13273          if (tmp->dsp)
13274             ast_dsp_set_digitmode(tmp->dsp, DSP_DIGITMODE_DTMF | tmp->dtmfrelax);
13275          update_conf(tmp);
13276          if (!here) {
13277             switch (chan_sig) {
13278             case SIG_PRI_LIB_HANDLE_CASES:
13279             case SIG_SS7:
13280             case SIG_MFCR2:
13281                break;
13282             default:
13283                /* Hang it up to be sure it's good */
13284                dahdi_set_hook(tmp->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
13285                break;
13286             }
13287          }
13288          ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SETTONEZONE,&tmp->tonezone);
13289          if ((res = get_alarms(tmp)) != DAHDI_ALARM_NONE) {
13290             /* the dchannel is down so put the channel in alarm */
13291             switch (tmp->sig) {
13292 #ifdef HAVE_PRI
13293             case SIG_PRI_LIB_HANDLE_CASES:
13294                sig_pri_set_alarm(tmp->sig_pvt, 1);
13295                break;
13296 #endif
13297 #if defined(HAVE_SS7)
13298             case SIG_SS7:
13299                sig_ss7_set_alarm(tmp->sig_pvt, 1);
13300                break;
13301 #endif   /* defined(HAVE_SS7) */
13302             default:
13303                /* The only sig submodule left should be sig_analog. */
13304                analog_p = tmp->sig_pvt;
13305                if (analog_p) {
13306                   analog_p->inalarm = 1;
13307                }
13308                tmp->inalarm = 1;
13309                break;
13310             }
13311             handle_alarms(tmp, res);
13312          }
13313       }
13314 
13315       tmp->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
13316       tmp->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
13317       tmp->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
13318       tmp->sendcalleridafter = conf->chan.sendcalleridafter;
13319       ast_cc_copy_config_params(tmp->cc_params, conf->chan.cc_params);
13320 
13321       if (!here) {
13322          tmp->locallyblocked = 0;
13323          tmp->remotelyblocked = 0;
13324          switch (tmp->sig) {
13325 #if defined(HAVE_PRI)
13326          case SIG_PRI_LIB_HANDLE_CASES:
13327             tmp->inservice = 1;/* Inservice until actually implemented. */
13328 #if defined(HAVE_PRI_SERVICE_MESSAGES)
13329             ((struct sig_pri_chan *) tmp->sig_pvt)->service_status = 0;
13330             if (chan_sig == SIG_PRI) {
13331                char db_chan_name[20];
13332                char db_answer[5];
13333 
13334                /*
13335                 * Initialize the active out-of-service status
13336                 * and delete any record if the feature is not enabled.
13337                 */
13338                snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, tmp->span, tmp->channel);
13339                if (!ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) {
13340                   unsigned *why;
13341 
13342                   why = &((struct sig_pri_chan *) tmp->sig_pvt)->service_status;
13343                   if (tmp->pri->enable_service_message_support) {
13344                      char state;
13345 
13346                      sscanf(db_answer, "%1c:%30u", &state, why);
13347 
13348                      /* Ensure that only the implemented bits could be set.*/
13349                      *why &= (SRVST_NEAREND | SRVST_FAREND);
13350                   }
13351                   if (!*why) {
13352                      ast_db_del(db_chan_name, SRVST_DBKEY);
13353                   }
13354                }
13355             }
13356 #endif   /* defined(HAVE_PRI_SERVICE_MESSAGES) */
13357             break;
13358 #endif   /* defined(HAVE_PRI) */
13359 #if defined(HAVE_SS7)
13360          case SIG_SS7:
13361             tmp->inservice = 0;
13362             break;
13363 #endif   /* defined(HAVE_SS7) */
13364          default:
13365              /* We default to in service on protocols that don't have a reset */
13366             tmp->inservice = 1;
13367             break;
13368          }
13369       }
13370 
13371       switch (tmp->sig) {
13372 #if defined(HAVE_PRI)
13373       case SIG_PRI_LIB_HANDLE_CASES:
13374          if (pri_chan) {
13375             pri_chan->channel = tmp->channel;
13376             pri_chan->hidecallerid = tmp->hidecallerid;
13377             pri_chan->hidecalleridname = tmp->hidecalleridname;
13378             pri_chan->immediate = tmp->immediate;
13379             pri_chan->inalarm = tmp->inalarm;
13380             pri_chan->priexclusive = tmp->priexclusive;
13381             pri_chan->priindication_oob = tmp->priindication_oob;
13382             pri_chan->use_callerid = tmp->use_callerid;
13383             pri_chan->use_callingpres = tmp->use_callingpres;
13384             ast_copy_string(pri_chan->context, tmp->context,
13385                sizeof(pri_chan->context));
13386             ast_copy_string(pri_chan->mohinterpret, tmp->mohinterpret,
13387                sizeof(pri_chan->mohinterpret));
13388             pri_chan->stripmsd = tmp->stripmsd;
13389          }
13390          break;
13391 #endif   /* defined(HAVE_PRI) */
13392 #if defined(HAVE_SS7)
13393       case SIG_SS7:
13394          if (ss7_chan) {
13395             ss7_chan->inalarm = tmp->inalarm;
13396 
13397             ss7_chan->stripmsd = tmp->stripmsd;
13398             ss7_chan->hidecallerid = tmp->hidecallerid;
13399             ss7_chan->use_callerid = tmp->use_callerid;
13400             ss7_chan->use_callingpres = tmp->use_callingpres;
13401             ss7_chan->immediate = tmp->immediate;
13402             ss7_chan->locallyblocked = tmp->locallyblocked;
13403             ss7_chan->remotelyblocked = tmp->remotelyblocked;
13404             ast_copy_string(ss7_chan->context, tmp->context,
13405                sizeof(ss7_chan->context));
13406             ast_copy_string(ss7_chan->mohinterpret, tmp->mohinterpret,
13407                sizeof(ss7_chan->mohinterpret));
13408          }
13409          break;
13410 #endif   /* defined(HAVE_SS7) */
13411       default:
13412          /* The only sig submodule left should be sig_analog. */
13413          analog_p = tmp->sig_pvt;
13414          if (analog_p) {
13415             analog_p->channel = tmp->channel;
13416             analog_p->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
13417             analog_p->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
13418             analog_p->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
13419             analog_p->permcallwaiting = conf->chan.callwaiting; /* permcallwaiting possibly modified in analog_config_complete */
13420             analog_p->callreturn = conf->chan.callreturn;
13421             analog_p->cancallforward = conf->chan.cancallforward;
13422             analog_p->canpark = conf->chan.canpark;
13423             analog_p->dahditrcallerid = conf->chan.dahditrcallerid;
13424             analog_p->immediate = conf->chan.immediate;
13425             analog_p->permhidecallerid = conf->chan.permhidecallerid;
13426             analog_p->pulse = conf->chan.pulse;
13427             analog_p->threewaycalling = conf->chan.threewaycalling;
13428             analog_p->transfer = conf->chan.transfer;
13429             analog_p->transfertobusy = conf->chan.transfertobusy;
13430             analog_p->use_callerid = tmp->use_callerid;
13431             analog_p->use_smdi = tmp->use_smdi;
13432             analog_p->smdi_iface = tmp->smdi_iface;
13433             analog_p->outsigmod = ANALOG_SIG_NONE;
13434             analog_p->echotraining = conf->chan.echotraining;
13435             analog_p->cid_signalling = conf->chan.cid_signalling;
13436             analog_p->stripmsd = conf->chan.stripmsd;
13437             switch (conf->chan.cid_start) {
13438             case CID_START_POLARITY:
13439                analog_p->cid_start = ANALOG_CID_START_POLARITY;
13440                break;
13441             case CID_START_POLARITY_IN:
13442                analog_p->cid_start = ANALOG_CID_START_POLARITY_IN;
13443                break;
13444             case CID_START_DTMF_NOALERT:
13445                analog_p->cid_start = ANALOG_CID_START_DTMF_NOALERT;
13446                break;
13447             default:
13448                analog_p->cid_start = ANALOG_CID_START_RING;
13449                break;
13450             }
13451             analog_p->callwaitingcallerid = conf->chan.callwaitingcallerid;
13452             analog_p->ringt = conf->chan.ringt;
13453             analog_p->ringt_base = ringt_base;
13454             analog_p->onhooktime = time(NULL);
13455             if (chan_sig & __DAHDI_SIG_FXO) {
13456                memset(&p, 0, sizeof(p));
13457                res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
13458                if (!res) {
13459                   analog_p->fxsoffhookstate = p.rxisoffhook;
13460                }
13461 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
13462                res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_VMWI_CONFIG, &tmp->mwisend_setting);
13463 #endif
13464             }
13465             analog_p->msgstate = -1;
13466 
13467             ast_copy_string(analog_p->mohsuggest, conf->chan.mohsuggest, sizeof(analog_p->mohsuggest));
13468             ast_copy_string(analog_p->cid_num, conf->chan.cid_num, sizeof(analog_p->cid_num));
13469             ast_copy_string(analog_p->cid_name, conf->chan.cid_name, sizeof(analog_p->cid_name));
13470 
13471             analog_config_complete(analog_p);
13472          }
13473          break;
13474       }
13475 #if defined(HAVE_PRI)
13476       if (tmp->channel == CHAN_PSEUDO) {
13477          /*
13478           * Save off pseudo channel buffer policy values for dynamic creation of
13479           * no B channel interfaces.
13480           */
13481          dahdi_pseudo_parms.buf_no = tmp->buf_no;
13482          dahdi_pseudo_parms.buf_policy = tmp->buf_policy;
13483          dahdi_pseudo_parms.faxbuf_no = tmp->faxbuf_no;
13484          dahdi_pseudo_parms.faxbuf_policy = tmp->faxbuf_policy;
13485       }
13486 #endif   /* defined(HAVE_PRI) */
13487    }
13488    if (tmp && !here) {
13489       /* Add the new channel interface to the sorted channel interface list. */
13490       dahdi_iflist_insert(tmp);
13491    }
13492    return tmp;
13493 }
13494 
13495 static int is_group_or_channel_match(struct dahdi_pvt *p, int span, ast_group_t groupmatch, int *groupmatched, int channelmatch, int *channelmatched)
13496 {
13497 #if defined(HAVE_PRI)
13498    if (0 < span) {
13499       /* The channel must be on the specified PRI span. */
13500       if (!p->pri || p->pri->span != span) {
13501          return 0;
13502       }
13503       if (!groupmatch && channelmatch == -1) {
13504          /* Match any group since it only needs to be on the PRI span. */
13505          *groupmatched = 1;
13506          return 1;
13507       }
13508    }
13509 #endif   /* defined(HAVE_PRI) */
13510    /* check group matching */
13511    if (groupmatch) {
13512       if ((p->group & groupmatch) != groupmatch)
13513          /* Doesn't match the specified group, try the next one */
13514          return 0;
13515       *groupmatched = 1;
13516    }
13517    /* Check to see if we have a channel match */
13518    if (channelmatch != -1) {
13519       if (p->channel != channelmatch)
13520          /* Doesn't match the specified channel, try the next one */
13521          return 0;
13522       *channelmatched = 1;
13523    }
13524 
13525    return 1;
13526 }
13527 
13528 static int available(struct dahdi_pvt **pvt, int is_specific_channel)
13529 {
13530    struct dahdi_pvt *p = *pvt;
13531 
13532    if (p->inalarm)
13533       return 0;
13534 
13535    if (analog_lib_handles(p->sig, p->radio, p->oprmode))
13536       return analog_available(p->sig_pvt);
13537 
13538    switch (p->sig) {
13539 #if defined(HAVE_PRI)
13540    case SIG_PRI_LIB_HANDLE_CASES:
13541       {
13542          struct sig_pri_chan *pvt_chan;
13543          int res;
13544 
13545          pvt_chan = p->sig_pvt;
13546          res = sig_pri_available(&pvt_chan, is_specific_channel);
13547          *pvt = pvt_chan->chan_pvt;
13548          return res;
13549       }
13550 #endif   /* defined(HAVE_PRI) */
13551 #if defined(HAVE_SS7)
13552    case SIG_SS7:
13553       return sig_ss7_available(p->sig_pvt);
13554 #endif   /* defined(HAVE_SS7) */
13555    default:
13556       break;
13557    }
13558 
13559    if (p->locallyblocked || p->remotelyblocked) {
13560       return 0;
13561    }
13562 
13563    /* If no owner definitely available */
13564    if (!p->owner) {
13565 #ifdef HAVE_OPENR2
13566       /* Trust MFC/R2 */
13567       if (p->mfcr2) {
13568          if (p->mfcr2call) {
13569             return 0;
13570          } else {
13571             return 1;
13572          }
13573       }
13574 #endif
13575       return 1;
13576    }
13577 
13578    return 0;
13579 }
13580 
13581 #if defined(HAVE_PRI)
13582 #if defined(HAVE_PRI_CALL_WAITING)
13583 /*!
13584  * \internal
13585  * \brief Init the private channel configuration using the span controller.
13586  * \since 1.8
13587  *
13588  * \param priv Channel to init the configuration.
13589  * \param pri sig_pri PRI control structure.
13590  *
13591  * \note Assumes the pri->lock is already obtained.
13592  *
13593  * \return Nothing
13594  */
13595 static void my_pri_init_config(void *priv, struct sig_pri_span *pri)
13596 {
13597    struct dahdi_pvt *pvt = priv;
13598 
13599    pvt->stripmsd = pri->ch_cfg.stripmsd;
13600    pvt->hidecallerid = pri->ch_cfg.hidecallerid;
13601    pvt->hidecalleridname = pri->ch_cfg.hidecalleridname;
13602    pvt->immediate = pri->ch_cfg.immediate;
13603    pvt->priexclusive = pri->ch_cfg.priexclusive;
13604    pvt->priindication_oob = pri->ch_cfg.priindication_oob;
13605    pvt->use_callerid = pri->ch_cfg.use_callerid;
13606    pvt->use_callingpres = pri->ch_cfg.use_callingpres;
13607    ast_copy_string(pvt->context, pri->ch_cfg.context, sizeof(pvt->context));
13608    ast_copy_string(pvt->mohinterpret, pri->ch_cfg.mohinterpret, sizeof(pvt->mohinterpret));
13609 }
13610 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
13611 #endif   /* defined(HAVE_PRI) */
13612 
13613 #if defined(HAVE_PRI)
13614 /*!
13615  * \internal
13616  * \brief Create a no B channel interface.
13617  * \since 1.8
13618  *
13619  * \param pri sig_pri span controller to add interface.
13620  *
13621  * \note Assumes the pri->lock is already obtained.
13622  *
13623  * \retval array-index into private pointer array on success.
13624  * \retval -1 on error.
13625  */
13626 static int dahdi_new_pri_nobch_channel(struct sig_pri_span *pri)
13627 {
13628    int pvt_idx;
13629    int res;
13630    unsigned idx;
13631    struct dahdi_pvt *pvt;
13632    struct sig_pri_chan *chan;
13633    struct dahdi_bufferinfo bi;
13634 
13635    static int nobch_channel = CHAN_PSEUDO;
13636 
13637    /* Find spot in the private pointer array for new interface. */
13638    for (pvt_idx = 0; pvt_idx < pri->numchans; ++pvt_idx) {
13639       if (!pri->pvts[pvt_idx]) {
13640          break;
13641       }
13642    }
13643    if (pri->numchans == pvt_idx) {
13644       if (ARRAY_LEN(pri->pvts) <= pvt_idx) {
13645          ast_log(LOG_ERROR, "Unable to add a no-B-channel interface!\n");
13646          return -1;
13647       }
13648 
13649       /* Add new spot to the private pointer array. */
13650       pri->pvts[pvt_idx] = NULL;
13651       ++pri->numchans;
13652    }
13653 
13654    pvt = ast_calloc(1, sizeof(*pvt));
13655    if (!pvt) {
13656       return -1;
13657    }
13658    pvt->cc_params = ast_cc_config_params_init();
13659    if (!pvt->cc_params) {
13660       ast_free(pvt);
13661       return -1;
13662    }
13663    ast_mutex_init(&pvt->lock);
13664    for (idx = 0; idx < ARRAY_LEN(pvt->subs); ++idx) {
13665       pvt->subs[idx].dfd = -1;
13666    }
13667    pvt->buf_no = dahdi_pseudo_parms.buf_no;
13668    pvt->buf_policy = dahdi_pseudo_parms.buf_policy;
13669    pvt->faxbuf_no = dahdi_pseudo_parms.faxbuf_no;
13670    pvt->faxbuf_policy = dahdi_pseudo_parms.faxbuf_policy;
13671 
13672    chan = sig_pri_chan_new(pvt, pri, 0, 0, 0);
13673    if (!chan) {
13674       destroy_dahdi_pvt(pvt);
13675       return -1;
13676    }
13677    chan->no_b_channel = 1;
13678 
13679    /*
13680     * Pseudo channel companding law.
13681     * Needed for outgoing call waiting calls.
13682     * XXX May need to make this determined by switchtype or user option.
13683     */
13684    pvt->law_default = DAHDI_LAW_ALAW;
13685 
13686    pvt->sig = pri->sig;
13687    pvt->outsigmod = -1;
13688    pvt->pri = pri;
13689    pvt->sig_pvt = chan;
13690    pri->pvts[pvt_idx] = chan;
13691 
13692    pvt->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo");
13693    if (pvt->subs[SUB_REAL].dfd < 0) {
13694       ast_log(LOG_ERROR, "Unable to open no B channel interface pseudo channel: %s\n",
13695          strerror(errno));
13696       destroy_dahdi_pvt(pvt);
13697       return -1;
13698    }
13699    memset(&bi, 0, sizeof(bi));
13700    res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
13701    if (!res) {
13702       pvt->bufsize = bi.bufsize;
13703       bi.txbufpolicy = pvt->buf_policy;
13704       bi.rxbufpolicy = pvt->buf_policy;
13705       bi.numbufs = pvt->buf_no;
13706       res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
13707       if (res < 0) {
13708          ast_log(LOG_WARNING,
13709             "Unable to set buffer policy on no B channel interface: %s\n",
13710             strerror(errno));
13711       }
13712    } else
13713       ast_log(LOG_WARNING,
13714          "Unable to check buffer policy on no B channel interface: %s\n",
13715          strerror(errno));
13716 
13717    --nobch_channel;
13718    if (CHAN_PSEUDO < nobch_channel) {
13719       nobch_channel = CHAN_PSEUDO - 1;
13720    }
13721    pvt->channel = nobch_channel;
13722    pvt->span = pri->span;
13723    chan->channel = pvt->channel;
13724 
13725    dahdi_nobch_insert(pri, pvt);
13726 
13727    return pvt_idx;
13728 }
13729 #endif   /* defined(HAVE_PRI) */
13730 
13731 /* This function can *ONLY* be used for copying pseudo (CHAN_PSEUDO) private
13732    structures; it makes no attempt to safely copy regular channel private
13733    structures that might contain reference-counted object pointers and other
13734    scary bits
13735 */
13736 static struct dahdi_pvt *duplicate_pseudo(struct dahdi_pvt *src)
13737 {
13738    struct dahdi_pvt *p;
13739    struct dahdi_bufferinfo bi;
13740    int res;
13741 
13742    p = ast_malloc(sizeof(*p));
13743    if (!p) {
13744       return NULL;
13745    }
13746    *p = *src;
13747 
13748    /* Must deep copy the cc_params. */
13749    p->cc_params = ast_cc_config_params_init();
13750    if (!p->cc_params) {
13751       ast_free(p);
13752       return NULL;
13753    }
13754    ast_cc_copy_config_params(p->cc_params, src->cc_params);
13755 
13756    p->which_iflist = DAHDI_IFLIST_NONE;
13757    p->next = NULL;
13758    p->prev = NULL;
13759    ast_mutex_init(&p->lock);
13760    p->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo");
13761    if (p->subs[SUB_REAL].dfd < 0) {
13762       ast_log(LOG_ERROR, "Unable to dup channel: %s\n", strerror(errno));
13763       destroy_dahdi_pvt(p);
13764       return NULL;
13765    }
13766    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
13767    if (!res) {
13768       bi.txbufpolicy = src->buf_policy;
13769       bi.rxbufpolicy = src->buf_policy;
13770       bi.numbufs = src->buf_no;
13771       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
13772       if (res < 0) {
13773          ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel: %s\n", strerror(errno));
13774       }
13775    } else
13776       ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel: %s\n", strerror(errno));
13777    p->destroy = 1;
13778    dahdi_iflist_insert(p);
13779    return p;
13780 }
13781 
13782 struct dahdi_starting_point {
13783    /*! Group matching mask.  Zero if not specified. */
13784    ast_group_t groupmatch;
13785    /*! DAHDI channel to match with.  -1 if not specified. */
13786    int channelmatch;
13787    /*! Round robin saved search location index. (Valid if roundrobin TRUE) */
13788    int rr_starting_point;
13789    /*! ISDN span where channels can be picked (Zero if not specified) */
13790    int span;
13791    /*! Analog channel distinctive ring cadance index. */
13792    int cadance;
13793    /*! Dialing option. c/r/d if present and valid. */
13794    char opt;
13795    /*! TRUE if to search the channel list backwards. */
13796    char backwards;
13797    /*! TRUE if search is done with round robin sequence. */
13798    char roundrobin;
13799 };
13800 static struct dahdi_pvt *determine_starting_point(const char *data, struct dahdi_starting_point *param)
13801 {
13802    char *dest;
13803    char *s;
13804    int x;
13805    int res = 0;
13806    struct dahdi_pvt *p;
13807    char *subdir = NULL;
13808    AST_DECLARE_APP_ARGS(args,
13809       AST_APP_ARG(group);  /* channel/group token */
13810       //AST_APP_ARG(ext);  /* extension token */
13811       //AST_APP_ARG(opts); /* options token */
13812       AST_APP_ARG(other);  /* Any remining unused arguments */
13813    );
13814 
13815    /*
13816     * data is ---v
13817     * Dial(DAHDI/pseudo[/extension[/options]])
13818     * Dial(DAHDI/<channel#>[c|r<cadance#>|d][/extension[/options]])
13819     * Dial(DAHDI/<subdir>!<channel#>[c|r<cadance#>|d][/extension[/options]])
13820     * Dial(DAHDI/i<span>[/extension[/options]])
13821     * Dial(DAHDI/[i<span>-](g|G|r|R)<group#(0-63)>[c|r<cadance#>|d][/extension[/options]])
13822     *
13823     * i - ISDN span channel restriction.
13824     *     Used by CC to ensure that the CC recall goes out the same span.
13825     *     Also to make ISDN channel names dialable when the sequence number
13826     *     is stripped off.  (Used by DTMF attended transfer feature.)
13827     *
13828     * g - channel group allocation search forward
13829     * G - channel group allocation search backward
13830     * r - channel group allocation round robin search forward
13831     * R - channel group allocation round robin search backward
13832     *
13833     * c - Wait for DTMF digit to confirm answer
13834     * r<cadance#> - Set distintive ring cadance number
13835     * d - Force bearer capability for ISDN/SS7 call to digital.
13836     */
13837 
13838    if (data) {
13839       dest = ast_strdupa(data);
13840    } else {
13841       ast_log(LOG_WARNING, "Channel requested with no data\n");
13842       return NULL;
13843    }
13844    AST_NONSTANDARD_APP_ARGS(args, dest, '/');
13845    if (!args.argc || ast_strlen_zero(args.group)) {
13846       ast_log(LOG_WARNING, "No channel/group specified\n");
13847       return NULL;
13848    }
13849 
13850    /* Initialize the output parameters */
13851    memset(param, 0, sizeof(*param));
13852    param->channelmatch = -1;
13853 
13854    if (strchr(args.group, '!') != NULL) {
13855       char *prev = args.group;
13856       while ((s = strchr(prev, '!')) != NULL) {
13857          *s++ = '/';
13858          prev = s;
13859       }
13860       *(prev - 1) = '\0';
13861       subdir = args.group;
13862       args.group = prev;
13863    } else if (args.group[0] == 'i') {
13864       /* Extract the ISDN span channel restriction specifier. */
13865       res = sscanf(args.group + 1, "%30d", &x);
13866       if (res < 1) {
13867          ast_log(LOG_WARNING, "Unable to determine ISDN span for data %s\n", data);
13868          return NULL;
13869       }
13870       param->span = x;
13871 
13872       /* Remove the ISDN span channel restriction specifier. */
13873       s = strchr(args.group, '-');
13874       if (!s) {
13875          /* Search all groups since we are ISDN span restricted. */
13876          return iflist;
13877       }
13878       args.group = s + 1;
13879       res = 0;
13880    }
13881    if (toupper(args.group[0]) == 'G' || toupper(args.group[0])=='R') {
13882       /* Retrieve the group number */
13883       s = args.group + 1;
13884       res = sscanf(s, "%30d%1c%30d", &x, &param->opt, &param->cadance);
13885       if (res < 1) {
13886          ast_log(LOG_WARNING, "Unable to determine group for data %s\n", data);
13887          return NULL;
13888       }
13889       param->groupmatch = ((ast_group_t) 1 << x);
13890 
13891       if (toupper(args.group[0]) == 'G') {
13892          if (args.group[0] == 'G') {
13893             param->backwards = 1;
13894             p = ifend;
13895          } else
13896             p = iflist;
13897       } else {
13898          if (ARRAY_LEN(round_robin) <= x) {
13899             ast_log(LOG_WARNING, "Round robin index %d out of range for data %s\n",
13900                x, data);
13901             return NULL;
13902          }
13903          if (args.group[0] == 'R') {
13904             param->backwards = 1;
13905             p = round_robin[x] ? round_robin[x]->prev : ifend;
13906             if (!p)
13907                p = ifend;
13908          } else {
13909             p = round_robin[x] ? round_robin[x]->next : iflist;
13910             if (!p)
13911                p = iflist;
13912          }
13913          param->roundrobin = 1;
13914          param->rr_starting_point = x;
13915       }
13916    } else {
13917       s = args.group;
13918       if (!strcasecmp(s, "pseudo")) {
13919          /* Special case for pseudo */
13920          x = CHAN_PSEUDO;
13921          param->channelmatch = x;
13922       } else {
13923          res = sscanf(s, "%30d%1c%30d", &x, &param->opt, &param->cadance);
13924          if (res < 1) {
13925             ast_log(LOG_WARNING, "Unable to determine channel for data %s\n", data);
13926             return NULL;
13927          } else {
13928             param->channelmatch = x;
13929          }
13930       }
13931       if (subdir) {
13932          char path[PATH_MAX];
13933          struct stat stbuf;
13934 
13935          snprintf(path, sizeof(path), "/dev/dahdi/%s/%d",
13936                subdir, param->channelmatch);
13937          if (stat(path, &stbuf) < 0) {
13938             ast_log(LOG_WARNING, "stat(%s) failed: %s\n",
13939                   path, strerror(errno));
13940             return NULL;
13941          }
13942          if (!S_ISCHR(stbuf.st_mode)) {
13943             ast_log(LOG_ERROR, "%s: Not a character device file\n",
13944                   path);
13945             return NULL;
13946          }
13947          param->channelmatch = minor(stbuf.st_rdev);
13948       }
13949 
13950       p = iflist;
13951    }
13952 
13953    if (param->opt == 'r' && res < 3) {
13954       ast_log(LOG_WARNING, "Distinctive ring missing identifier in '%s'\n", data);
13955       param->opt = '\0';
13956    }
13957 
13958    return p;
13959 }
13960 
13961 static struct ast_channel *dahdi_request(const char *type, struct ast_format_cap *cap, const struct ast_channel *requestor, const char *data, int *cause)
13962 {
13963    int callwait = 0;
13964    struct dahdi_pvt *p;
13965    struct ast_channel *tmp = NULL;
13966    struct dahdi_pvt *exitpvt;
13967    int channelmatched = 0;
13968    int groupmatched = 0;
13969 #if defined(HAVE_PRI) || defined(HAVE_SS7)
13970    int transcapdigital = 0;
13971 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
13972    struct dahdi_starting_point start;
13973    struct ast_callid *callid = NULL;
13974    int callid_created = ast_callid_threadstorage_auto(&callid);
13975 
13976    ast_mutex_lock(&iflock);
13977    p = determine_starting_point(data, &start);
13978    if (!p) {
13979       /* We couldn't determine a starting point, which likely means badly-formatted channel name. Abort! */
13980       ast_mutex_unlock(&iflock);
13981       ast_callid_threadstorage_auto_clean(callid, callid_created);
13982       return NULL;
13983    }
13984 
13985    /* Search for an unowned channel */
13986    exitpvt = p;
13987    while (p && !tmp) {
13988       if (start.roundrobin)
13989          round_robin[start.rr_starting_point] = p;
13990 
13991       if (is_group_or_channel_match(p, start.span, start.groupmatch, &groupmatched, start.channelmatch, &channelmatched)
13992          && available(&p, channelmatched)) {
13993          ast_debug(1, "Using channel %d\n", p->channel);
13994 
13995          callwait = (p->owner != NULL);
13996 #ifdef HAVE_OPENR2
13997          if (p->mfcr2) {
13998             ast_mutex_lock(&p->lock);
13999             if (p->mfcr2call) {
14000                ast_mutex_unlock(&p->lock);
14001                ast_debug(1, "Yay!, someone just beat us in the race for channel %d.\n", p->channel);
14002                goto next;
14003             }
14004             p->mfcr2call = 1;
14005             ast_mutex_unlock(&p->lock);
14006          }
14007 #endif
14008          if (p->channel == CHAN_PSEUDO) {
14009             p = duplicate_pseudo(p);
14010             if (!p) {
14011                break;
14012             }
14013          }
14014 
14015          p->distinctivering = 0;
14016          /* Make special notes */
14017          switch (start.opt) {
14018          case '\0':
14019             /* No option present. */
14020             break;
14021          case 'c':
14022             /* Confirm answer */
14023             p->confirmanswer = 1;
14024             break;
14025          case 'r':
14026             /* Distinctive ring */
14027             p->distinctivering = start.cadance;
14028             break;
14029          case 'd':
14030 #if defined(HAVE_PRI) || defined(HAVE_SS7)
14031             /* If this is an ISDN call, make it digital */
14032             transcapdigital = AST_TRANS_CAP_DIGITAL;
14033 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
14034             break;
14035          default:
14036             ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", start.opt, data);
14037             break;
14038          }
14039 
14040          p->outgoing = 1;
14041          if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
14042             tmp = analog_request(p->sig_pvt, &callwait, requestor);
14043 #ifdef HAVE_PRI
14044          } else if (dahdi_sig_pri_lib_handles(p->sig)) {
14045             /*
14046              * We already have the B channel reserved for this call.  We
14047              * just need to make sure that dahdi_hangup() has completed
14048              * cleaning up before continuing.
14049              */
14050             ast_mutex_lock(&p->lock);
14051             ast_mutex_unlock(&p->lock);
14052 
14053             sig_pri_extract_called_num_subaddr(p->sig_pvt, data, p->dnid,
14054                sizeof(p->dnid));
14055             tmp = sig_pri_request(p->sig_pvt, SIG_PRI_DEFLAW, requestor, transcapdigital);
14056 #endif
14057 #if defined(HAVE_SS7)
14058          } else if (p->sig == SIG_SS7) {
14059             tmp = sig_ss7_request(p->sig_pvt, SIG_SS7_DEFLAW, requestor, transcapdigital);
14060 #endif   /* defined(HAVE_SS7) */
14061          } else {
14062             tmp = dahdi_new(p, AST_STATE_RESERVED, 0, p->owner ? SUB_CALLWAIT : SUB_REAL, 0, requestor ? ast_channel_linkedid(requestor) : "", callid);
14063          }
14064          if (!tmp) {
14065             p->outgoing = 0;
14066 #if defined(HAVE_PRI)
14067             switch (p->sig) {
14068             case SIG_PRI_LIB_HANDLE_CASES:
14069 #if defined(HAVE_PRI_CALL_WAITING)
14070                if (((struct sig_pri_chan *) p->sig_pvt)->is_call_waiting) {
14071                   ((struct sig_pri_chan *) p->sig_pvt)->is_call_waiting = 0;
14072                   ast_atomic_fetchadd_int(&p->pri->num_call_waiting_calls, -1);
14073                }
14074 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
14075                /*
14076                 * This should be the last thing to clear when we are done with
14077                 * the channel.
14078                 */
14079                ((struct sig_pri_chan *) p->sig_pvt)->allocated = 0;
14080                break;
14081             default:
14082                break;
14083             }
14084 #endif   /* defined(HAVE_PRI) */
14085          } else {
14086             snprintf(p->dialstring, sizeof(p->dialstring), "DAHDI/%s", data);
14087          }
14088          break;
14089       }
14090 #ifdef HAVE_OPENR2
14091 next:
14092 #endif
14093       if (start.backwards) {
14094          p = p->prev;
14095          if (!p)
14096             p = ifend;
14097       } else {
14098          p = p->next;
14099          if (!p)
14100             p = iflist;
14101       }
14102       /* stop when you roll to the one that we started from */
14103       if (p == exitpvt)
14104          break;
14105    }
14106    ast_mutex_unlock(&iflock);
14107    restart_monitor();
14108    if (cause && !tmp) {
14109       if (callwait || channelmatched) {
14110          *cause = AST_CAUSE_BUSY;
14111       } else if (groupmatched) {
14112          *cause = AST_CAUSE_CONGESTION;
14113       } else {
14114          /*
14115           * We did not match any channel requested.
14116           * Dialplan error requesting non-existant channel?
14117           */
14118       }
14119    }
14120 
14121    ast_callid_threadstorage_auto_clean(callid, callid_created);
14122    return tmp;
14123 }
14124 
14125 /*!
14126  * \internal
14127  * \brief Determine the device state for a given DAHDI device if we can.
14128  * \since 1.8
14129  *
14130  * \param data DAHDI device name after "DAHDI/".
14131  *
14132  * \retval device_state enum ast_device_state value.
14133  * \retval AST_DEVICE_UNKNOWN if we could not determine the device's state.
14134  */
14135 static int dahdi_devicestate(const char *data)
14136 {
14137 #if defined(HAVE_PRI)
14138    const char *device;
14139    unsigned span;
14140    int res;
14141 
14142    device = data;
14143 
14144    if (*device != 'I') {
14145       /* The request is not for an ISDN span device. */
14146       return AST_DEVICE_UNKNOWN;
14147    }
14148    res = sscanf(device, "I%30u", &span);
14149    if (res != 1 || !span || NUM_SPANS < span) {
14150       /* Bad format for ISDN span device name. */
14151       return AST_DEVICE_UNKNOWN;
14152    }
14153    device = strchr(device, '/');
14154    if (!device) {
14155       /* Bad format for ISDN span device name. */
14156       return AST_DEVICE_UNKNOWN;
14157    }
14158 
14159    /*
14160     * Since there are currently no other span devstate's defined,
14161     * it must be congestion.
14162     */
14163 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
14164    ++device;
14165    if (!strcmp(device, "congestion"))
14166 #endif   /* defined(THRESHOLD_DEVSTATE_PLACEHOLDER) */
14167    {
14168       return pris[span - 1].pri.congestion_devstate;
14169    }
14170 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
14171    else if (!strcmp(device, "threshold")) {
14172       return pris[span - 1].pri.threshold_devstate;
14173    }
14174    return AST_DEVICE_UNKNOWN;
14175 #endif   /* defined(THRESHOLD_DEVSTATE_PLACEHOLDER) */
14176 #else
14177    return AST_DEVICE_UNKNOWN;
14178 #endif   /* defined(HAVE_PRI) */
14179 }
14180 
14181 /*!
14182  * \brief Callback made when dial failed to get a channel out of dahdi_request().
14183  * \since 1.8
14184  *
14185  * \param inbound Incoming asterisk channel.
14186  * \param dest Same dial string passed to dahdi_request().
14187  * \param callback Callback into CC core to announce a busy channel available for CC.
14188  *
14189  * \details
14190  * This callback acts like a forked dial with all prongs of the fork busy.
14191  * Essentially, for each channel that could have taken the call, indicate that
14192  * it is busy.
14193  *
14194  * \retval 0 on success.
14195  * \retval -1 on error.
14196  */
14197 static int dahdi_cc_callback(struct ast_channel *inbound, const char *dest, ast_cc_callback_fn callback)
14198 {
14199    struct dahdi_pvt *p;
14200    struct dahdi_pvt *exitpvt;
14201    struct dahdi_starting_point start;
14202    int groupmatched = 0;
14203    int channelmatched = 0;
14204 
14205    ast_mutex_lock(&iflock);
14206    p = determine_starting_point(dest, &start);
14207    if (!p) {
14208       ast_mutex_unlock(&iflock);
14209       return -1;
14210    }
14211    exitpvt = p;
14212    for (;;) {
14213       if (is_group_or_channel_match(p, start.span, start.groupmatch, &groupmatched, start.channelmatch, &channelmatched)) {
14214          /* We found a potential match. call the callback */
14215          struct ast_str *device_name;
14216          char *dash;
14217          const char *monitor_type;
14218          char dialstring[AST_CHANNEL_NAME];
14219          char full_device_name[AST_CHANNEL_NAME];
14220 
14221          switch (ast_get_cc_monitor_policy(p->cc_params)) {
14222          case AST_CC_MONITOR_NEVER:
14223             break;
14224          case AST_CC_MONITOR_NATIVE:
14225          case AST_CC_MONITOR_ALWAYS:
14226          case AST_CC_MONITOR_GENERIC:
14227 #if defined(HAVE_PRI)
14228             if (dahdi_sig_pri_lib_handles(p->sig)) {
14229                /*
14230                 * ISDN is in a trunk busy condition so we need to monitor
14231                 * the span congestion device state.
14232                 */
14233                snprintf(full_device_name, sizeof(full_device_name),
14234                   "DAHDI/I%d/congestion", p->pri->span);
14235             } else
14236 #endif   /* defined(HAVE_PRI) */
14237             {
14238 #if defined(HAVE_PRI)
14239                device_name = create_channel_name(p, 1, "");
14240 #else
14241                device_name = create_channel_name(p);
14242 #endif   /* defined(HAVE_PRI) */
14243                snprintf(full_device_name, sizeof(full_device_name), "DAHDI/%s",
14244                   device_name ? ast_str_buffer(device_name) : "");
14245                ast_free(device_name);
14246                /*
14247                 * The portion after the '-' in the channel name is either a random
14248                 * number, a sequence number, or a subchannel number. None are
14249                 * necessary so strip them off.
14250                 */
14251                dash = strrchr(full_device_name, '-');
14252                if (dash) {
14253                   *dash = '\0';
14254                }
14255             }
14256             snprintf(dialstring, sizeof(dialstring), "DAHDI/%s", dest);
14257 
14258             /*
14259              * Analog can only do generic monitoring.
14260              * ISDN is in a trunk busy condition and any "device" is going
14261              * to be busy until a B channel becomes available.  The generic
14262              * monitor can do this task.
14263              */
14264             monitor_type = AST_CC_GENERIC_MONITOR_TYPE;
14265             callback(inbound,
14266 #if defined(HAVE_PRI)
14267                p->pri ? p->pri->cc_params : p->cc_params,
14268 #else
14269                p->cc_params,
14270 #endif   /* defined(HAVE_PRI) */
14271                monitor_type, full_device_name, dialstring, NULL);
14272             break;
14273          }
14274       }
14275       p = start.backwards ? p->prev : p->next;
14276       if (!p) {
14277          p = start.backwards ? ifend : iflist;
14278       }
14279       if (p == exitpvt) {
14280          break;
14281       }
14282    }
14283    ast_mutex_unlock(&iflock);
14284    return 0;
14285 }
14286 
14287 #if defined(HAVE_SS7)
14288 static void dahdi_ss7_message(struct ss7 *ss7, char *s)
14289 {
14290    int i;
14291 
14292    if (ss7) {
14293       for (i = 0; i < NUM_SPANS; i++) {
14294          if (linksets[i].ss7.ss7 == ss7) {
14295             ast_verbose_callid(NULL, "[%d] %s", i + 1, s);
14296             return;
14297          }
14298       }
14299    }
14300    ast_verbose_callid(NULL, "%s", s);
14301 }
14302 #endif   /* defined(HAVE_SS7) */
14303 
14304 #if defined(HAVE_SS7)
14305 static void dahdi_ss7_error(struct ss7 *ss7, char *s)
14306 {
14307    int i;
14308 
14309    if (ss7) {
14310       for (i = 0; i < NUM_SPANS; i++) {
14311          if (linksets[i].ss7.ss7 == ss7) {
14312             ast_log_callid(LOG_ERROR, NULL, "[%d] %s", i + 1, s);
14313             return;
14314          }
14315       }
14316    }
14317    ast_log_callid(LOG_ERROR, NULL, "%s", s);
14318 }
14319 #endif   /* defined(HAVE_SS7) */
14320 
14321 #if defined(HAVE_OPENR2)
14322 static void *mfcr2_monitor(void *data)
14323 {
14324    struct dahdi_mfcr2 *mfcr2 = data;
14325    /* we should be using pthread_key_create
14326       and allocate pollers dynamically.
14327       I think do_monitor() could be leaking, since it
14328       could be cancelled at any time and is not
14329       using thread keys, why?, */
14330    struct pollfd pollers[ARRAY_LEN(mfcr2->pvts)];
14331    int res = 0;
14332    int i = 0;
14333    int oldstate = 0;
14334    int quit_loop = 0;
14335    int maxsleep = 20;
14336    int was_idle = 0;
14337    int pollsize = 0;
14338    /* now that we're ready to get calls, unblock our side and
14339       get current line state */
14340    for (i = 0; i < mfcr2->numchans; i++) {
14341       openr2_chan_set_idle(mfcr2->pvts[i]->r2chan);
14342       openr2_chan_handle_cas(mfcr2->pvts[i]->r2chan);
14343    }
14344    while (1) {
14345       /* we trust here that the mfcr2 channel list will not ever change once
14346          the module is loaded */
14347       pollsize = 0;
14348       for (i = 0; i < mfcr2->numchans; i++) {
14349          pollers[i].revents = 0;
14350          pollers[i].events = 0;
14351          if (mfcr2->pvts[i]->owner) {
14352             continue;
14353          }
14354          if (!mfcr2->pvts[i]->r2chan) {
14355             ast_debug(1, "Wow, no r2chan on channel %d\n", mfcr2->pvts[i]->channel);
14356             quit_loop = 1;
14357             break;
14358          }
14359          openr2_chan_enable_read(mfcr2->pvts[i]->r2chan);
14360          pollers[i].events = POLLIN | POLLPRI;
14361          pollers[i].fd = mfcr2->pvts[i]->subs[SUB_REAL].dfd;
14362          pollsize++;
14363       }
14364       if (quit_loop) {
14365          break;
14366       }
14367       if (pollsize == 0) {
14368          if (!was_idle) {
14369             ast_debug(1, "Monitor thread going idle since everybody has an owner\n");
14370             was_idle = 1;
14371          }
14372          poll(NULL, 0, maxsleep);
14373          continue;
14374       }
14375       was_idle = 0;
14376       /* probably poll() is a valid cancel point, lets just be on the safe side
14377          by calling pthread_testcancel */
14378       pthread_testcancel();
14379       res = poll(pollers, mfcr2->numchans, maxsleep);
14380       pthread_testcancel();
14381       if ((res < 0) && (errno != EINTR)) {
14382          ast_log(LOG_ERROR, "going out, poll failed: %s\n", strerror(errno));
14383          break;
14384       }
14385       /* do we want to allow to cancel while processing events? */
14386       pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate);
14387       for (i = 0; i < mfcr2->numchans; i++) {
14388          if (pollers[i].revents & POLLPRI || pollers[i].revents & POLLIN) {
14389             openr2_chan_process_event(mfcr2->pvts[i]->r2chan);
14390          }
14391       }
14392       pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
14393    }
14394    ast_log(LOG_NOTICE, "Quitting MFC/R2 monitor thread\n");
14395    return 0;
14396 }
14397 #endif /* HAVE_OPENR2 */
14398 
14399 #if defined(HAVE_PRI)
14400 static void dahdi_pri_message(struct pri *pri, char *s)
14401 {
14402    int x;
14403    int y;
14404    int dchan = -1;
14405    int span = -1;
14406    int dchancount = 0;
14407 
14408    if (pri) {
14409       for (x = 0; x < NUM_SPANS; x++) {
14410          for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
14411             if (pris[x].pri.dchans[y]) {
14412                dchancount++;
14413             }
14414 
14415             if (pris[x].pri.dchans[y] == pri) {
14416                dchan = y;
14417             }
14418          }
14419          if (dchan >= 0) {
14420             span = x;
14421             break;
14422          }
14423          dchancount = 0;
14424       }
14425       if (-1 < span) {
14426          if (1 < dchancount) {
14427             ast_verbose_callid(NULL, "[PRI Span: %d D-Channel: %d] %s", span + 1, dchan, s);
14428          } else {
14429             ast_verbose_callid(NULL, "PRI Span: %d %s", span + 1, s);
14430          }
14431       } else {
14432          ast_verbose_callid(NULL, "PRI Span: ? %s", s);
14433       }
14434    } else {
14435       ast_verbose_callid(NULL, "PRI Span: ? %s", s);
14436    }
14437 
14438    ast_mutex_lock(&pridebugfdlock);
14439 
14440    if (pridebugfd >= 0) {
14441       if (write(pridebugfd, s, strlen(s)) < 0) {
14442          ast_log_callid(LOG_WARNING, NULL, "write() failed: %s\n", strerror(errno));
14443       }
14444    }
14445 
14446    ast_mutex_unlock(&pridebugfdlock);
14447 }
14448 #endif   /* defined(HAVE_PRI) */
14449 
14450 #if defined(HAVE_PRI)
14451 static void dahdi_pri_error(struct pri *pri, char *s)
14452 {
14453    int x;
14454    int y;
14455    int dchan = -1;
14456    int span = -1;
14457    int dchancount = 0;
14458 
14459    if (pri) {
14460       for (x = 0; x < NUM_SPANS; x++) {
14461          for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
14462             if (pris[x].pri.dchans[y]) {
14463                dchancount++;
14464             }
14465 
14466             if (pris[x].pri.dchans[y] == pri) {
14467                dchan = y;
14468             }
14469          }
14470          if (dchan >= 0) {
14471             span = x;
14472             break;
14473          }
14474          dchancount = 0;
14475       }
14476       if (-1 < span) {
14477          if (1 < dchancount) {
14478             ast_log_callid(LOG_ERROR, NULL, "[PRI Span: %d D-Channel: %d] %s", span + 1, dchan, s);
14479          } else {
14480             ast_log_callid(LOG_ERROR, NULL, "PRI Span: %d %s", span + 1, s);
14481          }
14482       } else {
14483          ast_log_callid(LOG_ERROR, NULL, "PRI Span: ? %s", s);
14484       }
14485    } else {
14486       ast_log_callid(LOG_ERROR, NULL, "PRI Span: ? %s", s);
14487    }
14488 
14489    ast_mutex_lock(&pridebugfdlock);
14490 
14491    if (pridebugfd >= 0) {
14492       if (write(pridebugfd, s, strlen(s)) < 0) {
14493          ast_log_callid(LOG_WARNING, NULL, "write() failed: %s\n", strerror(errno));
14494       }
14495    }
14496 
14497    ast_mutex_unlock(&pridebugfdlock);
14498 }
14499 #endif   /* defined(HAVE_PRI) */
14500 
14501 #if defined(HAVE_PRI)
14502 static int prepare_pri(struct dahdi_pri *pri)
14503 {
14504    int i, res, x;
14505    struct dahdi_params p;
14506    struct dahdi_bufferinfo bi;
14507    struct dahdi_spaninfo si;
14508 
14509    for (i = 0; i < SIG_PRI_NUM_DCHANS; i++) {
14510       if (!pri->dchannels[i])
14511          break;
14512       pri->pri.fds[i] = open("/dev/dahdi/channel", O_RDWR);
14513       x = pri->dchannels[i];
14514       if ((pri->pri.fds[i] < 0) || (ioctl(pri->pri.fds[i],DAHDI_SPECIFY,&x) == -1)) {
14515          ast_log(LOG_ERROR, "Unable to open D-channel %d (%s)\n", x, strerror(errno));
14516          return -1;
14517       }
14518       memset(&p, 0, sizeof(p));
14519       res = ioctl(pri->pri.fds[i], DAHDI_GET_PARAMS, &p);
14520       if (res) {
14521          dahdi_close_pri_fd(pri, i);
14522          ast_log(LOG_ERROR, "Unable to get parameters for D-channel %d (%s)\n", x, strerror(errno));
14523          return -1;
14524       }
14525       if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC)) {
14526          dahdi_close_pri_fd(pri, i);
14527          ast_log(LOG_ERROR, "D-channel %d is not in HDLC/FCS mode.\n", x);
14528          return -1;
14529       }
14530       memset(&si, 0, sizeof(si));
14531       res = ioctl(pri->pri.fds[i], DAHDI_SPANSTAT, &si);
14532       if (res) {
14533          dahdi_close_pri_fd(pri, i);
14534          ast_log(LOG_ERROR, "Unable to get span state for D-channel %d (%s)\n", x, strerror(errno));
14535       }
14536       if (!si.alarms) {
14537          pri_event_noalarm(&pri->pri, i, 1);
14538       } else {
14539          pri_event_alarm(&pri->pri, i, 1);
14540       }
14541       memset(&bi, 0, sizeof(bi));
14542       bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
14543       bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
14544       bi.numbufs = 32;
14545       bi.bufsize = 1024;
14546       if (ioctl(pri->pri.fds[i], DAHDI_SET_BUFINFO, &bi)) {
14547          ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", x, strerror(errno));
14548          dahdi_close_pri_fd(pri, i);
14549          return -1;
14550       }
14551       pri->pri.dchan_logical_span[i] = pris[p.spanno - 1].prilogicalspan;
14552    }
14553    return 0;
14554 }
14555 #endif   /* defined(HAVE_PRI) */
14556 
14557 #if defined(HAVE_PRI)
14558 static char *complete_span_helper(const char *line, const char *word, int pos, int state, int rpos)
14559 {
14560    int which, span;
14561    char *ret = NULL;
14562 
14563    if (pos != rpos)
14564       return ret;
14565 
14566    for (which = span = 0; span < NUM_SPANS; span++) {
14567       if (pris[span].pri.pri && ++which > state) {
14568          if (ast_asprintf(&ret, "%d", span + 1) < 0) {   /* user indexes start from 1 */
14569             ret = NULL;
14570          }
14571          break;
14572       }
14573    }
14574    return ret;
14575 }
14576 #endif   /* defined(HAVE_PRI) */
14577 
14578 #if defined(HAVE_PRI)
14579 static char *complete_span_4(const char *line, const char *word, int pos, int state)
14580 {
14581    return complete_span_helper(line,word,pos,state,3);
14582 }
14583 #endif   /* defined(HAVE_PRI) */
14584 
14585 #if defined(HAVE_PRI)
14586 static char *handle_pri_set_debug_file(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14587 {
14588    int myfd;
14589    switch (cmd) {
14590    case CLI_INIT:
14591       e->command = "pri set debug file";
14592       e->usage = "Usage: pri set debug file [output-file]\n"
14593          "       Sends PRI debug output to the specified output file\n";
14594       return NULL;
14595    case CLI_GENERATE:
14596       return NULL;
14597    }
14598    if (a->argc < 5)
14599       return CLI_SHOWUSAGE;
14600 
14601    if (ast_strlen_zero(a->argv[4]))
14602       return CLI_SHOWUSAGE;
14603 
14604    myfd = open(a->argv[4], O_CREAT|O_WRONLY, AST_FILE_MODE);
14605    if (myfd < 0) {
14606       ast_cli(a->fd, "Unable to open '%s' for writing\n", a->argv[4]);
14607       return CLI_SUCCESS;
14608    }
14609 
14610    ast_mutex_lock(&pridebugfdlock);
14611 
14612    if (pridebugfd >= 0)
14613       close(pridebugfd);
14614 
14615    pridebugfd = myfd;
14616    ast_copy_string(pridebugfilename,a->argv[4],sizeof(pridebugfilename));
14617    ast_mutex_unlock(&pridebugfdlock);
14618    ast_cli(a->fd, "PRI debug output will be sent to '%s'\n", a->argv[4]);
14619    return CLI_SUCCESS;
14620 }
14621 #endif   /* defined(HAVE_PRI) */
14622 
14623 #if defined(HAVE_PRI)
14624 static char *handle_pri_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14625 {
14626    int span;
14627    int x;
14628    int debugmask = 0;
14629    int level = 0;
14630    switch (cmd) {
14631    case CLI_INIT:
14632       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";
14633       e->usage =
14634          "Usage: pri set debug {<level>|on|off|hex|intense} span <span>\n"
14635          "       Enables debugging on a given PRI span\n"
14636          "  Level is a bitmap of the following values:\n"
14637          "  1 General debugging incl. state changes\n"
14638          "  2 Decoded Q.931 messages\n"
14639          "  4 Decoded Q.921 messages\n"
14640          "  8 Raw hex dumps of Q.921 frames\n"
14641          "       on - equivalent to 3\n"
14642          "       hex - equivalent to 8\n"
14643          "       intense - equivalent to 15\n";
14644       return NULL;
14645    case CLI_GENERATE:
14646       return complete_span_4(a->line, a->word, a->pos, a->n);
14647    }
14648    if (a->argc < 6) {
14649       return CLI_SHOWUSAGE;
14650    }
14651 
14652    if (!strcasecmp(a->argv[3], "on")) {
14653       level = 3;
14654    } else if (!strcasecmp(a->argv[3], "off")) {
14655       level = 0;
14656    } else if (!strcasecmp(a->argv[3], "intense")) {
14657       level = 15;
14658    } else if (!strcasecmp(a->argv[3], "hex")) {
14659       level = 8;
14660    } else {
14661       level = atoi(a->argv[3]);
14662    }
14663    span = atoi(a->argv[5]);
14664    if ((span < 1) || (span > NUM_SPANS)) {
14665       ast_cli(a->fd, "Invalid span %s.  Should be a number %d to %d\n", a->argv[5], 1, NUM_SPANS);
14666       return CLI_SUCCESS;
14667    }
14668    if (!pris[span-1].pri.pri) {
14669       ast_cli(a->fd, "No PRI running on span %d\n", span);
14670       return CLI_SUCCESS;
14671    }
14672 
14673    if (level & 1) debugmask |= SIG_PRI_DEBUG_NORMAL;
14674    if (level & 2) debugmask |= PRI_DEBUG_Q931_DUMP;
14675    if (level & 4) debugmask |= PRI_DEBUG_Q921_DUMP;
14676    if (level & 8) debugmask |= PRI_DEBUG_Q921_RAW;
14677 
14678    /* Set debug level in libpri */
14679    for (x = 0; x < SIG_PRI_NUM_DCHANS; x++) {
14680       if (pris[span - 1].pri.dchans[x]) {
14681          pri_set_debug(pris[span - 1].pri.dchans[x], debugmask);
14682       }
14683    }
14684    if (level == 0) {
14685       /* Close the debugging file if it's set */
14686       ast_mutex_lock(&pridebugfdlock);
14687       if (0 <= pridebugfd) {
14688          close(pridebugfd);
14689          pridebugfd = -1;
14690          ast_cli(a->fd, "Disabled PRI debug output to file '%s'\n",
14691             pridebugfilename);
14692       }
14693       ast_mutex_unlock(&pridebugfdlock);
14694    }
14695    pris[span - 1].pri.debug = (level) ? 1 : 0;
14696    ast_cli(a->fd, "%s debugging on span %d\n", (level) ? "Enabled" : "Disabled", span);
14697    return CLI_SUCCESS;
14698 }
14699 #endif   /* defined(HAVE_PRI) */
14700 
14701 #if defined(HAVE_PRI)
14702 #if defined(HAVE_PRI_SERVICE_MESSAGES)
14703 static char *handle_pri_service_generic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a, int changestatus)
14704 {
14705    unsigned *why;
14706    int channel;
14707    int trunkgroup;
14708    int x, y, fd = a->fd;
14709    int interfaceid = 0;
14710    char db_chan_name[20], db_answer[5];
14711    struct dahdi_pvt *tmp;
14712    struct dahdi_pri *pri;
14713 
14714    if (a->argc < 5 || a->argc > 6)
14715       return CLI_SHOWUSAGE;
14716    if (strchr(a->argv[4], ':')) {
14717       if (sscanf(a->argv[4], "%30d:%30d", &trunkgroup, &channel) != 2)
14718          return CLI_SHOWUSAGE;
14719       if ((trunkgroup < 1) || (channel < 1))
14720          return CLI_SHOWUSAGE;
14721       pri = NULL;
14722       for (x=0;x<NUM_SPANS;x++) {
14723          if (pris[x].pri.trunkgroup == trunkgroup) {
14724             pri = pris + x;
14725             break;
14726          }
14727       }
14728       if (!pri) {
14729          ast_cli(fd, "No such trunk group %d\n", trunkgroup);
14730          return CLI_FAILURE;
14731       }
14732    } else
14733       channel = atoi(a->argv[4]);
14734 
14735    if (a->argc == 6)
14736       interfaceid = atoi(a->argv[5]);
14737 
14738    /* either servicing a D-Channel */
14739    for (x = 0; x < NUM_SPANS; x++) {
14740       for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
14741          if (pris[x].dchannels[y] == channel) {
14742             pri = pris + x;
14743             if (pri->pri.enable_service_message_support) {
14744                ast_mutex_lock(&pri->pri.lock);
14745                pri_maintenance_service(pri->pri.pri, interfaceid, -1, changestatus);
14746                ast_mutex_unlock(&pri->pri.lock);
14747             } else {
14748                ast_cli(fd,
14749                   "\n\tThis operation has not been enabled in chan_dahdi.conf, set 'service_message_support=yes' to use this operation.\n"
14750                   "\tNote only 4ESS, 5ESS, and NI2 switch types are supported.\n\n");
14751             }
14752             return CLI_SUCCESS;
14753          }
14754       }
14755    }
14756 
14757    /* or servicing a B-Channel */
14758    ast_mutex_lock(&iflock);
14759    for (tmp = iflist; tmp; tmp = tmp->next) {
14760       if (tmp->pri && tmp->channel == channel) {
14761          ast_mutex_unlock(&iflock);
14762          ast_mutex_lock(&tmp->pri->lock);
14763          if (!tmp->pri->enable_service_message_support) {
14764             ast_mutex_unlock(&tmp->pri->lock);
14765             ast_cli(fd,
14766                "\n\tThis operation has not been enabled in chan_dahdi.conf, set 'service_message_support=yes' to use this operation.\n"
14767                "\tNote only 4ESS, 5ESS, and NI2 switch types are supported.\n\n");
14768             return CLI_SUCCESS;
14769          }
14770          snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, tmp->span, channel);
14771          why = &((struct sig_pri_chan *) tmp->sig_pvt)->service_status;
14772          switch(changestatus) {
14773          case 0: /* enable */
14774             /* Near end wants to be in service now. */
14775             ast_db_del(db_chan_name, SRVST_DBKEY);
14776             *why &= ~SRVST_NEAREND;
14777             if (*why) {
14778                snprintf(db_answer, sizeof(db_answer), "%s:%u", SRVST_TYPE_OOS, *why);
14779                ast_db_put(db_chan_name, SRVST_DBKEY, db_answer);
14780             } else {
14781                dahdi_pri_update_span_devstate(tmp->pri);
14782             }
14783             break;
14784          /* case 1:  -- loop */
14785          case 2: /* disable */
14786             /* Near end wants to be out-of-service now. */
14787             ast_db_del(db_chan_name, SRVST_DBKEY);
14788             *why |= SRVST_NEAREND;
14789             snprintf(db_answer, sizeof(db_answer), "%s:%u", SRVST_TYPE_OOS, *why);
14790             ast_db_put(db_chan_name, SRVST_DBKEY, db_answer);
14791             dahdi_pri_update_span_devstate(tmp->pri);
14792             break;
14793          /* case 3:  -- continuity */
14794          /* case 4:  -- shutdown */
14795          default:
14796             ast_log(LOG_WARNING, "Unsupported changestatus: '%d'\n", changestatus);
14797             break;
14798          }
14799          pri_maintenance_bservice(tmp->pri->pri, tmp->sig_pvt, changestatus);
14800          ast_mutex_unlock(&tmp->pri->lock);
14801          return CLI_SUCCESS;
14802       }
14803    }
14804    ast_mutex_unlock(&iflock);
14805 
14806    ast_cli(fd, "Unable to find given channel %d, possibly not a PRI\n", channel);
14807    return CLI_FAILURE;
14808 }
14809 
14810 static char *handle_pri_service_enable_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14811 {
14812    switch (cmd) {
14813    case CLI_INIT:
14814       e->command = "pri service enable channel";
14815       e->usage =
14816          "Usage: pri service enable channel <channel> [<interface id>]\n"
14817          "       Send an AT&T / NFAS / CCS ANSI T1.607 maintenance message\n"
14818          "  to restore a channel to service, with optional interface id\n"
14819          "  as agreed upon with remote switch operator\n";
14820       return NULL;
14821    case CLI_GENERATE:
14822       return NULL;
14823    }
14824    return handle_pri_service_generic(e, cmd, a, 0);
14825 }
14826 
14827 static char *handle_pri_service_disable_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14828 {
14829    switch (cmd) {
14830    case CLI_INIT:
14831       e->command = "pri service disable channel";
14832       e->usage =
14833          "Usage: pri service disable channel <chan num> [<interface id>]\n"
14834          "  Send an AT&T / NFAS / CCS ANSI T1.607 maintenance message\n"
14835          "  to remove a channel from service, with optional interface id\n"
14836          "  as agreed upon with remote switch operator\n";
14837       return NULL;
14838    case CLI_GENERATE:
14839       return NULL;
14840    }
14841    return handle_pri_service_generic(e, cmd, a, 2);
14842 }
14843 #endif   /* defined(HAVE_PRI_SERVICE_MESSAGES) */
14844 #endif   /* defined(HAVE_PRI) */
14845 
14846 #if defined(HAVE_PRI)
14847 static char *handle_pri_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14848 {
14849    int span;
14850 
14851    switch (cmd) {
14852    case CLI_INIT:
14853       e->command = "pri show channels";
14854       e->usage =
14855          "Usage: pri show channels\n"
14856          "       Displays PRI channel information such as the current mapping\n"
14857          "       of DAHDI B channels to Asterisk channel names and which calls\n"
14858          "       are on hold or call-waiting.  Calls on hold or call-waiting\n"
14859          "       are not associated with any B channel.\n";
14860       return NULL;
14861    case CLI_GENERATE:
14862       return NULL;
14863    }
14864 
14865    if (a->argc != 3)
14866       return CLI_SHOWUSAGE;
14867 
14868    sig_pri_cli_show_channels_header(a->fd);
14869    for (span = 0; span < NUM_SPANS; ++span) {
14870       if (pris[span].pri.pri) {
14871          sig_pri_cli_show_channels(a->fd, &pris[span].pri);
14872       }
14873    }
14874    return CLI_SUCCESS;
14875 }
14876 #endif   /* defined(HAVE_PRI) */
14877 
14878 #if defined(HAVE_PRI)
14879 static char *handle_pri_show_spans(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14880 {
14881    int span;
14882 
14883    switch (cmd) {
14884    case CLI_INIT:
14885       e->command = "pri show spans";
14886       e->usage =
14887          "Usage: pri show spans\n"
14888          "       Displays PRI span information\n";
14889       return NULL;
14890    case CLI_GENERATE:
14891       return NULL;
14892    }
14893 
14894    if (a->argc != 3)
14895       return CLI_SHOWUSAGE;
14896 
14897    for (span = 0; span < NUM_SPANS; span++) {
14898       if (pris[span].pri.pri) {
14899          sig_pri_cli_show_spans(a->fd, span + 1, &pris[span].pri);
14900       }
14901    }
14902    return CLI_SUCCESS;
14903 }
14904 #endif   /* defined(HAVE_PRI) */
14905 
14906 #if defined(HAVE_PRI)
14907 #define container_of(ptr, type, member) \
14908    ((type *)((char *)(ptr) - offsetof(type, member)))
14909 /*!
14910  * \internal
14911  * \brief Destroy a D-Channel of a PRI span
14912  * \since 12
14913  *
14914  * \param pri the pri span
14915  *
14916  * \return TRUE if the span was valid and we attempted destroying.
14917  *
14918  * Shuts down a span and destroys its D-Channel. Further destruction
14919  * of the B-channels using dahdi_destroy_channel() would probably be required
14920  * for the B-Channels.
14921  */
14922 static int pri_destroy_dchan(struct sig_pri_span *pri)
14923 {
14924    int i;
14925    struct dahdi_pri* dahdi_pri;
14926 
14927    if (!pri->master || (pri->master == AST_PTHREADT_NULL)) {
14928       return 0;
14929    }
14930    pthread_cancel(pri->master);
14931    pthread_join(pri->master, NULL);
14932 
14933    /* The 'struct dahdi_pri' that contains our 'struct sig_pri_span' */
14934    dahdi_pri = container_of(pri, struct dahdi_pri, pri);
14935    for (i = 0; i < SIG_PRI_NUM_DCHANS; i++) {
14936       ast_debug(4, "closing pri_fd %d\n", i);
14937       dahdi_close_pri_fd(dahdi_pri, i);
14938    }
14939    pri->pri = NULL;
14940    ast_debug(1, "PRI span %d destroyed\n", pri->span);
14941    return 1;
14942 }
14943 
14944 static char *handle_pri_destroy_span(struct ast_cli_entry *e, int cmd,
14945       struct ast_cli_args *a)
14946 {
14947    int span;
14948    int i;
14949    int res;
14950 
14951    switch (cmd) {
14952    case CLI_INIT:
14953       e->command = "pri destroy span";
14954       e->usage =
14955          "Usage: pri destroy span <span>\n"
14956          "       Destorys D-channel of span and its B-channels.\n"
14957          "  DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n";
14958       return NULL;
14959    case CLI_GENERATE:
14960       return complete_span_4(a->line, a->word, a->pos, a->n);
14961    }
14962 
14963    if (a->argc < 4) {
14964       return CLI_SHOWUSAGE;
14965    }
14966    res = sscanf(a->argv[3], "%30d", &span);
14967    if ((res != 1) || span < 1 || span > NUM_SPANS) {
14968       ast_cli(a->fd,
14969          "Invalid span '%s'.  Should be a number from %d to %d\n",
14970          a->argv[3], 1, NUM_SPANS);
14971       return CLI_SUCCESS;
14972    }
14973    if (!pris[span - 1].pri.pri) {
14974       ast_cli(a->fd, "No PRI running on span %d\n", span);
14975       return CLI_SUCCESS;
14976    }
14977 
14978    for (i = 0; i < pris[span - 1].pri.numchans; i++) {
14979       int channel;
14980       struct sig_pri_chan *pvt = pris[span - 1].pri.pvts[i];
14981 
14982       if (!pvt) {
14983          continue;
14984       }
14985       channel = pvt->channel;
14986       ast_debug(2, "About to destroy B-channel %d.\n", channel);
14987       dahdi_destroy_channel_bynum(channel);
14988    }
14989    ast_debug(2, "About to destroy D-channel of span %d.\n", span);
14990    pri_destroy_dchan(&pris[span - 1].pri);
14991 
14992    return CLI_SUCCESS;
14993 }
14994 
14995 #endif   /* defined(HAVE_PRI) */
14996 
14997 #if defined(HAVE_PRI)
14998 static char *handle_pri_show_span(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14999 {
15000    int span;
15001 
15002    switch (cmd) {
15003    case CLI_INIT:
15004       e->command = "pri show span";
15005       e->usage =
15006          "Usage: pri show span <span>\n"
15007          "       Displays PRI Information on a given PRI span\n";
15008       return NULL;
15009    case CLI_GENERATE:
15010       return complete_span_4(a->line, a->word, a->pos, a->n);
15011    }
15012 
15013    if (a->argc < 4)
15014       return CLI_SHOWUSAGE;
15015    span = atoi(a->argv[3]);
15016    if ((span < 1) || (span > NUM_SPANS)) {
15017       ast_cli(a->fd, "Invalid span '%s'.  Should be a number from %d to %d\n", a->argv[3], 1, NUM_SPANS);
15018       return CLI_SUCCESS;
15019    }
15020    if (!pris[span-1].pri.pri) {
15021       ast_cli(a->fd, "No PRI running on span %d\n", span);
15022       return CLI_SUCCESS;
15023    }
15024 
15025    sig_pri_cli_show_span(a->fd, pris[span-1].dchannels, &pris[span-1].pri);
15026 
15027    return CLI_SUCCESS;
15028 }
15029 #endif   /* defined(HAVE_PRI) */
15030 
15031 #if defined(HAVE_PRI)
15032 static char *handle_pri_show_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15033 {
15034    int x;
15035    int span;
15036    int count=0;
15037    int debug;
15038 
15039    switch (cmd) {
15040    case CLI_INIT:
15041       e->command = "pri show debug";
15042       e->usage =
15043          "Usage: pri show debug\n"
15044          "  Show the debug state of pri spans\n";
15045       return NULL;
15046    case CLI_GENERATE:
15047       return NULL;
15048    }
15049 
15050    for (span = 0; span < NUM_SPANS; span++) {
15051       if (pris[span].pri.pri) {
15052          for (x = 0; x < SIG_PRI_NUM_DCHANS; x++) {
15053             if (pris[span].pri.dchans[x]) {
15054                debug = pri_get_debug(pris[span].pri.dchans[x]);
15055                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" );
15056                count++;
15057             }
15058          }
15059       }
15060 
15061    }
15062    ast_mutex_lock(&pridebugfdlock);
15063    if (pridebugfd >= 0)
15064       ast_cli(a->fd, "Logging PRI debug to file %s\n", pridebugfilename);
15065    ast_mutex_unlock(&pridebugfdlock);
15066 
15067    if (!count)
15068       ast_cli(a->fd, "No PRI running\n");
15069    return CLI_SUCCESS;
15070 }
15071 #endif   /* defined(HAVE_PRI) */
15072 
15073 #if defined(HAVE_PRI)
15074 static char *handle_pri_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15075 {
15076    switch (cmd) {
15077    case CLI_INIT:
15078       e->command = "pri show version";
15079       e->usage =
15080          "Usage: pri show version\n"
15081          "Show libpri version information\n";
15082       return NULL;
15083    case CLI_GENERATE:
15084       return NULL;
15085    }
15086 
15087    ast_cli(a->fd, "libpri version: %s\n", pri_get_version());
15088 
15089    return CLI_SUCCESS;
15090 }
15091 #endif   /* defined(HAVE_PRI) */
15092 
15093 #if defined(HAVE_PRI)
15094 static struct ast_cli_entry dahdi_pri_cli[] = {
15095    AST_CLI_DEFINE(handle_pri_debug, "Enables PRI debugging on a span"),
15096 #if defined(HAVE_PRI_SERVICE_MESSAGES)
15097    AST_CLI_DEFINE(handle_pri_service_enable_channel, "Return a channel to service"),
15098    AST_CLI_DEFINE(handle_pri_service_disable_channel, "Remove a channel from service"),
15099 #endif   /* defined(HAVE_PRI_SERVICE_MESSAGES) */
15100    AST_CLI_DEFINE(handle_pri_show_channels, "Displays PRI channel information"),
15101    AST_CLI_DEFINE(handle_pri_show_spans, "Displays PRI span information"),
15102    AST_CLI_DEFINE(handle_pri_show_span, "Displays PRI span information"),
15103    AST_CLI_DEFINE(handle_pri_destroy_span, "Destroy a PRI span"),
15104    AST_CLI_DEFINE(handle_pri_show_debug, "Displays current PRI debug settings"),
15105    AST_CLI_DEFINE(handle_pri_set_debug_file, "Sends PRI debug output to the specified file"),
15106    AST_CLI_DEFINE(handle_pri_version, "Displays libpri version"),
15107 };
15108 #endif   /* defined(HAVE_PRI) */
15109 
15110 #ifdef HAVE_OPENR2
15111 
15112 static char *handle_mfcr2_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15113 {
15114    switch (cmd) {
15115    case CLI_INIT:
15116       e->command = "mfcr2 show version";
15117       e->usage =
15118          "Usage: mfcr2 show version\n"
15119          "       Shows the version of the OpenR2 library being used.\n";
15120       return NULL;
15121    case CLI_GENERATE:
15122       return NULL;
15123    }
15124    ast_cli(a->fd, "OpenR2 version: %s, revision: %s\n", openr2_get_version(), openr2_get_revision());
15125    return CLI_SUCCESS;
15126 }
15127 
15128 static char *handle_mfcr2_show_variants(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15129 {
15130 #define FORMAT "%4s %40s\n"
15131    int i = 0;
15132    int numvariants = 0;
15133    const openr2_variant_entry_t *variants;
15134    switch (cmd) {
15135    case CLI_INIT:
15136       e->command = "mfcr2 show variants";
15137       e->usage =
15138          "Usage: mfcr2 show variants\n"
15139          "       Shows the list of MFC/R2 variants supported.\n";
15140       return NULL;
15141    case CLI_GENERATE:
15142       return NULL;
15143    }
15144    if (!(variants = openr2_proto_get_variant_list(&numvariants))) {
15145       ast_cli(a->fd, "Failed to get list of variants.\n");
15146       return CLI_FAILURE;
15147    }
15148    ast_cli(a->fd, FORMAT, "Variant Code", "Country");
15149    for (i = 0; i < numvariants; i++) {
15150       ast_cli(a->fd, FORMAT, variants[i].name, variants[i].country);
15151    }
15152    return CLI_SUCCESS;
15153 #undef FORMAT
15154 }
15155 
15156 static char *handle_mfcr2_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15157 {
15158 #define FORMAT "%4s %-7.7s %-7.7s %-8.8s %-9.9s %-16.16s %-8.8s %-8.8s\n"
15159    int filtertype = 0;
15160    int targetnum = 0;
15161    char channo[5];
15162    char anino[5];
15163    char dnisno[5];
15164    struct dahdi_pvt *p;
15165    openr2_context_t *r2context;
15166    openr2_variant_t r2variant;
15167    switch (cmd) {
15168    case CLI_INIT:
15169       e->command = "mfcr2 show channels [group|context]";
15170       e->usage =
15171          "Usage: mfcr2 show channels [group <group> | context <context>]\n"
15172          "       Shows the DAHDI channels configured with MFC/R2 signaling.\n";
15173       return NULL;
15174    case CLI_GENERATE:
15175       return NULL;
15176    }
15177    if (!((a->argc == 3) || (a->argc == 5))) {
15178       return CLI_SHOWUSAGE;
15179    }
15180    if (a->argc == 5) {
15181       if (!strcasecmp(a->argv[3], "group")) {
15182          targetnum = atoi(a->argv[4]);
15183          if ((targetnum < 0) || (targetnum > 63))
15184             return CLI_SHOWUSAGE;
15185          targetnum = 1 << targetnum;
15186          filtertype = 1;
15187       } else if (!strcasecmp(a->argv[3], "context")) {
15188          filtertype = 2;
15189       } else {
15190          return CLI_SHOWUSAGE;
15191       }
15192    }
15193    ast_cli(a->fd, FORMAT, "Chan", "Variant", "Max ANI", "Max DNIS", "ANI First", "Immediate Accept", "Tx CAS", "Rx CAS");
15194    ast_mutex_lock(&iflock);
15195    for (p = iflist; p; p = p->next) {
15196       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
15197          continue;
15198       }
15199       if (filtertype) {
15200          switch(filtertype) {
15201          case 1: /* mfcr2 show channels group <group> */
15202             if (p->group != targetnum) {
15203                continue;
15204             }
15205             break;
15206          case 2: /* mfcr2 show channels context <context> */
15207             if (strcasecmp(p->context, a->argv[4])) {
15208                continue;
15209             }
15210             break;
15211          default:
15212             ;
15213          }
15214       }
15215       r2context = openr2_chan_get_context(p->r2chan);
15216       r2variant = openr2_context_get_variant(r2context);
15217       snprintf(channo, sizeof(channo), "%d", p->channel);
15218       snprintf(anino, sizeof(anino), "%d", openr2_context_get_max_ani(r2context));
15219       snprintf(dnisno, sizeof(dnisno), "%d", openr2_context_get_max_dnis(r2context));
15220       ast_cli(a->fd, FORMAT, channo, openr2_proto_get_variant_string(r2variant),
15221             anino, dnisno, openr2_context_get_ani_first(r2context) ? "Yes" : "No",
15222             openr2_context_get_immediate_accept(r2context) ? "Yes" : "No",
15223             openr2_chan_get_tx_cas_string(p->r2chan), openr2_chan_get_rx_cas_string(p->r2chan));
15224    }
15225    ast_mutex_unlock(&iflock);
15226    return CLI_SUCCESS;
15227 #undef FORMAT
15228 }
15229 
15230 static char *handle_mfcr2_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15231 {
15232    struct dahdi_pvt *p = NULL;
15233    int channo = 0;
15234    char *toklevel = NULL;
15235    char *saveptr = NULL;
15236    char *logval = NULL;
15237    openr2_log_level_t loglevel = OR2_LOG_NOTHING;
15238    openr2_log_level_t tmplevel = OR2_LOG_NOTHING;
15239    switch (cmd) {
15240    case CLI_INIT:
15241       e->command = "mfcr2 set debug";
15242       e->usage =
15243          "Usage: mfcr2 set debug <loglevel> <channel>\n"
15244          "       Set a new logging level for the specified channel.\n"
15245          "       If no channel is specified the logging level will be applied to all channels.\n";
15246       return NULL;
15247    case CLI_GENERATE:
15248       return NULL;
15249    }
15250    if (a->argc < 4) {
15251       return CLI_SHOWUSAGE;
15252    }
15253    channo = (a->argc == 5) ? atoi(a->argv[4]) : -1;
15254    logval = ast_strdupa(a->argv[3]);
15255    toklevel = strtok_r(logval, ",", &saveptr);
15256    if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
15257       ast_cli(a->fd, "Invalid MFC/R2 logging level '%s'.\n", a->argv[3]);
15258       return CLI_FAILURE;
15259    } else if (OR2_LOG_NOTHING == tmplevel) {
15260       loglevel = tmplevel;
15261    } else {
15262       loglevel |= tmplevel;
15263       while ((toklevel = strtok_r(NULL, ",", &saveptr))) {
15264          if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
15265             ast_cli(a->fd, "Ignoring invalid logging level: '%s'.\n", toklevel);
15266             continue;
15267          }
15268          loglevel |= tmplevel;
15269       }
15270    }
15271    ast_mutex_lock(&iflock);
15272    for (p = iflist; p; p = p->next) {
15273       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
15274          continue;
15275       }
15276       if ((channo != -1) && (p->channel != channo )) {
15277          continue;
15278       }
15279       openr2_chan_set_log_level(p->r2chan, loglevel);
15280       if (channo != -1) {
15281          ast_cli(a->fd, "MFC/R2 debugging set to '%s' for channel %d.\n", a->argv[3], p->channel);
15282          break;
15283       }
15284    }
15285    if ((channo != -1) && !p) {
15286       ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
15287    }
15288    if (channo == -1) {
15289       ast_cli(a->fd, "MFC/R2 debugging set to '%s' for all channels.\n", a->argv[3]);
15290    }
15291    ast_mutex_unlock(&iflock);
15292    return CLI_SUCCESS;
15293 }
15294 
15295 static char *handle_mfcr2_call_files(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15296 {
15297    struct dahdi_pvt *p = NULL;
15298    int channo = 0;
15299    switch (cmd) {
15300    case CLI_INIT:
15301       e->command = "mfcr2 call files [on|off]";
15302       e->usage =
15303          "Usage: mfcr2 call files [on|off] <channel>\n"
15304          "       Enable call files creation on the specified channel.\n"
15305          "       If no channel is specified call files creation policy will be applied to all channels.\n";
15306       return NULL;
15307    case CLI_GENERATE:
15308       return NULL;
15309    }
15310    if (a->argc < 4) {
15311       return CLI_SHOWUSAGE;
15312    }
15313    channo = (a->argc == 5) ? atoi(a->argv[4]) : -1;
15314    ast_mutex_lock(&iflock);
15315    for (p = iflist; p; p = p->next) {
15316       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
15317          continue;
15318       }
15319       if ((channo != -1) && (p->channel != channo )) {
15320          continue;
15321       }
15322       if (ast_true(a->argv[3])) {
15323          openr2_chan_enable_call_files(p->r2chan);
15324       } else {
15325          openr2_chan_disable_call_files(p->r2chan);
15326       }
15327       if (channo != -1) {
15328          if (ast_true(a->argv[3])) {
15329             ast_cli(a->fd, "MFC/R2 call files enabled for channel %d.\n", p->channel);
15330          } else {
15331             ast_cli(a->fd, "MFC/R2 call files disabled for channel %d.\n", p->channel);
15332          }
15333          break;
15334       }
15335    }
15336    if ((channo != -1) && !p) {
15337       ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
15338    }
15339    if (channo == -1) {
15340       if (ast_true(a->argv[3])) {
15341          ast_cli(a->fd, "MFC/R2 Call files enabled for all channels.\n");
15342       } else {
15343          ast_cli(a->fd, "MFC/R2 Call files disabled for all channels.\n");
15344       }
15345    }
15346    ast_mutex_unlock(&iflock);
15347    return CLI_SUCCESS;
15348 }
15349 
15350 static char *handle_mfcr2_set_idle(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15351 {
15352    struct dahdi_pvt *p = NULL;
15353    int channo = 0;
15354    switch (cmd) {
15355    case CLI_INIT:
15356       e->command = "mfcr2 set idle";
15357       e->usage =
15358          "Usage: mfcr2 set idle <channel>\n"
15359          "       DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n"
15360          "       Force the given channel into IDLE state.\n"
15361          "       If no channel is specified, all channels will be set to IDLE.\n";
15362       return NULL;
15363    case CLI_GENERATE:
15364       return NULL;
15365    }
15366    channo = (a->argc == 4) ? atoi(a->argv[3]) : -1;
15367    ast_mutex_lock(&iflock);
15368    for (p = iflist; p; p = p->next) {
15369       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
15370          continue;
15371       }
15372       if ((channo != -1) && (p->channel != channo )) {
15373          continue;
15374       }
15375       openr2_chan_set_idle(p->r2chan);
15376       ast_mutex_lock(&p->lock);
15377       p->locallyblocked = 0;
15378       p->mfcr2call = 0;
15379       ast_mutex_unlock(&p->lock);
15380       if (channo != -1) {
15381          break;
15382       }
15383    }
15384    if ((channo != -1) && !p) {
15385       ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
15386    }
15387    ast_mutex_unlock(&iflock);
15388    return CLI_SUCCESS;
15389 }
15390 
15391 static char *handle_mfcr2_set_blocked(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15392 {
15393    struct dahdi_pvt *p = NULL;
15394    int channo = 0;
15395    switch (cmd) {
15396    case CLI_INIT:
15397       e->command = "mfcr2 set blocked";
15398       e->usage =
15399          "Usage: mfcr2 set blocked <channel>\n"
15400          "       DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n"
15401          "       Force the given channel into BLOCKED state.\n"
15402          "       If no channel is specified, all channels will be set to BLOCKED.\n";
15403       return NULL;
15404    case CLI_GENERATE:
15405       return NULL;
15406    }
15407    channo = (a->argc == 4) ? atoi(a->argv[3]) : -1;
15408    ast_mutex_lock(&iflock);
15409    for (p = iflist; p; p = p->next) {
15410       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
15411          continue;
15412       }
15413       if ((channo != -1) && (p->channel != channo )) {
15414          continue;
15415       }
15416       openr2_chan_set_blocked(p->r2chan);
15417       ast_mutex_lock(&p->lock);
15418       p->locallyblocked = 1;
15419       ast_mutex_unlock(&p->lock);
15420       if (channo != -1) {
15421          break;
15422       }
15423    }
15424    if ((channo != -1) && !p) {
15425       ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
15426    }
15427    ast_mutex_unlock(&iflock);
15428    return CLI_SUCCESS;
15429 }
15430 
15431 static struct ast_cli_entry dahdi_mfcr2_cli[] = {
15432    AST_CLI_DEFINE(handle_mfcr2_version, "Show OpenR2 library version"),
15433    AST_CLI_DEFINE(handle_mfcr2_show_variants, "Show supported MFC/R2 variants"),
15434    AST_CLI_DEFINE(handle_mfcr2_show_channels, "Show MFC/R2 channels"),
15435    AST_CLI_DEFINE(handle_mfcr2_set_debug, "Set MFC/R2 channel logging level"),
15436    AST_CLI_DEFINE(handle_mfcr2_call_files, "Enable/Disable MFC/R2 call files"),
15437    AST_CLI_DEFINE(handle_mfcr2_set_idle, "Reset MFC/R2 channel forcing it to IDLE"),
15438    AST_CLI_DEFINE(handle_mfcr2_set_blocked, "Reset MFC/R2 channel forcing it to BLOCKED"),
15439 };
15440 
15441 #endif /* HAVE_OPENR2 */
15442 
15443 static char *dahdi_destroy_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15444 {
15445    int channel;
15446    int ret;
15447    switch (cmd) {
15448    case CLI_INIT:
15449       e->command = "dahdi destroy channel";
15450       e->usage =
15451          "Usage: dahdi destroy channel <chan num>\n"
15452          "  DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.  Immediately removes a given channel, whether it is in use or not\n";
15453       return NULL;
15454    case CLI_GENERATE:
15455       return NULL;
15456    }
15457    if (a->argc != 4)
15458       return CLI_SHOWUSAGE;
15459 
15460    channel = atoi(a->argv[3]);
15461    ret = dahdi_destroy_channel_bynum(channel);
15462    return ( RESULT_SUCCESS == ret ) ? CLI_SUCCESS : CLI_FAILURE;
15463 }
15464 
15465 static void dahdi_softhangup_all(void)
15466 {
15467    struct dahdi_pvt *p;
15468 retry:
15469    ast_mutex_lock(&iflock);
15470    for (p = iflist; p; p = p->next) {
15471       ast_mutex_lock(&p->lock);
15472       if (p->owner && !p->restartpending) {
15473          if (ast_channel_trylock(p->owner)) {
15474             if (option_debug > 2)
15475                ast_verbose("Avoiding deadlock\n");
15476             /* Avoid deadlock since you're not supposed to lock iflock or pvt before a channel */
15477             ast_mutex_unlock(&p->lock);
15478             ast_mutex_unlock(&iflock);
15479             goto retry;
15480          }
15481          if (option_debug > 2)
15482             ast_verbose("Softhanging up on %s\n", ast_channel_name(p->owner));
15483          ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_EXPLICIT);
15484          p->restartpending = 1;
15485          num_restart_pending++;
15486          ast_channel_unlock(p->owner);
15487       }
15488       ast_mutex_unlock(&p->lock);
15489    }
15490    ast_mutex_unlock(&iflock);
15491 }
15492 
15493 static int setup_dahdi(int reload);
15494 static int dahdi_restart(void)
15495 {
15496 #if defined(HAVE_PRI) || defined(HAVE_SS7)
15497    int i, j;
15498 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
15499    int cancel_code;
15500    struct dahdi_pvt *p;
15501 
15502    ast_mutex_lock(&restart_lock);
15503    ast_verb(1, "Destroying channels and reloading DAHDI configuration.\n");
15504    dahdi_softhangup_all();
15505    ast_verb(4, "Initial softhangup of all DAHDI channels complete.\n");
15506 #ifdef HAVE_OPENR2
15507    dahdi_r2_destroy_links();
15508 #endif
15509 
15510 #if defined(HAVE_PRI)
15511    for (i = 0; i < NUM_SPANS; i++) {
15512       if (pris[i].pri.master && (pris[i].pri.master != AST_PTHREADT_NULL)) {
15513          cancel_code = pthread_cancel(pris[i].pri.master);
15514          pthread_kill(pris[i].pri.master, SIGURG);
15515          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);
15516          pthread_join(pris[i].pri.master, NULL);
15517          ast_debug(4, "Joined thread of span %d\n", i);
15518       }
15519    }
15520 #endif
15521 
15522 #if defined(HAVE_SS7)
15523    for (i = 0; i < NUM_SPANS; i++) {
15524       if (linksets[i].ss7.master && (linksets[i].ss7.master != AST_PTHREADT_NULL)) {
15525          cancel_code = pthread_cancel(linksets[i].ss7.master);
15526          pthread_kill(linksets[i].ss7.master, SIGURG);
15527          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);
15528          pthread_join(linksets[i].ss7.master, NULL);
15529          ast_debug(4, "Joined thread of span %d\n", i);
15530       }
15531    }
15532 #endif   /* defined(HAVE_SS7) */
15533 
15534    ast_mutex_lock(&monlock);
15535    if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
15536       cancel_code = pthread_cancel(monitor_thread);
15537       pthread_kill(monitor_thread, SIGURG);
15538       ast_debug(4, "Waiting to join monitor thread with pid=%p, cancel_code=%d\n", (void *) monitor_thread, cancel_code);
15539       pthread_join(monitor_thread, NULL);
15540       ast_debug(4, "Joined monitor thread\n");
15541    }
15542    monitor_thread = AST_PTHREADT_NULL; /* prepare to restart thread in setup_dahdi once channels are reconfigured */
15543 
15544    ast_mutex_lock(&ss_thread_lock);
15545    while (ss_thread_count > 0) { /* let ss_threads finish and run dahdi_hangup before dahvi_pvts are destroyed */
15546       int x = DAHDI_FLASH;
15547       ast_debug(3, "Waiting on %d analog_ss_thread(s) to finish\n", ss_thread_count);
15548 
15549       ast_mutex_lock(&iflock);
15550       for (p = iflist; p; p = p->next) {
15551          if (p->owner) {
15552             /* important to create an event for dahdi_wait_event to register so that all analog_ss_threads terminate */
15553             ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
15554          }
15555       }
15556       ast_mutex_unlock(&iflock);
15557       ast_cond_wait(&ss_thread_complete, &ss_thread_lock);
15558    }
15559 
15560    /* ensure any created channels before monitor threads were stopped are hungup */
15561    dahdi_softhangup_all();
15562    ast_verb(4, "Final softhangup of all DAHDI channels complete.\n");
15563    destroy_all_channels();
15564    memset(round_robin, 0, sizeof(round_robin));
15565    ast_debug(1, "Channels destroyed. Now re-reading config. %d active channels remaining.\n", ast_active_channels());
15566 
15567    ast_mutex_unlock(&monlock);
15568 
15569 #ifdef HAVE_PRI
15570    for (i = 0; i < NUM_SPANS; i++) {
15571       for (j = 0; j < SIG_PRI_NUM_DCHANS; j++)
15572          dahdi_close_pri_fd(&(pris[i]), j);
15573    }
15574 
15575    memset(pris, 0, sizeof(pris));
15576    for (i = 0; i < NUM_SPANS; i++) {
15577       sig_pri_init_pri(&pris[i].pri);
15578    }
15579    pri_set_error(dahdi_pri_error);
15580    pri_set_message(dahdi_pri_message);
15581 #endif
15582 #if defined(HAVE_SS7)
15583    for (i = 0; i < NUM_SPANS; i++) {
15584       for (j = 0; j < SIG_SS7_NUM_DCHANS; j++)
15585          dahdi_close_ss7_fd(&(linksets[i]), j);
15586    }
15587 
15588    memset(linksets, 0, sizeof(linksets));
15589    for (i = 0; i < NUM_SPANS; i++) {
15590       sig_ss7_init_linkset(&linksets[i].ss7);
15591    }
15592    ss7_set_error(dahdi_ss7_error);
15593    ss7_set_message(dahdi_ss7_message);
15594 #endif   /* defined(HAVE_SS7) */
15595 
15596    if (setup_dahdi(2) != 0) {
15597       ast_log(LOG_WARNING, "Reload channels from dahdi config failed!\n");
15598       ast_mutex_unlock(&ss_thread_lock);
15599       return 1;
15600    }
15601    ast_mutex_unlock(&ss_thread_lock);
15602    ast_mutex_unlock(&restart_lock);
15603    return 0;
15604 }
15605 
15606 static char *dahdi_restart_cmd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15607 {
15608    switch (cmd) {
15609    case CLI_INIT:
15610       e->command = "dahdi restart";
15611       e->usage =
15612          "Usage: dahdi restart\n"
15613          "  Restarts the DAHDI channels: destroys them all and then\n"
15614          "  re-reads them from chan_dahdi.conf.\n"
15615          "  Note that this will STOP any running CALL on DAHDI channels.\n"
15616          "";
15617       return NULL;
15618    case CLI_GENERATE:
15619       return NULL;
15620    }
15621    if (a->argc != 2)
15622       return CLI_SHOWUSAGE;
15623 
15624    if (dahdi_restart() != 0)
15625       return CLI_FAILURE;
15626    return CLI_SUCCESS;
15627 }
15628 
15629 static int action_dahdirestart(struct mansession *s, const struct message *m)
15630 {
15631    if (dahdi_restart() != 0) {
15632       astman_send_error(s, m, "Failed rereading DAHDI configuration");
15633       return 1;
15634    }
15635    astman_send_ack(s, m, "DAHDIRestart: Success");
15636    return 0;
15637 }
15638 
15639 static char *dahdi_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15640 {
15641 #define FORMAT "%7s %-15.15s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s %-32.32s\n"
15642 #define FORMAT2 "%7s %-15.15s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s %-32.32s\n"
15643    ast_group_t targetnum = 0;
15644    int filtertype = 0;
15645    struct dahdi_pvt *tmp = NULL;
15646    char tmps[20] = "";
15647    char statestr[20] = "";
15648    char blockstr[20] = "";
15649 
15650    switch (cmd) {
15651    case CLI_INIT:
15652       e->command = "dahdi show channels [group|context]";
15653       e->usage =
15654          "Usage: dahdi show channels [ group <group> | context <context> ]\n"
15655          "  Shows a list of available channels with optional filtering\n"
15656          "  <group> must be a number between 0 and 63\n";
15657       return NULL;
15658    case CLI_GENERATE:
15659       return NULL;
15660    }
15661 
15662    /* syntax: dahdi show channels [ group <group> | context <context> ] */
15663 
15664    if (!((a->argc == 3) || (a->argc == 5)))
15665       return CLI_SHOWUSAGE;
15666 
15667    if (a->argc == 5) {
15668       if (!strcasecmp(a->argv[3], "group")) {
15669          targetnum = atoi(a->argv[4]);
15670          if (63 < targetnum) {
15671             return CLI_SHOWUSAGE;
15672          }
15673          targetnum = ((ast_group_t) 1) << targetnum;
15674          filtertype = 1;
15675       } else if (!strcasecmp(a->argv[3], "context")) {
15676          filtertype = 2;
15677       }
15678    }
15679 
15680    ast_cli(a->fd, FORMAT2, "Chan", "Extension", "Context", "Language", "MOH Interpret", "Blocked", "State", "Description");
15681    ast_mutex_lock(&iflock);
15682    for (tmp = iflist; tmp; tmp = tmp->next) {
15683       if (filtertype) {
15684          switch(filtertype) {
15685          case 1: /* dahdi show channels group <group> */
15686             if (!(tmp->group & targetnum)) {
15687                continue;
15688             }
15689             break;
15690          case 2: /* dahdi show channels context <context> */
15691             if (strcasecmp(tmp->context, a->argv[4])) {
15692                continue;
15693             }
15694             break;
15695          default:
15696             break;
15697          }
15698       }
15699       if (tmp->channel > 0) {
15700          snprintf(tmps, sizeof(tmps), "%d", tmp->channel);
15701       } else
15702          ast_copy_string(tmps, "pseudo", sizeof(tmps));
15703 
15704       if (tmp->locallyblocked)
15705          blockstr[0] = 'L';
15706       else
15707          blockstr[0] = ' ';
15708 
15709       if (tmp->remotelyblocked)
15710          blockstr[1] = 'R';
15711       else
15712          blockstr[1] = ' ';
15713 
15714       blockstr[2] = '\0';
15715 
15716       snprintf(statestr, sizeof(statestr), "%s", "In Service");
15717 
15718       ast_cli(a->fd, FORMAT, tmps, tmp->exten, tmp->context, tmp->language, tmp->mohinterpret, blockstr, statestr, tmp->description);
15719    }
15720    ast_mutex_unlock(&iflock);
15721    return CLI_SUCCESS;
15722 #undef FORMAT
15723 #undef FORMAT2
15724 }
15725 
15726 static char *dahdi_show_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15727 {
15728    int channel;
15729    struct dahdi_pvt *tmp = NULL;
15730    struct dahdi_confinfo ci;
15731    struct dahdi_params ps;
15732    int x;
15733 
15734    switch (cmd) {
15735    case CLI_INIT:
15736       e->command = "dahdi show channel";
15737       e->usage =
15738          "Usage: dahdi show channel <chan num>\n"
15739          "  Detailed information about a given channel\n";
15740       return NULL;
15741    case CLI_GENERATE:
15742       return NULL;
15743    }
15744 
15745    if (a->argc != 4)
15746       return CLI_SHOWUSAGE;
15747 
15748    channel = atoi(a->argv[3]);
15749 
15750    ast_mutex_lock(&iflock);
15751    for (tmp = iflist; tmp; tmp = tmp->next) {
15752       if (tmp->channel == channel) {
15753          ast_cli(a->fd, "Channel: %d\n", tmp->channel);
15754          ast_cli(a->fd, "Description: %s\n", tmp->description);
15755          ast_cli(a->fd, "File Descriptor: %d\n", tmp->subs[SUB_REAL].dfd);
15756          ast_cli(a->fd, "Span: %d\n", tmp->span);
15757          ast_cli(a->fd, "Extension: %s\n", tmp->exten);
15758          ast_cli(a->fd, "Dialing: %s\n", tmp->dialing ? "yes" : "no");
15759          ast_cli(a->fd, "Context: %s\n", tmp->context);
15760          ast_cli(a->fd, "Caller ID: %s\n", tmp->cid_num);
15761          ast_cli(a->fd, "Calling TON: %d\n", tmp->cid_ton);
15762 #if defined(HAVE_PRI)
15763 #if defined(HAVE_PRI_SUBADDR)
15764          ast_cli(a->fd, "Caller ID subaddress: %s\n", tmp->cid_subaddr);
15765 #endif   /* defined(HAVE_PRI_SUBADDR) */
15766 #endif   /* defined(HAVE_PRI) */
15767          ast_cli(a->fd, "Caller ID name: %s\n", tmp->cid_name);
15768          ast_cli(a->fd, "Mailbox: %s\n", S_OR(tmp->mailbox, "none"));
15769          if (tmp->vars) {
15770             struct ast_variable *v;
15771             ast_cli(a->fd, "Variables:\n");
15772             for (v = tmp->vars ; v ; v = v->next)
15773                ast_cli(a->fd, "       %s = %s\n", v->name, v->value);
15774          }
15775          ast_cli(a->fd, "Destroy: %d\n", tmp->destroy);
15776          ast_cli(a->fd, "InAlarm: %d\n", tmp->inalarm);
15777          ast_cli(a->fd, "Signalling Type: %s\n", sig2str(tmp->sig));
15778          ast_cli(a->fd, "Radio: %d\n", tmp->radio);
15779          ast_cli(a->fd, "Owner: %s\n", tmp->owner ? ast_channel_name(tmp->owner) : "<None>");
15780          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)" : "");
15781          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)" : "");
15782          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)" : "");
15783          ast_cli(a->fd, "Confno: %d\n", tmp->confno);
15784          ast_cli(a->fd, "Propagated Conference: %d\n", tmp->propconfno);
15785          ast_cli(a->fd, "Real in conference: %d\n", tmp->inconference);
15786          ast_cli(a->fd, "DSP: %s\n", tmp->dsp ? "yes" : "no");
15787          ast_cli(a->fd, "Busy Detection: %s\n", tmp->busydetect ? "yes" : "no");
15788          if (tmp->busydetect) {
15789 #if defined(BUSYDETECT_TONEONLY)
15790             ast_cli(a->fd, "    Busy Detector Helper: BUSYDETECT_TONEONLY\n");
15791 #elif defined(BUSYDETECT_COMPARE_TONE_AND_SILENCE)
15792             ast_cli(a->fd, "    Busy Detector Helper: BUSYDETECT_COMPARE_TONE_AND_SILENCE\n");
15793 #endif
15794 #ifdef BUSYDETECT_DEBUG
15795             ast_cli(a->fd, "    Busy Detector Debug: Enabled\n");
15796 #endif
15797             ast_cli(a->fd, "    Busy Count: %d\n", tmp->busycount);
15798             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);
15799          }
15800          ast_cli(a->fd, "TDD: %s\n", tmp->tdd ? "yes" : "no");
15801          ast_cli(a->fd, "Relax DTMF: %s\n", tmp->dtmfrelax ? "yes" : "no");
15802          ast_cli(a->fd, "Dialing/CallwaitCAS: %d/%d\n", tmp->dialing, tmp->callwaitcas);
15803          ast_cli(a->fd, "Default law: %s\n", tmp->law_default == DAHDI_LAW_MULAW ? "ulaw" : tmp->law_default == DAHDI_LAW_ALAW ? "alaw" : "unknown");
15804          ast_cli(a->fd, "Fax Handled: %s\n", tmp->faxhandled ? "yes" : "no");
15805          ast_cli(a->fd, "Pulse phone: %s\n", tmp->pulsedial ? "yes" : "no");
15806          ast_cli(a->fd, "Gains (RX/TX): %.2f/%.2f\n", tmp->rxgain, tmp->txgain);
15807          ast_cli(a->fd, "Dynamic Range Compression (RX/TX): %.2f/%.2f\n", tmp->rxdrc, tmp->txdrc);
15808          ast_cli(a->fd, "DND: %s\n", dahdi_dnd(tmp, -1) ? "yes" : "no");
15809          ast_cli(a->fd, "Echo Cancellation:\n");
15810 
15811          if (tmp->echocancel.head.tap_length) {
15812             ast_cli(a->fd, "\t%d taps\n", tmp->echocancel.head.tap_length);
15813             for (x = 0; x < tmp->echocancel.head.param_count; x++) {
15814                ast_cli(a->fd, "\t\t%s: %ud\n", tmp->echocancel.params[x].name, tmp->echocancel.params[x].value);
15815             }
15816             ast_cli(a->fd, "\t%scurrently %s\n", tmp->echocanbridged ? "" : "(unless TDM bridged) ", tmp->echocanon ? "ON" : "OFF");
15817          } else {
15818             ast_cli(a->fd, "\tnone\n");
15819          }
15820          ast_cli(a->fd, "Wait for dialtone: %dms\n", tmp->waitfordialtone);
15821          if (tmp->master)
15822             ast_cli(a->fd, "Master Channel: %d\n", tmp->master->channel);
15823          for (x = 0; x < MAX_SLAVES; x++) {
15824             if (tmp->slaves[x])
15825                ast_cli(a->fd, "Slave Channel: %d\n", tmp->slaves[x]->channel);
15826          }
15827 #ifdef HAVE_OPENR2
15828          if (tmp->mfcr2) {
15829             char calldir[OR2_MAX_PATH];
15830             openr2_context_t *r2context = openr2_chan_get_context(tmp->r2chan);
15831             openr2_variant_t r2variant = openr2_context_get_variant(r2context);
15832             ast_cli(a->fd, "MFC/R2 MF State: %s\n", openr2_chan_get_mf_state_string(tmp->r2chan));
15833             ast_cli(a->fd, "MFC/R2 MF Group: %s\n", openr2_chan_get_mf_group_string(tmp->r2chan));
15834             ast_cli(a->fd, "MFC/R2 State: %s\n", openr2_chan_get_r2_state_string(tmp->r2chan));
15835             ast_cli(a->fd, "MFC/R2 Call State: %s\n", openr2_chan_get_call_state_string(tmp->r2chan));
15836             ast_cli(a->fd, "MFC/R2 Call Files Enabled: %s\n", openr2_chan_get_call_files_enabled(tmp->r2chan) ? "Yes" : "No");
15837             ast_cli(a->fd, "MFC/R2 Variant: %s\n", openr2_proto_get_variant_string(r2variant));
15838             ast_cli(a->fd, "MFC/R2 Max ANI: %d\n", openr2_context_get_max_ani(r2context));
15839             ast_cli(a->fd, "MFC/R2 Max DNIS: %d\n", openr2_context_get_max_dnis(r2context));
15840 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2
15841             ast_cli(a->fd, "MFC/R2 DTMF Dialing: %s\n", openr2_context_get_dtmf_dialing(r2context, NULL, NULL) ? "Yes" : "No");
15842             ast_cli(a->fd, "MFC/R2 DTMF Detection: %s\n", openr2_context_get_dtmf_detection(r2context) ? "Yes" : "No");
15843 #endif
15844             ast_cli(a->fd, "MFC/R2 Get ANI First: %s\n", openr2_context_get_ani_first(r2context) ? "Yes" : "No");
15845 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
15846             ast_cli(a->fd, "MFC/R2 Skip Category Request: %s\n", openr2_context_get_skip_category_request(r2context) ? "Yes" : "No");
15847 #endif
15848             ast_cli(a->fd, "MFC/R2 Immediate Accept: %s\n", openr2_context_get_immediate_accept(r2context) ? "Yes" : "No");
15849             ast_cli(a->fd, "MFC/R2 Accept on Offer: %s\n", tmp->mfcr2_accept_on_offer ? "Yes" : "No");
15850             ast_cli(a->fd, "MFC/R2 Charge Calls: %s\n", tmp->mfcr2_charge_calls ? "Yes" : "No");
15851             ast_cli(a->fd, "MFC/R2 Allow Collect Calls: %s\n", tmp->mfcr2_allow_collect_calls ? "Yes" : "No");
15852             ast_cli(a->fd, "MFC/R2 Forced Release: %s\n", tmp->mfcr2_forced_release ? "Yes" : "No");
15853             ast_cli(a->fd, "MFC/R2 MF Back Timeout: %dms\n", openr2_context_get_mf_back_timeout(r2context));
15854             ast_cli(a->fd, "MFC/R2 R2 Metering Pulse Timeout: %dms\n", openr2_context_get_metering_pulse_timeout(r2context));
15855             ast_cli(a->fd, "MFC/R2 Rx CAS: %s\n", openr2_chan_get_rx_cas_string(tmp->r2chan));
15856             ast_cli(a->fd, "MFC/R2 Tx CAS: %s\n", openr2_chan_get_tx_cas_string(tmp->r2chan));
15857             ast_cli(a->fd, "MFC/R2 MF Tx Signal: %d\n", openr2_chan_get_tx_mf_signal(tmp->r2chan));
15858             ast_cli(a->fd, "MFC/R2 MF Rx Signal: %d\n", openr2_chan_get_rx_mf_signal(tmp->r2chan));
15859             ast_cli(a->fd, "MFC/R2 Call Files Directory: %s\n", openr2_context_get_log_directory(r2context, calldir, sizeof(calldir)));
15860          }
15861 #endif
15862 #if defined(HAVE_SS7)
15863          if (tmp->ss7) {
15864             struct sig_ss7_chan *chan = tmp->sig_pvt;
15865 
15866             ast_cli(a->fd, "CIC: %d\n", chan->cic);
15867          }
15868 #endif   /* defined(HAVE_SS7) */
15869 #ifdef HAVE_PRI
15870          if (tmp->pri) {
15871             struct sig_pri_chan *chan = tmp->sig_pvt;
15872 
15873             ast_cli(a->fd, "PRI Flags: ");
15874             if (chan->resetting != SIG_PRI_RESET_IDLE) {
15875                ast_cli(a->fd, "Resetting=%d ", chan->resetting);
15876             }
15877             if (chan->call)
15878                ast_cli(a->fd, "Call ");
15879             if (chan->allocated) {
15880                ast_cli(a->fd, "Allocated ");
15881             }
15882             ast_cli(a->fd, "\n");
15883             if (tmp->logicalspan)
15884                ast_cli(a->fd, "PRI Logical Span: %d\n", tmp->logicalspan);
15885             else
15886                ast_cli(a->fd, "PRI Logical Span: Implicit\n");
15887          }
15888 #endif
15889          memset(&ci, 0, sizeof(ci));
15890          ps.channo = tmp->channel;
15891          if (tmp->subs[SUB_REAL].dfd > -1) {
15892             memset(&ci, 0, sizeof(ci));
15893             if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
15894                ast_cli(a->fd, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci.confno, ci.confmode);
15895             }
15896             if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONFMUTE, &x)) {
15897                ast_cli(a->fd, "Actual Confmute: %s\n", x ? "Yes" : "No");
15898             }
15899             memset(&ps, 0, sizeof(ps));
15900             if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
15901                ast_log(LOG_WARNING, "Failed to get parameters on channel %d: %s\n", tmp->channel, strerror(errno));
15902             } else {
15903                ast_cli(a->fd, "Hookstate (FXS only): %s\n", ps.rxisoffhook ? "Offhook" : "Onhook");
15904             }
15905          }
15906          ast_mutex_unlock(&iflock);
15907          return CLI_SUCCESS;
15908       }
15909    }
15910    ast_mutex_unlock(&iflock);
15911 
15912    ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15913    return CLI_FAILURE;
15914 }
15915 
15916 static char *handle_dahdi_show_cadences(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15917 {
15918    int i, j;
15919    switch (cmd) {
15920    case CLI_INIT:
15921       e->command = "dahdi show cadences";
15922       e->usage =
15923          "Usage: dahdi show cadences\n"
15924          "       Shows all cadences currently defined\n";
15925       return NULL;
15926    case CLI_GENERATE:
15927       return NULL;
15928    }
15929    for (i = 0; i < num_cadence; i++) {
15930       char output[1024];
15931       char tmp[16], tmp2[64];
15932       snprintf(tmp, sizeof(tmp), "r%d: ", i + 1);
15933       term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output));
15934 
15935       for (j = 0; j < 16; j++) {
15936          if (cadences[i].ringcadence[j] == 0)
15937             break;
15938          snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]);
15939          if (cidrings[i] * 2 - 1 == j)
15940             term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1);
15941          else
15942             term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1);
15943          if (j != 0)
15944             strncat(output, ",", sizeof(output) - strlen(output) - 1);
15945          strncat(output, tmp2, sizeof(output) - strlen(output) - 1);
15946       }
15947       ast_cli(a->fd,"%s\n",output);
15948    }
15949    return CLI_SUCCESS;
15950 }
15951 
15952 /* Based on irqmiss.c */
15953 static char *dahdi_show_status(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15954 {
15955    #define FORMAT "%-40.40s %-7.7s %-6d %-6d %-6d %-3.3s %-4.4s %-8.8s %s\n"
15956    #define FORMAT2 "%-40.40s %-7.7s %-6.6s %-6.6s %-6.6s %-3.3s %-4.4s %-8.8s %s\n"
15957    int span;
15958    int res;
15959    char alarmstr[50];
15960 
15961    int ctl;
15962    struct dahdi_spaninfo s;
15963 
15964    switch (cmd) {
15965    case CLI_INIT:
15966       e->command = "dahdi show status";
15967       e->usage =
15968          "Usage: dahdi show status\n"
15969          "       Shows a list of DAHDI cards with status\n";
15970       return NULL;
15971    case CLI_GENERATE:
15972       return NULL;
15973    }
15974    ctl = open("/dev/dahdi/ctl", O_RDWR);
15975    if (ctl < 0) {
15976       ast_cli(a->fd, "No DAHDI found. Unable to open /dev/dahdi/ctl: %s\n", strerror(errno));
15977       return CLI_FAILURE;
15978    }
15979    ast_cli(a->fd, FORMAT2, "Description", "Alarms", "IRQ", "bpviol", "CRC", "Framing", "Coding", "Options", "LBO");
15980 
15981    for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
15982       s.spanno = span;
15983       res = ioctl(ctl, DAHDI_SPANSTAT, &s);
15984       if (res) {
15985          continue;
15986       }
15987       alarmstr[0] = '\0';
15988       if (s.alarms > 0) {
15989          if (s.alarms & DAHDI_ALARM_BLUE)
15990             strcat(alarmstr, "BLU/");
15991          if (s.alarms & DAHDI_ALARM_YELLOW)
15992             strcat(alarmstr, "YEL/");
15993          if (s.alarms & DAHDI_ALARM_RED)
15994             strcat(alarmstr, "RED/");
15995          if (s.alarms & DAHDI_ALARM_LOOPBACK)
15996             strcat(alarmstr, "LB/");
15997          if (s.alarms & DAHDI_ALARM_RECOVER)
15998             strcat(alarmstr, "REC/");
15999          if (s.alarms & DAHDI_ALARM_NOTOPEN)
16000             strcat(alarmstr, "NOP/");
16001          if (!strlen(alarmstr))
16002             strcat(alarmstr, "UUU/");
16003          if (strlen(alarmstr)) {
16004             /* Strip trailing / */
16005             alarmstr[strlen(alarmstr) - 1] = '\0';
16006          }
16007       } else {
16008          if (s.numchans)
16009             strcpy(alarmstr, "OK");
16010          else
16011             strcpy(alarmstr, "UNCONFIGURED");
16012       }
16013 
16014       ast_cli(a->fd, FORMAT, s.desc, alarmstr, s.irqmisses, s.bpvcount, s.crc4count,
16015          s.lineconfig & DAHDI_CONFIG_D4 ? "D4" :
16016          s.lineconfig & DAHDI_CONFIG_ESF ? "ESF" :
16017          s.lineconfig & DAHDI_CONFIG_CCS ? "CCS" :
16018          "CAS",
16019          s.lineconfig & DAHDI_CONFIG_B8ZS ? "B8ZS" :
16020          s.lineconfig & DAHDI_CONFIG_HDB3 ? "HDB3" :
16021          s.lineconfig & DAHDI_CONFIG_AMI ? "AMI" :
16022          "Unk",
16023          s.lineconfig & DAHDI_CONFIG_CRC4 ?
16024             s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" :
16025             s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "YEL" : "",
16026          lbostr[s.lbo]
16027          );
16028    }
16029    close(ctl);
16030 
16031    return CLI_SUCCESS;
16032 #undef FORMAT
16033 #undef FORMAT2
16034 }
16035 
16036 static char *dahdi_show_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16037 {
16038    int pseudo_fd = -1;
16039    struct dahdi_versioninfo vi;
16040 
16041    switch (cmd) {
16042    case CLI_INIT:
16043       e->command = "dahdi show version";
16044       e->usage =
16045          "Usage: dahdi show version\n"
16046          "       Shows the DAHDI version in use\n";
16047       return NULL;
16048    case CLI_GENERATE:
16049       return NULL;
16050    }
16051    if ((pseudo_fd = open("/dev/dahdi/ctl", O_RDONLY)) < 0) {
16052       ast_cli(a->fd, "Failed to open control file to get version.\n");
16053       return CLI_SUCCESS;
16054    }
16055 
16056    strcpy(vi.version, "Unknown");
16057    strcpy(vi.echo_canceller, "Unknown");
16058 
16059    if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi))
16060       ast_cli(a->fd, "Failed to get DAHDI version: %s\n", strerror(errno));
16061    else
16062       ast_cli(a->fd, "DAHDI Version: %s Echo Canceller: %s\n", vi.version, vi.echo_canceller);
16063 
16064    close(pseudo_fd);
16065 
16066    return CLI_SUCCESS;
16067 }
16068 
16069 static char *dahdi_set_hwgain(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16070 {
16071    int channel;
16072    int gain;
16073    int tx;
16074    struct dahdi_hwgain hwgain;
16075    struct dahdi_pvt *tmp = NULL;
16076 
16077    switch (cmd) {
16078    case CLI_INIT:
16079       e->command = "dahdi set hwgain {rx|tx}";
16080       e->usage =
16081          "Usage: dahdi set hwgain <rx|tx> <chan#> <gain>\n"
16082          "   Sets the hardware gain on a given channel.  Changes take effect\n"
16083          "   immediately whether the channel is in use or not.\n"
16084          "\n"
16085          "   <rx|tx> which direction do you want to change (relative to our module)\n"
16086          "   <chan num> is the channel number relative to the device\n"
16087          "   <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n"
16088          "\n"
16089          "   Please note:\n"
16090          "   * This is currently the only way to set hwgain by the channel driver.\n"
16091          "   * hwgain is only supportable by hardware with analog ports because\n"
16092          "     hwgain works on the analog side of an analog-digital conversion.\n";
16093       return NULL;
16094    case CLI_GENERATE:
16095       return NULL;
16096    }
16097 
16098    if (a->argc != 6)
16099       return CLI_SHOWUSAGE;
16100 
16101    if (!strcasecmp("rx", a->argv[3]))
16102       tx = 0; /* rx */
16103    else if (!strcasecmp("tx", a->argv[3]))
16104       tx = 1; /* tx */
16105    else
16106       return CLI_SHOWUSAGE;
16107 
16108    channel = atoi(a->argv[4]);
16109    gain = atof(a->argv[5])*10.0;
16110 
16111    ast_mutex_lock(&iflock);
16112 
16113    for (tmp = iflist; tmp; tmp = tmp->next) {
16114 
16115       if (tmp->channel != channel)
16116          continue;
16117 
16118       if (tmp->subs[SUB_REAL].dfd == -1)
16119          break;
16120 
16121       hwgain.newgain = gain;
16122       hwgain.tx = tx;
16123       if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_HWGAIN, &hwgain) < 0) {
16124          ast_cli(a->fd, "Unable to set the hardware gain for channel %d: %s\n", channel, strerror(errno));
16125          ast_mutex_unlock(&iflock);
16126          return CLI_FAILURE;
16127       }
16128       ast_cli(a->fd, "hardware %s gain set to %d (%.1f dB) on channel %d\n",
16129          tx ? "tx" : "rx", gain, (float)gain/10.0, channel);
16130       break;
16131    }
16132 
16133    ast_mutex_unlock(&iflock);
16134 
16135    if (tmp)
16136       return CLI_SUCCESS;
16137 
16138    ast_cli(a->fd, "Unable to find given channel %d\n", channel);
16139    return CLI_FAILURE;
16140 
16141 }
16142 
16143 static char *dahdi_set_swgain(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16144 {
16145    int channel;
16146    float gain;
16147    int tx;
16148    int res;
16149    struct dahdi_pvt *tmp = NULL;
16150 
16151    switch (cmd) {
16152    case CLI_INIT:
16153       e->command = "dahdi set swgain {rx|tx}";
16154       e->usage =
16155          "Usage: dahdi set swgain <rx|tx> <chan#> <gain>\n"
16156          "   Sets the software gain on a given channel and overrides the\n"
16157          "   value provided at module loadtime.  Changes take effect\n"
16158          "   immediately whether the channel is in use or not.\n"
16159          "\n"
16160          "   <rx|tx> which direction do you want to change (relative to our module)\n"
16161          "   <chan num> is the channel number relative to the device\n"
16162          "   <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
16163       return NULL;
16164    case CLI_GENERATE:
16165       return NULL;
16166    }
16167 
16168    if (a->argc != 6)
16169       return CLI_SHOWUSAGE;
16170 
16171    if (!strcasecmp("rx", a->argv[3]))
16172       tx = 0; /* rx */
16173    else if (!strcasecmp("tx", a->argv[3]))
16174       tx = 1; /* tx */
16175    else
16176       return CLI_SHOWUSAGE;
16177 
16178    channel = atoi(a->argv[4]);
16179    gain = atof(a->argv[5]);
16180 
16181    ast_mutex_lock(&iflock);
16182    for (tmp = iflist; tmp; tmp = tmp->next) {
16183 
16184       if (tmp->channel != channel)
16185          continue;
16186 
16187       if (tmp->subs[SUB_REAL].dfd == -1)
16188          break;
16189 
16190       if (tx)
16191          res = set_actual_txgain(tmp->subs[SUB_REAL].dfd, gain, tmp->txdrc, tmp->law);
16192       else
16193          res = set_actual_rxgain(tmp->subs[SUB_REAL].dfd, gain, tmp->rxdrc, tmp->law);
16194 
16195       if (res) {
16196          ast_cli(a->fd, "Unable to set the software gain for channel %d\n", channel);
16197          ast_mutex_unlock(&iflock);
16198          return CLI_FAILURE;
16199       }
16200 
16201       ast_cli(a->fd, "software %s gain set to %.1f on channel %d\n",
16202          tx ? "tx" : "rx", gain, channel);
16203 
16204       if (tx) {
16205          tmp->txgain = gain;
16206       } else {
16207          tmp->rxgain = gain;
16208       }
16209       break;
16210    }
16211    ast_mutex_unlock(&iflock);
16212 
16213    if (tmp)
16214       return CLI_SUCCESS;
16215 
16216    ast_cli(a->fd, "Unable to find given channel %d\n", channel);
16217    return CLI_FAILURE;
16218 
16219 }
16220 
16221 static char *dahdi_set_dnd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16222 {
16223    int channel;
16224    int on;
16225    struct dahdi_pvt *dahdi_chan = NULL;
16226 
16227    switch (cmd) {
16228    case CLI_INIT:
16229       e->command = "dahdi set dnd";
16230       e->usage =
16231          "Usage: dahdi set dnd <chan#> <on|off>\n"
16232          "  Sets/resets DND (Do Not Disturb) mode on a channel.\n"
16233          "  Changes take effect immediately.\n"
16234          "  <chan num> is the channel number\n"
16235          "  <on|off> Enable or disable DND mode?\n"
16236          ;
16237       return NULL;
16238    case CLI_GENERATE:
16239       return NULL;
16240    }
16241 
16242    if (a->argc != 5)
16243       return CLI_SHOWUSAGE;
16244 
16245    if ((channel = atoi(a->argv[3])) <= 0) {
16246       ast_cli(a->fd, "Expected channel number, got '%s'\n", a->argv[3]);
16247       return CLI_SHOWUSAGE;
16248    }
16249 
16250    if (ast_true(a->argv[4]))
16251       on = 1;
16252    else if (ast_false(a->argv[4]))
16253       on = 0;
16254    else {
16255       ast_cli(a->fd, "Expected 'on' or 'off', got '%s'\n", a->argv[4]);
16256       return CLI_SHOWUSAGE;
16257    }
16258 
16259    ast_mutex_lock(&iflock);
16260    for (dahdi_chan = iflist; dahdi_chan; dahdi_chan = dahdi_chan->next) {
16261       if (dahdi_chan->channel != channel)
16262          continue;
16263 
16264       /* Found the channel. Actually set it */
16265       dahdi_dnd(dahdi_chan, on);
16266       break;
16267    }
16268    ast_mutex_unlock(&iflock);
16269 
16270    if (!dahdi_chan) {
16271       ast_cli(a->fd, "Unable to find given channel %d\n", channel);
16272       return CLI_FAILURE;
16273    }
16274 
16275    return CLI_SUCCESS;
16276 }
16277 
16278 static struct ast_cli_entry dahdi_cli[] = {
16279    AST_CLI_DEFINE(handle_dahdi_show_cadences, "List cadences"),
16280    AST_CLI_DEFINE(dahdi_show_channels, "Show active DAHDI channels"),
16281    AST_CLI_DEFINE(dahdi_show_channel, "Show information on a channel"),
16282    AST_CLI_DEFINE(dahdi_destroy_channel, "Destroy a channel"),
16283    AST_CLI_DEFINE(dahdi_restart_cmd, "Fully restart DAHDI channels"),
16284    AST_CLI_DEFINE(dahdi_show_status, "Show all DAHDI cards status"),
16285    AST_CLI_DEFINE(dahdi_show_version, "Show the DAHDI version in use"),
16286    AST_CLI_DEFINE(dahdi_set_hwgain, "Set hardware gain on a channel"),
16287    AST_CLI_DEFINE(dahdi_set_swgain, "Set software gain on a channel"),
16288    AST_CLI_DEFINE(dahdi_set_dnd, "Sets/resets DND (Do Not Disturb) mode on a channel"),
16289 };
16290 
16291 #define TRANSFER  0
16292 #define HANGUP    1
16293 
16294 static int dahdi_fake_event(struct dahdi_pvt *p, int mode)
16295 {
16296    if (p) {
16297       switch (mode) {
16298       case TRANSFER:
16299          p->fake_event = DAHDI_EVENT_WINKFLASH;
16300          break;
16301       case HANGUP:
16302          p->fake_event = DAHDI_EVENT_ONHOOK;
16303          break;
16304       default:
16305          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));
16306       }
16307    }
16308    return 0;
16309 }
16310 static struct dahdi_pvt *find_channel(int channel)
16311 {
16312    struct dahdi_pvt *p;
16313 
16314    ast_mutex_lock(&iflock);
16315    for (p = iflist; p; p = p->next) {
16316       if (p->channel == channel) {
16317          break;
16318       }
16319    }
16320    ast_mutex_unlock(&iflock);
16321    return p;
16322 }
16323 
16324 /*!
16325  * \internal
16326  * \brief Get private struct using given numeric channel string.
16327  *
16328  * \param channel Numeric channel number string get private struct.
16329  *
16330  * \retval pvt on success.
16331  * \retval NULL on error.
16332  */
16333 static struct dahdi_pvt *find_channel_from_str(const char *channel)
16334 {
16335    int chan_num;
16336 
16337    if (sscanf(channel, "%30d", &chan_num) != 1) {
16338       /* Not numeric string. */
16339       return NULL;
16340    }
16341 
16342    return find_channel(chan_num);
16343 }
16344 
16345 static int action_dahdidndon(struct mansession *s, const struct message *m)
16346 {
16347    struct dahdi_pvt *p;
16348    const char *channel = astman_get_header(m, "DAHDIChannel");
16349 
16350    if (ast_strlen_zero(channel)) {
16351       astman_send_error(s, m, "No channel specified");
16352       return 0;
16353    }
16354    p = find_channel_from_str(channel);
16355    if (!p) {
16356       astman_send_error(s, m, "No such channel");
16357       return 0;
16358    }
16359    dahdi_dnd(p, 1);
16360    astman_send_ack(s, m, "DND Enabled");
16361    return 0;
16362 }
16363 
16364 static int action_dahdidndoff(struct mansession *s, const struct message *m)
16365 {
16366    struct dahdi_pvt *p;
16367    const char *channel = astman_get_header(m, "DAHDIChannel");
16368 
16369    if (ast_strlen_zero(channel)) {
16370       astman_send_error(s, m, "No channel specified");
16371       return 0;
16372    }
16373    p = find_channel_from_str(channel);
16374    if (!p) {
16375       astman_send_error(s, m, "No such channel");
16376       return 0;
16377    }
16378    dahdi_dnd(p, 0);
16379    astman_send_ack(s, m, "DND Disabled");
16380    return 0;
16381 }
16382 
16383 static int action_transfer(struct mansession *s, const struct message *m)
16384 {
16385    struct dahdi_pvt *p;
16386    const char *channel = astman_get_header(m, "DAHDIChannel");
16387 
16388    if (ast_strlen_zero(channel)) {
16389       astman_send_error(s, m, "No channel specified");
16390       return 0;
16391    }
16392    p = find_channel_from_str(channel);
16393    if (!p) {
16394       astman_send_error(s, m, "No such channel");
16395       return 0;
16396    }
16397    if (!analog_lib_handles(p->sig, 0, 0)) {
16398       astman_send_error(s, m, "Channel signaling is not analog");
16399       return 0;
16400    }
16401    dahdi_fake_event(p,TRANSFER);
16402    astman_send_ack(s, m, "DAHDITransfer");
16403    return 0;
16404 }
16405 
16406 static int action_transferhangup(struct mansession *s, const struct message *m)
16407 {
16408    struct dahdi_pvt *p;
16409    const char *channel = astman_get_header(m, "DAHDIChannel");
16410 
16411    if (ast_strlen_zero(channel)) {
16412       astman_send_error(s, m, "No channel specified");
16413       return 0;
16414    }
16415    p = find_channel_from_str(channel);
16416    if (!p) {
16417       astman_send_error(s, m, "No such channel");
16418       return 0;
16419    }
16420    if (!analog_lib_handles(p->sig, 0, 0)) {
16421       astman_send_error(s, m, "Channel signaling is not analog");
16422       return 0;
16423    }
16424    dahdi_fake_event(p,HANGUP);
16425    astman_send_ack(s, m, "DAHDIHangup");
16426    return 0;
16427 }
16428 
16429 static int action_dahdidialoffhook(struct mansession *s, const struct message *m)
16430 {
16431    struct dahdi_pvt *p;
16432    const char *channel = astman_get_header(m, "DAHDIChannel");
16433    const char *number = astman_get_header(m, "Number");
16434    int i;
16435 
16436    if (ast_strlen_zero(channel)) {
16437       astman_send_error(s, m, "No channel specified");
16438       return 0;
16439    }
16440    if (ast_strlen_zero(number)) {
16441       astman_send_error(s, m, "No number specified");
16442       return 0;
16443    }
16444    p = find_channel_from_str(channel);
16445    if (!p) {
16446       astman_send_error(s, m, "No such channel");
16447       return 0;
16448    }
16449    if (!p->owner) {
16450       astman_send_error(s, m, "Channel does not have it's owner");
16451       return 0;
16452    }
16453    for (i = 0; i < strlen(number); i++) {
16454       struct ast_frame f = { AST_FRAME_DTMF, .subclass.integer = number[i] };
16455       dahdi_queue_frame(p, &f);
16456    }
16457    astman_send_ack(s, m, "DAHDIDialOffhook");
16458    return 0;
16459 }
16460 
16461 static int action_dahdishowchannels(struct mansession *s, const struct message *m)
16462 {
16463    struct dahdi_pvt *tmp = NULL;
16464    const char *id = astman_get_header(m, "ActionID");
16465    const char *dahdichannel = astman_get_header(m, "DAHDIChannel");
16466    char idText[256] = "";
16467    int channels = 0;
16468    int dahdichanquery;
16469 
16470    if (!dahdichannel || sscanf(dahdichannel, "%30d", &dahdichanquery) != 1) {
16471       /* Not numeric string. */
16472       dahdichanquery = -1;
16473    }
16474 
16475    astman_send_ack(s, m, "DAHDI channel status will follow");
16476    if (!ast_strlen_zero(id))
16477       snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
16478 
16479    ast_mutex_lock(&iflock);
16480 
16481    for (tmp = iflist; tmp; tmp = tmp->next) {
16482       if (tmp->channel > 0) {
16483          int alm;
16484 
16485          /* If a specific channel is queried for, only deliver status for that channel */
16486          if (dahdichanquery > 0 && tmp->channel != dahdichanquery)
16487             continue;
16488 
16489          alm = get_alarms(tmp);
16490          channels++;
16491          if (tmp->owner) {
16492             /* Add data if we have a current call */
16493             astman_append(s,
16494                "Event: DAHDIShowChannels\r\n"
16495                "DAHDIChannel: %d\r\n"
16496                "Channel: %s\r\n"
16497                "Uniqueid: %s\r\n"
16498                "AccountCode: %s\r\n"
16499                "Signalling: %s\r\n"
16500                "SignallingCode: %d\r\n"
16501                "Context: %s\r\n"
16502                "DND: %s\r\n"
16503                "Alarm: %s\r\n"
16504                "Description: %s\r\n"
16505                "%s"
16506                "\r\n",
16507                tmp->channel,
16508                ast_channel_name(tmp->owner),
16509                ast_channel_uniqueid(tmp->owner),
16510                ast_channel_accountcode(tmp->owner),
16511                sig2str(tmp->sig),
16512                tmp->sig,
16513                tmp->context,
16514                dahdi_dnd(tmp, -1) ? "Enabled" : "Disabled",
16515                alarm2str(alm),
16516                tmp->description, idText);
16517          } else {
16518             astman_append(s,
16519                "Event: DAHDIShowChannels\r\n"
16520                "DAHDIChannel: %d\r\n"
16521                "Signalling: %s\r\n"
16522                "SignallingCode: %d\r\n"
16523                "Context: %s\r\n"
16524                "DND: %s\r\n"
16525                "Alarm: %s\r\n"
16526                "Description: %s\r\n"
16527                "%s"
16528                "\r\n",
16529                tmp->channel, sig2str(tmp->sig), tmp->sig,
16530                tmp->context,
16531                dahdi_dnd(tmp, -1) ? "Enabled" : "Disabled",
16532                alarm2str(alm),
16533                tmp->description, idText);
16534          }
16535       }
16536    }
16537 
16538    ast_mutex_unlock(&iflock);
16539 
16540    astman_append(s,
16541       "Event: DAHDIShowChannelsComplete\r\n"
16542       "%s"
16543       "Items: %d\r\n"
16544       "\r\n",
16545       idText,
16546       channels);
16547    return 0;
16548 }
16549 
16550 #if defined(HAVE_PRI)
16551 static int action_prishowspans(struct mansession *s, const struct message *m)
16552 {
16553    int count;
16554    int idx;
16555    int span_query;
16556    struct dahdi_pri *dspan;
16557    const char *id = astman_get_header(m, "ActionID");
16558    const char *span_str = astman_get_header(m, "Span");
16559    char action_id[256];
16560    const char *show_cmd = "PRIShowSpans";
16561 
16562    /* NOTE: Asking for span 0 gets all spans. */
16563    if (!ast_strlen_zero(span_str)) {
16564       span_query = atoi(span_str);
16565    } else {
16566       span_query = 0;
16567    }
16568 
16569    if (!ast_strlen_zero(id)) {
16570       snprintf(action_id, sizeof(action_id), "ActionID: %s\r\n", id);
16571    } else {
16572       action_id[0] = '\0';
16573    }
16574 
16575    astman_send_ack(s, m, "Span status will follow");
16576 
16577    count = 0;
16578    for (idx = 0; idx < ARRAY_LEN(pris); ++idx) {
16579       dspan = &pris[idx];
16580 
16581       /* If a specific span is asked for, only deliver status for that span. */
16582       if (0 < span_query && dspan->pri.span != span_query) {
16583          continue;
16584       }
16585 
16586       if (dspan->pri.pri) {
16587          count += sig_pri_ami_show_spans(s, show_cmd, &dspan->pri, dspan->dchannels,
16588             action_id);
16589       }
16590    }
16591 
16592    astman_append(s,
16593       "Event: %sComplete\r\n"
16594       "Items: %d\r\n"
16595       "%s"
16596       "\r\n",
16597       show_cmd,
16598       count,
16599       action_id);
16600    return 0;
16601 }
16602 #endif   /* defined(HAVE_PRI) */
16603 
16604 #if defined(HAVE_SS7)
16605 static int linkset_addsigchan(int sigchan)
16606 {
16607    struct dahdi_ss7 *link;
16608    int res;
16609    int curfd;
16610    struct dahdi_params params;
16611    struct dahdi_bufferinfo bi;
16612    struct dahdi_spaninfo si;
16613 
16614    if (sigchan < 0) {
16615       ast_log(LOG_ERROR, "Invalid sigchan!\n");
16616       return -1;
16617    }
16618    if (cur_ss7type < 0) {
16619       ast_log(LOG_ERROR, "Unspecified or invalid ss7type\n");
16620       return -1;
16621    }
16622    if (cur_pointcode < 0) {
16623       ast_log(LOG_ERROR, "Unspecified pointcode!\n");
16624       return -1;
16625    }
16626    if (cur_adjpointcode < 0) {
16627       ast_log(LOG_ERROR, "Unspecified adjpointcode!\n");
16628       return -1;
16629    }
16630    if (cur_defaultdpc < 0) {
16631       ast_log(LOG_ERROR, "Unspecified defaultdpc!\n");
16632       return -1;
16633    }
16634    if (cur_networkindicator < 0) {
16635       ast_log(LOG_ERROR, "Invalid networkindicator!\n");
16636       return -1;
16637    }
16638    link = ss7_resolve_linkset(cur_linkset);
16639    if (!link) {
16640       ast_log(LOG_ERROR, "Invalid linkset number.  Must be between 1 and %d\n", NUM_SPANS + 1);
16641       return -1;
16642    }
16643    if (link->ss7.numsigchans >= SIG_SS7_NUM_DCHANS) {
16644       ast_log(LOG_ERROR, "Too many sigchans on linkset %d\n", cur_linkset);
16645       return -1;
16646    }
16647 
16648    curfd = link->ss7.numsigchans;
16649 
16650    /* Open signaling channel */
16651    link->ss7.fds[curfd] = open("/dev/dahdi/channel", O_RDWR, 0600);
16652    if (link->ss7.fds[curfd] < 0) {
16653       ast_log(LOG_ERROR, "Unable to open SS7 sigchan %d (%s)\n", sigchan,
16654          strerror(errno));
16655       return -1;
16656    }
16657    if (ioctl(link->ss7.fds[curfd], DAHDI_SPECIFY, &sigchan) == -1) {
16658       dahdi_close_ss7_fd(link, curfd);
16659       ast_log(LOG_ERROR, "Unable to specify SS7 sigchan %d (%s)\n", sigchan,
16660          strerror(errno));
16661       return -1;
16662    }
16663 
16664    /* Get signaling channel parameters */
16665    memset(&params, 0, sizeof(params));
16666    res = ioctl(link->ss7.fds[curfd], DAHDI_GET_PARAMS, &params);
16667    if (res) {
16668       dahdi_close_ss7_fd(link, curfd);
16669       ast_log(LOG_ERROR, "Unable to get parameters for sigchan %d (%s)\n", sigchan,
16670          strerror(errno));
16671       return -1;
16672    }
16673    if (params.sigtype != DAHDI_SIG_HDLCFCS
16674       && params.sigtype != DAHDI_SIG_HARDHDLC
16675       && params.sigtype != DAHDI_SIG_MTP2) {
16676       dahdi_close_ss7_fd(link, curfd);
16677       ast_log(LOG_ERROR, "sigchan %d is not in HDLC/FCS mode.\n", sigchan);
16678       return -1;
16679    }
16680 
16681    /* Set signaling channel buffer policy. */
16682    memset(&bi, 0, sizeof(bi));
16683    bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
16684    bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
16685    bi.numbufs = 32;
16686    bi.bufsize = 512;
16687    if (ioctl(link->ss7.fds[curfd], DAHDI_SET_BUFINFO, &bi)) {
16688       ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n",
16689          sigchan, strerror(errno));
16690       dahdi_close_ss7_fd(link, curfd);
16691       return -1;
16692    }
16693 
16694    /* Get current signaling channel alarm status. */
16695    memset(&si, 0, sizeof(si));
16696    res = ioctl(link->ss7.fds[curfd], DAHDI_SPANSTAT, &si);
16697    if (res) {
16698       dahdi_close_ss7_fd(link, curfd);
16699       ast_log(LOG_ERROR, "Unable to get span state for sigchan %d (%s)\n", sigchan,
16700          strerror(errno));
16701    }
16702 
16703    res = sig_ss7_add_sigchan(&link->ss7, curfd, cur_ss7type,
16704       (params.sigtype == DAHDI_SIG_MTP2)
16705          ? SS7_TRANSPORT_DAHDIMTP2
16706          : SS7_TRANSPORT_DAHDIDCHAN,
16707       si.alarms, cur_networkindicator, cur_pointcode, cur_adjpointcode);
16708    if (res) {
16709       dahdi_close_ss7_fd(link, curfd);
16710       return -1;
16711    }
16712 
16713    ++link->ss7.numsigchans;
16714 
16715    return 0;
16716 }
16717 #endif   /* defined(HAVE_SS7) */
16718 
16719 #if defined(HAVE_SS7)
16720 static char *handle_ss7_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16721 {
16722    int span;
16723    switch (cmd) {
16724    case CLI_INIT:
16725       e->command = "ss7 set debug {on|off} linkset";
16726       e->usage =
16727          "Usage: ss7 set debug {on|off} linkset <linkset>\n"
16728          "       Enables debugging on a given SS7 linkset\n";
16729       return NULL;
16730    case CLI_GENERATE:
16731       return NULL;
16732    }
16733    if (a->argc < 6)
16734       return CLI_SHOWUSAGE;
16735    span = atoi(a->argv[5]);
16736    if ((span < 1) || (span > NUM_SPANS)) {
16737       ast_cli(a->fd, "Invalid linkset %s.  Should be a number from %d to %d\n", a->argv[5], 1, NUM_SPANS);
16738       return CLI_SUCCESS;
16739    }
16740    if (!linksets[span-1].ss7.ss7) {
16741       ast_cli(a->fd, "No SS7 running on linkset %d\n", span);
16742    } else {
16743       if (!strcasecmp(a->argv[3], "on")) {
16744          linksets[span - 1].ss7.debug = 1;
16745          ss7_set_debug(linksets[span-1].ss7.ss7, SIG_SS7_DEBUG);
16746          ast_cli(a->fd, "Enabled debugging on linkset %d\n", span);
16747       } else {
16748          linksets[span - 1].ss7.debug = 0;
16749          ss7_set_debug(linksets[span-1].ss7.ss7, 0);
16750          ast_cli(a->fd, "Disabled debugging on linkset %d\n", span);
16751       }
16752    }
16753 
16754    return CLI_SUCCESS;
16755 }
16756 #endif   /* defined(HAVE_SS7) */
16757 
16758 #if defined(HAVE_SS7)
16759 static char *handle_ss7_block_cic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16760 {
16761    int linkset, cic;
16762    int blocked = -1, i;
16763    switch (cmd) {
16764    case CLI_INIT:
16765       e->command = "ss7 block cic";
16766       e->usage =
16767          "Usage: ss7 block cic <linkset> <CIC>\n"
16768          "       Sends a remote blocking request for the given CIC on the specified linkset\n";
16769       return NULL;
16770    case CLI_GENERATE:
16771       return NULL;
16772    }
16773    if (a->argc == 5)
16774       linkset = atoi(a->argv[3]);
16775    else
16776       return CLI_SHOWUSAGE;
16777 
16778    if ((linkset < 1) || (linkset > NUM_SPANS)) {
16779       ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16780       return CLI_SUCCESS;
16781    }
16782 
16783    if (!linksets[linkset-1].ss7.ss7) {
16784       ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16785       return CLI_SUCCESS;
16786    }
16787 
16788    cic = atoi(a->argv[4]);
16789 
16790    if (cic < 1) {
16791       ast_cli(a->fd, "Invalid CIC specified!\n");
16792       return CLI_SUCCESS;
16793    }
16794 
16795    for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
16796       if (linksets[linkset-1].ss7.pvts[i]->cic == cic) {
16797          blocked = linksets[linkset-1].ss7.pvts[i]->locallyblocked;
16798          if (!blocked) {
16799             ast_mutex_lock(&linksets[linkset-1].ss7.lock);
16800             isup_blo(linksets[linkset-1].ss7.ss7, cic, linksets[linkset-1].ss7.pvts[i]->dpc);
16801             ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
16802          }
16803       }
16804    }
16805 
16806    if (blocked < 0) {
16807       ast_cli(a->fd, "Invalid CIC specified!\n");
16808       return CLI_SUCCESS;
16809    }
16810 
16811    if (!blocked)
16812       ast_cli(a->fd, "Sent blocking request for linkset %d on CIC %d\n", linkset, cic);
16813    else
16814       ast_cli(a->fd, "CIC %d already locally blocked\n", cic);
16815 
16816    /* Break poll on the linkset so it sends our messages */
16817    pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
16818 
16819    return CLI_SUCCESS;
16820 }
16821 #endif   /* defined(HAVE_SS7) */
16822 
16823 #if defined(HAVE_SS7)
16824 static char *handle_ss7_block_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16825 {
16826    int linkset;
16827    int i;
16828    switch (cmd) {
16829    case CLI_INIT:
16830       e->command = "ss7 block linkset";
16831       e->usage =
16832          "Usage: ss7 block linkset <linkset number>\n"
16833          "       Sends a remote blocking request for all CICs on the given linkset\n";
16834       return NULL;
16835    case CLI_GENERATE:
16836       return NULL;
16837    }
16838    if (a->argc == 4)
16839       linkset = atoi(a->argv[3]);
16840    else
16841       return CLI_SHOWUSAGE;
16842 
16843    if ((linkset < 1) || (linkset > NUM_SPANS)) {
16844       ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16845       return CLI_SUCCESS;
16846    }
16847 
16848    if (!linksets[linkset-1].ss7.ss7) {
16849       ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16850       return CLI_SUCCESS;
16851    }
16852 
16853    for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
16854       ast_cli(a->fd, "Sending remote blocking request on CIC %d\n", linksets[linkset-1].ss7.pvts[i]->cic);
16855       ast_mutex_lock(&linksets[linkset-1].ss7.lock);
16856       isup_blo(linksets[linkset-1].ss7.ss7, linksets[linkset-1].ss7.pvts[i]->cic, linksets[linkset-1].ss7.pvts[i]->dpc);
16857       ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
16858    }
16859 
16860    /* Break poll on the linkset so it sends our messages */
16861    pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
16862 
16863    return CLI_SUCCESS;
16864 }
16865 #endif   /* defined(HAVE_SS7) */
16866 
16867 #if defined(HAVE_SS7)
16868 static char *handle_ss7_unblock_cic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16869 {
16870    int linkset, cic;
16871    int i, blocked = -1;
16872    switch (cmd) {
16873    case CLI_INIT:
16874       e->command = "ss7 unblock cic";
16875       e->usage =
16876          "Usage: ss7 unblock cic <linkset> <CIC>\n"
16877          "       Sends a remote unblocking request for the given CIC on the specified linkset\n";
16878       return NULL;
16879    case CLI_GENERATE:
16880       return NULL;
16881    }
16882 
16883    if (a->argc == 5)
16884       linkset = atoi(a->argv[3]);
16885    else
16886       return CLI_SHOWUSAGE;
16887 
16888    if ((linkset < 1) || (linkset > NUM_SPANS)) {
16889       ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16890       return CLI_SUCCESS;
16891    }
16892 
16893    if (!linksets[linkset-1].ss7.ss7) {
16894       ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16895       return CLI_SUCCESS;
16896    }
16897 
16898    cic = atoi(a->argv[4]);
16899 
16900    if (cic < 1) {
16901       ast_cli(a->fd, "Invalid CIC specified!\n");
16902       return CLI_SUCCESS;
16903    }
16904 
16905    for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
16906       if (linksets[linkset-1].ss7.pvts[i]->cic == cic) {
16907          blocked = linksets[linkset-1].ss7.pvts[i]->locallyblocked;
16908          if (blocked) {
16909             ast_mutex_lock(&linksets[linkset-1].ss7.lock);
16910             isup_ubl(linksets[linkset-1].ss7.ss7, cic, linksets[linkset-1].ss7.pvts[i]->dpc);
16911             ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
16912          }
16913       }
16914    }
16915 
16916    if (blocked > 0)
16917       ast_cli(a->fd, "Sent unblocking request for linkset %d on CIC %d\n", linkset, cic);
16918 
16919    /* Break poll on the linkset so it sends our messages */
16920    pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
16921 
16922    return CLI_SUCCESS;
16923 }
16924 #endif   /* defined(HAVE_SS7) */
16925 
16926 #if defined(HAVE_SS7)
16927 static char *handle_ss7_unblock_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16928 {
16929    int linkset;
16930    int i;
16931    switch (cmd) {
16932    case CLI_INIT:
16933       e->command = "ss7 unblock linkset";
16934       e->usage =
16935          "Usage: ss7 unblock linkset <linkset number>\n"
16936          "       Sends a remote unblocking request for all CICs on the specified linkset\n";
16937       return NULL;
16938    case CLI_GENERATE:
16939       return NULL;
16940    }
16941 
16942    if (a->argc == 4)
16943       linkset = atoi(a->argv[3]);
16944    else
16945       return CLI_SHOWUSAGE;
16946 
16947    if ((linkset < 1) || (linkset > NUM_SPANS)) {
16948       ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16949       return CLI_SUCCESS;
16950    }
16951 
16952    if (!linksets[linkset-1].ss7.ss7) {
16953       ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16954       return CLI_SUCCESS;
16955    }
16956 
16957    for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
16958       ast_cli(a->fd, "Sending remote unblock request on CIC %d\n", linksets[linkset-1].ss7.pvts[i]->cic);
16959       ast_mutex_lock(&linksets[linkset-1].ss7.lock);
16960       isup_ubl(linksets[linkset-1].ss7.ss7, linksets[linkset-1].ss7.pvts[i]->cic, linksets[linkset-1].ss7.pvts[i]->dpc);
16961       ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
16962    }
16963 
16964    /* Break poll on the linkset so it sends our messages */
16965    pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
16966 
16967    return CLI_SUCCESS;
16968 }
16969 #endif   /* defined(HAVE_SS7) */
16970 
16971 #if defined(HAVE_SS7)
16972 static char *handle_ss7_show_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16973 {
16974    int linkset;
16975    struct sig_ss7_linkset *ss7;
16976    switch (cmd) {
16977    case CLI_INIT:
16978       e->command = "ss7 show linkset";
16979       e->usage =
16980          "Usage: ss7 show linkset <span>\n"
16981          "       Shows the status of an SS7 linkset.\n";
16982       return NULL;
16983    case CLI_GENERATE:
16984       return NULL;
16985    }
16986 
16987    if (a->argc < 4)
16988       return CLI_SHOWUSAGE;
16989    linkset = atoi(a->argv[3]);
16990    if ((linkset < 1) || (linkset > NUM_SPANS)) {
16991       ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16992       return CLI_SUCCESS;
16993    }
16994    ss7 = &linksets[linkset - 1].ss7;
16995    if (!ss7->ss7) {
16996       ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16997       return CLI_SUCCESS;
16998    }
16999 
17000    ast_cli(a->fd, "SS7 linkset %d status: %s\n", linkset, (ss7->state == LINKSET_STATE_UP) ? "Up" : "Down");
17001 
17002    return CLI_SUCCESS;
17003 }
17004 #endif   /* defined(HAVE_SS7) */
17005 
17006 #if defined(HAVE_SS7)
17007 static char *handle_ss7_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
17008 {
17009    int linkset;
17010 
17011    switch (cmd) {
17012    case CLI_INIT:
17013       e->command = "ss7 show channels";
17014       e->usage =
17015          "Usage: ss7 show channels\n"
17016          "       Displays SS7 channel information at a glance.\n";
17017       return NULL;
17018    case CLI_GENERATE:
17019       return NULL;
17020    }
17021 
17022    if (a->argc != 3)
17023       return CLI_SHOWUSAGE;
17024 
17025    sig_ss7_cli_show_channels_header(a->fd);
17026    for (linkset = 0; linkset < NUM_SPANS; ++linkset) {
17027       if (linksets[linkset].ss7.ss7) {
17028          sig_ss7_cli_show_channels(a->fd, &linksets[linkset].ss7);
17029       }
17030    }
17031    return CLI_SUCCESS;
17032 }
17033 #endif   /* defined(HAVE_SS7) */
17034 
17035 #if defined(HAVE_SS7)
17036 static char *handle_ss7_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
17037 {
17038    switch (cmd) {
17039    case CLI_INIT:
17040       e->command = "ss7 show version";
17041       e->usage =
17042          "Usage: ss7 show version\n"
17043          "  Show the libss7 version\n";
17044       return NULL;
17045    case CLI_GENERATE:
17046       return NULL;
17047    }
17048 
17049    ast_cli(a->fd, "libss7 version: %s\n", ss7_get_version());
17050 
17051    return CLI_SUCCESS;
17052 }
17053 #endif   /* defined(HAVE_SS7) */
17054 
17055 #if defined(HAVE_SS7)
17056 static struct ast_cli_entry dahdi_ss7_cli[] = {
17057    AST_CLI_DEFINE(handle_ss7_debug, "Enables SS7 debugging on a linkset"),
17058    AST_CLI_DEFINE(handle_ss7_block_cic, "Blocks the given CIC"),
17059    AST_CLI_DEFINE(handle_ss7_unblock_cic, "Unblocks the given CIC"),
17060    AST_CLI_DEFINE(handle_ss7_block_linkset, "Blocks all CICs on a linkset"),
17061    AST_CLI_DEFINE(handle_ss7_unblock_linkset, "Unblocks all CICs on a linkset"),
17062    AST_CLI_DEFINE(handle_ss7_show_linkset, "Shows the status of a linkset"),
17063    AST_CLI_DEFINE(handle_ss7_show_channels, "Displays SS7 channel information"),
17064    AST_CLI_DEFINE(handle_ss7_version, "Displays libss7 version"),
17065 };
17066 #endif   /* defined(HAVE_SS7) */
17067 
17068 #if defined(HAVE_PRI)
17069 #if defined(HAVE_PRI_CCSS)
17070 /*!
17071  * \internal
17072  * \brief CC agent initialization.
17073  * \since 1.8
17074  *
17075  * \param agent CC core agent control.
17076  * \param chan Original channel the agent will attempt to recall.
17077  *
17078  * \details
17079  * This callback is called when the CC core is initialized.  Agents should allocate
17080  * any private data necessary for the call and assign it to the private_data
17081  * on the agent.  Additionally, if any ast_cc_agent_flags are pertinent to the
17082  * specific agent type, they should be set in this function as well.
17083  *
17084  * \retval 0 on success.
17085  * \retval -1 on error.
17086  */
17087 static int dahdi_pri_cc_agent_init(struct ast_cc_agent *agent, struct ast_channel *chan)
17088 {
17089    struct dahdi_pvt *pvt;
17090    struct sig_pri_chan *pvt_chan;
17091    int res;
17092 
17093    ast_assert(!strcmp(ast_channel_tech(chan)->type, "DAHDI"));
17094 
17095    pvt = ast_channel_tech_pvt(chan);
17096    if (dahdi_sig_pri_lib_handles(pvt->sig)) {
17097       pvt_chan = pvt->sig_pvt;
17098    } else {
17099       pvt_chan = NULL;
17100    }
17101    if (!pvt_chan) {
17102       return -1;
17103    }
17104 
17105    ast_module_ref(ast_module_info->self);
17106 
17107    res = sig_pri_cc_agent_init(agent, pvt_chan);
17108    if (res) {
17109       ast_module_unref(ast_module_info->self);
17110    }
17111    return res;
17112 }
17113 #endif   /* defined(HAVE_PRI_CCSS) */
17114 #endif   /* defined(HAVE_PRI) */
17115 
17116 #if defined(HAVE_PRI)
17117 #if defined(HAVE_PRI_CCSS)
17118 /*!
17119  * \internal
17120  * \brief Destroy private data on the agent.
17121  * \since 1.8
17122  *
17123  * \param agent CC core agent control.
17124  *
17125  * \details
17126  * The core will call this function upon completion
17127  * or failure of CC.
17128  *
17129  * \return Nothing
17130  */
17131 static void dahdi_pri_cc_agent_destructor(struct ast_cc_agent *agent)
17132 {
17133    sig_pri_cc_agent_destructor(agent);
17134 
17135    ast_module_unref(ast_module_info->self);
17136 }
17137 #endif   /* defined(HAVE_PRI_CCSS) */
17138 #endif   /* defined(HAVE_PRI) */
17139 
17140 #if defined(HAVE_PRI)
17141 #if defined(HAVE_PRI_CCSS)
17142 static struct ast_cc_agent_callbacks dahdi_pri_cc_agent_callbacks = {
17143    .type = dahdi_pri_cc_type,
17144    .init = dahdi_pri_cc_agent_init,
17145    .start_offer_timer = sig_pri_cc_agent_start_offer_timer,
17146    .stop_offer_timer = sig_pri_cc_agent_stop_offer_timer,
17147    .respond = sig_pri_cc_agent_req_rsp,
17148    .status_request = sig_pri_cc_agent_status_req,
17149    .stop_ringing = sig_pri_cc_agent_stop_ringing,
17150    .party_b_free = sig_pri_cc_agent_party_b_free,
17151    .start_monitoring = sig_pri_cc_agent_start_monitoring,
17152    .callee_available = sig_pri_cc_agent_callee_available,
17153    .destructor = dahdi_pri_cc_agent_destructor,
17154 };
17155 #endif   /* defined(HAVE_PRI_CCSS) */
17156 #endif   /* defined(HAVE_PRI) */
17157 
17158 #if defined(HAVE_PRI)
17159 #if defined(HAVE_PRI_CCSS)
17160 static struct ast_cc_monitor_callbacks dahdi_pri_cc_monitor_callbacks = {
17161    .type = dahdi_pri_cc_type,
17162    .request_cc = sig_pri_cc_monitor_req_cc,
17163    .suspend = sig_pri_cc_monitor_suspend,
17164    .unsuspend = sig_pri_cc_monitor_unsuspend,
17165    .status_response = sig_pri_cc_monitor_status_rsp,
17166    .cancel_available_timer = sig_pri_cc_monitor_cancel_available_timer,
17167    .destructor = sig_pri_cc_monitor_destructor,
17168 };
17169 #endif   /* defined(HAVE_PRI_CCSS) */
17170 #endif   /* defined(HAVE_PRI) */
17171 
17172 static int __unload_module(void)
17173 {
17174    struct dahdi_pvt *p;
17175 #if defined(HAVE_PRI) || defined(HAVE_SS7)
17176    int i, j;
17177 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
17178 
17179 #ifdef HAVE_PRI
17180    for (i = 0; i < NUM_SPANS; i++) {
17181       if (pris[i].pri.master != AST_PTHREADT_NULL) {
17182          pthread_cancel(pris[i].pri.master);
17183          pthread_kill(pris[i].pri.master, SIGURG);
17184       }
17185    }
17186    ast_cli_unregister_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
17187    ast_unregister_application(dahdi_send_keypad_facility_app);
17188 #ifdef HAVE_PRI_PROG_W_CAUSE
17189    ast_unregister_application(dahdi_send_callrerouting_facility_app);
17190 #endif
17191 #endif
17192 #if defined(HAVE_SS7)
17193    for (i = 0; i < NUM_SPANS; i++) {
17194       if (linksets[i].ss7.master != AST_PTHREADT_NULL) {
17195          pthread_cancel(linksets[i].ss7.master);
17196          pthread_kill(linksets[i].ss7.master, SIGURG);
17197       }
17198    }
17199    ast_cli_unregister_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
17200 #endif   /* defined(HAVE_SS7) */
17201 #if defined(HAVE_OPENR2)
17202    dahdi_r2_destroy_links();
17203    ast_cli_unregister_multiple(dahdi_mfcr2_cli, ARRAY_LEN(dahdi_mfcr2_cli));
17204    ast_unregister_application(dahdi_accept_r2_call_app);
17205 #endif
17206 
17207    ast_cli_unregister_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli));
17208    ast_manager_unregister("DAHDIDialOffhook");
17209    ast_manager_unregister("DAHDIHangup");
17210    ast_manager_unregister("DAHDITransfer");
17211    ast_manager_unregister("DAHDIDNDoff");
17212    ast_manager_unregister("DAHDIDNDon");
17213    ast_manager_unregister("DAHDIShowChannels");
17214    ast_manager_unregister("DAHDIRestart");
17215 #if defined(HAVE_PRI)
17216    ast_manager_unregister("PRIShowSpans");
17217 #endif   /* defined(HAVE_PRI) */
17218    ast_data_unregister(NULL);
17219    ast_channel_unregister(&dahdi_tech);
17220 
17221    /* Hangup all interfaces if they have an owner */
17222    ast_mutex_lock(&iflock);
17223    for (p = iflist; p; p = p->next) {
17224       if (p->owner)
17225          ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
17226    }
17227    ast_mutex_unlock(&iflock);
17228 
17229    ast_mutex_lock(&monlock);
17230    if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
17231       pthread_cancel(monitor_thread);
17232       pthread_kill(monitor_thread, SIGURG);
17233       pthread_join(monitor_thread, NULL);
17234    }
17235    monitor_thread = AST_PTHREADT_STOP;
17236    ast_mutex_unlock(&monlock);
17237 
17238    destroy_all_channels();
17239 
17240 #if defined(HAVE_PRI)
17241    for (i = 0; i < NUM_SPANS; i++) {
17242       if (pris[i].pri.master && (pris[i].pri.master != AST_PTHREADT_NULL)) {
17243          pthread_join(pris[i].pri.master, NULL);
17244       }
17245       for (j = 0; j < SIG_PRI_NUM_DCHANS; j++) {
17246          dahdi_close_pri_fd(&(pris[i]), j);
17247       }
17248       sig_pri_stop_pri(&pris[i].pri);
17249    }
17250 #if defined(HAVE_PRI_CCSS)
17251    ast_cc_agent_unregister(&dahdi_pri_cc_agent_callbacks);
17252    ast_cc_monitor_unregister(&dahdi_pri_cc_monitor_callbacks);
17253 #endif   /* defined(HAVE_PRI_CCSS) */
17254    sig_pri_unload();
17255 #endif
17256 
17257 #if defined(HAVE_SS7)
17258    for (i = 0; i < NUM_SPANS; i++) {
17259       if (linksets[i].ss7.master && (linksets[i].ss7.master != AST_PTHREADT_NULL)) {
17260          pthread_join(linksets[i].ss7.master, NULL);
17261       }
17262       for (j = 0; j < SIG_SS7_NUM_DCHANS; j++) {
17263          dahdi_close_ss7_fd(&(linksets[i]), j);
17264       }
17265    }
17266 #endif   /* defined(HAVE_SS7) */
17267    ast_cond_destroy(&ss_thread_complete);
17268 
17269    dahdi_tech.capabilities = ast_format_cap_destroy(dahdi_tech.capabilities);
17270    return 0;
17271 }
17272 
17273 static int unload_module(void)
17274 {
17275 #if defined(HAVE_PRI) || defined(HAVE_SS7)
17276    int y;
17277 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
17278 #ifdef HAVE_PRI
17279    for (y = 0; y < NUM_SPANS; y++)
17280       ast_mutex_destroy(&pris[y].pri.lock);
17281 #endif
17282 #if defined(HAVE_SS7)
17283    for (y = 0; y < NUM_SPANS; y++)
17284       ast_mutex_destroy(&linksets[y].ss7.lock);
17285 #endif   /* defined(HAVE_SS7) */
17286    return __unload_module();
17287 }
17288 
17289 static void string_replace(char *str, int char1, int char2)
17290 {
17291    for (; *str; str++) {
17292       if (*str == char1) {
17293          *str = char2;
17294       }
17295    }
17296 }
17297 
17298 static char *parse_spanchan(char *chanstr, char **subdir)
17299 {
17300    char *p;
17301 
17302    if ((p = strrchr(chanstr, '!')) == NULL) {
17303       *subdir = NULL;
17304       return chanstr;
17305    }
17306    *p++ = '\0';
17307    string_replace(chanstr, '!', '/');
17308    *subdir = chanstr;
17309    return p;
17310 }
17311 
17312 static int build_channels(struct dahdi_chan_conf *conf, const char *value, int reload, int lineno, int *found_pseudo)
17313 {
17314    char *c, *chan;
17315    char *subdir;
17316    int x, start, finish;
17317    struct dahdi_pvt *tmp;
17318 
17319    if ((reload == 0) && (conf->chan.sig < 0) && !conf->is_sig_auto) {
17320       ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n");
17321       return -1;
17322    }
17323 
17324    c = ast_strdupa(value);
17325    c = parse_spanchan(c, &subdir);
17326 
17327    while ((chan = strsep(&c, ","))) {
17328       if (sscanf(chan, "%30d-%30d", &start, &finish) == 2) {
17329          /* Range */
17330       } else if (sscanf(chan, "%30d", &start)) {
17331          /* Just one */
17332          finish = start;
17333       } else if (!strcasecmp(chan, "pseudo")) {
17334          finish = start = CHAN_PSEUDO;
17335          if (found_pseudo)
17336             *found_pseudo = 1;
17337       } else {
17338          ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan);
17339          return -1;
17340       }
17341       if (finish < start) {
17342          ast_log(LOG_WARNING, "Sillyness: %d < %d\n", start, finish);
17343          x = finish;
17344          finish = start;
17345          start = x;
17346       }
17347 
17348       for (x = start; x <= finish; x++) {
17349          char fn[PATH_MAX];
17350          int real_channel = x;
17351 
17352          if (!ast_strlen_zero(subdir)) {
17353             real_channel = device2chan(subdir, x, fn, sizeof(fn));
17354             if (real_channel < 0) {
17355                if (conf->ignore_failed_channels) {
17356                   ast_log(LOG_WARNING, "Failed configuring %s!%d, (got %d). But moving on to others.\n",
17357                         subdir, x, real_channel);
17358                   continue;
17359                } else {
17360                   ast_log(LOG_ERROR, "Failed configuring %s!%d, (got %d).\n",
17361                         subdir, x, real_channel);
17362                   return -1;
17363                }
17364             }
17365          }
17366          tmp = mkintf(real_channel, conf, reload);
17367 
17368          if (tmp) {
17369             ast_verb(3, "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", real_channel, sig2str(tmp->sig));
17370          } else {
17371             ast_log(LOG_ERROR, "Unable to %s channel '%s'\n",
17372                   (reload == 1) ? "reconfigure" : "register", value);
17373             return -1;
17374          }
17375       }
17376    }
17377 
17378    return 0;
17379 }
17380 
17381 /** The length of the parameters list of 'dahdichan'.
17382  * \todo Move definition of MAX_CHANLIST_LEN to a proper place. */
17383 #define MAX_CHANLIST_LEN 80
17384 
17385 static void process_echocancel(struct dahdi_chan_conf *confp, const char *data, unsigned int line)
17386 {
17387    char *parse = ast_strdupa(data);
17388    char *params[DAHDI_MAX_ECHOCANPARAMS + 1];
17389    unsigned int param_count;
17390    unsigned int x;
17391 
17392    if (!(param_count = ast_app_separate_args(parse, ',', params, ARRAY_LEN(params))))
17393       return;
17394 
17395    memset(&confp->chan.echocancel, 0, sizeof(confp->chan.echocancel));
17396 
17397    /* first parameter is tap length, process it here */
17398 
17399    x = ast_strlen_zero(params[0]) ? 0 : atoi(params[0]);
17400 
17401    if ((x == 32) || (x == 64) || (x == 128) || (x == 256) || (x == 512) || (x == 1024))
17402       confp->chan.echocancel.head.tap_length = x;
17403    else if ((confp->chan.echocancel.head.tap_length = ast_true(params[0])))
17404       confp->chan.echocancel.head.tap_length = 128;
17405 
17406    /* now process any remaining parameters */
17407 
17408    for (x = 1; x < param_count; x++) {
17409       struct {
17410          char *name;
17411          char *value;
17412       } param;
17413 
17414       if (ast_app_separate_args(params[x], '=', (char **) &param, 2) < 1) {
17415          ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, params[x]);
17416          continue;
17417       }
17418 
17419       if (ast_strlen_zero(param.name) || (strlen(param.name) > sizeof(confp->chan.echocancel.params[0].name)-1)) {
17420          ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, param.name);
17421          continue;
17422       }
17423 
17424       strcpy(confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].name, param.name);
17425 
17426       if (param.value) {
17427          if (sscanf(param.value, "%30d", &confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].value) != 1) {
17428             ast_log(LOG_WARNING, "Invalid echocancel parameter value supplied at line %d: '%s'\n", line, param.value);
17429             continue;
17430          }
17431       }
17432       confp->chan.echocancel.head.param_count++;
17433    }
17434 }
17435 
17436 #if defined(HAVE_PRI)
17437 #if defined(HAVE_PRI_DISPLAY_TEXT)
17438 /*!
17439  * \internal
17440  * \brief Determine the configured display text options.
17441  * \since 10.0
17442  *
17443  * \param value Configuration value string.
17444  *
17445  * \return Configured display text option flags.
17446  */
17447 static unsigned long dahdi_display_text_option(const char *value)
17448 {
17449    char *val_str;
17450    char *opt_str;
17451    unsigned long options;
17452 
17453    options = 0;
17454    val_str = ast_strdupa(value);
17455 
17456    for (;;) {
17457       opt_str = strsep(&val_str, ",");
17458       if (!opt_str) {
17459          break;
17460       }
17461       opt_str = ast_strip(opt_str);
17462       if (!*opt_str) {
17463          continue;
17464       }
17465 
17466       if (!strcasecmp(opt_str, "block")) {
17467          options |= PRI_DISPLAY_OPTION_BLOCK;
17468       } else if (!strcasecmp(opt_str, "name_initial")) {
17469          options |= PRI_DISPLAY_OPTION_NAME_INITIAL;
17470       } else if (!strcasecmp(opt_str, "name_update")) {
17471          options |= PRI_DISPLAY_OPTION_NAME_UPDATE;
17472       } else if (!strcasecmp(opt_str, "name")) {
17473          options |= (PRI_DISPLAY_OPTION_NAME_INITIAL | PRI_DISPLAY_OPTION_NAME_UPDATE);
17474       } else if (!strcasecmp(opt_str, "text")) {
17475          options |= PRI_DISPLAY_OPTION_TEXT;
17476       }
17477    }
17478    return options;
17479 }
17480 #endif   /* defined(HAVE_PRI_DISPLAY_TEXT) */
17481 #endif   /* defined(HAVE_PRI) */
17482 
17483 #if defined(HAVE_PRI)
17484 #if defined(HAVE_PRI_DATETIME_SEND)
17485 /*!
17486  * \internal
17487  * \brief Determine the configured date/time send policy option.
17488  * \since 10.0
17489  *
17490  * \param value Configuration value string.
17491  *
17492  * \return Configured date/time send policy option.
17493  */
17494 static int dahdi_datetime_send_option(const char *value)
17495 {
17496    int option;
17497 
17498    option = PRI_DATE_TIME_SEND_DEFAULT;
17499 
17500    if (ast_false(value)) {
17501       option = PRI_DATE_TIME_SEND_NO;
17502    } else if (!strcasecmp(value, "date")) {
17503       option = PRI_DATE_TIME_SEND_DATE;
17504    } else if (!strcasecmp(value, "date_hh")) {
17505       option = PRI_DATE_TIME_SEND_DATE_HH;
17506    } else if (!strcasecmp(value, "date_hhmm")) {
17507       option = PRI_DATE_TIME_SEND_DATE_HHMM;
17508    } else if (!strcasecmp(value, "date_hhmmss")) {
17509       option = PRI_DATE_TIME_SEND_DATE_HHMMSS;
17510    }
17511 
17512    return option;
17513 }
17514 #endif   /* defined(HAVE_PRI_DATETIME_SEND) */
17515 #endif   /* defined(HAVE_PRI) */
17516 
17517 /*! process_dahdi() - ignore keyword 'channel' and similar */
17518 #define PROC_DAHDI_OPT_NOCHAN  (1 << 0)
17519 /*! process_dahdi() - No warnings on non-existing cofiguration keywords */
17520 #define PROC_DAHDI_OPT_NOWARN  (1 << 1)
17521 
17522 static void parse_busy_pattern(struct ast_variable *v, struct ast_dsp_busy_pattern *busy_cadence)
17523 {
17524    int count_pattern = 0;
17525    int norval = 0;
17526    char *temp = NULL;
17527 
17528    for (; ;) {
17529       /* Scans the string for the next value in the pattern. If none, it checks to see if any have been entered so far. */
17530       if(!sscanf(v->value, "%30d", &norval) && count_pattern == 0) { 
17531          ast_log(LOG_ERROR, "busypattern= expects either busypattern=tonelength,quietlength or busypattern=t1length, q1length, t2length, q2length at line %d.\n", v->lineno);
17532          break;
17533       }
17534 
17535       busy_cadence->pattern[count_pattern] = norval; 
17536       
17537       count_pattern++;
17538       if (count_pattern == 4) {
17539          break;
17540       }
17541 
17542       temp = strchr(v->value, ',');
17543       if (temp == NULL) {
17544          break;
17545       }
17546       v->value = temp + 1;
17547    }
17548    busy_cadence->length = count_pattern;
17549 
17550    if (count_pattern % 2 != 0) { 
17551       /* The pattern length must be divisible by two */
17552       ast_log(LOG_ERROR, "busypattern= expects either busypattern=tonelength,quietlength or busypattern=t1length, q1length, t2length, q2length at line %d.\n", v->lineno);
17553    }
17554    
17555 }
17556 
17557 static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct ast_variable *v, int reload, int options)
17558 {
17559    struct dahdi_pvt *tmp;
17560    int y;
17561    int found_pseudo = 0;
17562    struct ast_variable *dahdichan = NULL;
17563 
17564    for (; v; v = v->next) {
17565       if (!ast_jb_read_conf(&global_jbconf, v->name, v->value))
17566          continue;
17567 
17568       /* Create the interface list */
17569       if (!strcasecmp(v->name, "channel") || !strcasecmp(v->name, "channels")) {
17570          if (options & PROC_DAHDI_OPT_NOCHAN) {
17571             ast_log(LOG_WARNING, "Channel '%s' ignored.\n", v->value);
17572             continue;
17573          }
17574          if (build_channels(confp, v->value, reload, v->lineno, &found_pseudo)) {
17575             if (confp->ignore_failed_channels) {
17576                ast_log(LOG_WARNING, "Channel '%s' failure ignored: ignore_failed_channels.\n", v->value);
17577                continue;
17578             } else {
17579                return -1;
17580             }
17581          }
17582          ast_debug(1, "Channel '%s' configured.\n", v->value);
17583       } else if (!strcasecmp(v->name, "ignore_failed_channels")) {
17584          confp->ignore_failed_channels = ast_true(v->value);
17585       } else if (!strcasecmp(v->name, "buffers")) {
17586          if (parse_buffers_policy(v->value, &confp->chan.buf_no, &confp->chan.buf_policy)) {
17587             ast_log(LOG_WARNING, "Using default buffer policy.\n");
17588             confp->chan.buf_no = numbufs;
17589             confp->chan.buf_policy = DAHDI_POLICY_IMMEDIATE;
17590          }
17591       } else if (!strcasecmp(v->name, "faxbuffers")) {
17592          if (!parse_buffers_policy(v->value, &confp->chan.faxbuf_no, &confp->chan.faxbuf_policy)) {
17593             confp->chan.usefaxbuffers = 1;
17594          }
17595       } else if (!strcasecmp(v->name, "dahdichan")) {
17596          /* Only process the last dahdichan value. */
17597          dahdichan = v;
17598       } else if (!strcasecmp(v->name, "usedistinctiveringdetection")) {
17599          usedistinctiveringdetection = ast_true(v->value);
17600       } else if (!strcasecmp(v->name, "distinctiveringaftercid")) {
17601          distinctiveringaftercid = ast_true(v->value);
17602       } else if (!strcasecmp(v->name, "dring1context")) {
17603          ast_copy_string(confp->chan.drings.ringContext[0].contextData,v->value,sizeof(confp->chan.drings.ringContext[0].contextData));
17604       } else if (!strcasecmp(v->name, "dring2context")) {
17605          ast_copy_string(confp->chan.drings.ringContext[1].contextData,v->value,sizeof(confp->chan.drings.ringContext[1].contextData));
17606       } else if (!strcasecmp(v->name, "dring3context")) {
17607          ast_copy_string(confp->chan.drings.ringContext[2].contextData,v->value,sizeof(confp->chan.drings.ringContext[2].contextData));
17608       } else if (!strcasecmp(v->name, "dring1range")) {
17609          confp->chan.drings.ringnum[0].range = atoi(v->value);
17610       } else if (!strcasecmp(v->name, "dring2range")) {
17611          confp->chan.drings.ringnum[1].range = atoi(v->value);
17612       } else if (!strcasecmp(v->name, "dring3range")) {
17613          confp->chan.drings.ringnum[2].range = atoi(v->value);
17614       } else if (!strcasecmp(v->name, "dring1")) {
17615          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]);
17616       } else if (!strcasecmp(v->name, "dring2")) {
17617          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]);
17618       } else if (!strcasecmp(v->name, "dring3")) {
17619          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]);
17620       } else if (!strcasecmp(v->name, "usecallerid")) {
17621          confp->chan.use_callerid = ast_true(v->value);
17622       } else if (!strcasecmp(v->name, "cidsignalling")) {
17623          if (!strcasecmp(v->value, "bell"))
17624             confp->chan.cid_signalling = CID_SIG_BELL;
17625          else if (!strcasecmp(v->value, "v23"))
17626             confp->chan.cid_signalling = CID_SIG_V23;
17627          else if (!strcasecmp(v->value, "dtmf"))
17628             confp->chan.cid_signalling = CID_SIG_DTMF;
17629          else if (!strcasecmp(v->value, "smdi"))
17630             confp->chan.cid_signalling = CID_SIG_SMDI;
17631          else if (!strcasecmp(v->value, "v23_jp"))
17632             confp->chan.cid_signalling = CID_SIG_V23_JP;
17633          else if (ast_true(v->value))
17634             confp->chan.cid_signalling = CID_SIG_BELL;
17635       } else if (!strcasecmp(v->name, "cidstart")) {
17636          if (!strcasecmp(v->value, "ring"))
17637             confp->chan.cid_start = CID_START_RING;
17638          else if (!strcasecmp(v->value, "polarity_in"))
17639             confp->chan.cid_start = CID_START_POLARITY_IN;
17640          else if (!strcasecmp(v->value, "polarity"))
17641             confp->chan.cid_start = CID_START_POLARITY;
17642          else if (!strcasecmp(v->value, "dtmf"))
17643             confp->chan.cid_start = CID_START_DTMF_NOALERT;
17644          else if (ast_true(v->value))
17645             confp->chan.cid_start = CID_START_RING;
17646       } else if (!strcasecmp(v->name, "threewaycalling")) {
17647          confp->chan.threewaycalling = ast_true(v->value);
17648       } else if (!strcasecmp(v->name, "cancallforward")) {
17649          confp->chan.cancallforward = ast_true(v->value);
17650       } else if (!strcasecmp(v->name, "relaxdtmf")) {
17651          if (ast_true(v->value))
17652             confp->chan.dtmfrelax = DSP_DIGITMODE_RELAXDTMF;
17653          else
17654             confp->chan.dtmfrelax = 0;
17655       } else if (!strcasecmp(v->name, "mailbox")) {
17656          ast_copy_string(confp->chan.mailbox, v->value, sizeof(confp->chan.mailbox));
17657       } else if (!strcasecmp(v->name, "description")) {
17658          ast_copy_string(confp->chan.description, v->value, sizeof(confp->chan.description));
17659       } else if (!strcasecmp(v->name, "hasvoicemail")) {
17660          if (ast_true(v->value) && ast_strlen_zero(confp->chan.mailbox)) {
17661             ast_copy_string(confp->chan.mailbox, cat, sizeof(confp->chan.mailbox));
17662          }
17663       } else if (!strcasecmp(v->name, "adsi")) {
17664          confp->chan.adsi = ast_true(v->value);
17665       } else if (!strcasecmp(v->name, "usesmdi")) {
17666          confp->chan.use_smdi = ast_true(v->value);
17667       } else if (!strcasecmp(v->name, "smdiport")) {
17668          ast_copy_string(confp->smdi_port, v->value, sizeof(confp->smdi_port));
17669       } else if (!strcasecmp(v->name, "transfer")) {
17670          confp->chan.transfer = ast_true(v->value);
17671       } else if (!strcasecmp(v->name, "canpark")) {
17672          confp->chan.canpark = ast_true(v->value);
17673       } else if (!strcasecmp(v->name, "echocancelwhenbridged")) {
17674          confp->chan.echocanbridged = ast_true(v->value);
17675       } else if (!strcasecmp(v->name, "busydetect")) {
17676          confp->chan.busydetect = ast_true(v->value);
17677       } else if (!strcasecmp(v->name, "busycount")) {
17678          confp->chan.busycount = atoi(v->value);
17679       } else if (!strcasecmp(v->name, "busypattern")) {
17680          parse_busy_pattern(v, &confp->chan.busy_cadence);
17681       } else if (!strcasecmp(v->name, "callprogress")) {
17682          confp->chan.callprogress &= ~CALLPROGRESS_PROGRESS;
17683          if (ast_true(v->value))
17684             confp->chan.callprogress |= CALLPROGRESS_PROGRESS;
17685       } else if (!strcasecmp(v->name, "waitfordialtone")) {
17686          confp->chan.waitfordialtone = atoi(v->value);
17687       } else if (!strcasecmp(v->name, "dialtone_detect")) {
17688          if (!strcasecmp(v->value, "always")) {
17689             confp->chan.dialtone_detect = -1;
17690          } else if (ast_true(v->value)) {
17691             confp->chan.dialtone_detect = DEFAULT_DIALTONE_DETECT_TIMEOUT;
17692          } else if (ast_false(v->value)) {
17693             confp->chan.dialtone_detect = 0;
17694          } else {
17695             confp->chan.dialtone_detect = ast_strlen_zero(v->value) ? 0 : (8 * atoi(v->value)) / READ_SIZE;
17696          }
17697       } else if (!strcasecmp(v->name, "faxdetect")) {
17698          confp->chan.callprogress &= ~CALLPROGRESS_FAX;
17699          if (!strcasecmp(v->value, "incoming")) {
17700             confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING;
17701          } else if (!strcasecmp(v->value, "outgoing")) {
17702             confp->chan.callprogress |= CALLPROGRESS_FAX_OUTGOING;
17703          } else if (!strcasecmp(v->value, "both") || ast_true(v->value))
17704             confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING;
17705       } else if (!strcasecmp(v->name, "echocancel")) {
17706          process_echocancel(confp, v->value, v->lineno);
17707       } else if (!strcasecmp(v->name, "echotraining")) {
17708          if (sscanf(v->value, "%30d", &y) == 1) {
17709             if ((y < 10) || (y > 4000)) {
17710                ast_log(LOG_WARNING, "Echo training time must be within the range of 10 to 4000 ms at line %d.\n", v->lineno);
17711             } else {
17712                confp->chan.echotraining = y;
17713             }
17714          } else if (ast_true(v->value)) {
17715             confp->chan.echotraining = 400;
17716          } else
17717             confp->chan.echotraining = 0;
17718       } else if (!strcasecmp(v->name, "hidecallerid")) {
17719          confp->chan.hidecallerid = ast_true(v->value);
17720       } else if (!strcasecmp(v->name, "hidecalleridname")) {
17721          confp->chan.hidecalleridname = ast_true(v->value);
17722       } else if (!strcasecmp(v->name, "pulsedial")) {
17723          confp->chan.pulse = ast_true(v->value);
17724       } else if (!strcasecmp(v->name, "callreturn")) {
17725          confp->chan.callreturn = ast_true(v->value);
17726       } else if (!strcasecmp(v->name, "callwaiting")) {
17727          confp->chan.callwaiting = ast_true(v->value);
17728       } else if (!strcasecmp(v->name, "callwaitingcallerid")) {
17729          confp->chan.callwaitingcallerid = ast_true(v->value);
17730       } else if (!strcasecmp(v->name, "context")) {
17731          ast_copy_string(confp->chan.context, v->value, sizeof(confp->chan.context));
17732       } else if (!strcasecmp(v->name, "language")) {
17733          ast_copy_string(confp->chan.language, v->value, sizeof(confp->chan.language));
17734       } else if (!strcasecmp(v->name, "progzone")) {
17735          ast_copy_string(progzone, v->value, sizeof(progzone));
17736       } else if (!strcasecmp(v->name, "mohinterpret")
17737          ||!strcasecmp(v->name, "musiconhold") || !strcasecmp(v->name, "musicclass")) {
17738          ast_copy_string(confp->chan.mohinterpret, v->value, sizeof(confp->chan.mohinterpret));
17739       } else if (!strcasecmp(v->name, "mohsuggest")) {
17740          ast_copy_string(confp->chan.mohsuggest, v->value, sizeof(confp->chan.mohsuggest));
17741       } else if (!strcasecmp(v->name, "parkinglot")) {
17742          ast_copy_string(confp->chan.parkinglot, v->value, sizeof(confp->chan.parkinglot));
17743       } else if (!strcasecmp(v->name, "stripmsd")) {
17744          ast_log(LOG_NOTICE, "Configuration option \"%s\" has been deprecated. Please use dialplan instead\n", v->name);
17745          confp->chan.stripmsd = atoi(v->value);
17746       } else if (!strcasecmp(v->name, "jitterbuffers")) {
17747          numbufs = atoi(v->value);
17748       } else if (!strcasecmp(v->name, "group")) {
17749          confp->chan.group = ast_get_group(v->value);
17750       } else if (!strcasecmp(v->name, "callgroup")) {
17751          if (!strcasecmp(v->value, "none"))
17752             confp->chan.callgroup = 0;
17753          else
17754             confp->chan.callgroup = ast_get_group(v->value);
17755       } else if (!strcasecmp(v->name, "pickupgroup")) {
17756          if (!strcasecmp(v->value, "none"))
17757             confp->chan.pickupgroup = 0;
17758          else
17759             confp->chan.pickupgroup = ast_get_group(v->value);
17760       } else if (!strcasecmp(v->name, "namedcallgroup")) {
17761          confp->chan.named_callgroups = ast_get_namedgroups(v->value);
17762       } else if (!strcasecmp(v->name, "namedpickupgroup")) {
17763          confp->chan.named_pickupgroups = ast_get_namedgroups(v->value);
17764       } else if (!strcasecmp(v->name, "setvar")) {
17765          char *varname = ast_strdupa(v->value), *varval = NULL;
17766          struct ast_variable *tmpvar;
17767          if (varname && (varval = strchr(varname, '='))) {
17768             *varval++ = '\0';
17769             if ((tmpvar = ast_variable_new(varname, varval, ""))) {
17770                tmpvar->next = confp->chan.vars;
17771                confp->chan.vars = tmpvar;
17772             }
17773          }
17774       } else if (!strcasecmp(v->name, "immediate")) {
17775          confp->chan.immediate = ast_true(v->value);
17776       } else if (!strcasecmp(v->name, "transfertobusy")) {
17777          confp->chan.transfertobusy = ast_true(v->value);
17778       } else if (!strcasecmp(v->name, "mwimonitor")) {
17779          confp->chan.mwimonitor_neon = 0;
17780          confp->chan.mwimonitor_fsk = 0;
17781          confp->chan.mwimonitor_rpas = 0;
17782          if (strcasestr(v->value, "fsk")) {
17783             confp->chan.mwimonitor_fsk = 1;
17784          }
17785          if (strcasestr(v->value, "rpas")) {
17786             confp->chan.mwimonitor_rpas = 1;
17787          }
17788          if (strcasestr(v->value, "neon")) {
17789             confp->chan.mwimonitor_neon = 1;
17790          }
17791          /* If set to true or yes, assume that simple fsk is desired */
17792          if (ast_true(v->value)) {
17793             confp->chan.mwimonitor_fsk = 1;
17794          }
17795       } else if (!strcasecmp(v->name, "cid_rxgain")) {
17796          if (sscanf(v->value, "%30f", &confp->chan.cid_rxgain) != 1) {
17797             ast_log(LOG_WARNING, "Invalid cid_rxgain: %s at line %d.\n", v->value, v->lineno);
17798          }
17799       } else if (!strcasecmp(v->name, "rxgain")) {
17800          if (sscanf(v->value, "%30f", &confp->chan.rxgain) != 1) {
17801             ast_log(LOG_WARNING, "Invalid rxgain: %s at line %d.\n", v->value, v->lineno);
17802          }
17803       } else if (!strcasecmp(v->name, "txgain")) {
17804          if (sscanf(v->value, "%30f", &confp->chan.txgain) != 1) {
17805             ast_log(LOG_WARNING, "Invalid txgain: %s at line %d.\n", v->value, v->lineno);
17806          }
17807       } else if (!strcasecmp(v->name, "txdrc")) {
17808          if (sscanf(v->value, "%f", &confp->chan.txdrc) != 1) {
17809             ast_log(LOG_WARNING, "Invalid txdrc: %s\n", v->value);
17810          }
17811       } else if (!strcasecmp(v->name, "rxdrc")) {
17812          if (sscanf(v->value, "%f", &confp->chan.rxdrc) != 1) {
17813             ast_log(LOG_WARNING, "Invalid rxdrc: %s\n", v->value);
17814          }
17815       } else if (!strcasecmp(v->name, "tonezone")) {
17816          if (sscanf(v->value, "%30d", &confp->chan.tonezone) != 1) {
17817             ast_log(LOG_WARNING, "Invalid tonezone: %s at line %d.\n", v->value, v->lineno);
17818          }
17819       } else if (!strcasecmp(v->name, "callerid")) {
17820          if (!strcasecmp(v->value, "asreceived")) {
17821             confp->chan.cid_num[0] = '\0';
17822             confp->chan.cid_name[0] = '\0';
17823          } else {
17824             ast_callerid_split(v->value, confp->chan.cid_name, sizeof(confp->chan.cid_name), confp->chan.cid_num, sizeof(confp->chan.cid_num));
17825          }
17826       } else if (!strcasecmp(v->name, "fullname")) {
17827          ast_copy_string(confp->chan.cid_name, v->value, sizeof(confp->chan.cid_name));
17828       } else if (!strcasecmp(v->name, "cid_number")) {
17829          ast_copy_string(confp->chan.cid_num, v->value, sizeof(confp->chan.cid_num));
17830       } else if (!strcasecmp(v->name, "cid_tag")) {
17831          ast_copy_string(confp->chan.cid_tag, v->value, sizeof(confp->chan.cid_tag));
17832       } else if (!strcasecmp(v->name, "useincomingcalleridondahditransfer")) {
17833          confp->chan.dahditrcallerid = ast_true(v->value);
17834       } else if (!strcasecmp(v->name, "restrictcid")) {
17835          confp->chan.restrictcid = ast_true(v->value);
17836       } else if (!strcasecmp(v->name, "usecallingpres")) {
17837          confp->chan.use_callingpres = ast_true(v->value);
17838       } else if (!strcasecmp(v->name, "accountcode")) {
17839          ast_copy_string(confp->chan.accountcode, v->value, sizeof(confp->chan.accountcode));
17840       } else if (!strcasecmp(v->name, "amaflags")) {
17841          y = ast_cdr_amaflags2int(v->value);
17842          if (y < 0)
17843             ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d.\n", v->value, v->lineno);
17844          else
17845             confp->chan.amaflags = y;
17846       } else if (!strcasecmp(v->name, "polarityonanswerdelay")) {
17847          confp->chan.polarityonanswerdelay = atoi(v->value);
17848       } else if (!strcasecmp(v->name, "answeronpolarityswitch")) {
17849          confp->chan.answeronpolarityswitch = ast_true(v->value);
17850       } else if (!strcasecmp(v->name, "hanguponpolarityswitch")) {
17851          confp->chan.hanguponpolarityswitch = ast_true(v->value);
17852       } else if (!strcasecmp(v->name, "sendcalleridafter")) {
17853          confp->chan.sendcalleridafter = atoi(v->value);
17854       } else if (!strcasecmp(v->name, "mwimonitornotify")) {
17855          ast_copy_string(mwimonitornotify, v->value, sizeof(mwimonitornotify));
17856       } else if (ast_cc_is_config_param(v->name)) {
17857          ast_cc_set_param(confp->chan.cc_params, v->name, v->value);
17858       } else if (!strcasecmp(v->name, "mwisendtype")) {
17859 #ifndef HAVE_DAHDI_LINEREVERSE_VMWI  /* backward compatibility for older dahdi VMWI implementation */
17860          if (!strcasecmp(v->value, "rpas")) { /* Ring Pulse Alert Signal */
17861             mwisend_rpas = 1;
17862          } else {
17863             mwisend_rpas = 0;
17864          }
17865 #else
17866          /* Default is fsk, to turn it off you must specify nofsk */
17867          memset(&confp->chan.mwisend_setting, 0, sizeof(confp->chan.mwisend_setting));
17868          if (strcasestr(v->value, "nofsk")) {      /* NoFSK */
17869             confp->chan.mwisend_fsk = 0;
17870          } else {             /* Default FSK */
17871             confp->chan.mwisend_fsk = 1;
17872          }
17873          if (strcasestr(v->value, "rpas")) {       /* Ring Pulse Alert Signal, normally followed by FSK */
17874             confp->chan.mwisend_rpas = 1;
17875          } else {
17876             confp->chan.mwisend_rpas = 0;
17877          }
17878          if (strcasestr(v->value, "lrev")) {       /* Line Reversal */
17879             confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_LREV;
17880          }
17881          if (strcasestr(v->value, "hvdc")) {       /* HV 90VDC */
17882             confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_HVDC;
17883          }
17884          if ( (strcasestr(v->value, "neon")) || (strcasestr(v->value, "hvac")) ){   /* 90V DC pulses */
17885             confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_HVAC;
17886          }
17887 #endif
17888       } else if (reload != 1) {
17889           if (!strcasecmp(v->name, "signalling") || !strcasecmp(v->name, "signaling")) {
17890             int orig_radio = confp->chan.radio;
17891             int orig_outsigmod = confp->chan.outsigmod;
17892             int orig_auto = confp->is_sig_auto;
17893 
17894             confp->chan.radio = 0;
17895             confp->chan.outsigmod = -1;
17896             confp->is_sig_auto = 0;
17897             if (!strcasecmp(v->value, "em")) {
17898                confp->chan.sig = SIG_EM;
17899             } else if (!strcasecmp(v->value, "em_e1")) {
17900                confp->chan.sig = SIG_EM_E1;
17901             } else if (!strcasecmp(v->value, "em_w")) {
17902                confp->chan.sig = SIG_EMWINK;
17903             } else if (!strcasecmp(v->value, "fxs_ls")) {
17904                confp->chan.sig = SIG_FXSLS;
17905             } else if (!strcasecmp(v->value, "fxs_gs")) {
17906                confp->chan.sig = SIG_FXSGS;
17907             } else if (!strcasecmp(v->value, "fxs_ks")) {
17908                confp->chan.sig = SIG_FXSKS;
17909             } else if (!strcasecmp(v->value, "fxo_ls")) {
17910                confp->chan.sig = SIG_FXOLS;
17911             } else if (!strcasecmp(v->value, "fxo_gs")) {
17912                confp->chan.sig = SIG_FXOGS;
17913             } else if (!strcasecmp(v->value, "fxo_ks")) {
17914                confp->chan.sig = SIG_FXOKS;
17915             } else if (!strcasecmp(v->value, "fxs_rx")) {
17916                confp->chan.sig = SIG_FXSKS;
17917                confp->chan.radio = 1;
17918             } else if (!strcasecmp(v->value, "fxo_rx")) {
17919                confp->chan.sig = SIG_FXOLS;
17920                confp->chan.radio = 1;
17921             } else if (!strcasecmp(v->value, "fxs_tx")) {
17922                confp->chan.sig = SIG_FXSLS;
17923                confp->chan.radio = 1;
17924             } else if (!strcasecmp(v->value, "fxo_tx")) {
17925                confp->chan.sig = SIG_FXOGS;
17926                confp->chan.radio = 1;
17927             } else if (!strcasecmp(v->value, "em_rx")) {
17928                confp->chan.sig = SIG_EM;
17929                confp->chan.radio = 1;
17930             } else if (!strcasecmp(v->value, "em_tx")) {
17931                confp->chan.sig = SIG_EM;
17932                confp->chan.radio = 1;
17933             } else if (!strcasecmp(v->value, "em_rxtx")) {
17934                confp->chan.sig = SIG_EM;
17935                confp->chan.radio = 2;
17936             } else if (!strcasecmp(v->value, "em_txrx")) {
17937                confp->chan.sig = SIG_EM;
17938                confp->chan.radio = 2;
17939             } else if (!strcasecmp(v->value, "sf")) {
17940                confp->chan.sig = SIG_SF;
17941             } else if (!strcasecmp(v->value, "sf_w")) {
17942                confp->chan.sig = SIG_SFWINK;
17943             } else if (!strcasecmp(v->value, "sf_featd")) {
17944                confp->chan.sig = SIG_FEATD;
17945             } else if (!strcasecmp(v->value, "sf_featdmf")) {
17946                confp->chan.sig = SIG_FEATDMF;
17947             } else if (!strcasecmp(v->value, "sf_featb")) {
17948                confp->chan.sig = SIG_SF_FEATB;
17949             } else if (!strcasecmp(v->value, "sf")) {
17950                confp->chan.sig = SIG_SF;
17951             } else if (!strcasecmp(v->value, "sf_rx")) {
17952                confp->chan.sig = SIG_SF;
17953                confp->chan.radio = 1;
17954             } else if (!strcasecmp(v->value, "sf_tx")) {
17955                confp->chan.sig = SIG_SF;
17956                confp->chan.radio = 1;
17957             } else if (!strcasecmp(v->value, "sf_rxtx")) {
17958                confp->chan.sig = SIG_SF;
17959                confp->chan.radio = 2;
17960             } else if (!strcasecmp(v->value, "sf_txrx")) {
17961                confp->chan.sig = SIG_SF;
17962                confp->chan.radio = 2;
17963             } else if (!strcasecmp(v->value, "featd")) {
17964                confp->chan.sig = SIG_FEATD;
17965             } else if (!strcasecmp(v->value, "featdmf")) {
17966                confp->chan.sig = SIG_FEATDMF;
17967             } else if (!strcasecmp(v->value, "featdmf_ta")) {
17968                confp->chan.sig = SIG_FEATDMF_TA;
17969             } else if (!strcasecmp(v->value, "e911")) {
17970                confp->chan.sig = SIG_E911;
17971             } else if (!strcasecmp(v->value, "fgccama")) {
17972                confp->chan.sig = SIG_FGC_CAMA;
17973             } else if (!strcasecmp(v->value, "fgccamamf")) {
17974                confp->chan.sig = SIG_FGC_CAMAMF;
17975             } else if (!strcasecmp(v->value, "featb")) {
17976                confp->chan.sig = SIG_FEATB;
17977 #ifdef HAVE_PRI
17978             } else if (!strcasecmp(v->value, "pri_net")) {
17979                confp->chan.sig = SIG_PRI;
17980                confp->pri.pri.nodetype = PRI_NETWORK;
17981             } else if (!strcasecmp(v->value, "pri_cpe")) {
17982                confp->chan.sig = SIG_PRI;
17983                confp->pri.pri.nodetype = PRI_CPE;
17984             } else if (!strcasecmp(v->value, "bri_cpe")) {
17985                confp->chan.sig = SIG_BRI;
17986                confp->pri.pri.nodetype = PRI_CPE;
17987             } else if (!strcasecmp(v->value, "bri_net")) {
17988                confp->chan.sig = SIG_BRI;
17989                confp->pri.pri.nodetype = PRI_NETWORK;
17990             } else if (!strcasecmp(v->value, "bri_cpe_ptmp")) {
17991                confp->chan.sig = SIG_BRI_PTMP;
17992                confp->pri.pri.nodetype = PRI_CPE;
17993             } else if (!strcasecmp(v->value, "bri_net_ptmp")) {
17994 #if defined(HAVE_PRI_CALL_HOLD)
17995                confp->chan.sig = SIG_BRI_PTMP;
17996                confp->pri.pri.nodetype = PRI_NETWORK;
17997 #else
17998                ast_log(LOG_WARNING, "How cool would it be if someone implemented this mode!  For now, sucks for you. (line %d)\n", v->lineno);
17999 #endif   /* !defined(HAVE_PRI_CALL_HOLD) */
18000 #endif
18001 #if defined(HAVE_SS7)
18002             } else if (!strcasecmp(v->value, "ss7")) {
18003                confp->chan.sig = SIG_SS7;
18004 #endif   /* defined(HAVE_SS7) */
18005 #ifdef HAVE_OPENR2
18006             } else if (!strcasecmp(v->value, "mfcr2")) {
18007                confp->chan.sig = SIG_MFCR2;
18008 #endif
18009             } else if (!strcasecmp(v->value, "auto")) {
18010                confp->is_sig_auto = 1;
18011             } else {
18012                confp->chan.outsigmod = orig_outsigmod;
18013                confp->chan.radio = orig_radio;
18014                confp->is_sig_auto = orig_auto;
18015                ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
18016             }
18017           } else if (!strcasecmp(v->name, "outsignalling") || !strcasecmp(v->name, "outsignaling")) {
18018             if (!strcasecmp(v->value, "em")) {
18019                confp->chan.outsigmod = SIG_EM;
18020             } else if (!strcasecmp(v->value, "em_e1")) {
18021                confp->chan.outsigmod = SIG_EM_E1;
18022             } else if (!strcasecmp(v->value, "em_w")) {
18023                confp->chan.outsigmod = SIG_EMWINK;
18024             } else if (!strcasecmp(v->value, "sf")) {
18025                confp->chan.outsigmod = SIG_SF;
18026             } else if (!strcasecmp(v->value, "sf_w")) {
18027                confp->chan.outsigmod = SIG_SFWINK;
18028             } else if (!strcasecmp(v->value, "sf_featd")) {
18029                confp->chan.outsigmod = SIG_FEATD;
18030             } else if (!strcasecmp(v->value, "sf_featdmf")) {
18031                confp->chan.outsigmod = SIG_FEATDMF;
18032             } else if (!strcasecmp(v->value, "sf_featb")) {
18033                confp->chan.outsigmod = SIG_SF_FEATB;
18034             } else if (!strcasecmp(v->value, "sf")) {
18035                confp->chan.outsigmod = SIG_SF;
18036             } else if (!strcasecmp(v->value, "featd")) {
18037                confp->chan.outsigmod = SIG_FEATD;
18038             } else if (!strcasecmp(v->value, "featdmf")) {
18039                confp->chan.outsigmod = SIG_FEATDMF;
18040             } else if (!strcasecmp(v->value, "featdmf_ta")) {
18041                confp->chan.outsigmod = SIG_FEATDMF_TA;
18042             } else if (!strcasecmp(v->value, "e911")) {
18043                confp->chan.outsigmod = SIG_E911;
18044             } else if (!strcasecmp(v->value, "fgccama")) {
18045                confp->chan.outsigmod = SIG_FGC_CAMA;
18046             } else if (!strcasecmp(v->value, "fgccamamf")) {
18047                confp->chan.outsigmod = SIG_FGC_CAMAMF;
18048             } else if (!strcasecmp(v->value, "featb")) {
18049                confp->chan.outsigmod = SIG_FEATB;
18050             } else {
18051                ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
18052             }
18053 #ifdef HAVE_PRI
18054          } else if (!strcasecmp(v->name, "pridialplan")) {
18055             if (!strcasecmp(v->value, "national")) {
18056                confp->pri.pri.dialplan = PRI_NATIONAL_ISDN + 1;
18057             } else if (!strcasecmp(v->value, "unknown")) {
18058                confp->pri.pri.dialplan = PRI_UNKNOWN + 1;
18059             } else if (!strcasecmp(v->value, "private")) {
18060                confp->pri.pri.dialplan = PRI_PRIVATE + 1;
18061             } else if (!strcasecmp(v->value, "international")) {
18062                confp->pri.pri.dialplan = PRI_INTERNATIONAL_ISDN + 1;
18063             } else if (!strcasecmp(v->value, "local")) {
18064                confp->pri.pri.dialplan = PRI_LOCAL_ISDN + 1;
18065             } else if (!strcasecmp(v->value, "dynamic")) {
18066                confp->pri.pri.dialplan = -1;
18067             } else if (!strcasecmp(v->value, "redundant")) {
18068                confp->pri.pri.dialplan = -2;
18069             } else {
18070                ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno);
18071             }
18072          } else if (!strcasecmp(v->name, "prilocaldialplan")) {
18073             if (!strcasecmp(v->value, "national")) {
18074                confp->pri.pri.localdialplan = PRI_NATIONAL_ISDN + 1;
18075             } else if (!strcasecmp(v->value, "unknown")) {
18076                confp->pri.pri.localdialplan = PRI_UNKNOWN + 1;
18077             } else if (!strcasecmp(v->value, "private")) {
18078                confp->pri.pri.localdialplan = PRI_PRIVATE + 1;
18079             } else if (!strcasecmp(v->value, "international")) {
18080                confp->pri.pri.localdialplan = PRI_INTERNATIONAL_ISDN + 1;
18081             } else if (!strcasecmp(v->value, "local")) {
18082                confp->pri.pri.localdialplan = PRI_LOCAL_ISDN + 1;
18083             } else if (!strcasecmp(v->value, "from_channel")) {
18084                confp->pri.pri.localdialplan = 0;
18085             } else if (!strcasecmp(v->value, "dynamic")) {
18086                confp->pri.pri.localdialplan = -1;
18087             } else if (!strcasecmp(v->value, "redundant")) {
18088                confp->pri.pri.localdialplan = -2;
18089             } else {
18090                ast_log(LOG_WARNING, "Unknown PRI localdialplan '%s' at line %d.\n", v->value, v->lineno);
18091             }
18092          } else if (!strcasecmp(v->name, "pricpndialplan")) {
18093             if (!strcasecmp(v->value, "national")) {
18094                confp->pri.pri.cpndialplan = PRI_NATIONAL_ISDN + 1;
18095             } else if (!strcasecmp(v->value, "unknown")) {
18096                confp->pri.pri.cpndialplan = PRI_UNKNOWN + 1;
18097             } else if (!strcasecmp(v->value, "private")) {
18098                confp->pri.pri.cpndialplan = PRI_PRIVATE + 1;
18099             } else if (!strcasecmp(v->value, "international")) {
18100                confp->pri.pri.cpndialplan = PRI_INTERNATIONAL_ISDN + 1;
18101             } else if (!strcasecmp(v->value, "local")) {
18102                confp->pri.pri.cpndialplan = PRI_LOCAL_ISDN + 1;
18103             } else if (!strcasecmp(v->value, "from_channel")) {
18104                confp->pri.pri.cpndialplan = 0;
18105             } else if (!strcasecmp(v->value, "dynamic")) {
18106                confp->pri.pri.cpndialplan = -1;
18107             } else if (!strcasecmp(v->value, "redundant")) {
18108                confp->pri.pri.cpndialplan = -2;
18109             } else {
18110                ast_log(LOG_WARNING, "Unknown PRI cpndialplan '%s' at line %d.\n", v->value, v->lineno);
18111             }
18112          } else if (!strcasecmp(v->name, "switchtype")) {
18113             if (!strcasecmp(v->value, "national"))
18114                confp->pri.pri.switchtype = PRI_SWITCH_NI2;
18115             else if (!strcasecmp(v->value, "ni1"))
18116                confp->pri.pri.switchtype = PRI_SWITCH_NI1;
18117             else if (!strcasecmp(v->value, "dms100"))
18118                confp->pri.pri.switchtype = PRI_SWITCH_DMS100;
18119             else if (!strcasecmp(v->value, "4ess"))
18120                confp->pri.pri.switchtype = PRI_SWITCH_ATT4ESS;
18121             else if (!strcasecmp(v->value, "5ess"))
18122                confp->pri.pri.switchtype = PRI_SWITCH_LUCENT5E;
18123             else if (!strcasecmp(v->value, "euroisdn"))
18124                confp->pri.pri.switchtype = PRI_SWITCH_EUROISDN_E1;
18125             else if (!strcasecmp(v->value, "qsig"))
18126                confp->pri.pri.switchtype = PRI_SWITCH_QSIG;
18127             else {
18128                ast_log(LOG_ERROR, "Unknown switchtype '%s' at line %d.\n", v->value, v->lineno);
18129                return -1;
18130             }
18131          } else if (!strcasecmp(v->name, "msn")) {
18132             ast_copy_string(confp->pri.pri.msn_list, v->value,
18133                sizeof(confp->pri.pri.msn_list));
18134          } else if (!strcasecmp(v->name, "nsf")) {
18135             if (!strcasecmp(v->value, "sdn"))
18136                confp->pri.pri.nsf = PRI_NSF_SDN;
18137             else if (!strcasecmp(v->value, "megacom"))
18138                confp->pri.pri.nsf = PRI_NSF_MEGACOM;
18139             else if (!strcasecmp(v->value, "tollfreemegacom"))
18140                confp->pri.pri.nsf = PRI_NSF_TOLL_FREE_MEGACOM;
18141             else if (!strcasecmp(v->value, "accunet"))
18142                confp->pri.pri.nsf = PRI_NSF_ACCUNET;
18143             else if (!strcasecmp(v->value, "none"))
18144                confp->pri.pri.nsf = PRI_NSF_NONE;
18145             else {
18146                ast_log(LOG_WARNING, "Unknown network-specific facility '%s' at line %d.\n", v->value, v->lineno);
18147                confp->pri.pri.nsf = PRI_NSF_NONE;
18148             }
18149          } else if (!strcasecmp(v->name, "priindication")) {
18150             if (!strcasecmp(v->value, "outofband"))
18151                confp->chan.priindication_oob = 1;
18152             else if (!strcasecmp(v->value, "inband"))
18153                confp->chan.priindication_oob = 0;
18154             else
18155                ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d.\n",
18156                   v->value, v->lineno);
18157          } else if (!strcasecmp(v->name, "priexclusive")) {
18158             confp->chan.priexclusive = ast_true(v->value);
18159          } else if (!strcasecmp(v->name, "internationalprefix")) {
18160             ast_copy_string(confp->pri.pri.internationalprefix, v->value, sizeof(confp->pri.pri.internationalprefix));
18161          } else if (!strcasecmp(v->name, "nationalprefix")) {
18162             ast_copy_string(confp->pri.pri.nationalprefix, v->value, sizeof(confp->pri.pri.nationalprefix));
18163          } else if (!strcasecmp(v->name, "localprefix")) {
18164             ast_copy_string(confp->pri.pri.localprefix, v->value, sizeof(confp->pri.pri.localprefix));
18165          } else if (!strcasecmp(v->name, "privateprefix")) {
18166             ast_copy_string(confp->pri.pri.privateprefix, v->value, sizeof(confp->pri.pri.privateprefix));
18167          } else if (!strcasecmp(v->name, "unknownprefix")) {
18168             ast_copy_string(confp->pri.pri.unknownprefix, v->value, sizeof(confp->pri.pri.unknownprefix));
18169          } else if (!strcasecmp(v->name, "resetinterval")) {
18170             if (!strcasecmp(v->value, "never"))
18171                confp->pri.pri.resetinterval = -1;
18172             else if (atoi(v->value) >= 60)
18173                confp->pri.pri.resetinterval = atoi(v->value);
18174             else
18175                ast_log(LOG_WARNING, "'%s' is not a valid reset interval, should be >= 60 seconds or 'never' at line %d.\n",
18176                   v->value, v->lineno);
18177          } else if (!strcasecmp(v->name, "minunused")) {
18178             confp->pri.pri.minunused = atoi(v->value);
18179          } else if (!strcasecmp(v->name, "minidle")) {
18180             confp->pri.pri.minidle = atoi(v->value);
18181          } else if (!strcasecmp(v->name, "idleext")) {
18182             ast_copy_string(confp->pri.pri.idleext, v->value, sizeof(confp->pri.pri.idleext));
18183          } else if (!strcasecmp(v->name, "idledial")) {
18184             ast_copy_string(confp->pri.pri.idledial, v->value, sizeof(confp->pri.pri.idledial));
18185          } else if (!strcasecmp(v->name, "overlapdial")) {
18186             if (ast_true(v->value)) {
18187                confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
18188             } else if (!strcasecmp(v->value, "incoming")) {
18189                confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_INCOMING;
18190             } else if (!strcasecmp(v->value, "outgoing")) {
18191                confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_OUTGOING;
18192             } else if (!strcasecmp(v->value, "both") || ast_true(v->value)) {
18193                confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
18194             } else {
18195                confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_NONE;
18196             }
18197 #ifdef HAVE_PRI_PROG_W_CAUSE
18198          } else if (!strcasecmp(v->name, "qsigchannelmapping")) {
18199             if (!strcasecmp(v->value, "logical")) {
18200                confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_LOGICAL;
18201             } else if (!strcasecmp(v->value, "physical")) {
18202                confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL;
18203             } else {
18204                confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL;
18205             }
18206 #endif
18207          } else if (!strcasecmp(v->name, "discardremoteholdretrieval")) {
18208             confp->pri.pri.discardremoteholdretrieval = ast_true(v->value);
18209 #if defined(HAVE_PRI_SERVICE_MESSAGES)
18210          } else if (!strcasecmp(v->name, "service_message_support")) {
18211             /* assuming switchtype for this channel group has been configured already */
18212             if ((confp->pri.pri.switchtype == PRI_SWITCH_ATT4ESS 
18213                || confp->pri.pri.switchtype == PRI_SWITCH_LUCENT5E
18214                || confp->pri.pri.switchtype == PRI_SWITCH_NI2) && ast_true(v->value)) {
18215                confp->pri.pri.enable_service_message_support = 1;
18216             } else {
18217                confp->pri.pri.enable_service_message_support = 0;
18218             }
18219 #endif   /* defined(HAVE_PRI_SERVICE_MESSAGES) */
18220 #ifdef HAVE_PRI_INBANDDISCONNECT
18221          } else if (!strcasecmp(v->name, "inbanddisconnect")) {
18222             confp->pri.pri.inbanddisconnect = ast_true(v->value);
18223 #endif
18224          } else if (!strcasecmp(v->name, "pritimer")) {
18225 #ifdef PRI_GETSET_TIMERS
18226             char tmp[20];
18227             char *timerc;
18228             char *c;
18229             int timer;
18230             int timeridx;
18231 
18232             ast_copy_string(tmp, v->value, sizeof(tmp));
18233             c = tmp;
18234             timerc = strsep(&c, ",");
18235             if (!ast_strlen_zero(timerc) && !ast_strlen_zero(c)) {
18236                timeridx = pri_timer2idx(timerc);
18237                timer = atoi(c);
18238                if (timeridx < 0 || PRI_MAX_TIMERS <= timeridx) {
18239                   ast_log(LOG_WARNING,
18240                      "'%s' is not a valid ISDN timer at line %d.\n", timerc,
18241                      v->lineno);
18242                } else if (!timer) {
18243                   ast_log(LOG_WARNING,
18244                      "'%s' is not a valid value for ISDN timer '%s' at line %d.\n",
18245                      c, timerc, v->lineno);
18246                } else {
18247                   confp->pri.pri.pritimers[timeridx] = timer;
18248                }
18249             } else {
18250                ast_log(LOG_WARNING,
18251                   "'%s' is not a valid ISDN timer configuration string at line %d.\n",
18252                   v->value, v->lineno);
18253             }
18254 #endif /* PRI_GETSET_TIMERS */
18255          } else if (!strcasecmp(v->name, "facilityenable")) {
18256             confp->pri.pri.facilityenable = ast_true(v->value);
18257 #if defined(HAVE_PRI_AOC_EVENTS)
18258          } else if (!strcasecmp(v->name, "aoc_enable")) {
18259             confp->pri.pri.aoc_passthrough_flag = 0;
18260             if (strchr(v->value, 's') || strchr(v->value, 'S')) {
18261                confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_S;
18262             }
18263             if (strchr(v->value, 'd') || strchr(v->value, 'D')) {
18264                confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_D;
18265             }
18266             if (strchr(v->value, 'e') || strchr(v->value, 'E')) {
18267                confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_E;
18268             }
18269          } else if (!strcasecmp(v->name, "aoce_delayhangup")) {
18270             confp->pri.pri.aoce_delayhangup = ast_true(v->value);
18271 #endif   /* defined(HAVE_PRI_AOC_EVENTS) */
18272 #if defined(HAVE_PRI_CALL_HOLD)
18273          } else if (!strcasecmp(v->name, "hold_disconnect_transfer")) {
18274             confp->pri.pri.hold_disconnect_transfer = ast_true(v->value);
18275 #endif   /* defined(HAVE_PRI_CALL_HOLD) */
18276          } else if (!strcasecmp(v->name, "moh_signaling")
18277             || !strcasecmp(v->name, "moh_signalling")) {
18278             if (!strcasecmp(v->value, "moh")) {
18279                confp->pri.pri.moh_signaling = SIG_PRI_MOH_SIGNALING_MOH;
18280             } else if (!strcasecmp(v->value, "notify")) {
18281                confp->pri.pri.moh_signaling = SIG_PRI_MOH_SIGNALING_NOTIFY;
18282 #if defined(HAVE_PRI_CALL_HOLD)
18283             } else if (!strcasecmp(v->value, "hold")) {
18284                confp->pri.pri.moh_signaling = SIG_PRI_MOH_SIGNALING_HOLD;
18285 #endif   /* defined(HAVE_PRI_CALL_HOLD) */
18286             } else {
18287                confp->pri.pri.moh_signaling = SIG_PRI_MOH_SIGNALING_MOH;
18288             }
18289 #if defined(HAVE_PRI_CCSS)
18290          } else if (!strcasecmp(v->name, "cc_ptmp_recall_mode")) {
18291             if (!strcasecmp(v->value, "global")) {
18292                confp->pri.pri.cc_ptmp_recall_mode = 0;/* globalRecall */
18293             } else if (!strcasecmp(v->value, "specific")) {
18294                confp->pri.pri.cc_ptmp_recall_mode = 1;/* specificRecall */
18295             } else {
18296                confp->pri.pri.cc_ptmp_recall_mode = 1;/* specificRecall */
18297             }
18298          } else if (!strcasecmp(v->name, "cc_qsig_signaling_link_req")) {
18299             if (!strcasecmp(v->value, "release")) {
18300                confp->pri.pri.cc_qsig_signaling_link_req = 0;/* release */
18301             } else if (!strcasecmp(v->value, "retain")) {
18302                confp->pri.pri.cc_qsig_signaling_link_req = 1;/* retain */
18303             } else if (!strcasecmp(v->value, "do_not_care")) {
18304                confp->pri.pri.cc_qsig_signaling_link_req = 2;/* do-not-care */
18305             } else {
18306                confp->pri.pri.cc_qsig_signaling_link_req = 1;/* retain */
18307             }
18308          } else if (!strcasecmp(v->name, "cc_qsig_signaling_link_rsp")) {
18309             if (!strcasecmp(v->value, "release")) {
18310                confp->pri.pri.cc_qsig_signaling_link_rsp = 0;/* release */
18311             } else if (!strcasecmp(v->value, "retain")) {
18312                confp->pri.pri.cc_qsig_signaling_link_rsp = 1;/* retain */
18313             } else {
18314                confp->pri.pri.cc_qsig_signaling_link_rsp = 1;/* retain */
18315             }
18316 #endif   /* defined(HAVE_PRI_CCSS) */
18317 #if defined(HAVE_PRI_CALL_WAITING)
18318          } else if (!strcasecmp(v->name, "max_call_waiting_calls")) {
18319             confp->pri.pri.max_call_waiting_calls = atoi(v->value);
18320             if (confp->pri.pri.max_call_waiting_calls < 0) {
18321                /* Negative values are not allowed. */
18322                confp->pri.pri.max_call_waiting_calls = 0;
18323             }
18324          } else if (!strcasecmp(v->name, "allow_call_waiting_calls")) {
18325             confp->pri.pri.allow_call_waiting_calls = ast_true(v->value);
18326 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
18327 #if defined(HAVE_PRI_MWI)
18328          } else if (!strcasecmp(v->name, "mwi_mailboxes")) {
18329             ast_copy_string(confp->pri.pri.mwi_mailboxes, v->value,
18330                sizeof(confp->pri.pri.mwi_mailboxes));
18331          } else if (!strcasecmp(v->name, "mwi_vm_numbers")) {
18332             ast_copy_string(confp->pri.pri.mwi_vm_numbers, v->value,
18333                sizeof(confp->pri.pri.mwi_vm_numbers));
18334 #endif   /* defined(HAVE_PRI_MWI) */
18335          } else if (!strcasecmp(v->name, "append_msn_to_cid_tag")) {
18336             confp->pri.pri.append_msn_to_user_tag = ast_true(v->value);
18337          } else if (!strcasecmp(v->name, "inband_on_proceeding")) {
18338             confp->pri.pri.inband_on_proceeding = ast_true(v->value);
18339 #if defined(HAVE_PRI_DISPLAY_TEXT)
18340          } else if (!strcasecmp(v->name, "display_send")) {
18341             confp->pri.pri.display_flags_send = dahdi_display_text_option(v->value);
18342          } else if (!strcasecmp(v->name, "display_receive")) {
18343             confp->pri.pri.display_flags_receive = dahdi_display_text_option(v->value);
18344 #endif   /* defined(HAVE_PRI_DISPLAY_TEXT) */
18345 #if defined(HAVE_PRI_MCID)
18346          } else if (!strcasecmp(v->name, "mcid_send")) {
18347             confp->pri.pri.mcid_send = ast_true(v->value);
18348 #endif   /* defined(HAVE_PRI_MCID) */
18349 #if defined(HAVE_PRI_DATETIME_SEND)
18350          } else if (!strcasecmp(v->name, "datetime_send")) {
18351             confp->pri.pri.datetime_send = dahdi_datetime_send_option(v->value);
18352 #endif   /* defined(HAVE_PRI_DATETIME_SEND) */
18353          } else if (!strcasecmp(v->name, "layer1_presence")) {
18354             if (!strcasecmp(v->value, "required")) {
18355                confp->pri.pri.layer1_ignored = 0;
18356             } else if (!strcasecmp(v->value, "ignore")) {
18357                confp->pri.pri.layer1_ignored = 1;
18358             } else {
18359                /* Default */
18360                confp->pri.pri.layer1_ignored = 0;
18361             }
18362 #if defined(HAVE_PRI_L2_PERSISTENCE)
18363          } else if (!strcasecmp(v->name, "layer2_persistence")) {
18364             if (!strcasecmp(v->value, "keep_up")) {
18365                confp->pri.pri.l2_persistence = PRI_L2_PERSISTENCE_KEEP_UP;
18366             } else if (!strcasecmp(v->value, "leave_down")) {
18367                confp->pri.pri.l2_persistence = PRI_L2_PERSISTENCE_LEAVE_DOWN;
18368             } else {
18369                confp->pri.pri.l2_persistence = PRI_L2_PERSISTENCE_DEFAULT;
18370             }
18371 #endif   /* defined(HAVE_PRI_L2_PERSISTENCE) */
18372          } else if (!strcasecmp(v->name, "colp_send")) {
18373             if (!strcasecmp(v->value, "block")) {
18374                confp->pri.pri.colp_send = SIG_PRI_COLP_BLOCK;
18375             } else if (!strcasecmp(v->value, "connect")) {
18376                confp->pri.pri.colp_send = SIG_PRI_COLP_CONNECT;
18377             } else if (!strcasecmp(v->value, "update")) {
18378                confp->pri.pri.colp_send = SIG_PRI_COLP_UPDATE;
18379             } else {
18380                confp->pri.pri.colp_send = SIG_PRI_COLP_UPDATE;
18381             }
18382 #endif /* HAVE_PRI */
18383 #if defined(HAVE_SS7)
18384          } else if (!strcasecmp(v->name, "ss7type")) {
18385             if (!strcasecmp(v->value, "itu")) {
18386                cur_ss7type = SS7_ITU;
18387             } else if (!strcasecmp(v->value, "ansi")) {
18388                cur_ss7type = SS7_ANSI;
18389             } else
18390                ast_log(LOG_WARNING, "'%s' is an unknown ss7 switch type at line %d.!\n", v->value, v->lineno);
18391          } else if (!strcasecmp(v->name, "linkset")) {
18392             cur_linkset = atoi(v->value);
18393          } else if (!strcasecmp(v->name, "pointcode")) {
18394             cur_pointcode = parse_pointcode(v->value);
18395          } else if (!strcasecmp(v->name, "adjpointcode")) {
18396             cur_adjpointcode = parse_pointcode(v->value);
18397          } else if (!strcasecmp(v->name, "defaultdpc")) {
18398             cur_defaultdpc = parse_pointcode(v->value);
18399          } else if (!strcasecmp(v->name, "cicbeginswith")) {
18400             cur_cicbeginswith = atoi(v->value);
18401          } else if (!strcasecmp(v->name, "networkindicator")) {
18402             if (!strcasecmp(v->value, "national"))
18403                cur_networkindicator = SS7_NI_NAT;
18404             else if (!strcasecmp(v->value, "national_spare"))
18405                cur_networkindicator = SS7_NI_NAT_SPARE;
18406             else if (!strcasecmp(v->value, "international"))
18407                cur_networkindicator = SS7_NI_INT;
18408             else if (!strcasecmp(v->value, "international_spare"))
18409                cur_networkindicator = SS7_NI_INT_SPARE;
18410             else
18411                cur_networkindicator = -1;
18412          } else if (!strcasecmp(v->name, "ss7_internationalprefix")) {
18413             ast_copy_string(confp->ss7.ss7.internationalprefix, v->value, sizeof(confp->ss7.ss7.internationalprefix));
18414          } else if (!strcasecmp(v->name, "ss7_nationalprefix")) {
18415             ast_copy_string(confp->ss7.ss7.nationalprefix, v->value, sizeof(confp->ss7.ss7.nationalprefix));
18416          } else if (!strcasecmp(v->name, "ss7_subscriberprefix")) {
18417             ast_copy_string(confp->ss7.ss7.subscriberprefix, v->value, sizeof(confp->ss7.ss7.subscriberprefix));
18418          } else if (!strcasecmp(v->name, "ss7_unknownprefix")) {
18419             ast_copy_string(confp->ss7.ss7.unknownprefix, v->value, sizeof(confp->ss7.ss7.unknownprefix));
18420          } else if (!strcasecmp(v->name, "ss7_called_nai")) {
18421             if (!strcasecmp(v->value, "national")) {
18422                confp->ss7.ss7.called_nai = SS7_NAI_NATIONAL;
18423             } else if (!strcasecmp(v->value, "international")) {
18424                confp->ss7.ss7.called_nai = SS7_NAI_INTERNATIONAL;
18425             } else if (!strcasecmp(v->value, "subscriber")) {
18426                confp->ss7.ss7.called_nai = SS7_NAI_SUBSCRIBER;
18427             } else if (!strcasecmp(v->value, "unknown")) {
18428                confp->ss7.ss7.called_nai = SS7_NAI_UNKNOWN;
18429             } else if (!strcasecmp(v->value, "dynamic")) {
18430                confp->ss7.ss7.called_nai = SS7_NAI_DYNAMIC;
18431             } else {
18432                ast_log(LOG_WARNING, "Unknown SS7 called_nai '%s' at line %d.\n", v->value, v->lineno);
18433             }
18434          } else if (!strcasecmp(v->name, "ss7_calling_nai")) {
18435             if (!strcasecmp(v->value, "national")) {
18436                confp->ss7.ss7.calling_nai = SS7_NAI_NATIONAL;
18437             } else if (!strcasecmp(v->value, "international")) {
18438                confp->ss7.ss7.calling_nai = SS7_NAI_INTERNATIONAL;
18439             } else if (!strcasecmp(v->value, "subscriber")) {
18440                confp->ss7.ss7.calling_nai = SS7_NAI_SUBSCRIBER;
18441             } else if (!strcasecmp(v->value, "unknown")) {
18442                confp->ss7.ss7.calling_nai = SS7_NAI_UNKNOWN;
18443             } else if (!strcasecmp(v->value, "dynamic")) {
18444                confp->ss7.ss7.calling_nai = SS7_NAI_DYNAMIC;
18445             } else {
18446                ast_log(LOG_WARNING, "Unknown SS7 calling_nai '%s' at line %d.\n", v->value, v->lineno);
18447             }
18448          } else if (!strcasecmp(v->name, "sigchan")) {
18449             int sigchan, res;
18450             sigchan = atoi(v->value);
18451             res = linkset_addsigchan(sigchan);
18452             if (res < 0)
18453                return -1;
18454 
18455          } else if (!strcasecmp(v->name, "ss7_explicitacm")) {
18456             struct dahdi_ss7 *link;
18457             link = ss7_resolve_linkset(cur_linkset);
18458             if (!link) {
18459                ast_log(LOG_ERROR, "Invalid linkset number.  Must be between 1 and %d\n", NUM_SPANS + 1);
18460                return -1;
18461             }
18462             if (ast_true(v->value))
18463                link->ss7.flags |= LINKSET_FLAG_EXPLICITACM;
18464 #endif   /* defined(HAVE_SS7) */
18465 #ifdef HAVE_OPENR2
18466          } else if (!strcasecmp(v->name, "mfcr2_advanced_protocol_file")) {
18467             ast_copy_string(confp->mfcr2.r2proto_file, v->value, sizeof(confp->mfcr2.r2proto_file));
18468             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);
18469          } else if (!strcasecmp(v->name, "mfcr2_logdir")) {
18470             ast_copy_string(confp->mfcr2.logdir, v->value, sizeof(confp->mfcr2.logdir));
18471          } else if (!strcasecmp(v->name, "mfcr2_variant")) {
18472             confp->mfcr2.variant = openr2_proto_get_variant(v->value);
18473             if (OR2_VAR_UNKNOWN == confp->mfcr2.variant) {
18474                ast_log(LOG_WARNING, "Unknown MFC/R2 variant '%s' at line %d, defaulting to ITU.\n", v->value, v->lineno);
18475                confp->mfcr2.variant = OR2_VAR_ITU;
18476             }
18477          } else if (!strcasecmp(v->name, "mfcr2_mfback_timeout")) {
18478             confp->mfcr2.mfback_timeout = atoi(v->value);
18479             if (!confp->mfcr2.mfback_timeout) {
18480                ast_log(LOG_WARNING, "MF timeout of 0? hum, I will protect you from your ignorance. Setting default.\n");
18481                confp->mfcr2.mfback_timeout = -1;
18482             } else if (confp->mfcr2.mfback_timeout > 0 && confp->mfcr2.mfback_timeout < 500) {
18483                ast_log(LOG_WARNING, "MF timeout less than 500ms is not recommended, you have been warned!\n");
18484             }
18485          } else if (!strcasecmp(v->name, "mfcr2_metering_pulse_timeout")) {
18486             confp->mfcr2.metering_pulse_timeout = atoi(v->value);
18487             if (confp->mfcr2.metering_pulse_timeout > 500) {
18488                ast_log(LOG_WARNING, "Metering pulse timeout greater than 500ms is not recommended, you have been warned!\n");
18489             }
18490 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2
18491          } else if (!strcasecmp(v->name, "mfcr2_dtmf_detection")) {
18492             confp->mfcr2.dtmf_detection = ast_true(v->value) ? 1 : 0;
18493          } else if (!strcasecmp(v->name, "mfcr2_dtmf_dialing")) {
18494             confp->mfcr2.dtmf_dialing = ast_true(v->value) ? 1 : 0;
18495          } else if (!strcasecmp(v->name, "mfcr2_dtmf_time_on")) {
18496             confp->mfcr2.dtmf_time_on = atoi(v->value);
18497          } else if (!strcasecmp(v->name, "mfcr2_dtmf_time_off")) {
18498             confp->mfcr2.dtmf_time_off = atoi(v->value);
18499 #endif
18500 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 3
18501          } else if (!strcasecmp(v->name, "mfcr2_dtmf_end_timeout")) {
18502             confp->mfcr2.dtmf_end_timeout = atoi(v->value);
18503 #endif
18504          } else if (!strcasecmp(v->name, "mfcr2_get_ani_first")) {
18505             confp->mfcr2.get_ani_first = ast_true(v->value) ? 1 : 0;
18506          } else if (!strcasecmp(v->name, "mfcr2_double_answer")) {
18507             confp->mfcr2.double_answer = ast_true(v->value) ? 1 : 0;
18508          } else if (!strcasecmp(v->name, "mfcr2_charge_calls")) {
18509             confp->mfcr2.charge_calls = ast_true(v->value) ? 1 : 0;
18510          } else if (!strcasecmp(v->name, "mfcr2_accept_on_offer")) {
18511             confp->mfcr2.accept_on_offer = ast_true(v->value) ? 1 : 0;
18512          } else if (!strcasecmp(v->name, "mfcr2_allow_collect_calls")) {
18513             confp->mfcr2.allow_collect_calls = ast_true(v->value) ? 1 : 0;
18514          } else if (!strcasecmp(v->name, "mfcr2_forced_release")) {
18515             confp->mfcr2.forced_release = ast_true(v->value) ? 1 : 0;
18516          } else if (!strcasecmp(v->name, "mfcr2_immediate_accept")) {
18517             confp->mfcr2.immediate_accept = ast_true(v->value) ? 1 : 0;
18518 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
18519          } else if (!strcasecmp(v->name, "mfcr2_skip_category")) {
18520             confp->mfcr2.skip_category_request = ast_true(v->value) ? 1 : 0;
18521 #endif
18522          } else if (!strcasecmp(v->name, "mfcr2_call_files")) {
18523             confp->mfcr2.call_files = ast_true(v->value) ? 1 : 0;
18524          } else if (!strcasecmp(v->name, "mfcr2_max_ani")) {
18525             confp->mfcr2.max_ani = atoi(v->value);
18526             if (confp->mfcr2.max_ani >= AST_MAX_EXTENSION){
18527                confp->mfcr2.max_ani = AST_MAX_EXTENSION - 1;
18528             }
18529          } else if (!strcasecmp(v->name, "mfcr2_max_dnis")) {
18530             confp->mfcr2.max_dnis = atoi(v->value);
18531             if (confp->mfcr2.max_dnis >= AST_MAX_EXTENSION){
18532                confp->mfcr2.max_dnis = AST_MAX_EXTENSION - 1;
18533             }
18534          } else if (!strcasecmp(v->name, "mfcr2_category")) {
18535             confp->mfcr2.category = openr2_proto_get_category(v->value);
18536             if (OR2_CALLING_PARTY_CATEGORY_UNKNOWN == confp->mfcr2.category) {
18537                confp->mfcr2.category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER;
18538                ast_log(LOG_WARNING, "Invalid MFC/R2 caller category '%s' at line %d. Using national subscriber as default.\n",
18539                      v->value, v->lineno);
18540             }
18541          } else if (!strcasecmp(v->name, "mfcr2_logging")) {
18542             openr2_log_level_t tmplevel;
18543             char *clevel;
18544             char *logval = ast_strdupa(v->value);
18545             while (logval) {
18546                clevel = strsep(&logval,",");
18547                if (-1 == (tmplevel = openr2_log_get_level(clevel))) {
18548                   ast_log(LOG_WARNING, "Ignoring invalid logging level: '%s' at line %d.\n", clevel, v->lineno);
18549                   continue;
18550                }
18551                confp->mfcr2.loglevel |= tmplevel;
18552             }
18553 #endif /* HAVE_OPENR2 */
18554          } else if (!strcasecmp(v->name, "cadence")) {
18555             /* setup to scan our argument */
18556             int element_count, c[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
18557             int i;
18558             struct dahdi_ring_cadence new_cadence;
18559             int cid_location = -1;
18560             int firstcadencepos = 0;
18561             char original_args[80];
18562             int cadence_is_ok = 1;
18563 
18564             ast_copy_string(original_args, v->value, sizeof(original_args));
18565             /* 16 cadences allowed (8 pairs) */
18566             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]);
18567 
18568             /* Cadence must be even (on/off) */
18569             if (element_count % 2 == 1) {
18570                ast_log(LOG_ERROR, "Must be a silence duration for each ring duration: %s at line %d.\n", original_args, v->lineno);
18571                cadence_is_ok = 0;
18572             }
18573 
18574             /* Ring cadences cannot be negative */
18575             for (i = 0; i < element_count; i++) {
18576                if (c[i] == 0) {
18577                   ast_log(LOG_ERROR, "Ring or silence duration cannot be zero: %s at line %d.\n", original_args, v->lineno);
18578                   cadence_is_ok = 0;
18579                   break;
18580                } else if (c[i] < 0) {
18581                   if (i % 2 == 1) {
18582                      /* Silence duration, negative possibly okay */
18583                      if (cid_location == -1) {
18584                         cid_location = i;
18585                         c[i] *= -1;
18586                      } else {
18587                         ast_log(LOG_ERROR, "CID location specified twice: %s at line %d.\n", original_args, v->lineno);
18588                         cadence_is_ok = 0;
18589                         break;
18590                      }
18591                   } else {
18592                      if (firstcadencepos == 0) {
18593                         firstcadencepos = i; /* only recorded to avoid duplicate specification */
18594                                  /* duration will be passed negative to the DAHDI driver */
18595                      } else {
18596                          ast_log(LOG_ERROR, "First cadence position specified twice: %s at line %d.\n", original_args, v->lineno);
18597                         cadence_is_ok = 0;
18598                         break;
18599                      }
18600                   }
18601                }
18602             }
18603 
18604             /* Substitute our scanned cadence */
18605             for (i = 0; i < 16; i++) {
18606                new_cadence.ringcadence[i] = c[i];
18607             }
18608 
18609             if (cadence_is_ok) {
18610                /* ---we scanned it without getting annoyed; now some sanity checks--- */
18611                if (element_count < 2) {
18612                   ast_log(LOG_ERROR, "Minimum cadence is ring,pause: %s at line %d.\n", original_args, v->lineno);
18613                } else {
18614                   if (cid_location == -1) {
18615                      /* user didn't say; default to first pause */
18616                      cid_location = 1;
18617                   } else {
18618                      /* convert element_index to cidrings value */
18619                      cid_location = (cid_location + 1) / 2;
18620                   }
18621                   /* ---we like their cadence; try to install it--- */
18622                   if (!user_has_defined_cadences++)
18623                      /* this is the first user-defined cadence; clear the default user cadences */
18624                      num_cadence = 0;
18625                   if ((num_cadence+1) >= NUM_CADENCE_MAX)
18626                      ast_log(LOG_ERROR, "Already %d cadences; can't add another: %s at line %d.\n", NUM_CADENCE_MAX, original_args, v->lineno);
18627                   else {
18628                      cadences[num_cadence] = new_cadence;
18629                      cidrings[num_cadence++] = cid_location;
18630                      ast_verb(3, "cadence 'r%d' added: %s\n",num_cadence,original_args);
18631                   }
18632                }
18633             }
18634          } else if (!strcasecmp(v->name, "ringtimeout")) {
18635             ringt_base = (atoi(v->value) * 8) / READ_SIZE;
18636          } else if (!strcasecmp(v->name, "prewink")) {
18637             confp->timing.prewinktime = atoi(v->value);
18638          } else if (!strcasecmp(v->name, "preflash")) {
18639             confp->timing.preflashtime = atoi(v->value);
18640          } else if (!strcasecmp(v->name, "wink")) {
18641             confp->timing.winktime = atoi(v->value);
18642          } else if (!strcasecmp(v->name, "flash")) {
18643             confp->timing.flashtime = atoi(v->value);
18644          } else if (!strcasecmp(v->name, "start")) {
18645             confp->timing.starttime = atoi(v->value);
18646          } else if (!strcasecmp(v->name, "rxwink")) {
18647             confp->timing.rxwinktime = atoi(v->value);
18648          } else if (!strcasecmp(v->name, "rxflash")) {
18649             confp->timing.rxflashtime = atoi(v->value);
18650          } else if (!strcasecmp(v->name, "debounce")) {
18651             confp->timing.debouncetime = atoi(v->value);
18652          } else if (!strcasecmp(v->name, "toneduration")) {
18653             int toneduration;
18654             int ctlfd;
18655             int res;
18656             struct dahdi_dialparams dps;
18657 
18658             ctlfd = open("/dev/dahdi/ctl", O_RDWR);
18659             if (ctlfd == -1) {
18660                ast_log(LOG_ERROR, "Unable to open /dev/dahdi/ctl to set toneduration at line %d.\n", v->lineno);
18661                return -1;
18662             }
18663 
18664             toneduration = atoi(v->value);
18665             if (toneduration > -1) {
18666                memset(&dps, 0, sizeof(dps));
18667 
18668                dps.dtmf_tonelen = dps.mfv1_tonelen = toneduration;
18669                res = ioctl(ctlfd, DAHDI_SET_DIALPARAMS, &dps);
18670                if (res < 0) {
18671                   ast_log(LOG_ERROR, "Invalid tone duration: %d ms at line %d: %s\n", toneduration, v->lineno, strerror(errno));
18672                   close(ctlfd);
18673                   return -1;
18674                }
18675             }
18676             close(ctlfd);
18677          } else if (!strcasecmp(v->name, "defaultcic")) {
18678             ast_copy_string(defaultcic, v->value, sizeof(defaultcic));
18679          } else if (!strcasecmp(v->name, "defaultozz")) {
18680             ast_copy_string(defaultozz, v->value, sizeof(defaultozz));
18681          } else if (!strcasecmp(v->name, "mwilevel")) {
18682             mwilevel = atoi(v->value);
18683          } else if (!strcasecmp(v->name, "dtmfcidlevel")) {
18684             dtmfcid_level = atoi(v->value);
18685          } else if (!strcasecmp(v->name, "reportalarms")) {
18686             if (!strcasecmp(v->value, "all"))
18687                report_alarms = REPORT_CHANNEL_ALARMS | REPORT_SPAN_ALARMS;
18688             if (!strcasecmp(v->value, "none"))
18689                report_alarms = 0;
18690             else if (!strcasecmp(v->value, "channels"))
18691                report_alarms = REPORT_CHANNEL_ALARMS;
18692             else if (!strcasecmp(v->value, "spans"))
18693                report_alarms = REPORT_SPAN_ALARMS;
18694           }
18695       } else if (!(options & PROC_DAHDI_OPT_NOWARN) )
18696          ast_log(LOG_WARNING, "Ignoring any changes to '%s' (on reload) at line %d.\n", v->name, v->lineno);
18697    }
18698 
18699    /* Since confp has already filled invidual dahdi_pvt objects with channels at this point, clear the variables in confp's pvt. */
18700    if (confp->chan.vars) {
18701       ast_variables_destroy(confp->chan.vars);
18702       confp->chan.vars = NULL;
18703    }
18704 
18705    if (dahdichan) {
18706       /* Process the deferred dahdichan value. */
18707       if (build_channels(confp, dahdichan->value, reload, dahdichan->lineno,
18708          &found_pseudo)) {
18709          if (confp->ignore_failed_channels) {
18710             ast_log(LOG_WARNING,
18711                "Dahdichan '%s' failure ignored: ignore_failed_channels.\n",
18712                dahdichan->value);
18713          } else {
18714             return -1;
18715          }
18716       }
18717    }
18718 
18719    /* mark the first channels of each DAHDI span to watch for their span alarms */
18720    for (tmp = iflist, y=-1; tmp; tmp = tmp->next) {
18721       if (!tmp->destroy && tmp->span != y) {
18722          tmp->manages_span_alarms = 1;
18723          y = tmp->span; 
18724       } else {
18725          tmp->manages_span_alarms = 0;
18726       }
18727    }
18728 
18729    /*< \todo why check for the pseudo in the per-channel section.
18730     * Any actual use for manual setup of the pseudo channel? */
18731    if (!found_pseudo && reload != 1 && !(options & PROC_DAHDI_OPT_NOCHAN)) {
18732       /* use the default configuration for a channel, so
18733          that any settings from real configured channels
18734          don't "leak" into the pseudo channel config
18735       */
18736       struct dahdi_chan_conf conf = dahdi_chan_conf_default();
18737 
18738       if (conf.chan.cc_params) {
18739          tmp = mkintf(CHAN_PSEUDO, &conf, reload);
18740       } else {
18741          tmp = NULL;
18742       }
18743       if (tmp) {
18744          ast_verb(3, "Automatically generated pseudo channel\n");
18745       } else {
18746          ast_log(LOG_WARNING, "Unable to register pseudo channel!\n");
18747       }
18748       ast_cc_config_params_destroy(conf.chan.cc_params);
18749    }
18750 
18751    /* Since named callgroup and named pickup group are ref'd to dahdi_pvt at this point, unref container in confp's pvt. */
18752    confp->chan.named_callgroups = ast_unref_namedgroups(confp->chan.named_callgroups);
18753    confp->chan.named_pickupgroups = ast_unref_namedgroups(confp->chan.named_pickupgroups);
18754 
18755    return 0;
18756 }
18757 
18758 /*!
18759  * \internal
18760  * \brief Deep copy struct dahdi_chan_conf.
18761  * \since 1.8
18762  *
18763  * \param dest Destination.
18764  * \param src Source.
18765  *
18766  * \return Nothing
18767  */
18768 static void deep_copy_dahdi_chan_conf(struct dahdi_chan_conf *dest, const struct dahdi_chan_conf *src)
18769 {
18770    struct ast_cc_config_params *cc_params;
18771 
18772    cc_params = dest->chan.cc_params;
18773    *dest = *src;
18774    dest->chan.cc_params = cc_params;
18775    ast_cc_copy_config_params(dest->chan.cc_params, src->chan.cc_params);
18776 }
18777 
18778 /*!
18779  * \internal
18780  * \brief Setup DAHDI channel driver.
18781  *
18782  * \param reload enum: load_module(0), reload(1), restart(2).
18783  * \param default_conf Default config parameters.  So cc_params can be properly destroyed.
18784  * \param base_conf Default config parameters per section.  So cc_params can be properly destroyed.
18785  * \param conf Local config parameters.  So cc_params can be properly destroyed.
18786  *
18787  * \retval 0 on success.
18788  * \retval -1 on error.
18789  */
18790 static int setup_dahdi_int(int reload, struct dahdi_chan_conf *default_conf, struct dahdi_chan_conf *base_conf, struct dahdi_chan_conf *conf)
18791 {
18792    struct ast_config *cfg;
18793    struct ast_config *ucfg;
18794    struct ast_variable *v;
18795    struct ast_flags config_flags = { reload == 1 ? CONFIG_FLAG_FILEUNCHANGED : 0 };
18796    const char *chans;
18797    const char *cat;
18798    int res;
18799 
18800 #ifdef HAVE_PRI
18801    char *c;
18802    int spanno;
18803    int i;
18804    int logicalspan;
18805    int trunkgroup;
18806    int dchannels[SIG_PRI_NUM_DCHANS];
18807 #endif
18808    int have_cfg_now;
18809    static int had_cfg_before = 1;/* So initial load will complain if we don't have cfg. */
18810 
18811    cfg = ast_config_load(config, config_flags);
18812    have_cfg_now = !!cfg;
18813    if (!cfg) {
18814       /* Error if we have no config file */
18815       if (had_cfg_before) {
18816          ast_log(LOG_ERROR, "Unable to load config %s\n", config);
18817          ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
18818       }
18819       cfg = ast_config_new();/* Dummy config */
18820       if (!cfg) {
18821          return 0;
18822       }
18823       ucfg = ast_config_load("users.conf", config_flags);
18824       if (ucfg == CONFIG_STATUS_FILEUNCHANGED) {
18825          ast_config_destroy(cfg);
18826          return 0;
18827       }
18828       if (ucfg == CONFIG_STATUS_FILEINVALID) {
18829          ast_log(LOG_ERROR, "File users.conf cannot be parsed.  Aborting.\n");
18830          ast_config_destroy(cfg);
18831          return 0;
18832       }
18833    } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
18834       ucfg = ast_config_load("users.conf", config_flags);
18835       if (ucfg == CONFIG_STATUS_FILEUNCHANGED) {
18836          return 0;
18837       }
18838       if (ucfg == CONFIG_STATUS_FILEINVALID) {
18839          ast_log(LOG_ERROR, "File users.conf cannot be parsed.  Aborting.\n");
18840          return 0;
18841       }
18842       ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
18843       cfg = ast_config_load(config, config_flags);
18844       have_cfg_now = !!cfg;
18845       if (!cfg) {
18846          if (had_cfg_before) {
18847             /* We should have been able to load the config. */
18848             ast_log(LOG_ERROR, "Bad. Unable to load config %s\n", config);
18849             ast_config_destroy(ucfg);
18850             return 0;
18851          }
18852          cfg = ast_config_new();/* Dummy config */
18853          if (!cfg) {
18854             ast_config_destroy(ucfg);
18855             return 0;
18856          }
18857       } else if (cfg == CONFIG_STATUS_FILEINVALID) {
18858          ast_log(LOG_ERROR, "File %s cannot be parsed.  Aborting.\n", config);
18859          ast_config_destroy(ucfg);
18860          return 0;
18861       }
18862    } else if (cfg == CONFIG_STATUS_FILEINVALID) {
18863       ast_log(LOG_ERROR, "File %s cannot be parsed.  Aborting.\n", config);
18864       return 0;
18865    } else {
18866       ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
18867       ucfg = ast_config_load("users.conf", config_flags);
18868       if (ucfg == CONFIG_STATUS_FILEINVALID) {
18869          ast_log(LOG_ERROR, "File users.conf cannot be parsed.  Aborting.\n");
18870          ast_config_destroy(cfg);
18871          return 0;
18872       }
18873    }
18874    had_cfg_before = have_cfg_now;
18875 
18876    /* It's a little silly to lock it, but we might as well just to be sure */
18877    ast_mutex_lock(&iflock);
18878 #ifdef HAVE_PRI
18879    if (reload != 1) {
18880       /* Process trunkgroups first */
18881       v = ast_variable_browse(cfg, "trunkgroups");
18882       while (v) {
18883          if (!strcasecmp(v->name, "trunkgroup")) {
18884             trunkgroup = atoi(v->value);
18885             if (trunkgroup > 0) {
18886                if ((c = strchr(v->value, ','))) {
18887                   i = 0;
18888                   memset(dchannels, 0, sizeof(dchannels));
18889                   while (c && (i < SIG_PRI_NUM_DCHANS)) {
18890                      dchannels[i] = atoi(c + 1);
18891                      if (dchannels[i] < 0) {
18892                         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);
18893                      } else
18894                         i++;
18895                      c = strchr(c + 1, ',');
18896                   }
18897                   if (i) {
18898                      if (pri_create_trunkgroup(trunkgroup, dchannels)) {
18899                         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);
18900                   } else
18901                         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");
18902                   } else
18903                      ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
18904                } else
18905                   ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
18906             } else
18907                ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of chan_dahdi.conf\n", v->lineno);
18908          } else if (!strcasecmp(v->name, "spanmap")) {
18909             spanno = atoi(v->value);
18910             if (spanno > 0) {
18911                if ((c = strchr(v->value, ','))) {
18912                   trunkgroup = atoi(c + 1);
18913                   if (trunkgroup > 0) {
18914                      if ((c = strchr(c + 1, ',')))
18915                         logicalspan = atoi(c + 1);
18916                      else
18917                         logicalspan = 0;
18918                      if (logicalspan >= 0) {
18919                         if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) {
18920                            ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
18921                      } else
18922                            ast_verb(2, "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
18923                      } else
18924                         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);
18925                   } else
18926                      ast_log(LOG_WARNING, "Trunk group must be a postive number at line %d of chan_dahdi.conf\n", v->lineno);
18927                } else
18928                   ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of chan_dahdi.conf\n", v->lineno);
18929             } else
18930                ast_log(LOG_WARNING, "Span number must be a postive integer at line %d of chan_dahdi.conf\n", v->lineno);
18931          } else {
18932             ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name);
18933          }
18934          v = v->next;
18935       }
18936    }
18937 #endif
18938 
18939    /* Copy the default jb config over global_jbconf */
18940    memcpy(&global_jbconf, &default_jbconf, sizeof(global_jbconf));
18941 
18942    mwimonitornotify[0] = '\0';
18943 
18944    v = ast_variable_browse(cfg, "channels");
18945    if ((res = process_dahdi(base_conf,
18946       "" /* Must be empty for the channels category.  Silly voicemail mailbox. */,
18947       v, reload, 0))) {
18948       ast_mutex_unlock(&iflock);
18949       ast_config_destroy(cfg);
18950       if (ucfg) {
18951          ast_config_destroy(ucfg);
18952       }
18953       return res;
18954    }
18955 
18956    /* Now get configuration from all normal sections in chan_dahdi.conf: */
18957    for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) {
18958       /* [channels] and [trunkgroups] are used. Let's also reserve
18959        * [globals] and [general] for future use
18960        */
18961       if (!strcasecmp(cat, "general") ||
18962          !strcasecmp(cat, "trunkgroups") ||
18963          !strcasecmp(cat, "globals") ||
18964          !strcasecmp(cat, "channels")) {
18965          continue;
18966       }
18967 
18968       chans = ast_variable_retrieve(cfg, cat, "dahdichan");
18969       if (ast_strlen_zero(chans)) {
18970          /* Section is useless without a dahdichan value present. */
18971          continue;
18972       }
18973 
18974       /* Copy base_conf to conf. */
18975       deep_copy_dahdi_chan_conf(conf, base_conf);
18976 
18977       if ((res = process_dahdi(conf, cat, ast_variable_browse(cfg, cat), reload, PROC_DAHDI_OPT_NOCHAN))) {
18978          ast_mutex_unlock(&iflock);
18979          ast_config_destroy(cfg);
18980          if (ucfg) {
18981             ast_config_destroy(ucfg);
18982          }
18983          return res;
18984       }
18985    }
18986 
18987    ast_config_destroy(cfg);
18988 
18989    if (ucfg) {
18990       /* Reset base_conf, so things don't leak from chan_dahdi.conf */
18991       deep_copy_dahdi_chan_conf(base_conf, default_conf);
18992       process_dahdi(base_conf,
18993          "" /* Must be empty for the general category.  Silly voicemail mailbox. */,
18994          ast_variable_browse(ucfg, "general"), 1, 0);
18995 
18996       for (cat = ast_category_browse(ucfg, NULL); cat ; cat = ast_category_browse(ucfg, cat)) {
18997          if (!strcasecmp(cat, "general")) {
18998             continue;
18999          }
19000 
19001          chans = ast_variable_retrieve(ucfg, cat, "dahdichan");
19002          if (ast_strlen_zero(chans)) {
19003             /* Section is useless without a dahdichan value present. */
19004             continue;
19005          }
19006 
19007          /* Copy base_conf to conf. */
19008          deep_copy_dahdi_chan_conf(conf, base_conf);
19009 
19010          if ((res = process_dahdi(conf, cat, ast_variable_browse(ucfg, cat), reload, PROC_DAHDI_OPT_NOCHAN | PROC_DAHDI_OPT_NOWARN))) {
19011             ast_config_destroy(ucfg);
19012             ast_mutex_unlock(&iflock);
19013             return res;
19014          }
19015       }
19016       ast_config_destroy(ucfg);
19017    }
19018    ast_mutex_unlock(&iflock);
19019 
19020 #ifdef HAVE_PRI
19021    if (reload != 1) {
19022       int x;
19023       for (x = 0; x < NUM_SPANS; x++) {
19024          if (pris[x].pri.pvts[0]) {
19025             prepare_pri(pris + x);
19026             if (sig_pri_start_pri(&pris[x].pri)) {
19027                ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1);
19028                return -1;
19029             } else
19030                ast_verb(2, "Starting D-Channel on span %d\n", x + 1);
19031          }
19032       }
19033    }
19034 #endif
19035 #if defined(HAVE_SS7)
19036    if (reload != 1) {
19037       int x;
19038       for (x = 0; x < NUM_SPANS; x++) {
19039          if (linksets[x].ss7.ss7) {
19040             if (ast_pthread_create(&linksets[x].ss7.master, NULL, ss7_linkset, &linksets[x].ss7)) {
19041                ast_log(LOG_ERROR, "Unable to start SS7 linkset on span %d\n", x + 1);
19042                return -1;
19043             } else
19044                ast_verb(2, "Starting SS7 linkset on span %d\n", x + 1);
19045          }
19046       }
19047    }
19048 #endif   /* defined(HAVE_SS7) */
19049 #ifdef HAVE_OPENR2
19050    if (reload != 1) {
19051       int x;
19052       for (x = 0; x < r2links_count; x++) {
19053          if (ast_pthread_create(&r2links[x]->r2master, NULL, mfcr2_monitor, r2links[x])) {
19054             ast_log(LOG_ERROR, "Unable to start R2 monitor on channel group %d\n", x + 1);
19055             return -1;
19056          } else {
19057             ast_verb(2, "Starting R2 monitor on channel group %d\n", x + 1);
19058          }
19059       }
19060    }
19061 #endif
19062    /* And start the monitor for the first time */
19063    restart_monitor();
19064    return 0;
19065 }
19066 
19067 /*!
19068  * \internal
19069  * \brief Setup DAHDI channel driver.
19070  *
19071  * \param reload enum: load_module(0), reload(1), restart(2).
19072  *
19073  * \retval 0 on success.
19074  * \retval -1 on error.
19075  */
19076 static int setup_dahdi(int reload)
19077 {
19078    int res;
19079    struct dahdi_chan_conf default_conf = dahdi_chan_conf_default();
19080    struct dahdi_chan_conf base_conf = dahdi_chan_conf_default();
19081    struct dahdi_chan_conf conf = dahdi_chan_conf_default();
19082 
19083    if (default_conf.chan.cc_params && base_conf.chan.cc_params && conf.chan.cc_params) {
19084       res = setup_dahdi_int(reload, &default_conf, &base_conf, &conf);
19085    } else {
19086       res = -1;
19087    }
19088    ast_cc_config_params_destroy(default_conf.chan.cc_params);
19089    ast_cc_config_params_destroy(base_conf.chan.cc_params);
19090    ast_cc_config_params_destroy(conf.chan.cc_params);
19091 
19092    return res;
19093 }
19094 
19095 /*!
19096  * \internal
19097  * \brief Callback used to generate the dahdi status tree.
19098  * \param[in] search The search pattern tree.
19099  * \retval NULL on error.
19100  * \retval non-NULL The generated tree.
19101  */
19102 static int dahdi_status_data_provider_get(const struct ast_data_search *search,
19103       struct ast_data *data_root)
19104 {
19105    int ctl, res, span;
19106    struct ast_data *data_span, *data_alarms;
19107    struct dahdi_spaninfo s;
19108 
19109    ctl = open("/dev/dahdi/ctl", O_RDWR);
19110    if (ctl < 0) {
19111       ast_log(LOG_ERROR, "No DAHDI found. Unable to open /dev/dahdi/ctl: %s\n", strerror(errno));
19112       return -1;
19113    }
19114    for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
19115       s.spanno = span;
19116       res = ioctl(ctl, DAHDI_SPANSTAT, &s);
19117       if (res) {
19118          continue;
19119       }
19120 
19121       data_span = ast_data_add_node(data_root, "span");
19122       if (!data_span) {
19123          continue;
19124       }
19125       ast_data_add_str(data_span, "description", s.desc);
19126 
19127       /* insert the alarms status */
19128       data_alarms = ast_data_add_node(data_span, "alarms");
19129       if (!data_alarms) {
19130          continue;
19131       }
19132 
19133       ast_data_add_bool(data_alarms, "BLUE", s.alarms & DAHDI_ALARM_BLUE);
19134       ast_data_add_bool(data_alarms, "YELLOW", s.alarms & DAHDI_ALARM_YELLOW);
19135       ast_data_add_bool(data_alarms, "RED", s.alarms & DAHDI_ALARM_RED);
19136       ast_data_add_bool(data_alarms, "LOOPBACK", s.alarms & DAHDI_ALARM_LOOPBACK);
19137       ast_data_add_bool(data_alarms, "RECOVER", s.alarms & DAHDI_ALARM_RECOVER);
19138       ast_data_add_bool(data_alarms, "NOTOPEN", s.alarms & DAHDI_ALARM_NOTOPEN);
19139 
19140       ast_data_add_int(data_span, "irqmisses", s.irqmisses);
19141       ast_data_add_int(data_span, "bpviol", s.bpvcount);
19142       ast_data_add_int(data_span, "crc4", s.crc4count);
19143       ast_data_add_str(data_span, "framing", s.lineconfig & DAHDI_CONFIG_D4 ? "D4" :
19144                      s.lineconfig & DAHDI_CONFIG_ESF ? "ESF" :
19145                      s.lineconfig & DAHDI_CONFIG_CCS ? "CCS" :
19146                      "CAS");
19147       ast_data_add_str(data_span, "coding",  s.lineconfig & DAHDI_CONFIG_B8ZS ? "B8ZS" :
19148                      s.lineconfig & DAHDI_CONFIG_HDB3 ? "HDB3" :
19149                      s.lineconfig & DAHDI_CONFIG_AMI ? "AMI" :
19150                      "Unknown");
19151       ast_data_add_str(data_span, "options", s.lineconfig & DAHDI_CONFIG_CRC4 ?
19152                      s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" :
19153                      s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "YEL" : "");
19154       ast_data_add_str(data_span, "lbo", lbostr[s.lbo]);
19155 
19156       /* if this span doesn't match remove it. */
19157       if (!ast_data_search_match(search, data_span)) {
19158          ast_data_remove_node(data_root, data_span);
19159       }
19160    }
19161    close(ctl);
19162 
19163    return 0;
19164 }
19165 
19166 /*!
19167  * \internal
19168  * \brief Callback used to generate the dahdi channels tree.
19169  * \param[in] search The search pattern tree.
19170  * \retval NULL on error.
19171  * \retval non-NULL The generated tree.
19172  */
19173 static int dahdi_channels_data_provider_get(const struct ast_data_search *search,
19174       struct ast_data *data_root)
19175 {
19176    struct dahdi_pvt *tmp;
19177    struct ast_data *data_channel;
19178 
19179    ast_mutex_lock(&iflock);
19180    for (tmp = iflist; tmp; tmp = tmp->next) {
19181       data_channel = ast_data_add_node(data_root, "channel");
19182       if (!data_channel) {
19183          continue;
19184       }
19185 
19186       ast_data_add_structure(dahdi_pvt, data_channel, tmp);
19187 
19188       /* if this channel doesn't match remove it. */
19189       if (!ast_data_search_match(search, data_channel)) {
19190          ast_data_remove_node(data_root, data_channel);
19191       }
19192    }
19193    ast_mutex_unlock(&iflock);
19194 
19195    return 0;
19196 }
19197 
19198 /*!
19199  * \internal
19200  * \brief Callback used to generate the dahdi channels tree.
19201  * \param[in] search The search pattern tree.
19202  * \retval NULL on error.
19203  * \retval non-NULL The generated tree.
19204  */
19205 static int dahdi_version_data_provider_get(const struct ast_data_search *search,
19206       struct ast_data *data_root)
19207 {
19208    int pseudo_fd = -1;
19209    struct dahdi_versioninfo vi = {
19210       .version = "Unknown",
19211       .echo_canceller = "Unknown"
19212    };
19213 
19214    if ((pseudo_fd = open("/dev/dahdi/ctl", O_RDONLY)) < 0) {
19215       ast_log(LOG_ERROR, "Failed to open control file to get version.\n");
19216       return -1;
19217    }
19218 
19219    if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi)) {
19220       ast_log(LOG_ERROR, "Failed to get DAHDI version: %s\n", strerror(errno));
19221    }
19222 
19223    close(pseudo_fd);
19224 
19225    ast_data_add_str(data_root, "value", vi.version);
19226    ast_data_add_str(data_root, "echocanceller", vi.echo_canceller);
19227 
19228    return 0;
19229 }
19230 
19231 static const struct ast_data_handler dahdi_status_data_provider = {
19232    .version = AST_DATA_HANDLER_VERSION,
19233    .get = dahdi_status_data_provider_get
19234 };
19235 
19236 static const struct ast_data_handler dahdi_channels_data_provider = {
19237    .version = AST_DATA_HANDLER_VERSION,
19238    .get = dahdi_channels_data_provider_get
19239 };
19240 
19241 static const struct ast_data_handler dahdi_version_data_provider = {
19242    .version = AST_DATA_HANDLER_VERSION,
19243    .get = dahdi_version_data_provider_get
19244 };
19245 
19246 static const struct ast_data_entry dahdi_data_providers[] = {
19247    AST_DATA_ENTRY("asterisk/channel/dahdi/status", &dahdi_status_data_provider),
19248    AST_DATA_ENTRY("asterisk/channel/dahdi/channels", &dahdi_channels_data_provider),
19249    AST_DATA_ENTRY("asterisk/channel/dahdi/version", &dahdi_version_data_provider)
19250 };
19251 
19252 static int load_module(void)
19253 {
19254    int res;
19255    struct ast_format tmpfmt;
19256 #if defined(HAVE_PRI) || defined(HAVE_SS7)
19257    int y;
19258 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
19259 
19260    if (!(dahdi_tech.capabilities = ast_format_cap_alloc())) {
19261       return AST_MODULE_LOAD_FAILURE;
19262    }
19263    ast_format_cap_add(dahdi_tech.capabilities, ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR, 0));
19264    ast_format_cap_add(dahdi_tech.capabilities, ast_format_set(&tmpfmt, AST_FORMAT_ULAW, 0));
19265    ast_format_cap_add(dahdi_tech.capabilities, ast_format_set(&tmpfmt, AST_FORMAT_ALAW, 0));
19266 
19267 #ifdef HAVE_PRI
19268    memset(pris, 0, sizeof(pris));
19269    for (y = 0; y < NUM_SPANS; y++) {
19270       sig_pri_init_pri(&pris[y].pri);
19271    }
19272    pri_set_error(dahdi_pri_error);
19273    pri_set_message(dahdi_pri_message);
19274    ast_register_application_xml(dahdi_send_keypad_facility_app, dahdi_send_keypad_facility_exec);
19275 #ifdef HAVE_PRI_PROG_W_CAUSE
19276    ast_register_application_xml(dahdi_send_callrerouting_facility_app, dahdi_send_callrerouting_facility_exec);
19277 #endif
19278 #if defined(HAVE_PRI_CCSS)
19279    if (ast_cc_agent_register(&dahdi_pri_cc_agent_callbacks)
19280       || ast_cc_monitor_register(&dahdi_pri_cc_monitor_callbacks)) {
19281       __unload_module();
19282       return AST_MODULE_LOAD_FAILURE;
19283    }
19284 #endif   /* defined(HAVE_PRI_CCSS) */
19285    if (sig_pri_load(
19286 #if defined(HAVE_PRI_CCSS)
19287       dahdi_pri_cc_type
19288 #else
19289       NULL
19290 #endif   /* defined(HAVE_PRI_CCSS) */
19291       )) {
19292       __unload_module();
19293       return AST_MODULE_LOAD_FAILURE;
19294    }
19295 #endif
19296 #if defined(HAVE_SS7)
19297    memset(linksets, 0, sizeof(linksets));
19298    for (y = 0; y < NUM_SPANS; y++) {
19299       sig_ss7_init_linkset(&linksets[y].ss7);
19300    }
19301    ss7_set_error(dahdi_ss7_error);
19302    ss7_set_message(dahdi_ss7_message);
19303 #endif   /* defined(HAVE_SS7) */
19304    res = setup_dahdi(0);
19305    /* Make sure we can register our DAHDI channel type */
19306    if (res)
19307       return AST_MODULE_LOAD_DECLINE;
19308    if (ast_channel_register(&dahdi_tech)) {
19309       ast_log(LOG_ERROR, "Unable to register channel class 'DAHDI'\n");
19310       __unload_module();
19311       return AST_MODULE_LOAD_FAILURE;
19312    }
19313 #ifdef HAVE_PRI
19314    ast_cli_register_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
19315 #endif
19316 #if defined(HAVE_SS7)
19317    ast_cli_register_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
19318 #endif   /* defined(HAVE_SS7) */
19319 #ifdef HAVE_OPENR2
19320    ast_cli_register_multiple(dahdi_mfcr2_cli, ARRAY_LEN(dahdi_mfcr2_cli));
19321    ast_register_application_xml(dahdi_accept_r2_call_app, dahdi_accept_r2_call_exec);
19322 #endif
19323 
19324    ast_cli_register_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli));
19325    /* register all the data providers */
19326    ast_data_register_multiple(dahdi_data_providers, ARRAY_LEN(dahdi_data_providers));
19327    memset(round_robin, 0, sizeof(round_robin));
19328    ast_manager_register_xml("DAHDITransfer", 0, action_transfer);
19329    ast_manager_register_xml("DAHDIHangup", 0, action_transferhangup);
19330    ast_manager_register_xml("DAHDIDialOffhook", 0, action_dahdidialoffhook);
19331    ast_manager_register_xml("DAHDIDNDon", 0, action_dahdidndon);
19332    ast_manager_register_xml("DAHDIDNDoff", 0, action_dahdidndoff);
19333    ast_manager_register_xml("DAHDIShowChannels", 0, action_dahdishowchannels);
19334    ast_manager_register_xml("DAHDIRestart", 0, action_dahdirestart);
19335 #if defined(HAVE_PRI)
19336    ast_manager_register_xml("PRIShowSpans", 0, action_prishowspans);
19337 #endif   /* defined(HAVE_PRI) */
19338 
19339    ast_cond_init(&ss_thread_complete, NULL);
19340 
19341    return res;
19342 }
19343 
19344 static int dahdi_sendtext(struct ast_channel *c, const char *text)
19345 {
19346 #define  END_SILENCE_LEN 400
19347 #define  HEADER_MS 50
19348 #define  TRAILER_MS 5
19349 #define  HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8)
19350 #define  ASCII_BYTES_PER_CHAR 80
19351 
19352    unsigned char *buf,*mybuf;
19353    struct dahdi_pvt *p = ast_channel_tech_pvt(c);
19354    struct pollfd fds[1];
19355    int size,res,fd,len,x;
19356    int bytes=0;
19357    int idx;
19358 
19359    /*
19360     * Initial carrier (imaginary)
19361     *
19362     * Note: The following float variables are used by the
19363     * PUT_CLID_MARKMS and PUT_CLID() macros.
19364     */
19365    float cr = 1.0;
19366    float ci = 0.0;
19367    float scont = 0.0;
19368 
19369    if (!text[0]) {
19370       return(0); /* if nothing to send, don't */
19371    }
19372    idx = dahdi_get_index(c, p, 0);
19373    if (idx < 0) {
19374       ast_log(LOG_WARNING, "Huh?  I don't exist?\n");
19375       return -1;
19376    }
19377    if ((!p->tdd) && (!p->mate)) {
19378 #if defined(HAVE_PRI)
19379 #if defined(HAVE_PRI_DISPLAY_TEXT)
19380       ast_mutex_lock(&p->lock);
19381       if (dahdi_sig_pri_lib_handles(p->sig)) {
19382          sig_pri_sendtext(p->sig_pvt, text);
19383       }
19384       ast_mutex_unlock(&p->lock);
19385 #endif   /* defined(HAVE_PRI_DISPLAY_TEXT) */
19386 #endif   /* defined(HAVE_PRI) */
19387       return(0);  /* if not in TDD mode, just return */
19388    }
19389    if (p->mate)
19390       buf = ast_malloc(((strlen(text) + 1) * ASCII_BYTES_PER_CHAR) + END_SILENCE_LEN + HEADER_LEN);
19391    else
19392       buf = ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN);
19393    if (!buf)
19394       return -1;
19395    mybuf = buf;
19396    if (p->mate) {
19397       struct ast_format tmp;
19398       /* PUT_CLI_MARKMS is a macro and requires a format ptr called codec to be present */
19399       struct ast_format *codec = &tmp;
19400       ast_format_set(codec, AST_LAW(p), 0);
19401       for (x = 0; x < HEADER_MS; x++) {   /* 50 ms of Mark */
19402          PUT_CLID_MARKMS;
19403       }
19404       /* Put actual message */
19405       for (x = 0; text[x]; x++) {
19406          PUT_CLID(text[x]);
19407       }
19408       for (x = 0; x < TRAILER_MS; x++) {  /* 5 ms of Mark */
19409          PUT_CLID_MARKMS;
19410       }
19411       len = bytes;
19412       buf = mybuf;
19413    } else {
19414       len = tdd_generate(p->tdd, buf, text);
19415       if (len < 1) {
19416          ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text));
19417          ast_free(mybuf);
19418          return -1;
19419       }
19420    }
19421    memset(buf + len, 0x7f, END_SILENCE_LEN);
19422    len += END_SILENCE_LEN;
19423    fd = p->subs[idx].dfd;
19424    while (len) {
19425       if (ast_check_hangup(c)) {
19426          ast_free(mybuf);
19427          return -1;
19428       }
19429       size = len;
19430       if (size > READ_SIZE)
19431          size = READ_SIZE;
19432       fds[0].fd = fd;
19433       fds[0].events = POLLOUT | POLLPRI;
19434       fds[0].revents = 0;
19435       res = poll(fds, 1, -1);
19436       if (!res) {
19437          ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
19438          continue;
19439       }
19440       /* if got exception */
19441       if (fds[0].revents & POLLPRI) {
19442          ast_free(mybuf);
19443          return -1;
19444       }
19445       if (!(fds[0].revents & POLLOUT)) {
19446          ast_debug(1, "write fd not ready on channel %d\n", p->channel);
19447          continue;
19448       }
19449       res = write(fd, buf, size);
19450       if (res != size) {
19451          if (res == -1) {
19452             ast_free(mybuf);
19453             return -1;
19454          }
19455          ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
19456          break;
19457       }
19458       len -= size;
19459       buf += size;
19460    }
19461    ast_free(mybuf);
19462    return(0);
19463 }
19464 
19465 
19466 static int reload(void)
19467 {
19468    int res = 0;
19469 
19470    res = setup_dahdi(1);
19471    if (res) {
19472       ast_log(LOG_WARNING, "Reload of chan_dahdi.so is unsuccessful!\n");
19473       return -1;
19474    }
19475    return 0;
19476 }
19477 
19478 /* This is a workaround so that menuselect displays a proper description
19479  * AST_MODULE_INFO(, , "DAHDI Telephony"
19480  */
19481 
19482 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, tdesc,
19483    .load = load_module,
19484    .unload = unload_module,
19485    .reload = reload,
19486    .load_pri = AST_MODPRI_CHANNEL_DRIVER,
19487       .nonoptreq = "res_smdi",
19488    );