Wed Aug 7 17:15:37 2019

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>res_smdi</use>
00042    <depend>dahdi</depend>
00043    <depend>tonezone</depend>
00044    <use>pri</use>
00045    <use>ss7</use>
00046    <use>openr2</use>
00047    <support_level>core</support_level>
00048  ***/
00049 
00050 #include "asterisk.h"
00051 
00052 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 417956 $")
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  ***/
00280 
00281 #define SMDI_MD_WAIT_TIMEOUT 1500 /* 1.5 seconds */
00282 
00283 static const char * const lbostr[] = {
00284 "0 db (CSU)/0-133 feet (DSX-1)",
00285 "133-266 feet (DSX-1)",
00286 "266-399 feet (DSX-1)",
00287 "399-533 feet (DSX-1)",
00288 "533-655 feet (DSX-1)",
00289 "-7.5db (CSU)",
00290 "-15db (CSU)",
00291 "-22.5db (CSU)"
00292 };
00293 
00294 /*! Global jitterbuffer configuration - by default, jb is disabled
00295  *  \note Values shown here match the defaults shown in chan_dahdi.conf.sample */
00296 static struct ast_jb_conf default_jbconf =
00297 {
00298    .flags = 0,
00299    .max_size = 200,
00300    .resync_threshold = 1000,
00301    .impl = "fixed",
00302    .target_extra = 40,
00303 };
00304 static struct ast_jb_conf global_jbconf;
00305 
00306 /*!
00307  * \note Define ZHONE_HACK to cause us to go off hook and then back on hook when
00308  * the user hangs up to reset the state machine so ring works properly.
00309  * This is used to be able to support kewlstart by putting the zhone in
00310  * groundstart mode since their forward disconnect supervision is entirely
00311  * broken even though their documentation says it isn't and their support
00312  * is entirely unwilling to provide any assistance with their channel banks
00313  * even though their web site says they support their products for life.
00314  */
00315 /* #define ZHONE_HACK */
00316 
00317 /*! \brief Typically, how many rings before we should send Caller*ID */
00318 #define DEFAULT_CIDRINGS 1
00319 
00320 #define AST_LAW(p) (((p)->law == DAHDI_LAW_ALAW) ? AST_FORMAT_ALAW : AST_FORMAT_ULAW)
00321 
00322 
00323 /*! \brief Signaling types that need to use MF detection should be placed in this macro */
00324 #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))
00325 
00326 static const char tdesc[] = "DAHDI Telephony Driver"
00327 #if defined(HAVE_PRI) || defined(HAVE_SS7) || defined(HAVE_OPENR2)
00328    " w/"
00329    #if defined(HAVE_PRI)
00330       "PRI"
00331    #endif   /* defined(HAVE_PRI) */
00332    #if defined(HAVE_SS7)
00333       #if defined(HAVE_PRI)
00334       " & "
00335       #endif   /* defined(HAVE_PRI) */
00336       "SS7"
00337    #endif   /* defined(HAVE_SS7) */
00338    #if defined(HAVE_OPENR2)
00339       #if defined(HAVE_PRI) || defined(HAVE_SS7)
00340       " & "
00341       #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
00342       "MFC/R2"
00343    #endif   /* defined(HAVE_OPENR2) */
00344 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) || defined(HAVE_OPENR2) */
00345 ;
00346 
00347 static const char config[] = "chan_dahdi.conf";
00348 
00349 #define SIG_EM    DAHDI_SIG_EM
00350 #define SIG_EMWINK   (0x0100000 | DAHDI_SIG_EM)
00351 #define SIG_FEATD (0x0200000 | DAHDI_SIG_EM)
00352 #define  SIG_FEATDMF (0x0400000 | DAHDI_SIG_EM)
00353 #define  SIG_FEATB   (0x0800000 | DAHDI_SIG_EM)
00354 #define  SIG_E911 (0x1000000 | DAHDI_SIG_EM)
00355 #define  SIG_FEATDMF_TA (0x2000000 | DAHDI_SIG_EM)
00356 #define  SIG_FGC_CAMA   (0x4000000 | DAHDI_SIG_EM)
00357 #define  SIG_FGC_CAMAMF (0x8000000 | DAHDI_SIG_EM)
00358 #define SIG_FXSLS DAHDI_SIG_FXSLS
00359 #define SIG_FXSGS DAHDI_SIG_FXSGS
00360 #define SIG_FXSKS DAHDI_SIG_FXSKS
00361 #define SIG_FXOLS DAHDI_SIG_FXOLS
00362 #define SIG_FXOGS DAHDI_SIG_FXOGS
00363 #define SIG_FXOKS DAHDI_SIG_FXOKS
00364 #define SIG_PRI      DAHDI_SIG_CLEAR
00365 #define SIG_BRI      (0x2000000 | DAHDI_SIG_CLEAR)
00366 #define SIG_BRI_PTMP (0X4000000 | DAHDI_SIG_CLEAR)
00367 #define SIG_SS7      (0x1000000 | DAHDI_SIG_CLEAR)
00368 #define SIG_MFCR2    DAHDI_SIG_CAS
00369 #define  SIG_SF      DAHDI_SIG_SF
00370 #define SIG_SFWINK   (0x0100000 | DAHDI_SIG_SF)
00371 #define SIG_SF_FEATD (0x0200000 | DAHDI_SIG_SF)
00372 #define  SIG_SF_FEATDMF (0x0400000 | DAHDI_SIG_SF)
00373 #define  SIG_SF_FEATB   (0x0800000 | DAHDI_SIG_SF)
00374 #define SIG_EM_E1 DAHDI_SIG_EM_E1
00375 
00376 #ifdef LOTS_OF_SPANS
00377 #define NUM_SPANS DAHDI_MAX_SPANS
00378 #else
00379 #define NUM_SPANS       32
00380 #endif
00381 
00382 #define CHAN_PSEUDO  -2
00383 
00384 #define CALLPROGRESS_PROGRESS    1
00385 #define CALLPROGRESS_FAX_OUTGOING   2
00386 #define CALLPROGRESS_FAX_INCOMING   4
00387 #define CALLPROGRESS_FAX      (CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING)
00388 
00389 #define NUM_CADENCE_MAX 25
00390 static int num_cadence = 4;
00391 static int user_has_defined_cadences = 0;
00392 
00393 static struct dahdi_ring_cadence cadences[NUM_CADENCE_MAX] = {
00394    { { 125, 125, 2000, 4000 } },       /*!< Quick chirp followed by normal ring */
00395    { { 250, 250, 500, 1000, 250, 250, 500, 4000 } }, /*!< British style ring */
00396    { { 125, 125, 125, 125, 125, 4000 } }, /*!< Three short bursts */
00397    { { 1000, 500, 2500, 5000 } },   /*!< Long ring */
00398 };
00399 
00400 /*! \brief cidrings says in which pause to transmit the cid information, where the first pause
00401  * is 1, the second pause is 2 and so on.
00402  */
00403 
00404 static int cidrings[NUM_CADENCE_MAX] = {
00405    2,                            /*!< Right after first long ring */
00406    4,                            /*!< Right after long part */
00407    3,                            /*!< After third chirp */
00408    2,                            /*!< Second spell */
00409 };
00410 
00411 /* ETSI EN300 659-1 specifies the ring pulse between 200 and 300 mS */
00412 static struct dahdi_ring_cadence AS_RP_cadence = {{250, 10000}};
00413 
00414 #define ISTRUNK(p) ((p->sig == SIG_FXSLS) || (p->sig == SIG_FXSKS) || \
00415          (p->sig == SIG_FXSGS) || (p->sig == SIG_PRI))
00416 
00417 #define CANBUSYDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */)
00418 #define CANPROGRESSDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */)
00419 
00420 static char defaultcic[64] = "";
00421 static char defaultozz[64] = "";
00422 
00423 /*! Run this script when the MWI state changes on an FXO line, if mwimonitor is enabled */
00424 static char mwimonitornotify[PATH_MAX] = "";
00425 #ifndef HAVE_DAHDI_LINEREVERSE_VMWI
00426 static int  mwisend_rpas = 0;
00427 #endif
00428 
00429 static char progzone[10] = "";
00430 
00431 static int usedistinctiveringdetection = 0;
00432 static int distinctiveringaftercid = 0;
00433 
00434 static int numbufs = 4;
00435 
00436 static int mwilevel = 512;
00437 static int dtmfcid_level = 256;
00438 
00439 #define REPORT_CHANNEL_ALARMS 1
00440 #define REPORT_SPAN_ALARMS    2 
00441 static int report_alarms = REPORT_CHANNEL_ALARMS;
00442 
00443 #ifdef HAVE_PRI
00444 static int pridebugfd = -1;
00445 static char pridebugfilename[1024] = "";
00446 #endif
00447 
00448 /*! \brief Wait up to 16 seconds for first digit (FXO logic) */
00449 static int firstdigittimeout = 16000;
00450 
00451 /*! \brief How long to wait for following digits (FXO logic) */
00452 static int gendigittimeout = 8000;
00453 
00454 /*! \brief How long to wait for an extra digit, if there is an ambiguous match */
00455 static int matchdigittimeout = 3000;
00456 
00457 /*! \brief Protect the interface list (of dahdi_pvt's) */
00458 AST_MUTEX_DEFINE_STATIC(iflock);
00459 
00460 
00461 static int ifcount = 0;
00462 
00463 #ifdef HAVE_PRI
00464 AST_MUTEX_DEFINE_STATIC(pridebugfdlock);
00465 #endif
00466 
00467 /*! \brief Protect the monitoring thread, so only one process can kill or start it, and not
00468    when it's doing something critical. */
00469 AST_MUTEX_DEFINE_STATIC(monlock);
00470 
00471 /*! \brief This is the thread for the monitor which checks for input on the channels
00472    which are not currently in use. */
00473 static pthread_t monitor_thread = AST_PTHREADT_NULL;
00474 static ast_cond_t ss_thread_complete;
00475 AST_MUTEX_DEFINE_STATIC(ss_thread_lock);
00476 AST_MUTEX_DEFINE_STATIC(restart_lock);
00477 static int ss_thread_count = 0;
00478 static int num_restart_pending = 0;
00479 
00480 static int restart_monitor(void);
00481 
00482 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);
00483 
00484 static int dahdi_sendtext(struct ast_channel *c, const char *text);
00485 
00486 static void mwi_event_cb(const struct ast_event *event, void *userdata)
00487 {
00488    /* This module does not handle MWI in an event-based manner.  However, it
00489     * subscribes to MWI for each mailbox that is configured so that the core
00490     * knows that we care about it.  Then, chan_dahdi will get the MWI from the
00491     * event cache instead of checking the mailbox directly. */
00492 }
00493 
00494 /*! \brief Avoid the silly dahdi_getevent which ignores a bunch of events */
00495 static inline int dahdi_get_event(int fd)
00496 {
00497    int j;
00498    if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
00499       return -1;
00500    return j;
00501 }
00502 
00503 /*! \brief Avoid the silly dahdi_waitevent which ignores a bunch of events */
00504 static inline int dahdi_wait_event(int fd)
00505 {
00506    int i, j = 0;
00507    i = DAHDI_IOMUX_SIGEVENT;
00508    if (ioctl(fd, DAHDI_IOMUX, &i) == -1)
00509       return -1;
00510    if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
00511       return -1;
00512    return j;
00513 }
00514 
00515 /*! Chunk size to read -- we use 20ms chunks to make things happy. */
00516 #define READ_SIZE 160
00517 
00518 #define MASK_AVAIL      (1 << 0) /*!< Channel available for PRI use */
00519 #define MASK_INUSE      (1 << 1) /*!< Channel currently in use */
00520 
00521 #define CALLWAITING_SILENT_SAMPLES     ((300 * 8) / READ_SIZE) /*!< 300 ms */
00522 #define CALLWAITING_REPEAT_SAMPLES     ((10000 * 8) / READ_SIZE) /*!< 10,000 ms */
00523 #define CALLWAITING_SUPPRESS_SAMPLES   ((100 * 8) / READ_SIZE) /*!< 100 ms */
00524 #define CIDCW_EXPIRE_SAMPLES        ((500 * 8) / READ_SIZE) /*!< 500 ms */
00525 #define MIN_MS_SINCE_FLASH          ((2000) )   /*!< 2000 ms */
00526 #define DEFAULT_RINGT               ((8000 * 8) / READ_SIZE) /*!< 8,000 ms */
00527 
00528 struct dahdi_pvt;
00529 
00530 /*!
00531  * \brief Configured ring timeout base.
00532  * \note Value computed from "ringtimeout" read in from chan_dahdi.conf if it exists.
00533  */
00534 static int ringt_base = DEFAULT_RINGT;
00535 
00536 #if defined(HAVE_SS7)
00537 
00538 struct dahdi_ss7 {
00539    struct sig_ss7_linkset ss7;
00540 };
00541 
00542 static struct dahdi_ss7 linksets[NUM_SPANS];
00543 
00544 static int cur_ss7type = -1;
00545 static int cur_linkset = -1;
00546 static int cur_pointcode = -1;
00547 static int cur_cicbeginswith = -1;
00548 static int cur_adjpointcode = -1;
00549 static int cur_networkindicator = -1;
00550 static int cur_defaultdpc = -1;
00551 #endif   /* defined(HAVE_SS7) */
00552 
00553 #ifdef HAVE_OPENR2
00554 struct dahdi_mfcr2_conf {
00555    openr2_variant_t variant;
00556    int mfback_timeout;
00557    int metering_pulse_timeout;
00558    int max_ani;
00559    int max_dnis;
00560    signed int get_ani_first:2;
00561 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
00562    signed int skip_category_request:2;
00563 #endif
00564    unsigned int call_files:1;
00565    unsigned int allow_collect_calls:1;
00566    unsigned int charge_calls:1;
00567    unsigned int accept_on_offer:1;
00568    unsigned int forced_release:1;
00569    unsigned int double_answer:1;
00570    signed int immediate_accept:2;
00571    char logdir[OR2_MAX_PATH];
00572    char r2proto_file[OR2_MAX_PATH];
00573    openr2_log_level_t loglevel;
00574    openr2_calling_party_category_t category;
00575 };
00576 
00577 /* MFC-R2 pseudo-link structure */
00578 struct dahdi_mfcr2 {
00579    pthread_t r2master;            /*!< Thread of master */
00580    openr2_context_t *protocol_context;    /*!< OpenR2 context handle */
00581    struct dahdi_pvt *pvts[SIG_MFCR2_MAX_CHANNELS];     /*!< Member channel pvt structs */
00582    int numchans;                          /*!< Number of channels in this R2 block */
00583    struct dahdi_mfcr2_conf conf;         /*!< Configuration used to setup this pseudo-link */
00584 };
00585 
00586 /* malloc'd array of malloc'd r2links */
00587 static struct dahdi_mfcr2 **r2links;
00588 /* how many r2links have been malloc'd */
00589 static int r2links_count = 0;
00590 
00591 #endif /* HAVE_OPENR2 */
00592 
00593 #ifdef HAVE_PRI
00594 
00595 struct dahdi_pri {
00596    int dchannels[SIG_PRI_NUM_DCHANS];     /*!< What channel are the dchannels on */
00597    int mastertrunkgroup;               /*!< What trunk group is our master */
00598    int prilogicalspan;                 /*!< Logical span number within trunk group */
00599    struct sig_pri_span pri;
00600 };
00601 
00602 static struct dahdi_pri pris[NUM_SPANS];
00603 
00604 #if defined(HAVE_PRI_CCSS)
00605 /*! DAHDI PRI CCSS agent and monitor type name. */
00606 static const char dahdi_pri_cc_type[] = "DAHDI/PRI";
00607 #endif   /* defined(HAVE_PRI_CCSS) */
00608 
00609 #else
00610 /*! Shut up the compiler */
00611 struct dahdi_pri;
00612 #endif
00613 
00614 #define SUB_REAL  0        /*!< Active call */
00615 #define SUB_CALLWAIT 1        /*!< Call-Waiting call on hold */
00616 #define SUB_THREEWAY 2        /*!< Three-way call */
00617 
00618 /* Polarity states */
00619 #define POLARITY_IDLE   0
00620 #define POLARITY_REV    1
00621 
00622 
00623 struct distRingData {
00624    int ring[3];
00625    int range;
00626 };
00627 struct ringContextData {
00628    char contextData[AST_MAX_CONTEXT];
00629 };
00630 struct dahdi_distRings {
00631    struct distRingData ringnum[3];
00632    struct ringContextData ringContext[3];
00633 };
00634 
00635 static const char * const subnames[] = {
00636    "Real",
00637    "Callwait",
00638    "Threeway"
00639 };
00640 
00641 struct dahdi_subchannel {
00642    int dfd;
00643    struct ast_channel *owner;
00644    int chan;
00645    short buffer[AST_FRIENDLY_OFFSET/2 + READ_SIZE];
00646    struct ast_frame f;     /*!< One frame for each channel.  How did this ever work before? */
00647    unsigned int needringing:1;
00648    unsigned int needbusy:1;
00649    unsigned int needcongestion:1;
00650    unsigned int needanswer:1;
00651    unsigned int needflash:1;
00652    unsigned int needhold:1;
00653    unsigned int needunhold:1;
00654    unsigned int linear:1;
00655    unsigned int inthreeway:1;
00656    struct dahdi_confinfo curconf;
00657 };
00658 
00659 #define CONF_USER_REAL     (1 << 0)
00660 #define CONF_USER_THIRDCALL   (1 << 1)
00661 
00662 #define MAX_SLAVES   4
00663 
00664 /* States for sending MWI message
00665  * First three states are required for send Ring Pulse Alert Signal
00666  */
00667 typedef enum {
00668    MWI_SEND_NULL = 0,
00669    MWI_SEND_SA,
00670    MWI_SEND_SA_WAIT,
00671    MWI_SEND_PAUSE,
00672    MWI_SEND_SPILL,
00673    MWI_SEND_CLEANUP,
00674    MWI_SEND_DONE,
00675 } mwisend_states;
00676 
00677 struct mwisend_info {
00678    struct   timeval  pause;
00679    mwisend_states    mwisend_current;
00680 };
00681 
00682 /*! Specify the lists dahdi_pvt can be put in. */
00683 enum DAHDI_IFLIST {
00684    DAHDI_IFLIST_NONE,   /*!< The dahdi_pvt is not in any list. */
00685    DAHDI_IFLIST_MAIN,   /*!< The dahdi_pvt is in the main interface list */
00686 #if defined(HAVE_PRI)
00687    DAHDI_IFLIST_NO_B_CHAN, /*!< The dahdi_pvt is in a no B channel interface list */
00688 #endif   /* defined(HAVE_PRI) */
00689 };
00690 
00691 struct dahdi_pvt {
00692    ast_mutex_t lock;             /*!< Channel private lock. */
00693    struct callerid_state *cs;
00694    struct ast_channel *owner;       /*!< Our current active owner (if applicable) */
00695                      /*!< Up to three channels can be associated with this call */
00696 
00697    struct dahdi_subchannel sub_unused;    /*!< Just a safety precaution */
00698    struct dahdi_subchannel subs[3];       /*!< Sub-channels */
00699    struct dahdi_confinfo saveconf;        /*!< Saved conference info */
00700 
00701    struct dahdi_pvt *slaves[MAX_SLAVES];     /*!< Slave to us (follows our conferencing) */
00702    struct dahdi_pvt *master;           /*!< Master to us (we follow their conferencing) */
00703    int inconference;          /*!< If our real should be in the conference */
00704 
00705    int bufsize;                /*!< Size of the buffers */
00706    int buf_no;             /*!< Number of buffers */
00707    int buf_policy;            /*!< Buffer policy */
00708    int faxbuf_no;              /*!< Number of Fax buffers */
00709    int faxbuf_policy;          /*!< Fax buffer policy */
00710    int sig;             /*!< Signalling style */
00711    /*!
00712     * \brief Nonzero if the signaling type is sent over a radio.
00713     * \note Set to a couple of nonzero values but it is only tested like a boolean.
00714     */
00715    int radio;
00716    int outsigmod;             /*!< Outbound Signalling style (modifier) */
00717    int oprmode;               /*!< "Operator Services" mode */
00718    struct dahdi_pvt *oprpeer;          /*!< "Operator Services" peer tech_pvt ptr */
00719    /*! \brief Amount of gain to increase during caller id */
00720    float cid_rxgain;
00721    /*! \brief Software Rx gain set by chan_dahdi.conf */
00722    float rxgain;
00723    /*! \brief Software Tx gain set by chan_dahdi.conf */
00724    float txgain;
00725 
00726    float txdrc; /*!< Dynamic Range Compression factor. a number between 1 and 6ish */
00727    float rxdrc;
00728    
00729    int tonezone;              /*!< tone zone for this chan, or -1 for default */
00730    enum DAHDI_IFLIST which_iflist;  /*!< Which interface list is this structure listed? */
00731    struct dahdi_pvt *next;          /*!< Next channel in list */
00732    struct dahdi_pvt *prev;          /*!< Prev channel in list */
00733 
00734    /* flags */
00735 
00736    /*!
00737     * \brief TRUE if ADSI (Analog Display Services Interface) available
00738     * \note Set from the "adsi" value read in from chan_dahdi.conf
00739     */
00740    unsigned int adsi:1;
00741    /*!
00742     * \brief TRUE if we can use a polarity reversal to mark when an outgoing
00743     * call is answered by the remote party.
00744     * \note Set from the "answeronpolarityswitch" value read in from chan_dahdi.conf
00745     */
00746    unsigned int answeronpolarityswitch:1;
00747    /*!
00748     * \brief TRUE if busy detection is enabled.
00749     * (Listens for the beep-beep busy pattern.)
00750     * \note Set from the "busydetect" value read in from chan_dahdi.conf
00751     */
00752    unsigned int busydetect:1;
00753    /*!
00754     * \brief TRUE if call return is enabled.
00755     * (*69, if your dialplan doesn't catch this first)
00756     * \note Set from the "callreturn" value read in from chan_dahdi.conf
00757     */
00758    unsigned int callreturn:1;
00759    /*!
00760     * \brief TRUE if busy extensions will hear the call-waiting tone
00761     * and can use hook-flash to switch between callers.
00762     * \note Can be disabled by dialing *70.
00763     * \note Initialized with the "callwaiting" value read in from chan_dahdi.conf
00764     */
00765    unsigned int callwaiting:1;
00766    /*!
00767     * \brief TRUE if send caller ID for Call Waiting
00768     * \note Set from the "callwaitingcallerid" value read in from chan_dahdi.conf
00769     */
00770    unsigned int callwaitingcallerid:1;
00771    /*!
00772     * \brief TRUE if support for call forwarding enabled.
00773     * Dial *72 to enable call forwarding.
00774     * Dial *73 to disable call forwarding.
00775     * \note Set from the "cancallforward" value read in from chan_dahdi.conf
00776     */
00777    unsigned int cancallforward:1;
00778    /*!
00779     * \brief TRUE if support for call parking is enabled.
00780     * \note Set from the "canpark" value read in from chan_dahdi.conf
00781     */
00782    unsigned int canpark:1;
00783    /*! \brief TRUE if to wait for a DTMF digit to confirm answer */
00784    unsigned int confirmanswer:1;
00785    /*!
00786     * \brief TRUE if the channel is to be destroyed on hangup.
00787     * (Used by pseudo channels.)
00788     */
00789    unsigned int destroy:1;
00790    unsigned int didtdd:1;           /*!< flag to say its done it once */
00791    /*! \brief TRUE if analog type line dialed no digits in Dial() */
00792    unsigned int dialednone:1;
00793    /*!
00794     * \brief TRUE if in the process of dialing digits or sending something.
00795     * \note This is used as a receive squelch for ISDN until connected.
00796     */
00797    unsigned int dialing:1;
00798    /*! \brief TRUE if the transfer capability of the call is digital. */
00799    unsigned int digital:1;
00800    /*! \brief TRUE if Do-Not-Disturb is enabled, present only for non sig_analog */
00801    unsigned int dnd:1;
00802    /*! \brief XXX BOOLEAN Purpose??? */
00803    unsigned int echobreak:1;
00804    /*!
00805     * \brief TRUE if echo cancellation enabled when bridged.
00806     * \note Initialized with the "echocancelwhenbridged" value read in from chan_dahdi.conf
00807     * \note Disabled if the echo canceller is not setup.
00808     */
00809    unsigned int echocanbridged:1;
00810    /*! \brief TRUE if echo cancellation is turned on. */
00811    unsigned int echocanon:1;
00812    /*! \brief TRUE if a fax tone has already been handled. */
00813    unsigned int faxhandled:1;
00814    /*! TRUE if dynamic faxbuffers are configured for use, default is OFF */
00815    unsigned int usefaxbuffers:1;
00816    /*! TRUE while buffer configuration override is in use */
00817    unsigned int bufferoverrideinuse:1;
00818    /*! \brief TRUE if over a radio and dahdi_read() has been called. */
00819    unsigned int firstradio:1;
00820    /*!
00821     * \brief TRUE if the call will be considered "hung up" on a polarity reversal.
00822     * \note Set from the "hanguponpolarityswitch" value read in from chan_dahdi.conf
00823     */
00824    unsigned int hanguponpolarityswitch:1;
00825    /*! \brief TRUE if DTMF detection needs to be done by hardware. */
00826    unsigned int hardwaredtmf:1;
00827    /*!
00828     * \brief TRUE if the outgoing caller ID is blocked/hidden.
00829     * \note Caller ID can be disabled by dialing *67.
00830     * \note Caller ID can be enabled by dialing *82.
00831     * \note Initialized with the "hidecallerid" value read in from chan_dahdi.conf
00832     */
00833    unsigned int hidecallerid:1;
00834    /*!
00835     * \brief TRUE if hide just the name not the number for legacy PBX use.
00836     * \note Only applies to PRI channels.
00837     * \note Set from the "hidecalleridname" value read in from chan_dahdi.conf
00838     */
00839    unsigned int hidecalleridname:1;
00840    /*! \brief TRUE if DTMF detection is disabled. */
00841    unsigned int ignoredtmf:1;
00842    /*!
00843     * \brief TRUE if the channel should be answered immediately
00844     * without attempting to gather any digits.
00845     * \note Set from the "immediate" value read in from chan_dahdi.conf
00846     */
00847    unsigned int immediate:1;
00848    /*! \brief TRUE if in an alarm condition. */
00849    unsigned int inalarm:1;
00850    /*! \brief TRUE if TDD in MATE mode */
00851    unsigned int mate:1;
00852    /*! \brief TRUE if we originated the call leg. */
00853    unsigned int outgoing:1;
00854    /* unsigned int overlapdial:1;         unused and potentially confusing */
00855    /*!
00856     * \brief TRUE if busy extensions will hear the call-waiting tone
00857     * and can use hook-flash to switch between callers.
00858     * \note Set from the "callwaiting" value read in from chan_dahdi.conf
00859     */
00860    unsigned int permcallwaiting:1;
00861    /*!
00862     * \brief TRUE if the outgoing caller ID is blocked/restricted/hidden.
00863     * \note Set from the "hidecallerid" value read in from chan_dahdi.conf
00864     */
00865    unsigned int permhidecallerid:1;
00866    /*!
00867     * \brief TRUE if PRI congestion/busy indications are sent out-of-band.
00868     * \note Set from the "priindication" value read in from chan_dahdi.conf
00869     */
00870    unsigned int priindication_oob:1;
00871    /*!
00872     * \brief TRUE if PRI B channels are always exclusively selected.
00873     * \note Set from the "priexclusive" value read in from chan_dahdi.conf
00874     */
00875    unsigned int priexclusive:1;
00876    /*!
00877     * \brief TRUE if we will pulse dial.
00878     * \note Set from the "pulsedial" value read in from chan_dahdi.conf
00879     */
00880    unsigned int pulse:1;
00881    /*! \brief TRUE if a pulsed digit was detected. (Pulse dial phone detected) */
00882    unsigned int pulsedial:1;
00883    unsigned int restartpending:1;      /*!< flag to ensure counted only once for restart */
00884    /*!
00885     * \brief TRUE if caller ID is restricted.
00886     * \note Set but not used.  Should be deleted.  Redundant with permhidecallerid.
00887     * \note Set from the "restrictcid" value read in from chan_dahdi.conf
00888     */
00889    unsigned int restrictcid:1;
00890    /*!
00891     * \brief TRUE if three way calling is enabled
00892     * \note Set from the "threewaycalling" value read in from chan_dahdi.conf
00893     */
00894    unsigned int threewaycalling:1;
00895    /*!
00896     * \brief TRUE if call transfer is enabled
00897     * \note For FXS ports (either direct analog or over T1/E1):
00898     *   Support flash-hook call transfer
00899     * \note For digital ports using ISDN PRI protocols:
00900     *   Support switch-side transfer (called 2BCT, RLT or other names)
00901     * \note Set from the "transfer" value read in from chan_dahdi.conf
00902     */
00903    unsigned int transfer:1;
00904    /*!
00905     * \brief TRUE if caller ID is used on this channel.
00906     * \note PRI and SS7 spans will save caller ID from the networking peer.
00907     * \note FXS ports will generate the caller ID spill.
00908     * \note FXO ports will listen for the caller ID spill.
00909     * \note Set from the "usecallerid" value read in from chan_dahdi.conf
00910     */
00911    unsigned int use_callerid:1;
00912    /*!
00913     * \brief TRUE if we will use the calling presentation setting
00914     * from the Asterisk channel for outgoing calls.
00915     * \note Only applies to PRI and SS7 channels.
00916     * \note Set from the "usecallingpres" value read in from chan_dahdi.conf
00917     */
00918    unsigned int use_callingpres:1;
00919    /*!
00920     * \brief TRUE if distinctive rings are to be detected.
00921     * \note For FXO lines
00922     * \note Set indirectly from the "usedistinctiveringdetection" value read in from chan_dahdi.conf
00923     */
00924    unsigned int usedistinctiveringdetection:1;
00925    /*!
00926     * \brief TRUE if we should use the callerid from incoming call on dahdi transfer.
00927     * \note Set from the "useincomingcalleridondahditransfer" value read in from chan_dahdi.conf
00928     */
00929    unsigned int dahditrcallerid:1;
00930    /*!
00931     * \brief TRUE if allowed to flash-transfer to busy channels.
00932     * \note Set from the "transfertobusy" value read in from chan_dahdi.conf
00933     */
00934    unsigned int transfertobusy:1;
00935    /*!
00936     * \brief TRUE if the FXO port monitors for neon type MWI indications from the other end.
00937     * \note Set if the "mwimonitor" value read in contains "neon" from chan_dahdi.conf
00938     */
00939    unsigned int mwimonitor_neon:1;
00940    /*!
00941     * \brief TRUE if the FXO port monitors for fsk type MWI indications from the other end.
00942     * \note Set if the "mwimonitor" value read in contains "fsk" from chan_dahdi.conf
00943     */
00944    unsigned int mwimonitor_fsk:1;
00945    /*!
00946     * \brief TRUE if the FXO port monitors for rpas precursor to fsk MWI indications from the other end.
00947     * \note RPAS - Ring Pulse Alert Signal
00948     * \note Set if the "mwimonitor" value read in contains "rpas" from chan_dahdi.conf
00949     */
00950    unsigned int mwimonitor_rpas:1;
00951    /*! \brief TRUE if an MWI monitor thread is currently active */
00952    unsigned int mwimonitoractive:1;
00953    /*! \brief TRUE if a MWI message sending thread is active */
00954    unsigned int mwisendactive:1;
00955    /*!
00956     * \brief TRUE if channel is out of reset and ready
00957     * \note Set but not used.
00958     */
00959    unsigned int inservice:1;
00960    /*!
00961     * \brief TRUE if the channel is locally blocked.
00962     * \note Applies to SS7 and MFCR2 channels.
00963     */
00964    unsigned int locallyblocked:1;
00965    /*!
00966     * \brief TRUE if the channel is remotely blocked.
00967     * \note Applies to SS7 and MFCR2 channels.
00968     */
00969    unsigned int remotelyblocked:1;
00970    /*!
00971     * \brief TRUE if the channel alarms will be managed also as Span ones
00972     * \note Applies to all channels
00973     */
00974    unsigned int manages_span_alarms:1;
00975 
00976 #if defined(HAVE_PRI)
00977    struct sig_pri_span *pri;
00978    int logicalspan;
00979 #endif
00980    /*!
00981     * \brief TRUE if SMDI (Simplified Message Desk Interface) is enabled
00982     * \note Set from the "usesmdi" value read in from chan_dahdi.conf
00983     */
00984    unsigned int use_smdi:1;
00985    struct mwisend_info mwisend_data;
00986    /*! \brief The SMDI interface to get SMDI messages from. */
00987    struct ast_smdi_interface *smdi_iface;
00988 
00989    /*! \brief Distinctive Ring data */
00990    struct dahdi_distRings drings;
00991 
00992    /*!
00993     * \brief The configured context for incoming calls.
00994     * \note The "context" string read in from chan_dahdi.conf
00995     */
00996    char context[AST_MAX_CONTEXT];
00997    /*!
00998     * \brief Saved context string.
00999     */
01000    char defcontext[AST_MAX_CONTEXT];
01001    /*! \brief Extension to use in the dialplan. */
01002    char exten[AST_MAX_EXTENSION];
01003    /*!
01004     * \brief Language configured for calls.
01005     * \note The "language" string read in from chan_dahdi.conf
01006     */
01007    char language[MAX_LANGUAGE];
01008    /*!
01009     * \brief The configured music-on-hold class to use for calls.
01010     * \note The "musicclass" or "mohinterpret" or "musiconhold" string read in from chan_dahdi.conf
01011     */
01012    char mohinterpret[MAX_MUSICCLASS];
01013    /*!
01014     * \brief Suggested music-on-hold class for peer channel to use for calls.
01015     * \note The "mohsuggest" string read in from chan_dahdi.conf
01016     */
01017    char mohsuggest[MAX_MUSICCLASS];
01018    char parkinglot[AST_MAX_EXTENSION]; /*!< Parking lot for this channel */
01019 #if defined(HAVE_PRI) || defined(HAVE_SS7)
01020    /*! \brief Automatic Number Identification number (Alternate PRI caller ID number) */
01021    char cid_ani[AST_MAX_EXTENSION];
01022 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
01023    /*! \brief Automatic Number Identification code from PRI */
01024    int cid_ani2;
01025    /*! \brief Caller ID number from an incoming call. */
01026    char cid_num[AST_MAX_EXTENSION];
01027    /*!
01028     * \brief Caller ID tag from incoming call
01029     * \note the "cid_tag" string read in from chan_dahdi.conf
01030     */
01031    char cid_tag[AST_MAX_EXTENSION];
01032    /*! \brief Caller ID Q.931 TON/NPI field values.  Set by PRI. Zero otherwise. */
01033    int cid_ton;
01034    /*! \brief Caller ID name from an incoming call. */
01035    char cid_name[AST_MAX_EXTENSION];
01036    /*! \brief Caller ID subaddress from an incoming call. */
01037    char cid_subaddr[AST_MAX_EXTENSION];
01038    char *origcid_num;            /*!< malloced original callerid */
01039    char *origcid_name;           /*!< malloced original callerid */
01040    /*! \brief Call waiting number. */
01041    char callwait_num[AST_MAX_EXTENSION];
01042    /*! \brief Call waiting name. */
01043    char callwait_name[AST_MAX_EXTENSION];
01044    /*! \brief Redirecting Directory Number Information Service (RDNIS) number */
01045    char rdnis[AST_MAX_EXTENSION];
01046    /*! \brief Dialed Number Identifier */
01047    char dnid[AST_MAX_EXTENSION];
01048    /*!
01049     * \brief Bitmapped groups this belongs to.
01050     * \note The "group" bitmapped group string read in from chan_dahdi.conf
01051     */
01052    ast_group_t group;
01053    /*! \brief Default call PCM encoding format: DAHDI_LAW_ALAW or DAHDI_LAW_MULAW. */
01054    int law_default;
01055    /*! \brief Active PCM encoding format: DAHDI_LAW_ALAW or DAHDI_LAW_MULAW */
01056    int law;
01057    int confno;             /*!< Our conference */
01058    int confusers;             /*!< Who is using our conference */
01059    int propconfno;               /*!< Propagated conference number */
01060    /*!
01061     * \brief Bitmapped call groups this belongs to.
01062     * \note The "callgroup" bitmapped group string read in from chan_dahdi.conf
01063     */
01064    ast_group_t callgroup;
01065    /*!
01066     * \brief Bitmapped pickup groups this belongs to.
01067     * \note The "pickupgroup" bitmapped group string read in from chan_dahdi.conf
01068     */
01069    ast_group_t pickupgroup;
01070    /*!
01071     * \brief Channel variable list with associated values to set when a channel is created.
01072     * \note The "setvar" strings read in from chan_dahdi.conf
01073     */
01074    struct ast_variable *vars;
01075    int channel;               /*!< Channel Number */
01076    int span;               /*!< Span number */
01077    time_t guardtime;          /*!< Must wait this much time before using for new call */
01078    int cid_signalling;           /*!< CID signalling type bell202 or v23 */
01079    int cid_start;             /*!< CID start indicator, polarity or ring or DTMF without warning event */
01080    int dtmfcid_holdoff_state;    /*!< State indicator that allows for line to settle before checking for dtmf energy */
01081    struct timeval dtmfcid_delay;  /*!< Time value used for allow line to settle */
01082    int callingpres;           /*!< The value of calling presentation that we're going to use when placing a PRI call */
01083    int callwaitingrepeat;           /*!< How many samples to wait before repeating call waiting */
01084    int cidcwexpire;           /*!< When to stop waiting for CID/CW CAS response (In samples) */
01085    int cid_suppress_expire;      /*!< How many samples to suppress after a CID spill. */
01086    /*! \brief Analog caller ID waveform sample buffer */
01087    unsigned char *cidspill;
01088    /*! \brief Position in the cidspill buffer to send out next. */
01089    int cidpos;
01090    /*! \brief Length of the cidspill buffer containing samples. */
01091    int cidlen;
01092    /*! \brief Ring timeout timer?? */
01093    int ringt;
01094    /*!
01095     * \brief Ring timeout base.
01096     * \note Value computed indirectly from "ringtimeout" read in from chan_dahdi.conf
01097     */
01098    int ringt_base;
01099    /*!
01100     * \brief Number of most significant digits/characters to strip from the dialed number.
01101     * \note Feature is deprecated.  Use dialplan logic.
01102     * \note The characters are stripped before the PRI TON/NPI prefix
01103     * characters are processed.
01104     */
01105    int stripmsd;
01106    /*!
01107     * \brief TRUE if Call Waiting (CW) CPE Alert Signal (CAS) is being sent.
01108     * \note
01109     * After CAS is sent, the call waiting caller id will be sent if the phone
01110     * gives a positive reply.
01111     */
01112    int callwaitcas;
01113    /*! \brief Number of call waiting rings. */
01114    int callwaitrings;
01115    /*! \brief Echo cancel parameters. */
01116    struct {
01117       struct dahdi_echocanparams head;
01118       struct dahdi_echocanparam params[DAHDI_MAX_ECHOCANPARAMS];
01119    } echocancel;
01120    /*!
01121     * \brief Echo training time. 0 = disabled
01122     * \note Set from the "echotraining" value read in from chan_dahdi.conf
01123     */
01124    int echotraining;
01125    /*! \brief Filled with 'w'.  XXX Purpose?? */
01126    char echorest[20];
01127    /*!
01128     * \brief Number of times to see "busy" tone before hanging up.
01129     * \note Set from the "busycount" value read in from chan_dahdi.conf
01130     */
01131    int busycount;
01132    /*!
01133     * \brief If your country has a busy tone with the same length tone and silence (as many countries do), consider using this option in order to compare tone and silence lengths
01134     * \note Set from the "busycompare" value read in from chan_dahdi.conf
01135     */
01136    int busycompare;
01137    /*!
01138     * \brief Lenght of "tone" in ms.
01139     * \note Set from the "busypattern" value read in from chan_dahdi.conf
01140     */
01141    int busytonelength;
01142    /*!
01143     * \brief Lenght of "silence" in ms.
01144     * \note Set from the "busypattern" value read in from chan_dahdi.conf
01145     */
01146    int busyquietlength;
01147    /*!
01148     * \brief  Maximun percentage difference allowed between measured and actual pattern
01149     * \note Set from the "busyfuzziness" value read in from chan_dahdi.conf
01150     */
01151    int busyfuzziness;
01152    /*!
01153     * \brief Maximun signal average level considered as silence in this channel
01154     * \note Set from the "silencethreshold" value read in from chan_dahdi.conf
01155     */
01156    int silencethreshold;
01157    /*!
01158     * \brief Bitmapped call progress detection flags. CALLPROGRESS_xxx values.
01159     * \note Bits set from the "callprogress" and "faxdetect" values read in from chan_dahdi.conf
01160     */
01161    int callprogress;
01162    /*!
01163     * \brief Number of milliseconds to wait for dialtone.
01164     * \note Set from the "waitfordialtone" value read in from chan_dahdi.conf
01165     */
01166    int waitfordialtone;
01167    struct timeval waitingfordt;        /*!< Time we started waiting for dialtone */
01168    struct timeval flashtime;        /*!< Last flash-hook time */
01169    /*! \brief Opaque DSP configuration structure. */
01170    struct ast_dsp *dsp;
01171    /*! \brief DAHDI dial operation command struct for ioctl() call. */
01172    struct dahdi_dialoperation dop;
01173    int whichwink;             /*!< SIG_FEATDMF_TA Which wink are we on? */
01174    /*! \brief Second part of SIG_FEATDMF_TA wink operation. */
01175    char finaldial[64];
01176    char accountcode[AST_MAX_ACCOUNT_CODE];      /*!< Account code */
01177    int amaflags;              /*!< AMA Flags */
01178    struct tdd_state *tdd;           /*!< TDD flag */
01179    /*! \brief Accumulated call forwarding number. */
01180    char call_forward[AST_MAX_EXTENSION];
01181    /*!
01182     * \brief Voice mailbox location.
01183     * \note Set from the "mailbox" string read in from chan_dahdi.conf
01184     */
01185    char mailbox[AST_MAX_EXTENSION];
01186    /*! \brief Opaque event subscription parameters for message waiting indication support. */
01187    struct ast_event_sub *mwi_event_sub;
01188    /*! \brief Delayed dialing for E911.  Overlap digits for ISDN. */
01189    char dialdest[256];
01190 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
01191    struct dahdi_vmwi_info mwisend_setting;            /*!< Which VMWI methods to use */
01192    unsigned int mwisend_fsk: 1;     /*! Variable for enabling FSK MWI handling in chan_dahdi */
01193    unsigned int mwisend_rpas:1;     /*! Variable for enabling Ring Pulse Alert before MWI FSK Spill */
01194 #endif
01195    int distinctivering;          /*!< Which distinctivering to use */
01196    int dtmfrelax;             /*!< whether to run in relaxed DTMF mode */
01197    /*! \brief Holding place for event injected from outside normal operation. */
01198    int fake_event;
01199    /*!
01200     * \brief Minimal time period (ms) between the answer polarity
01201     * switch and hangup polarity switch.
01202     */
01203    int polarityonanswerdelay;
01204    /*! \brief Start delay time if polarityonanswerdelay is nonzero. */
01205    struct timeval polaritydelaytv;
01206    /*!
01207     * \brief Send caller ID on FXS after this many rings. Set to 1 for US.
01208     * \note Set from the "sendcalleridafter" value read in from chan_dahdi.conf
01209     */
01210    int sendcalleridafter;
01211    /*! \brief Current line interface polarity. POLARITY_IDLE, POLARITY_REV */
01212    int polarity;
01213    /*! \brief DSP feature flags: DSP_FEATURE_xxx */
01214    int dsp_features;
01215 #if defined(HAVE_SS7)
01216    /*! \brief SS7 control parameters */
01217    struct sig_ss7_linkset *ss7;
01218 #endif   /* defined(HAVE_SS7) */
01219 #ifdef HAVE_OPENR2
01220    struct dahdi_mfcr2 *mfcr2;
01221    openr2_chan_t *r2chan;
01222    openr2_calling_party_category_t mfcr2_recvd_category;
01223    openr2_calling_party_category_t mfcr2_category;
01224    int mfcr2_dnis_index;
01225    int mfcr2_ani_index;
01226    int mfcr2call:1;
01227    int mfcr2_answer_pending:1;
01228    int mfcr2_charge_calls:1;
01229    int mfcr2_allow_collect_calls:1;
01230    int mfcr2_forced_release:1;
01231    int mfcr2_dnis_matched:1;
01232    int mfcr2_call_accepted:1;
01233    int mfcr2_progress:1;
01234    int mfcr2_accept_on_offer:1;
01235 #endif
01236    /*! \brief DTMF digit in progress.  0 when no digit in progress. */
01237    char begindigit;
01238    /*! \brief TRUE if confrence is muted. */
01239    int muting;
01240    void *sig_pvt;
01241    struct ast_cc_config_params *cc_params;
01242    /* DAHDI channel names may differ greatly from the
01243     * string that was provided to an app such as Dial. We
01244     * need to save the original string passed to dahdi_request
01245     * for call completion purposes. This way, we can replicate
01246     * the original dialed string later.
01247     */
01248    char dialstring[AST_CHANNEL_NAME];
01249 };
01250 
01251 #define DATA_EXPORT_DAHDI_PVT(MEMBER)              \
01252    MEMBER(dahdi_pvt, cid_rxgain, AST_DATA_DOUBLE)        \
01253    MEMBER(dahdi_pvt, rxgain, AST_DATA_DOUBLE)         \
01254    MEMBER(dahdi_pvt, txgain, AST_DATA_DOUBLE)         \
01255    MEMBER(dahdi_pvt, txdrc, AST_DATA_DOUBLE)       \
01256    MEMBER(dahdi_pvt, rxdrc, AST_DATA_DOUBLE)       \
01257    MEMBER(dahdi_pvt, adsi, AST_DATA_BOOLEAN)       \
01258    MEMBER(dahdi_pvt, answeronpolarityswitch, AST_DATA_BOOLEAN) \
01259    MEMBER(dahdi_pvt, busydetect, AST_DATA_BOOLEAN)       \
01260    MEMBER(dahdi_pvt, callreturn, AST_DATA_BOOLEAN)       \
01261    MEMBER(dahdi_pvt, callwaiting, AST_DATA_BOOLEAN)      \
01262    MEMBER(dahdi_pvt, callwaitingcallerid, AST_DATA_BOOLEAN) \
01263    MEMBER(dahdi_pvt, cancallforward, AST_DATA_BOOLEAN)      \
01264    MEMBER(dahdi_pvt, canpark, AST_DATA_BOOLEAN)       \
01265    MEMBER(dahdi_pvt, confirmanswer, AST_DATA_BOOLEAN)    \
01266    MEMBER(dahdi_pvt, destroy, AST_DATA_BOOLEAN)       \
01267    MEMBER(dahdi_pvt, didtdd, AST_DATA_BOOLEAN)        \
01268    MEMBER(dahdi_pvt, dialednone, AST_DATA_BOOLEAN)       \
01269    MEMBER(dahdi_pvt, dialing, AST_DATA_BOOLEAN)       \
01270    MEMBER(dahdi_pvt, digital, AST_DATA_BOOLEAN)       \
01271    MEMBER(dahdi_pvt, dnd, AST_DATA_BOOLEAN)        \
01272    MEMBER(dahdi_pvt, echobreak, AST_DATA_BOOLEAN)        \
01273    MEMBER(dahdi_pvt, echocanbridged, AST_DATA_BOOLEAN)      \
01274    MEMBER(dahdi_pvt, echocanon, AST_DATA_BOOLEAN)        \
01275    MEMBER(dahdi_pvt, faxhandled, AST_DATA_BOOLEAN)       \
01276    MEMBER(dahdi_pvt, usefaxbuffers, AST_DATA_BOOLEAN)    \
01277    MEMBER(dahdi_pvt, bufferoverrideinuse, AST_DATA_BOOLEAN) \
01278    MEMBER(dahdi_pvt, firstradio, AST_DATA_BOOLEAN)       \
01279    MEMBER(dahdi_pvt, hanguponpolarityswitch, AST_DATA_BOOLEAN) \
01280    MEMBER(dahdi_pvt, hardwaredtmf, AST_DATA_BOOLEAN)     \
01281    MEMBER(dahdi_pvt, hidecallerid, AST_DATA_BOOLEAN)     \
01282    MEMBER(dahdi_pvt, hidecalleridname, AST_DATA_BOOLEAN)    \
01283    MEMBER(dahdi_pvt, ignoredtmf, AST_DATA_BOOLEAN)       \
01284    MEMBER(dahdi_pvt, immediate, AST_DATA_BOOLEAN)        \
01285    MEMBER(dahdi_pvt, inalarm, AST_DATA_BOOLEAN)       \
01286    MEMBER(dahdi_pvt, mate, AST_DATA_BOOLEAN)       \
01287    MEMBER(dahdi_pvt, outgoing, AST_DATA_BOOLEAN)         \
01288    MEMBER(dahdi_pvt, permcallwaiting, AST_DATA_BOOLEAN)     \
01289    MEMBER(dahdi_pvt, priindication_oob, AST_DATA_BOOLEAN)      \
01290    MEMBER(dahdi_pvt, priexclusive, AST_DATA_BOOLEAN)     \
01291    MEMBER(dahdi_pvt, pulse, AST_DATA_BOOLEAN)         \
01292    MEMBER(dahdi_pvt, pulsedial, AST_DATA_BOOLEAN)        \
01293    MEMBER(dahdi_pvt, restartpending, AST_DATA_BOOLEAN)      \
01294    MEMBER(dahdi_pvt, restrictcid, AST_DATA_BOOLEAN)      \
01295    MEMBER(dahdi_pvt, threewaycalling, AST_DATA_BOOLEAN)     \
01296    MEMBER(dahdi_pvt, transfer, AST_DATA_BOOLEAN)         \
01297    MEMBER(dahdi_pvt, use_callerid, AST_DATA_BOOLEAN)     \
01298    MEMBER(dahdi_pvt, use_callingpres, AST_DATA_BOOLEAN)     \
01299    MEMBER(dahdi_pvt, usedistinctiveringdetection, AST_DATA_BOOLEAN)  \
01300    MEMBER(dahdi_pvt, dahditrcallerid, AST_DATA_BOOLEAN)        \
01301    MEMBER(dahdi_pvt, transfertobusy, AST_DATA_BOOLEAN)         \
01302    MEMBER(dahdi_pvt, mwimonitor_neon, AST_DATA_BOOLEAN)        \
01303    MEMBER(dahdi_pvt, mwimonitor_fsk, AST_DATA_BOOLEAN)         \
01304    MEMBER(dahdi_pvt, mwimonitor_rpas, AST_DATA_BOOLEAN)        \
01305    MEMBER(dahdi_pvt, mwimonitoractive, AST_DATA_BOOLEAN)       \
01306    MEMBER(dahdi_pvt, mwisendactive, AST_DATA_BOOLEAN)       \
01307    MEMBER(dahdi_pvt, inservice, AST_DATA_BOOLEAN)           \
01308    MEMBER(dahdi_pvt, locallyblocked, AST_DATA_BOOLEAN)         \
01309    MEMBER(dahdi_pvt, remotelyblocked, AST_DATA_BOOLEAN)        \
01310    MEMBER(dahdi_pvt, manages_span_alarms, AST_DATA_BOOLEAN)    \
01311    MEMBER(dahdi_pvt, use_smdi, AST_DATA_BOOLEAN)            \
01312    MEMBER(dahdi_pvt, context, AST_DATA_STRING)           \
01313    MEMBER(dahdi_pvt, defcontext, AST_DATA_STRING)           \
01314    MEMBER(dahdi_pvt, exten, AST_DATA_STRING)          \
01315    MEMBER(dahdi_pvt, language, AST_DATA_STRING)          \
01316    MEMBER(dahdi_pvt, mohinterpret, AST_DATA_STRING)         \
01317    MEMBER(dahdi_pvt, mohsuggest, AST_DATA_STRING)           \
01318    MEMBER(dahdi_pvt, parkinglot, AST_DATA_STRING)
01319 
01320 AST_DATA_STRUCTURE(dahdi_pvt, DATA_EXPORT_DAHDI_PVT);
01321 
01322 static struct dahdi_pvt *iflist = NULL;   /*!< Main interface list start */
01323 static struct dahdi_pvt *ifend = NULL; /*!< Main interface list end */
01324 
01325 #if defined(HAVE_PRI)
01326 static struct dahdi_parms_pseudo {
01327    int buf_no;             /*!< Number of buffers */
01328    int buf_policy;            /*!< Buffer policy */
01329    int faxbuf_no;              /*!< Number of Fax buffers */
01330    int faxbuf_policy;          /*!< Fax buffer policy */
01331 } dahdi_pseudo_parms;
01332 #endif   /* defined(HAVE_PRI) */
01333 
01334 /*! \brief Channel configuration from chan_dahdi.conf .
01335  * This struct is used for parsing the [channels] section of chan_dahdi.conf.
01336  * Generally there is a field here for every possible configuration item.
01337  *
01338  * The state of fields is saved along the parsing and whenever a 'channel'
01339  * statement is reached, the current dahdi_chan_conf is used to configure the
01340  * channel (struct dahdi_pvt)
01341  *
01342  * \see dahdi_chan_init for the default values.
01343  */
01344 struct dahdi_chan_conf {
01345    struct dahdi_pvt chan;
01346 #ifdef HAVE_PRI
01347    struct dahdi_pri pri;
01348 #endif
01349 
01350 #if defined(HAVE_SS7)
01351    struct dahdi_ss7 ss7;
01352 #endif   /* defined(HAVE_SS7) */
01353 
01354 #ifdef HAVE_OPENR2
01355    struct dahdi_mfcr2_conf mfcr2;
01356 #endif
01357    struct dahdi_params timing;
01358    int is_sig_auto; /*!< Use channel signalling from DAHDI? */
01359    /*! Continue configuration even if a channel is not there. */
01360    int ignore_failed_channels;
01361 
01362    /*!
01363     * \brief The serial port to listen for SMDI data on
01364     * \note Set from the "smdiport" string read in from chan_dahdi.conf
01365     */
01366    char smdi_port[SMDI_MAX_FILENAME_LEN];
01367 };
01368 
01369 /*! returns a new dahdi_chan_conf with default values (by-value) */
01370 static struct dahdi_chan_conf dahdi_chan_conf_default(void)
01371 {
01372    /* recall that if a field is not included here it is initialized
01373     * to 0 or equivalent
01374     */
01375    struct dahdi_chan_conf conf = {
01376 #ifdef HAVE_PRI
01377       .pri.pri = {
01378          .nsf = PRI_NSF_NONE,
01379          .switchtype = PRI_SWITCH_NI2,
01380          .dialplan = PRI_UNKNOWN + 1,
01381          .localdialplan = PRI_NATIONAL_ISDN + 1,
01382          .nodetype = PRI_CPE,
01383          .qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL,
01384          .inband_on_setup_ack = 1,
01385          .inband_on_proceeding = 1,
01386 
01387 #if defined(HAVE_PRI_CCSS)
01388          .cc_ptmp_recall_mode = 1,/* specificRecall */
01389          .cc_qsig_signaling_link_req = 1,/* retain */
01390          .cc_qsig_signaling_link_rsp = 1,/* retain */
01391 #endif   /* defined(HAVE_PRI_CCSS) */
01392 
01393          .minunused = 2,
01394          .idleext = "",
01395          .idledial = "",
01396          .internationalprefix = "",
01397          .nationalprefix = "",
01398          .localprefix = "",
01399          .privateprefix = "",
01400          .unknownprefix = "",
01401          .resetinterval = -1,
01402       },
01403 #endif
01404 #if defined(HAVE_SS7)
01405       .ss7.ss7 = {
01406          .called_nai = SS7_NAI_NATIONAL,
01407          .calling_nai = SS7_NAI_NATIONAL,
01408          .internationalprefix = "",
01409          .nationalprefix = "",
01410          .subscriberprefix = "",
01411          .unknownprefix = ""
01412       },
01413 #endif   /* defined(HAVE_SS7) */
01414 #ifdef HAVE_OPENR2
01415       .mfcr2 = {
01416          .variant = OR2_VAR_ITU,
01417          .mfback_timeout = -1,
01418          .metering_pulse_timeout = -1,
01419          .max_ani = 10,
01420          .max_dnis = 4,
01421          .get_ani_first = -1,
01422 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
01423          .skip_category_request = -1,
01424 #endif
01425          .call_files = 0,
01426          .allow_collect_calls = 0,
01427          .charge_calls = 1,
01428          .accept_on_offer = 1,
01429          .forced_release = 0,
01430          .double_answer = 0,
01431          .immediate_accept = -1,
01432          .logdir = "",
01433          .r2proto_file = "",
01434          .loglevel = OR2_LOG_ERROR | OR2_LOG_WARNING,
01435          .category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER
01436       },
01437 #endif
01438       .chan = {
01439          .context = "default",
01440          .cid_num = "",
01441          .cid_name = "",
01442          .cid_tag = "",
01443          .mohinterpret = "default",
01444          .mohsuggest = "",
01445          .parkinglot = "",
01446          .transfertobusy = 1,
01447 
01448          .cid_signalling = CID_SIG_BELL,
01449          .cid_start = CID_START_RING,
01450          .dahditrcallerid = 0,
01451          .use_callerid = 1,
01452          .sig = -1,
01453          .outsigmod = -1,
01454 
01455          .cid_rxgain = +5.0,
01456 
01457          .tonezone = -1,
01458 
01459          .echocancel.head.tap_length = 1,
01460 
01461          .busycount = 3,
01462          .busycompare = 0,
01463          .busytonelength = 0,
01464          .busyquietlength = 0,
01465          .busyfuzziness = 0,
01466          .silencethreshold = 0,
01467 
01468          .accountcode = "",
01469 
01470          .mailbox = "",
01471 
01472 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
01473          .mwisend_fsk = 1,
01474 #endif
01475          .polarityonanswerdelay = 600,
01476 
01477          .sendcalleridafter = DEFAULT_CIDRINGS,
01478 
01479          .buf_policy = DAHDI_POLICY_IMMEDIATE,
01480          .buf_no = numbufs,
01481          .usefaxbuffers = 0,
01482          .cc_params = ast_cc_config_params_init(),
01483       },
01484       .timing = {
01485          .prewinktime = -1,
01486          .preflashtime = -1,
01487          .winktime = -1,
01488          .flashtime = -1,
01489          .starttime = -1,
01490          .rxwinktime = -1,
01491          .rxflashtime = -1,
01492          .debouncetime = -1
01493       },
01494       .is_sig_auto = 1,
01495       .smdi_port = "/dev/ttyS0",
01496    };
01497 
01498    return conf;
01499 }
01500 
01501 
01502 static struct ast_channel *dahdi_request(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause);
01503 static int dahdi_digit_begin(struct ast_channel *ast, char digit);
01504 static int dahdi_digit_end(struct ast_channel *ast, char digit, unsigned int duration);
01505 static int dahdi_sendtext(struct ast_channel *c, const char *text);
01506 static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout);
01507 static int dahdi_hangup(struct ast_channel *ast);
01508 static int dahdi_answer(struct ast_channel *ast);
01509 static struct ast_frame *dahdi_read(struct ast_channel *ast);
01510 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame);
01511 static struct ast_frame *dahdi_exception(struct ast_channel *ast);
01512 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen);
01513 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
01514 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen);
01515 static int dahdi_queryoption(struct ast_channel *chan, int option, void *data, int *datalen);
01516 static int dahdi_func_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len);
01517 static int dahdi_func_write(struct ast_channel *chan, const char *function, char *data, const char *value);
01518 static int dahdi_devicestate(void *data);
01519 static int dahdi_cc_callback(struct ast_channel *inbound, const char *dest, ast_cc_callback_fn callback);
01520 
01521 static const struct ast_channel_tech dahdi_tech = {
01522    .type = "DAHDI",
01523    .description = tdesc,
01524    .capabilities = AST_FORMAT_SLINEAR | AST_FORMAT_ULAW | AST_FORMAT_ALAW,
01525    .requester = dahdi_request,
01526    .send_digit_begin = dahdi_digit_begin,
01527    .send_digit_end = dahdi_digit_end,
01528    .send_text = dahdi_sendtext,
01529    .call = dahdi_call,
01530    .hangup = dahdi_hangup,
01531    .answer = dahdi_answer,
01532    .read = dahdi_read,
01533    .write = dahdi_write,
01534    .bridge = dahdi_bridge,
01535    .exception = dahdi_exception,
01536    .indicate = dahdi_indicate,
01537    .fixup = dahdi_fixup,
01538    .setoption = dahdi_setoption,
01539    .queryoption = dahdi_queryoption,
01540    .func_channel_read = dahdi_func_read,
01541    .func_channel_write = dahdi_func_write,
01542    .devicestate = dahdi_devicestate,
01543    .cc_callback = dahdi_cc_callback,
01544 };
01545 
01546 #define GET_CHANNEL(p) ((p)->channel)
01547 
01548 #define SIG_PRI_LIB_HANDLE_CASES \
01549    SIG_PRI:                \
01550    case SIG_BRI:              \
01551    case SIG_BRI_PTMP
01552 
01553 /*!
01554  * \internal
01555  * \brief Determine if sig_pri handles the signaling.
01556  * \since 1.8
01557  *
01558  * \param signaling Signaling to determine if is for sig_pri.
01559  *
01560  * \return TRUE if the signaling is for sig_pri.
01561  */
01562 static inline int dahdi_sig_pri_lib_handles(int signaling)
01563 {
01564    int handles;
01565 
01566    switch (signaling) {
01567    case SIG_PRI_LIB_HANDLE_CASES:
01568       handles = 1;
01569       break;
01570    default:
01571       handles = 0;
01572       break;
01573    }
01574 
01575    return handles;
01576 }
01577 
01578 static int analog_lib_handles(int signalling, int radio, int oprmode)
01579 {
01580    switch (signalling) {
01581    case SIG_FXOLS:
01582    case SIG_FXOGS:
01583    case SIG_FXOKS:
01584    case SIG_FXSLS:
01585    case SIG_FXSGS:
01586    case SIG_FXSKS:
01587    case SIG_EMWINK:
01588    case SIG_EM:
01589    case SIG_EM_E1:
01590    case SIG_FEATD:
01591    case SIG_FEATDMF:
01592    case SIG_E911:
01593    case SIG_FGC_CAMA:
01594    case SIG_FGC_CAMAMF:
01595    case SIG_FEATB:
01596    case SIG_SFWINK:
01597    case SIG_SF:
01598    case SIG_SF_FEATD:
01599    case SIG_SF_FEATDMF:
01600    case SIG_FEATDMF_TA:
01601    case SIG_SF_FEATB:
01602       break;
01603    default:
01604       /* The rest of the function should cover the remainder of signalling types */
01605       return 0;
01606    }
01607 
01608    if (radio) {
01609       return 0;
01610    }
01611 
01612    if (oprmode) {
01613       return 0;
01614    }
01615 
01616    return 1;
01617 }
01618 
01619 static enum analog_sigtype dahdisig_to_analogsig(int sig)
01620 {
01621    switch (sig) {
01622    case SIG_FXOLS:
01623       return ANALOG_SIG_FXOLS;
01624    case SIG_FXOGS:
01625       return ANALOG_SIG_FXOGS;
01626    case SIG_FXOKS:
01627       return ANALOG_SIG_FXOKS;
01628    case SIG_FXSLS:
01629       return ANALOG_SIG_FXSLS;
01630    case SIG_FXSGS:
01631       return ANALOG_SIG_FXSGS;
01632    case SIG_FXSKS:
01633       return ANALOG_SIG_FXSKS;
01634    case SIG_EMWINK:
01635       return ANALOG_SIG_EMWINK;
01636    case SIG_EM:
01637       return ANALOG_SIG_EM;
01638    case SIG_EM_E1:
01639       return ANALOG_SIG_EM_E1;
01640    case SIG_FEATD:
01641       return ANALOG_SIG_FEATD;
01642    case SIG_FEATDMF:
01643       return ANALOG_SIG_FEATDMF;
01644    case SIG_E911:
01645       return SIG_E911;
01646    case SIG_FGC_CAMA:
01647       return ANALOG_SIG_FGC_CAMA;
01648    case SIG_FGC_CAMAMF:
01649       return ANALOG_SIG_FGC_CAMAMF;
01650    case SIG_FEATB:
01651       return ANALOG_SIG_FEATB;
01652    case SIG_SFWINK:
01653       return ANALOG_SIG_SFWINK;
01654    case SIG_SF:
01655       return ANALOG_SIG_SF;
01656    case SIG_SF_FEATD:
01657       return ANALOG_SIG_SF_FEATD;
01658    case SIG_SF_FEATDMF:
01659       return ANALOG_SIG_SF_FEATDMF;
01660    case SIG_FEATDMF_TA:
01661       return ANALOG_SIG_FEATDMF_TA;
01662    case SIG_SF_FEATB:
01663       return ANALOG_SIG_FEATB;
01664    default:
01665       return -1;
01666    }
01667 }
01668 
01669 
01670 static int analog_tone_to_dahditone(enum analog_tone tone)
01671 {
01672    switch (tone) {
01673    case ANALOG_TONE_RINGTONE:
01674       return DAHDI_TONE_RINGTONE;
01675    case ANALOG_TONE_STUTTER:
01676       return DAHDI_TONE_STUTTER;
01677    case ANALOG_TONE_CONGESTION:
01678       return DAHDI_TONE_CONGESTION;
01679    case ANALOG_TONE_DIALTONE:
01680       return DAHDI_TONE_DIALTONE;
01681    case ANALOG_TONE_DIALRECALL:
01682       return DAHDI_TONE_DIALRECALL;
01683    case ANALOG_TONE_INFO:
01684       return DAHDI_TONE_INFO;
01685    default:
01686       return -1;
01687    }
01688 }
01689 
01690 static int analogsub_to_dahdisub(enum analog_sub analogsub)
01691 {
01692    int index;
01693 
01694    switch (analogsub) {
01695    case ANALOG_SUB_REAL:
01696       index = SUB_REAL;
01697       break;
01698    case ANALOG_SUB_CALLWAIT:
01699       index = SUB_CALLWAIT;
01700       break;
01701    case ANALOG_SUB_THREEWAY:
01702       index = SUB_THREEWAY;
01703       break;
01704    default:
01705       ast_log(LOG_ERROR, "Unidentified sub!\n");
01706       index = SUB_REAL;
01707    }
01708 
01709    return index;
01710 }
01711 
01712 static enum analog_event dahdievent_to_analogevent(int event);
01713 static int bump_gains(struct dahdi_pvt *p);
01714 static int dahdi_setlinear(int dfd, int linear);
01715 
01716 static int my_start_cid_detect(void *pvt, int cid_signalling)
01717 {
01718    struct dahdi_pvt *p = pvt;
01719    int index = SUB_REAL;
01720    p->cs = callerid_new(cid_signalling);
01721    if (!p->cs) {
01722       ast_log(LOG_ERROR, "Unable to alloc callerid\n");
01723       return -1;
01724    }
01725    bump_gains(p);
01726    dahdi_setlinear(p->subs[index].dfd, 0);
01727 
01728    return 0;
01729 }
01730 
01731 static int my_stop_cid_detect(void *pvt)
01732 {
01733    struct dahdi_pvt *p = pvt;
01734    int index = SUB_REAL;
01735    if (p->cs)
01736       callerid_free(p->cs);
01737    dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
01738    return 0;
01739 }
01740 
01741 static int my_get_callerid(void *pvt, char *namebuf, char *numbuf, enum analog_event *ev, size_t timeout)
01742 {
01743    struct dahdi_pvt *p = pvt;
01744    struct analog_pvt *analog_p = p->sig_pvt;
01745    struct pollfd poller;
01746    char *name, *num;
01747    int index = SUB_REAL;
01748    int res;
01749    unsigned char buf[256];
01750    int flags;
01751 
01752    poller.fd = p->subs[SUB_REAL].dfd;
01753    poller.events = POLLPRI | POLLIN;
01754    poller.revents = 0;
01755 
01756    res = poll(&poller, 1, timeout);
01757 
01758    if (poller.revents & POLLPRI) {
01759       *ev = dahdievent_to_analogevent(dahdi_get_event(p->subs[SUB_REAL].dfd));
01760       return 1;
01761    }
01762 
01763    if (poller.revents & POLLIN) {
01764       /*** NOTES ***/
01765       /* Change API: remove cid_signalling from get_callerid, add a new start_cid_detect and stop_cid_detect function
01766        * to enable slin mode and allocate cid detector. get_callerid should be able to be called any number of times until
01767        * either a timeout occurs or CID is detected (returns 0). returning 1 should be event received, and -1 should be
01768        * a failure and die, and returning 2 means no event was received. */
01769       res = read(p->subs[index].dfd, buf, sizeof(buf));
01770       if (res < 0) {
01771          ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
01772          return -1;
01773       }
01774 
01775       if (analog_p->ringt > 0) {
01776          if (!(--analog_p->ringt)) {
01777             /* only return if we timeout from a ring event */
01778             return -1;
01779          }
01780       }
01781 
01782       if (p->cid_signalling == CID_SIG_V23_JP) {
01783          res = callerid_feed_jp(p->cs, buf, res, AST_LAW(p));
01784       } else {
01785          res = callerid_feed(p->cs, buf, res, AST_LAW(p));
01786       }
01787       if (res < 0) {
01788          /*
01789           * The previous diagnostic message output likely
01790           * explains why it failed.
01791           */
01792          ast_log(LOG_WARNING, "Failed to decode CallerID\n");
01793          return -1;
01794       }
01795 
01796       if (res == 1) {
01797          callerid_get(p->cs, &name, &num, &flags);
01798          if (name)
01799             ast_copy_string(namebuf, name, ANALOG_MAX_CID);
01800          if (num)
01801             ast_copy_string(numbuf, num, ANALOG_MAX_CID);
01802 
01803          ast_debug(1, "CallerID number: %s, name: %s, flags=%d\n", num, name, flags);
01804          return 0;
01805       }
01806    }
01807 
01808    *ev = ANALOG_EVENT_NONE;
01809    return 2;
01810 }
01811 
01812 static const char *event2str(int event);
01813 static int restore_gains(struct dahdi_pvt *p);
01814 
01815 static int my_distinctive_ring(struct ast_channel *chan, void *pvt, int idx, int *ringdata)
01816 {
01817    unsigned char buf[256];
01818    int distMatches;
01819    int curRingData[RING_PATTERNS];
01820    int receivedRingT;
01821    int counter1;
01822    int counter;
01823    int i;
01824    int res;
01825    int checkaftercid = 0;
01826 
01827    struct dahdi_pvt *p = pvt;
01828    struct analog_pvt *analog_p = p->sig_pvt;
01829 
01830    if (ringdata == NULL) {
01831       ringdata = curRingData;
01832    } else {
01833       checkaftercid = 1;
01834    }
01835 
01836    /* We must have a ring by now, so, if configured, lets try to listen for
01837     * distinctive ringing */
01838    if ((checkaftercid && distinctiveringaftercid) || !checkaftercid) {
01839       /* Clear the current ring data array so we don't have old data in it. */
01840       for (receivedRingT = 0; receivedRingT < RING_PATTERNS; receivedRingT++)
01841          ringdata[receivedRingT] = 0;
01842       receivedRingT = 0;
01843       if (checkaftercid && distinctiveringaftercid)
01844          ast_verb(3, "Detecting post-CID distinctive ring\n");
01845       /* Check to see if context is what it should be, if not set to be. */
01846       else if (strcmp(p->context,p->defcontext) != 0) {
01847          ast_copy_string(p->context, p->defcontext, sizeof(p->context));
01848          ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
01849       }
01850 
01851       for (;;) {
01852          i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
01853          if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
01854             ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
01855             ast_hangup(chan);
01856             return 1;
01857          }
01858          if (i & DAHDI_IOMUX_SIGEVENT) {
01859             res = dahdi_get_event(p->subs[idx].dfd);
01860             if (res == DAHDI_EVENT_NOALARM) {
01861                p->inalarm = 0;
01862                analog_p->inalarm = 0;
01863             }
01864             ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
01865             res = 0;
01866             /* Let us detect distinctive ring */
01867 
01868             ringdata[receivedRingT] = analog_p->ringt;
01869 
01870             if (analog_p->ringt < analog_p->ringt_base/2)
01871                break;
01872             /* Increment the ringT counter so we can match it against
01873                values in chan_dahdi.conf for distinctive ring */
01874             if (++receivedRingT == RING_PATTERNS)
01875                break;
01876          } else if (i & DAHDI_IOMUX_READ) {
01877             res = read(p->subs[idx].dfd, buf, sizeof(buf));
01878             if (res < 0) {
01879                if (errno != ELAST) {
01880                   ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
01881                   ast_hangup(chan);
01882                   return 1;
01883                }
01884                break;
01885             }
01886             if (analog_p->ringt > 0) {
01887                if (!(--analog_p->ringt)) {
01888                   res = -1;
01889                   break;
01890                }
01891             }
01892          }
01893       }
01894    }
01895    if ((checkaftercid && usedistinctiveringdetection) || !checkaftercid) {
01896       /* this only shows up if you have n of the dring patterns filled in */
01897       ast_verb(3, "Detected ring pattern: %d,%d,%d\n",ringdata[0],ringdata[1],ringdata[2]);
01898       for (counter = 0; counter < 3; counter++) {
01899       /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this channel */
01900          distMatches = 0;
01901          /* this only shows up if you have n of the dring patterns filled in */
01902          ast_verb(3, "Checking %d,%d,%d\n",
01903                p->drings.ringnum[counter].ring[0],
01904                p->drings.ringnum[counter].ring[1],
01905                p->drings.ringnum[counter].ring[2]);
01906          for (counter1 = 0; counter1 < 3; counter1++) {
01907             ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
01908             if (p->drings.ringnum[counter].ring[counter1] == -1) {
01909                ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
01910                ringdata[counter1]);
01911                distMatches++;
01912             } else if (ringdata[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
01913                               ringdata[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
01914                ast_verb(3, "Ring pattern matched in range: %d to %d\n",
01915                (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
01916                (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
01917                distMatches++;
01918             }
01919          }
01920 
01921          if (distMatches == 3) {
01922             /* The ring matches, set the context to whatever is for distinctive ring.. */
01923             ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context));
01924             ast_copy_string(chan->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(chan->context));
01925             ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
01926             break;
01927          }
01928       }
01929    }
01930    /* Restore linear mode (if appropriate) for Caller*ID processing */
01931    dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
01932    restore_gains(p);
01933 
01934    return 0;
01935 }
01936 
01937 static int my_stop_callwait(void *pvt)
01938 {
01939    struct dahdi_pvt *p = pvt;
01940    p->callwaitingrepeat = 0;
01941    p->cidcwexpire = 0;
01942    p->cid_suppress_expire = 0;
01943 
01944    return 0;
01945 }
01946 
01947 static int send_callerid(struct dahdi_pvt *p);
01948 static int save_conference(struct dahdi_pvt *p);
01949 static int restore_conference(struct dahdi_pvt *p);
01950 
01951 static int my_callwait(void *pvt)
01952 {
01953    struct dahdi_pvt *p = pvt;
01954    p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
01955    if (p->cidspill) {
01956       ast_log(LOG_WARNING, "Spill already exists?!?\n");
01957       ast_free(p->cidspill);
01958    }
01959 
01960    /*
01961     * SAS: Subscriber Alert Signal, 440Hz for 300ms
01962     * CAS: CPE Alert Signal, 2130Hz * 2750Hz sine waves
01963     */
01964    if (!(p->cidspill = ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE * 4)))
01965       return -1;
01966    save_conference(p);
01967    /* Silence */
01968    memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
01969    if (!p->callwaitrings && p->callwaitingcallerid) {
01970       ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
01971       p->callwaitcas = 1;
01972       p->cidlen = 2400 + 680 + READ_SIZE * 4;
01973    } else {
01974       ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
01975       p->callwaitcas = 0;
01976       p->cidlen = 2400 + READ_SIZE * 4;
01977    }
01978    p->cidpos = 0;
01979    send_callerid(p);
01980 
01981    return 0;
01982 }
01983 
01984 static int my_send_callerid(void *pvt, int cwcid, struct ast_party_caller *caller)
01985 {
01986    struct dahdi_pvt *p = pvt;
01987 
01988    ast_debug(2, "Starting cid spill\n");
01989 
01990    if (p->cidspill) {
01991       ast_log(LOG_WARNING, "cidspill already exists??\n");
01992       ast_free(p->cidspill);
01993    }
01994 
01995    if ((p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) {
01996       if (cwcid == 0) {
01997          p->cidlen = ast_callerid_generate(p->cidspill,
01998             caller->id.name.str,
01999             caller->id.number.str,
02000             AST_LAW(p));
02001       } else {
02002          ast_verb(3, "CPE supports Call Waiting Caller*ID.  Sending '%s/%s'\n",
02003             caller->id.name.str, caller->id.number.str);
02004          p->callwaitcas = 0;
02005          p->cidcwexpire = 0;
02006          p->cidlen = ast_callerid_callwaiting_generate(p->cidspill,
02007             caller->id.name.str,
02008             caller->id.number.str,
02009             AST_LAW(p));
02010          p->cidlen += READ_SIZE * 4;
02011       }
02012       p->cidpos = 0;
02013       p->cid_suppress_expire = 0;
02014       send_callerid(p);
02015    }
02016    return 0;
02017 }
02018 
02019 static int my_dsp_reset_and_flush_digits(void *pvt)
02020 {
02021    struct dahdi_pvt *p = pvt;
02022    if (p->dsp)
02023       ast_dsp_digitreset(p->dsp);
02024 
02025    return 0;
02026 }
02027 
02028 static int my_dsp_set_digitmode(void *pvt, enum analog_dsp_digitmode mode)
02029 {
02030    struct dahdi_pvt *p = pvt;
02031 
02032    if (p->channel == CHAN_PSEUDO)
02033       ast_log(LOG_ERROR, "You have assumed incorrectly sir!\n");
02034 
02035    if (mode == ANALOG_DIGITMODE_DTMF) {
02036       /* If we do hardware dtmf, no need for a DSP */
02037       if (p->hardwaredtmf) {
02038          if (p->dsp) {
02039             ast_dsp_free(p->dsp);
02040             p->dsp = NULL;
02041          }
02042          return 0;
02043       }
02044 
02045       if (!p->dsp) {
02046          p->dsp = ast_dsp_new();
02047          if (!p->dsp) {
02048             ast_log(LOG_ERROR, "Unable to allocate DSP\n");
02049             return -1;
02050          }
02051       }
02052 
02053       ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
02054    } else if (mode == ANALOG_DIGITMODE_MF) {
02055       if (!p->dsp) {
02056          p->dsp = ast_dsp_new();
02057          if (!p->dsp) {
02058             ast_log(LOG_ERROR, "Unable to allocate DSP\n");
02059             return -1;
02060          }
02061       }
02062       ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
02063    }
02064    return 0;
02065 }
02066 
02067 static int dahdi_wink(struct dahdi_pvt *p, int index);
02068 
02069 static int my_wink(void *pvt, enum analog_sub sub)
02070 {
02071    struct dahdi_pvt *p = pvt;
02072    int index = analogsub_to_dahdisub(sub);
02073    if (index != SUB_REAL) {
02074       ast_log(LOG_ERROR, "We used a sub other than SUB_REAL (incorrect assumption sir)\n");
02075    }
02076    return dahdi_wink(p, index);
02077 }
02078 
02079 static void wakeup_sub(struct dahdi_pvt *p, int a);
02080 
02081 static int reset_conf(struct dahdi_pvt *p);
02082 
02083 static inline int dahdi_confmute(struct dahdi_pvt *p, int muted);
02084 
02085 static void my_handle_dtmf(void *pvt, struct ast_channel *ast, enum analog_sub analog_index, struct ast_frame **dest)
02086 {
02087    struct ast_frame *f = *dest;
02088    struct dahdi_pvt *p = pvt;
02089    int idx = analogsub_to_dahdisub(analog_index);
02090 
02091    ast_debug(1, "%s DTMF digit: 0x%02X '%c' on %s\n",
02092       f->frametype == AST_FRAME_DTMF_BEGIN ? "Begin" : "End",
02093       (unsigned)f->subclass.integer, f->subclass.integer, ast->name);
02094 
02095    if (f->subclass.integer == 'f') {
02096       if (f->frametype == AST_FRAME_DTMF_END) {
02097          /* Fax tone -- Handle and return NULL */
02098          if ((p->callprogress & CALLPROGRESS_FAX) && !p->faxhandled) {
02099             /* If faxbuffers are configured, use them for the fax transmission */
02100             if (p->usefaxbuffers && !p->bufferoverrideinuse) {
02101                struct dahdi_bufferinfo bi = {
02102                   .txbufpolicy = p->faxbuf_policy,
02103                   .bufsize = p->bufsize,
02104                   .numbufs = p->faxbuf_no
02105                };
02106                int res;
02107 
02108                if ((res = ioctl(p->subs[idx].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
02109                   ast_log(LOG_WARNING, "Channel '%s' unable to set buffer policy, reason: %s\n", ast->name, strerror(errno));
02110                } else {
02111                   p->bufferoverrideinuse = 1;
02112                }
02113             }
02114             p->faxhandled = 1;
02115             if (p->dsp) {
02116                p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
02117                ast_dsp_set_features(p->dsp, p->dsp_features);
02118                ast_debug(1, "Disabling FAX tone detection on %s after tone received\n", ast->name);
02119             }
02120             if (strcmp(ast->exten, "fax")) {
02121                const char *target_context = S_OR(ast->macrocontext, ast->context);
02122 
02123                /* We need to unlock 'ast' here because ast_exists_extension has the
02124                 * potential to start autoservice on the channel. Such action is prone
02125                 * to deadlock.
02126                 */
02127                ast_mutex_unlock(&p->lock);
02128                ast_channel_unlock(ast);
02129                if (ast_exists_extension(ast, target_context, "fax", 1,
02130                   S_COR(ast->caller.id.number.valid, ast->caller.id.number.str, NULL))) {
02131                   ast_channel_lock(ast);
02132                   ast_mutex_lock(&p->lock);
02133                   ast_verb(3, "Redirecting %s to fax extension\n", ast->name);
02134                   /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
02135                   pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten);
02136                   if (ast_async_goto(ast, target_context, "fax", 1))
02137                      ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context);
02138                } else {
02139                   ast_channel_lock(ast);
02140                   ast_mutex_lock(&p->lock);
02141                   ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
02142                }
02143             } else {
02144                ast_debug(1, "Already in a fax extension, not redirecting\n");
02145             }
02146          } else {
02147             ast_debug(1, "Fax already handled\n");
02148          }
02149          dahdi_confmute(p, 0);
02150       }
02151       p->subs[idx].f.frametype = AST_FRAME_NULL;
02152       p->subs[idx].f.subclass.integer = 0;
02153       *dest = &p->subs[idx].f;
02154    }
02155 }
02156 
02157 static void my_lock_private(void *pvt)
02158 {
02159    struct dahdi_pvt *p = pvt;
02160    ast_mutex_lock(&p->lock);
02161 }
02162 
02163 static void my_unlock_private(void *pvt)
02164 {
02165    struct dahdi_pvt *p = pvt;
02166    ast_mutex_unlock(&p->lock);
02167 }
02168 
02169 static void my_deadlock_avoidance_private(void *pvt)
02170 {
02171    struct dahdi_pvt *p = pvt;
02172 
02173    DEADLOCK_AVOIDANCE(&p->lock);
02174 }
02175 
02176 /*!
02177  * \internal
02178  * \brief Post an AMI DAHDI channel association event.
02179  * \since 1.8
02180  *
02181  * \param p DAHDI private pointer
02182  * \param chan Channel associated with the private pointer
02183  *
02184  * \return Nothing
02185  */
02186 static void dahdi_ami_channel_event(struct dahdi_pvt *p, struct ast_channel *chan)
02187 {
02188    char ch_name[20];
02189 
02190    if (p->channel < CHAN_PSEUDO) {
02191       /* No B channel */
02192       snprintf(ch_name, sizeof(ch_name), "no-media (%d)", p->channel);
02193    } else if (p->channel == CHAN_PSEUDO) {
02194       /* Pseudo channel */
02195       strcpy(ch_name, "pseudo");
02196    } else {
02197       /* Real channel */
02198       snprintf(ch_name, sizeof(ch_name), "%d", p->channel);
02199    }
02200    ast_manager_event(chan, EVENT_FLAG_CALL, "DAHDIChannel",
02201       "Channel: %s\r\n"
02202       "Uniqueid: %s\r\n"
02203       "DAHDISpan: %d\r\n"
02204       "DAHDIChannel: %s\r\n",
02205       chan->name,
02206       chan->uniqueid,
02207       p->span,
02208       ch_name);
02209 }
02210 
02211 #ifdef HAVE_PRI
02212 /*!
02213  * \internal
02214  * \brief Post an AMI DAHDI channel association event.
02215  * \since 1.8
02216  *
02217  * \param pvt DAHDI private pointer
02218  * \param chan Channel associated with the private pointer
02219  *
02220  * \return Nothing
02221  */
02222 static void my_ami_channel_event(void *pvt, struct ast_channel *chan)
02223 {
02224    struct dahdi_pvt *p = pvt;
02225 
02226    dahdi_ami_channel_event(p, chan);
02227 }
02228 #endif
02229 
02230 /* linear_mode = 0 - turn linear mode off, >0 - turn linear mode on
02231 *  returns the last value of the linear setting 
02232 */ 
02233 static int my_set_linear_mode(void *pvt, enum analog_sub sub, int linear_mode)
02234 {
02235    struct dahdi_pvt *p = pvt;
02236    int oldval;
02237    int idx = analogsub_to_dahdisub(sub);
02238    
02239    dahdi_setlinear(p->subs[idx].dfd, linear_mode);
02240    oldval = p->subs[idx].linear;
02241    p->subs[idx].linear = linear_mode ? 1 : 0;
02242    return oldval;
02243 }
02244 
02245 static void my_set_inthreeway(void *pvt, enum analog_sub sub, int inthreeway)
02246 {
02247    struct dahdi_pvt *p = pvt;
02248    int idx = analogsub_to_dahdisub(sub);
02249 
02250    p->subs[idx].inthreeway = inthreeway;
02251 }
02252 
02253 static int get_alarms(struct dahdi_pvt *p);
02254 static void handle_alarms(struct dahdi_pvt *p, int alms);
02255 static void my_get_and_handle_alarms(void *pvt)
02256 {
02257    int res;
02258    struct dahdi_pvt *p = pvt;
02259 
02260    res = get_alarms(p);
02261    handle_alarms(p, res);
02262 }
02263 
02264 static void *my_get_sigpvt_bridged_channel(struct ast_channel *chan)
02265 {
02266    struct ast_channel *bridged = ast_bridged_channel(chan);
02267 
02268    if (bridged && bridged->tech == &dahdi_tech) {
02269       struct dahdi_pvt *p = bridged->tech_pvt;
02270 
02271       if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
02272          return p->sig_pvt;
02273       }
02274    }
02275    return NULL;
02276 }
02277 
02278 static int my_get_sub_fd(void *pvt, enum analog_sub sub)
02279 {
02280    struct dahdi_pvt *p = pvt;
02281    int dahdi_sub = analogsub_to_dahdisub(sub);
02282    return p->subs[dahdi_sub].dfd;
02283 }
02284 
02285 static void my_set_cadence(void *pvt, int *cid_rings, struct ast_channel *ast)
02286 {
02287    struct dahdi_pvt *p = pvt;
02288 
02289    /* Choose proper cadence */
02290    if ((p->distinctivering > 0) && (p->distinctivering <= num_cadence)) {
02291       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &cadences[p->distinctivering - 1]))
02292          ast_log(LOG_WARNING, "Unable to set distinctive ring cadence %d on '%s': %s\n", p->distinctivering, ast->name, strerror(errno));
02293       *cid_rings = cidrings[p->distinctivering - 1];
02294    } else {
02295       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, NULL))
02296          ast_log(LOG_WARNING, "Unable to reset default ring on '%s': %s\n", ast->name, strerror(errno));
02297       *cid_rings = p->sendcalleridafter;
02298    }
02299 }
02300 
02301 static void my_set_alarm(void *pvt, int in_alarm)
02302 {
02303    struct dahdi_pvt *p = pvt;
02304 
02305    p->inalarm = in_alarm;
02306 }
02307 
02308 static void my_set_dialing(void *pvt, int is_dialing)
02309 {
02310    struct dahdi_pvt *p = pvt;
02311 
02312    p->dialing = is_dialing;
02313 }
02314 
02315 static void my_set_outgoing(void *pvt, int is_outgoing)
02316 {
02317    struct dahdi_pvt *p = pvt;
02318 
02319    p->outgoing = is_outgoing;
02320 }
02321 
02322 #if defined(HAVE_PRI) || defined(HAVE_SS7)
02323 static void my_set_digital(void *pvt, int is_digital)
02324 {
02325    struct dahdi_pvt *p = pvt;
02326 
02327    p->digital = is_digital;
02328 }
02329 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
02330 
02331 #if defined(HAVE_SS7)
02332 static void my_set_inservice(void *pvt, int is_inservice)
02333 {
02334    struct dahdi_pvt *p = pvt;
02335 
02336    p->inservice = is_inservice;
02337 }
02338 #endif   /* defined(HAVE_SS7) */
02339 
02340 #if defined(HAVE_SS7)
02341 static void my_set_locallyblocked(void *pvt, int is_blocked)
02342 {
02343    struct dahdi_pvt *p = pvt;
02344 
02345    p->locallyblocked = is_blocked;
02346 }
02347 #endif   /* defined(HAVE_SS7) */
02348 
02349 #if defined(HAVE_SS7)
02350 static void my_set_remotelyblocked(void *pvt, int is_blocked)
02351 {
02352    struct dahdi_pvt *p = pvt;
02353 
02354    p->remotelyblocked = is_blocked;
02355 }
02356 #endif   /* defined(HAVE_SS7) */
02357 
02358 static void my_set_ringtimeout(void *pvt, int ringt)
02359 {
02360    struct dahdi_pvt *p = pvt;
02361    p->ringt = ringt;
02362 }
02363 
02364 static void my_set_waitingfordt(void *pvt, struct ast_channel *ast)
02365 {
02366    struct dahdi_pvt *p = pvt;
02367 
02368    if (p->waitfordialtone && CANPROGRESSDETECT(p) && p->dsp) {
02369       ast_log(LOG_DEBUG, "Defer dialing for %dms or dialtone\n", p->waitfordialtone);
02370       gettimeofday(&p->waitingfordt, NULL);
02371       ast_setstate(ast, AST_STATE_OFFHOOK);
02372    }
02373 }
02374 
02375 static int my_check_waitingfordt(void *pvt)
02376 {
02377    struct dahdi_pvt *p = pvt;
02378 
02379    if (p->waitingfordt.tv_sec) {
02380       return 1;
02381    }
02382 
02383    return 0;
02384 }
02385 
02386 static void my_set_confirmanswer(void *pvt, int flag)
02387 {
02388    struct dahdi_pvt *p = pvt;
02389    p->confirmanswer = flag;
02390 }
02391 
02392 static int my_check_confirmanswer(void *pvt)
02393 {
02394    struct dahdi_pvt *p = pvt;
02395    if (p->confirmanswer) {
02396       return 1;
02397    }
02398 
02399    return 0;
02400 }
02401 
02402 static void my_set_callwaiting(void *pvt, int callwaiting_enable)
02403 {
02404    struct dahdi_pvt *p = pvt;
02405 
02406    p->callwaiting = callwaiting_enable;
02407 }
02408 
02409 static void my_cancel_cidspill(void *pvt)
02410 {
02411    struct dahdi_pvt *p = pvt;
02412 
02413    ast_free(p->cidspill);
02414    p->cidspill = NULL;
02415    restore_conference(p);
02416 }
02417 
02418 static int my_confmute(void *pvt, int mute)
02419 {
02420    struct dahdi_pvt *p = pvt;
02421    return dahdi_confmute(p, mute);
02422 }
02423 
02424 static void my_set_pulsedial(void *pvt, int flag)
02425 {
02426    struct dahdi_pvt *p = pvt;
02427    p->pulsedial = flag;
02428 }
02429 
02430 static void my_set_new_owner(void *pvt, struct ast_channel *new_owner)
02431 {
02432    struct dahdi_pvt *p = pvt;
02433 
02434    p->owner = new_owner;
02435 }
02436 
02437 static const char *my_get_orig_dialstring(void *pvt)
02438 {
02439    struct dahdi_pvt *p = pvt;
02440 
02441    return p->dialstring;
02442 }
02443 
02444 static void my_increase_ss_count(void)
02445 {
02446    ast_mutex_lock(&ss_thread_lock);
02447    ss_thread_count++;
02448    ast_mutex_unlock(&ss_thread_lock);
02449 }
02450 
02451 static void my_decrease_ss_count(void)
02452 {
02453    ast_mutex_lock(&ss_thread_lock);
02454    ss_thread_count--;
02455    ast_cond_signal(&ss_thread_complete);
02456    ast_mutex_unlock(&ss_thread_lock);
02457 }
02458 
02459 static void my_all_subchannels_hungup(void *pvt)
02460 {
02461    struct dahdi_pvt *p = pvt;
02462    int res, law;
02463 
02464    p->faxhandled = 0;
02465    p->didtdd = 0;
02466 
02467    if (p->dsp) {
02468       ast_dsp_free(p->dsp);
02469       p->dsp = NULL;
02470    }
02471 
02472    p->law = p->law_default;
02473    law = p->law_default;
02474    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
02475    if (res < 0)
02476       ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
02477 
02478    dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
02479 
02480 #if 1
02481    {
02482    int i;
02483    p->owner = NULL;
02484    /* Cleanup owners here */
02485    for (i = 0; i < 3; i++) {
02486       p->subs[i].owner = NULL;
02487    }
02488    }
02489 #endif
02490 
02491    reset_conf(p);
02492    if (num_restart_pending == 0) {
02493       restart_monitor();
02494    }
02495 }
02496 
02497 static int conf_del(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index);
02498 
02499 static int my_conf_del(void *pvt, enum analog_sub sub)
02500 {
02501    struct dahdi_pvt *p = pvt;
02502    int x = analogsub_to_dahdisub(sub);
02503 
02504    return conf_del(p, &p->subs[x], x);
02505 }
02506 
02507 static int conf_add(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index, int slavechannel);
02508 
02509 static int my_conf_add(void *pvt, enum analog_sub sub)
02510 {
02511    struct dahdi_pvt *p = pvt;
02512    int x = analogsub_to_dahdisub(sub);
02513 
02514    return conf_add(p, &p->subs[x], x, 0);
02515 }
02516 
02517 static int isslavenative(struct dahdi_pvt *p, struct dahdi_pvt **out);
02518 
02519 static int my_complete_conference_update(void *pvt, int needconference)
02520 {
02521    struct dahdi_pvt *p = pvt;
02522    int needconf = needconference;
02523    int x;
02524    int useslavenative;
02525    struct dahdi_pvt *slave = NULL;
02526 
02527    useslavenative = isslavenative(p, &slave);
02528 
02529    /* If we have a slave, add him to our conference now. or DAX
02530       if this is slave native */
02531    for (x = 0; x < MAX_SLAVES; x++) {
02532       if (p->slaves[x]) {
02533          if (useslavenative)
02534             conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
02535          else {
02536             conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
02537             needconf++;
02538          }
02539       }
02540    }
02541    /* If we're supposed to be in there, do so now */
02542    if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
02543       if (useslavenative)
02544          conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
02545       else {
02546          conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
02547          needconf++;
02548       }
02549    }
02550    /* If we have a master, add ourselves to his conference */
02551    if (p->master) {
02552       if (isslavenative(p->master, NULL)) {
02553          conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
02554       } else {
02555          conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
02556       }
02557    }
02558    if (!needconf) {
02559       /* Nobody is left (or should be left) in our conference.
02560          Kill it. */
02561       p->confno = -1;
02562    }
02563 
02564    return 0;
02565 }
02566 
02567 static int check_for_conference(struct dahdi_pvt *p);
02568 
02569 static int my_check_for_conference(void *pvt)
02570 {
02571    struct dahdi_pvt *p = pvt;
02572    return check_for_conference(p);
02573 }
02574 
02575 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)
02576 {
02577    struct dahdi_pvt *p = pvt;
02578    int da, db;
02579    int tchan;
02580    int tinthreeway;
02581 
02582    da = analogsub_to_dahdisub(a);
02583    db = analogsub_to_dahdisub(b);
02584 
02585    tchan = p->subs[da].chan;
02586    p->subs[da].chan = p->subs[db].chan;
02587    p->subs[db].chan = tchan;
02588 
02589    tinthreeway = p->subs[da].inthreeway;
02590    p->subs[da].inthreeway = p->subs[db].inthreeway;
02591    p->subs[db].inthreeway = tinthreeway;
02592 
02593    p->subs[da].owner = ast_a;
02594    p->subs[db].owner = ast_b;
02595 
02596    if (ast_a)
02597       ast_channel_set_fd(ast_a, 0, p->subs[da].dfd);
02598    if (ast_b)
02599       ast_channel_set_fd(ast_b, 0, p->subs[db].dfd);
02600 
02601    wakeup_sub(p, a);
02602    wakeup_sub(p, b);
02603 
02604    return;
02605 }
02606 
02607 static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpbx, int idx, int law, const char *linkedid);
02608 
02609 static struct ast_channel *my_new_analog_ast_channel(void *pvt, int state, int startpbx, enum analog_sub sub, const struct ast_channel *requestor)
02610 {
02611    struct dahdi_pvt *p = pvt;
02612    int dsub = analogsub_to_dahdisub(sub);
02613 
02614    return dahdi_new(p, state, startpbx, dsub, 0, requestor ? requestor->linkedid : "");
02615 }
02616 
02617 #if defined(HAVE_PRI) || defined(HAVE_SS7)
02618 static int dahdi_setlaw(int dfd, int law)
02619 {
02620    int res;
02621    res = ioctl(dfd, DAHDI_SETLAW, &law);
02622    if (res)
02623       return res;
02624    return 0;
02625 }
02626 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
02627 
02628 #if defined(HAVE_PRI)
02629 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)
02630 {
02631    struct dahdi_pvt *p = pvt;
02632    int audio;
02633    int newlaw = -1;
02634 
02635    switch (p->sig) {
02636    case SIG_PRI_LIB_HANDLE_CASES:
02637       if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
02638          /* PRI nobch pseudo channel.  Does not handle ioctl(DAHDI_AUDIOMODE) */
02639          break;
02640       }
02641       /* Fall through */
02642    default:
02643       /* Set to audio mode at this point */
02644       audio = 1;
02645       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &audio) == -1) {
02646          ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n",
02647             p->channel, audio, strerror(errno));
02648       }
02649       break;
02650    }
02651 
02652    if (law != SIG_PRI_DEFLAW) {
02653       dahdi_setlaw(p->subs[SUB_REAL].dfd, (law == SIG_PRI_ULAW) ? DAHDI_LAW_MULAW : DAHDI_LAW_ALAW);
02654    }
02655 
02656    ast_copy_string(p->exten, exten, sizeof(p->exten));
02657 
02658    switch (law) {
02659       case SIG_PRI_DEFLAW:
02660          newlaw = 0;
02661          break;
02662       case SIG_PRI_ALAW:
02663          newlaw = DAHDI_LAW_ALAW;
02664          break;
02665       case SIG_PRI_ULAW:
02666          newlaw = DAHDI_LAW_MULAW;
02667          break;
02668    }
02669    return dahdi_new(p, state, 0, SUB_REAL, newlaw, requestor ? requestor->linkedid : "");
02670 }
02671 #endif   /* defined(HAVE_PRI) */
02672 
02673 static int set_actual_gain(int fd, float rxgain, float txgain, float rxdrc, float txdrc, int law);
02674 
02675 #if defined(HAVE_PRI) || defined(HAVE_SS7)
02676 /*!
02677  * \internal
02678  * \brief Open the PRI/SS7 channel media path.
02679  * \since 1.8
02680  *
02681  * \param p Channel private control structure.
02682  *
02683  * \return Nothing
02684  */
02685 static void my_pri_ss7_open_media(void *p)
02686 {
02687    struct dahdi_pvt *pvt = p;
02688    int res;
02689    int dfd;
02690    int set_val;
02691 
02692    dfd = pvt->subs[SUB_REAL].dfd;
02693 
02694    /* Open the media path. */
02695    set_val = 1;
02696    res = ioctl(dfd, DAHDI_AUDIOMODE, &set_val);
02697    if (res < 0) {
02698       ast_log(LOG_WARNING, "Unable to enable audio mode on channel %d (%s)\n",
02699          pvt->channel, strerror(errno));
02700    }
02701 
02702    /* Set correct companding law for this call. */
02703    res = dahdi_setlaw(dfd, pvt->law);
02704    if (res < 0) {
02705       ast_log(LOG_WARNING, "Unable to set law on channel %d\n", pvt->channel);
02706    }
02707 
02708    /* Set correct gain for this call. */
02709    if (pvt->digital) {
02710       res = set_actual_gain(dfd, 0, 0, pvt->rxdrc, pvt->txdrc, pvt->law);
02711    } else {
02712       res = set_actual_gain(dfd, pvt->rxgain, pvt->txgain, pvt->rxdrc, pvt->txdrc,
02713          pvt->law);
02714    }
02715    if (res < 0) {
02716       ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", pvt->channel);
02717    }
02718 
02719    if (pvt->dsp_features && pvt->dsp) {
02720       ast_dsp_set_features(pvt->dsp, pvt->dsp_features);
02721       pvt->dsp_features = 0;
02722    }
02723 }
02724 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
02725 
02726 #if defined(HAVE_PRI)
02727 /*!
02728  * \internal
02729  * \brief Ask DAHDI to dial the given dial string.
02730  * \since 1.8.11
02731  *
02732  * \param p Channel private control structure.
02733  * \param dial_string String to pass to DAHDI to dial.
02734  *
02735  * \note The channel private lock needs to be held when calling.
02736  *
02737  * \return Nothing
02738  */
02739 static void my_pri_dial_digits(void *p, const char *dial_string)
02740 {
02741    struct dahdi_dialoperation zo = {
02742       .op = DAHDI_DIAL_OP_APPEND,
02743    };
02744    struct dahdi_pvt *pvt = p;
02745    int res;
02746 
02747    snprintf(zo.dialstr, sizeof(zo.dialstr), "T%s", dial_string);
02748    ast_debug(1, "Channel %d: Sending '%s' to DAHDI_DIAL.\n", pvt->channel, zo.dialstr);
02749    res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo);
02750    if (res) {
02751       ast_log(LOG_WARNING, "Channel %d: Couldn't dial '%s': %s\n",
02752          pvt->channel, dial_string, strerror(errno));
02753    } else {
02754       pvt->dialing = 1;
02755    }
02756 }
02757 #endif   /* defined(HAVE_PRI) */
02758 
02759 static int unalloc_sub(struct dahdi_pvt *p, int x);
02760 
02761 static int my_unallocate_sub(void *pvt, enum analog_sub analogsub)
02762 {
02763    struct dahdi_pvt *p = pvt;
02764 
02765    return unalloc_sub(p, analogsub_to_dahdisub(analogsub));
02766 }
02767 
02768 static int alloc_sub(struct dahdi_pvt *p, int x);
02769 
02770 static int my_allocate_sub(void *pvt, enum analog_sub analogsub)
02771 {
02772    struct dahdi_pvt *p = pvt;
02773 
02774    return alloc_sub(p, analogsub_to_dahdisub(analogsub));
02775 }
02776 
02777 static int has_voicemail(struct dahdi_pvt *p);
02778 
02779 static int my_has_voicemail(void *pvt)
02780 {
02781    struct dahdi_pvt *p = pvt;
02782 
02783    return has_voicemail(p);
02784 }
02785 
02786 static int my_play_tone(void *pvt, enum analog_sub sub, enum analog_tone tone)
02787 {
02788    struct dahdi_pvt *p = pvt;
02789    int index;
02790 
02791    index = analogsub_to_dahdisub(sub);
02792 
02793    return tone_zone_play_tone(p->subs[index].dfd, analog_tone_to_dahditone(tone));
02794 }
02795 
02796 static enum analog_event dahdievent_to_analogevent(int event)
02797 {
02798    enum analog_event res;
02799 
02800    switch (event) {
02801    case DAHDI_EVENT_ONHOOK:
02802       res = ANALOG_EVENT_ONHOOK;
02803       break;
02804    case DAHDI_EVENT_RINGOFFHOOK:
02805       res = ANALOG_EVENT_RINGOFFHOOK;
02806       break;
02807    case DAHDI_EVENT_WINKFLASH:
02808       res = ANALOG_EVENT_WINKFLASH;
02809       break;
02810    case DAHDI_EVENT_ALARM:
02811       res = ANALOG_EVENT_ALARM;
02812       break;
02813    case DAHDI_EVENT_NOALARM:
02814       res = ANALOG_EVENT_NOALARM;
02815       break;
02816    case DAHDI_EVENT_DIALCOMPLETE:
02817       res = ANALOG_EVENT_DIALCOMPLETE;
02818       break;
02819    case DAHDI_EVENT_RINGERON:
02820       res = ANALOG_EVENT_RINGERON;
02821       break;
02822    case DAHDI_EVENT_RINGEROFF:
02823       res = ANALOG_EVENT_RINGEROFF;
02824       break;
02825    case DAHDI_EVENT_HOOKCOMPLETE:
02826       res = ANALOG_EVENT_HOOKCOMPLETE;
02827       break;
02828    case DAHDI_EVENT_PULSE_START:
02829       res = ANALOG_EVENT_PULSE_START;
02830       break;
02831    case DAHDI_EVENT_POLARITY:
02832       res = ANALOG_EVENT_POLARITY;
02833       break;
02834    case DAHDI_EVENT_RINGBEGIN:
02835       res = ANALOG_EVENT_RINGBEGIN;
02836       break;
02837    case DAHDI_EVENT_EC_DISABLED:
02838       res = ANALOG_EVENT_EC_DISABLED;
02839       break;
02840    case DAHDI_EVENT_REMOVED:
02841       res = ANALOG_EVENT_REMOVED;
02842       break;
02843    case DAHDI_EVENT_NEONMWI_ACTIVE:
02844       res = ANALOG_EVENT_NEONMWI_ACTIVE;
02845       break;
02846    case DAHDI_EVENT_NEONMWI_INACTIVE:
02847       res = ANALOG_EVENT_NEONMWI_INACTIVE;
02848       break;
02849 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
02850    case DAHDI_EVENT_TX_CED_DETECTED:
02851       res = ANALOG_EVENT_TX_CED_DETECTED;
02852       break;
02853    case DAHDI_EVENT_RX_CED_DETECTED:
02854       res = ANALOG_EVENT_RX_CED_DETECTED;
02855       break;
02856    case DAHDI_EVENT_EC_NLP_DISABLED:
02857       res = ANALOG_EVENT_EC_NLP_DISABLED;
02858       break;
02859    case DAHDI_EVENT_EC_NLP_ENABLED:
02860       res = ANALOG_EVENT_EC_NLP_ENABLED;
02861       break;
02862 #endif
02863    case DAHDI_EVENT_PULSEDIGIT:
02864       res = ANALOG_EVENT_PULSEDIGIT;
02865       break;
02866    case DAHDI_EVENT_DTMFDOWN:
02867       res = ANALOG_EVENT_DTMFDOWN;
02868       break;
02869    case DAHDI_EVENT_DTMFUP:
02870       res = ANALOG_EVENT_DTMFUP;
02871       break;
02872    default:
02873       switch(event & 0xFFFF0000) {
02874       case DAHDI_EVENT_PULSEDIGIT:
02875       case DAHDI_EVENT_DTMFDOWN:
02876       case DAHDI_EVENT_DTMFUP:
02877          /* The event includes a digit number in the low word.
02878           * Converting it to a 'enum analog_event' would remove
02879           * that information. Thus it is returned as-is.
02880           */
02881          return event;
02882       }
02883 
02884       res = ANALOG_EVENT_ERROR;
02885       break;
02886    }
02887 
02888    return res;
02889 }
02890 
02891 static inline int dahdi_wait_event(int fd);
02892 
02893 static int my_wait_event(void *pvt)
02894 {
02895    struct dahdi_pvt *p = pvt;
02896 
02897    return dahdi_wait_event(p->subs[SUB_REAL].dfd);
02898 }
02899 
02900 static int my_get_event(void *pvt)
02901 {
02902    struct dahdi_pvt *p = pvt;
02903    int res;
02904 
02905    if (p->fake_event) {
02906       res = p->fake_event;
02907       p->fake_event = 0;
02908    } else
02909       res = dahdi_get_event(p->subs[SUB_REAL].dfd);
02910 
02911    return dahdievent_to_analogevent(res);
02912 }
02913 
02914 static int my_is_off_hook(void *pvt)
02915 {
02916    struct dahdi_pvt *p = pvt;
02917    int res;
02918    struct dahdi_params par;
02919 
02920    memset(&par, 0, sizeof(par));
02921 
02922    if (p->subs[SUB_REAL].dfd > -1)
02923       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
02924    else {
02925       /* Assume not off hook on CVRS */
02926       res = 0;
02927       par.rxisoffhook = 0;
02928    }
02929    if (res) {
02930       ast_log(LOG_WARNING, "Unable to check hook state on channel %d: %s\n", p->channel, strerror(errno));
02931    }
02932 
02933    if ((p->sig == SIG_FXSKS) || (p->sig == SIG_FXSGS)) {
02934       /* When "onhook" that means no battery on the line, and thus
02935       it is out of service..., if it's on a TDM card... If it's a channel
02936       bank, there is no telling... */
02937       return (par.rxbits > -1) || par.rxisoffhook;
02938    }
02939 
02940    return par.rxisoffhook;
02941 }
02942 
02943 static void dahdi_enable_ec(struct dahdi_pvt *p);
02944 static void dahdi_disable_ec(struct dahdi_pvt *p);
02945 
02946 static int my_set_echocanceller(void *pvt, int enable)
02947 {
02948    struct dahdi_pvt *p = pvt;
02949 
02950    if (enable)
02951       dahdi_enable_ec(p);
02952    else
02953       dahdi_disable_ec(p);
02954 
02955    return 0;
02956 }
02957 
02958 static int dahdi_ring_phone(struct dahdi_pvt *p);
02959 
02960 static int my_ring(void *pvt)
02961 {
02962    struct dahdi_pvt *p = pvt;
02963 
02964    return dahdi_ring_phone(p);
02965 }
02966 
02967 static int my_flash(void *pvt)
02968 {
02969    struct dahdi_pvt *p = pvt;
02970    int func = DAHDI_FLASH;
02971    return ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &func);
02972 }
02973 
02974 static inline int dahdi_set_hook(int fd, int hs);
02975 
02976 static int my_off_hook(void *pvt)
02977 {
02978    struct dahdi_pvt *p = pvt;
02979    return dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
02980 }
02981 
02982 static void my_set_needringing(void *pvt, int value)
02983 {
02984    struct dahdi_pvt *p = pvt;
02985    p->subs[SUB_REAL].needringing = value;
02986 }
02987 
02988 static void my_set_polarity(void *pvt, int value)
02989 {
02990    struct dahdi_pvt *p = pvt;
02991 
02992    if (p->channel == CHAN_PSEUDO) {
02993       return;
02994    }
02995    p->polarity = value;
02996    ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETPOLARITY, &value);
02997 }
02998 
02999 static void my_start_polarityswitch(void *pvt)
03000 {
03001    struct dahdi_pvt *p = pvt;
03002 
03003    if (p->answeronpolarityswitch || p->hanguponpolarityswitch) {
03004       my_set_polarity(pvt, 0);
03005    }
03006 }
03007 
03008 static void my_answer_polarityswitch(void *pvt)
03009 {
03010    struct dahdi_pvt *p = pvt;
03011 
03012    if (!p->answeronpolarityswitch) {
03013       return;
03014    }
03015 
03016    my_set_polarity(pvt, 1);
03017 }
03018 
03019 static void my_hangup_polarityswitch(void *pvt)
03020 {
03021    struct dahdi_pvt *p = pvt;
03022 
03023    if (!p->hanguponpolarityswitch) {
03024       return;
03025    }
03026 
03027    if (p->answeronpolarityswitch) {
03028       my_set_polarity(pvt, 0);
03029    } else {
03030       my_set_polarity(pvt, 1);
03031    }
03032 }
03033 
03034 static int my_start(void *pvt)
03035 {
03036    struct dahdi_pvt *p = pvt;
03037    int x = DAHDI_START;
03038 
03039    return ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
03040 }
03041 
03042 static int my_dial_digits(void *pvt, enum analog_sub sub, struct analog_dialoperation *dop)
03043 {
03044    int index = analogsub_to_dahdisub(sub);
03045    int res;
03046    struct dahdi_pvt *p = pvt;
03047    struct dahdi_dialoperation ddop;
03048 
03049    if (dop->op != ANALOG_DIAL_OP_REPLACE) {
03050       ast_log(LOG_ERROR, "Fix the dial_digits callback!\n");
03051       return -1;
03052    }
03053 
03054    if (sub != ANALOG_SUB_REAL) {
03055       ast_log(LOG_ERROR, "Trying to dial_digits '%s' on channel %d subchannel %u\n",
03056          dop->dialstr, p->channel, sub);
03057       return -1;
03058    }
03059 
03060    ddop.op = DAHDI_DIAL_OP_REPLACE;
03061    ast_copy_string(ddop.dialstr, dop->dialstr, sizeof(ddop.dialstr));
03062 
03063    ast_debug(1, "Channel %d: Sending '%s' to DAHDI_DIAL.\n", p->channel, ddop.dialstr);
03064 
03065    res = ioctl(p->subs[index].dfd, DAHDI_DIAL, &ddop);
03066    if (res == -1) {
03067       ast_debug(1, "DAHDI_DIAL ioctl failed on %s: %s\n", p->owner->name, strerror(errno));
03068    }
03069 
03070    return res;
03071 }
03072 
03073 static void dahdi_train_ec(struct dahdi_pvt *p);
03074 
03075 static int my_train_echocanceller(void *pvt)
03076 {
03077    struct dahdi_pvt *p = pvt;
03078 
03079    dahdi_train_ec(p);
03080 
03081    return 0;
03082 }
03083 
03084 static int my_is_dialing(void *pvt, enum analog_sub sub)
03085 {
03086    struct dahdi_pvt *p = pvt;
03087    int index;
03088    int x;
03089 
03090    index = analogsub_to_dahdisub(sub);
03091 
03092    if (ioctl(p->subs[index].dfd, DAHDI_DIALING, &x)) {
03093       ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed!\n");
03094       return -1;
03095    }
03096 
03097    return x;
03098 }
03099 
03100 static int my_on_hook(void *pvt)
03101 {
03102    struct dahdi_pvt *p = pvt;
03103    return dahdi_set_hook(p->subs[ANALOG_SUB_REAL].dfd, DAHDI_ONHOOK);
03104 }
03105 
03106 #if defined(HAVE_PRI)
03107 static void my_pri_fixup_chans(void *chan_old, void *chan_new)
03108 {
03109    struct dahdi_pvt *old_chan = chan_old;
03110    struct dahdi_pvt *new_chan = chan_new;
03111 
03112    new_chan->owner = old_chan->owner;
03113    old_chan->owner = NULL;
03114    if (new_chan->owner) {
03115       new_chan->owner->tech_pvt = new_chan;
03116       new_chan->owner->fds[0] = new_chan->subs[SUB_REAL].dfd;
03117       new_chan->subs[SUB_REAL].owner = old_chan->subs[SUB_REAL].owner;
03118       old_chan->subs[SUB_REAL].owner = NULL;
03119    }
03120    /* Copy any DSP that may be present */
03121    new_chan->dsp = old_chan->dsp;
03122    new_chan->dsp_features = old_chan->dsp_features;
03123    old_chan->dsp = NULL;
03124    old_chan->dsp_features = 0;
03125 
03126    /* Transfer flags from the old channel. */
03127    new_chan->dialing = old_chan->dialing;
03128    new_chan->digital = old_chan->digital;
03129    new_chan->outgoing = old_chan->outgoing;
03130    old_chan->dialing = 0;
03131    old_chan->digital = 0;
03132    old_chan->outgoing = 0;
03133 
03134    /* More stuff to transfer to the new channel. */
03135    new_chan->law = old_chan->law;
03136    strcpy(new_chan->dialstring, old_chan->dialstring);
03137 }
03138 #endif   /* defined(HAVE_PRI) */
03139 
03140 #if defined(HAVE_PRI)
03141 static int sig_pri_tone_to_dahditone(enum sig_pri_tone tone)
03142 {
03143    switch (tone) {
03144    case SIG_PRI_TONE_RINGTONE:
03145       return DAHDI_TONE_RINGTONE;
03146    case SIG_PRI_TONE_STUTTER:
03147       return DAHDI_TONE_STUTTER;
03148    case SIG_PRI_TONE_CONGESTION:
03149       return DAHDI_TONE_CONGESTION;
03150    case SIG_PRI_TONE_DIALTONE:
03151       return DAHDI_TONE_DIALTONE;
03152    case SIG_PRI_TONE_DIALRECALL:
03153       return DAHDI_TONE_DIALRECALL;
03154    case SIG_PRI_TONE_INFO:
03155       return DAHDI_TONE_INFO;
03156    case SIG_PRI_TONE_BUSY:
03157       return DAHDI_TONE_BUSY;
03158    default:
03159       return -1;
03160    }
03161 }
03162 #endif   /* defined(HAVE_PRI) */
03163 
03164 #if defined(HAVE_PRI)
03165 static int pri_destroy_dchan(struct sig_pri_span *pri);
03166 
03167 static void my_handle_dchan_exception(struct sig_pri_span *pri, int index)
03168 {
03169    int x;
03170 
03171    ioctl(pri->fds[index], DAHDI_GETEVENT, &x);
03172    switch (x) {
03173    case DAHDI_EVENT_NONE:
03174       break;
03175    case DAHDI_EVENT_ALARM:
03176    case DAHDI_EVENT_NOALARM:
03177       if (sig_pri_is_alarm_ignored(pri)) {
03178          break;
03179       }
03180       /* Fall through */
03181    default:
03182       ast_log(LOG_NOTICE, "PRI got event: %s (%d) on D-channel of span %d\n",
03183          event2str(x), x, pri->span);
03184       break;
03185    }
03186    /* Keep track of alarm state */
03187    switch (x) {
03188    case DAHDI_EVENT_ALARM:
03189       pri_event_alarm(pri, index, 0);
03190       break;
03191    case DAHDI_EVENT_NOALARM:
03192       pri_event_noalarm(pri, index, 0);
03193       break;
03194    case DAHDI_EVENT_REMOVED:
03195       pri_destroy_dchan(pri);
03196       break;
03197    default:
03198       break;
03199    }
03200 }
03201 #endif   /* defined(HAVE_PRI) */
03202 
03203 #if defined(HAVE_PRI)
03204 static int my_pri_play_tone(void *pvt, enum sig_pri_tone tone)
03205 {
03206    struct dahdi_pvt *p = pvt;
03207 
03208    return tone_zone_play_tone(p->subs[SUB_REAL].dfd, sig_pri_tone_to_dahditone(tone));
03209 }
03210 #endif   /* defined(HAVE_PRI) */
03211 
03212 #if defined(HAVE_PRI) || defined(HAVE_SS7)
03213 /*!
03214  * \internal
03215  * \brief Set the caller id information.
03216  * \since 1.8
03217  *
03218  * \param pvt DAHDI private structure
03219  * \param caller Caller-id information to set.
03220  *
03221  * \return Nothing
03222  */
03223 static void my_set_callerid(void *pvt, const struct ast_party_caller *caller)
03224 {
03225    struct dahdi_pvt *p = pvt;
03226 
03227    ast_copy_string(p->cid_num,
03228       S_COR(caller->id.number.valid, caller->id.number.str, ""),
03229       sizeof(p->cid_num));
03230    ast_copy_string(p->cid_name,
03231       S_COR(caller->id.name.valid, caller->id.name.str, ""),
03232       sizeof(p->cid_name));
03233    ast_copy_string(p->cid_subaddr,
03234       S_COR(caller->id.subaddress.valid, caller->id.subaddress.str, ""),
03235       sizeof(p->cid_subaddr));
03236    p->cid_ton = caller->id.number.plan;
03237    p->callingpres = ast_party_id_presentation(&caller->id);
03238    if (caller->id.tag) {
03239       ast_copy_string(p->cid_tag, caller->id.tag, sizeof(p->cid_tag));
03240    }
03241    ast_copy_string(p->cid_ani,
03242       S_COR(caller->ani.number.valid, caller->ani.number.str, ""),
03243       sizeof(p->cid_ani));
03244    p->cid_ani2 = caller->ani2;
03245 }
03246 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
03247 
03248 #if defined(HAVE_PRI) || defined(HAVE_SS7)
03249 /*!
03250  * \internal
03251  * \brief Set the Dialed Number Identifier.
03252  * \since 1.8
03253  *
03254  * \param pvt DAHDI private structure
03255  * \param dnid Dialed Number Identifier string.
03256  *
03257  * \return Nothing
03258  */
03259 static void my_set_dnid(void *pvt, const char *dnid)
03260 {
03261    struct dahdi_pvt *p = pvt;
03262 
03263    ast_copy_string(p->dnid, dnid, sizeof(p->dnid));
03264 }
03265 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
03266 
03267 #if defined(HAVE_PRI)
03268 /*!
03269  * \internal
03270  * \brief Set the Redirecting Directory Number Information Service (RDNIS).
03271  * \since 1.8
03272  *
03273  * \param pvt DAHDI private structure
03274  * \param rdnis Redirecting Directory Number Information Service (RDNIS) string.
03275  *
03276  * \return Nothing
03277  */
03278 static void my_set_rdnis(void *pvt, const char *rdnis)
03279 {
03280    struct dahdi_pvt *p = pvt;
03281 
03282    ast_copy_string(p->rdnis, rdnis, sizeof(p->rdnis));
03283 }
03284 #endif   /* defined(HAVE_PRI) */
03285 
03286 #if defined(HAVE_PRI)
03287 /*!
03288  * \internal
03289  * \brief Make a dialstring for native ISDN CC to recall properly.
03290  * \since 1.8
03291  *
03292  * \param priv Channel private control structure.
03293  * \param buf Where to put the modified dialstring.
03294  * \param buf_size Size of modified dialstring buffer.
03295  *
03296  * \details
03297  * original dialstring:
03298  * DAHDI/[i<span>-](g|G|r|R)<group#(0-63)>[c|r<cadance#>|d][/extension[/options]]
03299  *
03300  * The modified dialstring will have prefixed the channel-group section
03301  * with the ISDN channel restriction.
03302  *
03303  * buf:
03304  * DAHDI/i<span>-(g|G|r|R)<group#(0-63)>[c|r<cadance#>|d][/extension[/options]]
03305  *
03306  * The routine will check to see if the ISDN channel restriction is already
03307  * in the original dialstring.
03308  *
03309  * \return Nothing
03310  */
03311 static void my_pri_make_cc_dialstring(void *priv, char *buf, size_t buf_size)
03312 {
03313    char *dial;
03314    struct dahdi_pvt *pvt;
03315    AST_DECLARE_APP_ARGS(args,
03316       AST_APP_ARG(tech);   /* channel technology token */
03317       AST_APP_ARG(group);  /* channel/group token */
03318       //AST_APP_ARG(ext);  /* extension token */
03319       //AST_APP_ARG(opts); /* options token */
03320       //AST_APP_ARG(other);   /* Any remining unused arguments */
03321    );
03322 
03323    pvt = priv;
03324    dial = ast_strdupa(pvt->dialstring);
03325    AST_NONSTANDARD_APP_ARGS(args, dial, '/');
03326    if (!args.tech) {
03327       ast_copy_string(buf, pvt->dialstring, buf_size);
03328       return;
03329    }
03330    if (!args.group) {
03331       /* Append the ISDN span channel restriction to the dialstring. */
03332       snprintf(buf, buf_size, "%s/i%d-", args.tech, pvt->pri->span);
03333       return;
03334    }
03335    if (isdigit(args.group[0]) || args.group[0] == 'i' || strchr(args.group, '!')) {
03336       /* The ISDN span channel restriction is not needed or already
03337        * in the dialstring. */
03338       ast_copy_string(buf, pvt->dialstring, buf_size);
03339       return;
03340    }
03341    /* Insert the ISDN span channel restriction into the dialstring. */
03342    snprintf(buf, buf_size, "%s/i%d-%s", args.tech, pvt->pri->span, args.group);
03343 }
03344 #endif   /* defined(HAVE_PRI) */
03345 
03346 #if defined(HAVE_PRI)
03347 /*!
03348  * \internal
03349  * \brief Reevaluate the PRI span device state.
03350  * \since 1.8
03351  *
03352  * \param pri Asterisk D channel control structure.
03353  *
03354  * \return Nothing
03355  *
03356  * \note Assumes the pri->lock is already obtained.
03357  */
03358 static void dahdi_pri_update_span_devstate(struct sig_pri_span *pri)
03359 {
03360    unsigned idx;
03361    unsigned num_b_chans;   /* Number of B channels provisioned on the span. */
03362    unsigned in_use;     /* Number of B channels in use on the span. */
03363    unsigned in_alarm;      /* TRUE if the span is in alarm condition. */
03364    enum ast_device_state new_state;
03365 
03366    /* Count the number of B channels and the number of B channels in use. */
03367    num_b_chans = 0;
03368    in_use = 0;
03369    in_alarm = 1;
03370    for (idx = pri->numchans; idx--;) {
03371       if (pri->pvts[idx] && !pri->pvts[idx]->no_b_channel) {
03372          /* This is a B channel interface. */
03373          ++num_b_chans;
03374          if (!sig_pri_is_chan_available(pri->pvts[idx])) {
03375             ++in_use;
03376          }
03377          if (!pri->pvts[idx]->inalarm) {
03378             /* There is a channel that is not in alarm. */
03379             in_alarm = 0;
03380          }
03381       }
03382    }
03383 
03384    /* Update the span congestion device state and report any change. */
03385    if (in_alarm) {
03386       new_state = AST_DEVICE_UNAVAILABLE;
03387    } else {
03388       new_state = num_b_chans == in_use ? AST_DEVICE_BUSY : AST_DEVICE_NOT_INUSE;
03389    }
03390    if (pri->congestion_devstate != new_state) {
03391       pri->congestion_devstate = new_state;
03392       ast_devstate_changed(AST_DEVICE_UNKNOWN, AST_DEVSTATE_NOT_CACHABLE, "DAHDI/I%d/congestion", pri->span);
03393    }
03394 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
03395    /* Update the span threshold device state and report any change. */
03396    if (in_alarm) {
03397       new_state = AST_DEVICE_UNAVAILABLE;
03398    } else if (!in_use) {
03399       new_state = AST_DEVICE_NOT_INUSE;
03400    } else if (!pri->user_busy_threshold) {
03401       new_state = in_use < num_b_chans ? AST_DEVICE_INUSE : AST_DEVICE_BUSY;
03402    } else {
03403       new_state = in_use < pri->user_busy_threshold ? AST_DEVICE_INUSE
03404          : AST_DEVICE_BUSY;
03405    }
03406    if (pri->threshold_devstate != new_state) {
03407       pri->threshold_devstate = new_state;
03408       ast_devstate_changed(AST_DEVICE_UNKNOWN, AST_DEVSTATE_NOT_CACHABLE, "DAHDI/I%d/threshold", pri->span);
03409    }
03410 #endif   /* defined(THRESHOLD_DEVSTATE_PLACEHOLDER) */
03411 }
03412 #endif   /* defined(HAVE_PRI) */
03413 
03414 #if defined(HAVE_PRI)
03415 /*!
03416  * \internal
03417  * \brief Reference this module.
03418  * \since 1.8
03419  *
03420  * \return Nothing
03421  */
03422 static void my_module_ref(void)
03423 {
03424    ast_module_ref(ast_module_info->self);
03425 }
03426 #endif   /* defined(HAVE_PRI) */
03427 
03428 #if defined(HAVE_PRI)
03429 /*!
03430  * \internal
03431  * \brief Unreference this module.
03432  * \since 1.8
03433  *
03434  * \return Nothing
03435  */
03436 static void my_module_unref(void)
03437 {
03438    ast_module_unref(ast_module_info->self);
03439 }
03440 #endif   /* defined(HAVE_PRI) */
03441 
03442 #if defined(HAVE_PRI)
03443 #if defined(HAVE_PRI_CALL_WAITING)
03444 static void my_pri_init_config(void *priv, struct sig_pri_span *pri);
03445 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
03446 static int dahdi_new_pri_nobch_channel(struct sig_pri_span *pri);
03447 
03448 static struct sig_pri_callback dahdi_pri_callbacks =
03449 {
03450    .handle_dchan_exception = my_handle_dchan_exception,
03451    .play_tone = my_pri_play_tone,
03452    .set_echocanceller = my_set_echocanceller,
03453    .dsp_reset_and_flush_digits = my_dsp_reset_and_flush_digits,
03454    .lock_private = my_lock_private,
03455    .unlock_private = my_unlock_private,
03456    .new_ast_channel = my_new_pri_ast_channel,
03457    .fixup_chans = my_pri_fixup_chans,
03458    .set_alarm = my_set_alarm,
03459    .set_dialing = my_set_dialing,
03460    .set_outgoing = my_set_outgoing,
03461    .set_digital = my_set_digital,
03462    .set_callerid = my_set_callerid,
03463    .set_dnid = my_set_dnid,
03464    .set_rdnis = my_set_rdnis,
03465    .new_nobch_intf = dahdi_new_pri_nobch_channel,
03466 #if defined(HAVE_PRI_CALL_WAITING)
03467    .init_config = my_pri_init_config,
03468 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
03469    .get_orig_dialstring = my_get_orig_dialstring,
03470    .make_cc_dialstring = my_pri_make_cc_dialstring,
03471    .update_span_devstate = dahdi_pri_update_span_devstate,
03472    .module_ref = my_module_ref,
03473    .module_unref = my_module_unref,
03474    .dial_digits = my_pri_dial_digits,
03475    .open_media = my_pri_ss7_open_media,
03476    .ami_channel_event = my_ami_channel_event,
03477 };
03478 #endif   /* defined(HAVE_PRI) */
03479 
03480 #if defined(HAVE_SS7)
03481 /*!
03482  * \internal
03483  * \brief Handle the SS7 link exception.
03484  * \since 1.8
03485  *
03486  * \param linkset Controlling linkset for the channel.
03487  * \param which Link index of the signaling channel.
03488  *
03489  * \return Nothing
03490  */
03491 static void my_handle_link_exception(struct sig_ss7_linkset *linkset, int which)
03492 {
03493    int event;
03494 
03495    if (ioctl(linkset->fds[which], DAHDI_GETEVENT, &event)) {
03496       ast_log(LOG_ERROR, "SS7: Error in exception retrieval on span %d/%d!\n",
03497          linkset->span, which);
03498       return;
03499    }
03500    switch (event) {
03501    case DAHDI_EVENT_NONE:
03502       break;
03503    case DAHDI_EVENT_ALARM:
03504       ast_log(LOG_ERROR, "SS7 got event: %s(%d) on span %d/%d\n",
03505          event2str(event), event, linkset->span, which);
03506       sig_ss7_link_alarm(linkset, which);
03507       break;
03508    case DAHDI_EVENT_NOALARM:
03509       ast_log(LOG_ERROR, "SS7 got event: %s(%d) on span %d/%d\n",
03510          event2str(event), event, linkset->span, which);
03511       sig_ss7_link_noalarm(linkset, which);
03512       break;
03513    default:
03514       ast_log(LOG_NOTICE, "SS7 got event: %s(%d) on span %d/%d\n",
03515          event2str(event), event, linkset->span, which);
03516       break;
03517    }
03518 }
03519 #endif   /* defined(HAVE_SS7) */
03520 
03521 #if defined(HAVE_SS7)
03522 static void my_ss7_set_loopback(void *pvt, int enable)
03523 {
03524    struct dahdi_pvt *p = pvt;
03525 
03526    if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_LOOPBACK, &enable)) {
03527       ast_log(LOG_WARNING, "Unable to set loopback on channel %d: %s\n", p->channel,
03528          strerror(errno));
03529    }
03530 }
03531 #endif   /* defined(HAVE_SS7) */
03532 
03533 #if defined(HAVE_SS7)
03534 /*!
03535  * \internal
03536  * \brief Create a new asterisk channel structure for SS7.
03537  * \since 1.8
03538  *
03539  * \param pvt Private channel structure.
03540  * \param state Initial state of new channel.
03541  * \param law Combanding law to use.
03542  * \param exten Dialplan extension for incoming call.
03543  * \param requestor Channel requesting this new channel.
03544  *
03545  * \retval ast_channel on success.
03546  * \retval NULL on error.
03547  */
03548 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)
03549 {
03550    struct dahdi_pvt *p = pvt;
03551    int audio;
03552    int newlaw;
03553 
03554    /* Set to audio mode at this point */
03555    audio = 1;
03556    if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &audio) == -1)
03557       ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n",
03558          p->channel, audio, strerror(errno));
03559 
03560    if (law != SIG_SS7_DEFLAW) {
03561       dahdi_setlaw(p->subs[SUB_REAL].dfd,
03562          (law == SIG_SS7_ULAW) ? DAHDI_LAW_MULAW : DAHDI_LAW_ALAW);
03563    }
03564 
03565    ast_copy_string(p->exten, exten, sizeof(p->exten));
03566 
03567    newlaw = -1;
03568    switch (law) {
03569    case SIG_SS7_DEFLAW:
03570       newlaw = 0;
03571       break;
03572    case SIG_SS7_ALAW:
03573       newlaw = DAHDI_LAW_ALAW;
03574       break;
03575    case SIG_SS7_ULAW:
03576       newlaw = DAHDI_LAW_MULAW;
03577       break;
03578    }
03579    return dahdi_new(p, state, 0, SUB_REAL, newlaw, requestor ? requestor->linkedid : "");
03580 }
03581 #endif   /* defined(HAVE_SS7) */
03582 
03583 #if defined(HAVE_SS7)
03584 static int sig_ss7_tone_to_dahditone(enum sig_ss7_tone tone)
03585 {
03586    switch (tone) {
03587    case SIG_SS7_TONE_RINGTONE:
03588       return DAHDI_TONE_RINGTONE;
03589    case SIG_SS7_TONE_STUTTER:
03590       return DAHDI_TONE_STUTTER;
03591    case SIG_SS7_TONE_CONGESTION:
03592       return DAHDI_TONE_CONGESTION;
03593    case SIG_SS7_TONE_DIALTONE:
03594       return DAHDI_TONE_DIALTONE;
03595    case SIG_SS7_TONE_DIALRECALL:
03596       return DAHDI_TONE_DIALRECALL;
03597    case SIG_SS7_TONE_INFO:
03598       return DAHDI_TONE_INFO;
03599    case SIG_SS7_TONE_BUSY:
03600       return DAHDI_TONE_BUSY;
03601    default:
03602       return -1;
03603    }
03604 }
03605 #endif   /* defined(HAVE_SS7) */
03606 
03607 #if defined(HAVE_SS7)
03608 static int my_ss7_play_tone(void *pvt, enum sig_ss7_tone tone)
03609 {
03610    struct dahdi_pvt *p = pvt;
03611 
03612    return tone_zone_play_tone(p->subs[SUB_REAL].dfd, sig_ss7_tone_to_dahditone(tone));
03613 }
03614 #endif   /* defined(HAVE_SS7) */
03615 
03616 #if defined(HAVE_SS7)
03617 static struct sig_ss7_callback dahdi_ss7_callbacks =
03618 {
03619    .lock_private = my_lock_private,
03620    .unlock_private = my_unlock_private,
03621 
03622    .set_echocanceller = my_set_echocanceller,
03623    .set_loopback = my_ss7_set_loopback,
03624 
03625    .new_ast_channel = my_new_ss7_ast_channel,
03626    .play_tone = my_ss7_play_tone,
03627 
03628    .handle_link_exception = my_handle_link_exception,
03629    .set_alarm = my_set_alarm,
03630    .set_dialing = my_set_dialing,
03631    .set_outgoing = my_set_outgoing,
03632    .set_digital = my_set_digital,
03633    .set_inservice = my_set_inservice,
03634    .set_locallyblocked = my_set_locallyblocked,
03635    .set_remotelyblocked = my_set_remotelyblocked,
03636    .set_callerid = my_set_callerid,
03637    .set_dnid = my_set_dnid,
03638    .open_media = my_pri_ss7_open_media,
03639 };
03640 #endif   /* defined(HAVE_SS7) */
03641 
03642 /*!
03643  * \brief Send MWI state change
03644  *
03645  * \arg mailbox_full This is the mailbox associated with the FXO line that the
03646  *      MWI state has changed on.
03647  * \arg thereornot This argument should simply be set to 1 or 0, to indicate
03648  *      whether there are messages waiting or not.
03649  *
03650  *  \return nothing
03651  *
03652  * This function does two things:
03653  *
03654  * 1) It generates an internal Asterisk event notifying any other module that
03655  *    cares about MWI that the state of a mailbox has changed.
03656  *
03657  * 2) It runs the script specified by the mwimonitornotify option to allow
03658  *    some custom handling of the state change.
03659  */
03660 static void notify_message(char *mailbox_full, int thereornot)
03661 {
03662    char s[sizeof(mwimonitornotify) + 80];
03663    struct ast_event *event;
03664    char *mailbox, *context;
03665 
03666    /* Strip off @default */
03667    context = mailbox = ast_strdupa(mailbox_full);
03668    strsep(&context, "@");
03669    if (ast_strlen_zero(context))
03670       context = "default";
03671 
03672    if (!(event = ast_event_new(AST_EVENT_MWI,
03673          AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
03674          AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
03675          AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot,
03676          AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot,
03677          AST_EVENT_IE_END))) {
03678       return;
03679    }
03680 
03681    ast_event_queue_and_cache(event);
03682 
03683    if (!ast_strlen_zero(mailbox) && !ast_strlen_zero(mwimonitornotify)) {
03684       snprintf(s, sizeof(s), "%s %s %d", mwimonitornotify, mailbox, thereornot);
03685       ast_safe_system(s);
03686    }
03687 }
03688 
03689 static void my_handle_notify_message(struct ast_channel *chan, void *pvt, int cid_flags, int neon_mwievent)
03690 {
03691    struct dahdi_pvt *p = pvt;
03692 
03693    if (neon_mwievent > -1 && !p->mwimonitor_neon)
03694       return;
03695 
03696    if (neon_mwievent == ANALOG_EVENT_NEONMWI_ACTIVE || cid_flags & CID_MSGWAITING) {
03697       ast_log(LOG_NOTICE, "MWI: Channel %d message waiting, mailbox %s\n", p->channel, p->mailbox);
03698       notify_message(p->mailbox, 1);
03699    } else if (neon_mwievent == ANALOG_EVENT_NEONMWI_INACTIVE || cid_flags & CID_NOMSGWAITING) {
03700       ast_log(LOG_NOTICE, "MWI: Channel %d no message waiting, mailbox %s\n", p->channel, p->mailbox);
03701       notify_message(p->mailbox, 0);
03702    }
03703    /* If the CID had Message waiting payload, assume that this for MWI only and hangup the call */
03704    /* If generated using Ring Pulse Alert, then ring has been answered as a call and needs to be hungup */
03705    if (neon_mwievent == -1 && p->mwimonitor_rpas) {
03706       ast_hangup(chan);
03707       return;
03708    }
03709 }
03710 
03711 static int my_have_progressdetect(void *pvt)
03712 {
03713    struct dahdi_pvt *p = pvt;
03714 
03715    if ((p->callprogress & CALLPROGRESS_PROGRESS)
03716       && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
03717       return 1;
03718    } else {
03719       /* Don't have progress detection. */
03720       return 0;
03721    }
03722 }
03723 
03724 static struct analog_callback dahdi_analog_callbacks =
03725 {
03726    .play_tone = my_play_tone,
03727    .get_event = my_get_event,
03728    .wait_event = my_wait_event,
03729    .is_off_hook = my_is_off_hook,
03730    .set_echocanceller = my_set_echocanceller,
03731    .ring = my_ring,
03732    .flash = my_flash,
03733    .off_hook = my_off_hook,
03734    .dial_digits = my_dial_digits,
03735    .train_echocanceller = my_train_echocanceller,
03736    .on_hook = my_on_hook,
03737    .is_dialing = my_is_dialing,
03738    .allocate_sub = my_allocate_sub,
03739    .unallocate_sub = my_unallocate_sub,
03740    .swap_subs = my_swap_subchannels,
03741    .has_voicemail = my_has_voicemail,
03742    .check_for_conference = my_check_for_conference,
03743    .conf_add = my_conf_add,
03744    .conf_del = my_conf_del,
03745    .complete_conference_update = my_complete_conference_update,
03746    .start = my_start,
03747    .all_subchannels_hungup = my_all_subchannels_hungup,
03748    .lock_private = my_lock_private,
03749    .unlock_private = my_unlock_private,
03750    .deadlock_avoidance_private = my_deadlock_avoidance_private,
03751    .handle_dtmf = my_handle_dtmf,
03752    .wink = my_wink,
03753    .new_ast_channel = my_new_analog_ast_channel,
03754    .dsp_set_digitmode = my_dsp_set_digitmode,
03755    .dsp_reset_and_flush_digits = my_dsp_reset_and_flush_digits,
03756    .send_callerid = my_send_callerid,
03757    .callwait = my_callwait,
03758    .stop_callwait = my_stop_callwait,
03759    .get_callerid = my_get_callerid,
03760    .start_cid_detect = my_start_cid_detect,
03761    .stop_cid_detect = my_stop_cid_detect,
03762    .handle_notify_message = my_handle_notify_message,
03763    .increase_ss_count = my_increase_ss_count,
03764    .decrease_ss_count = my_decrease_ss_count,
03765    .distinctive_ring = my_distinctive_ring,
03766    .set_linear_mode = my_set_linear_mode,
03767    .set_inthreeway = my_set_inthreeway,
03768    .get_and_handle_alarms = my_get_and_handle_alarms,
03769    .get_sigpvt_bridged_channel = my_get_sigpvt_bridged_channel,
03770    .get_sub_fd = my_get_sub_fd,
03771    .set_cadence = my_set_cadence,
03772    .set_alarm = my_set_alarm,
03773    .set_dialing = my_set_dialing,
03774    .set_outgoing = my_set_outgoing,
03775    .set_ringtimeout = my_set_ringtimeout,
03776    .set_waitingfordt = my_set_waitingfordt,
03777    .check_waitingfordt = my_check_waitingfordt,
03778    .set_confirmanswer = my_set_confirmanswer,
03779    .check_confirmanswer = my_check_confirmanswer,
03780    .set_callwaiting = my_set_callwaiting,
03781    .cancel_cidspill = my_cancel_cidspill,
03782    .confmute = my_confmute,
03783    .set_pulsedial = my_set_pulsedial,
03784    .set_new_owner = my_set_new_owner,
03785    .get_orig_dialstring = my_get_orig_dialstring,
03786    .set_needringing = my_set_needringing,
03787    .set_polarity = my_set_polarity,
03788    .start_polarityswitch = my_start_polarityswitch,
03789    .answer_polarityswitch = my_answer_polarityswitch,
03790    .hangup_polarityswitch = my_hangup_polarityswitch,
03791    .have_progressdetect = my_have_progressdetect,
03792 };
03793 
03794 /*! Round robin search locations. */
03795 static struct dahdi_pvt *round_robin[32];
03796 
03797 #define dahdi_get_index(ast, p, nullok)   _dahdi_get_index(ast, p, nullok, __PRETTY_FUNCTION__, __LINE__)
03798 static int _dahdi_get_index(struct ast_channel *ast, struct dahdi_pvt *p, int nullok, const char *fname, unsigned long line)
03799 {
03800    int res;
03801    if (p->subs[SUB_REAL].owner == ast)
03802       res = 0;
03803    else if (p->subs[SUB_CALLWAIT].owner == ast)
03804       res = 1;
03805    else if (p->subs[SUB_THREEWAY].owner == ast)
03806       res = 2;
03807    else {
03808       res = -1;
03809       if (!nullok)
03810          ast_log(LOG_WARNING,
03811             "Unable to get index for '%s' on channel %d (%s(), line %lu)\n",
03812             ast ? ast->name : "", p->channel, fname, line);
03813    }
03814    return res;
03815 }
03816 
03817 /*!
03818  * \internal
03819  * \brief Obtain the specified subchannel owner lock if the owner exists.
03820  *
03821  * \param pvt Channel private struct.
03822  * \param sub_idx Subchannel owner to lock.
03823  *
03824  * \note Assumes the pvt->lock is already obtained.
03825  *
03826  * \note
03827  * Because deadlock avoidance may have been necessary, you need to confirm
03828  * the state of things before continuing.
03829  *
03830  * \return Nothing
03831  */
03832 static void dahdi_lock_sub_owner(struct dahdi_pvt *pvt, int sub_idx)
03833 {
03834    for (;;) {
03835       if (!pvt->subs[sub_idx].owner) {
03836          /* No subchannel owner pointer */
03837          break;
03838       }
03839       if (!ast_channel_trylock(pvt->subs[sub_idx].owner)) {
03840          /* Got subchannel owner lock */
03841          break;
03842       }
03843       /* We must unlock the private to avoid the possibility of a deadlock */
03844       DEADLOCK_AVOIDANCE(&pvt->lock);
03845    }
03846 }
03847 
03848 static void wakeup_sub(struct dahdi_pvt *p, int a)
03849 {
03850    dahdi_lock_sub_owner(p, a);
03851    if (p->subs[a].owner) {
03852       ast_queue_frame(p->subs[a].owner, &ast_null_frame);
03853       ast_channel_unlock(p->subs[a].owner);
03854    }
03855 }
03856 
03857 static void dahdi_queue_frame(struct dahdi_pvt *p, struct ast_frame *f)
03858 {
03859    for (;;) {
03860       if (p->owner) {
03861          if (ast_channel_trylock(p->owner)) {
03862             DEADLOCK_AVOIDANCE(&p->lock);
03863          } else {
03864             ast_queue_frame(p->owner, f);
03865             ast_channel_unlock(p->owner);
03866             break;
03867          }
03868       } else
03869          break;
03870    }
03871 }
03872 
03873 static void handle_clear_alarms(struct dahdi_pvt *p)
03874 {
03875 #if defined(HAVE_PRI)
03876    if (dahdi_sig_pri_lib_handles(p->sig) && sig_pri_is_alarm_ignored(p->pri)) {
03877       return;
03878    }
03879 #endif   /* defined(HAVE_PRI) */
03880 
03881    if (report_alarms & REPORT_CHANNEL_ALARMS) {
03882       ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel);
03883       manager_event(EVENT_FLAG_SYSTEM, "AlarmClear", "Channel: %d\r\n", p->channel);
03884    }
03885    if (report_alarms & REPORT_SPAN_ALARMS && p->manages_span_alarms) {
03886       ast_log(LOG_NOTICE, "Alarm cleared on span %d\n", p->span);
03887       manager_event(EVENT_FLAG_SYSTEM, "SpanAlarmClear", "Span: %d\r\n", p->span);
03888    }
03889 }
03890 
03891 #ifdef HAVE_OPENR2
03892 
03893 static int dahdi_r2_answer(struct dahdi_pvt *p)
03894 {
03895    int res = 0;
03896    /* openr2 1.1.0 and older does not even define OR2_LIB_INTERFACE
03897    * and does not has support for openr2_chan_answer_call_with_mode
03898    *  */
03899 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
03900    const char *double_answer = pbx_builtin_getvar_helper(p->owner, "MFCR2_DOUBLE_ANSWER");
03901    int wants_double_answer = ast_true(double_answer) ? 1 : 0;
03902    if (!double_answer) {
03903       /* this still can result in double answer if the channel context
03904       * was configured that way */
03905       res = openr2_chan_answer_call(p->r2chan);
03906    } else if (wants_double_answer) {
03907       res = openr2_chan_answer_call_with_mode(p->r2chan, OR2_ANSWER_DOUBLE);
03908    } else {
03909       res = openr2_chan_answer_call_with_mode(p->r2chan, OR2_ANSWER_SIMPLE);
03910    }
03911 #else
03912    res = openr2_chan_answer_call(p->r2chan);
03913 #endif
03914    return res;
03915 }
03916 
03917 
03918 
03919 /* should be called with the ast_channel locked */
03920 static openr2_calling_party_category_t dahdi_r2_get_channel_category(struct ast_channel *c)
03921 {
03922    openr2_calling_party_category_t cat;
03923    const char *catstr = pbx_builtin_getvar_helper(c, "MFCR2_CATEGORY");
03924    struct dahdi_pvt *p = c->tech_pvt;
03925    if (ast_strlen_zero(catstr)) {
03926       ast_debug(1, "No MFC/R2 category specified for chan %s, using default %s\n",
03927             c->name, openr2_proto_get_category_string(p->mfcr2_category));
03928       return p->mfcr2_category;
03929    }
03930    if ((cat = openr2_proto_get_category(catstr)) == OR2_CALLING_PARTY_CATEGORY_UNKNOWN) {
03931       ast_log(LOG_WARNING, "Invalid category specified '%s' for chan %s, using default %s\n",
03932             catstr, c->name, openr2_proto_get_category_string(p->mfcr2_category));
03933       return p->mfcr2_category;
03934    }
03935    ast_debug(1, "Using category %s\n", catstr);
03936    return cat;
03937 }
03938 
03939 static void dahdi_r2_on_call_init(openr2_chan_t *r2chan)
03940 {
03941    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
03942    ast_mutex_lock(&p->lock);
03943    if (p->mfcr2call) {
03944       ast_mutex_unlock(&p->lock);
03945       /* TODO: This can happen when some other thread just finished dahdi_request requesting this very same
03946          interface but has not yet seized the line (dahdi_call), and the far end wins and seize the line,
03947          can we avoid this somehow?, at this point when dahdi_call send the seize, it is likely that since
03948          the other end will see our seize as a forced release and drop the call, we will see an invalid
03949          pattern that will be seen and treated as protocol error. */
03950       ast_log(LOG_ERROR, "Collision of calls on chan %d detected!.\n", openr2_chan_get_number(r2chan));
03951       return;
03952    }
03953    p->mfcr2call = 1;
03954    /* better safe than sorry ... */
03955    p->cid_name[0] = '\0';
03956    p->cid_num[0] = '\0';
03957    p->cid_subaddr[0] = '\0';
03958    p->rdnis[0] = '\0';
03959    p->exten[0] = '\0';
03960    p->mfcr2_ani_index = '\0';
03961    p->mfcr2_dnis_index = '\0';
03962    p->mfcr2_dnis_matched = 0;
03963    p->mfcr2_answer_pending = 0;
03964    p->mfcr2_call_accepted = 0;
03965    ast_mutex_unlock(&p->lock);
03966    ast_verbose("New MFC/R2 call detected on chan %d.\n", openr2_chan_get_number(r2chan));
03967 }
03968 
03969 static void dahdi_r2_on_hardware_alarm(openr2_chan_t *r2chan, int alarm)
03970 {
03971    int res;
03972    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
03973    ast_mutex_lock(&p->lock);
03974    p->inalarm = alarm ? 1 : 0;
03975    if (p->inalarm) {
03976       res = get_alarms(p);
03977       handle_alarms(p, res);
03978    } else {
03979       handle_clear_alarms(p);
03980    }
03981    ast_mutex_unlock(&p->lock);
03982 }
03983 
03984 static void dahdi_r2_on_os_error(openr2_chan_t *r2chan, int errorcode)
03985 {
03986    ast_log(LOG_ERROR, "OS error on chan %d: %s\n", openr2_chan_get_number(r2chan), strerror(errorcode));
03987 }
03988 
03989 static void dahdi_r2_on_protocol_error(openr2_chan_t *r2chan, openr2_protocol_error_t reason)
03990 {
03991    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
03992    ast_log(LOG_ERROR, "MFC/R2 protocol error on chan %d: %s\n", openr2_chan_get_number(r2chan), openr2_proto_get_error(reason));
03993    if (p->owner) {
03994       p->owner->hangupcause = AST_CAUSE_PROTOCOL_ERROR;
03995       p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
03996    }
03997    ast_mutex_lock(&p->lock);
03998    p->mfcr2call = 0;
03999    ast_mutex_unlock(&p->lock);
04000 }
04001 
04002 static void dahdi_r2_disconnect_call(struct dahdi_pvt *p, openr2_call_disconnect_cause_t cause)
04003 {
04004    if (openr2_chan_disconnect_call(p->r2chan, cause)) {
04005       ast_log(LOG_NOTICE, "Bad! failed to disconnect call on channel %d with reason %s, hope for the best!\n",
04006          p->channel, openr2_proto_get_disconnect_string(cause));
04007       /* force the chan to idle and release the call flag now since we will not see a clean on_call_end */
04008       openr2_chan_set_idle(p->r2chan);
04009       ast_mutex_lock(&p->lock);
04010       p->mfcr2call = 0;
04011       ast_mutex_unlock(&p->lock);
04012    }
04013 }
04014 
04015 static void dahdi_r2_on_call_offered(openr2_chan_t *r2chan, const char *ani, const char *dnis, openr2_calling_party_category_t category)
04016 {
04017    struct dahdi_pvt *p;
04018    struct ast_channel *c;
04019    ast_verbose("MFC/R2 call offered on chan %d. ANI = %s, DNIS = %s, Category = %s\n",
04020          openr2_chan_get_number(r2chan), ani ? ani : "(restricted)", dnis,
04021          openr2_proto_get_category_string(category));
04022    p = openr2_chan_get_client_data(r2chan);
04023    /* if collect calls are not allowed and this is a collect call, reject it! */
04024    if (!p->mfcr2_allow_collect_calls && category == OR2_CALLING_PARTY_CATEGORY_COLLECT_CALL) {
04025       ast_log(LOG_NOTICE, "Rejecting MFC/R2 collect call\n");
04026       dahdi_r2_disconnect_call(p, OR2_CAUSE_COLLECT_CALL_REJECTED);
04027       return;
04028    }
04029    ast_mutex_lock(&p->lock);
04030    p->mfcr2_recvd_category = category;
04031    /* if we're not supposed to use CID, clear whatever we have */
04032    if (!p->use_callerid) {
04033       ast_log(LOG_DEBUG, "No CID allowed in configuration, CID is being cleared!\n");
04034       p->cid_num[0] = 0;
04035       p->cid_name[0] = 0;
04036    }
04037    /* if we're supposed to answer immediately, clear DNIS and set 's' exten */
04038    if (p->immediate || !openr2_context_get_max_dnis(openr2_chan_get_context(r2chan))) {
04039       ast_log(LOG_DEBUG, "Setting exten => s because of immediate or 0 DNIS configured\n");
04040       p->exten[0] = 's';
04041       p->exten[1] = 0;
04042    }
04043    ast_mutex_unlock(&p->lock);
04044    if (!ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
04045       ast_log(LOG_NOTICE, "MFC/R2 call on channel %d requested non-existent extension '%s' in context '%s'. Rejecting call.\n",
04046             p->channel, p->exten, p->context);
04047       dahdi_r2_disconnect_call(p, OR2_CAUSE_UNALLOCATED_NUMBER);
04048       return;
04049    }
04050    if (!p->mfcr2_accept_on_offer) {
04051       /* The user wants us to start the PBX thread right away without accepting the call first */
04052       c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, NULL);
04053       if (c) {
04054          /* Done here, don't disable reading now since we still need to generate MF tones to accept
04055             the call or reject it and detect the tone off condition of the other end, all of this
04056             will be done in the PBX thread now */
04057          return;
04058       }
04059       ast_log(LOG_WARNING, "Unable to create PBX channel in DAHDI channel %d\n", p->channel);
04060       dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER);
04061    } else if (p->mfcr2_charge_calls) {
04062       ast_log(LOG_DEBUG, "Accepting MFC/R2 call with charge on chan %d\n", p->channel);
04063       openr2_chan_accept_call(r2chan, OR2_CALL_WITH_CHARGE);
04064    } else {
04065       ast_log(LOG_DEBUG, "Accepting MFC/R2 call with no charge on chan %d\n", p->channel);
04066       openr2_chan_accept_call(r2chan, OR2_CALL_NO_CHARGE);
04067    }
04068 }
04069 
04070 static void dahdi_r2_on_call_end(openr2_chan_t *r2chan)
04071 {
04072    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04073    ast_verbose("MFC/R2 call end on channel %d\n", p->channel);
04074    ast_mutex_lock(&p->lock);
04075    p->mfcr2call = 0;
04076    ast_mutex_unlock(&p->lock);
04077 }
04078 
04079 static void dahdi_enable_ec(struct dahdi_pvt *p);
04080 static void dahdi_r2_on_call_accepted(openr2_chan_t *r2chan, openr2_call_mode_t mode)
04081 {
04082    struct dahdi_pvt *p = NULL;
04083    struct ast_channel *c = NULL;
04084    p = openr2_chan_get_client_data(r2chan);
04085    dahdi_enable_ec(p);
04086    p->mfcr2_call_accepted = 1;
04087    /* if it's an incoming call ... */
04088    if (OR2_DIR_BACKWARD == openr2_chan_get_direction(r2chan)) {
04089       ast_verbose("MFC/R2 call has been accepted on backward channel %d\n", openr2_chan_get_number(r2chan));
04090       /* If accept on offer is not set, it means at this point the PBX thread is already
04091          launched (was launched in the 'on call offered' handler) and therefore this callback
04092          is being executed already in the PBX thread rather than the monitor thread, don't launch
04093          any other thread, just disable the openr2 reading and answer the call if needed */
04094       if (!p->mfcr2_accept_on_offer) {
04095          openr2_chan_disable_read(r2chan);
04096          if (p->mfcr2_answer_pending) {
04097             ast_log(LOG_DEBUG, "Answering MFC/R2 call after accepting it on chan %d\n", openr2_chan_get_number(r2chan));
04098             dahdi_r2_answer(p);
04099          }
04100          return;
04101       }
04102       c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, NULL);
04103       if (c) {
04104          /* chan_dahdi will take care of reading from now on in the PBX thread, tell the
04105             library to forget about it */
04106          openr2_chan_disable_read(r2chan);
04107          return;
04108       }
04109       ast_log(LOG_WARNING, "Unable to create PBX channel in DAHDI channel %d\n", p->channel);
04110       /* failed to create the channel, bail out and report it as an out of order line */
04111       dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER);
04112       return;
04113    }
04114    /* this is an outgoing call, no need to launch the PBX thread, most likely we're in one already */
04115    ast_verbose("MFC/R2 call has been accepted on forward channel %d\n", p->channel);
04116    p->subs[SUB_REAL].needringing = 1;
04117    p->dialing = 0;
04118    /* chan_dahdi will take care of reading from now on in the PBX thread, tell the library to forget about it */
04119    openr2_chan_disable_read(r2chan);
04120 }
04121 
04122 static void dahdi_r2_on_call_answered(openr2_chan_t *r2chan)
04123 {
04124    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04125    ast_verbose("MFC/R2 call has been answered on channel %d\n", openr2_chan_get_number(r2chan));
04126    p->subs[SUB_REAL].needanswer = 1;
04127 }
04128 
04129 static void dahdi_r2_on_call_read(openr2_chan_t *r2chan, const unsigned char *buf, int buflen)
04130 {
04131    /*ast_log(LOG_DEBUG, "Read data from dahdi channel %d\n", openr2_chan_get_number(r2chan));*/
04132 }
04133 
04134 static int dahdi_r2_cause_to_ast_cause(openr2_call_disconnect_cause_t cause)
04135 {
04136    switch (cause) {
04137    case OR2_CAUSE_BUSY_NUMBER:
04138       return AST_CAUSE_BUSY;
04139    case OR2_CAUSE_NETWORK_CONGESTION:
04140       return AST_CAUSE_CONGESTION;
04141    case OR2_CAUSE_OUT_OF_ORDER:
04142       return AST_CAUSE_DESTINATION_OUT_OF_ORDER;
04143    case OR2_CAUSE_UNALLOCATED_NUMBER:
04144       return AST_CAUSE_UNREGISTERED;
04145    case OR2_CAUSE_NO_ANSWER:
04146       return AST_CAUSE_NO_ANSWER;
04147    case OR2_CAUSE_NORMAL_CLEARING:
04148       return AST_CAUSE_NORMAL_CLEARING;
04149    case OR2_CAUSE_UNSPECIFIED:
04150    default:
04151       return AST_CAUSE_NOTDEFINED;
04152    }
04153 }
04154 
04155 static void dahdi_r2_on_call_disconnect(openr2_chan_t *r2chan, openr2_call_disconnect_cause_t cause)
04156 {
04157    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04158    ast_verbose("MFC/R2 call disconnected on channel %d\n", openr2_chan_get_number(r2chan));
04159    ast_mutex_lock(&p->lock);
04160    if (!p->owner) {
04161       ast_mutex_unlock(&p->lock);
04162       /* no owner, therefore we can't use dahdi_hangup to disconnect, do it right now */
04163       dahdi_r2_disconnect_call(p, OR2_CAUSE_NORMAL_CLEARING);
04164       return;
04165    }
04166    /* when we have an owner we don't call dahdi_r2_disconnect_call here, that will
04167       be done in dahdi_hangup */
04168    if (p->owner->_state == AST_STATE_UP) {
04169       p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
04170       ast_mutex_unlock(&p->lock);
04171    } else if (openr2_chan_get_direction(r2chan) == OR2_DIR_FORWARD) {
04172       /* being the forward side we must report what happened to the call to whoever requested it */
04173       switch (cause) {
04174       case OR2_CAUSE_BUSY_NUMBER:
04175          p->subs[SUB_REAL].needbusy = 1;
04176          break;
04177       case OR2_CAUSE_NETWORK_CONGESTION:
04178       case OR2_CAUSE_OUT_OF_ORDER:
04179       case OR2_CAUSE_UNALLOCATED_NUMBER:
04180       case OR2_CAUSE_NO_ANSWER:
04181       case OR2_CAUSE_UNSPECIFIED:
04182       case OR2_CAUSE_NORMAL_CLEARING:
04183          p->subs[SUB_REAL].needcongestion = 1;
04184          break;
04185       default:
04186          p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
04187       }
04188       ast_mutex_unlock(&p->lock);
04189    } else {
04190       ast_mutex_unlock(&p->lock);
04191       /* being the backward side and not UP yet, we only need to request hangup */
04192       /* TODO: what about doing this same thing when were AST_STATE_UP? */
04193       ast_queue_hangup_with_cause(p->owner, dahdi_r2_cause_to_ast_cause(cause));
04194    }
04195 }
04196 
04197 static void dahdi_r2_write_log(openr2_log_level_t level, char *logmessage)
04198 {
04199    switch (level) {
04200    case OR2_LOG_NOTICE:
04201       ast_verbose("%s", logmessage);
04202       break;
04203    case OR2_LOG_WARNING:
04204       ast_log(LOG_WARNING, "%s", logmessage);
04205       break;
04206    case OR2_LOG_ERROR:
04207       ast_log(LOG_ERROR, "%s", logmessage);
04208       break;
04209    case OR2_LOG_STACK_TRACE:
04210    case OR2_LOG_MF_TRACE:
04211    case OR2_LOG_CAS_TRACE:
04212    case OR2_LOG_DEBUG:
04213    case OR2_LOG_EX_DEBUG:
04214       ast_log(LOG_DEBUG, "%s", logmessage);
04215       break;
04216    default:
04217       ast_log(LOG_WARNING, "We should handle logging level %d here.\n", level);
04218       ast_log(LOG_DEBUG, "%s", logmessage);
04219       break;
04220    }
04221 }
04222 
04223 static void dahdi_r2_on_line_blocked(openr2_chan_t *r2chan)
04224 {
04225    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04226    ast_mutex_lock(&p->lock);
04227    p->remotelyblocked = 1;
04228    ast_mutex_unlock(&p->lock);
04229    ast_log(LOG_NOTICE, "Far end blocked on chan %d\n", openr2_chan_get_number(r2chan));
04230 }
04231 
04232 static void dahdi_r2_on_line_idle(openr2_chan_t *r2chan)
04233 {
04234    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04235    ast_mutex_lock(&p->lock);
04236    p->remotelyblocked = 0;
04237    ast_mutex_unlock(&p->lock);
04238    ast_log(LOG_NOTICE, "Far end unblocked on chan %d\n", openr2_chan_get_number(r2chan));
04239 }
04240 
04241 static void dahdi_r2_on_context_log(openr2_context_t *r2context, openr2_log_level_t level, const char *fmt, va_list ap)
04242    __attribute__((format (printf, 3, 0)));
04243 static void dahdi_r2_on_context_log(openr2_context_t *r2context, openr2_log_level_t level, const char *fmt, va_list ap)
04244 {
04245 #define CONTEXT_TAG "Context - "
04246    char logmsg[256];
04247    char completemsg[sizeof(logmsg) + sizeof(CONTEXT_TAG) - 1];
04248    vsnprintf(logmsg, sizeof(logmsg), fmt, ap);
04249    snprintf(completemsg, sizeof(completemsg), CONTEXT_TAG "%s", logmsg);
04250    dahdi_r2_write_log(level, completemsg);
04251 #undef CONTEXT_TAG
04252 }
04253 
04254 static void dahdi_r2_on_chan_log(openr2_chan_t *r2chan, openr2_log_level_t level, const char *fmt, va_list ap)
04255    __attribute__((format (printf, 3, 0)));
04256 static void dahdi_r2_on_chan_log(openr2_chan_t *r2chan, openr2_log_level_t level, const char *fmt, va_list ap)
04257 {
04258 #define CHAN_TAG "Chan "
04259    char logmsg[256];
04260    char completemsg[sizeof(logmsg) + sizeof(CHAN_TAG) - 1];
04261    vsnprintf(logmsg, sizeof(logmsg), fmt, ap);
04262    snprintf(completemsg, sizeof(completemsg), CHAN_TAG "%d - %s", openr2_chan_get_number(r2chan), logmsg);
04263    dahdi_r2_write_log(level, completemsg);
04264 }
04265 
04266 static int dahdi_r2_on_dnis_digit_received(openr2_chan_t *r2chan, char digit)
04267 {
04268    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04269    /* if 'immediate' is set, let's stop requesting DNIS */
04270    if (p->immediate) {
04271       return 0;
04272    }
04273    p->exten[p->mfcr2_dnis_index] = digit;
04274    p->rdnis[p->mfcr2_dnis_index] = digit;
04275    p->mfcr2_dnis_index++;
04276    p->exten[p->mfcr2_dnis_index] = 0;
04277    p->rdnis[p->mfcr2_dnis_index] = 0;
04278    /* if the DNIS is a match and cannot match more, stop requesting DNIS */
04279    if ((p->mfcr2_dnis_matched ||
04280        (ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num) && (p->mfcr2_dnis_matched = 1))) &&
04281        !ast_matchmore_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
04282       return 0;
04283    }
04284    /* otherwise keep going */
04285    return 1;
04286 }
04287 
04288 static void dahdi_r2_on_ani_digit_received(openr2_chan_t *r2chan, char digit)
04289 {
04290    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04291    p->cid_num[p->mfcr2_ani_index] = digit;
04292    p->cid_name[p->mfcr2_ani_index] = digit;
04293    p->mfcr2_ani_index++;
04294    p->cid_num[p->mfcr2_ani_index] = 0;
04295    p->cid_name[p->mfcr2_ani_index] = 0;
04296 }
04297 
04298 static void dahdi_r2_on_billing_pulse_received(openr2_chan_t *r2chan)
04299 {
04300    ast_verbose("MFC/R2 billing pulse received on channel %d\n", openr2_chan_get_number(r2chan));
04301 }
04302 
04303 static openr2_event_interface_t dahdi_r2_event_iface = {
04304    .on_call_init = dahdi_r2_on_call_init,
04305    .on_call_offered = dahdi_r2_on_call_offered,
04306    .on_call_accepted = dahdi_r2_on_call_accepted,
04307    .on_call_answered = dahdi_r2_on_call_answered,
04308    .on_call_disconnect = dahdi_r2_on_call_disconnect,
04309    .on_call_end = dahdi_r2_on_call_end,
04310    .on_call_read = dahdi_r2_on_call_read,
04311    .on_hardware_alarm = dahdi_r2_on_hardware_alarm,
04312    .on_os_error = dahdi_r2_on_os_error,
04313    .on_protocol_error = dahdi_r2_on_protocol_error,
04314    .on_line_blocked = dahdi_r2_on_line_blocked,
04315    .on_line_idle = dahdi_r2_on_line_idle,
04316    /* cast seems to be needed to get rid of the annoying warning regarding format attribute  */
04317    .on_context_log = (openr2_handle_context_logging_func)dahdi_r2_on_context_log,
04318    .on_dnis_digit_received = dahdi_r2_on_dnis_digit_received,
04319    .on_ani_digit_received = dahdi_r2_on_ani_digit_received,
04320    /* so far we do nothing with billing pulses */
04321    .on_billing_pulse_received = dahdi_r2_on_billing_pulse_received
04322 };
04323 
04324 static inline int16_t dahdi_r2_alaw_to_linear(uint8_t sample)
04325 {
04326    return AST_ALAW(sample);
04327 }
04328 
04329 static inline uint8_t dahdi_r2_linear_to_alaw(int sample)
04330 {
04331    return AST_LIN2A(sample);
04332 }
04333 
04334 static openr2_transcoder_interface_t dahdi_r2_transcode_iface = {
04335    dahdi_r2_alaw_to_linear,
04336    dahdi_r2_linear_to_alaw
04337 };
04338 
04339 #endif /* HAVE_OPENR2 */
04340 
04341 static void swap_subs(struct dahdi_pvt *p, int a, int b)
04342 {
04343    int tchan;
04344    int tinthreeway;
04345    struct ast_channel *towner;
04346 
04347    ast_debug(1, "Swapping %d and %d\n", a, b);
04348 
04349    tchan = p->subs[a].chan;
04350    towner = p->subs[a].owner;
04351    tinthreeway = p->subs[a].inthreeway;
04352 
04353    p->subs[a].chan = p->subs[b].chan;
04354    p->subs[a].owner = p->subs[b].owner;
04355    p->subs[a].inthreeway = p->subs[b].inthreeway;
04356 
04357    p->subs[b].chan = tchan;
04358    p->subs[b].owner = towner;
04359    p->subs[b].inthreeway = tinthreeway;
04360 
04361    if (p->subs[a].owner)
04362       ast_channel_set_fd(p->subs[a].owner, 0, p->subs[a].dfd);
04363    if (p->subs[b].owner)
04364       ast_channel_set_fd(p->subs[b].owner, 0, p->subs[b].dfd);
04365    wakeup_sub(p, a);
04366    wakeup_sub(p, b);
04367 }
04368 
04369 static int dahdi_open(char *fn)
04370 {
04371    int fd;
04372    int isnum;
04373    int chan = 0;
04374    int bs;
04375    int x;
04376    isnum = 1;
04377    for (x = 0; x < strlen(fn); x++) {
04378       if (!isdigit(fn[x])) {
04379          isnum = 0;
04380          break;
04381       }
04382    }
04383    if (isnum) {
04384       chan = atoi(fn);
04385       if (chan < 1) {
04386          ast_log(LOG_WARNING, "Invalid channel number '%s'\n", fn);
04387          return -1;
04388       }
04389       fn = "/dev/dahdi/channel";
04390    }
04391    fd = open(fn, O_RDWR | O_NONBLOCK);
04392    if (fd < 0) {
04393       ast_log(LOG_WARNING, "Unable to open '%s': %s\n", fn, strerror(errno));
04394       return -1;
04395    }
04396    if (chan) {
04397       if (ioctl(fd, DAHDI_SPECIFY, &chan)) {
04398          x = errno;
04399          close(fd);
04400          errno = x;
04401          ast_log(LOG_WARNING, "Unable to specify channel %d: %s\n", chan, strerror(errno));
04402          return -1;
04403       }
04404    }
04405    bs = READ_SIZE;
04406    if (ioctl(fd, DAHDI_SET_BLOCKSIZE, &bs) == -1) {
04407       ast_log(LOG_WARNING, "Unable to set blocksize '%d': %s\n", bs,  strerror(errno));
04408       x = errno;
04409       close(fd);
04410       errno = x;
04411       return -1;
04412    }
04413    return fd;
04414 }
04415 
04416 static void dahdi_close(int fd)
04417 {
04418    if (fd > 0)
04419       close(fd);
04420 }
04421 
04422 static void dahdi_close_sub(struct dahdi_pvt *chan_pvt, int sub_num)
04423 {
04424    dahdi_close(chan_pvt->subs[sub_num].dfd);
04425    chan_pvt->subs[sub_num].dfd = -1;
04426 }
04427 
04428 #if defined(HAVE_PRI)
04429 static void dahdi_close_pri_fd(struct dahdi_pri *pri, int fd_num)
04430 {
04431    dahdi_close(pri->pri.fds[fd_num]);
04432    pri->pri.fds[fd_num] = -1;
04433 }
04434 #endif   /* defined(HAVE_PRI) */
04435 
04436 #if defined(HAVE_SS7)
04437 static void dahdi_close_ss7_fd(struct dahdi_ss7 *ss7, int fd_num)
04438 {
04439    dahdi_close(ss7->ss7.fds[fd_num]);
04440    ss7->ss7.fds[fd_num] = -1;
04441 }
04442 #endif   /* defined(HAVE_SS7) */
04443 
04444 static int dahdi_setlinear(int dfd, int linear)
04445 {
04446    return ioctl(dfd, DAHDI_SETLINEAR, &linear);
04447 }
04448 
04449 
04450 static int alloc_sub(struct dahdi_pvt *p, int x)
04451 {
04452    struct dahdi_bufferinfo bi;
04453    int res;
04454    if (p->subs[x].dfd >= 0) {
04455       ast_log(LOG_WARNING, "%s subchannel of %d already in use\n", subnames[x], p->channel);
04456       return -1;
04457    }
04458 
04459    p->subs[x].dfd = dahdi_open("/dev/dahdi/pseudo");
04460    if (p->subs[x].dfd <= -1) {
04461       ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno));
04462       return -1;
04463    }
04464 
04465    res = ioctl(p->subs[x].dfd, DAHDI_GET_BUFINFO, &bi);
04466    if (!res) {
04467       bi.txbufpolicy = p->buf_policy;
04468       bi.rxbufpolicy = p->buf_policy;
04469       bi.numbufs = p->buf_no;
04470       res = ioctl(p->subs[x].dfd, DAHDI_SET_BUFINFO, &bi);
04471       if (res < 0) {
04472          ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", x, strerror(errno));
04473       }
04474    } else
04475       ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", x, strerror(errno));
04476 
04477    if (ioctl(p->subs[x].dfd, DAHDI_CHANNO, &p->subs[x].chan) == 1) {
04478       ast_log(LOG_WARNING, "Unable to get channel number for pseudo channel on FD %d: %s\n", p->subs[x].dfd, strerror(errno));
04479       dahdi_close_sub(p, x);
04480       p->subs[x].dfd = -1;
04481       return -1;
04482    }
04483    ast_debug(1, "Allocated %s subchannel on FD %d channel %d\n", subnames[x], p->subs[x].dfd, p->subs[x].chan);
04484    return 0;
04485 }
04486 
04487 static int unalloc_sub(struct dahdi_pvt *p, int x)
04488 {
04489    if (!x) {
04490       ast_log(LOG_WARNING, "Trying to unalloc the real channel %d?!?\n", p->channel);
04491       return -1;
04492    }
04493    ast_debug(1, "Released sub %d of channel %d\n", x, p->channel);
04494    dahdi_close_sub(p, x);
04495    p->subs[x].linear = 0;
04496    p->subs[x].chan = 0;
04497    p->subs[x].owner = NULL;
04498    p->subs[x].inthreeway = 0;
04499    p->polarity = POLARITY_IDLE;
04500    memset(&p->subs[x].curconf, 0, sizeof(p->subs[x].curconf));
04501    return 0;
04502 }
04503 
04504 static int digit_to_dtmfindex(char digit)
04505 {
04506    if (isdigit(digit))
04507       return DAHDI_TONE_DTMF_BASE + (digit - '0');
04508    else if (digit >= 'A' && digit <= 'D')
04509       return DAHDI_TONE_DTMF_A + (digit - 'A');
04510    else if (digit >= 'a' && digit <= 'd')
04511       return DAHDI_TONE_DTMF_A + (digit - 'a');
04512    else if (digit == '*')
04513       return DAHDI_TONE_DTMF_s;
04514    else if (digit == '#')
04515       return DAHDI_TONE_DTMF_p;
04516    else
04517       return -1;
04518 }
04519 
04520 static int dahdi_digit_begin(struct ast_channel *chan, char digit)
04521 {
04522    struct dahdi_pvt *pvt;
04523    int idx;
04524    int dtmf = -1;
04525    int res;
04526 
04527    pvt = chan->tech_pvt;
04528 
04529    ast_mutex_lock(&pvt->lock);
04530 
04531    idx = dahdi_get_index(chan, pvt, 0);
04532 
04533    if ((idx != SUB_REAL) || !pvt->owner)
04534       goto out;
04535 
04536 #ifdef HAVE_PRI
04537    switch (pvt->sig) {
04538    case SIG_PRI_LIB_HANDLE_CASES:
04539       res = sig_pri_digit_begin(pvt->sig_pvt, chan, digit);
04540       if (!res)
04541          goto out;
04542       break;
04543    default:
04544       break;
04545    }
04546 #endif
04547    if ((dtmf = digit_to_dtmfindex(digit)) == -1)
04548       goto out;
04549 
04550    if (pvt->pulse || ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &dtmf)) {
04551       struct dahdi_dialoperation zo = {
04552          .op = DAHDI_DIAL_OP_APPEND,
04553       };
04554 
04555       zo.dialstr[0] = 'T';
04556       zo.dialstr[1] = digit;
04557       zo.dialstr[2] = '\0';
04558       if ((res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo)))
04559          ast_log(LOG_WARNING, "Channel %s couldn't dial digit %c: %s\n",
04560             chan->name, digit, strerror(errno));
04561       else
04562          pvt->dialing = 1;
04563    } else {
04564       ast_debug(1, "Channel %s started VLDTMF digit '%c'\n",
04565          chan->name, digit);
04566       pvt->dialing = 1;
04567       pvt->begindigit = digit;
04568    }
04569 
04570 out:
04571    ast_mutex_unlock(&pvt->lock);
04572 
04573    return 0;
04574 }
04575 
04576 static int dahdi_digit_end(struct ast_channel *chan, char digit, unsigned int duration)
04577 {
04578    struct dahdi_pvt *pvt;
04579    int res = 0;
04580    int idx;
04581    int x;
04582 
04583    pvt = chan->tech_pvt;
04584 
04585    ast_mutex_lock(&pvt->lock);
04586 
04587    idx = dahdi_get_index(chan, pvt, 0);
04588 
04589    if ((idx != SUB_REAL) || !pvt->owner || pvt->pulse)
04590       goto out;
04591 
04592 #ifdef HAVE_PRI
04593    /* This means that the digit was already sent via PRI signalling */
04594    if (dahdi_sig_pri_lib_handles(pvt->sig) && !pvt->begindigit) {
04595       goto out;
04596    }
04597 #endif
04598 
04599    if (pvt->begindigit) {
04600       x = -1;
04601       ast_debug(1, "Channel %s ending VLDTMF digit '%c'\n",
04602          chan->name, digit);
04603       res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &x);
04604       pvt->dialing = 0;
04605       pvt->begindigit = 0;
04606    }
04607 
04608 out:
04609    ast_mutex_unlock(&pvt->lock);
04610 
04611    return res;
04612 }
04613 
04614 static const char * const events[] = {
04615    "No event",
04616    "On hook",
04617    "Ring/Answered",
04618    "Wink/Flash",
04619    "Alarm",
04620    "No more alarm",
04621    "HDLC Abort",
04622    "HDLC Overrun",
04623    "HDLC Bad FCS",
04624    "Dial Complete",
04625    "Ringer On",
04626    "Ringer Off",
04627    "Hook Transition Complete",
04628    "Bits Changed",
04629    "Pulse Start",
04630    "Timer Expired",
04631    "Timer Ping",
04632    "Polarity Reversal",
04633    "Ring Begin",
04634 };
04635 
04636 static struct {
04637    int alarm;
04638    char *name;
04639 } alarms[] = {
04640    { DAHDI_ALARM_RED, "Red Alarm" },
04641    { DAHDI_ALARM_YELLOW, "Yellow Alarm" },
04642    { DAHDI_ALARM_BLUE, "Blue Alarm" },
04643    { DAHDI_ALARM_RECOVER, "Recovering" },
04644    { DAHDI_ALARM_LOOPBACK, "Loopback" },
04645    { DAHDI_ALARM_NOTOPEN, "Not Open" },
04646    { DAHDI_ALARM_NONE, "None" },
04647 };
04648 
04649 static char *alarm2str(int alm)
04650 {
04651    int x;
04652    for (x = 0; x < ARRAY_LEN(alarms); x++) {
04653       if (alarms[x].alarm & alm)
04654          return alarms[x].name;
04655    }
04656    return alm ? "Unknown Alarm" : "No Alarm";
04657 }
04658 
04659 static const char *event2str(int event)
04660 {
04661    static char buf[256];
04662    if ((event < (ARRAY_LEN(events))) && (event > -1))
04663       return events[event];
04664    sprintf(buf, "Event %d", event); /* safe */
04665    return buf;
04666 }
04667 
04668 static char *dahdi_sig2str(int sig)
04669 {
04670    static char buf[256];
04671    switch (sig) {
04672    case SIG_EM:
04673       return "E & M Immediate";
04674    case SIG_EMWINK:
04675       return "E & M Wink";
04676    case SIG_EM_E1:
04677       return "E & M E1";
04678    case SIG_FEATD:
04679       return "Feature Group D (DTMF)";
04680    case SIG_FEATDMF:
04681       return "Feature Group D (MF)";
04682    case SIG_FEATDMF_TA:
04683       return "Feature Groud D (MF) Tandem Access";
04684    case SIG_FEATB:
04685       return "Feature Group B (MF)";
04686    case SIG_E911:
04687       return "E911 (MF)";
04688    case SIG_FGC_CAMA:
04689       return "FGC/CAMA (Dialpulse)";
04690    case SIG_FGC_CAMAMF:
04691       return "FGC/CAMA (MF)";
04692    case SIG_FXSLS:
04693       return "FXS Loopstart";
04694    case SIG_FXSGS:
04695       return "FXS Groundstart";
04696    case SIG_FXSKS:
04697       return "FXS Kewlstart";
04698    case SIG_FXOLS:
04699       return "FXO Loopstart";
04700    case SIG_FXOGS:
04701       return "FXO Groundstart";
04702    case SIG_FXOKS:
04703       return "FXO Kewlstart";
04704    case SIG_PRI:
04705       return "ISDN PRI";
04706    case SIG_BRI:
04707       return "ISDN BRI Point to Point";
04708    case SIG_BRI_PTMP:
04709       return "ISDN BRI Point to MultiPoint";
04710    case SIG_SS7:
04711       return "SS7";
04712    case SIG_MFCR2:
04713       return "MFC/R2";
04714    case SIG_SF:
04715       return "SF (Tone) Immediate";
04716    case SIG_SFWINK:
04717       return "SF (Tone) Wink";
04718    case SIG_SF_FEATD:
04719       return "SF (Tone) with Feature Group D (DTMF)";
04720    case SIG_SF_FEATDMF:
04721       return "SF (Tone) with Feature Group D (MF)";
04722    case SIG_SF_FEATB:
04723       return "SF (Tone) with Feature Group B (MF)";
04724    case 0:
04725       return "Pseudo";
04726    default:
04727       snprintf(buf, sizeof(buf), "Unknown signalling %d", sig);
04728       return buf;
04729    }
04730 }
04731 
04732 #define sig2str dahdi_sig2str
04733 
04734 static int conf_add(struct dahdi_pvt *p, struct dahdi_subchannel *c, int idx, int slavechannel)
04735 {
04736    /* If the conference already exists, and we're already in it
04737       don't bother doing anything */
04738    struct dahdi_confinfo zi;
04739 
04740    memset(&zi, 0, sizeof(zi));
04741    zi.chan = 0;
04742 
04743    if (slavechannel > 0) {
04744       /* If we have only one slave, do a digital mon */
04745       zi.confmode = DAHDI_CONF_DIGITALMON;
04746       zi.confno = slavechannel;
04747    } else {
04748       if (!idx) {
04749          /* Real-side and pseudo-side both participate in conference */
04750          zi.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER |
04751             DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER;
04752       } else
04753          zi.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER;
04754       zi.confno = p->confno;
04755    }
04756    if ((zi.confno == c->curconf.confno) && (zi.confmode == c->curconf.confmode))
04757       return 0;
04758    if (c->dfd < 0)
04759       return 0;
04760    if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
04761       ast_log(LOG_WARNING, "Failed to add %d to conference %d/%d: %s\n", c->dfd, zi.confmode, zi.confno, strerror(errno));
04762       return -1;
04763    }
04764    if (slavechannel < 1) {
04765       p->confno = zi.confno;
04766    }
04767    c->curconf = zi;
04768    ast_debug(1, "Added %d to conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
04769    return 0;
04770 }
04771 
04772 static int isourconf(struct dahdi_pvt *p, struct dahdi_subchannel *c)
04773 {
04774    /* If they're listening to our channel, they're ours */
04775    if ((p->channel == c->curconf.confno) && (c->curconf.confmode == DAHDI_CONF_DIGITALMON))
04776       return 1;
04777    /* If they're a talker on our (allocated) conference, they're ours */
04778    if ((p->confno > 0) && (p->confno == c->curconf.confno) && (c->curconf.confmode & DAHDI_CONF_TALKER))
04779       return 1;
04780    return 0;
04781 }
04782 
04783 static int conf_del(struct dahdi_pvt *p, struct dahdi_subchannel *c, int idx)
04784 {
04785    struct dahdi_confinfo zi;
04786    if (/* Can't delete if there's no dfd */
04787       (c->dfd < 0) ||
04788       /* Don't delete from the conference if it's not our conference */
04789       !isourconf(p, c)
04790       /* Don't delete if we don't think it's conferenced at all (implied) */
04791       ) return 0;
04792    memset(&zi, 0, sizeof(zi));
04793    if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
04794       ast_log(LOG_WARNING, "Failed to drop %d from conference %d/%d: %s\n", c->dfd, c->curconf.confmode, c->curconf.confno, strerror(errno));
04795       return -1;
04796    }
04797    ast_debug(1, "Removed %d from conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
04798    memcpy(&c->curconf, &zi, sizeof(c->curconf));
04799    return 0;
04800 }
04801 
04802 static int isslavenative(struct dahdi_pvt *p, struct dahdi_pvt **out)
04803 {
04804    int x;
04805    int useslavenative;
04806    struct dahdi_pvt *slave = NULL;
04807    /* Start out optimistic */
04808    useslavenative = 1;
04809    /* Update conference state in a stateless fashion */
04810    for (x = 0; x < 3; x++) {
04811       /* Any three-way calling makes slave native mode *definitely* out
04812          of the question */
04813       if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway)
04814          useslavenative = 0;
04815    }
04816    /* If we don't have any 3-way calls, check to see if we have
04817       precisely one slave */
04818    if (useslavenative) {
04819       for (x = 0; x < MAX_SLAVES; x++) {
04820          if (p->slaves[x]) {
04821             if (slave) {
04822                /* Whoops already have a slave!  No
04823                   slave native and stop right away */
04824                slave = NULL;
04825                useslavenative = 0;
04826                break;
04827             } else {
04828                /* We have one slave so far */
04829                slave = p->slaves[x];
04830             }
04831          }
04832       }
04833    }
04834    /* If no slave, slave native definitely out */
04835    if (!slave)
04836       useslavenative = 0;
04837    else if (slave->law != p->law) {
04838       useslavenative = 0;
04839       slave = NULL;
04840    }
04841    if (out)
04842       *out = slave;
04843    return useslavenative;
04844 }
04845 
04846 static int reset_conf(struct dahdi_pvt *p)
04847 {
04848    p->confno = -1;
04849    memset(&p->subs[SUB_REAL].curconf, 0, sizeof(p->subs[SUB_REAL].curconf));
04850    if (p->subs[SUB_REAL].dfd > -1) {
04851       struct dahdi_confinfo zi;
04852 
04853       memset(&zi, 0, sizeof(zi));
04854       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &zi))
04855          ast_log(LOG_WARNING, "Failed to reset conferencing on channel %d: %s\n", p->channel, strerror(errno));
04856    }
04857    return 0;
04858 }
04859 
04860 static int update_conf(struct dahdi_pvt *p)
04861 {
04862    int needconf = 0;
04863    int x;
04864    int useslavenative;
04865    struct dahdi_pvt *slave = NULL;
04866 
04867    useslavenative = isslavenative(p, &slave);
04868    /* Start with the obvious, general stuff */
04869    for (x = 0; x < 3; x++) {
04870       /* Look for three way calls */
04871       if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) {
04872          conf_add(p, &p->subs[x], x, 0);
04873          needconf++;
04874       } else {
04875          conf_del(p, &p->subs[x], x);
04876       }
04877    }
04878    /* If we have a slave, add him to our conference now. or DAX
04879       if this is slave native */
04880    for (x = 0; x < MAX_SLAVES; x++) {
04881       if (p->slaves[x]) {
04882          if (useslavenative)
04883             conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
04884          else {
04885             conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
04886             needconf++;
04887          }
04888       }
04889    }
04890    /* If we're supposed to be in there, do so now */
04891    if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
04892       if (useslavenative)
04893          conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
04894       else {
04895          conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
04896          needconf++;
04897       }
04898    }
04899    /* If we have a master, add ourselves to his conference */
04900    if (p->master) {
04901       if (isslavenative(p->master, NULL)) {
04902          conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
04903       } else {
04904          conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
04905       }
04906    }
04907    if (!needconf) {
04908       /* Nobody is left (or should be left) in our conference.
04909          Kill it. */
04910       p->confno = -1;
04911    }
04912    ast_debug(1, "Updated conferencing on %d, with %d conference users\n", p->channel, needconf);
04913    return 0;
04914 }
04915 
04916 static void dahdi_enable_ec(struct dahdi_pvt *p)
04917 {
04918    int res;
04919    if (!p)
04920       return;
04921    if (p->echocanon) {
04922       ast_debug(1, "Echo cancellation already on\n");
04923       return;
04924    }
04925    if (p->digital) {
04926       ast_debug(1, "Echo cancellation isn't required on digital connection\n");
04927       return;
04928    }
04929    if (p->echocancel.head.tap_length) {
04930 #if defined(HAVE_PRI) || defined(HAVE_SS7)
04931       switch (p->sig) {
04932 #if defined(HAVE_PRI)
04933       case SIG_PRI_LIB_HANDLE_CASES:
04934          if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
04935             /*
04936              * PRI nobch pseudo channel.  Does not need ec anyway.
04937              * Does not handle ioctl(DAHDI_AUDIOMODE)
04938              */
04939             return;
04940          }
04941          /* Fall through */
04942 #endif   /* defined(HAVE_PRI) */
04943 #if defined(HAVE_SS7)
04944       case SIG_SS7:
04945 #endif   /* defined(HAVE_SS7) */
04946          {
04947             int x = 1;
04948 
04949             res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x);
04950             if (res)
04951                ast_log(LOG_WARNING,
04952                   "Unable to enable audio mode on channel %d (%s)\n",
04953                   p->channel, strerror(errno));
04954          }
04955          break;
04956       default:
04957          break;
04958       }
04959 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
04960       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &p->echocancel);
04961       if (res) {
04962          ast_log(LOG_WARNING, "Unable to enable echo cancellation on channel %d (%s)\n", p->channel, strerror(errno));
04963       } else {
04964          p->echocanon = 1;
04965          ast_debug(1, "Enabled echo cancellation on channel %d\n", p->channel);
04966       }
04967    } else
04968       ast_debug(1, "No echo cancellation requested\n");
04969 }
04970 
04971 static void dahdi_train_ec(struct dahdi_pvt *p)
04972 {
04973    int x;
04974    int res;
04975 
04976    if (p && p->echocanon && p->echotraining) {
04977       x = p->echotraining;
04978       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOTRAIN, &x);
04979       if (res)
04980          ast_log(LOG_WARNING, "Unable to request echo training on channel %d: %s\n", p->channel, strerror(errno));
04981       else
04982          ast_debug(1, "Engaged echo training on channel %d\n", p->channel);
04983    } else {
04984       ast_debug(1, "No echo training requested\n");
04985    }
04986 }
04987 
04988 static void dahdi_disable_ec(struct dahdi_pvt *p)
04989 {
04990    int res;
04991 
04992    if (p->echocanon) {
04993       struct dahdi_echocanparams ecp = { .tap_length = 0 };
04994 
04995       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &ecp);
04996 
04997       if (res)
04998          ast_log(LOG_WARNING, "Unable to disable echo cancellation on channel %d: %s\n", p->channel, strerror(errno));
04999       else
05000          ast_debug(1, "Disabled echo cancellation on channel %d\n", p->channel);
05001    }
05002 
05003    p->echocanon = 0;
05004 }
05005 
05006 /* perform a dynamic range compression transform on the given sample */
05007 static int drc_sample(int sample, float drc)
05008 {
05009    float neg;
05010    float shallow, steep;
05011    float max = SHRT_MAX;
05012    
05013    neg = (sample < 0 ? -1 : 1);
05014    steep = drc*sample;
05015    shallow = neg*(max-max/drc)+(float)sample/drc;
05016    if (abs(steep) < abs(shallow)) {
05017       sample = steep;
05018    }
05019    else {
05020       sample = shallow;
05021    }
05022 
05023    return sample;
05024 }
05025 
05026 
05027 static void fill_txgain(struct dahdi_gains *g, float gain, float drc, int law)
05028 {
05029    int j;
05030    int k;
05031 
05032    float linear_gain = pow(10.0, gain / 20.0);
05033 
05034    switch (law) {
05035    case DAHDI_LAW_ALAW:
05036       for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
05037          if (gain || drc) {
05038             k = AST_ALAW(j);
05039             if (drc) {
05040                k = drc_sample(k, drc);
05041             }
05042             k = (float)k * linear_gain;
05043             if (k > 32767) {
05044                k = 32767;
05045             } else if (k < -32768) {
05046                k = -32768;
05047             }
05048             g->txgain[j] = AST_LIN2A(k);
05049          } else {
05050             g->txgain[j] = j;
05051          }
05052       }
05053       break;
05054    case DAHDI_LAW_MULAW:
05055       for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
05056          if (gain || drc) {
05057             k = AST_MULAW(j);
05058             if (drc) {
05059                k = drc_sample(k, drc);
05060             }
05061             k = (float)k * linear_gain;
05062             if (k > 32767) {
05063                k = 32767;
05064             } else if (k < -32768) {
05065                k = -32768;
05066             }
05067             g->txgain[j] = AST_LIN2MU(k);
05068 
05069          } else {
05070             g->txgain[j] = j;
05071          }
05072       }
05073       break;
05074    }
05075 }
05076 
05077 static void fill_rxgain(struct dahdi_gains *g, float gain, float drc, int law)
05078 {
05079    int j;
05080    int k;
05081    float linear_gain = pow(10.0, gain / 20.0);
05082 
05083    switch (law) {
05084    case DAHDI_LAW_ALAW:
05085       for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
05086          if (gain || drc) {
05087             k = AST_ALAW(j);
05088             if (drc) {
05089                k = drc_sample(k, drc);
05090             }
05091             k = (float)k * linear_gain;
05092             if (k > 32767) {
05093                k = 32767;
05094             } else if (k < -32768) {
05095                k = -32768;
05096             }
05097             g->rxgain[j] = AST_LIN2A(k);
05098          } else {
05099             g->rxgain[j] = j;
05100          }
05101       }
05102       break;
05103    case DAHDI_LAW_MULAW:
05104       for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
05105          if (gain || drc) {
05106             k = AST_MULAW(j);
05107             if (drc) {
05108                k = drc_sample(k, drc);
05109             }
05110             k = (float)k * linear_gain;
05111             if (k > 32767) {
05112                k = 32767;
05113             } else if (k < -32768) {
05114                k = -32768;
05115             }
05116             g->rxgain[j] = AST_LIN2MU(k);
05117          } else {
05118             g->rxgain[j] = j;
05119          }
05120       }
05121       break;
05122    }
05123 }
05124 
05125 static int set_actual_txgain(int fd, float gain, float drc, int law)
05126 {
05127    struct dahdi_gains g;
05128    int res;
05129 
05130    memset(&g, 0, sizeof(g));
05131    res = ioctl(fd, DAHDI_GETGAINS, &g);
05132    if (res) {
05133       ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
05134       return res;
05135    }
05136 
05137    fill_txgain(&g, gain, drc, law);
05138 
05139    return ioctl(fd, DAHDI_SETGAINS, &g);
05140 }
05141 
05142 static int set_actual_rxgain(int fd, float gain, float drc, int law)
05143 {
05144    struct dahdi_gains g;
05145    int res;
05146 
05147    memset(&g, 0, sizeof(g));
05148    res = ioctl(fd, DAHDI_GETGAINS, &g);
05149    if (res) {
05150       ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
05151       return res;
05152    }
05153 
05154    fill_rxgain(&g, gain, drc, law);
05155 
05156    return ioctl(fd, DAHDI_SETGAINS, &g);
05157 }
05158 
05159 static int set_actual_gain(int fd, float rxgain, float txgain, float rxdrc, float txdrc, int law)
05160 {
05161    return set_actual_txgain(fd, txgain, txdrc, law) | set_actual_rxgain(fd, rxgain, rxdrc, law);
05162 }
05163 
05164 static int bump_gains(struct dahdi_pvt *p)
05165 {
05166    int res;
05167 
05168    /* Bump receive gain by value stored in cid_rxgain */
05169    res = set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain + p->cid_rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
05170    if (res) {
05171       ast_log(LOG_WARNING, "Unable to bump gain: %s\n", strerror(errno));
05172       return -1;
05173    }
05174 
05175    return 0;
05176 }
05177 
05178 static int restore_gains(struct dahdi_pvt *p)
05179 {
05180    int res;
05181 
05182    res = set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
05183    if (res) {
05184       ast_log(LOG_WARNING, "Unable to restore gains: %s\n", strerror(errno));
05185       return -1;
05186    }
05187 
05188    return 0;
05189 }
05190 
05191 static inline int dahdi_set_hook(int fd, int hs)
05192 {
05193    int x, res;
05194 
05195    x = hs;
05196    res = ioctl(fd, DAHDI_HOOK, &x);
05197 
05198    if (res < 0) {
05199       if (errno == EINPROGRESS)
05200          return 0;
05201       ast_log(LOG_WARNING, "DAHDI hook failed returned %d (trying %d): %s\n", res, hs, strerror(errno));
05202       /* will expectedly fail if phone is off hook during operation, such as during a restart */
05203    }
05204 
05205    return res;
05206 }
05207 
05208 static inline int dahdi_confmute(struct dahdi_pvt *p, int muted)
05209 {
05210    int x, res;
05211 
05212    x = muted;
05213 #if defined(HAVE_PRI) || defined(HAVE_SS7)
05214    switch (p->sig) {
05215 #if defined(HAVE_PRI)
05216    case SIG_PRI_LIB_HANDLE_CASES:
05217       if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
05218          /* PRI nobch pseudo channel.  Does not handle ioctl(DAHDI_AUDIOMODE) */
05219          break;
05220       }
05221       /* Fall through */
05222 #endif   /* defined(HAVE_PRI) */
05223 #if defined(HAVE_SS7)
05224    case SIG_SS7:
05225 #endif   /* defined(HAVE_SS7) */
05226       {
05227          int y = 1;
05228 
05229          res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &y);
05230          if (res)
05231             ast_log(LOG_WARNING, "Unable to set audio mode on %d: %s\n",
05232                p->channel, strerror(errno));
05233       }
05234       break;
05235    default:
05236       break;
05237    }
05238 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
05239    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_CONFMUTE, &x);
05240    if (res < 0)
05241       ast_log(LOG_WARNING, "DAHDI confmute(%d) failed on channel %d: %s\n", muted, p->channel, strerror(errno));
05242    return res;
05243 }
05244 
05245 static int save_conference(struct dahdi_pvt *p)
05246 {
05247    struct dahdi_confinfo c;
05248    int res;
05249    if (p->saveconf.confmode) {
05250       ast_log(LOG_WARNING, "Can't save conference -- already in use\n");
05251       return -1;
05252    }
05253    p->saveconf.chan = 0;
05254    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &p->saveconf);
05255    if (res) {
05256       ast_log(LOG_WARNING, "Unable to get conference info: %s\n", strerror(errno));
05257       p->saveconf.confmode = 0;
05258       return -1;
05259    }
05260    memset(&c, 0, sizeof(c));
05261    c.confmode = DAHDI_CONF_NORMAL;
05262    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &c);
05263    if (res) {
05264       ast_log(LOG_WARNING, "Unable to set conference info: %s\n", strerror(errno));
05265       return -1;
05266    }
05267    ast_debug(1, "Disabled conferencing\n");
05268    return 0;
05269 }
05270 
05271 static int restore_conference(struct dahdi_pvt *p)
05272 {
05273    int res;
05274    if (p->saveconf.confmode) {
05275       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &p->saveconf);
05276       p->saveconf.confmode = 0;
05277       if (res) {
05278          ast_log(LOG_WARNING, "Unable to restore conference info: %s\n", strerror(errno));
05279          return -1;
05280       }
05281       ast_debug(1, "Restored conferencing\n");
05282    }
05283    return 0;
05284 }
05285 
05286 static int send_cwcidspill(struct dahdi_pvt *p)
05287 {
05288    p->callwaitcas = 0;
05289    p->cidcwexpire = 0;
05290    p->cid_suppress_expire = 0;
05291    if (!(p->cidspill = ast_malloc(MAX_CALLERID_SIZE)))
05292       return -1;
05293    p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, p->callwait_name, p->callwait_num, AST_LAW(p));
05294    /* Make sure we account for the end */
05295    p->cidlen += READ_SIZE * 4;
05296    p->cidpos = 0;
05297    send_callerid(p);
05298    ast_verb(3, "CPE supports Call Waiting Caller*ID.  Sending '%s/%s'\n", p->callwait_name, p->callwait_num);
05299    return 0;
05300 }
05301 
05302 static int has_voicemail(struct dahdi_pvt *p)
05303 {
05304    int new_msgs;
05305    struct ast_event *event;
05306    char *mailbox, *context;
05307 
05308    mailbox = context = ast_strdupa(p->mailbox);
05309    strsep(&context, "@");
05310    if (ast_strlen_zero(context))
05311       context = "default";
05312 
05313    event = ast_event_get_cached(AST_EVENT_MWI,
05314       AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
05315       AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
05316       AST_EVENT_IE_END);
05317 
05318    if (event) {
05319       new_msgs = ast_event_get_ie_uint(event, AST_EVENT_IE_NEWMSGS);
05320       ast_event_destroy(event);
05321    } else
05322       new_msgs = ast_app_has_voicemail(p->mailbox, NULL);
05323 
05324    return new_msgs;
05325 }
05326 
05327 
05328 
05329 static int send_callerid(struct dahdi_pvt *p)
05330 {
05331    /* Assumes spill in p->cidspill, p->cidlen in length and we're p->cidpos into it */
05332    int res;
05333    /* Take out of linear mode if necessary */
05334    if (p->subs[SUB_REAL].linear) {
05335       p->subs[SUB_REAL].linear = 0;
05336       dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
05337    }
05338    while (p->cidpos < p->cidlen) {
05339       res = write(p->subs[SUB_REAL].dfd, p->cidspill + p->cidpos, p->cidlen - p->cidpos);
05340       ast_debug(4, "writing callerid at pos %d of %d, res = %d\n", p->cidpos, p->cidlen, res);
05341       if (res < 0) {
05342          if (errno == EAGAIN)
05343             return 0;
05344          else {
05345             ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
05346             return -1;
05347          }
05348       }
05349       if (!res)
05350          return 0;
05351       p->cidpos += res;
05352    }
05353    p->cid_suppress_expire = CALLWAITING_SUPPRESS_SAMPLES;
05354    ast_free(p->cidspill);
05355    p->cidspill = NULL;
05356    if (p->callwaitcas) {
05357       /* Wait for CID/CW to expire */
05358       p->cidcwexpire = CIDCW_EXPIRE_SAMPLES;
05359       p->cid_suppress_expire = p->cidcwexpire;
05360    } else
05361       restore_conference(p);
05362    return 0;
05363 }
05364 
05365 static int dahdi_callwait(struct ast_channel *ast)
05366 {
05367    struct dahdi_pvt *p = ast->tech_pvt;
05368    p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
05369    if (p->cidspill) {
05370       ast_log(LOG_WARNING, "Spill already exists?!?\n");
05371       ast_free(p->cidspill);
05372    }
05373 
05374    /*
05375     * SAS: Subscriber Alert Signal, 440Hz for 300ms
05376     * CAS: CPE Alert Signal, 2130Hz * 2750Hz sine waves
05377     */
05378    if (!(p->cidspill = ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE * 4)))
05379       return -1;
05380    save_conference(p);
05381    /* Silence */
05382    memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
05383    if (!p->callwaitrings && p->callwaitingcallerid) {
05384       ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
05385       p->callwaitcas = 1;
05386       p->cidlen = 2400 + 680 + READ_SIZE * 4;
05387    } else {
05388       ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
05389       p->callwaitcas = 0;
05390       p->cidlen = 2400 + READ_SIZE * 4;
05391    }
05392    p->cidpos = 0;
05393    send_callerid(p);
05394 
05395    return 0;
05396 }
05397 
05398 static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout)
05399 {
05400    struct dahdi_pvt *p = ast->tech_pvt;
05401    int x, res, mysig;
05402    char dest[256]; /* must be same length as p->dialdest */
05403 
05404    ast_mutex_lock(&p->lock);
05405    ast_copy_string(dest, rdest, sizeof(dest));
05406    ast_copy_string(p->dialdest, rdest, sizeof(p->dialdest));
05407    if ((ast->_state == AST_STATE_BUSY)) {
05408       p->subs[SUB_REAL].needbusy = 1;
05409       ast_mutex_unlock(&p->lock);
05410       return 0;
05411    }
05412    if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
05413       ast_log(LOG_WARNING, "dahdi_call called on %s, neither down nor reserved\n", ast->name);
05414       ast_mutex_unlock(&p->lock);
05415       return -1;
05416    }
05417    p->waitingfordt.tv_sec = 0;
05418    p->dialednone = 0;
05419    if ((p->radio || (p->oprmode < 0)))  /* if a radio channel, up immediately */
05420    {
05421       /* Special pseudo -- automatically up */
05422       ast_setstate(ast, AST_STATE_UP);
05423       ast_mutex_unlock(&p->lock);
05424       return 0;
05425    }
05426    x = DAHDI_FLUSH_READ | DAHDI_FLUSH_WRITE;
05427    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
05428    if (res)
05429       ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", p->channel, strerror(errno));
05430    p->outgoing = 1;
05431 
05432    if (IS_DIGITAL(ast->transfercapability)){
05433       set_actual_gain(p->subs[SUB_REAL].dfd, 0, 0, p->rxdrc, p->txdrc, p->law);
05434    } else {
05435       set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
05436    }  
05437 
05438 #ifdef HAVE_PRI
05439    if (dahdi_sig_pri_lib_handles(p->sig)) {
05440       res = sig_pri_call(p->sig_pvt, ast, rdest, timeout,
05441          (p->law == DAHDI_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW);
05442       ast_mutex_unlock(&p->lock);
05443       return res;
05444    }
05445 #endif
05446 
05447 #if defined(HAVE_SS7)
05448    if (p->sig == SIG_SS7) {
05449       res = sig_ss7_call(p->sig_pvt, ast, rdest);
05450       ast_mutex_unlock(&p->lock);
05451       return res;
05452    }
05453 #endif   /* defined(HAVE_SS7) */
05454 
05455    /* If this is analog signalling we can exit here */
05456    if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
05457       p->callwaitrings = 0;
05458       res = analog_call(p->sig_pvt, ast, rdest, timeout);
05459       ast_mutex_unlock(&p->lock);
05460       return res;
05461    }
05462 
05463    mysig = p->outsigmod > -1 ? p->outsigmod : p->sig;
05464    switch (mysig) {
05465    case 0:
05466       /* Special pseudo -- automatically up*/
05467       ast_setstate(ast, AST_STATE_UP);
05468       break;
05469    case SIG_MFCR2:
05470       break;
05471    default:
05472       ast_debug(1, "not yet implemented\n");
05473       ast_mutex_unlock(&p->lock);
05474       return -1;
05475    }
05476 
05477 #ifdef HAVE_OPENR2
05478    if (p->mfcr2) {
05479       openr2_calling_party_category_t chancat;
05480       int callres = 0;
05481       char *c, *l;
05482 
05483       /* We'll get it in a moment -- but use dialdest to store pre-setup_ack digits */
05484       p->dialdest[0] = '\0';
05485 
05486       c = strchr(dest, '/');
05487       if (c) {
05488          c++;
05489       } else {
05490          c = "";
05491       }
05492       if (!p->hidecallerid) {
05493          l = ast->connected.id.number.valid ? ast->connected.id.number.str : NULL;
05494       } else {
05495          l = NULL;
05496       }
05497       if (strlen(c) < p->stripmsd) {
05498          ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
05499          ast_mutex_unlock(&p->lock);
05500          return -1;
05501       }
05502       p->dialing = 1;
05503       chancat = dahdi_r2_get_channel_category(ast);
05504       callres = openr2_chan_make_call(p->r2chan, l, (c + p->stripmsd), chancat);
05505       if (-1 == callres) {
05506          ast_mutex_unlock(&p->lock);
05507          ast_log(LOG_ERROR, "unable to make new MFC/R2 call!\n");
05508          return -1;
05509       }
05510       p->mfcr2_call_accepted = 0;
05511       p->mfcr2_progress = 0;
05512       ast_setstate(ast, AST_STATE_DIALING);
05513    }
05514 #endif /* HAVE_OPENR2 */
05515    ast_mutex_unlock(&p->lock);
05516    return 0;
05517 }
05518 
05519 /*!
05520  * \internal
05521  * \brief Insert the given chan_dahdi interface structure into the interface list.
05522  * \since 1.8
05523  *
05524  * \param pvt chan_dahdi private interface structure to insert.
05525  *
05526  * \details
05527  * The interface list is a doubly linked list sorted by the chan_dahdi channel number.
05528  * Any duplicates are inserted after the existing entries.
05529  *
05530  * \note The new interface must not already be in the list.
05531  *
05532  * \return Nothing
05533  */
05534 static void dahdi_iflist_insert(struct dahdi_pvt *pvt)
05535 {
05536    struct dahdi_pvt *cur;
05537 
05538    pvt->which_iflist = DAHDI_IFLIST_MAIN;
05539 
05540    /* Find place in middle of list for the new interface. */
05541    for (cur = iflist; cur; cur = cur->next) {
05542       if (pvt->channel < cur->channel) {
05543          /* New interface goes before the current interface. */
05544          pvt->prev = cur->prev;
05545          pvt->next = cur;
05546          if (cur->prev) {
05547             /* Insert into the middle of the list. */
05548             cur->prev->next = pvt;
05549          } else {
05550             /* Insert at head of list. */
05551             iflist = pvt;
05552          }
05553          cur->prev = pvt;
05554          return;
05555       }
05556    }
05557 
05558    /* New interface goes onto the end of the list */
05559    pvt->prev = ifend;
05560    pvt->next = NULL;
05561    if (ifend) {
05562       ifend->next = pvt;
05563    }
05564    ifend = pvt;
05565    if (!iflist) {
05566       /* List was empty */
05567       iflist = pvt;
05568    }
05569 }
05570 
05571 /*!
05572  * \internal
05573  * \brief Extract the given chan_dahdi interface structure from the interface list.
05574  * \since 1.8
05575  *
05576  * \param pvt chan_dahdi private interface structure to extract.
05577  *
05578  * \note
05579  * The given interface structure can be either in the interface list or a stand alone
05580  * structure that has not been put in the list if the next and prev pointers are NULL.
05581  *
05582  * \return Nothing
05583  */
05584 static void dahdi_iflist_extract(struct dahdi_pvt *pvt)
05585 {
05586    /* Extract from the forward chain. */
05587    if (pvt->prev) {
05588       pvt->prev->next = pvt->next;
05589    } else if (iflist == pvt) {
05590       /* Node is at the head of the list. */
05591       iflist = pvt->next;
05592    }
05593 
05594    /* Extract from the reverse chain. */
05595    if (pvt->next) {
05596       pvt->next->prev = pvt->prev;
05597    } else if (ifend == pvt) {
05598       /* Node is at the end of the list. */
05599       ifend = pvt->prev;
05600    }
05601 
05602    /* Node is no longer in the list. */
05603    pvt->which_iflist = DAHDI_IFLIST_NONE;
05604    pvt->prev = NULL;
05605    pvt->next = NULL;
05606 }
05607 
05608 #if defined(HAVE_PRI)
05609 /*!
05610  * \internal
05611  * \brief Insert the given chan_dahdi interface structure into the no B channel list.
05612  * \since 1.8
05613  *
05614  * \param pri sig_pri span control structure holding no B channel list.
05615  * \param pvt chan_dahdi private interface structure to insert.
05616  *
05617  * \details
05618  * The interface list is a doubly linked list sorted by the chan_dahdi channel number.
05619  * Any duplicates are inserted after the existing entries.
05620  *
05621  * \note The new interface must not already be in the list.
05622  *
05623  * \return Nothing
05624  */
05625 static void dahdi_nobch_insert(struct sig_pri_span *pri, struct dahdi_pvt *pvt)
05626 {
05627    struct dahdi_pvt *cur;
05628 
05629    pvt->which_iflist = DAHDI_IFLIST_NO_B_CHAN;
05630 
05631    /* Find place in middle of list for the new interface. */
05632    for (cur = pri->no_b_chan_iflist; cur; cur = cur->next) {
05633       if (pvt->channel < cur->channel) {
05634          /* New interface goes before the current interface. */
05635          pvt->prev = cur->prev;
05636          pvt->next = cur;
05637          if (cur->prev) {
05638             /* Insert into the middle of the list. */
05639             cur->prev->next = pvt;
05640          } else {
05641             /* Insert at head of list. */
05642             pri->no_b_chan_iflist = pvt;
05643          }
05644          cur->prev = pvt;
05645          return;
05646       }
05647    }
05648 
05649    /* New interface goes onto the end of the list */
05650    pvt->prev = pri->no_b_chan_end;
05651    pvt->next = NULL;
05652    if (pri->no_b_chan_end) {
05653       ((struct dahdi_pvt *) pri->no_b_chan_end)->next = pvt;
05654    }
05655    pri->no_b_chan_end = pvt;
05656    if (!pri->no_b_chan_iflist) {
05657       /* List was empty */
05658       pri->no_b_chan_iflist = pvt;
05659    }
05660 }
05661 #endif   /* defined(HAVE_PRI) */
05662 
05663 #if defined(HAVE_PRI)
05664 /*!
05665  * \internal
05666  * \brief Extract the given chan_dahdi interface structure from the no B channel list.
05667  * \since 1.8
05668  *
05669  * \param pri sig_pri span control structure holding no B channel list.
05670  * \param pvt chan_dahdi private interface structure to extract.
05671  *
05672  * \note
05673  * The given interface structure can be either in the interface list or a stand alone
05674  * structure that has not been put in the list if the next and prev pointers are NULL.
05675  *
05676  * \return Nothing
05677  */
05678 static void dahdi_nobch_extract(struct sig_pri_span *pri, struct dahdi_pvt *pvt)
05679 {
05680    /* Extract from the forward chain. */
05681    if (pvt->prev) {
05682       pvt->prev->next = pvt->next;
05683    } else if (pri->no_b_chan_iflist == pvt) {
05684       /* Node is at the head of the list. */
05685       pri->no_b_chan_iflist = pvt->next;
05686    }
05687 
05688    /* Extract from the reverse chain. */
05689    if (pvt->next) {
05690       pvt->next->prev = pvt->prev;
05691    } else if (pri->no_b_chan_end == pvt) {
05692       /* Node is at the end of the list. */
05693       pri->no_b_chan_end = pvt->prev;
05694    }
05695 
05696    /* Node is no longer in the list. */
05697    pvt->which_iflist = DAHDI_IFLIST_NONE;
05698    pvt->prev = NULL;
05699    pvt->next = NULL;
05700 }
05701 #endif   /* defined(HAVE_PRI) */
05702 
05703 #if defined(HAVE_PRI)
05704 /*!
05705  * \internal
05706  * \brief Unlink the channel interface from the PRI private pointer array.
05707  * \since 1.8
05708  *
05709  * \param pvt chan_dahdi private interface structure to unlink.
05710  *
05711  * \return Nothing
05712  */
05713 static void dahdi_unlink_pri_pvt(struct dahdi_pvt *pvt)
05714 {
05715    unsigned idx;
05716    struct sig_pri_span *pri;
05717 
05718    pri = pvt->pri;
05719    if (!pri) {
05720       /* Not PRI signaling so cannot be in a PRI private pointer array. */
05721       return;
05722    }
05723    ast_mutex_lock(&pri->lock);
05724    for (idx = 0; idx < pri->numchans; ++idx) {
05725       if (pri->pvts[idx] == pvt->sig_pvt) {
05726          pri->pvts[idx] = NULL;
05727          ast_mutex_unlock(&pri->lock);
05728          return;
05729       }
05730    }
05731    ast_mutex_unlock(&pri->lock);
05732 }
05733 #endif   /* defined(HAVE_PRI) */
05734 
05735 #if defined(HAVE_SS7)
05736 /*!
05737  * \internal
05738  * \brief Unlink the channel interface from the SS7 private pointer array.
05739  * \since 1.8
05740  *
05741  * \param pvt chan_dahdi private interface structure to unlink.
05742  *
05743  * \return Nothing
05744  */
05745 static void dahdi_unlink_ss7_pvt(struct dahdi_pvt *pvt)
05746 {
05747    unsigned idx;
05748    struct sig_ss7_linkset *ss7;
05749 
05750    ss7 = pvt->ss7;
05751    if (!ss7) {
05752       /* Not SS7 signaling so cannot be in a SS7 private pointer array. */
05753       return;
05754    }
05755    ast_mutex_lock(&ss7->lock);
05756    for (idx = 0; idx < ss7->numchans; ++idx) {
05757       if (ss7->pvts[idx] == pvt->sig_pvt) {
05758          ss7->pvts[idx] = NULL;
05759          ast_mutex_unlock(&ss7->lock);
05760          return;
05761       }
05762    }
05763    ast_mutex_unlock(&ss7->lock);
05764 }
05765 #endif   /* defined(HAVE_SS7) */
05766 
05767 static struct dahdi_pvt *find_next_iface_in_span(struct dahdi_pvt *cur)
05768 {
05769    if (cur->next && cur->next->span == cur->span) {
05770       return cur->next;
05771    } else if (cur->prev && cur->prev->span == cur->span) {
05772       return cur->prev;
05773    }
05774 
05775    return NULL;
05776 }
05777 
05778 static void destroy_dahdi_pvt(struct dahdi_pvt *pvt)
05779 {
05780    struct dahdi_pvt *p = pvt;
05781 
05782    if (p->manages_span_alarms) {
05783       struct dahdi_pvt *next = find_next_iface_in_span(p);
05784       if (next) {
05785          next->manages_span_alarms = 1;
05786       }
05787    }
05788 
05789    /* Remove channel from the list */
05790 #if defined(HAVE_PRI)
05791    dahdi_unlink_pri_pvt(p);
05792 #endif   /* defined(HAVE_PRI) */
05793 #if defined(HAVE_SS7)
05794    dahdi_unlink_ss7_pvt(p);
05795 #endif   /* defined(HAVE_SS7) */
05796    switch (pvt->which_iflist) {
05797    case DAHDI_IFLIST_NONE:
05798       break;
05799    case DAHDI_IFLIST_MAIN:
05800       dahdi_iflist_extract(p);
05801       break;
05802 #if defined(HAVE_PRI)
05803    case DAHDI_IFLIST_NO_B_CHAN:
05804       if (p->pri) {
05805          dahdi_nobch_extract(p->pri, p);
05806       }
05807       break;
05808 #endif   /* defined(HAVE_PRI) */
05809    }
05810 
05811    if (p->sig_pvt) {
05812       if (analog_lib_handles(p->sig, 0, 0)) {
05813          analog_delete(p->sig_pvt);
05814       }
05815       switch (p->sig) {
05816 #if defined(HAVE_PRI)
05817       case SIG_PRI_LIB_HANDLE_CASES:
05818          sig_pri_chan_delete(p->sig_pvt);
05819          break;
05820 #endif   /* defined(HAVE_PRI) */
05821 #if defined(HAVE_SS7)
05822       case SIG_SS7:
05823          sig_ss7_chan_delete(p->sig_pvt);
05824          break;
05825 #endif   /* defined(HAVE_SS7) */
05826       default:
05827          break;
05828       }
05829    }
05830    ast_free(p->cidspill);
05831    if (p->use_smdi)
05832       ast_smdi_interface_unref(p->smdi_iface);
05833    if (p->mwi_event_sub)
05834       ast_event_unsubscribe(p->mwi_event_sub);
05835    if (p->vars) {
05836       ast_variables_destroy(p->vars);
05837    }
05838    if (p->cc_params) {
05839       ast_cc_config_params_destroy(p->cc_params);
05840    }
05841    ast_mutex_destroy(&p->lock);
05842    dahdi_close_sub(p, SUB_REAL);
05843    if (p->owner)
05844       p->owner->tech_pvt = NULL;
05845    ast_free(p);
05846 }
05847 
05848 static void destroy_channel(struct dahdi_pvt *cur, int now)
05849 {
05850    int i;
05851 
05852    if (!now) {
05853       /* Do not destroy the channel now if it is owned by someone. */
05854       if (cur->owner) {
05855          return;
05856       }
05857       for (i = 0; i < 3; i++) {
05858          if (cur->subs[i].owner) {
05859             return;
05860          }
05861       }
05862    }
05863    destroy_dahdi_pvt(cur);
05864 }
05865 
05866 static void destroy_all_channels(void)
05867 {
05868    int chan;
05869 #if defined(HAVE_PRI)
05870    unsigned span;
05871    struct sig_pri_span *pri;
05872 #endif   /* defined(HAVE_PRI) */
05873    struct dahdi_pvt *p;
05874 
05875    while (num_restart_pending) {
05876       usleep(1);
05877    }
05878 
05879    ast_mutex_lock(&iflock);
05880    /* Destroy all the interfaces and free their memory */
05881    while (iflist) {
05882       p = iflist;
05883 
05884       chan = p->channel;
05885 #if defined(HAVE_PRI_SERVICE_MESSAGES)
05886       {
05887          char db_chan_name[20];
05888          char db_answer[5];
05889          char state;
05890          int why = -1;
05891 
05892          snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, p->span, chan);
05893          if (!ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) {
05894             sscanf(db_answer, "%1c:%30d", &state, &why);
05895          }
05896          if (!why) {
05897             /* SRVST persistence is not required */
05898             ast_db_del(db_chan_name, SRVST_DBKEY);
05899          }
05900       }
05901 #endif   /* defined(HAVE_PRI_SERVICE_MESSAGES) */
05902       /* Free associated memory */
05903       destroy_dahdi_pvt(p);
05904       ast_verb(3, "Unregistered channel %d\n", chan);
05905    }
05906    ifcount = 0;
05907    ast_mutex_unlock(&iflock);
05908 
05909 #if defined(HAVE_PRI)
05910    /* Destroy all of the no B channel interface lists */
05911    for (span = 0; span < NUM_SPANS; ++span) {
05912       if (!pris[span].dchannels[0]) {
05913          break;
05914       }
05915       pri = &pris[span].pri;
05916       ast_mutex_lock(&pri->lock);
05917       while (pri->no_b_chan_iflist) {
05918          p = pri->no_b_chan_iflist;
05919 
05920          /* Free associated memory */
05921          destroy_dahdi_pvt(p);
05922       }
05923       ast_mutex_unlock(&pri->lock);
05924    }
05925 #endif   /* defined(HAVE_PRI) */
05926 }
05927 
05928 #if defined(HAVE_PRI)
05929 static char *dahdi_send_keypad_facility_app = "DAHDISendKeypadFacility";
05930 
05931 static int dahdi_send_keypad_facility_exec(struct ast_channel *chan, const char *digits)
05932 {
05933    /* Data will be our digit string */
05934    struct dahdi_pvt *p;
05935 
05936    if (ast_strlen_zero(digits)) {
05937       ast_debug(1, "No digit string sent to application!\n");
05938       return -1;
05939    }
05940 
05941    p = (struct dahdi_pvt *)chan->tech_pvt;
05942 
05943    if (!p) {
05944       ast_debug(1, "Unable to find technology private\n");
05945       return -1;
05946    }
05947 
05948    pri_send_keypad_facility_exec(p->sig_pvt, digits);
05949 
05950    return 0;
05951 }
05952 #endif   /* defined(HAVE_PRI) */
05953 
05954 #if defined(HAVE_PRI)
05955 #if defined(HAVE_PRI_PROG_W_CAUSE)
05956 static char *dahdi_send_callrerouting_facility_app = "DAHDISendCallreroutingFacility";
05957 
05958 static int dahdi_send_callrerouting_facility_exec(struct ast_channel *chan, const char *data)
05959 {
05960    /* Data will be our digit string */
05961    struct dahdi_pvt *pvt;
05962    char *parse;
05963    int res;
05964    AST_DECLARE_APP_ARGS(args,
05965       AST_APP_ARG(destination);
05966       AST_APP_ARG(original);
05967       AST_APP_ARG(reason);
05968    );
05969 
05970    if (ast_strlen_zero(data)) {
05971       ast_log(LOG_DEBUG, "No data sent to application!\n");
05972       return -1;
05973    }
05974    if (chan->tech != &dahdi_tech) {
05975       ast_log(LOG_DEBUG, "Only DAHDI technology accepted!\n");
05976       return -1;
05977    }
05978    pvt = (struct dahdi_pvt *) chan->tech_pvt;
05979    if (!pvt) {
05980       ast_log(LOG_DEBUG, "Unable to find technology private\n");
05981       return -1;
05982    }
05983    switch (pvt->sig) {
05984    case SIG_PRI_LIB_HANDLE_CASES:
05985       break;
05986    default:
05987       ast_log(LOG_DEBUG, "callrerouting attempted on non-ISDN channel %s\n",
05988          chan->name);
05989       return -1;
05990    }
05991 
05992    parse = ast_strdupa(data);
05993    AST_STANDARD_APP_ARGS(args, parse);
05994 
05995    if (ast_strlen_zero(args.destination)) {
05996       ast_log(LOG_WARNING, "callrerouting facility requires at least destination number argument\n");
05997       return -1;
05998    }
05999 
06000    if (ast_strlen_zero(args.original)) {
06001       ast_log(LOG_WARNING, "Callrerouting Facility without original called number argument\n");
06002       args.original = NULL;
06003    }
06004 
06005    if (ast_strlen_zero(args.reason)) {
06006       ast_log(LOG_NOTICE, "Callrerouting Facility without diversion reason argument, defaulting to unknown\n");
06007       args.reason = NULL;
06008    }
06009 
06010    res = pri_send_callrerouting_facility_exec(pvt->sig_pvt, chan->_state,
06011       args.destination, args.original, args.reason);
06012    if (!res) {
06013       /*
06014        * Wait up to 5 seconds for a reply before hanging up this call
06015        * leg if the peer does not disconnect first.
06016        */
06017       ast_safe_sleep(chan, 5000);
06018    }
06019 
06020    return -1;
06021 }
06022 #endif   /* defined(HAVE_PRI_PROG_W_CAUSE) */
06023 #endif   /* defined(HAVE_PRI) */
06024 
06025 #if defined(HAVE_OPENR2)
06026 static const char * const dahdi_accept_r2_call_app = "DAHDIAcceptR2Call";
06027 
06028 static int dahdi_accept_r2_call_exec(struct ast_channel *chan, const char *data)
06029 {
06030    /* data is whether to accept with charge or no charge */
06031    openr2_call_mode_t accept_mode;
06032    int res, timeout, maxloops;
06033    struct ast_frame *f;
06034    struct dahdi_pvt *p;
06035    char *parse;
06036    AST_DECLARE_APP_ARGS(args,
06037          AST_APP_ARG(charge);
06038    );
06039 
06040    if (ast_strlen_zero(data)) {
06041       ast_log(LOG_DEBUG, "No data sent to application!\n");
06042       return -1;
06043    }
06044 
06045    if (chan->tech != &dahdi_tech) {
06046       ast_log(LOG_DEBUG, "Only DAHDI technology accepted!\n");
06047       return -1;
06048    }
06049 
06050    p = (struct dahdi_pvt *)chan->tech_pvt;
06051    if (!p) {
06052       ast_log(LOG_DEBUG, "Unable to find technology private!\n");
06053       return -1;
06054    }
06055 
06056    parse = ast_strdupa(data);
06057    AST_STANDARD_APP_ARGS(args, parse);
06058 
06059    if (ast_strlen_zero(args.charge)) {
06060       ast_log(LOG_WARNING, "DAHDIAcceptR2Call requires 'yes' or 'no' for the charge parameter\n");
06061       return -1;
06062    }
06063 
06064    ast_mutex_lock(&p->lock);
06065    if (!p->mfcr2 || !p->mfcr2call) {
06066       ast_mutex_unlock(&p->lock);
06067       ast_log(LOG_DEBUG, "Channel %s does not seems to be an R2 active channel!\n", chan->name);
06068       return -1;
06069    }
06070 
06071    if (p->mfcr2_call_accepted) {
06072       ast_mutex_unlock(&p->lock);
06073       ast_log(LOG_DEBUG, "MFC/R2 call already accepted on channel %s!\n", chan->name);
06074       return 0;
06075    }
06076    accept_mode = ast_true(args.charge) ? OR2_CALL_WITH_CHARGE : OR2_CALL_NO_CHARGE;
06077    if (openr2_chan_accept_call(p->r2chan, accept_mode)) {
06078       ast_mutex_unlock(&p->lock);
06079       ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n");
06080       return -1;
06081    }
06082    ast_mutex_unlock(&p->lock);
06083 
06084    res = 0;
06085    timeout = 100;
06086    maxloops = 50; /* wait up to 5 seconds */
06087    /* we need to read() until the call is accepted */
06088    while (maxloops > 0) {
06089       maxloops--;
06090       if (ast_check_hangup(chan)) {
06091          break;
06092       }
06093       res = ast_waitfor(chan, timeout);
06094       if (res < 0) {
06095          ast_log(LOG_DEBUG, "ast_waitfor failed on channel %s, going out ...\n", chan->name);
06096          res = -1;
06097          break;
06098       }
06099       if (res == 0) {
06100          continue;
06101       }
06102       res = 0;
06103       f = ast_read(chan);
06104       if (!f) {
06105          ast_log(LOG_DEBUG, "No frame read on channel %s, going out ...\n", chan->name);
06106          res = -1;
06107          break;
06108       }
06109       if (f->frametype == AST_FRAME_CONTROL && f->subclass.integer == AST_CONTROL_HANGUP) {
06110          ast_log(LOG_DEBUG, "Got HANGUP frame on channel %s, going out ...\n", chan->name);
06111          ast_frfree(f);
06112          res = -1;
06113          break;
06114       }
06115       ast_frfree(f);
06116       ast_mutex_lock(&p->lock);
06117       if (p->mfcr2_call_accepted) {
06118          ast_mutex_unlock(&p->lock);
06119          ast_log(LOG_DEBUG, "Accepted MFC/R2 call!\n");
06120          break;
06121       }
06122       ast_mutex_unlock(&p->lock);
06123    }
06124    if (res == -1) {
06125       ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n");
06126    }
06127    return res;
06128 }
06129 
06130 static openr2_call_disconnect_cause_t dahdi_ast_cause_to_r2_cause(int cause)
06131 {
06132    openr2_call_disconnect_cause_t r2cause = OR2_CAUSE_NORMAL_CLEARING;
06133    switch (cause) {
06134    case AST_CAUSE_USER_BUSY:
06135    case AST_CAUSE_CALL_REJECTED:
06136    case AST_CAUSE_INTERWORKING: /* I don't know wtf is this but is used sometimes when ekiga rejects a call */
06137       r2cause = OR2_CAUSE_BUSY_NUMBER;
06138       break;
06139 
06140    case AST_CAUSE_NORMAL_CIRCUIT_CONGESTION:
06141    case AST_CAUSE_SWITCH_CONGESTION:
06142       r2cause = OR2_CAUSE_NETWORK_CONGESTION;
06143       break;
06144 
06145    case AST_CAUSE_UNALLOCATED:
06146       r2cause = OR2_CAUSE_UNALLOCATED_NUMBER;
06147       break;
06148 
06149    case AST_CAUSE_NETWORK_OUT_OF_ORDER:
06150    case AST_CAUSE_DESTINATION_OUT_OF_ORDER:
06151       r2cause = OR2_CAUSE_OUT_OF_ORDER;
06152       break;
06153 
06154    case AST_CAUSE_NO_ANSWER:
06155    case AST_CAUSE_NO_USER_RESPONSE:
06156       r2cause = OR2_CAUSE_NO_ANSWER;
06157       break;
06158 
06159    default:
06160       r2cause = OR2_CAUSE_NORMAL_CLEARING;
06161       break;
06162    }
06163    ast_log(LOG_DEBUG, "ast cause %d resulted in openr2 cause %d/%s\n",
06164          cause, r2cause, openr2_proto_get_disconnect_string(r2cause));
06165    return r2cause;
06166 }
06167 #endif
06168 
06169 static int revert_fax_buffers(struct dahdi_pvt *p, struct ast_channel *ast)
06170 {
06171    if (p->bufferoverrideinuse) {
06172       /* faxbuffers are in use, revert them */
06173       struct dahdi_bufferinfo bi = {
06174          .txbufpolicy = p->buf_policy,
06175          .rxbufpolicy = p->buf_policy,
06176          .bufsize = p->bufsize,
06177          .numbufs = p->buf_no
06178       };
06179       int bpres;
06180 
06181       if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
06182          ast_log(LOG_WARNING, "Channel '%s' unable to revert buffer policy: %s\n", ast->name, strerror(errno));
06183       }
06184       p->bufferoverrideinuse = 0;
06185       return bpres;
06186    }
06187 
06188    return -1;
06189 }
06190 
06191 static int dahdi_hangup(struct ast_channel *ast)
06192 {
06193    int res = 0;
06194    int idx,x;
06195    int law;
06196    /*static int restore_gains(struct dahdi_pvt *p);*/
06197    struct dahdi_pvt *p = ast->tech_pvt;
06198    struct dahdi_params par;
06199 
06200    ast_debug(1, "dahdi_hangup(%s)\n", ast->name);
06201    if (!ast->tech_pvt) {
06202       ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
06203       return 0;
06204    }
06205 
06206    ast_mutex_lock(&p->lock);
06207    p->exten[0] = '\0';
06208    if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
06209       dahdi_confmute(p, 0);
06210       restore_gains(p);
06211       p->ignoredtmf = 0;
06212       p->waitingfordt.tv_sec = 0;
06213 
06214       res = analog_hangup(p->sig_pvt, ast);
06215       revert_fax_buffers(p, ast);
06216 
06217       goto hangup_out;
06218    } else {
06219       p->cid_num[0] = '\0';
06220       p->cid_name[0] = '\0';
06221       p->cid_subaddr[0] = '\0';
06222    }
06223 
06224 #if defined(HAVE_PRI)
06225    if (dahdi_sig_pri_lib_handles(p->sig)) {
06226       x = 1;
06227       ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
06228 
06229       dahdi_confmute(p, 0);
06230       p->muting = 0;
06231       restore_gains(p);
06232       if (p->dsp) {
06233          ast_dsp_free(p->dsp);
06234          p->dsp = NULL;
06235       }
06236       p->ignoredtmf = 0;
06237 
06238       /* Real channel, do some fixup */
06239       p->subs[SUB_REAL].owner = NULL;
06240       p->subs[SUB_REAL].needbusy = 0;
06241       dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
06242 
06243       p->owner = NULL;
06244       p->cid_tag[0] = '\0';
06245       p->ringt = 0;/* Probably not used in this mode.  Reset anyway. */
06246       p->distinctivering = 0;/* Probably not used in this mode. Reset anyway. */
06247       p->confirmanswer = 0;/* Probably not used in this mode. Reset anyway. */
06248       p->outgoing = 0;
06249       p->digital = 0;
06250       p->faxhandled = 0;
06251       p->pulsedial = 0;/* Probably not used in this mode. Reset anyway. */
06252 
06253       revert_fax_buffers(p, ast);
06254 
06255       p->law = p->law_default;
06256       law = p->law_default;
06257       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
06258       if (res < 0) {
06259          ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n",
06260             p->channel, strerror(errno));
06261       }
06262 
06263       sig_pri_hangup(p->sig_pvt, ast);
06264 
06265       tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06266       dahdi_disable_ec(p);
06267 
06268       x = 0;
06269       ast_channel_setoption(ast, AST_OPTION_TDD, &x, sizeof(char), 0);
06270       p->didtdd = 0;/* Probably not used in this mode. Reset anyway. */
06271 
06272       p->rdnis[0] = '\0';
06273       update_conf(p);
06274       reset_conf(p);
06275 
06276       /* Restore data mode */
06277       x = 0;
06278       ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
06279 
06280       if (num_restart_pending == 0) {
06281          restart_monitor();
06282       }
06283       goto hangup_out;
06284    }
06285 #endif   /* defined(HAVE_PRI) */
06286 
06287 #if defined(HAVE_SS7)
06288    if (p->sig == SIG_SS7) {
06289       x = 1;
06290       ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
06291 
06292       dahdi_confmute(p, 0);
06293       p->muting = 0;
06294       restore_gains(p);
06295       if (p->dsp) {
06296          ast_dsp_free(p->dsp);
06297          p->dsp = NULL;
06298       }
06299       p->ignoredtmf = 0;
06300 
06301       /* Real channel, do some fixup */
06302       p->subs[SUB_REAL].owner = NULL;
06303       p->subs[SUB_REAL].needbusy = 0;
06304       dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
06305 
06306       p->owner = NULL;
06307       p->ringt = 0;/* Probably not used in this mode.  Reset anyway. */
06308       p->distinctivering = 0;/* Probably not used in this mode. Reset anyway. */
06309       p->confirmanswer = 0;/* Probably not used in this mode. Reset anyway. */
06310       p->outgoing = 0;
06311       p->digital = 0;
06312       p->faxhandled = 0;
06313       p->pulsedial = 0;/* Probably not used in this mode. Reset anyway. */
06314 
06315       revert_fax_buffers(p, ast);
06316 
06317       p->law = p->law_default;
06318       law = p->law_default;
06319       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
06320       if (res < 0) {
06321          ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n",
06322             p->channel, strerror(errno));
06323       }
06324 
06325       sig_ss7_hangup(p->sig_pvt, ast);
06326 
06327       tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06328       dahdi_disable_ec(p);
06329 
06330       x = 0;
06331       ast_channel_setoption(ast, AST_OPTION_TDD, &x, sizeof(char), 0);
06332       p->didtdd = 0;/* Probably not used in this mode. Reset anyway. */
06333 
06334       update_conf(p);
06335       reset_conf(p);
06336 
06337       /* Restore data mode */
06338       x = 0;
06339       ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
06340 
06341       if (num_restart_pending == 0) {
06342          restart_monitor();
06343       }
06344       goto hangup_out;
06345    }
06346 #endif   /* defined(HAVE_SS7) */
06347 
06348    idx = dahdi_get_index(ast, p, 1);
06349 
06350    dahdi_confmute(p, 0);
06351    p->muting = 0;
06352    restore_gains(p);
06353    if (p->origcid_num) {
06354       ast_copy_string(p->cid_num, p->origcid_num, sizeof(p->cid_num));
06355       ast_free(p->origcid_num);
06356       p->origcid_num = NULL;
06357    }
06358    if (p->origcid_name) {
06359       ast_copy_string(p->cid_name, p->origcid_name, sizeof(p->cid_name));
06360       ast_free(p->origcid_name);
06361       p->origcid_name = NULL;
06362    }
06363    if (p->dsp)
06364       ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
06365 
06366    ast_debug(1, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n",
06367       p->channel, idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
06368    p->ignoredtmf = 0;
06369 
06370    if (idx > -1) {
06371       /* Real channel, do some fixup */
06372       p->subs[idx].owner = NULL;
06373       p->subs[idx].needanswer = 0;
06374       p->subs[idx].needflash = 0;
06375       p->subs[idx].needringing = 0;
06376       p->subs[idx].needbusy = 0;
06377       p->subs[idx].needcongestion = 0;
06378       p->subs[idx].linear = 0;
06379       p->polarity = POLARITY_IDLE;
06380       dahdi_setlinear(p->subs[idx].dfd, 0);
06381       if (idx == SUB_REAL) {
06382          if ((p->subs[SUB_CALLWAIT].dfd > -1) && (p->subs[SUB_THREEWAY].dfd > -1)) {
06383             ast_debug(1, "Normal call hung up with both three way call and a call waiting call in place?\n");
06384             if (p->subs[SUB_CALLWAIT].inthreeway) {
06385                /* We had flipped over to answer a callwait and now it's gone */
06386                ast_debug(1, "We were flipped over to the callwait, moving back and unowning.\n");
06387                /* Move to the call-wait, but un-own us until they flip back. */
06388                swap_subs(p, SUB_CALLWAIT, SUB_REAL);
06389                unalloc_sub(p, SUB_CALLWAIT);
06390                p->owner = NULL;
06391             } else {
06392                /* The three way hung up, but we still have a call wait */
06393                ast_debug(1, "We were in the threeway and have a callwait still.  Ditching the threeway.\n");
06394                swap_subs(p, SUB_THREEWAY, SUB_REAL);
06395                unalloc_sub(p, SUB_THREEWAY);
06396                if (p->subs[SUB_REAL].inthreeway) {
06397                   /* This was part of a three way call.  Immediately make way for
06398                      another call */
06399                   ast_debug(1, "Call was complete, setting owner to former third call\n");
06400                   p->owner = p->subs[SUB_REAL].owner;
06401                } else {
06402                   /* This call hasn't been completed yet...  Set owner to NULL */
06403                   ast_debug(1, "Call was incomplete, setting owner to NULL\n");
06404                   p->owner = NULL;
06405                }
06406                p->subs[SUB_REAL].inthreeway = 0;
06407             }
06408          } else if (p->subs[SUB_CALLWAIT].dfd > -1) {
06409             /* Move to the call-wait and switch back to them. */
06410             swap_subs(p, SUB_CALLWAIT, SUB_REAL);
06411             unalloc_sub(p, SUB_CALLWAIT);
06412             p->owner = p->subs[SUB_REAL].owner;
06413             if (p->owner->_state != AST_STATE_UP)
06414                p->subs[SUB_REAL].needanswer = 1;
06415             if (ast_bridged_channel(p->subs[SUB_REAL].owner))
06416                ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
06417          } else if (p->subs[SUB_THREEWAY].dfd > -1) {
06418             swap_subs(p, SUB_THREEWAY, SUB_REAL);
06419             unalloc_sub(p, SUB_THREEWAY);
06420             if (p->subs[SUB_REAL].inthreeway) {
06421                /* This was part of a three way call.  Immediately make way for
06422                   another call */
06423                ast_debug(1, "Call was complete, setting owner to former third call\n");
06424                p->owner = p->subs[SUB_REAL].owner;
06425             } else {
06426                /* This call hasn't been completed yet...  Set owner to NULL */
06427                ast_debug(1, "Call was incomplete, setting owner to NULL\n");
06428                p->owner = NULL;
06429             }
06430             p->subs[SUB_REAL].inthreeway = 0;
06431          }
06432       } else if (idx == SUB_CALLWAIT) {
06433          /* Ditch the holding callwait call, and immediately make it availabe */
06434          if (p->subs[SUB_CALLWAIT].inthreeway) {
06435             /* This is actually part of a three way, placed on hold.  Place the third part
06436                on music on hold now */
06437             if (p->subs[SUB_THREEWAY].owner && ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
06438                ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
06439                   S_OR(p->mohsuggest, NULL),
06440                   !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
06441             }
06442             p->subs[SUB_THREEWAY].inthreeway = 0;
06443             /* Make it the call wait now */
06444             swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
06445             unalloc_sub(p, SUB_THREEWAY);
06446          } else
06447             unalloc_sub(p, SUB_CALLWAIT);
06448       } else if (idx == SUB_THREEWAY) {
06449          if (p->subs[SUB_CALLWAIT].inthreeway) {
06450             /* The other party of the three way call is currently in a call-wait state.
06451                Start music on hold for them, and take the main guy out of the third call */
06452             if (p->subs[SUB_CALLWAIT].owner && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
06453                ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
06454                   S_OR(p->mohsuggest, NULL),
06455                   !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
06456             }
06457             p->subs[SUB_CALLWAIT].inthreeway = 0;
06458          }
06459          p->subs[SUB_REAL].inthreeway = 0;
06460          /* If this was part of a three way call index, let us make
06461             another three way call */
06462          unalloc_sub(p, SUB_THREEWAY);
06463       } else {
06464          /* This wasn't any sort of call, but how are we an index? */
06465          ast_log(LOG_WARNING, "Index found but not any type of call?\n");
06466       }
06467    }
06468 
06469    if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) {
06470       p->owner = NULL;
06471       p->ringt = 0;
06472       p->distinctivering = 0;
06473       p->confirmanswer = 0;
06474       p->outgoing = 0;
06475       p->digital = 0;
06476       p->faxhandled = 0;
06477       p->pulsedial = 0;
06478       if (p->dsp) {
06479          ast_dsp_free(p->dsp);
06480          p->dsp = NULL;
06481       }
06482 
06483       revert_fax_buffers(p, ast);
06484 
06485       p->law = p->law_default;
06486       law = p->law_default;
06487       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
06488       if (res < 0)
06489          ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
06490       /* Perform low level hangup if no owner left */
06491 #ifdef HAVE_OPENR2
06492       if (p->mfcr2 && p->mfcr2call && openr2_chan_get_direction(p->r2chan) != OR2_DIR_STOPPED) {
06493          ast_log(LOG_DEBUG, "disconnecting MFC/R2 call on chan %d\n", p->channel);
06494          /* If it's an incoming call, check the mfcr2_forced_release setting */
06495          if (openr2_chan_get_direction(p->r2chan) == OR2_DIR_BACKWARD && p->mfcr2_forced_release) {
06496             dahdi_r2_disconnect_call(p, OR2_CAUSE_FORCED_RELEASE);
06497          } else {
06498             const char *r2causestr = pbx_builtin_getvar_helper(ast, "MFCR2_CAUSE");
06499             int r2cause_user = r2causestr ? atoi(r2causestr) : 0;
06500             openr2_call_disconnect_cause_t r2cause = r2cause_user ? dahdi_ast_cause_to_r2_cause(r2cause_user)
06501                                                              : dahdi_ast_cause_to_r2_cause(ast->hangupcause);
06502             dahdi_r2_disconnect_call(p, r2cause);
06503          }
06504       } else if (p->mfcr2call) {
06505          ast_log(LOG_DEBUG, "Clearing call request on channel %d\n", p->channel);
06506          /* since ast_request() was called but not ast_call() we have not yet dialed
06507          and the openr2 stack will not call on_call_end callback, we need to unset
06508          the mfcr2call flag and bump the monitor count so the monitor thread can take
06509          care of this channel events from now on */
06510          p->mfcr2call = 0;
06511       }
06512 #endif
06513       switch (p->sig) {
06514       case SIG_SS7:
06515       case SIG_MFCR2:
06516       case SIG_PRI_LIB_HANDLE_CASES:
06517       case 0:
06518          break;
06519       default:
06520          res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
06521          break;
06522       }
06523       if (res < 0) {
06524          ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast->name);
06525       }
06526       switch (p->sig) {
06527       case SIG_FXOGS:
06528       case SIG_FXOLS:
06529       case SIG_FXOKS:
06530          memset(&par, 0, sizeof(par));
06531          res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
06532          if (!res) {
06533             struct analog_pvt *analog_p = p->sig_pvt;
06534 #if 0
06535             ast_debug(1, "Hanging up channel %d, offhook = %d\n", p->channel, par.rxisoffhook);
06536 #endif
06537             /* If they're off hook, try playing congestion */
06538             if ((par.rxisoffhook) && (!(p->radio || (p->oprmode < 0))))
06539                tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
06540             else
06541                tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06542             analog_p->fxsoffhookstate = par.rxisoffhook;
06543          }
06544          break;
06545       case SIG_FXSGS:
06546       case SIG_FXSLS:
06547       case SIG_FXSKS:
06548          /* Make sure we're not made available for at least two seconds assuming
06549          we were actually used for an inbound or outbound call. */
06550          if (ast->_state != AST_STATE_RESERVED) {
06551             time(&p->guardtime);
06552             p->guardtime += 2;
06553          }
06554          break;
06555       default:
06556          tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06557          break;
06558       }
06559       if (p->sig)
06560          dahdi_disable_ec(p);
06561       x = 0;
06562       ast_channel_setoption(ast,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0);
06563       ast_channel_setoption(ast,AST_OPTION_TDD,&x,sizeof(char),0);
06564       p->didtdd = 0;
06565       p->callwaitcas = 0;
06566       p->callwaiting = p->permcallwaiting;
06567       p->hidecallerid = p->permhidecallerid;
06568       p->waitingfordt.tv_sec = 0;
06569       p->dialing = 0;
06570       p->rdnis[0] = '\0';
06571       update_conf(p);
06572       reset_conf(p);
06573       /* Restore data mode */
06574       switch (p->sig) {
06575       case SIG_PRI_LIB_HANDLE_CASES:
06576       case SIG_SS7:
06577          x = 0;
06578          ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
06579          break;
06580       default:
06581          break;
06582       }
06583       if (num_restart_pending == 0)
06584          restart_monitor();
06585    }
06586 
06587    p->callwaitingrepeat = 0;
06588    p->cidcwexpire = 0;
06589    p->cid_suppress_expire = 0;
06590    p->oprmode = 0;
06591 hangup_out:
06592    ast->tech_pvt = NULL;
06593    ast_free(p->cidspill);
06594    p->cidspill = NULL;
06595 
06596    ast_mutex_unlock(&p->lock);
06597    ast_verb(3, "Hungup '%s'\n", ast->name);
06598 
06599    ast_mutex_lock(&iflock);
06600    if (p->restartpending) {
06601       num_restart_pending--;
06602    }
06603 
06604    if (p->destroy) {
06605       destroy_channel(p, 0);
06606    }
06607    ast_mutex_unlock(&iflock);
06608 
06609    ast_module_unref(ast_module_info->self);
06610    return 0;
06611 }
06612 
06613 static int dahdi_answer(struct ast_channel *ast)
06614 {
06615    struct dahdi_pvt *p = ast->tech_pvt;
06616    int res = 0;
06617    int idx;
06618    ast_setstate(ast, AST_STATE_UP);/*! \todo XXX this is redundantly set by the analog and PRI submodules! */
06619    ast_mutex_lock(&p->lock);
06620    idx = dahdi_get_index(ast, p, 0);
06621    if (idx < 0)
06622       idx = SUB_REAL;
06623    /* nothing to do if a radio channel */
06624    if ((p->radio || (p->oprmode < 0))) {
06625       ast_mutex_unlock(&p->lock);
06626       return 0;
06627    }
06628 
06629    if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
06630       res = analog_answer(p->sig_pvt, ast);
06631       ast_mutex_unlock(&p->lock);
06632       return res;
06633    }
06634 
06635    switch (p->sig) {
06636 #if defined(HAVE_PRI)
06637    case SIG_PRI_LIB_HANDLE_CASES:
06638       res = sig_pri_answer(p->sig_pvt, ast);
06639       break;
06640 #endif   /* defined(HAVE_PRI) */
06641 #if defined(HAVE_SS7)
06642    case SIG_SS7:
06643       res = sig_ss7_answer(p->sig_pvt, ast);
06644       break;
06645 #endif   /* defined(HAVE_SS7) */
06646 #ifdef HAVE_OPENR2
06647    case SIG_MFCR2:
06648       if (!p->mfcr2_call_accepted) {
06649          /* The call was not accepted on offer nor the user, so it must be accepted now before answering,
06650             openr2_chan_answer_call will be called when the callback on_call_accepted is executed */
06651          p->mfcr2_answer_pending = 1;
06652          if (p->mfcr2_charge_calls) {
06653             ast_log(LOG_DEBUG, "Accepting MFC/R2 call with charge before answering on chan %d\n", p->channel);
06654             openr2_chan_accept_call(p->r2chan, OR2_CALL_WITH_CHARGE);
06655          } else {
06656             ast_log(LOG_DEBUG, "Accepting MFC/R2 call with no charge before answering on chan %d\n", p->channel);
06657             openr2_chan_accept_call(p->r2chan, OR2_CALL_NO_CHARGE);
06658          }
06659       } else {
06660          ast_log(LOG_DEBUG, "Answering MFC/R2 call on chan %d\n", p->channel);
06661          dahdi_r2_answer(p);
06662       }
06663       break;
06664 #endif
06665    case 0:
06666       ast_mutex_unlock(&p->lock);
06667       return 0;
06668    default:
06669       ast_log(LOG_WARNING, "Don't know how to answer signalling %d (channel %d)\n", p->sig, p->channel);
06670       res = -1;
06671       break;
06672    }
06673    ast_mutex_unlock(&p->lock);
06674    return res;
06675 }
06676 
06677 static void disable_dtmf_detect(struct dahdi_pvt *p)
06678 {
06679    int val = 0;
06680 
06681    p->ignoredtmf = 1;
06682 
06683    ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
06684 
06685    if (!p->hardwaredtmf && p->dsp) {
06686       p->dsp_features &= ~DSP_FEATURE_DIGIT_DETECT;
06687       ast_dsp_set_features(p->dsp, p->dsp_features);
06688    }
06689 }
06690 
06691 static void enable_dtmf_detect(struct dahdi_pvt *p)
06692 {
06693    int val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
06694 
06695    if (p->channel == CHAN_PSEUDO)
06696       return;
06697 
06698    p->ignoredtmf = 0;
06699 
06700    ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
06701 
06702    if (!p->hardwaredtmf && p->dsp) {
06703       p->dsp_features |= DSP_FEATURE_DIGIT_DETECT;
06704       ast_dsp_set_features(p->dsp, p->dsp_features);
06705    }
06706 }
06707 
06708 static int dahdi_queryoption(struct ast_channel *chan, int option, void *data, int *datalen)
06709 {
06710    char *cp;
06711    struct dahdi_pvt *p = chan->tech_pvt;
06712 
06713    /* all supported options require data */
06714    if (!p || !data || (*datalen < 1)) {
06715       errno = EINVAL;
06716       return -1;
06717    }
06718 
06719    switch (option) {
06720    case AST_OPTION_DIGIT_DETECT:
06721       cp = (char *) data;
06722       *cp = p->ignoredtmf ? 0 : 1;
06723       ast_debug(1, "Reporting digit detection %sabled on %s\n", *cp ? "en" : "dis", chan->name);
06724       break;
06725    case AST_OPTION_FAX_DETECT:
06726       cp = (char *) data;
06727       *cp = (p->dsp_features & DSP_FEATURE_FAX_DETECT) ? 0 : 1;
06728       ast_debug(1, "Reporting fax tone detection %sabled on %s\n", *cp ? "en" : "dis", chan->name);
06729       break;
06730    case AST_OPTION_CC_AGENT_TYPE:
06731 #if defined(HAVE_PRI)
06732 #if defined(HAVE_PRI_CCSS)
06733       if (dahdi_sig_pri_lib_handles(p->sig)) {
06734          ast_copy_string((char *) data, dahdi_pri_cc_type, *datalen);
06735          break;
06736       }
06737 #endif   /* defined(HAVE_PRI_CCSS) */
06738 #endif   /* defined(HAVE_PRI) */
06739       return -1;
06740    default:
06741       return -1;
06742    }
06743 
06744    errno = 0;
06745 
06746    return 0;
06747 }
06748 
06749 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen)
06750 {
06751    char *cp;
06752    signed char *scp;
06753    int x;
06754    int idx;
06755    struct dahdi_pvt *p = chan->tech_pvt, *pp;
06756    struct oprmode *oprmode;
06757 
06758 
06759    /* all supported options require data */
06760    if (!p || !data || (datalen < 1)) {
06761       errno = EINVAL;
06762       return -1;
06763    }
06764 
06765    switch (option) {
06766    case AST_OPTION_TXGAIN:
06767       scp = (signed char *) data;
06768       idx = dahdi_get_index(chan, p, 0);
06769       if (idx < 0) {
06770          ast_log(LOG_WARNING, "No index in TXGAIN?\n");
06771          return -1;
06772       }
06773       ast_debug(1, "Setting actual tx gain on %s to %f\n", chan->name, p->txgain + (float) *scp);
06774       return set_actual_txgain(p->subs[idx].dfd, p->txgain + (float) *scp, p->txdrc, p->law);
06775    case AST_OPTION_RXGAIN:
06776       scp = (signed char *) data;
06777       idx = dahdi_get_index(chan, p, 0);
06778       if (idx < 0) {
06779          ast_log(LOG_WARNING, "No index in RXGAIN?\n");
06780          return -1;
06781       }
06782       ast_debug(1, "Setting actual rx gain on %s to %f\n", chan->name, p->rxgain + (float) *scp);
06783       return set_actual_rxgain(p->subs[idx].dfd, p->rxgain + (float) *scp, p->rxdrc, p->law);
06784    case AST_OPTION_TONE_VERIFY:
06785       if (!p->dsp)
06786          break;
06787       cp = (char *) data;
06788       switch (*cp) {
06789       case 1:
06790          ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",chan->name);
06791          ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | p->dtmfrelax);  /* set mute mode if desired */
06792          break;
06793       case 2:
06794          ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",chan->name);
06795          ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX | p->dtmfrelax);  /* set mute mode if desired */
06796          break;
06797       default:
06798          ast_debug(1, "Set option TONE VERIFY, mode: OFF(0) on %s\n",chan->name);
06799          ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);  /* set mute mode if desired */
06800          break;
06801       }
06802       break;
06803    case AST_OPTION_TDD:
06804       /* turn on or off TDD */
06805       cp = (char *) data;
06806       p->mate = 0;
06807       if (!*cp) { /* turn it off */
06808          ast_debug(1, "Set option TDD MODE, value: OFF(0) on %s\n",chan->name);
06809          if (p->tdd)
06810             tdd_free(p->tdd);
06811          p->tdd = 0;
06812          break;
06813       }
06814       ast_debug(1, "Set option TDD MODE, value: %s(%d) on %s\n",
06815          (*cp == 2) ? "MATE" : "ON", (int) *cp, chan->name);
06816       dahdi_disable_ec(p);
06817       /* otherwise, turn it on */
06818       if (!p->didtdd) { /* if havent done it yet */
06819          unsigned char mybuf[41000];/*! \todo XXX This is an abuse of the stack!! */
06820          unsigned char *buf;
06821          int size, res, fd, len;
06822          struct pollfd fds[1];
06823 
06824          buf = mybuf;
06825          memset(buf, 0x7f, sizeof(mybuf)); /* set to silence */
06826          ast_tdd_gen_ecdisa(buf + 16000, 16000);  /* put in tone */
06827          len = 40000;
06828          idx = dahdi_get_index(chan, p, 0);
06829          if (idx < 0) {
06830             ast_log(LOG_WARNING, "No index in TDD?\n");
06831             return -1;
06832          }
06833          fd = p->subs[idx].dfd;
06834          while (len) {
06835             if (ast_check_hangup(chan))
06836                return -1;
06837             size = len;
06838             if (size > READ_SIZE)
06839                size = READ_SIZE;
06840             fds[0].fd = fd;
06841             fds[0].events = POLLPRI | POLLOUT;
06842             fds[0].revents = 0;
06843             res = poll(fds, 1, -1);
06844             if (!res) {
06845                ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
06846                continue;
06847             }
06848             /* if got exception */
06849             if (fds[0].revents & POLLPRI)
06850                return -1;
06851             if (!(fds[0].revents & POLLOUT)) {
06852                ast_debug(1, "write fd not ready on channel %d\n", p->channel);
06853                continue;
06854             }
06855             res = write(fd, buf, size);
06856             if (res != size) {
06857                if (res == -1) return -1;
06858                ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
06859                break;
06860             }
06861             len -= size;
06862             buf += size;
06863          }
06864          p->didtdd = 1; /* set to have done it now */
06865       }
06866       if (*cp == 2) { /* Mate mode */
06867          if (p->tdd)
06868             tdd_free(p->tdd);
06869          p->tdd = 0;
06870          p->mate = 1;
06871          break;
06872       }
06873       if (!p->tdd) { /* if we don't have one yet */
06874          p->tdd = tdd_new(); /* allocate one */
06875       }
06876       break;
06877    case AST_OPTION_RELAXDTMF:  /* Relax DTMF decoding (or not) */
06878       if (!p->dsp)
06879          break;
06880       cp = (char *) data;
06881       ast_debug(1, "Set option RELAX DTMF, value: %s(%d) on %s\n",
06882          *cp ? "ON" : "OFF", (int) *cp, chan->name);
06883       ast_dsp_set_digitmode(p->dsp, ((*cp) ? DSP_DIGITMODE_RELAXDTMF : DSP_DIGITMODE_DTMF) | p->dtmfrelax);
06884       break;
06885    case AST_OPTION_AUDIO_MODE:  /* Set AUDIO mode (or not) */
06886 #if defined(HAVE_PRI)
06887       if (dahdi_sig_pri_lib_handles(p->sig)
06888          && ((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
06889          /* PRI nobch pseudo channel.  Does not handle ioctl(DAHDI_AUDIOMODE) */
06890          break;
06891       }
06892 #endif   /* defined(HAVE_PRI) */
06893 
06894       cp = (char *) data;
06895       if (!*cp) {
06896          ast_debug(1, "Set option AUDIO MODE, value: OFF(0) on %s\n", chan->name);
06897          x = 0;
06898          dahdi_disable_ec(p);
06899       } else {
06900          ast_debug(1, "Set option AUDIO MODE, value: ON(1) on %s\n", chan->name);
06901          x = 1;
06902       }
06903       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x) == -1)
06904          ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, x, strerror(errno));
06905       break;
06906    case AST_OPTION_OPRMODE:  /* Operator services mode */
06907       oprmode = (struct oprmode *) data;
06908       /* We don't support operator mode across technologies */
06909       if (strcasecmp(chan->tech->type, oprmode->peer->tech->type)) {
06910          ast_log(LOG_NOTICE, "Operator mode not supported on %s to %s calls.\n",
06911                chan->tech->type, oprmode->peer->tech->type);
06912          errno = EINVAL;
06913          return -1;
06914       }
06915       pp = oprmode->peer->tech_pvt;
06916       p->oprmode = pp->oprmode = 0;
06917       /* setup peers */
06918       p->oprpeer = pp;
06919       pp->oprpeer = p;
06920       /* setup modes, if any */
06921       if (oprmode->mode)
06922       {
06923          pp->oprmode = oprmode->mode;
06924          p->oprmode = -oprmode->mode;
06925       }
06926       ast_debug(1, "Set Operator Services mode, value: %d on %s/%s\n",
06927          oprmode->mode, chan->name,oprmode->peer->name);
06928       break;
06929    case AST_OPTION_ECHOCAN:
06930       cp = (char *) data;
06931       if (*cp) {
06932          ast_debug(1, "Enabling echo cancellation on %s\n", chan->name);
06933          dahdi_enable_ec(p);
06934       } else {
06935          ast_debug(1, "Disabling echo cancellation on %s\n", chan->name);
06936          dahdi_disable_ec(p);
06937       }
06938       break;
06939    case AST_OPTION_DIGIT_DETECT:
06940       cp = (char *) data;
06941       ast_debug(1, "%sabling digit detection on %s\n", *cp ? "En" : "Dis", chan->name);
06942       if (*cp) {
06943          enable_dtmf_detect(p);
06944       } else {
06945          disable_dtmf_detect(p);
06946       }
06947       break;
06948    case AST_OPTION_FAX_DETECT:
06949       cp = (char *) data;
06950       if (p->dsp) {
06951          ast_debug(1, "%sabling fax tone detection on %s\n", *cp ? "En" : "Dis", chan->name);
06952          if (*cp) {
06953             p->dsp_features |= DSP_FEATURE_FAX_DETECT;
06954          } else {
06955             p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
06956          }
06957          ast_dsp_set_features(p->dsp, p->dsp_features);
06958       }
06959       break;
06960    default:
06961       return -1;
06962    }
06963    errno = 0;
06964 
06965    return 0;
06966 }
06967 
06968 static int dahdi_func_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len)
06969 {
06970    struct dahdi_pvt *p = chan->tech_pvt;
06971    int res = 0;
06972 
06973    if (!p) {
06974       /* No private structure! */
06975       *buf = '\0';
06976       return -1;
06977    }
06978 
06979    if (!strcasecmp(data, "rxgain")) {
06980       ast_mutex_lock(&p->lock);
06981       snprintf(buf, len, "%f", p->rxgain);
06982       ast_mutex_unlock(&p->lock);
06983    } else if (!strcasecmp(data, "txgain")) {
06984       ast_mutex_lock(&p->lock);
06985       snprintf(buf, len, "%f", p->txgain);
06986       ast_mutex_unlock(&p->lock);
06987    } else if (!strcasecmp(data, "dahdi_channel")) {
06988       ast_mutex_lock(&p->lock);
06989       snprintf(buf, len, "%d", p->channel);
06990       ast_mutex_unlock(&p->lock);
06991    } else if (!strcasecmp(data, "dahdi_span")) {
06992       ast_mutex_lock(&p->lock);
06993       snprintf(buf, len, "%d", p->span);
06994       ast_mutex_unlock(&p->lock);
06995    } else if (!strcasecmp(data, "dahdi_type")) {
06996       ast_mutex_lock(&p->lock);
06997       switch (p->sig) {
06998 #if defined(HAVE_OPENR2)
06999       case SIG_MFCR2:
07000          ast_copy_string(buf, "mfc/r2", len);
07001          break;
07002 #endif   /* defined(HAVE_OPENR2) */
07003 #if defined(HAVE_PRI)
07004       case SIG_PRI_LIB_HANDLE_CASES:
07005          ast_copy_string(buf, "pri", len);
07006          break;
07007 #endif   /* defined(HAVE_PRI) */
07008       case 0:
07009          ast_copy_string(buf, "pseudo", len);
07010          break;
07011 #if defined(HAVE_SS7)
07012       case SIG_SS7:
07013          ast_copy_string(buf, "ss7", len);
07014          break;
07015 #endif   /* defined(HAVE_SS7) */
07016       default:
07017          /* The only thing left is analog ports. */
07018          ast_copy_string(buf, "analog", len);
07019          break;
07020       }
07021       ast_mutex_unlock(&p->lock);
07022 #if defined(HAVE_PRI)
07023 #if defined(HAVE_PRI_REVERSE_CHARGE)
07024    } else if (!strcasecmp(data, "reversecharge")) {
07025       ast_mutex_lock(&p->lock);
07026       switch (p->sig) {
07027       case SIG_PRI_LIB_HANDLE_CASES:
07028          snprintf(buf, len, "%d", ((struct sig_pri_chan *) p->sig_pvt)->reverse_charging_indication);
07029          break;
07030       default:
07031          *buf = '\0';
07032          res = -1;
07033          break;
07034       }
07035       ast_mutex_unlock(&p->lock);
07036 #endif
07037 #if defined(HAVE_PRI_SETUP_KEYPAD)
07038    } else if (!strcasecmp(data, "keypad_digits")) {
07039       ast_mutex_lock(&p->lock);
07040       switch (p->sig) {
07041       case SIG_PRI_LIB_HANDLE_CASES:
07042          ast_copy_string(buf, ((struct sig_pri_chan *) p->sig_pvt)->keypad_digits,
07043             len);
07044          break;
07045       default:
07046          *buf = '\0';
07047          res = -1;
07048          break;
07049       }
07050       ast_mutex_unlock(&p->lock);
07051 #endif   /* defined(HAVE_PRI_SETUP_KEYPAD) */
07052    } else if (!strcasecmp(data, "no_media_path")) {
07053       ast_mutex_lock(&p->lock);
07054       switch (p->sig) {
07055       case SIG_PRI_LIB_HANDLE_CASES:
07056          /*
07057           * TRUE if the call is on hold or is call waiting because
07058           * there is no media path available.
07059           */
07060          snprintf(buf, len, "%d", ((struct sig_pri_chan *) p->sig_pvt)->no_b_channel);
07061          break;
07062       default:
07063          *buf = '\0';
07064          res = -1;
07065          break;
07066       }
07067       ast_mutex_unlock(&p->lock);
07068 #endif   /* defined(HAVE_PRI) */
07069    } else {
07070       *buf = '\0';
07071       res = -1;
07072    }
07073 
07074    return res;
07075 }
07076 
07077 
07078 static int parse_buffers_policy(const char *parse, int *num_buffers, int *policy)
07079 {
07080    int res;
07081    char policy_str[21] = "";
07082 
07083    if ((res = sscanf(parse, "%30d,%20s", num_buffers, policy_str)) != 2) {
07084       ast_log(LOG_WARNING, "Parsing buffer string '%s' failed.\n", parse);
07085       return 1;
07086    }
07087    if (*num_buffers < 0) {
07088       ast_log(LOG_WARNING, "Invalid buffer count given '%d'.\n", *num_buffers);
07089       return -1;
07090    }
07091    if (!strcasecmp(policy_str, "full")) {
07092       *policy = DAHDI_POLICY_WHEN_FULL;
07093    } else if (!strcasecmp(policy_str, "immediate")) {
07094       *policy = DAHDI_POLICY_IMMEDIATE;
07095 #if defined(HAVE_DAHDI_HALF_FULL)
07096    } else if (!strcasecmp(policy_str, "half")) {
07097       *policy = DAHDI_POLICY_HALF_FULL;
07098 #endif
07099    } else {
07100       ast_log(LOG_WARNING, "Invalid policy name given '%s'.\n", policy_str);
07101       return -1;
07102    }
07103 
07104    return 0;
07105 }
07106 
07107 static int dahdi_func_write(struct ast_channel *chan, const char *function, char *data, const char *value)
07108 {
07109    struct dahdi_pvt *p = chan->tech_pvt;
07110    int res = 0;
07111 
07112    if (!p) {
07113       /* No private structure! */
07114       return -1;
07115    }
07116 
07117    if (!strcasecmp(data, "buffers")) {
07118       int num_bufs, policy;
07119 
07120       if (!(parse_buffers_policy(value, &num_bufs, &policy))) {
07121          struct dahdi_bufferinfo bi = {
07122             .txbufpolicy = policy,
07123             .rxbufpolicy = policy,
07124             .bufsize = p->bufsize,
07125             .numbufs = num_bufs,
07126          };
07127          int bpres;
07128 
07129          if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
07130             ast_log(LOG_WARNING, "Channel '%d' unable to override buffer policy: %s\n", p->channel, strerror(errno));
07131          } else {
07132             p->bufferoverrideinuse = 1;
07133          }
07134       } else {
07135          res = -1;
07136       }
07137    } else if (!strcasecmp(data, "echocan_mode")) {
07138       if (!strcasecmp(value, "on")) {
07139          ast_mutex_lock(&p->lock);
07140          dahdi_enable_ec(p);
07141          ast_mutex_unlock(&p->lock);
07142       } else if (!strcasecmp(value, "off")) {
07143          ast_mutex_lock(&p->lock);
07144          dahdi_disable_ec(p);
07145          ast_mutex_unlock(&p->lock);
07146 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
07147       } else if (!strcasecmp(value, "fax")) {
07148          int blah = 1;
07149 
07150          ast_mutex_lock(&p->lock);
07151          if (!p->echocanon) {
07152             dahdi_enable_ec(p);
07153          }
07154          if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_FAX_MODE, &blah)) {
07155             ast_log(LOG_WARNING, "Unable to place echocan into fax mode on channel %d: %s\n", p->channel, strerror(errno));
07156          }
07157          ast_mutex_unlock(&p->lock);
07158       } else if (!strcasecmp(value, "voice")) {
07159          int blah = 0;
07160 
07161          ast_mutex_lock(&p->lock);
07162          if (!p->echocanon) {
07163             dahdi_enable_ec(p);
07164          }
07165          if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_FAX_MODE, &blah)) {
07166             ast_log(LOG_WARNING, "Unable to place echocan into voice mode on channel %d: %s\n", p->channel, strerror(errno));
07167          }
07168          ast_mutex_unlock(&p->lock);
07169 #endif
07170       } else {
07171          ast_log(LOG_WARNING, "Unsupported value '%s' provided for '%s' item.\n", value, data);
07172          res = -1;
07173       }
07174    } else {
07175       res = -1;
07176    }
07177 
07178    return res;
07179 }
07180 
07181 static void dahdi_unlink(struct dahdi_pvt *slave, struct dahdi_pvt *master, int needlock)
07182 {
07183    /* Unlink a specific slave or all slaves/masters from a given master */
07184    int x;
07185    int hasslaves;
07186    if (!master)
07187       return;
07188    if (needlock) {
07189       ast_mutex_lock(&master->lock);
07190       if (slave) {
07191          while (ast_mutex_trylock(&slave->lock)) {
07192             DEADLOCK_AVOIDANCE(&master->lock);
07193          }
07194       }
07195    }
07196    hasslaves = 0;
07197    for (x = 0; x < MAX_SLAVES; x++) {
07198       if (master->slaves[x]) {
07199          if (!slave || (master->slaves[x] == slave)) {
07200             /* Take slave out of the conference */
07201             ast_debug(1, "Unlinking slave %d from %d\n", master->slaves[x]->channel, master->channel);
07202             conf_del(master, &master->slaves[x]->subs[SUB_REAL], SUB_REAL);
07203             conf_del(master->slaves[x], &master->subs[SUB_REAL], SUB_REAL);
07204             master->slaves[x]->master = NULL;
07205             master->slaves[x] = NULL;
07206          } else
07207             hasslaves = 1;
07208       }
07209       if (!hasslaves)
07210          master->inconference = 0;
07211    }
07212    if (!slave) {
07213       if (master->master) {
07214          /* Take master out of the conference */
07215          conf_del(master->master, &master->subs[SUB_REAL], SUB_REAL);
07216          conf_del(master, &master->master->subs[SUB_REAL], SUB_REAL);
07217          hasslaves = 0;
07218          for (x = 0; x < MAX_SLAVES; x++) {
07219             if (master->master->slaves[x] == master)
07220                master->master->slaves[x] = NULL;
07221             else if (master->master->slaves[x])
07222                hasslaves = 1;
07223          }
07224          if (!hasslaves)
07225             master->master->inconference = 0;
07226       }
07227       master->master = NULL;
07228    }
07229    update_conf(master);
07230    if (needlock) {
07231       if (slave)
07232          ast_mutex_unlock(&slave->lock);
07233       ast_mutex_unlock(&master->lock);
07234    }
07235 }
07236 
07237 static void dahdi_link(struct dahdi_pvt *slave, struct dahdi_pvt *master) {
07238    int x;
07239    if (!slave || !master) {
07240       ast_log(LOG_WARNING, "Tried to link to/from NULL??\n");
07241       return;
07242    }
07243    for (x = 0; x < MAX_SLAVES; x++) {
07244       if (!master->slaves[x]) {
07245          master->slaves[x] = slave;
07246          break;
07247       }
07248    }
07249    if (x >= MAX_SLAVES) {
07250       ast_log(LOG_WARNING, "Replacing slave %d with new slave, %d\n", master->slaves[MAX_SLAVES - 1]->channel, slave->channel);
07251       master->slaves[MAX_SLAVES - 1] = slave;
07252    }
07253    if (slave->master)
07254       ast_log(LOG_WARNING, "Replacing master %d with new master, %d\n", slave->master->channel, master->channel);
07255    slave->master = master;
07256 
07257    ast_debug(1, "Making %d slave to master %d at %d\n", slave->channel, master->channel, x);
07258 }
07259 
07260 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)
07261 {
07262    struct ast_channel *who;
07263    struct dahdi_pvt *p0, *p1, *op0, *op1;
07264    struct dahdi_pvt *master = NULL, *slave = NULL;
07265    struct ast_frame *f;
07266    int inconf = 0;
07267    int nothingok = 1;
07268    int ofd0, ofd1;
07269    int oi0, oi1, i0 = -1, i1 = -1, t0, t1;
07270    int os0 = -1, os1 = -1;
07271    int priority = 0;
07272    struct ast_channel *oc0, *oc1;
07273    enum ast_bridge_result res;
07274    struct timeval start = ast_tvnow();
07275 #ifdef PRI_2BCT
07276    int triedtopribridge = 0;
07277    q931_call *q931c0;
07278    q931_call *q931c1;
07279 #endif
07280 
07281    /* For now, don't attempt to native bridge if either channel needs DTMF detection.
07282       There is code below to handle it properly until DTMF is actually seen,
07283       but due to currently unresolved issues it's ignored...
07284    */
07285 
07286    if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1))
07287       return AST_BRIDGE_FAILED_NOWARN;
07288 
07289    ast_channel_lock(c0);
07290    while (ast_channel_trylock(c1)) {
07291       CHANNEL_DEADLOCK_AVOIDANCE(c0);
07292    }
07293 
07294    p0 = c0->tech_pvt;
07295    p1 = c1->tech_pvt;
07296    /* cant do pseudo-channels here */
07297    if (!p0 || (!p0->sig) || !p1 || (!p1->sig)) {
07298       ast_channel_unlock(c0);
07299       ast_channel_unlock(c1);
07300       return AST_BRIDGE_FAILED_NOWARN;
07301    }
07302 
07303    oi0 = dahdi_get_index(c0, p0, 0);
07304    oi1 = dahdi_get_index(c1, p1, 0);
07305    if ((oi0 < 0) || (oi1 < 0)) {
07306       ast_channel_unlock(c0);
07307       ast_channel_unlock(c1);
07308       return AST_BRIDGE_FAILED;
07309    }
07310 
07311    op0 = p0 = c0->tech_pvt;
07312    op1 = p1 = c1->tech_pvt;
07313    ofd0 = c0->fds[0];
07314    ofd1 = c1->fds[0];
07315    oc0 = p0->owner;
07316    oc1 = p1->owner;
07317 
07318    if (ast_mutex_trylock(&p0->lock)) {
07319       /* Don't block, due to potential for deadlock */
07320       ast_channel_unlock(c0);
07321       ast_channel_unlock(c1);
07322       ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
07323       return AST_BRIDGE_RETRY;
07324    }
07325    if (ast_mutex_trylock(&p1->lock)) {
07326       /* Don't block, due to potential for deadlock */
07327       ast_mutex_unlock(&p0->lock);
07328       ast_channel_unlock(c0);
07329       ast_channel_unlock(c1);
07330       ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
07331       return AST_BRIDGE_RETRY;
07332    }
07333 
07334    if ((p0->callwaiting && p0->callwaitingcallerid)
07335       || (p1->callwaiting && p1->callwaitingcallerid)) {
07336       /*
07337        * Call Waiting Caller ID requires DTMF detection to know if it
07338        * can send the CID spill.
07339        *
07340        * For now, don't attempt to native bridge if either channel
07341        * needs DTMF detection.  There is code below to handle it
07342        * properly until DTMF is actually seen, but due to currently
07343        * unresolved issues it's ignored...
07344        */
07345       ast_mutex_unlock(&p0->lock);
07346       ast_mutex_unlock(&p1->lock);
07347       ast_channel_unlock(c0);
07348       ast_channel_unlock(c1);
07349       return AST_BRIDGE_FAILED_NOWARN;
07350    }
07351 
07352 #if defined(HAVE_PRI)
07353    if ((dahdi_sig_pri_lib_handles(p0->sig)
07354          && ((struct sig_pri_chan *) p0->sig_pvt)->no_b_channel)
07355       || (dahdi_sig_pri_lib_handles(p1->sig)
07356          && ((struct sig_pri_chan *) p1->sig_pvt)->no_b_channel)) {
07357       /*
07358        * PRI nobch channels (hold and call waiting) are equivalent to
07359        * pseudo channels and cannot be done here.
07360        */
07361       ast_mutex_unlock(&p0->lock);
07362       ast_mutex_unlock(&p1->lock);
07363       ast_channel_unlock(c0);
07364       ast_channel_unlock(c1);
07365       return AST_BRIDGE_FAILED_NOWARN;
07366    }
07367 #endif   /* defined(HAVE_PRI) */
07368 
07369    if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
07370       if (p0->owner && p1->owner) {
07371          /* If we don't have a call-wait in a 3-way, and we aren't in a 3-way, we can be master */
07372          if (!p0->subs[SUB_CALLWAIT].inthreeway && !p1->subs[SUB_REAL].inthreeway) {
07373             master = p0;
07374             slave = p1;
07375             inconf = 1;
07376          } else if (!p1->subs[SUB_CALLWAIT].inthreeway && !p0->subs[SUB_REAL].inthreeway) {
07377             master = p1;
07378             slave = p0;
07379             inconf = 1;
07380          } else {
07381             ast_log(LOG_WARNING, "Huh?  Both calls are callwaits or 3-ways?  That's clever...?\n");
07382             ast_log(LOG_WARNING, "p0: chan %d/%d/CW%d/3W%d, p1: chan %d/%d/CW%d/3W%d\n",
07383                p0->channel,
07384                oi0, (p0->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
07385                p0->subs[SUB_REAL].inthreeway, p0->channel,
07386                oi0, (p1->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
07387                p1->subs[SUB_REAL].inthreeway);
07388          }
07389          nothingok = 0;
07390       }
07391    } else if ((oi0 == SUB_REAL) && (oi1 == SUB_THREEWAY)) {
07392       if (p1->subs[SUB_THREEWAY].inthreeway) {
07393          master = p1;
07394          slave = p0;
07395          nothingok = 0;
07396       }
07397    } else if ((oi0 == SUB_THREEWAY) && (oi1 == SUB_REAL)) {
07398       if (p0->subs[SUB_THREEWAY].inthreeway) {
07399          master = p0;
07400          slave = p1;
07401          nothingok = 0;
07402       }
07403    } else if ((oi0 == SUB_REAL) && (oi1 == SUB_CALLWAIT)) {
07404       /* We have a real and a call wait.  If we're in a three way call, put us in it, otherwise,
07405          don't put us in anything */
07406       if (p1->subs[SUB_CALLWAIT].inthreeway) {
07407          master = p1;
07408          slave = p0;
07409          nothingok = 0;
07410       }
07411    } else if ((oi0 == SUB_CALLWAIT) && (oi1 == SUB_REAL)) {
07412       /* Same as previous */
07413       if (p0->subs[SUB_CALLWAIT].inthreeway) {
07414          master = p0;
07415          slave = p1;
07416          nothingok = 0;
07417       }
07418    }
07419    ast_debug(1, "master: %d, slave: %d, nothingok: %d\n",
07420       master ? master->channel : 0, slave ? slave->channel : 0, nothingok);
07421    if (master && slave) {
07422       /* Stop any tones, or play ringtone as appropriate.  If they're bridged
07423          in an active threeway call with a channel that is ringing, we should
07424          indicate ringing. */
07425       if ((oi1 == SUB_THREEWAY) &&
07426          p1->subs[SUB_THREEWAY].inthreeway &&
07427          p1->subs[SUB_REAL].owner &&
07428          p1->subs[SUB_REAL].inthreeway &&
07429          (p1->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
07430          ast_debug(1,
07431             "Playing ringback on %d/%d(%s) since %d/%d(%s) is in a ringing three-way\n",
07432             p0->channel, oi0, c0->name, p1->channel, oi1, c1->name);
07433          tone_zone_play_tone(p0->subs[oi0].dfd, DAHDI_TONE_RINGTONE);
07434          os1 = p1->subs[SUB_REAL].owner->_state;
07435       } else {
07436          ast_debug(1, "Stopping tones on %d/%d(%s) talking to %d/%d(%s)\n",
07437             p0->channel, oi0, c0->name, p1->channel, oi1, c1->name);
07438          tone_zone_play_tone(p0->subs[oi0].dfd, -1);
07439       }
07440       if ((oi0 == SUB_THREEWAY) &&
07441          p0->subs[SUB_THREEWAY].inthreeway &&
07442          p0->subs[SUB_REAL].owner &&
07443          p0->subs[SUB_REAL].inthreeway &&
07444          (p0->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
07445          ast_debug(1,
07446             "Playing ringback on %d/%d(%s) since %d/%d(%s) is in a ringing three-way\n",
07447             p1->channel, oi1, c1->name, p0->channel, oi0, c0->name);
07448          tone_zone_play_tone(p1->subs[oi1].dfd, DAHDI_TONE_RINGTONE);
07449          os0 = p0->subs[SUB_REAL].owner->_state;
07450       } else {
07451          ast_debug(1, "Stopping tones on %d/%d(%s) talking to %d/%d(%s)\n",
07452             p1->channel, oi1, c1->name, p0->channel, oi0, c0->name);
07453          tone_zone_play_tone(p1->subs[oi1].dfd, -1);
07454       }
07455       if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
07456          if (!p0->echocanbridged || !p1->echocanbridged) {
07457             /* Disable echo cancellation if appropriate */
07458             dahdi_disable_ec(p0);
07459             dahdi_disable_ec(p1);
07460          }
07461       }
07462       dahdi_link(slave, master);
07463       master->inconference = inconf;
07464    } else if (!nothingok)
07465       ast_log(LOG_WARNING, "Can't link %d/%s with %d/%s\n", p0->channel, subnames[oi0], p1->channel, subnames[oi1]);
07466 
07467    update_conf(p0);
07468    update_conf(p1);
07469    t0 = p0->subs[SUB_REAL].inthreeway;
07470    t1 = p1->subs[SUB_REAL].inthreeway;
07471 
07472    ast_mutex_unlock(&p0->lock);
07473    ast_mutex_unlock(&p1->lock);
07474 
07475    ast_channel_unlock(c0);
07476    ast_channel_unlock(c1);
07477 
07478    /* Native bridge failed */
07479    if ((!master || !slave) && !nothingok) {
07480       dahdi_enable_ec(p0);
07481       dahdi_enable_ec(p1);
07482       return AST_BRIDGE_FAILED;
07483    }
07484 
07485    ast_verb(3, "Native bridging %s and %s\n", c0->name, c1->name);
07486 
07487    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
07488       disable_dtmf_detect(op0);
07489 
07490    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
07491       disable_dtmf_detect(op1);
07492 
07493    for (;;) {
07494       struct ast_channel *c0_priority[2] = {c0, c1};
07495       struct ast_channel *c1_priority[2] = {c1, c0};
07496       int ms;
07497 
07498       /* Here's our main loop...  Start by locking things, looking for private parts,
07499          and then balking if anything is wrong */
07500 
07501       ast_channel_lock(c0);
07502       while (ast_channel_trylock(c1)) {
07503          CHANNEL_DEADLOCK_AVOIDANCE(c0);
07504       }
07505 
07506       p0 = c0->tech_pvt;
07507       p1 = c1->tech_pvt;
07508 
07509       if (op0 == p0)
07510          i0 = dahdi_get_index(c0, p0, 1);
07511       if (op1 == p1)
07512          i1 = dahdi_get_index(c1, p1, 1);
07513 
07514       ast_channel_unlock(c0);
07515       ast_channel_unlock(c1);
07516       ms = ast_remaining_ms(start, timeoutms);
07517       if (!ms ||
07518          (op0 != p0) ||
07519          (op1 != p1) ||
07520          (ofd0 != c0->fds[0]) ||
07521          (ofd1 != c1->fds[0]) ||
07522          (p0->subs[SUB_REAL].owner && (os0 > -1) && (os0 != p0->subs[SUB_REAL].owner->_state)) ||
07523          (p1->subs[SUB_REAL].owner && (os1 > -1) && (os1 != p1->subs[SUB_REAL].owner->_state)) ||
07524          (oc0 != p0->owner) ||
07525          (oc1 != p1->owner) ||
07526          (t0 != p0->subs[SUB_REAL].inthreeway) ||
07527          (t1 != p1->subs[SUB_REAL].inthreeway) ||
07528          (oi0 != i0) ||
07529          (oi1 != i1)) {
07530          ast_debug(1, "Something changed out on %d/%d to %d/%d, returning -3 to restart\n",
07531             op0->channel, oi0, op1->channel, oi1);
07532          res = AST_BRIDGE_RETRY;
07533          goto return_from_bridge;
07534       }
07535 
07536 #ifdef PRI_2BCT
07537       if (!triedtopribridge) {
07538          triedtopribridge = 1;
07539          if (p0->pri && p0->pri == p1->pri && p0->pri->transfer) {
07540             ast_mutex_lock(&p0->pri->lock);
07541             switch (p0->sig) {
07542             case SIG_PRI_LIB_HANDLE_CASES:
07543                q931c0 = ((struct sig_pri_chan *) (p0->sig_pvt))->call;
07544                break;
07545             default:
07546                q931c0 = NULL;
07547                break;
07548             }
07549             switch (p1->sig) {
07550             case SIG_PRI_LIB_HANDLE_CASES:
07551                q931c1 = ((struct sig_pri_chan *) (p1->sig_pvt))->call;
07552                break;
07553             default:
07554                q931c1 = NULL;
07555                break;
07556             }
07557             if (q931c0 && q931c1) {
07558                pri_channel_bridge(q931c0, q931c1);
07559             }
07560             ast_mutex_unlock(&p0->pri->lock);
07561          }
07562       }
07563 #endif
07564 
07565       who = ast_waitfor_n(priority ? c0_priority : c1_priority, 2, &ms);
07566       if (!who) {
07567          ast_debug(1, "Ooh, empty read...\n");
07568          continue;
07569       }
07570       f = ast_read(who);
07571       if (!f || (f->frametype == AST_FRAME_CONTROL)) {
07572          *fo = f;
07573          *rc = who;
07574          res = AST_BRIDGE_COMPLETE;
07575          goto return_from_bridge;
07576       }
07577       if (f->frametype == AST_FRAME_DTMF) {
07578          if ((who == c0) && p0->pulsedial) {
07579             ast_write(c1, f);
07580          } else if ((who == c1) && p1->pulsedial) {
07581             ast_write(c0, f);
07582          } else {
07583             *fo = f;
07584             *rc = who;
07585             res = AST_BRIDGE_COMPLETE;
07586             goto return_from_bridge;
07587          }
07588       }
07589       ast_frfree(f);
07590 
07591       /* Swap who gets priority */
07592       priority = !priority;
07593    }
07594 
07595 return_from_bridge:
07596    if (op0 == p0)
07597       dahdi_enable_ec(p0);
07598 
07599    if (op1 == p1)
07600       dahdi_enable_ec(p1);
07601 
07602    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
07603       enable_dtmf_detect(op0);
07604 
07605    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
07606       enable_dtmf_detect(op1);
07607 
07608    dahdi_unlink(slave, master, 1);
07609 
07610    return res;
07611 }
07612 
07613 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
07614 {
07615    struct dahdi_pvt *p = newchan->tech_pvt;
07616    int x;
07617 
07618    ast_mutex_lock(&p->lock);
07619 
07620    ast_debug(1, "New owner for channel %d is %s\n", p->channel, newchan->name);
07621    if (p->owner == oldchan) {
07622       p->owner = newchan;
07623    }
07624    for (x = 0; x < 3; x++) {
07625       if (p->subs[x].owner == oldchan) {
07626          if (!x) {
07627             dahdi_unlink(NULL, p, 0);
07628          }
07629          p->subs[x].owner = newchan;
07630       }
07631    }
07632    if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
07633       analog_fixup(oldchan, newchan, p->sig_pvt);
07634 #if defined(HAVE_PRI)
07635    } else if (dahdi_sig_pri_lib_handles(p->sig)) {
07636       sig_pri_fixup(oldchan, newchan, p->sig_pvt);
07637 #endif   /* defined(HAVE_PRI) */
07638 #if defined(HAVE_SS7)
07639    } else if (p->sig == SIG_SS7) {
07640       sig_ss7_fixup(oldchan, newchan, p->sig_pvt);
07641 #endif   /* defined(HAVE_SS7) */
07642    }
07643    update_conf(p);
07644 
07645    ast_mutex_unlock(&p->lock);
07646 
07647    if (newchan->_state == AST_STATE_RINGING) {
07648       dahdi_indicate(newchan, AST_CONTROL_RINGING, NULL, 0);
07649    }
07650    return 0;
07651 }
07652 
07653 static int dahdi_ring_phone(struct dahdi_pvt *p)
07654 {
07655    int x;
07656    int res;
07657    /* Make sure our transmit state is on hook */
07658    x = 0;
07659    x = DAHDI_ONHOOK;
07660    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
07661    do {
07662       x = DAHDI_RING;
07663       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
07664       if (res) {
07665          switch (errno) {
07666          case EBUSY:
07667          case EINTR:
07668             /* Wait just in case */
07669             usleep(10000);
07670             continue;
07671          case EINPROGRESS:
07672             res = 0;
07673             break;
07674          default:
07675             ast_log(LOG_WARNING, "Couldn't ring the phone: %s\n", strerror(errno));
07676             res = 0;
07677          }
07678       }
07679    } while (res);
07680    return res;
07681 }
07682 
07683 static void *analog_ss_thread(void *data);
07684 
07685 static int attempt_transfer(struct dahdi_pvt *p)
07686 {
07687    /* In order to transfer, we need at least one of the channels to
07688       actually be in a call bridge.  We can't conference two applications
07689       together (but then, why would we want to?) */
07690    if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
07691       /* The three-way person we're about to transfer to could still be in MOH, so
07692          stop if now if appropriate */
07693       if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner))
07694          ast_queue_control(p->subs[SUB_THREEWAY].owner, AST_CONTROL_UNHOLD);
07695       if (p->subs[SUB_REAL].owner->_state == AST_STATE_RINGING) {
07696          ast_indicate(ast_bridged_channel(p->subs[SUB_REAL].owner), AST_CONTROL_RINGING);
07697       }
07698       if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RING) {
07699          tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE);
07700       }
07701        if (ast_channel_masquerade(p->subs[SUB_THREEWAY].owner, ast_bridged_channel(p->subs[SUB_REAL].owner))) {
07702          ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
07703                ast_bridged_channel(p->subs[SUB_REAL].owner)->name, p->subs[SUB_THREEWAY].owner->name);
07704          return -1;
07705       }
07706       /* Orphan the channel after releasing the lock */
07707       ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
07708       unalloc_sub(p, SUB_THREEWAY);
07709    } else if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
07710       ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
07711       if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RINGING) {
07712          ast_indicate(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), AST_CONTROL_RINGING);
07713       }
07714       if (p->subs[SUB_REAL].owner->_state == AST_STATE_RING) {
07715          tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
07716       }
07717       if (ast_channel_masquerade(p->subs[SUB_REAL].owner, ast_bridged_channel(p->subs[SUB_THREEWAY].owner))) {
07718          ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
07719                ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->name, p->subs[SUB_REAL].owner->name);
07720          return -1;
07721       }
07722       /* Three-way is now the REAL */
07723       swap_subs(p, SUB_THREEWAY, SUB_REAL);
07724       ast_channel_unlock(p->subs[SUB_REAL].owner);
07725       unalloc_sub(p, SUB_THREEWAY);
07726       /* Tell the caller not to hangup */
07727       return 1;
07728    } else {
07729       ast_debug(1, "Neither %s nor %s are in a bridge, nothing to transfer\n",
07730          p->subs[SUB_REAL].owner->name, p->subs[SUB_THREEWAY].owner->name);
07731       p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
07732       return -1;
07733    }
07734    return 0;
07735 }
07736 
07737 static int check_for_conference(struct dahdi_pvt *p)
07738 {
07739    struct dahdi_confinfo ci;
07740    /* Fine if we already have a master, etc */
07741    if (p->master || (p->confno > -1))
07742       return 0;
07743    memset(&ci, 0, sizeof(ci));
07744    if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
07745       ast_log(LOG_WARNING, "Failed to get conference info on channel %d: %s\n", p->channel, strerror(errno));
07746       return 0;
07747    }
07748    /* If we have no master and don't have a confno, then
07749       if we're in a conference, it's probably a MeetMe room or
07750       some such, so don't let us 3-way out! */
07751    if ((p->subs[SUB_REAL].curconf.confno != ci.confno) || (p->subs[SUB_REAL].curconf.confmode != ci.confmode)) {
07752       ast_verb(3, "Avoiding 3-way call when in an external conference\n");
07753       return 1;
07754    }
07755    return 0;
07756 }
07757 
07758 /*! Checks channel for alarms
07759  * \param p a channel to check for alarms.
07760  * \returns the alarms on the span to which the channel belongs, or alarms on
07761  *          the channel if no span alarms.
07762  */
07763 static int get_alarms(struct dahdi_pvt *p)
07764 {
07765    int res;
07766    struct dahdi_spaninfo zi;
07767    struct dahdi_params params;
07768 
07769    memset(&zi, 0, sizeof(zi));
07770    zi.spanno = p->span;
07771 
07772    if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SPANSTAT, &zi)) >= 0) {
07773       if (zi.alarms != DAHDI_ALARM_NONE)
07774          return zi.alarms;
07775    } else {
07776       ast_log(LOG_WARNING, "Unable to determine alarm on channel %d: %s\n", p->channel, strerror(errno));
07777       return 0;
07778    }
07779 
07780    /* No alarms on the span. Check for channel alarms. */
07781    memset(&params, 0, sizeof(params));
07782    if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &params)) >= 0)
07783       return params.chan_alarms;
07784 
07785    ast_log(LOG_WARNING, "Unable to determine alarm on channel %d\n", p->channel);
07786 
07787    return DAHDI_ALARM_NONE;
07788 }
07789 
07790 static void dahdi_handle_dtmf(struct ast_channel *ast, int idx, struct ast_frame **dest)
07791 {
07792    struct dahdi_pvt *p = ast->tech_pvt;
07793    struct ast_frame *f = *dest;
07794 
07795    ast_debug(1, "%s DTMF digit: 0x%02X '%c' on %s\n",
07796       f->frametype == AST_FRAME_DTMF_BEGIN ? "Begin" : "End",
07797       (unsigned)f->subclass.integer, f->subclass.integer, ast->name);
07798 
07799    if (p->confirmanswer) {
07800       if (f->frametype == AST_FRAME_DTMF_END) {
07801          ast_debug(1, "Confirm answer on %s!\n", ast->name);
07802          /* Upon receiving a DTMF digit, consider this an answer confirmation instead
07803             of a DTMF digit */
07804          p->subs[idx].f.frametype = AST_FRAME_CONTROL;
07805          p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
07806          /* Reset confirmanswer so DTMF's will behave properly for the duration of the call */
07807          p->confirmanswer = 0;
07808       } else {
07809          p->subs[idx].f.frametype = AST_FRAME_NULL;
07810          p->subs[idx].f.subclass.integer = 0;
07811       }
07812       *dest = &p->subs[idx].f;
07813    } else if (p->callwaitcas) {
07814       if (f->frametype == AST_FRAME_DTMF_END) {
07815          if ((f->subclass.integer == 'A') || (f->subclass.integer == 'D')) {
07816             ast_debug(1, "Got some DTMF, but it's for the CAS\n");
07817             ast_free(p->cidspill);
07818             p->cidspill = NULL;
07819             send_cwcidspill(p);
07820          }
07821          p->callwaitcas = 0;
07822       }
07823       p->subs[idx].f.frametype = AST_FRAME_NULL;
07824       p->subs[idx].f.subclass.integer = 0;
07825       *dest = &p->subs[idx].f;
07826    } else if (f->subclass.integer == 'f') {
07827       if (f->frametype == AST_FRAME_DTMF_END) {
07828          /* Fax tone -- Handle and return NULL */
07829          if ((p->callprogress & CALLPROGRESS_FAX) && !p->faxhandled) {
07830             /* If faxbuffers are configured, use them for the fax transmission */
07831             if (p->usefaxbuffers && !p->bufferoverrideinuse) {
07832                struct dahdi_bufferinfo bi = {
07833                   .txbufpolicy = p->faxbuf_policy,
07834                   .bufsize = p->bufsize,
07835                   .numbufs = p->faxbuf_no
07836                };
07837                int res;
07838 
07839                if ((res = ioctl(p->subs[idx].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
07840                   ast_log(LOG_WARNING, "Channel '%s' unable to set buffer policy, reason: %s\n", ast->name, strerror(errno));
07841                } else {
07842                   p->bufferoverrideinuse = 1;
07843                }
07844             }
07845             p->faxhandled = 1;
07846             if (p->dsp) {
07847                p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
07848                ast_dsp_set_features(p->dsp, p->dsp_features);
07849                ast_debug(1, "Disabling FAX tone detection on %s after tone received\n", ast->name);
07850             }
07851             if (strcmp(ast->exten, "fax")) {
07852                const char *target_context = S_OR(ast->macrocontext, ast->context);
07853 
07854                /* We need to unlock 'ast' here because ast_exists_extension has the
07855                 * potential to start autoservice on the channel. Such action is prone
07856                 * to deadlock.
07857                 */
07858                ast_mutex_unlock(&p->lock);
07859                ast_channel_unlock(ast);
07860                if (ast_exists_extension(ast, target_context, "fax", 1,
07861                   S_COR(ast->caller.id.number.valid, ast->caller.id.number.str, NULL))) {
07862                   ast_channel_lock(ast);
07863                   ast_mutex_lock(&p->lock);
07864                   ast_verb(3, "Redirecting %s to fax extension\n", ast->name);
07865                   /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
07866                   pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten);
07867                   if (ast_async_goto(ast, target_context, "fax", 1))
07868                      ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context);
07869                } else {
07870                   ast_channel_lock(ast);
07871                   ast_mutex_lock(&p->lock);
07872                   ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
07873                }
07874             } else {
07875                ast_debug(1, "Already in a fax extension, not redirecting\n");
07876             }
07877          } else {
07878             ast_debug(1, "Fax already handled\n");
07879          }
07880          dahdi_confmute(p, 0);
07881       }
07882       p->subs[idx].f.frametype = AST_FRAME_NULL;
07883       p->subs[idx].f.subclass.integer = 0;
07884       *dest = &p->subs[idx].f;
07885    }
07886 }
07887 
07888 static void handle_alarms(struct dahdi_pvt *p, int alms)
07889 {
07890    const char *alarm_str;
07891 
07892 #if defined(HAVE_PRI)
07893    if (dahdi_sig_pri_lib_handles(p->sig) && sig_pri_is_alarm_ignored(p->pri)) {
07894       return;
07895    }
07896 #endif   /* defined(HAVE_PRI) */
07897 
07898    alarm_str = alarm2str(alms);
07899    if (report_alarms & REPORT_CHANNEL_ALARMS) {
07900       ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", p->channel, alarm_str);
07901       manager_event(EVENT_FLAG_SYSTEM, "Alarm",
07902                  "Alarm: %s\r\n"
07903                  "Channel: %d\r\n",
07904                  alarm_str, p->channel);
07905    }
07906 
07907    if (report_alarms & REPORT_SPAN_ALARMS && p->manages_span_alarms) {
07908       ast_log(LOG_WARNING, "Detected alarm on span %d: %s\n", p->span, alarm_str);
07909       manager_event(EVENT_FLAG_SYSTEM, "SpanAlarm",
07910                  "Alarm: %s\r\n"
07911                  "Span: %d\r\n",
07912                  alarm_str, p->span);
07913    }
07914 }
07915 
07916 static struct ast_frame *dahdi_handle_event(struct ast_channel *ast)
07917 {
07918    int res, x;
07919    int idx, mysig;
07920    char *c;
07921    struct dahdi_pvt *p = ast->tech_pvt;
07922    pthread_t threadid;
07923    struct ast_channel *chan;
07924    struct ast_frame *f;
07925 
07926    idx = dahdi_get_index(ast, p, 0);
07927    if (idx < 0) {
07928       return &ast_null_frame;
07929    }
07930    mysig = p->sig;
07931    if (p->outsigmod > -1)
07932       mysig = p->outsigmod;
07933    p->subs[idx].f.frametype = AST_FRAME_NULL;
07934    p->subs[idx].f.subclass.integer = 0;
07935    p->subs[idx].f.datalen = 0;
07936    p->subs[idx].f.samples = 0;
07937    p->subs[idx].f.mallocd = 0;
07938    p->subs[idx].f.offset = 0;
07939    p->subs[idx].f.src = "dahdi_handle_event";
07940    p->subs[idx].f.data.ptr = NULL;
07941    f = &p->subs[idx].f;
07942 
07943    if (p->fake_event) {
07944       res = p->fake_event;
07945       p->fake_event = 0;
07946    } else
07947       res = dahdi_get_event(p->subs[idx].dfd);
07948 
07949    ast_debug(1, "Got event %s(%d) on channel %d (index %d)\n", event2str(res), res, p->channel, idx);
07950 
07951    if (res & (DAHDI_EVENT_PULSEDIGIT | DAHDI_EVENT_DTMFUP)) {
07952       p->pulsedial = (res & DAHDI_EVENT_PULSEDIGIT) ? 1 : 0;
07953       ast_debug(1, "Detected %sdigit '%c'\n", p->pulsedial ? "pulse ": "", res & 0xff);
07954 #if defined(HAVE_PRI)
07955       if (dahdi_sig_pri_lib_handles(p->sig)
07956          && ((struct sig_pri_chan *) p->sig_pvt)->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING
07957          && p->pri
07958          && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
07959          /* absorb event */
07960       } else
07961 #endif   /* defined(HAVE_PRI) */
07962       {
07963          /* Unmute conference */
07964          dahdi_confmute(p, 0);
07965          p->subs[idx].f.frametype = AST_FRAME_DTMF_END;
07966          p->subs[idx].f.subclass.integer = res & 0xff;
07967          dahdi_handle_dtmf(ast, idx, &f);
07968       }
07969       return f;
07970    }
07971 
07972    if (res & DAHDI_EVENT_DTMFDOWN) {
07973       ast_debug(1, "DTMF Down '%c'\n", res & 0xff);
07974 #if defined(HAVE_PRI)
07975       if (dahdi_sig_pri_lib_handles(p->sig)
07976          && ((struct sig_pri_chan *) p->sig_pvt)->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING
07977          && p->pri
07978          && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
07979          /* absorb event */
07980       } else
07981 #endif   /* defined(HAVE_PRI) */
07982       {
07983          /* Mute conference */
07984          dahdi_confmute(p, 1);
07985          p->subs[idx].f.frametype = AST_FRAME_DTMF_BEGIN;
07986          p->subs[idx].f.subclass.integer = res & 0xff;
07987          dahdi_handle_dtmf(ast, idx, &f);
07988       }
07989       return &p->subs[idx].f;
07990    }
07991 
07992    switch (res) {
07993    case DAHDI_EVENT_EC_DISABLED:
07994       ast_verb(3, "Channel %d echo canceler disabled.\n", p->channel);
07995       p->echocanon = 0;
07996       break;
07997 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
07998    case DAHDI_EVENT_TX_CED_DETECTED:
07999       ast_verb(3, "Channel %d detected a CED tone towards the network.\n", p->channel);
08000       break;
08001    case DAHDI_EVENT_RX_CED_DETECTED:
08002       ast_verb(3, "Channel %d detected a CED tone from the network.\n", p->channel);
08003       break;
08004    case DAHDI_EVENT_EC_NLP_DISABLED:
08005       ast_verb(3, "Channel %d echo canceler disabled its NLP.\n", p->channel);
08006       break;
08007    case DAHDI_EVENT_EC_NLP_ENABLED:
08008       ast_verb(3, "Channel %d echo canceler enabled its NLP.\n", p->channel);
08009       break;
08010 #endif
08011    case DAHDI_EVENT_BITSCHANGED:
08012 #ifdef HAVE_OPENR2
08013       if (p->sig != SIG_MFCR2) {
08014          ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig));
08015       } else {
08016          ast_log(LOG_DEBUG, "bits changed in chan %d\n", p->channel);
08017          openr2_chan_handle_cas(p->r2chan);
08018       }
08019 #else
08020       ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig));
08021 #endif
08022       break;
08023    case DAHDI_EVENT_PULSE_START:
08024       /* Stop tone if there's a pulse start and the PBX isn't started */
08025       if (!ast->pbx)
08026          tone_zone_play_tone(p->subs[idx].dfd, -1);
08027       break;
08028    case DAHDI_EVENT_DIALCOMPLETE:
08029       /* DAHDI has completed dialing all digits sent using DAHDI_DIAL. */
08030 #if defined(HAVE_PRI)
08031       if (dahdi_sig_pri_lib_handles(p->sig)) {
08032          if (p->inalarm) {
08033             break;
08034          }
08035          if (ioctl(p->subs[idx].dfd, DAHDI_DIALING, &x) == -1) {
08036             ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed on %s: %s\n", ast->name,
08037                strerror(errno));
08038             return NULL;
08039          }
08040          if (x) {
08041             /* Still dialing in DAHDI driver */
08042             break;
08043          }
08044          /*
08045           * The ast channel is locked and the private may be locked more
08046           * than once.
08047           */
08048          sig_pri_dial_complete(p->sig_pvt, ast);
08049          break;
08050       }
08051 #endif   /* defined(HAVE_PRI) */
08052 #ifdef HAVE_OPENR2
08053       if ((p->sig & SIG_MFCR2) && p->r2chan && ast->_state != AST_STATE_UP) {
08054          /* we don't need to do anything for this event for R2 signaling
08055             if the call is being setup */
08056          break;
08057       }
08058 #endif
08059       if (p->inalarm) break;
08060       if ((p->radio || (p->oprmode < 0))) break;
08061       if (ioctl(p->subs[idx].dfd,DAHDI_DIALING,&x) == -1) {
08062          ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed on %s: %s\n",ast->name, strerror(errno));
08063          return NULL;
08064       }
08065       if (!x) { /* if not still dialing in driver */
08066          dahdi_enable_ec(p);
08067          if (p->echobreak) {
08068             dahdi_train_ec(p);
08069             ast_copy_string(p->dop.dialstr, p->echorest, sizeof(p->dop.dialstr));
08070             p->dop.op = DAHDI_DIAL_OP_REPLACE;
08071             res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
08072             p->echobreak = 0;
08073          } else {
08074             p->dialing = 0;
08075             if ((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) {
08076                /* if thru with dialing after offhook */
08077                if (ast->_state == AST_STATE_DIALING_OFFHOOK) {
08078                   ast_setstate(ast, AST_STATE_UP);
08079                   p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08080                   p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
08081                   break;
08082                } else { /* if to state wait for offhook to dial rest */
08083                   /* we now wait for off hook */
08084                   ast_setstate(ast,AST_STATE_DIALING_OFFHOOK);
08085                }
08086             }
08087             if (ast->_state == AST_STATE_DIALING) {
08088                if ((p->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
08089                   ast_debug(1, "Done dialing, but waiting for progress detection before doing more...\n");
08090                } else if (p->confirmanswer || (!p->dialednone
08091                   && ((mysig == SIG_EM) || (mysig == SIG_EM_E1)
08092                      || (mysig == SIG_EMWINK) || (mysig == SIG_FEATD)
08093                      || (mysig == SIG_FEATDMF_TA) || (mysig == SIG_FEATDMF)
08094                      || (mysig == SIG_E911) || (mysig == SIG_FGC_CAMA)
08095                      || (mysig == SIG_FGC_CAMAMF) || (mysig == SIG_FEATB)
08096                      || (mysig == SIG_SF) || (mysig == SIG_SFWINK)
08097                      || (mysig == SIG_SF_FEATD) || (mysig == SIG_SF_FEATDMF)
08098                      || (mysig == SIG_SF_FEATB)))) {
08099                   ast_setstate(ast, AST_STATE_RINGING);
08100                } else if (!p->answeronpolarityswitch) {
08101                   ast_setstate(ast, AST_STATE_UP);
08102                   p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08103                   p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
08104                   /* If aops=0 and hops=1, this is necessary */
08105                   p->polarity = POLARITY_REV;
08106                } else {
08107                   /* Start clean, so we can catch the change to REV polarity when party answers */
08108                   p->polarity = POLARITY_IDLE;
08109                }
08110             }
08111          }
08112       }
08113       break;
08114    case DAHDI_EVENT_ALARM:
08115       switch (p->sig) {
08116 #if defined(HAVE_PRI)
08117       case SIG_PRI_LIB_HANDLE_CASES:
08118          sig_pri_chan_alarm_notify(p->sig_pvt, 0);
08119          break;
08120 #endif   /* defined(HAVE_PRI) */
08121 #if defined(HAVE_SS7)
08122       case SIG_SS7:
08123          sig_ss7_set_alarm(p->sig_pvt, 1);
08124          break;
08125 #endif   /* defined(HAVE_SS7) */
08126       default:
08127          p->inalarm = 1;
08128          break;
08129       }
08130       res = get_alarms(p);
08131       handle_alarms(p, res);
08132 #ifdef HAVE_PRI
08133       if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
08134          /* fall through intentionally */
08135       } else {
08136          break;
08137       }
08138 #endif
08139 #if defined(HAVE_SS7)
08140       if (p->sig == SIG_SS7)
08141          break;
08142 #endif   /* defined(HAVE_SS7) */
08143 #ifdef HAVE_OPENR2
08144       if (p->sig == SIG_MFCR2)
08145          break;
08146 #endif
08147    case DAHDI_EVENT_ONHOOK:
08148       if (p->radio) {
08149          p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08150          p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_UNKEY;
08151          break;
08152       }
08153       if (p->oprmode < 0)
08154       {
08155          if (p->oprmode != -1) break;
08156          if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
08157          {
08158             /* Make sure it starts ringing */
08159             dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
08160             dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RING);
08161             save_conference(p->oprpeer);
08162             tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
08163          }
08164          break;
08165       }
08166       switch (p->sig) {
08167       case SIG_FXOLS:
08168       case SIG_FXOGS:
08169       case SIG_FXOKS:
08170          /* Check for some special conditions regarding call waiting */
08171          if (idx == SUB_REAL) {
08172             /* The normal line was hung up */
08173             if (p->subs[SUB_CALLWAIT].owner) {
08174                /* There's a call waiting call, so ring the phone, but make it unowned in the mean time */
08175                swap_subs(p, SUB_CALLWAIT, SUB_REAL);
08176                ast_verb(3, "Channel %d still has (callwait) call, ringing phone\n", p->channel);
08177                unalloc_sub(p, SUB_CALLWAIT);
08178 #if 0
08179                p->subs[idx].needanswer = 0;
08180                p->subs[idx].needringing = 0;
08181 #endif
08182                p->callwaitingrepeat = 0;
08183                p->cidcwexpire = 0;
08184                p->cid_suppress_expire = 0;
08185                p->owner = NULL;
08186                /* Don't start streaming audio yet if the incoming call isn't up yet */
08187                if (p->subs[SUB_REAL].owner->_state != AST_STATE_UP)
08188                   p->dialing = 1;
08189                dahdi_ring_phone(p);
08190             } else if (p->subs[SUB_THREEWAY].owner) {
08191                unsigned int mssinceflash;
08192                /* Here we have to retain the lock on both the main channel, the 3-way channel, and
08193                   the private structure -- not especially easy or clean */
08194                while (p->subs[SUB_THREEWAY].owner && ast_channel_trylock(p->subs[SUB_THREEWAY].owner)) {
08195                   /* Yuck, didn't get the lock on the 3-way, gotta release everything and re-grab! */
08196                   DLA_UNLOCK(&p->lock);
08197                   CHANNEL_DEADLOCK_AVOIDANCE(ast);
08198                   /* We can grab ast and p in that order, without worry.  We should make sure
08199                      nothing seriously bad has happened though like some sort of bizarre double
08200                      masquerade! */
08201                   DLA_LOCK(&p->lock);
08202                   if (p->owner != ast) {
08203                      ast_log(LOG_WARNING, "This isn't good...\n");
08204                      return NULL;
08205                   }
08206                }
08207                if (!p->subs[SUB_THREEWAY].owner) {
08208                   ast_log(LOG_NOTICE, "Whoa, threeway disappeared kinda randomly.\n");
08209                   return NULL;
08210                }
08211                mssinceflash = ast_tvdiff_ms(ast_tvnow(), p->flashtime);
08212                ast_debug(1, "Last flash was %u ms ago\n", mssinceflash);
08213                if (mssinceflash < MIN_MS_SINCE_FLASH) {
08214                   /* It hasn't been long enough since the last flashook.  This is probably a bounce on
08215                      hanging up.  Hangup both channels now */
08216                   if (p->subs[SUB_THREEWAY].owner)
08217                      ast_queue_hangup_with_cause(p->subs[SUB_THREEWAY].owner, AST_CAUSE_NO_ANSWER);
08218                   p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08219                   ast_debug(1, "Looks like a bounced flash, hanging up both calls on %d\n", p->channel);
08220                   ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08221                } else if ((ast->pbx) || (ast->_state == AST_STATE_UP)) {
08222                   if (p->transfer) {
08223                      /* In any case this isn't a threeway call anymore */
08224                      p->subs[SUB_REAL].inthreeway = 0;
08225                      p->subs[SUB_THREEWAY].inthreeway = 0;
08226                      /* Only attempt transfer if the phone is ringing; why transfer to busy tone eh? */
08227                      if (!p->transfertobusy && ast->_state == AST_STATE_BUSY) {
08228                         ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08229                         /* Swap subs and dis-own channel */
08230                         swap_subs(p, SUB_THREEWAY, SUB_REAL);
08231                         p->owner = NULL;
08232                         /* Ring the phone */
08233                         dahdi_ring_phone(p);
08234                      } else {
08235                         if ((res = attempt_transfer(p)) < 0) {
08236                            p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08237                            if (p->subs[SUB_THREEWAY].owner)
08238                               ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08239                         } else if (res) {
08240                            /* Don't actually hang up at this point */
08241                            if (p->subs[SUB_THREEWAY].owner)
08242                               ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08243                            break;
08244                         }
08245                      }
08246                   } else {
08247                      p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08248                      if (p->subs[SUB_THREEWAY].owner)
08249                         ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08250                   }
08251                } else {
08252                   ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08253                   /* Swap subs and dis-own channel */
08254                   swap_subs(p, SUB_THREEWAY, SUB_REAL);
08255                   p->owner = NULL;
08256                   /* Ring the phone */
08257                   dahdi_ring_phone(p);
08258                }
08259             }
08260          } else {
08261             ast_log(LOG_WARNING, "Got a hangup and my index is %d?\n", idx);
08262          }
08263          /* Fall through */
08264       default:
08265          dahdi_disable_ec(p);
08266          return NULL;
08267       }
08268       break;
08269    case DAHDI_EVENT_RINGOFFHOOK:
08270       if (p->inalarm) break;
08271       if (p->oprmode < 0)
08272       {
08273          if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
08274          {
08275             /* Make sure it stops ringing */
08276             dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
08277             tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, -1);
08278             restore_conference(p->oprpeer);
08279          }
08280          break;
08281       }
08282       if (p->radio)
08283       {
08284          p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08285          p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_KEY;
08286          break;
08287       }
08288       /* for E911, its supposed to wait for offhook then dial
08289          the second half of the dial string */
08290       if (((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) && (ast->_state == AST_STATE_DIALING_OFFHOOK)) {
08291          c = strchr(p->dialdest, '/');
08292          if (c)
08293             c++;
08294          else
08295             c = p->dialdest;
08296          if (*c) snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*0%s#", c);
08297          else ast_copy_string(p->dop.dialstr,"M*2#", sizeof(p->dop.dialstr));
08298          if (strlen(p->dop.dialstr) > 4) {
08299             memset(p->echorest, 'w', sizeof(p->echorest) - 1);
08300             strcpy(p->echorest + (p->echotraining / 401) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
08301             p->echorest[sizeof(p->echorest) - 1] = '\0';
08302             p->echobreak = 1;
08303             p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
08304          } else
08305             p->echobreak = 0;
08306          if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
08307             int saveerr = errno;
08308 
08309             x = DAHDI_ONHOOK;
08310             ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
08311             ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
08312             return NULL;
08313             }
08314          p->dialing = 1;
08315          return &p->subs[idx].f;
08316       }
08317       switch (p->sig) {
08318       case SIG_FXOLS:
08319       case SIG_FXOGS:
08320       case SIG_FXOKS:
08321          switch (ast->_state) {
08322          case AST_STATE_RINGING:
08323             dahdi_enable_ec(p);
08324             dahdi_train_ec(p);
08325             p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08326             p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
08327             /* Make sure it stops ringing */
08328             p->subs[SUB_REAL].needringing = 0;
08329             dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
08330             ast_debug(1, "channel %d answered\n", p->channel);
08331 
08332             /* Cancel any running CallerID spill */
08333             ast_free(p->cidspill);
08334             p->cidspill = NULL;
08335             restore_conference(p);
08336 
08337             p->dialing = 0;
08338             p->callwaitcas = 0;
08339             if (p->confirmanswer) {
08340                /* Ignore answer if "confirm answer" is enabled */
08341                p->subs[idx].f.frametype = AST_FRAME_NULL;
08342                p->subs[idx].f.subclass.integer = 0;
08343             } else if (!ast_strlen_zero(p->dop.dialstr)) {
08344                /* nick@dccinc.com 4/3/03 - fxo should be able to do deferred dialing */
08345                res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
08346                if (res < 0) {
08347                   ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
08348                   p->dop.dialstr[0] = '\0';
08349                   return NULL;
08350                } else {
08351                   ast_debug(1, "Sent FXO deferred digit string: %s\n", p->dop.dialstr);
08352                   p->subs[idx].f.frametype = AST_FRAME_NULL;
08353                   p->subs[idx].f.subclass.integer = 0;
08354                   p->dialing = 1;
08355                }
08356                p->dop.dialstr[0] = '\0';
08357                ast_setstate(ast, AST_STATE_DIALING);
08358             } else
08359                ast_setstate(ast, AST_STATE_UP);
08360             return &p->subs[idx].f;
08361          case AST_STATE_DOWN:
08362             ast_setstate(ast, AST_STATE_RING);
08363             ast->rings = 1;
08364             p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08365             p->subs[idx].f.subclass.integer = AST_CONTROL_OFFHOOK;
08366             ast_debug(1, "channel %d picked up\n", p->channel);
08367             return &p->subs[idx].f;
08368          case AST_STATE_UP:
08369             /* Make sure it stops ringing */
08370             dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
08371             /* Okay -- probably call waiting*/
08372             if (ast_bridged_channel(p->owner))
08373                ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
08374             p->subs[idx].needunhold = 1;
08375             break;
08376          case AST_STATE_RESERVED:
08377             /* Start up dialtone */
08378             if (has_voicemail(p))
08379                res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
08380             else
08381                res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
08382             break;
08383          default:
08384             ast_log(LOG_WARNING, "FXO phone off hook in weird state %u??\n", ast->_state);
08385          }
08386          break;
08387       case SIG_FXSLS:
08388       case SIG_FXSGS:
08389       case SIG_FXSKS:
08390          if (ast->_state == AST_STATE_RING) {
08391             p->ringt = p->ringt_base;
08392          }
08393 
08394          /* If we get a ring then we cannot be in
08395           * reversed polarity. So we reset to idle */
08396          ast_debug(1, "Setting IDLE polarity due "
08397             "to ring. Old polarity was %d\n",
08398             p->polarity);
08399          p->polarity = POLARITY_IDLE;
08400 
08401          /* Fall through */
08402       case SIG_EM:
08403       case SIG_EM_E1:
08404       case SIG_EMWINK:
08405       case SIG_FEATD:
08406       case SIG_FEATDMF:
08407       case SIG_FEATDMF_TA:
08408       case SIG_E911:
08409       case SIG_FGC_CAMA:
08410       case SIG_FGC_CAMAMF:
08411       case SIG_FEATB:
08412       case SIG_SF:
08413       case SIG_SFWINK:
08414       case SIG_SF_FEATD:
08415       case SIG_SF_FEATDMF:
08416       case SIG_SF_FEATB:
08417          if (ast->_state == AST_STATE_PRERING)
08418             ast_setstate(ast, AST_STATE_RING);
08419          if ((ast->_state == AST_STATE_DOWN) || (ast->_state == AST_STATE_RING)) {
08420             ast_debug(1, "Ring detected\n");
08421             p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08422             p->subs[idx].f.subclass.integer = AST_CONTROL_RING;
08423          } else if (p->outgoing && ((ast->_state == AST_STATE_RINGING) || (ast->_state == AST_STATE_DIALING))) {
08424             ast_debug(1, "Line answered\n");
08425             if (p->confirmanswer) {
08426                p->subs[idx].f.frametype = AST_FRAME_NULL;
08427                p->subs[idx].f.subclass.integer = 0;
08428             } else {
08429                p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08430                p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
08431                ast_setstate(ast, AST_STATE_UP);
08432             }
08433          } else if (ast->_state != AST_STATE_RING)
08434             ast_log(LOG_WARNING, "Ring/Off-hook in strange state %u on channel %d\n", ast->_state, p->channel);
08435          break;
08436       default:
08437          ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
08438       }
08439       break;
08440    case DAHDI_EVENT_RINGBEGIN:
08441       switch (p->sig) {
08442       case SIG_FXSLS:
08443       case SIG_FXSGS:
08444       case SIG_FXSKS:
08445          if (ast->_state == AST_STATE_RING) {
08446             p->ringt = p->ringt_base;
08447          }
08448          break;
08449       }
08450       break;
08451    case DAHDI_EVENT_RINGERON:
08452       break;
08453    case DAHDI_EVENT_NOALARM:
08454       switch (p->sig) {
08455 #if defined(HAVE_PRI)
08456       case SIG_PRI_LIB_HANDLE_CASES:
08457          sig_pri_chan_alarm_notify(p->sig_pvt, 1);
08458          break;
08459 #endif   /* defined(HAVE_PRI) */
08460 #if defined(HAVE_SS7)
08461       case SIG_SS7:
08462          sig_ss7_set_alarm(p->sig_pvt, 0);
08463          break;
08464 #endif   /* defined(HAVE_SS7) */
08465       default:
08466          p->inalarm = 0;
08467          break;
08468       }
08469       handle_clear_alarms(p);
08470       break;
08471    case DAHDI_EVENT_WINKFLASH:
08472       if (p->inalarm) break;
08473       if (p->radio) break;
08474       if (p->oprmode < 0) break;
08475       if (p->oprmode > 1)
08476       {
08477          struct dahdi_params par;
08478 
08479          memset(&par, 0, sizeof(par));
08480          if (ioctl(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par) != -1)
08481          {
08482             if (!par.rxisoffhook)
08483             {
08484                /* Make sure it stops ringing */
08485                dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
08486                dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RING);
08487                save_conference(p);
08488                tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
08489             }
08490          }
08491          break;
08492       }
08493       /* Remember last time we got a flash-hook */
08494       p->flashtime = ast_tvnow();
08495       switch (mysig) {
08496       case SIG_FXOLS:
08497       case SIG_FXOGS:
08498       case SIG_FXOKS:
08499          ast_debug(1, "Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n",
08500             idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
08501 
08502          /* Cancel any running CallerID spill */
08503          ast_free(p->cidspill);
08504          p->cidspill = NULL;
08505          restore_conference(p);
08506          p->callwaitcas = 0;
08507 
08508          if (idx != SUB_REAL) {
08509             ast_log(LOG_WARNING, "Got flash hook with index %d on channel %d?!?\n", idx, p->channel);
08510             goto winkflashdone;
08511          }
08512 
08513          if (p->subs[SUB_CALLWAIT].owner) {
08514             /* Swap to call-wait */
08515             swap_subs(p, SUB_REAL, SUB_CALLWAIT);
08516             tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
08517             p->owner = p->subs[SUB_REAL].owner;
08518             ast_debug(1, "Making %s the new owner\n", p->owner->name);
08519             if (p->owner->_state == AST_STATE_RINGING) {
08520                ast_setstate(p->owner, AST_STATE_UP);
08521                p->subs[SUB_REAL].needanswer = 1;
08522             }
08523             p->callwaitingrepeat = 0;
08524             p->cidcwexpire = 0;
08525             p->cid_suppress_expire = 0;
08526             /* Start music on hold if appropriate */
08527             if (!p->subs[SUB_CALLWAIT].inthreeway && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
08528                ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
08529                   S_OR(p->mohsuggest, NULL),
08530                   !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
08531             }
08532             p->subs[SUB_CALLWAIT].needhold = 1;
08533             if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
08534                ast_queue_control_data(p->subs[SUB_REAL].owner, AST_CONTROL_HOLD,
08535                   S_OR(p->mohsuggest, NULL),
08536                   !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
08537             }
08538             p->subs[SUB_REAL].needunhold = 1;
08539          } else if (!p->subs[SUB_THREEWAY].owner) {
08540             if (!p->threewaycalling) {
08541                /* Just send a flash if no 3-way calling */
08542                p->subs[SUB_REAL].needflash = 1;
08543                goto winkflashdone;
08544             } else if (!check_for_conference(p)) {
08545                char cid_num[256];
08546                char cid_name[256];
08547 
08548                cid_num[0] = 0;
08549                cid_name[0] = 0;
08550                if (p->dahditrcallerid && p->owner) {
08551                   if (p->owner->caller.id.number.valid
08552                      && p->owner->caller.id.number.str) {
08553                      ast_copy_string(cid_num, p->owner->caller.id.number.str,
08554                         sizeof(cid_num));
08555                   }
08556                   if (p->owner->caller.id.name.valid
08557                      && p->owner->caller.id.name.str) {
08558                      ast_copy_string(cid_name, p->owner->caller.id.name.str,
08559                         sizeof(cid_name));
08560                   }
08561                }
08562                /* XXX This section needs much more error checking!!! XXX */
08563                /* Start a 3-way call if feasible */
08564                if (!((ast->pbx) ||
08565                   (ast->_state == AST_STATE_UP) ||
08566                   (ast->_state == AST_STATE_RING))) {
08567                   ast_debug(1, "Flash when call not up or ringing\n");
08568                   goto winkflashdone;
08569                }
08570                if (alloc_sub(p, SUB_THREEWAY)) {
08571                   ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n");
08572                   goto winkflashdone;
08573                }
08574 
08575                /*
08576                 * Make new channel
08577                 *
08578                 * We cannot hold the p or ast locks while creating a new
08579                 * channel.
08580                 */
08581                ast_mutex_unlock(&p->lock);
08582                ast_channel_unlock(ast);
08583                chan = dahdi_new(p, AST_STATE_RESERVED, 0, SUB_THREEWAY, 0, NULL);
08584                ast_channel_lock(ast);
08585                ast_mutex_lock(&p->lock);
08586                if (p->dahditrcallerid) {
08587                   if (!p->origcid_num)
08588                      p->origcid_num = ast_strdup(p->cid_num);
08589                   if (!p->origcid_name)
08590                      p->origcid_name = ast_strdup(p->cid_name);
08591                   ast_copy_string(p->cid_num, cid_num, sizeof(p->cid_num));
08592                   ast_copy_string(p->cid_name, cid_name, sizeof(p->cid_name));
08593                }
08594                /* Swap things around between the three-way and real call */
08595                swap_subs(p, SUB_THREEWAY, SUB_REAL);
08596                /* Disable echo canceller for better dialing */
08597                dahdi_disable_ec(p);
08598                res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALRECALL);
08599                if (res)
08600                   ast_log(LOG_WARNING, "Unable to start dial recall tone on channel %d\n", p->channel);
08601                p->owner = chan;
08602                if (!chan) {
08603                   ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", p->channel);
08604                } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
08605                   ast_log(LOG_WARNING, "Unable to start simple switch on channel %d\n", p->channel);
08606                   res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
08607                   dahdi_enable_ec(p);
08608                   ast_hangup(chan);
08609                } else {
08610                   ast_verb(3, "Started three way call on channel %d\n", p->channel);
08611 
08612                   /* Start music on hold if appropriate */
08613                   if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
08614                      ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
08615                         S_OR(p->mohsuggest, NULL),
08616                         !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
08617                   }
08618                   p->subs[SUB_THREEWAY].needhold = 1;
08619                }
08620             }
08621          } else {
08622             /* Already have a 3 way call */
08623             if (p->subs[SUB_THREEWAY].inthreeway) {
08624                /* Call is already up, drop the last person */
08625                ast_debug(1, "Got flash with three way call up, dropping last call on %d\n", p->channel);
08626                /* If the primary call isn't answered yet, use it */
08627                if ((p->subs[SUB_REAL].owner->_state != AST_STATE_UP) && (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_UP)) {
08628                   /* Swap back -- we're dropping the real 3-way that isn't finished yet*/
08629                   swap_subs(p, SUB_THREEWAY, SUB_REAL);
08630                   p->owner = p->subs[SUB_REAL].owner;
08631                }
08632                /* Drop the last call and stop the conference */
08633                ast_verb(3, "Dropping three-way call on %s\n", p->subs[SUB_THREEWAY].owner->name);
08634                p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08635                p->subs[SUB_REAL].inthreeway = 0;
08636                p->subs[SUB_THREEWAY].inthreeway = 0;
08637             } else {
08638                /* Lets see what we're up to */
08639                if (((ast->pbx) || (ast->_state == AST_STATE_UP)) &&
08640                   (p->transfertobusy || (ast->_state != AST_STATE_BUSY))) {
08641                   int otherindex = SUB_THREEWAY;
08642 
08643                   ast_verb(3, "Building conference call with %s and %s\n",
08644                      p->subs[SUB_THREEWAY].owner->name,
08645                      p->subs[SUB_REAL].owner->name);
08646                   /* Put them in the threeway, and flip */
08647                   p->subs[SUB_THREEWAY].inthreeway = 1;
08648                   p->subs[SUB_REAL].inthreeway = 1;
08649                   if (ast->_state == AST_STATE_UP) {
08650                      swap_subs(p, SUB_THREEWAY, SUB_REAL);
08651                      otherindex = SUB_REAL;
08652                   }
08653                   if (p->subs[otherindex].owner && ast_bridged_channel(p->subs[otherindex].owner))
08654                      ast_queue_control(p->subs[otherindex].owner, AST_CONTROL_UNHOLD);
08655                   p->subs[otherindex].needunhold = 1;
08656                   p->owner = p->subs[SUB_REAL].owner;
08657                } else {
08658                   ast_verb(3, "Dumping incomplete call on on %s\n", p->subs[SUB_THREEWAY].owner->name);
08659                   swap_subs(p, SUB_THREEWAY, SUB_REAL);
08660                   p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08661                   p->owner = p->subs[SUB_REAL].owner;
08662                   if (p->subs[SUB_REAL].owner && ast_bridged_channel(p->subs[SUB_REAL].owner))
08663                      ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
08664                   p->subs[SUB_REAL].needunhold = 1;
08665                   dahdi_enable_ec(p);
08666                }
08667             }
08668          }
08669 winkflashdone:
08670          update_conf(p);
08671          break;
08672       case SIG_EM:
08673       case SIG_EM_E1:
08674       case SIG_FEATD:
08675       case SIG_SF:
08676       case SIG_SFWINK:
08677       case SIG_SF_FEATD:
08678       case SIG_FXSLS:
08679       case SIG_FXSGS:
08680          if (p->dialing)
08681             ast_debug(1, "Ignoring wink on channel %d\n", p->channel);
08682          else
08683             ast_debug(1, "Got wink in weird state %u on channel %d\n", ast->_state, p->channel);
08684          break;
08685       case SIG_FEATDMF_TA:
08686          switch (p->whichwink) {
08687          case 0:
08688             ast_debug(1, "ANI2 set to '%d' and ANI is '%s'\n", p->owner->caller.ani2,
08689                S_COR(p->owner->caller.ani.number.valid,
08690                   p->owner->caller.ani.number.str, ""));
08691             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%d%s#",
08692                p->owner->caller.ani2,
08693                S_COR(p->owner->caller.ani.number.valid,
08694                   p->owner->caller.ani.number.str, ""));
08695             break;
08696          case 1:
08697             ast_copy_string(p->dop.dialstr, p->finaldial, sizeof(p->dop.dialstr));
08698             break;
08699          case 2:
08700             ast_log(LOG_WARNING, "Received unexpected wink on channel of type SIG_FEATDMF_TA\n");
08701             return NULL;
08702          }
08703          p->whichwink++;
08704          /* Fall through */
08705       case SIG_FEATDMF:
08706       case SIG_E911:
08707       case SIG_FGC_CAMAMF:
08708       case SIG_FGC_CAMA:
08709       case SIG_FEATB:
08710       case SIG_SF_FEATDMF:
08711       case SIG_SF_FEATB:
08712       case SIG_EMWINK:
08713          /* FGD MF and EMWINK *Must* wait for wink */
08714          if (!ast_strlen_zero(p->dop.dialstr)) {
08715             res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
08716             if (res < 0) {
08717                ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
08718                p->dop.dialstr[0] = '\0';
08719                return NULL;
08720             } else
08721                ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
08722          }
08723          p->dop.dialstr[0] = '\0';
08724          break;
08725       default:
08726          ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
08727       }
08728       break;
08729    case DAHDI_EVENT_HOOKCOMPLETE:
08730       if (p->inalarm) break;
08731       if ((p->radio || (p->oprmode < 0))) break;
08732       if (p->waitingfordt.tv_sec) break;
08733       switch (mysig) {
08734       case SIG_FXSLS:  /* only interesting for FXS */
08735       case SIG_FXSGS:
08736       case SIG_FXSKS:
08737       case SIG_EM:
08738       case SIG_EM_E1:
08739       case SIG_EMWINK:
08740       case SIG_FEATD:
08741       case SIG_SF:
08742       case SIG_SFWINK:
08743       case SIG_SF_FEATD:
08744          if (!ast_strlen_zero(p->dop.dialstr)) {
08745             res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
08746             if (res < 0) {
08747                ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
08748                p->dop.dialstr[0] = '\0';
08749                return NULL;
08750             } else
08751                ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
08752          }
08753          p->dop.dialstr[0] = '\0';
08754          p->dop.op = DAHDI_DIAL_OP_REPLACE;
08755          break;
08756       case SIG_FEATDMF:
08757       case SIG_FEATDMF_TA:
08758       case SIG_E911:
08759       case SIG_FGC_CAMA:
08760       case SIG_FGC_CAMAMF:
08761       case SIG_FEATB:
08762       case SIG_SF_FEATDMF:
08763       case SIG_SF_FEATB:
08764          ast_debug(1, "Got hook complete in MF FGD, waiting for wink now on channel %d\n",p->channel);
08765          break;
08766       default:
08767          break;
08768       }
08769       break;
08770    case DAHDI_EVENT_POLARITY:
08771       /*
08772        * If we get a Polarity Switch event, check to see
08773        * if we should change the polarity state and
08774        * mark the channel as UP or if this is an indication
08775        * of remote end disconnect.
08776        */
08777       if (p->polarity == POLARITY_IDLE) {
08778          p->polarity = POLARITY_REV;
08779          if (p->answeronpolarityswitch &&
08780             ((ast->_state == AST_STATE_DIALING) ||
08781             (ast->_state == AST_STATE_RINGING))) {
08782             ast_debug(1, "Answering on polarity switch!\n");
08783             ast_setstate(p->owner, AST_STATE_UP);
08784             if (p->hanguponpolarityswitch) {
08785                p->polaritydelaytv = ast_tvnow();
08786             }
08787          } else
08788             ast_debug(1, "Ignore switch to REVERSED Polarity on channel %d, state %u\n", p->channel, ast->_state);
08789       }
08790       /* Removed else statement from here as it was preventing hangups from ever happening*/
08791       /* Added AST_STATE_RING in if statement below to deal with calling party hangups that take place when ringing */
08792       if (p->hanguponpolarityswitch &&
08793          (p->polarityonanswerdelay > 0) &&
08794          (p->polarity == POLARITY_REV) &&
08795          ((ast->_state == AST_STATE_UP) || (ast->_state == AST_STATE_RING)) ) {
08796          /* Added log_debug information below to provide a better indication of what is going on */
08797          ast_debug(1, "Polarity Reversal event occured - DEBUG 1: channel %d, state %u, pol= %d, aonp= %d, honp= %d, pdelay= %d, tv= %" PRIi64 "\n", p->channel, ast->_state, p->polarity, p->answeronpolarityswitch, p->hanguponpolarityswitch, p->polarityonanswerdelay, ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) );
08798 
08799          if (ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) > p->polarityonanswerdelay) {
08800             ast_debug(1, "Polarity Reversal detected and now Hanging up on channel %d\n", p->channel);
08801             ast_softhangup(p->owner, AST_SOFTHANGUP_EXPLICIT);
08802             p->polarity = POLARITY_IDLE;
08803          } else
08804             ast_debug(1, "Polarity Reversal detected but NOT hanging up (too close to answer event) on channel %d, state %u\n", p->channel, ast->_state);
08805 
08806       } else {
08807          p->polarity = POLARITY_IDLE;
08808          ast_debug(1, "Ignoring Polarity switch to IDLE on channel %d, state %u\n", p->channel, ast->_state);
08809       }
08810       /* Added more log_debug information below to provide a better indication of what is going on */
08811       ast_debug(1, "Polarity Reversal event occured - DEBUG 2: channel %d, state %u, pol= %d, aonp= %d, honp= %d, pdelay= %d, tv= %" PRIi64 "\n", p->channel, ast->_state, p->polarity, p->answeronpolarityswitch, p->hanguponpolarityswitch, p->polarityonanswerdelay, ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) );
08812       break;
08813    default:
08814       ast_debug(1, "Dunno what to do with event %d on channel %d\n", res, p->channel);
08815    }
08816    return &p->subs[idx].f;
08817 }
08818 
08819 static struct ast_frame *__dahdi_exception(struct ast_channel *ast)
08820 {
08821    int res;
08822    int idx;
08823    struct ast_frame *f;
08824    int usedindex = -1;
08825    struct dahdi_pvt *p = ast->tech_pvt;
08826 
08827    if ((idx = dahdi_get_index(ast, p, 0)) < 0) {
08828       idx = SUB_REAL;
08829    }
08830 
08831    p->subs[idx].f.frametype = AST_FRAME_NULL;
08832    p->subs[idx].f.datalen = 0;
08833    p->subs[idx].f.samples = 0;
08834    p->subs[idx].f.mallocd = 0;
08835    p->subs[idx].f.offset = 0;
08836    p->subs[idx].f.subclass.integer = 0;
08837    p->subs[idx].f.delivery = ast_tv(0,0);
08838    p->subs[idx].f.src = "dahdi_exception";
08839    p->subs[idx].f.data.ptr = NULL;
08840 
08841 
08842    if ((!p->owner) && (!(p->radio || (p->oprmode < 0)))) {
08843       /* If nobody owns us, absorb the event appropriately, otherwise
08844          we loop indefinitely.  This occurs when, during call waiting, the
08845          other end hangs up our channel so that it no longer exists, but we
08846          have neither FLASH'd nor ONHOOK'd to signify our desire to
08847          change to the other channel. */
08848       if (p->fake_event) {
08849          res = p->fake_event;
08850          p->fake_event = 0;
08851       } else
08852          res = dahdi_get_event(p->subs[SUB_REAL].dfd);
08853       /* Switch to real if there is one and this isn't something really silly... */
08854       if ((res != DAHDI_EVENT_RINGEROFF) && (res != DAHDI_EVENT_RINGERON) &&
08855          (res != DAHDI_EVENT_HOOKCOMPLETE)) {
08856          ast_debug(1, "Restoring owner of channel %d on event %d\n", p->channel, res);
08857          p->owner = p->subs[SUB_REAL].owner;
08858          if (p->owner && ast_bridged_channel(p->owner))
08859             ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
08860          p->subs[SUB_REAL].needunhold = 1;
08861       }
08862       switch (res) {
08863       case DAHDI_EVENT_ONHOOK:
08864          dahdi_disable_ec(p);
08865          if (p->owner) {
08866             ast_verb(3, "Channel %s still has call, ringing phone\n", p->owner->name);
08867             dahdi_ring_phone(p);
08868             p->callwaitingrepeat = 0;
08869             p->cidcwexpire = 0;
08870             p->cid_suppress_expire = 0;
08871          } else
08872             ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
08873          update_conf(p);
08874          break;
08875       case DAHDI_EVENT_RINGOFFHOOK:
08876          dahdi_enable_ec(p);
08877          dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
08878          if (p->owner && (p->owner->_state == AST_STATE_RINGING)) {
08879             p->subs[SUB_REAL].needanswer = 1;
08880             p->dialing = 0;
08881          }
08882          break;
08883       case DAHDI_EVENT_HOOKCOMPLETE:
08884       case DAHDI_EVENT_RINGERON:
08885       case DAHDI_EVENT_RINGEROFF:
08886          /* Do nothing */
08887          break;
08888       case DAHDI_EVENT_WINKFLASH:
08889          p->flashtime = ast_tvnow();
08890          if (p->owner) {
08891             ast_verb(3, "Channel %d flashed to other channel %s\n", p->channel, p->owner->name);
08892             if (p->owner->_state != AST_STATE_UP) {
08893                /* Answer if necessary */
08894                usedindex = dahdi_get_index(p->owner, p, 0);
08895                if (usedindex > -1) {
08896                   p->subs[usedindex].needanswer = 1;
08897                }
08898                ast_setstate(p->owner, AST_STATE_UP);
08899             }
08900             p->callwaitingrepeat = 0;
08901             p->cidcwexpire = 0;
08902             p->cid_suppress_expire = 0;
08903             if (ast_bridged_channel(p->owner))
08904                ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
08905             p->subs[SUB_REAL].needunhold = 1;
08906          } else
08907             ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
08908          update_conf(p);
08909          break;
08910       default:
08911          ast_log(LOG_WARNING, "Don't know how to absorb event %s\n", event2str(res));
08912       }
08913       f = &p->subs[idx].f;
08914       return f;
08915    }
08916    if (!(p->radio || (p->oprmode < 0)))
08917       ast_debug(1, "Exception on %d, channel %d\n", ast->fds[0],p->channel);
08918    /* If it's not us, return NULL immediately */
08919    if (ast != p->owner) {
08920       if (p->owner) {
08921          ast_log(LOG_WARNING, "We're %s, not %s\n", ast->name, p->owner->name);
08922       }
08923       f = &p->subs[idx].f;
08924       return f;
08925    }
08926 
08927    f = dahdi_handle_event(ast);
08928    if (!f) {
08929       const char *name = ast_strdupa(ast->name);
08930 
08931       /* Tell the CDR this DAHDI device hung up */
08932       ast_mutex_unlock(&p->lock);
08933       ast_channel_unlock(ast);
08934       ast_set_hangupsource(ast, name, 0);
08935       ast_channel_lock(ast);
08936       ast_mutex_lock(&p->lock);
08937    }
08938    return f;
08939 }
08940 
08941 static struct ast_frame *dahdi_exception(struct ast_channel *ast)
08942 {
08943    struct dahdi_pvt *p = ast->tech_pvt;
08944    struct ast_frame *f;
08945    ast_mutex_lock(&p->lock);
08946    if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
08947       struct analog_pvt *analog_p = p->sig_pvt;
08948       f = analog_exception(analog_p, ast);
08949    } else {
08950       f = __dahdi_exception(ast);
08951    }
08952    ast_mutex_unlock(&p->lock);
08953    return f;
08954 }
08955 
08956 static struct ast_frame *dahdi_read(struct ast_channel *ast)
08957 {
08958    struct dahdi_pvt *p;
08959    int res;
08960    int idx;
08961    void *readbuf;
08962    struct ast_frame *f;
08963 
08964    /*
08965     * For analog channels, we must do deadlock avoidance because
08966     * analog ports can have more than one Asterisk channel using
08967     * the same private structure.
08968     */
08969    p = ast->tech_pvt;
08970    while (ast_mutex_trylock(&p->lock)) {
08971       CHANNEL_DEADLOCK_AVOIDANCE(ast);
08972 
08973       /*
08974        * Check to see if the channel is still associated with the same
08975        * private structure.  While the Asterisk channel was unlocked
08976        * the following events may have occured:
08977        *
08978        * 1) A masquerade may have associated the channel with another
08979        * technology or private structure.
08980        *
08981        * 2) For PRI calls, call signaling could change the channel
08982        * association to another B channel (private structure).
08983        */
08984       if (ast->tech_pvt != p) {
08985          /* The channel is no longer associated.  Quit gracefully. */
08986          return &ast_null_frame;
08987       }
08988    }
08989 
08990    idx = dahdi_get_index(ast, p, 0);
08991 
08992    /* Hang up if we don't really exist */
08993    if (idx < 0)   {
08994       ast_log(LOG_WARNING, "We don't exist?\n");
08995       ast_mutex_unlock(&p->lock);
08996       return NULL;
08997    }
08998 
08999    if ((p->radio || (p->oprmode < 0)) && p->inalarm) {
09000       ast_mutex_unlock(&p->lock);
09001       return NULL;
09002    }
09003 
09004    p->subs[idx].f.frametype = AST_FRAME_NULL;
09005    p->subs[idx].f.datalen = 0;
09006    p->subs[idx].f.samples = 0;
09007    p->subs[idx].f.mallocd = 0;
09008    p->subs[idx].f.offset = 0;
09009    p->subs[idx].f.subclass.integer = 0;
09010    p->subs[idx].f.delivery = ast_tv(0,0);
09011    p->subs[idx].f.src = "dahdi_read";
09012    p->subs[idx].f.data.ptr = NULL;
09013 
09014    /* make sure it sends initial key state as first frame */
09015    if ((p->radio || (p->oprmode < 0)) && (!p->firstradio))
09016    {
09017       struct dahdi_params ps;
09018 
09019       memset(&ps, 0, sizeof(ps));
09020       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
09021          ast_mutex_unlock(&p->lock);
09022          return NULL;
09023       }
09024       p->firstradio = 1;
09025       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09026       if (ps.rxisoffhook)
09027       {
09028          p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_KEY;
09029       }
09030       else
09031       {
09032          p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_UNKEY;
09033       }
09034       ast_mutex_unlock(&p->lock);
09035       return &p->subs[idx].f;
09036    }
09037    if (p->ringt > 0) {
09038       if (!(--p->ringt)) {
09039          ast_mutex_unlock(&p->lock);
09040          return NULL;
09041       }
09042    }
09043 
09044 #ifdef HAVE_OPENR2
09045    if (p->mfcr2) {
09046       openr2_chan_process_event(p->r2chan);
09047       if (OR2_DIR_FORWARD == openr2_chan_get_direction(p->r2chan)) {
09048          struct ast_frame f = { AST_FRAME_CONTROL, { AST_CONTROL_PROGRESS }, };
09049          /* if the call is already accepted and we already delivered AST_CONTROL_RINGING
09050           * now enqueue a progress frame to bridge the media up */
09051          if (p->mfcr2_call_accepted &&
09052              !p->mfcr2_progress && 
09053              ast->_state == AST_STATE_RINGING) {
09054             ast_log(LOG_DEBUG, "Enqueuing progress frame after R2 accept in chan %d\n", p->channel);
09055             ast_queue_frame(p->owner, &f);
09056             p->mfcr2_progress = 1;
09057          }
09058       }
09059    }
09060 #endif
09061 
09062    if (p->subs[idx].needringing) {
09063       /* Send ringing frame if requested */
09064       p->subs[idx].needringing = 0;
09065       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09066       p->subs[idx].f.subclass.integer = AST_CONTROL_RINGING;
09067       ast_setstate(ast, AST_STATE_RINGING);
09068       ast_mutex_unlock(&p->lock);
09069       return &p->subs[idx].f;
09070    }
09071 
09072    if (p->subs[idx].needbusy) {
09073       /* Send busy frame if requested */
09074       p->subs[idx].needbusy = 0;
09075       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09076       p->subs[idx].f.subclass.integer = AST_CONTROL_BUSY;
09077       ast_mutex_unlock(&p->lock);
09078       return &p->subs[idx].f;
09079    }
09080 
09081    if (p->subs[idx].needcongestion) {
09082       /* Send congestion frame if requested */
09083       p->subs[idx].needcongestion = 0;
09084       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09085       p->subs[idx].f.subclass.integer = AST_CONTROL_CONGESTION;
09086       ast_mutex_unlock(&p->lock);
09087       return &p->subs[idx].f;
09088    }
09089 
09090    if (p->subs[idx].needanswer) {
09091       /* Send answer frame if requested */
09092       p->subs[idx].needanswer = 0;
09093       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09094       p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
09095       ast_mutex_unlock(&p->lock);
09096       return &p->subs[idx].f;
09097    }
09098 #ifdef HAVE_OPENR2
09099    if (p->mfcr2 && openr2_chan_get_read_enabled(p->r2chan)) {
09100       /* openr2 took care of reading and handling any event
09101         (needanswer, needbusy etc), if we continue we will read()
09102         twice, lets just return a null frame. This should only
09103         happen when openr2 is dialing out */
09104       ast_mutex_unlock(&p->lock);
09105       return &ast_null_frame;
09106    }
09107 #endif
09108 
09109    if (p->subs[idx].needflash) {
09110       /* Send answer frame if requested */
09111       p->subs[idx].needflash = 0;
09112       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09113       p->subs[idx].f.subclass.integer = AST_CONTROL_FLASH;
09114       ast_mutex_unlock(&p->lock);
09115       return &p->subs[idx].f;
09116    }
09117 
09118    if (p->subs[idx].needhold) {
09119       /* Send answer frame if requested */
09120       p->subs[idx].needhold = 0;
09121       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09122       p->subs[idx].f.subclass.integer = AST_CONTROL_HOLD;
09123       ast_mutex_unlock(&p->lock);
09124       ast_debug(1, "Sending hold on '%s'\n", ast->name);
09125       return &p->subs[idx].f;
09126    }
09127 
09128    if (p->subs[idx].needunhold) {
09129       /* Send answer frame if requested */
09130       p->subs[idx].needunhold = 0;
09131       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09132       p->subs[idx].f.subclass.integer = AST_CONTROL_UNHOLD;
09133       ast_mutex_unlock(&p->lock);
09134       ast_debug(1, "Sending unhold on '%s'\n", ast->name);
09135       return &p->subs[idx].f;
09136    }
09137 
09138    /*
09139     * If we have a fake_event, fake an exception to handle it only
09140     * if this channel owns the private.
09141     */
09142    if (p->fake_event && p->owner == ast) {
09143       if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
09144          struct analog_pvt *analog_p = p->sig_pvt;
09145 
09146          f = analog_exception(analog_p, ast);
09147       } else {
09148          f = __dahdi_exception(ast);
09149       }
09150       ast_mutex_unlock(&p->lock);
09151       return f;
09152    }
09153 
09154    if (ast->rawreadformat == AST_FORMAT_SLINEAR) {
09155       if (!p->subs[idx].linear) {
09156          p->subs[idx].linear = 1;
09157          res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09158          if (res)
09159             ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to linear mode.\n", p->channel, idx);
09160       }
09161    } else if ((ast->rawreadformat == AST_FORMAT_ULAW) ||
09162       (ast->rawreadformat == AST_FORMAT_ALAW)) {
09163       if (p->subs[idx].linear) {
09164          p->subs[idx].linear = 0;
09165          res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09166          if (res)
09167             ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to companded mode.\n", p->channel, idx);
09168       }
09169    } else {
09170       ast_log(LOG_WARNING, "Don't know how to read frames in format %s\n", ast_getformatname(ast->rawreadformat));
09171       ast_mutex_unlock(&p->lock);
09172       return NULL;
09173    }
09174    readbuf = ((unsigned char *)p->subs[idx].buffer) + AST_FRIENDLY_OFFSET;
09175    CHECK_BLOCKING(ast);
09176    res = read(p->subs[idx].dfd, readbuf, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
09177    ast_clear_flag(ast, AST_FLAG_BLOCKING);
09178    /* Check for hangup */
09179    if (res < 0) {
09180       f = NULL;
09181       if (res == -1) {
09182          if (errno == EAGAIN) {
09183             /* Return "NULL" frame if there is nobody there */
09184             ast_mutex_unlock(&p->lock);
09185             return &p->subs[idx].f;
09186          } else if (errno == ELAST) {
09187             if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
09188                struct analog_pvt *analog_p = p->sig_pvt;
09189                f = analog_exception(analog_p, ast);
09190             } else {
09191                f = __dahdi_exception(ast);
09192             }
09193          } else
09194             ast_log(LOG_WARNING, "dahdi_rec: %s\n", strerror(errno));
09195       }
09196       ast_mutex_unlock(&p->lock);
09197       return f;
09198    }
09199    if (res != (p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE)) {
09200       ast_debug(1, "Short read (%d/%d), must be an event...\n", res, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
09201       if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
09202          struct analog_pvt *analog_p = p->sig_pvt;
09203          f = analog_exception(analog_p, ast);
09204       } else {
09205          f = __dahdi_exception(ast);
09206       }
09207       ast_mutex_unlock(&p->lock);
09208       return f;
09209    }
09210    if (p->tdd) { /* if in TDD mode, see if we receive that */
09211       int c;
09212 
09213       c = tdd_feed(p->tdd,readbuf,READ_SIZE);
09214       if (c < 0) {
09215          ast_debug(1,"tdd_feed failed\n");
09216          ast_mutex_unlock(&p->lock);
09217          return NULL;
09218       }
09219       if (c) { /* if a char to return */
09220          p->subs[idx].f.subclass.integer = 0;
09221          p->subs[idx].f.frametype = AST_FRAME_TEXT;
09222          p->subs[idx].f.mallocd = 0;
09223          p->subs[idx].f.offset = AST_FRIENDLY_OFFSET;
09224          p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET;
09225          p->subs[idx].f.datalen = 1;
09226          *((char *) p->subs[idx].f.data.ptr) = c;
09227          ast_mutex_unlock(&p->lock);
09228          return &p->subs[idx].f;
09229       }
09230    }
09231    if (idx == SUB_REAL) {
09232       /* Ensure the CW timers decrement only on a single subchannel */
09233       if (p->cidcwexpire) {
09234          if (!--p->cidcwexpire) {
09235             /* Expired CID/CW */
09236             ast_verb(3, "CPE does not support Call Waiting Caller*ID.\n");
09237             restore_conference(p);
09238          }
09239       }
09240       if (p->cid_suppress_expire) {
09241          --p->cid_suppress_expire;
09242       }
09243       if (p->callwaitingrepeat) {
09244          if (!--p->callwaitingrepeat) {
09245             /* Expired, Repeat callwaiting tone */
09246             ++p->callwaitrings;
09247             dahdi_callwait(ast);
09248          }
09249       }
09250    }
09251    if (p->subs[idx].linear) {
09252       p->subs[idx].f.datalen = READ_SIZE * 2;
09253    } else
09254       p->subs[idx].f.datalen = READ_SIZE;
09255 
09256    /* Handle CallerID Transmission */
09257    if ((p->owner == ast) && p->cidspill) {
09258       send_callerid(p);
09259    }
09260 
09261    p->subs[idx].f.frametype = AST_FRAME_VOICE;
09262    p->subs[idx].f.subclass.codec = ast->rawreadformat;
09263    p->subs[idx].f.samples = READ_SIZE;
09264    p->subs[idx].f.mallocd = 0;
09265    p->subs[idx].f.offset = AST_FRIENDLY_OFFSET;
09266    p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET / sizeof(p->subs[idx].buffer[0]);
09267 #if 0
09268    ast_debug(1, "Read %d of voice on %s\n", p->subs[idx].f.datalen, ast->name);
09269 #endif
09270    if ((p->dialing && !p->waitingfordt.tv_sec) ||  p->radio || /* Transmitting something */
09271       (idx && (ast->_state != AST_STATE_UP)) || /* Three-way or callwait that isn't up */
09272       ((idx == SUB_CALLWAIT) && !p->subs[SUB_CALLWAIT].inthreeway) /* Inactive and non-confed call-wait */
09273       ) {
09274       /* Whoops, we're still dialing, or in a state where we shouldn't transmit....
09275          don't send anything */
09276       p->subs[idx].f.frametype = AST_FRAME_NULL;
09277       p->subs[idx].f.subclass.integer = 0;
09278       p->subs[idx].f.samples = 0;
09279       p->subs[idx].f.mallocd = 0;
09280       p->subs[idx].f.offset = 0;
09281       p->subs[idx].f.data.ptr = NULL;
09282       p->subs[idx].f.datalen= 0;
09283    }
09284    if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect || p->callprogress || p->waitingfordt.tv_sec) && !idx) {
09285       /* Perform busy detection etc on the dahdi line */
09286       int mute;
09287 
09288       f = ast_dsp_process(ast, p->dsp, &p->subs[idx].f);
09289 
09290       /* Check if DSP code thinks we should be muting this frame and mute the conference if so */
09291       mute = ast_dsp_was_muted(p->dsp);
09292       if (p->muting != mute) {
09293          p->muting = mute;
09294          dahdi_confmute(p, mute);
09295       }
09296 
09297       if (f) {
09298          if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass.integer == AST_CONTROL_BUSY)) {
09299             if ((ast->_state == AST_STATE_UP) && !p->outgoing) {
09300                /* Treat this as a "hangup" instead of a "busy" on the assumption that
09301                   a busy */
09302                ast_frfree(f);
09303                f = NULL;
09304             }
09305          } else if (f->frametype == AST_FRAME_DTMF_BEGIN
09306             || f->frametype == AST_FRAME_DTMF_END) {
09307 #ifdef HAVE_PRI
09308             if (dahdi_sig_pri_lib_handles(p->sig)
09309                && ((struct sig_pri_chan *) p->sig_pvt)->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING
09310                && p->pri
09311                && ((!p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING))
09312                   || (p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)))) {
09313                /* Don't accept in-band DTMF when in overlap dial mode */
09314                ast_debug(1, "Absorbing inband %s DTMF digit: 0x%02X '%c' on %s\n",
09315                   f->frametype == AST_FRAME_DTMF_BEGIN ? "begin" : "end",
09316                   (unsigned)f->subclass.integer, f->subclass.integer, ast->name);
09317 
09318                f->frametype = AST_FRAME_NULL;
09319                f->subclass.integer = 0;
09320             }
09321 #endif
09322             /* DSP clears us of being pulse */
09323             p->pulsedial = 0;
09324          } else if (p->waitingfordt.tv_sec) {
09325             if (ast_tvdiff_ms(ast_tvnow(), p->waitingfordt) >= p->waitfordialtone ) {
09326                p->waitingfordt.tv_sec = 0;
09327                ast_log(LOG_WARNING, "Never saw dialtone on channel %d\n", p->channel);
09328                ast_frfree(f);
09329                f = NULL;
09330             } else if (f->frametype == AST_FRAME_VOICE) {
09331                f->frametype = AST_FRAME_NULL;
09332                f->subclass.integer = 0;
09333                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) {
09334                   p->waitingfordt.tv_sec = 0;
09335                   p->dsp_features &= ~DSP_FEATURE_WAITDIALTONE;
09336                   ast_dsp_set_features(p->dsp, p->dsp_features);
09337                   ast_log(LOG_DEBUG, "Got 10 samples of dialtone!\n");
09338                   if (!ast_strlen_zero(p->dop.dialstr)) { /* Dial deferred digits */
09339                      res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
09340                      if (res < 0) {
09341                         ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d\n", p->channel);
09342                         p->dop.dialstr[0] = '\0';
09343                         ast_mutex_unlock(&p->lock);
09344                         ast_frfree(f);
09345                         return NULL;
09346                      } else {
09347                         ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", p->dop.dialstr);
09348                         p->dialing = 1;
09349                         p->dop.dialstr[0] = '\0';
09350                         p->dop.op = DAHDI_DIAL_OP_REPLACE;
09351                         ast_setstate(ast, AST_STATE_DIALING);
09352                      }
09353                   }
09354                }
09355             }
09356          }
09357       }
09358    } else
09359       f = &p->subs[idx].f;
09360 
09361    if (f) {
09362       switch (f->frametype) {
09363       case AST_FRAME_DTMF_BEGIN:
09364       case AST_FRAME_DTMF_END:
09365          if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
09366             analog_handle_dtmf(p->sig_pvt, ast, idx, &f);
09367          } else {
09368             dahdi_handle_dtmf(ast, idx, &f);
09369          }
09370          break;
09371       case AST_FRAME_VOICE:
09372          if (p->cidspill || p->cid_suppress_expire) {
09373             /* We are/were sending a caller id spill.  Suppress any echo. */
09374             p->subs[idx].f.frametype = AST_FRAME_NULL;
09375             p->subs[idx].f.subclass.integer = 0;
09376             p->subs[idx].f.samples = 0;
09377             p->subs[idx].f.mallocd = 0;
09378             p->subs[idx].f.offset = 0;
09379             p->subs[idx].f.data.ptr = NULL;
09380             p->subs[idx].f.datalen= 0;
09381          }
09382          break;
09383       default:
09384          break;
09385       }
09386    }
09387 
09388    ast_mutex_unlock(&p->lock);
09389    return f;
09390 }
09391 
09392 static int my_dahdi_write(struct dahdi_pvt *p, unsigned char *buf, int len, int idx, int linear)
09393 {
09394    int sent=0;
09395    int size;
09396    int res;
09397    int fd;
09398    fd = p->subs[idx].dfd;
09399    while (len) {
09400       size = len;
09401       if (size > (linear ? READ_SIZE * 2 : READ_SIZE))
09402          size = (linear ? READ_SIZE * 2 : READ_SIZE);
09403       res = write(fd, buf, size);
09404       if (res != size) {
09405          ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
09406          return sent;
09407       }
09408       len -= size;
09409       buf += size;
09410    }
09411    return sent;
09412 }
09413 
09414 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame)
09415 {
09416    struct dahdi_pvt *p = ast->tech_pvt;
09417    int res;
09418    int idx;
09419    idx = dahdi_get_index(ast, p, 0);
09420    if (idx < 0) {
09421       ast_log(LOG_WARNING, "%s doesn't really exist?\n", ast->name);
09422       return -1;
09423    }
09424 
09425    /* Write a frame of (presumably voice) data */
09426    if (frame->frametype != AST_FRAME_VOICE) {
09427       if (frame->frametype != AST_FRAME_IMAGE)
09428          ast_log(LOG_WARNING, "Don't know what to do with frame type '%u'\n", frame->frametype);
09429       return 0;
09430    }
09431    if ((frame->subclass.codec != AST_FORMAT_SLINEAR) &&
09432       (frame->subclass.codec != AST_FORMAT_ULAW) &&
09433       (frame->subclass.codec != AST_FORMAT_ALAW)) {
09434       ast_log(LOG_WARNING, "Cannot handle frames in %s format\n", ast_getformatname(frame->subclass.codec));
09435       return -1;
09436    }
09437    if (p->dialing) {
09438       ast_debug(1, "Dropping frame since I'm still dialing on %s...\n",ast->name);
09439       return 0;
09440    }
09441    if (!p->owner) {
09442       ast_debug(1, "Dropping frame since there is no active owner on %s...\n",ast->name);
09443       return 0;
09444    }
09445    if (p->cidspill) {
09446       ast_debug(1, "Dropping frame since I've still got a callerid spill on %s...\n",
09447          ast->name);
09448       return 0;
09449    }
09450    /* Return if it's not valid data */
09451    if (!frame->data.ptr || !frame->datalen)
09452       return 0;
09453 
09454    if (frame->subclass.codec == AST_FORMAT_SLINEAR) {
09455       if (!p->subs[idx].linear) {
09456          p->subs[idx].linear = 1;
09457          res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09458          if (res)
09459             ast_log(LOG_WARNING, "Unable to set linear mode on channel %d\n", p->channel);
09460       }
09461       res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 1);
09462    } else {
09463       /* x-law already */
09464       if (p->subs[idx].linear) {
09465          p->subs[idx].linear = 0;
09466          res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09467          if (res)
09468             ast_log(LOG_WARNING, "Unable to set companded mode on channel %d\n", p->channel);
09469       }
09470       res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 0);
09471    }
09472    if (res < 0) {
09473       ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
09474       return -1;
09475    }
09476    return 0;
09477 }
09478 
09479 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen)
09480 {
09481    struct dahdi_pvt *p = chan->tech_pvt;
09482    int res=-1;
09483    int idx;
09484    int func = DAHDI_FLASH;
09485 
09486    ast_mutex_lock(&p->lock);
09487    ast_debug(1, "Requested indication %d on channel %s\n", condition, chan->name);
09488    switch (p->sig) {
09489 #if defined(HAVE_PRI)
09490    case SIG_PRI_LIB_HANDLE_CASES:
09491       res = sig_pri_indicate(p->sig_pvt, chan, condition, data, datalen);
09492       ast_mutex_unlock(&p->lock);
09493       return res;
09494 #endif   /* defined(HAVE_PRI) */
09495 #if defined(HAVE_SS7)
09496    case SIG_SS7:
09497       res = sig_ss7_indicate(p->sig_pvt, chan, condition, data, datalen);
09498       ast_mutex_unlock(&p->lock);
09499       return res;
09500 #endif   /* defined(HAVE_SS7) */
09501    default:
09502       break;
09503    }
09504 #ifdef HAVE_OPENR2
09505    if (p->mfcr2 && !p->mfcr2_call_accepted) {
09506       ast_mutex_unlock(&p->lock);
09507       /* if this is an R2 call and the call is not yet accepted, we don't want the
09508          tone indications to mess up with the MF tones */
09509       return 0;
09510    }
09511 #endif
09512    idx = dahdi_get_index(chan, p, 0);
09513    if (idx == SUB_REAL) {
09514       switch (condition) {
09515       case AST_CONTROL_BUSY:
09516          res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_BUSY);
09517          break;
09518       case AST_CONTROL_RINGING:
09519          res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_RINGTONE);
09520 
09521          if (chan->_state != AST_STATE_UP) {
09522             if ((chan->_state != AST_STATE_RING) ||
09523                ((p->sig != SIG_FXSKS) &&
09524              (p->sig != SIG_FXSLS) &&
09525              (p->sig != SIG_FXSGS)))
09526             ast_setstate(chan, AST_STATE_RINGING);
09527          }
09528          break;
09529       case AST_CONTROL_INCOMPLETE:
09530          ast_debug(1, "Received AST_CONTROL_INCOMPLETE on %s\n", chan->name);
09531          /* act as a progress or proceeding, allowing the caller to enter additional numbers */
09532          res = 0;
09533          break;
09534       case AST_CONTROL_PROCEEDING:
09535          ast_debug(1, "Received AST_CONTROL_PROCEEDING on %s\n", chan->name);
09536          /* don't continue in ast_indicate */
09537          res = 0;
09538          break;
09539       case AST_CONTROL_PROGRESS:
09540          ast_debug(1, "Received AST_CONTROL_PROGRESS on %s\n", chan->name);
09541          /* don't continue in ast_indicate */
09542          res = 0;
09543          break;
09544       case AST_CONTROL_CONGESTION:
09545          /* There are many cause codes that generate an AST_CONTROL_CONGESTION. */
09546          switch (chan->hangupcause) {
09547          case AST_CAUSE_USER_BUSY:
09548          case AST_CAUSE_NORMAL_CLEARING:
09549          case 0:/* Cause has not been set. */
09550             /* Supply a more appropriate cause. */
09551             chan->hangupcause = AST_CAUSE_CONGESTION;
09552             break;
09553          default:
09554             break;
09555          }
09556          break;
09557       case AST_CONTROL_HOLD:
09558          ast_moh_start(chan, data, p->mohinterpret);
09559          break;
09560       case AST_CONTROL_UNHOLD:
09561          ast_moh_stop(chan);
09562          break;
09563       case AST_CONTROL_RADIO_KEY:
09564          if (p->radio)
09565             res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
09566          res = 0;
09567          break;
09568       case AST_CONTROL_RADIO_UNKEY:
09569          if (p->radio)
09570             res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_RINGOFF);
09571          res = 0;
09572          break;
09573       case AST_CONTROL_FLASH:
09574          /* flash hookswitch */
09575          if (ISTRUNK(p) && (p->sig != SIG_PRI)) {
09576             /* Clear out the dial buffer */
09577             p->dop.dialstr[0] = '\0';
09578             if ((ioctl(p->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
09579                ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
09580                   chan->name, strerror(errno));
09581             } else
09582                res = 0;
09583          } else
09584             res = 0;
09585          break;
09586       case AST_CONTROL_SRCUPDATE:
09587          res = 0;
09588          break;
09589       case -1:
09590          res = tone_zone_play_tone(p->subs[idx].dfd, -1);
09591          break;
09592       }
09593    } else {
09594       res = 0;
09595    }
09596    ast_mutex_unlock(&p->lock);
09597    return res;
09598 }
09599 
09600 #if defined(HAVE_PRI)
09601 static struct ast_str *create_channel_name(struct dahdi_pvt *i, int is_outgoing, char *address)
09602 #else
09603 static struct ast_str *create_channel_name(struct dahdi_pvt *i)
09604 #endif   /* defined(HAVE_PRI) */
09605 {
09606    struct ast_str *chan_name;
09607    int x, y;
09608 
09609    /* Create the new channel name tail. */
09610    if (!(chan_name = ast_str_create(32))) {
09611       return NULL;
09612    }
09613    if (i->channel == CHAN_PSEUDO) {
09614       ast_str_set(&chan_name, 0, "pseudo-%ld", ast_random());
09615 #if defined(HAVE_PRI)
09616    } else if (i->pri) {
09617       ast_mutex_lock(&i->pri->lock);
09618       y = ++i->pri->new_chan_seq;
09619       if (is_outgoing) {
09620          ast_str_set(&chan_name, 0, "i%d/%s-%x", i->pri->span, address, (unsigned)y);
09621          address[0] = '\0';
09622       } else if (ast_strlen_zero(i->cid_subaddr)) {
09623          /* Put in caller-id number only since there is no subaddress. */
09624          ast_str_set(&chan_name, 0, "i%d/%s-%x", i->pri->span, i->cid_num, (unsigned)y);
09625       } else {
09626          /* Put in caller-id number and subaddress. */
09627          ast_str_set(&chan_name, 0, "i%d/%s:%s-%x", i->pri->span, i->cid_num,
09628             i->cid_subaddr, (unsigned)y);
09629       }
09630       ast_mutex_unlock(&i->pri->lock);
09631 #endif   /* defined(HAVE_PRI) */
09632    } else {
09633       y = 1;
09634       do {
09635          ast_str_set(&chan_name, 0, "%d-%d", i->channel, y);
09636          for (x = 0; x < 3; ++x) {
09637             if (i->subs[x].owner && !strcasecmp(ast_str_buffer(chan_name),
09638                i->subs[x].owner->name + 6)) {
09639                break;
09640             }
09641          }
09642          ++y;
09643       } while (x < 3);
09644    }
09645    return chan_name;
09646 }
09647 
09648 static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpbx, int idx, int law, const char *linkedid)
09649 {
09650    struct ast_channel *tmp;
09651    format_t deflaw;
09652    int x;
09653    int features;
09654    struct ast_str *chan_name;
09655    struct ast_variable *v;
09656    char *dashptr;
09657    char device_name[AST_CHANNEL_NAME];
09658 
09659    if (i->subs[idx].owner) {
09660       ast_log(LOG_WARNING, "Channel %d already has a %s call\n", i->channel,subnames[idx]);
09661       return NULL;
09662    }
09663 
09664 #if defined(HAVE_PRI)
09665    /*
09666     * The dnid has been stuffed with the called-number[:subaddress]
09667     * by dahdi_request() for outgoing calls.
09668     */
09669    chan_name = create_channel_name(i, i->outgoing, i->dnid);
09670 #else
09671    chan_name = create_channel_name(i);
09672 #endif   /* defined(HAVE_PRI) */
09673    if (!chan_name) {
09674       return NULL;
09675    }
09676 
09677    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));
09678    ast_free(chan_name);
09679    if (!tmp)
09680       return NULL;
09681    tmp->tech = &dahdi_tech;
09682 #if defined(HAVE_PRI)
09683    if (i->pri) {
09684       ast_cc_copy_config_params(i->cc_params, i->pri->cc_params);
09685    }
09686 #endif   /* defined(HAVE_PRI) */
09687    ast_channel_cc_params_init(tmp, i->cc_params);
09688    if (law) {
09689       i->law = law;
09690       if (law == DAHDI_LAW_ALAW) {
09691          deflaw = AST_FORMAT_ALAW;
09692       } else {
09693          deflaw = AST_FORMAT_ULAW;
09694       }
09695    } else {
09696       switch (i->sig) {
09697       case SIG_PRI_LIB_HANDLE_CASES:
09698          /* Make sure companding law is known. */
09699          i->law = (i->law_default == DAHDI_LAW_ALAW)
09700             ? DAHDI_LAW_ALAW : DAHDI_LAW_MULAW;
09701          break;
09702       default:
09703          i->law = i->law_default;
09704          break;
09705       }
09706       if (i->law_default == DAHDI_LAW_ALAW) {
09707          deflaw = AST_FORMAT_ALAW;
09708       } else {
09709          deflaw = AST_FORMAT_ULAW;
09710       }
09711    }
09712    ast_channel_set_fd(tmp, 0, i->subs[idx].dfd);
09713    tmp->nativeformats = deflaw;
09714    /* Start out assuming ulaw since it's smaller :) */
09715    tmp->rawreadformat = deflaw;
09716    tmp->readformat = deflaw;
09717    tmp->rawwriteformat = deflaw;
09718    tmp->writeformat = deflaw;
09719    i->subs[idx].linear = 0;
09720    dahdi_setlinear(i->subs[idx].dfd, i->subs[idx].linear);
09721    features = 0;
09722    if (idx == SUB_REAL) {
09723       if (i->busydetect && CANBUSYDETECT(i))
09724          features |= DSP_FEATURE_BUSY_DETECT;
09725       if ((i->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(i))
09726          features |= DSP_FEATURE_CALL_PROGRESS;
09727       if ((i->waitfordialtone) && CANPROGRESSDETECT(i))
09728          features |= DSP_FEATURE_WAITDIALTONE;
09729       if ((!i->outgoing && (i->callprogress & CALLPROGRESS_FAX_INCOMING)) ||
09730          (i->outgoing && (i->callprogress & CALLPROGRESS_FAX_OUTGOING))) {
09731          features |= DSP_FEATURE_FAX_DETECT;
09732       }
09733       x = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
09734       if (ioctl(i->subs[idx].dfd, DAHDI_TONEDETECT, &x)) {
09735          i->hardwaredtmf = 0;
09736          features |= DSP_FEATURE_DIGIT_DETECT;
09737       } else if (NEED_MFDETECT(i)) {
09738          i->hardwaredtmf = 1;
09739          features |= DSP_FEATURE_DIGIT_DETECT;
09740       }
09741    }
09742    if (features) {
09743       if (i->dsp) {
09744          ast_debug(1, "Already have a dsp on %s?\n", tmp->name);
09745       } else {
09746          if (i->channel != CHAN_PSEUDO)
09747             i->dsp = ast_dsp_new();
09748          else
09749             i->dsp = NULL;
09750          if (i->dsp) {
09751             i->dsp_features = features;
09752 #if defined(HAVE_PRI) || defined(HAVE_SS7)
09753             /* We cannot do progress detection until receive PROGRESS message */
09754             if (i->outgoing && (dahdi_sig_pri_lib_handles(i->sig) || (i->sig == SIG_SS7))) {
09755                /* Remember requested DSP features, don't treat
09756                   talking as ANSWER */
09757                i->dsp_features = features & ~DSP_PROGRESS_TALK;
09758                features = 0;
09759             }
09760 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
09761             ast_dsp_set_features(i->dsp, features);
09762             ast_dsp_set_digitmode(i->dsp, DSP_DIGITMODE_DTMF | i->dtmfrelax);
09763             if (!ast_strlen_zero(progzone))
09764                ast_dsp_set_call_progress_zone(i->dsp, progzone);
09765             if (i->busydetect && CANBUSYDETECT(i)) {
09766                if(i->silencethreshold > 0)
09767                   ast_dsp_set_threshold(i->dsp, i->silencethreshold);
09768                ast_dsp_set_busy_count(i->dsp, i->busycount);
09769                if(i->busytonelength > 0)
09770                   ast_dsp_set_busy_pattern(i->dsp, i->busytonelength, i->busyquietlength, i->busyfuzziness);
09771                if((i->busytonelength == i->busyquietlength) && i->busycompare)
09772                   ast_dsp_set_busy_compare(i->dsp, i->busycompare);
09773             }
09774          }
09775       }
09776    }
09777 
09778    if (state == AST_STATE_RING)
09779       tmp->rings = 1;
09780    tmp->tech_pvt = i;
09781    if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) {
09782       /* Only FXO signalled stuff can be picked up */
09783       tmp->callgroup = i->callgroup;
09784       tmp->pickupgroup = i->pickupgroup;
09785    }
09786    if (!ast_strlen_zero(i->parkinglot))
09787       ast_string_field_set(tmp, parkinglot, i->parkinglot);
09788    if (!ast_strlen_zero(i->language))
09789       ast_string_field_set(tmp, language, i->language);
09790    if (!i->owner)
09791       i->owner = tmp;
09792    if (!ast_strlen_zero(i->accountcode))
09793       ast_string_field_set(tmp, accountcode, i->accountcode);
09794    if (i->amaflags)
09795       tmp->amaflags = i->amaflags;
09796    i->subs[idx].owner = tmp;
09797    ast_copy_string(tmp->context, i->context, sizeof(tmp->context));
09798    if (!analog_lib_handles(i->sig, i->radio, i->oprmode)) {
09799       ast_string_field_set(tmp, call_forward, i->call_forward);
09800    }
09801    /* If we've been told "no ADSI" then enforce it */
09802    if (!i->adsi)
09803       tmp->adsicpe = AST_ADSI_UNAVAILABLE;
09804    if (!ast_strlen_zero(i->exten))
09805       ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten));
09806    if (!ast_strlen_zero(i->rdnis)) {
09807       tmp->redirecting.from.number.valid = 1;
09808       tmp->redirecting.from.number.str = ast_strdup(i->rdnis);
09809    }
09810    if (!ast_strlen_zero(i->dnid)) {
09811       tmp->dialed.number.str = ast_strdup(i->dnid);
09812    }
09813 
09814    /* Don't use ast_set_callerid() here because it will
09815     * generate a needless NewCallerID event */
09816 #if defined(HAVE_PRI) || defined(HAVE_SS7)
09817    if (!ast_strlen_zero(i->cid_ani)) {
09818       tmp->caller.ani.number.valid = 1;
09819       tmp->caller.ani.number.str = ast_strdup(i->cid_ani);
09820    } else if (!ast_strlen_zero(i->cid_num)) {
09821       tmp->caller.ani.number.valid = 1;
09822       tmp->caller.ani.number.str = ast_strdup(i->cid_num);
09823    }
09824 #else
09825    if (!ast_strlen_zero(i->cid_num)) {
09826       tmp->caller.ani.number.valid = 1;
09827       tmp->caller.ani.number.str = ast_strdup(i->cid_num);
09828    }
09829 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
09830    tmp->caller.id.name.presentation = i->callingpres;
09831    tmp->caller.id.number.presentation = i->callingpres;
09832    tmp->caller.id.number.plan = i->cid_ton;
09833    tmp->caller.ani2 = i->cid_ani2;
09834    tmp->caller.id.tag = ast_strdup(i->cid_tag);
09835    /* clear the fake event in case we posted one before we had ast_channel */
09836    i->fake_event = 0;
09837    /* Assure there is no confmute on this channel */
09838    dahdi_confmute(i, 0);
09839    i->muting = 0;
09840    /* Configure the new channel jb */
09841    ast_jb_configure(tmp, &global_jbconf);
09842 
09843    /* Set initial device state */
09844    ast_copy_string(device_name, tmp->name, sizeof(device_name));
09845    dashptr = strrchr(device_name, '-');
09846    if (dashptr) {
09847       *dashptr = '\0';
09848    }
09849    tmp->flags |= AST_FLAG_DISABLE_DEVSTATE_CACHE;
09850    ast_devstate_changed_literal(AST_DEVICE_UNKNOWN, AST_DEVSTATE_NOT_CACHABLE, device_name);
09851 
09852    for (v = i->vars ; v ; v = v->next)
09853       pbx_builtin_setvar_helper(tmp, v->name, v->value);
09854 
09855    ast_module_ref(ast_module_info->self);
09856 
09857    dahdi_ami_channel_event(i, tmp);
09858    if (startpbx) {
09859 #ifdef HAVE_OPENR2
09860       if (i->mfcr2call) {
09861          pbx_builtin_setvar_helper(tmp, "MFCR2_CATEGORY", openr2_proto_get_category_string(i->mfcr2_recvd_category));
09862       }
09863 #endif
09864       if (ast_pbx_start(tmp)) {
09865          ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
09866          ast_hangup(tmp);
09867          return NULL;
09868       }
09869    }
09870    return tmp;
09871 }
09872 
09873 
09874 static int my_getsigstr(struct ast_channel *chan, char *str, const char *term, int ms)
09875 {
09876    char c;
09877 
09878    *str = 0; /* start with empty output buffer */
09879    for (;;)
09880    {
09881       /* Wait for the first digit (up to specified ms). */
09882       c = ast_waitfordigit(chan, ms);
09883       /* if timeout, hangup or error, return as such */
09884       if (c < 1)
09885          return c;
09886       *str++ = c;
09887       *str = 0;
09888       if (strchr(term, c))
09889          return 1;
09890    }
09891 }
09892 
09893 static int dahdi_wink(struct dahdi_pvt *p, int idx)
09894 {
09895    int j;
09896    dahdi_set_hook(p->subs[idx].dfd, DAHDI_WINK);
09897    for (;;)
09898    {
09899       /* set bits of interest */
09900       j = DAHDI_IOMUX_SIGEVENT;
09901       /* wait for some happening */
09902       if (ioctl(p->subs[idx].dfd,DAHDI_IOMUX,&j) == -1) return(-1);
09903       /* exit loop if we have it */
09904       if (j & DAHDI_IOMUX_SIGEVENT) break;
09905    }
09906    /* get the event info */
09907    if (ioctl(p->subs[idx].dfd,DAHDI_GETEVENT,&j) == -1) return(-1);
09908    return 0;
09909 }
09910 
09911 /*! \brief enable or disable the chan_dahdi Do-Not-Disturb mode for a DAHDI channel
09912  * \param dahdichan "Physical" DAHDI channel (e.g: DAHDI/5)
09913  * \param flag on 1 to enable, 0 to disable, -1 return dnd value
09914  *
09915  * chan_dahdi has a DND (Do Not Disturb) mode for each dahdichan (physical
09916  * DAHDI channel). Use this to enable or disable it.
09917  *
09918  * \bug the use of the word "channel" for those dahdichans is really confusing.
09919  */
09920 static int dahdi_dnd(struct dahdi_pvt *dahdichan, int flag)
09921 {
09922    if (analog_lib_handles(dahdichan->sig, dahdichan->radio, dahdichan->oprmode)) {
09923       return analog_dnd(dahdichan->sig_pvt, flag);
09924    }
09925 
09926    if (flag == -1) {
09927       return dahdichan->dnd;
09928    }
09929 
09930    /* Do not disturb */
09931    dahdichan->dnd = flag;
09932    ast_verb(3, "%s DND on channel %d\n",
09933          flag? "Enabled" : "Disabled",
09934          dahdichan->channel);
09935    manager_event(EVENT_FLAG_SYSTEM, "DNDState",
09936          "Channel: DAHDI/%d\r\n"
09937          "Status: %s\r\n", dahdichan->channel,
09938          flag? "enabled" : "disabled");
09939 
09940    return 0;
09941 }
09942 
09943 static int canmatch_featurecode(const char *exten)
09944 {
09945    int extlen = strlen(exten);
09946    const char *pickup_ext;
09947    if (!extlen) {
09948       return 1;
09949    }
09950    pickup_ext = ast_pickup_ext();
09951    if (extlen < strlen(pickup_ext) && !strncmp(pickup_ext, exten, extlen)) {
09952       return 1;
09953    }
09954    /* hardcoded features are *60, *67, *69, *70, *72, *73, *78, *79, *82, *0 */
09955    if (exten[0] == '*' && extlen < 3) {
09956       if (extlen == 1) {
09957          return 1;
09958       }
09959       /* "*0" should be processed before it gets here */
09960       switch (exten[1]) {
09961       case '6':
09962       case '7':
09963       case '8':
09964          return 1;
09965       }
09966    }
09967    return 0;
09968 }
09969 
09970 static void *analog_ss_thread(void *data)
09971 {
09972    struct ast_channel *chan = data;
09973    struct dahdi_pvt *p = chan->tech_pvt;
09974    char exten[AST_MAX_EXTENSION] = "";
09975    char exten2[AST_MAX_EXTENSION] = "";
09976    unsigned char buf[256];
09977    char dtmfcid[300];
09978    char dtmfbuf[300];
09979    struct callerid_state *cs = NULL;
09980    char *name = NULL, *number = NULL;
09981    int distMatches;
09982    int curRingData[3];
09983    int receivedRingT;
09984    int counter1;
09985    int counter;
09986    int samples = 0;
09987    struct ast_smdi_md_message *smdi_msg = NULL;
09988    int flags = 0;
09989    int i;
09990    int timeout;
09991    int getforward = 0;
09992    char *s1, *s2;
09993    int len = 0;
09994    int res;
09995    int idx;
09996 
09997    ast_mutex_lock(&ss_thread_lock);
09998    ss_thread_count++;
09999    ast_mutex_unlock(&ss_thread_lock);
10000    /* in the bizarre case where the channel has become a zombie before we
10001       even get started here, abort safely
10002    */
10003    if (!p) {
10004       ast_log(LOG_WARNING, "Channel became a zombie before simple switch could be started (%s)\n", chan->name);
10005       ast_hangup(chan);
10006       goto quit;
10007    }
10008    ast_verb(3, "Starting simple switch on '%s'\n", chan->name);
10009    idx = dahdi_get_index(chan, p, 1);
10010    if (idx < 0) {
10011       ast_log(LOG_WARNING, "Huh?\n");
10012       ast_hangup(chan);
10013       goto quit;
10014    }
10015    if (p->dsp)
10016       ast_dsp_digitreset(p->dsp);
10017    switch (p->sig) {
10018    case SIG_FEATD:
10019    case SIG_FEATDMF:
10020    case SIG_FEATDMF_TA:
10021    case SIG_E911:
10022    case SIG_FGC_CAMAMF:
10023    case SIG_FEATB:
10024    case SIG_EMWINK:
10025    case SIG_SF_FEATD:
10026    case SIG_SF_FEATDMF:
10027    case SIG_SF_FEATB:
10028    case SIG_SFWINK:
10029       if (dahdi_wink(p, idx))
10030          goto quit;
10031       /* Fall through */
10032    case SIG_EM:
10033    case SIG_EM_E1:
10034    case SIG_SF:
10035    case SIG_FGC_CAMA:
10036       res = tone_zone_play_tone(p->subs[idx].dfd, -1);
10037       if (p->dsp)
10038          ast_dsp_digitreset(p->dsp);
10039       /* set digit mode appropriately */
10040       if (p->dsp) {
10041          if (NEED_MFDETECT(p))
10042             ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
10043          else
10044             ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
10045       }
10046       memset(dtmfbuf, 0, sizeof(dtmfbuf));
10047       /* Wait for the first digit only if immediate=no */
10048       if (!p->immediate)
10049          /* Wait for the first digit (up to 5 seconds). */
10050          res = ast_waitfordigit(chan, 5000);
10051       else
10052          res = 0;
10053       if (res > 0) {
10054          /* save first char */
10055          dtmfbuf[0] = res;
10056          switch (p->sig) {
10057          case SIG_FEATD:
10058          case SIG_SF_FEATD:
10059             res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
10060             if (res > 0)
10061                res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
10062             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
10063             break;
10064          case SIG_FEATDMF_TA:
10065             res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
10066             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
10067             if (dahdi_wink(p, idx)) goto quit;
10068             dtmfbuf[0] = 0;
10069             /* Wait for the first digit (up to 5 seconds). */
10070             res = ast_waitfordigit(chan, 5000);
10071             if (res <= 0) break;
10072             dtmfbuf[0] = res;
10073             /* fall through intentionally */
10074          case SIG_FEATDMF:
10075          case SIG_E911:
10076          case SIG_FGC_CAMAMF:
10077          case SIG_SF_FEATDMF:
10078             res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
10079             /* if international caca, do it again to get real ANO */
10080             if ((p->sig == SIG_FEATDMF) && (dtmfbuf[1] != '0') && (strlen(dtmfbuf) != 14))
10081             {
10082                if (dahdi_wink(p, idx)) goto quit;
10083                dtmfbuf[0] = 0;
10084                /* Wait for the first digit (up to 5 seconds). */
10085                res = ast_waitfordigit(chan, 5000);
10086                if (res <= 0) break;
10087                dtmfbuf[0] = res;
10088                res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
10089             }
10090             if (res > 0) {
10091                /* if E911, take off hook */
10092                if (p->sig == SIG_E911)
10093                   dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
10094                res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "#", 3000);
10095             }
10096             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
10097             break;
10098          case SIG_FEATB:
10099          case SIG_SF_FEATB:
10100             res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
10101             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
10102             break;
10103          case SIG_EMWINK:
10104             /* if we received a '*', we are actually receiving Feature Group D
10105                dial syntax, so use that mode; otherwise, fall through to normal
10106                mode
10107             */
10108             if (res == '*') {
10109                res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
10110                if (res > 0)
10111                   res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
10112                if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
10113                break;
10114             }
10115          default:
10116             /* If we got the first digit, get the rest */
10117             len = 1;
10118             dtmfbuf[len] = '\0';
10119             while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
10120                if (ast_exists_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
10121                   timeout = matchdigittimeout;
10122                } else {
10123                   timeout = gendigittimeout;
10124                }
10125                res = ast_waitfordigit(chan, timeout);
10126                if (res < 0) {
10127                   ast_debug(1, "waitfordigit returned < 0...\n");
10128                   ast_hangup(chan);
10129                   goto quit;
10130                } else if (res) {
10131                   dtmfbuf[len++] = res;
10132                   dtmfbuf[len] = '\0';
10133                } else {
10134                   break;
10135                }
10136             }
10137             break;
10138          }
10139       }
10140       if (res == -1) {
10141          ast_log(LOG_WARNING, "getdtmf on channel %d: %s\n", p->channel, strerror(errno));
10142          ast_hangup(chan);
10143          goto quit;
10144       } else if (res < 0) {
10145          ast_debug(1, "Got hung up before digits finished\n");
10146          ast_hangup(chan);
10147          goto quit;
10148       }
10149 
10150       if (p->sig == SIG_FGC_CAMA) {
10151          char anibuf[100];
10152 
10153          if (ast_safe_sleep(chan,1000) == -1) {
10154             ast_hangup(chan);
10155             goto quit;
10156          }
10157          dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
10158          ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
10159          res = my_getsigstr(chan, anibuf, "#", 10000);
10160          if ((res > 0) && (strlen(anibuf) > 2)) {
10161             if (anibuf[strlen(anibuf) - 1] == '#')
10162                anibuf[strlen(anibuf) - 1] = 0;
10163             ast_set_callerid(chan, anibuf + 2, NULL, anibuf + 2);
10164          }
10165          ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
10166       }
10167 
10168       ast_copy_string(exten, dtmfbuf, sizeof(exten));
10169       if (ast_strlen_zero(exten))
10170          ast_copy_string(exten, "s", sizeof(exten));
10171       if (p->sig == SIG_FEATD || p->sig == SIG_EMWINK) {
10172          /* Look for Feature Group D on all E&M Wink and Feature Group D trunks */
10173          if (exten[0] == '*') {
10174             char *stringp=NULL;
10175             ast_copy_string(exten2, exten, sizeof(exten2));
10176             /* Parse out extension and callerid */
10177             stringp=exten2 +1;
10178             s1 = strsep(&stringp, "*");
10179             s2 = strsep(&stringp, "*");
10180             if (s2) {
10181                if (!ast_strlen_zero(p->cid_num))
10182                   ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
10183                else
10184                   ast_set_callerid(chan, s1, NULL, s1);
10185                ast_copy_string(exten, s2, sizeof(exten));
10186             } else
10187                ast_copy_string(exten, s1, sizeof(exten));
10188          } else if (p->sig == SIG_FEATD)
10189             ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d.  Assuming E&M Wink instead\n", p->channel);
10190       }
10191       if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
10192          if (exten[0] == '*') {
10193             char *stringp=NULL;
10194             ast_copy_string(exten2, exten, sizeof(exten2));
10195             /* Parse out extension and callerid */
10196             stringp=exten2 +1;
10197             s1 = strsep(&stringp, "#");
10198             s2 = strsep(&stringp, "#");
10199             if (s2) {
10200                if (!ast_strlen_zero(p->cid_num))
10201                   ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
10202                else
10203                   if (*(s1 + 2))
10204                      ast_set_callerid(chan, s1 + 2, NULL, s1 + 2);
10205                ast_copy_string(exten, s2 + 1, sizeof(exten));
10206             } else
10207                ast_copy_string(exten, s1 + 2, sizeof(exten));
10208          } else
10209             ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d.  Assuming E&M Wink instead\n", p->channel);
10210       }
10211       if ((p->sig == SIG_E911) || (p->sig == SIG_FGC_CAMAMF)) {
10212          if (exten[0] == '*') {
10213             char *stringp=NULL;
10214             ast_copy_string(exten2, exten, sizeof(exten2));
10215             /* Parse out extension and callerid */
10216             stringp=exten2 +1;
10217             s1 = strsep(&stringp, "#");
10218             s2 = strsep(&stringp, "#");
10219             if (s2 && (*(s2 + 1) == '0')) {
10220                if (*(s2 + 2))
10221                   ast_set_callerid(chan, s2 + 2, NULL, s2 + 2);
10222             }
10223             if (s1)  ast_copy_string(exten, s1, sizeof(exten));
10224             else ast_copy_string(exten, "911", sizeof(exten));
10225          } else
10226             ast_log(LOG_WARNING, "Got a non-E911/FGC CAMA input on channel %d.  Assuming E&M Wink instead\n", p->channel);
10227       }
10228       if (p->sig == SIG_FEATB) {
10229          if (exten[0] == '*') {
10230             char *stringp=NULL;
10231             ast_copy_string(exten2, exten, sizeof(exten2));
10232             /* Parse out extension and callerid */
10233             stringp=exten2 +1;
10234             s1 = strsep(&stringp, "#");
10235             ast_copy_string(exten, exten2 + 1, sizeof(exten));
10236          } else
10237             ast_log(LOG_WARNING, "Got a non-Feature Group B input on channel %d.  Assuming E&M Wink instead\n", p->channel);
10238       }
10239       if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
10240          dahdi_wink(p, idx);
10241          /* some switches require a minimum guard time between
10242             the last FGD wink and something that answers
10243             immediately. This ensures it */
10244          if (ast_safe_sleep(chan, 100)) {
10245             ast_hangup(chan);
10246             goto quit;
10247          }
10248       }
10249       dahdi_enable_ec(p);
10250       if (NEED_MFDETECT(p)) {
10251          if (p->dsp) {
10252             if (!p->hardwaredtmf)
10253                ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
10254             else {
10255                ast_dsp_free(p->dsp);
10256                p->dsp = NULL;
10257             }
10258          }
10259       }
10260 
10261       if (ast_exists_extension(chan, chan->context, exten, 1,
10262          S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
10263          ast_copy_string(chan->exten, exten, sizeof(chan->exten));
10264          if (p->dsp) ast_dsp_digitreset(p->dsp);
10265          res = ast_pbx_run(chan);
10266          if (res) {
10267             ast_log(LOG_WARNING, "PBX exited non-zero\n");
10268             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10269          }
10270          goto quit;
10271       } else {
10272          ast_verb(2, "Unknown extension '%s' in context '%s' requested\n", exten, chan->context);
10273          sleep(2);
10274          res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_INFO);
10275          if (res < 0)
10276             ast_log(LOG_WARNING, "Unable to start special tone on %d\n", p->channel);
10277          else
10278             sleep(1);
10279          res = ast_streamfile(chan, "ss-noservice", chan->language);
10280          if (res >= 0)
10281             ast_waitstream(chan, "");
10282          res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10283          ast_hangup(chan);
10284          goto quit;
10285       }
10286       break;
10287    case SIG_FXOLS:
10288    case SIG_FXOGS:
10289    case SIG_FXOKS:
10290       /* Read the first digit */
10291       timeout = firstdigittimeout;
10292       /* If starting a threeway call, never timeout on the first digit so someone
10293          can use flash-hook as a "hold" feature */
10294       if (p->subs[SUB_THREEWAY].owner)
10295          timeout = 999999;
10296       while (len < AST_MAX_EXTENSION-1) {
10297          /* Read digit unless it's supposed to be immediate, in which case the
10298             only answer is 's' */
10299          if (p->immediate)
10300             res = 's';
10301          else
10302             res = ast_waitfordigit(chan, timeout);
10303          timeout = 0;
10304          if (res < 0) {
10305             ast_debug(1, "waitfordigit returned < 0...\n");
10306             res = tone_zone_play_tone(p->subs[idx].dfd, -1);
10307             ast_hangup(chan);
10308             goto quit;
10309          } else if (res) {
10310             ast_debug(1,"waitfordigit returned '%c' (%d), timeout = %d\n", res, res, timeout);
10311             exten[len++]=res;
10312             exten[len] = '\0';
10313          }
10314          if (!ast_ignore_pattern(chan->context, exten))
10315             tone_zone_play_tone(p->subs[idx].dfd, -1);
10316          else
10317             tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
10318          if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num) && !ast_parking_ext_valid(exten, chan, chan->context)) {
10319             if (!res || !ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
10320                if (getforward) {
10321                   /* Record this as the forwarding extension */
10322                   ast_copy_string(p->call_forward, exten, sizeof(p->call_forward));
10323                   ast_verb(3, "Setting call forward to '%s' on channel %d\n", p->call_forward, p->channel);
10324                   res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10325                   if (res)
10326                      break;
10327                   usleep(500000);
10328                   res = tone_zone_play_tone(p->subs[idx].dfd, -1);
10329                   sleep(1);
10330                   memset(exten, 0, sizeof(exten));
10331                   res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
10332                   len = 0;
10333                   getforward = 0;
10334                } else {
10335                   res = tone_zone_play_tone(p->subs[idx].dfd, -1);
10336                   ast_copy_string(chan->exten, exten, sizeof(chan->exten));
10337                   if (!ast_strlen_zero(p->cid_num)) {
10338                      if (!p->hidecallerid)
10339                         ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
10340                      else
10341                         ast_set_callerid(chan, NULL, NULL, p->cid_num);
10342                   }
10343                   if (!ast_strlen_zero(p->cid_name)) {
10344                      if (!p->hidecallerid)
10345                         ast_set_callerid(chan, NULL, p->cid_name, NULL);
10346                   }
10347                   ast_setstate(chan, AST_STATE_RING);
10348                   dahdi_enable_ec(p);
10349                   res = ast_pbx_run(chan);
10350                   if (res) {
10351                      ast_log(LOG_WARNING, "PBX exited non-zero\n");
10352                      res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10353                   }
10354                   goto quit;
10355                }
10356             } else {
10357                /* It's a match, but they just typed a digit, and there is an ambiguous match,
10358                   so just set the timeout to matchdigittimeout and wait some more */
10359                timeout = matchdigittimeout;
10360             }
10361          } else if (res == 0) {
10362             ast_debug(1, "not enough digits (and no ambiguous match)...\n");
10363             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10364             dahdi_wait_event(p->subs[idx].dfd);
10365             ast_hangup(chan);
10366             goto quit;
10367          } else if (p->callwaiting && !strcmp(exten, "*70")) {
10368             ast_verb(3, "Disabling call waiting on %s\n", chan->name);
10369             /* Disable call waiting if enabled */
10370             p->callwaiting = 0;
10371             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10372             if (res) {
10373                ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
10374                   chan->name, strerror(errno));
10375             }
10376             len = 0;
10377             ioctl(p->subs[idx].dfd,DAHDI_CONFDIAG,&len);
10378             memset(exten, 0, sizeof(exten));
10379             timeout = firstdigittimeout;
10380 
10381          } else if (!strcmp(exten,ast_pickup_ext())) {
10382             /* Scan all channels and see if there are any
10383              * ringing channels that have call groups
10384              * that equal this channels pickup group
10385              */
10386             if (idx == SUB_REAL) {
10387                /* Switch us from Third call to Call Wait */
10388                if (p->subs[SUB_THREEWAY].owner) {
10389                   /* If you make a threeway call and the *8# a call, it should actually
10390                      look like a callwait */
10391                   alloc_sub(p, SUB_CALLWAIT);
10392                   swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
10393                   unalloc_sub(p, SUB_THREEWAY);
10394                }
10395                dahdi_enable_ec(p);
10396                if (ast_pickup_call(chan)) {
10397                   ast_debug(1, "No call pickup possible...\n");
10398                   res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10399                   dahdi_wait_event(p->subs[idx].dfd);
10400                }
10401                ast_hangup(chan);
10402                goto quit;
10403             } else {
10404                ast_log(LOG_WARNING, "Huh?  Got *8# on call not on real\n");
10405                ast_hangup(chan);
10406                goto quit;
10407             }
10408 
10409          } else if (!p->hidecallerid && !strcmp(exten, "*67")) {
10410             ast_verb(3, "Disabling Caller*ID on %s\n", chan->name);
10411             /* Disable Caller*ID if enabled */
10412             p->hidecallerid = 1;
10413             ast_party_number_free(&chan->caller.id.number);
10414             ast_party_number_init(&chan->caller.id.number);
10415             ast_party_name_free(&chan->caller.id.name);
10416             ast_party_name_init(&chan->caller.id.name);
10417             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10418             if (res) {
10419                ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
10420                   chan->name, strerror(errno));
10421             }
10422             len = 0;
10423             memset(exten, 0, sizeof(exten));
10424             timeout = firstdigittimeout;
10425          } else if (p->callreturn && !strcmp(exten, "*69")) {
10426             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10427             break;
10428          } else if (!strcmp(exten, "*78")) {
10429             dahdi_dnd(p, 1);
10430             /* Do not disturb */
10431             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10432             getforward = 0;
10433             memset(exten, 0, sizeof(exten));
10434             len = 0;
10435          } else if (!strcmp(exten, "*79")) {
10436             dahdi_dnd(p, 0);
10437             /* Do not disturb */
10438             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10439             getforward = 0;
10440             memset(exten, 0, sizeof(exten));
10441             len = 0;
10442          } else if (p->cancallforward && !strcmp(exten, "*72")) {
10443             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10444             getforward = 1;
10445             memset(exten, 0, sizeof(exten));
10446             len = 0;
10447          } else if (p->cancallforward && !strcmp(exten, "*73")) {
10448             ast_verb(3, "Cancelling call forwarding on channel %d\n", p->channel);
10449             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10450             memset(p->call_forward, 0, sizeof(p->call_forward));
10451             getforward = 0;
10452             memset(exten, 0, sizeof(exten));
10453             len = 0;
10454          } else if ((p->transfer || p->canpark) && ast_parking_ext_valid(exten, chan, chan->context) &&
10455                   p->subs[SUB_THREEWAY].owner &&
10456                   ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
10457             /* This is a three way call, the main call being a real channel,
10458                and we're parking the first call. */
10459             ast_masq_park_call_exten(ast_bridged_channel(p->subs[SUB_THREEWAY].owner),
10460                chan, exten, chan->context, 0, NULL);
10461             ast_verb(3, "Parking call to '%s'\n", chan->name);
10462             break;
10463          } else if (p->hidecallerid && !strcmp(exten, "*82")) {
10464             ast_verb(3, "Enabling Caller*ID on %s\n", chan->name);
10465             /* Enable Caller*ID if enabled */
10466             p->hidecallerid = 0;
10467             ast_set_callerid(chan, p->cid_num, p->cid_name, NULL);
10468             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10469             if (res) {
10470                ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
10471                   chan->name, strerror(errno));
10472             }
10473             len = 0;
10474             memset(exten, 0, sizeof(exten));
10475             timeout = firstdigittimeout;
10476          } else if (!strcmp(exten, "*0")) {
10477             struct ast_channel *nbridge =
10478                p->subs[SUB_THREEWAY].owner;
10479             struct dahdi_pvt *pbridge = NULL;
10480             /* set up the private struct of the bridged one, if any */
10481             if (nbridge && ast_bridged_channel(nbridge))
10482                pbridge = ast_bridged_channel(nbridge)->tech_pvt;
10483             if (nbridge && pbridge &&
10484                (nbridge->tech == &dahdi_tech) &&
10485                (ast_bridged_channel(nbridge)->tech == &dahdi_tech) &&
10486                ISTRUNK(pbridge)) {
10487                int func = DAHDI_FLASH;
10488                /* Clear out the dial buffer */
10489                p->dop.dialstr[0] = '\0';
10490                /* flash hookswitch */
10491                if ((ioctl(pbridge->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
10492                   ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
10493                      nbridge->name, strerror(errno));
10494                }
10495                swap_subs(p, SUB_REAL, SUB_THREEWAY);
10496                unalloc_sub(p, SUB_THREEWAY);
10497                p->owner = p->subs[SUB_REAL].owner;
10498                if (ast_bridged_channel(p->subs[SUB_REAL].owner))
10499                   ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
10500                ast_hangup(chan);
10501                goto quit;
10502             } else {
10503                tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10504                dahdi_wait_event(p->subs[idx].dfd);
10505                tone_zone_play_tone(p->subs[idx].dfd, -1);
10506                swap_subs(p, SUB_REAL, SUB_THREEWAY);
10507                unalloc_sub(p, SUB_THREEWAY);
10508                p->owner = p->subs[SUB_REAL].owner;
10509                ast_hangup(chan);
10510                goto quit;
10511             }
10512          } else if (!ast_canmatch_extension(chan, chan->context, exten, 1,
10513             S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))
10514             && !canmatch_featurecode(exten)) {
10515             ast_debug(1, "Can't match %s from '%s' in context %s\n", exten,
10516                S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, "<Unknown Caller>"),
10517                chan->context);
10518             break;
10519          }
10520          if (!timeout)
10521             timeout = gendigittimeout;
10522          if (len && !ast_ignore_pattern(chan->context, exten))
10523             tone_zone_play_tone(p->subs[idx].dfd, -1);
10524       }
10525       break;
10526    case SIG_FXSLS:
10527    case SIG_FXSGS:
10528    case SIG_FXSKS:
10529       /* check for SMDI messages */
10530       if (p->use_smdi && p->smdi_iface) {
10531          smdi_msg = ast_smdi_md_message_wait(p->smdi_iface, SMDI_MD_WAIT_TIMEOUT);
10532 
10533          if (smdi_msg != NULL) {
10534             ast_copy_string(chan->exten, smdi_msg->fwd_st, sizeof(chan->exten));
10535 
10536             if (smdi_msg->type == 'B')
10537                pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "b");
10538             else if (smdi_msg->type == 'N')
10539                pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "u");
10540 
10541             ast_debug(1, "Received SMDI message on %s\n", chan->name);
10542          } else {
10543             ast_log(LOG_WARNING, "SMDI enabled but no SMDI message present\n");
10544          }
10545       }
10546 
10547       if (p->use_callerid && (p->cid_signalling == CID_SIG_SMDI && smdi_msg)) {
10548          number = smdi_msg->calling_st;
10549 
10550       /* If we want caller id, we're in a prering state due to a polarity reversal
10551        * and we're set to use a polarity reversal to trigger the start of caller id,
10552        * grab the caller id and wait for ringing to start... */
10553       } else if (p->use_callerid && (chan->_state == AST_STATE_PRERING &&
10554                    (p->cid_start == CID_START_POLARITY || p->cid_start == CID_START_POLARITY_IN || p->cid_start == CID_START_DTMF_NOALERT))) {
10555          /* If set to use DTMF CID signalling, listen for DTMF */
10556          if (p->cid_signalling == CID_SIG_DTMF) {
10557             int k = 0;
10558             int off_ms;
10559             struct timeval start = ast_tvnow();
10560             int ms;
10561             cs = NULL;
10562             ast_debug(1, "Receiving DTMF cid on channel %s\n", chan->name);
10563             dahdi_setlinear(p->subs[idx].dfd, 0);
10564             /*
10565              * We are the only party interested in the Rx stream since
10566              * we have not answered yet.  We don't need or even want DTMF
10567              * emulation.  The DTMF digits can come so fast that emulation
10568              * can drop some of them.
10569              */
10570             ast_set_flag(chan, AST_FLAG_END_DTMF_ONLY);
10571             off_ms = 4000;/* This is a typical OFF time between rings. */
10572             for (;;) {
10573                struct ast_frame *f;
10574 
10575                ms = ast_remaining_ms(start, off_ms);
10576                res = ast_waitfor(chan, ms);
10577                if (res <= 0) {
10578                   /*
10579                    * We do not need to restore the dahdi_setlinear()
10580                    * or AST_FLAG_END_DTMF_ONLY flag settings since we
10581                    * are hanging up the channel.
10582                    */
10583                   ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
10584                      "Exiting simple switch\n");
10585                   ast_hangup(chan);
10586                   goto quit;
10587                }
10588                f = ast_read(chan);
10589                if (!f)
10590                   break;
10591                if (f->frametype == AST_FRAME_DTMF) {
10592                   if (k < ARRAY_LEN(dtmfbuf) - 1) {
10593                      dtmfbuf[k++] = f->subclass.integer;
10594                   }
10595                   ast_debug(1, "CID got digit '%c'\n", f->subclass.integer);
10596                   start = ast_tvnow();
10597                }
10598                ast_frfree(f);
10599                if (chan->_state == AST_STATE_RING ||
10600                   chan->_state == AST_STATE_RINGING)
10601                   break; /* Got ring */
10602             }
10603             ast_clear_flag(chan, AST_FLAG_END_DTMF_ONLY);
10604             dtmfbuf[k] = '\0';
10605             dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10606             /* Got cid and ring. */
10607             ast_debug(1, "CID got string '%s'\n", dtmfbuf);
10608             callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
10609             ast_debug(1, "CID is '%s', flags %d\n", dtmfcid, flags);
10610             /* If first byte is NULL, we have no cid */
10611             if (!ast_strlen_zero(dtmfcid))
10612                number = dtmfcid;
10613             else
10614                number = NULL;
10615          /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */
10616          } else if ((p->cid_signalling == CID_SIG_V23) || (p->cid_signalling == CID_SIG_V23_JP)) {
10617             cs = callerid_new(p->cid_signalling);
10618             if (cs) {
10619                int off_ms;
10620                struct timeval start;
10621                int ms;
10622                samples = 0;
10623 #if 1
10624                bump_gains(p);
10625 #endif
10626                /* Take out of linear mode for Caller*ID processing */
10627                dahdi_setlinear(p->subs[idx].dfd, 0);
10628 
10629                /* First we wait and listen for the Caller*ID */
10630                for (;;) {
10631                   i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10632                   if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10633                      ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10634                      callerid_free(cs);
10635                      ast_hangup(chan);
10636                      goto quit;
10637                   }
10638                   if (i & DAHDI_IOMUX_SIGEVENT) {
10639                      res = dahdi_get_event(p->subs[idx].dfd);
10640                      ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10641                      if (res == DAHDI_EVENT_NOALARM) {
10642                         p->inalarm = 0;
10643                      }
10644 
10645                      if (p->cid_signalling == CID_SIG_V23_JP) {
10646                         if (res == DAHDI_EVENT_RINGBEGIN) {
10647                            res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
10648                            usleep(1);
10649                         }
10650                      } else {
10651                         res = 0;
10652                         break;
10653                      }
10654                   } else if (i & DAHDI_IOMUX_READ) {
10655                      res = read(p->subs[idx].dfd, buf, sizeof(buf));
10656                      if (res < 0) {
10657                         if (errno != ELAST) {
10658                            ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10659                            callerid_free(cs);
10660                            ast_hangup(chan);
10661                            goto quit;
10662                         }
10663                         break;
10664                      }
10665                      samples += res;
10666 
10667                      if (p->cid_signalling == CID_SIG_V23_JP) {
10668                         res = callerid_feed_jp(cs, buf, res, AST_LAW(p));
10669                      } else {
10670                         res = callerid_feed(cs, buf, res, AST_LAW(p));
10671                      }
10672                      if (res < 0) {
10673                         /*
10674                          * The previous diagnostic message output likely
10675                          * explains why it failed.
10676                          */
10677                         ast_log(LOG_WARNING,
10678                            "Failed to decode CallerID on channel '%s'\n",
10679                            chan->name);
10680                         break;
10681                      } else if (res)
10682                         break;
10683                      else if (samples > (8000 * 10))
10684                         break;
10685                   }
10686                }
10687                if (res == 1) {
10688                   callerid_get(cs, &name, &number, &flags);
10689                   ast_log(LOG_NOTICE, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
10690                }
10691 
10692                if (p->cid_signalling == CID_SIG_V23_JP) {
10693                   res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
10694                   usleep(1);
10695                }
10696 
10697                /* Finished with Caller*ID, now wait for a ring to make sure there really is a call coming */
10698                start = ast_tvnow();
10699                off_ms = 4000;/* This is a typical OFF time between rings. */
10700                for (;;) {
10701                   struct ast_frame *f;
10702 
10703                   ms = ast_remaining_ms(start, off_ms);
10704                   res = ast_waitfor(chan, ms);
10705                   if (res <= 0) {
10706                      ast_log(LOG_WARNING, "CID timed out waiting for ring. "
10707                         "Exiting simple switch\n");
10708                      ast_hangup(chan);
10709                      goto quit;
10710                   }
10711                   if (!(f = ast_read(chan))) {
10712                      ast_log(LOG_WARNING, "Hangup received waiting for ring. Exiting simple switch\n");
10713                      ast_hangup(chan);
10714                      goto quit;
10715                   }
10716                   ast_frfree(f);
10717                   if (chan->_state == AST_STATE_RING ||
10718                      chan->_state == AST_STATE_RINGING)
10719                      break; /* Got ring */
10720                }
10721 
10722                /* We must have a ring by now, so, if configured, lets try to listen for
10723                 * distinctive ringing */
10724                if (p->usedistinctiveringdetection) {
10725                   len = 0;
10726                   distMatches = 0;
10727                   /* Clear the current ring data array so we don't have old data in it. */
10728                   for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
10729                      curRingData[receivedRingT] = 0;
10730                   receivedRingT = 0;
10731                   counter = 0;
10732                   counter1 = 0;
10733                   /* Check to see if context is what it should be, if not set to be. */
10734                   if (strcmp(p->context,p->defcontext) != 0) {
10735                      ast_copy_string(p->context, p->defcontext, sizeof(p->context));
10736                      ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
10737                   }
10738 
10739                   for (;;) {
10740                      i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10741                      if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10742                         ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10743                         callerid_free(cs);
10744                         ast_hangup(chan);
10745                         goto quit;
10746                      }
10747                      if (i & DAHDI_IOMUX_SIGEVENT) {
10748                         res = dahdi_get_event(p->subs[idx].dfd);
10749                         ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10750                         if (res == DAHDI_EVENT_NOALARM) {
10751                            p->inalarm = 0;
10752                         }
10753                         res = 0;
10754                         /* Let us detect distinctive ring */
10755 
10756                         curRingData[receivedRingT] = p->ringt;
10757 
10758                         if (p->ringt < p->ringt_base/2)
10759                            break;
10760                         /* Increment the ringT counter so we can match it against
10761                            values in chan_dahdi.conf for distinctive ring */
10762                         if (++receivedRingT == ARRAY_LEN(curRingData))
10763                            break;
10764                      } else if (i & DAHDI_IOMUX_READ) {
10765                         res = read(p->subs[idx].dfd, buf, sizeof(buf));
10766                         if (res < 0) {
10767                            if (errno != ELAST) {
10768                               ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10769                               callerid_free(cs);
10770                               ast_hangup(chan);
10771                               goto quit;
10772                            }
10773                            break;
10774                         }
10775                         if (p->ringt > 0) {
10776                            if (!(--p->ringt)) {
10777                               res = -1;
10778                               break;
10779                            }
10780                         }
10781                      }
10782                   }
10783                      /* this only shows up if you have n of the dring patterns filled in */
10784                   ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
10785                   for (counter = 0; counter < 3; counter++) {
10786                      /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this
10787                      channel */
10788                      distMatches = 0;
10789                      for (counter1 = 0; counter1 < 3; counter1++) {
10790                         ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
10791                         if (p->drings.ringnum[counter].ring[counter1] == -1) {
10792                            ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
10793                            curRingData[counter1]);
10794                            distMatches++;
10795                         } else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
10796                               curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
10797                            ast_verb(3, "Ring pattern matched in range: %d to %d\n",
10798                            (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
10799                            (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
10800                            distMatches++;
10801                         }
10802                      }
10803 
10804                      if (distMatches == 3) {
10805                         /* The ring matches, set the context to whatever is for distinctive ring.. */
10806                         ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context));
10807                         ast_copy_string(chan->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(chan->context));
10808                         ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
10809                         break;
10810                      }
10811                   }
10812                }
10813                /* Restore linear mode (if appropriate) for Caller*ID processing */
10814                dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10815 #if 1
10816                restore_gains(p);
10817 #endif
10818             } else
10819                ast_log(LOG_WARNING, "Unable to get caller ID space\n");
10820          } else {
10821             ast_log(LOG_WARNING, "Channel %s in prering "
10822                "state, but I have nothing to do. "
10823                "Terminating simple switch, should be "
10824                "restarted by the actual ring.\n",
10825                chan->name);
10826             ast_hangup(chan);
10827             goto quit;
10828          }
10829       } else if (p->use_callerid && p->cid_start == CID_START_RING) {
10830          if (p->cid_signalling == CID_SIG_DTMF) {
10831             int k = 0;
10832             int off_ms;
10833             struct timeval start;
10834             int ms;
10835             cs = NULL;
10836             dahdi_setlinear(p->subs[idx].dfd, 0);
10837             off_ms = 2000;
10838             start = ast_tvnow();
10839             for (;;) {
10840                struct ast_frame *f;
10841 
10842                ms = ast_remaining_ms(start, off_ms);
10843                res = ast_waitfor(chan, ms);
10844                if (res <= 0) {
10845                   ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
10846                      "Exiting simple switch\n");
10847                   ast_hangup(chan);
10848                   goto quit;
10849                }
10850                f = ast_read(chan);
10851                if (!f) {
10852                   /* Hangup received waiting for DTMFCID. Exiting simple switch. */
10853                   ast_hangup(chan);
10854                   goto quit;
10855                }
10856                if (f->frametype == AST_FRAME_DTMF) {
10857                   dtmfbuf[k++] = f->subclass.integer;
10858                   ast_log(LOG_DEBUG, "CID got digit '%c'\n", f->subclass.integer);
10859                   start = ast_tvnow();
10860                }
10861                ast_frfree(f);
10862 
10863                if (p->ringt_base == p->ringt)
10864                   break;
10865             }
10866             dtmfbuf[k] = '\0';
10867             dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10868             /* Got cid and ring. */
10869             callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
10870             ast_log(LOG_DEBUG, "CID is '%s', flags %d\n",
10871                dtmfcid, flags);
10872             /* If first byte is NULL, we have no cid */
10873             if (!ast_strlen_zero(dtmfcid))
10874                number = dtmfcid;
10875             else
10876                number = NULL;
10877             /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */
10878          } else {
10879             /* FSK Bell202 callerID */
10880             cs = callerid_new(p->cid_signalling);
10881             if (cs) {
10882 #if 1
10883                bump_gains(p);
10884 #endif
10885                samples = 0;
10886                len = 0;
10887                distMatches = 0;
10888                /* Clear the current ring data array so we don't have old data in it. */
10889                for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
10890                   curRingData[receivedRingT] = 0;
10891                receivedRingT = 0;
10892                counter = 0;
10893                counter1 = 0;
10894                /* Check to see if context is what it should be, if not set to be. */
10895                if (strcmp(p->context,p->defcontext) != 0) {
10896                   ast_copy_string(p->context, p->defcontext, sizeof(p->context));
10897                   ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
10898                }
10899 
10900                /* Take out of linear mode for Caller*ID processing */
10901                dahdi_setlinear(p->subs[idx].dfd, 0);
10902                for (;;) {
10903                   i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10904                   if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10905                      ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10906                      callerid_free(cs);
10907                      ast_hangup(chan);
10908                      goto quit;
10909                   }
10910                   if (i & DAHDI_IOMUX_SIGEVENT) {
10911                      res = dahdi_get_event(p->subs[idx].dfd);
10912                      ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10913                      if (res == DAHDI_EVENT_NOALARM) {
10914                         p->inalarm = 0;
10915                      }
10916                      /* If we get a PR event, they hung up while processing calerid */
10917                      if ( res == DAHDI_EVENT_POLARITY && p->hanguponpolarityswitch && p->polarity == POLARITY_REV) {
10918                         ast_log(LOG_DEBUG, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p->channel);
10919                         p->polarity = POLARITY_IDLE;
10920                         callerid_free(cs);
10921                         ast_hangup(chan);
10922                         goto quit;
10923                      }
10924                      res = 0;
10925                      /* Let us detect callerid when the telco uses distinctive ring */
10926 
10927                      curRingData[receivedRingT] = p->ringt;
10928 
10929                      if (p->ringt < p->ringt_base/2)
10930                         break;
10931                      /* Increment the ringT counter so we can match it against
10932                         values in chan_dahdi.conf for distinctive ring */
10933                      if (++receivedRingT == ARRAY_LEN(curRingData))
10934                         break;
10935                   } else if (i & DAHDI_IOMUX_READ) {
10936                      res = read(p->subs[idx].dfd, buf, sizeof(buf));
10937                      if (res < 0) {
10938                         if (errno != ELAST) {
10939                            ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10940                            callerid_free(cs);
10941                            ast_hangup(chan);
10942                            goto quit;
10943                         }
10944                         break;
10945                      }
10946                      if (p->ringt > 0) {
10947                         if (!(--p->ringt)) {
10948                            res = -1;
10949                            break;
10950                         }
10951                      }
10952                      samples += res;
10953                      res = callerid_feed(cs, buf, res, AST_LAW(p));
10954                      if (res < 0) {
10955                         /*
10956                          * The previous diagnostic message output likely
10957                          * explains why it failed.
10958                          */
10959                         ast_log(LOG_WARNING,
10960                            "Failed to decode CallerID on channel '%s'\n",
10961                            chan->name);
10962                         break;
10963                      } else if (res)
10964                         break;
10965                      else if (samples > (8000 * 10))
10966                         break;
10967                   }
10968                }
10969                if (res == 1) {
10970                   callerid_get(cs, &name, &number, &flags);
10971                   ast_debug(1, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
10972                }
10973                if (distinctiveringaftercid == 1) {
10974                   /* Clear the current ring data array so we don't have old data in it. */
10975                   for (receivedRingT = 0; receivedRingT < 3; receivedRingT++) {
10976                      curRingData[receivedRingT] = 0;
10977                   }
10978                   receivedRingT = 0;
10979                   ast_verb(3, "Detecting post-CID distinctive ring\n");
10980                   for (;;) {
10981                      i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10982                      if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10983                         ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10984                         callerid_free(cs);
10985                         ast_hangup(chan);
10986                         goto quit;
10987                      }
10988                      if (i & DAHDI_IOMUX_SIGEVENT) {
10989                         res = dahdi_get_event(p->subs[idx].dfd);
10990                         ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10991                         if (res == DAHDI_EVENT_NOALARM) {
10992                            p->inalarm = 0;
10993                         }
10994                         res = 0;
10995                         /* Let us detect callerid when the telco uses distinctive ring */
10996 
10997                         curRingData[receivedRingT] = p->ringt;
10998 
10999                         if (p->ringt < p->ringt_base/2)
11000                            break;
11001                         /* Increment the ringT counter so we can match it against
11002                            values in chan_dahdi.conf for distinctive ring */
11003                         if (++receivedRingT == ARRAY_LEN(curRingData))
11004                            break;
11005                      } else if (i & DAHDI_IOMUX_READ) {
11006                         res = read(p->subs[idx].dfd, buf, sizeof(buf));
11007                         if (res < 0) {
11008                            if (errno != ELAST) {
11009                               ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
11010                               callerid_free(cs);
11011                               ast_hangup(chan);
11012                               goto quit;
11013                            }
11014                            break;
11015                         }
11016                         if (p->ringt > 0) {
11017                            if (!(--p->ringt)) {
11018                               res = -1;
11019                               break;
11020                            }
11021                         }
11022                      }
11023                   }
11024                }
11025                if (p->usedistinctiveringdetection) {
11026                   /* this only shows up if you have n of the dring patterns filled in */
11027                   ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
11028 
11029                   for (counter = 0; counter < 3; counter++) {
11030                      /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this
11031                      channel */
11032                      /* this only shows up if you have n of the dring patterns filled in */
11033                      ast_verb(3, "Checking %d,%d,%d\n",
11034                            p->drings.ringnum[counter].ring[0],
11035                            p->drings.ringnum[counter].ring[1],
11036                            p->drings.ringnum[counter].ring[2]);
11037                      distMatches = 0;
11038                      for (counter1 = 0; counter1 < 3; counter1++) {
11039                         ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
11040                         if (p->drings.ringnum[counter].ring[counter1] == -1) {
11041                            ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
11042                            curRingData[counter1]);
11043                            distMatches++;
11044                         }
11045                         else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
11046                            curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
11047                            ast_verb(3, "Ring pattern matched in range: %d to %d\n",
11048                            (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
11049                            (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
11050                            distMatches++;
11051                         }
11052                      }
11053                      if (distMatches == 3) {
11054                         /* The ring matches, set the context to whatever is for distinctive ring.. */
11055                         ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context));
11056                         ast_copy_string(chan->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(chan->context));
11057                         ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
11058                         break;
11059                      }
11060                   }
11061                }
11062                /* Restore linear mode (if appropriate) for Caller*ID processing */
11063                dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
11064 #if 1
11065                restore_gains(p);
11066 #endif
11067                if (res < 0) {
11068                   ast_log(LOG_WARNING, "CallerID returned with error on channel '%s'\n", chan->name);
11069                }
11070             } else
11071                ast_log(LOG_WARNING, "Unable to get caller ID space\n");
11072          }
11073       } else
11074          cs = NULL;
11075 
11076       if (number)
11077          ast_shrink_phone_number(number);
11078       ast_set_callerid(chan, number, name, number);
11079 
11080       if (smdi_msg)
11081          ASTOBJ_UNREF(smdi_msg, ast_smdi_md_message_destroy);
11082 
11083       if (cs)
11084          callerid_free(cs);
11085 
11086       my_handle_notify_message(chan, p, flags, -1);
11087 
11088       ast_setstate(chan, AST_STATE_RING);
11089       chan->rings = 1;
11090       p->ringt = p->ringt_base;
11091       res = ast_pbx_run(chan);
11092       if (res) {
11093          ast_hangup(chan);
11094          ast_log(LOG_WARNING, "PBX exited non-zero\n");
11095       }
11096       goto quit;
11097    default:
11098       ast_log(LOG_WARNING, "Don't know how to handle simple switch with signalling %s on channel %d\n", sig2str(p->sig), p->channel);
11099       res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
11100       if (res < 0)
11101             ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
11102    }
11103    res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
11104    if (res < 0)
11105          ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
11106    ast_hangup(chan);
11107 quit:
11108    ast_mutex_lock(&ss_thread_lock);
11109    ss_thread_count--;
11110    ast_cond_signal(&ss_thread_complete);
11111    ast_mutex_unlock(&ss_thread_lock);
11112    return NULL;
11113 }
11114 
11115 struct mwi_thread_data {
11116    struct dahdi_pvt *pvt;
11117    unsigned char buf[READ_SIZE];
11118    size_t len;
11119 };
11120 
11121 static int calc_energy(const unsigned char *buf, int len, format_t law)
11122 {
11123    int x;
11124    int sum = 0;
11125 
11126    if (!len)
11127       return 0;
11128 
11129    for (x = 0; x < len; x++)
11130       sum += abs(law == AST_FORMAT_ULAW ? AST_MULAW(buf[x]) : AST_ALAW(buf[x]));
11131 
11132    return sum / len;
11133 }
11134 
11135 static void *mwi_thread(void *data)
11136 {
11137    struct mwi_thread_data *mtd = data;
11138    struct callerid_state *cs;
11139    pthread_t threadid;
11140    int samples = 0;
11141    char *name, *number;
11142    int flags;
11143    int i, res;
11144    unsigned int spill_done = 0;
11145    int spill_result = -1;
11146 
11147    if (!(cs = callerid_new(mtd->pvt->cid_signalling))) {
11148       goto quit_no_clean;
11149    }
11150 
11151    callerid_feed(cs, mtd->buf, mtd->len, AST_LAW(mtd->pvt));
11152 
11153    bump_gains(mtd->pvt);
11154 
11155    for (;;) {
11156       i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
11157       if ((res = ioctl(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_IOMUX, &i))) {
11158          ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
11159          goto quit;
11160       }
11161 
11162       if (i & DAHDI_IOMUX_SIGEVENT) {
11163          struct ast_channel *chan;
11164 
11165          /* If we get an event, screen out events that we do not act on.
11166           * Otherwise, cancel and go to the simple switch to let it deal with it.
11167           */
11168          res = dahdi_get_event(mtd->pvt->subs[SUB_REAL].dfd);
11169 
11170          switch (res) {
11171          case DAHDI_EVENT_NEONMWI_ACTIVE:
11172          case DAHDI_EVENT_NEONMWI_INACTIVE:
11173          case DAHDI_EVENT_NONE:
11174          case DAHDI_EVENT_BITSCHANGED:
11175             break;
11176          case DAHDI_EVENT_NOALARM:
11177             if (analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) {
11178                struct analog_pvt *analog_p = mtd->pvt->sig_pvt;
11179 
11180                analog_p->inalarm = 0;
11181             }
11182             mtd->pvt->inalarm = 0;
11183             handle_clear_alarms(mtd->pvt);
11184             break;
11185          case DAHDI_EVENT_ALARM:
11186             if (analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) {
11187                struct analog_pvt *analog_p = mtd->pvt->sig_pvt;
11188 
11189                analog_p->inalarm = 1;
11190             }
11191             mtd->pvt->inalarm = 1;
11192             res = get_alarms(mtd->pvt);
11193             handle_alarms(mtd->pvt, res);
11194             break; /* What to do on channel alarm ???? -- fall thru intentionally?? */
11195          default:
11196             ast_log(LOG_NOTICE, "Got event %d (%s)...  Passing along to analog_ss_thread\n", res, event2str(res));
11197             callerid_free(cs);
11198 
11199             restore_gains(mtd->pvt);
11200             mtd->pvt->ringt = mtd->pvt->ringt_base;
11201 
11202             if ((chan = dahdi_new(mtd->pvt, AST_STATE_RING, 0, SUB_REAL, 0, NULL))) {
11203                int result;
11204 
11205                if (analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) {
11206                   result = analog_ss_thread_start(mtd->pvt->sig_pvt, chan);
11207                } else {
11208                   result = ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan);
11209                }
11210                if (result) {
11211                   ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", mtd->pvt->channel);
11212                   res = tone_zone_play_tone(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11213                   if (res < 0)
11214                      ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", mtd->pvt->channel);
11215                   ast_hangup(chan);
11216                }
11217             } else {
11218                ast_log(LOG_WARNING, "Could not create channel to handle call\n");
11219             }
11220             goto quit_no_clean;
11221          }
11222       } else if (i & DAHDI_IOMUX_READ) {
11223          if ((res = read(mtd->pvt->subs[SUB_REAL].dfd, mtd->buf, sizeof(mtd->buf))) < 0) {
11224             if (errno != ELAST) {
11225                ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
11226                goto quit;
11227             }
11228             break;
11229          }
11230          samples += res;
11231          if (!spill_done) {
11232             if ((spill_result = callerid_feed(cs, mtd->buf, res, AST_LAW(mtd->pvt))) < 0) {
11233                /*
11234                 * The previous diagnostic message output likely
11235                 * explains why it failed.
11236                 */
11237                ast_log(LOG_WARNING, "Failed to decode CallerID\n");
11238                break;
11239             } else if (spill_result) {
11240                spill_done = 1;
11241             }
11242          } else {
11243             /* keep reading data until the energy level drops below the threshold
11244                so we don't get another 'trigger' on the remaining carrier signal
11245             */
11246             if (calc_energy(mtd->buf, res, AST_LAW(mtd->pvt)) <= mwilevel)
11247                break;
11248          }
11249          if (samples > (8000 * 4)) /*Termination case - time to give up*/
11250             break;
11251       }
11252    }
11253 
11254    if (spill_result == 1) {
11255       callerid_get(cs, &name, &number, &flags);
11256       if (flags & CID_MSGWAITING) {
11257          ast_log(LOG_NOTICE, "mwi: Have Messages on channel %d\n", mtd->pvt->channel);
11258          notify_message(mtd->pvt->mailbox, 1);
11259       } else if (flags & CID_NOMSGWAITING) {
11260          ast_log(LOG_NOTICE, "mwi: No Messages on channel %d\n", mtd->pvt->channel);
11261          notify_message(mtd->pvt->mailbox, 0);
11262       } else {
11263          ast_log(LOG_NOTICE, "mwi: Status unknown on channel %d\n", mtd->pvt->channel);
11264       }
11265    }
11266 
11267 
11268 quit:
11269    callerid_free(cs);
11270 
11271    restore_gains(mtd->pvt);
11272 
11273 quit_no_clean:
11274    mtd->pvt->mwimonitoractive = 0;
11275    ast_free(mtd);
11276 
11277    return NULL;
11278 }
11279 
11280 /*
11281 * The following three functions (mwi_send_init, mwi_send_process_buffer,
11282 * mwi_send_process_event) work with the do_monitor thread to generate mwi spills
11283 * that are sent out via FXS port on voicemail state change.  The execution of
11284 * the mwi send is state driven and can either generate a ring pulse prior to
11285 * sending the fsk spill or simply send an fsk spill.
11286 */
11287 static int mwi_send_init(struct dahdi_pvt * pvt)
11288 {
11289    int x;
11290 
11291 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11292    /* Determine how this spill is to be sent */
11293    if (pvt->mwisend_rpas) {
11294       pvt->mwisend_data.mwisend_current = MWI_SEND_SA;
11295       pvt->mwisendactive = 1;
11296    } else if (pvt->mwisend_fsk) {
11297       pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
11298       pvt->mwisendactive = 1;
11299    } else {
11300       pvt->mwisendactive = 0;
11301       return 0;
11302    }
11303 #else
11304    if (mwisend_rpas) {
11305       pvt->mwisend_data.mwisend_current = MWI_SEND_SA;
11306    } else {
11307       pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
11308    }
11309    pvt->mwisendactive = 1;
11310 #endif
11311 
11312    if (pvt->cidspill) {
11313       ast_log(LOG_WARNING, "cidspill already exists when trying to send FSK MWI\n");
11314       ast_free(pvt->cidspill);
11315       pvt->cidspill = NULL;
11316       pvt->cidpos = 0;
11317       pvt->cidlen = 0;
11318    }
11319    pvt->cidspill = ast_calloc(1, MAX_CALLERID_SIZE);
11320    if (!pvt->cidspill) {
11321       pvt->mwisendactive = 0;
11322       return -1;
11323    }
11324    x = DAHDI_FLUSH_BOTH;
11325    ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
11326    x = 3000;
11327    ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_ONHOOKTRANSFER, &x);
11328 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11329    if (pvt->mwisend_fsk) {
11330 #endif
11331       pvt->cidlen = ast_callerid_vmwi_generate(pvt->cidspill, has_voicemail(pvt), CID_MWI_TYPE_MDMF_FULL,
11332                       AST_LAW(pvt), pvt->cid_name, pvt->cid_num, 0);
11333       pvt->cidpos = 0;
11334 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11335    }
11336 #endif
11337    return 0;
11338 }
11339 
11340 static int mwi_send_process_buffer(struct dahdi_pvt * pvt, int num_read)
11341 {
11342    struct timeval    now;
11343    int         res;
11344 
11345    /* sanity check to catch if this had been interrupted previously
11346    *  i.e. state says there is more to do but there is no spill allocated
11347    */
11348    if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current && !pvt->cidspill) {
11349       pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11350    } else if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current) {
11351       /* Normal processing -- Perform mwi send action */
11352       switch ( pvt->mwisend_data.mwisend_current) {
11353       case MWI_SEND_SA:
11354          /* Send the Ring Pulse Signal Alert */
11355          res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &AS_RP_cadence);
11356          if (res) {
11357             ast_log(LOG_WARNING, "Unable to set RP-AS ring cadence: %s\n", strerror(errno));
11358             goto quit;
11359          }
11360          res = dahdi_set_hook(pvt->subs[SUB_REAL].dfd, DAHDI_RING);
11361          pvt->mwisend_data.mwisend_current = MWI_SEND_SA_WAIT;
11362          break;
11363       case MWI_SEND_SA_WAIT:  /* do nothing until I get RINGEROFF event */
11364          break;
11365       case MWI_SEND_PAUSE:  /* Wait between alert and spill - min of 500 mS*/
11366 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11367          if (pvt->mwisend_fsk) {
11368 #endif
11369             gettimeofday(&now, NULL);
11370             if ((int)(now.tv_sec - pvt->mwisend_data.pause.tv_sec) * 1000000 + (int)now.tv_usec - (int)pvt->mwisend_data.pause.tv_usec > 500000) {
11371                pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
11372             }
11373 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11374          } else { /* support for mwisendtype=nofsk */
11375             pvt->mwisend_data.mwisend_current = MWI_SEND_CLEANUP;
11376          }
11377 #endif
11378          break;
11379       case MWI_SEND_SPILL:
11380          /* We read some number of bytes.  Write an equal amount of data */
11381          if(0 < num_read) {
11382             if (num_read > pvt->cidlen - pvt->cidpos)
11383                num_read = pvt->cidlen - pvt->cidpos;
11384             res = write(pvt->subs[SUB_REAL].dfd, pvt->cidspill + pvt->cidpos, num_read);
11385             if (res > 0) {
11386                pvt->cidpos += res;
11387                if (pvt->cidpos >= pvt->cidlen) {
11388                   pvt->mwisend_data.mwisend_current = MWI_SEND_CLEANUP;
11389                }
11390             } else {
11391                ast_log(LOG_WARNING, "MWI FSK Send Write failed: %s\n", strerror(errno));
11392                goto quit;
11393             }
11394          }
11395          break;
11396       case MWI_SEND_CLEANUP:
11397          /* For now, do nothing */
11398          pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11399          break;
11400       default:
11401          /* Should not get here, punt*/
11402          goto quit;
11403       }
11404    }
11405 
11406    if (MWI_SEND_DONE == pvt->mwisend_data.mwisend_current) {
11407       if (pvt->cidspill) {
11408          ast_free(pvt->cidspill);
11409          pvt->cidspill = NULL;
11410          pvt->cidpos = 0;
11411          pvt->cidlen = 0;
11412       }
11413       pvt->mwisendactive = 0;
11414    }
11415    return 0;
11416 quit:
11417    if (pvt->cidspill) {
11418       ast_free(pvt->cidspill);
11419       pvt->cidspill = NULL;
11420       pvt->cidpos = 0;
11421       pvt->cidlen = 0;
11422    }
11423    pvt->mwisendactive = 0;
11424    return -1;
11425 }
11426 
11427 static int mwi_send_process_event(struct dahdi_pvt * pvt, int event)
11428 {
11429    int handled = 0;
11430 
11431    if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current) {
11432       switch (event) {
11433       case DAHDI_EVENT_RINGEROFF:
11434          if(pvt->mwisend_data.mwisend_current == MWI_SEND_SA_WAIT) {
11435             handled = 1;
11436 
11437             if (dahdi_set_hook(pvt->subs[SUB_REAL].dfd, DAHDI_RINGOFF) ) {
11438                ast_log(LOG_WARNING, "Unable to finish RP-AS: %s mwi send aborted\n", strerror(errno));
11439                ast_free(pvt->cidspill);
11440                pvt->cidspill = NULL;
11441                pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11442                pvt->mwisendactive = 0;
11443             } else {
11444                pvt->mwisend_data.mwisend_current = MWI_SEND_PAUSE;
11445                gettimeofday(&pvt->mwisend_data.pause, NULL);
11446             }
11447          }
11448          break;
11449       /* Going off hook, I need to punt this spill */
11450       case DAHDI_EVENT_RINGOFFHOOK:
11451          if (pvt->cidspill) {
11452             ast_free(pvt->cidspill);
11453             pvt->cidspill = NULL;
11454             pvt->cidpos = 0;
11455             pvt->cidlen = 0;
11456          }
11457          pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11458          pvt->mwisendactive = 0;
11459          break;
11460       case DAHDI_EVENT_RINGERON:
11461       case DAHDI_EVENT_HOOKCOMPLETE:
11462          break;
11463       default:
11464          break;
11465       }
11466    }
11467    return handled;
11468 }
11469 
11470 /* destroy a DAHDI channel, identified by its number */
11471 static int dahdi_destroy_channel_bynum(int channel)
11472 {
11473    struct dahdi_pvt *cur;
11474 
11475    ast_mutex_lock(&iflock);
11476    for (cur = iflist; cur; cur = cur->next) {
11477       if (cur->channel == channel) {
11478          int x = DAHDI_FLASH;
11479 
11480          /* important to create an event for dahdi_wait_event to register so that all analog_ss_threads terminate */
11481          ioctl(cur->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
11482 
11483          destroy_channel(cur, 1);
11484          ast_mutex_unlock(&iflock);
11485          ast_module_unref(ast_module_info->self);
11486          return RESULT_SUCCESS;
11487       }
11488    }
11489    ast_mutex_unlock(&iflock);
11490    return RESULT_FAILURE;
11491 }
11492 
11493 static struct dahdi_pvt *handle_init_event(struct dahdi_pvt *i, int event)
11494 {
11495    int res;
11496    pthread_t threadid;
11497    struct ast_channel *chan;
11498 
11499    /* Handle an event on a given channel for the monitor thread. */
11500 
11501    switch (event) {
11502    case DAHDI_EVENT_NONE:
11503    case DAHDI_EVENT_BITSCHANGED:
11504       break;
11505    case DAHDI_EVENT_WINKFLASH:
11506    case DAHDI_EVENT_RINGOFFHOOK:
11507       if (i->inalarm) break;
11508       if (i->radio) break;
11509       /* Got a ring/answer.  What kind of channel are we? */
11510       switch (i->sig) {
11511       case SIG_FXOLS:
11512       case SIG_FXOGS:
11513       case SIG_FXOKS:
11514          res = dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
11515          if (res && (errno == EBUSY))
11516             break;
11517 
11518          /* Cancel VMWI spill */
11519          ast_free(i->cidspill);
11520          i->cidspill = NULL;
11521          restore_conference(i);
11522 
11523          if (i->immediate) {
11524             dahdi_enable_ec(i);
11525             /* The channel is immediately up.  Start right away */
11526             res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
11527             chan = dahdi_new(i, AST_STATE_RING, 1, SUB_REAL, 0, NULL);
11528             if (!chan) {
11529                ast_log(LOG_WARNING, "Unable to start PBX on channel %d\n", i->channel);
11530                res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11531                if (res < 0)
11532                   ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11533             }
11534          } else {
11535             /* Check for callerid, digits, etc */
11536             chan = dahdi_new(i, AST_STATE_RESERVED, 0, SUB_REAL, 0, NULL);
11537             if (chan) {
11538                if (has_voicemail(i))
11539                   res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
11540                else
11541                   res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
11542                if (res < 0)
11543                   ast_log(LOG_WARNING, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i->channel);
11544                if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
11545                   ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11546                   res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11547                   if (res < 0)
11548                      ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11549                   ast_hangup(chan);
11550                }
11551             } else
11552                ast_log(LOG_WARNING, "Unable to create channel\n");
11553          }
11554          break;
11555       case SIG_FXSLS:
11556       case SIG_FXSGS:
11557       case SIG_FXSKS:
11558             i->ringt = i->ringt_base;
11559             /* Fall through */
11560       case SIG_EMWINK:
11561       case SIG_FEATD:
11562       case SIG_FEATDMF:
11563       case SIG_FEATDMF_TA:
11564       case SIG_E911:
11565       case SIG_FGC_CAMA:
11566       case SIG_FGC_CAMAMF:
11567       case SIG_FEATB:
11568       case SIG_EM:
11569       case SIG_EM_E1:
11570       case SIG_SFWINK:
11571       case SIG_SF_FEATD:
11572       case SIG_SF_FEATDMF:
11573       case SIG_SF_FEATB:
11574       case SIG_SF:
11575          /* Check for callerid, digits, etc */
11576          if (i->cid_start == CID_START_POLARITY_IN) {
11577             chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL);
11578          } else {
11579             chan = dahdi_new(i, AST_STATE_RING, 0, SUB_REAL, 0, NULL);
11580          }
11581 
11582          if (!chan) {
11583             ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
11584          } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
11585             ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11586             res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11587             if (res < 0) {
11588                ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11589             }
11590             ast_hangup(chan);
11591          }
11592          break;
11593       default:
11594          ast_log(LOG_WARNING, "Don't know how to handle ring/answer with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
11595          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11596          if (res < 0)
11597             ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11598          return NULL;
11599       }
11600       break;
11601    case DAHDI_EVENT_NOALARM:
11602       switch (i->sig) {
11603 #if defined(HAVE_PRI)
11604       case SIG_PRI_LIB_HANDLE_CASES:
11605          ast_mutex_lock(&i->lock);
11606          sig_pri_chan_alarm_notify(i->sig_pvt, 1);
11607          ast_mutex_unlock(&i->lock);
11608          break;
11609 #endif   /* defined(HAVE_PRI) */
11610 #if defined(HAVE_SS7)
11611       case SIG_SS7:
11612          sig_ss7_set_alarm(i->sig_pvt, 0);
11613          break;
11614 #endif   /* defined(HAVE_SS7) */
11615       default:
11616          i->inalarm = 0;
11617          break;
11618       }
11619       handle_clear_alarms(i);
11620       break;
11621    case DAHDI_EVENT_ALARM:
11622       switch (i->sig) {
11623 #if defined(HAVE_PRI)
11624       case SIG_PRI_LIB_HANDLE_CASES:
11625          ast_mutex_lock(&i->lock);
11626          sig_pri_chan_alarm_notify(i->sig_pvt, 0);
11627          ast_mutex_unlock(&i->lock);
11628          break;
11629 #endif   /* defined(HAVE_PRI) */
11630 #if defined(HAVE_SS7)
11631       case SIG_SS7:
11632          sig_ss7_set_alarm(i->sig_pvt, 1);
11633          break;
11634 #endif   /* defined(HAVE_SS7) */
11635       default:
11636          i->inalarm = 1;
11637          break;
11638       }
11639       res = get_alarms(i);
11640       handle_alarms(i, res);
11641       /* fall thru intentionally */
11642    case DAHDI_EVENT_ONHOOK:
11643       if (i->radio)
11644          break;
11645       /* Back on hook.  Hang up. */
11646       switch (i->sig) {
11647       case SIG_FXOLS:
11648       case SIG_FXOGS:
11649       case SIG_FEATD:
11650       case SIG_FEATDMF:
11651       case SIG_FEATDMF_TA:
11652       case SIG_E911:
11653       case SIG_FGC_CAMA:
11654       case SIG_FGC_CAMAMF:
11655       case SIG_FEATB:
11656       case SIG_EM:
11657       case SIG_EM_E1:
11658       case SIG_EMWINK:
11659       case SIG_SF_FEATD:
11660       case SIG_SF_FEATDMF:
11661       case SIG_SF_FEATB:
11662       case SIG_SF:
11663       case SIG_SFWINK:
11664       case SIG_FXSLS:
11665       case SIG_FXSGS:
11666       case SIG_FXSKS:
11667       case SIG_FXOKS:
11668          dahdi_disable_ec(i);
11669          /* Diddle the battery for the zhone */
11670 #ifdef ZHONE_HACK
11671          dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
11672          usleep(1);
11673 #endif
11674          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
11675          dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
11676          break;
11677       case SIG_SS7:
11678       case SIG_PRI_LIB_HANDLE_CASES:
11679          dahdi_disable_ec(i);
11680          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
11681          break;
11682       default:
11683          ast_log(LOG_WARNING, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
11684          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
11685          return NULL;
11686       }
11687       break;
11688    case DAHDI_EVENT_POLARITY:
11689       switch (i->sig) {
11690       case SIG_FXSLS:
11691       case SIG_FXSKS:
11692       case SIG_FXSGS:
11693          /* We have already got a PR before the channel was
11694             created, but it wasn't handled. We need polarity
11695             to be REV for remote hangup detection to work.
11696             At least in Spain */
11697          if (i->hanguponpolarityswitch)
11698             i->polarity = POLARITY_REV;
11699          if (i->cid_start == CID_START_POLARITY || i->cid_start == CID_START_POLARITY_IN) {
11700             i->polarity = POLARITY_REV;
11701             ast_verb(2, "Starting post polarity "
11702                "CID detection on channel %d\n",
11703                i->channel);
11704             chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL);
11705             if (!chan) {
11706                ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
11707             } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
11708                ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11709                ast_hangup(chan);
11710             }
11711          }
11712          break;
11713       default:
11714          ast_log(LOG_WARNING, "handle_init_event detected "
11715             "polarity reversal on non-FXO (SIG_FXS) "
11716             "interface %d\n", i->channel);
11717       }
11718       break;
11719    case DAHDI_EVENT_REMOVED: /* destroy channel, will actually do so in do_monitor */
11720       ast_log(LOG_NOTICE,
11721             "Got DAHDI_EVENT_REMOVED. Destroying channel %d\n",
11722             i->channel);
11723       return i;
11724    case DAHDI_EVENT_NEONMWI_ACTIVE:
11725       if (i->mwimonitor_neon) {
11726          notify_message(i->mailbox, 1);
11727          ast_log(LOG_NOTICE, "NEON MWI set for channel %d, mailbox %s \n", i->channel, i->mailbox);
11728       }
11729       break;
11730    case DAHDI_EVENT_NEONMWI_INACTIVE:
11731       if (i->mwimonitor_neon) {
11732          notify_message(i->mailbox, 0);
11733          ast_log(LOG_NOTICE, "NEON MWI cleared for channel %d, mailbox %s\n", i->channel, i->mailbox);
11734       }
11735       break;
11736    }
11737    return NULL;
11738 }
11739 
11740 static void monitor_pfds_clean(void *arg) {
11741    struct pollfd **pfds = arg;
11742    ast_free(*pfds);
11743 }
11744 
11745 static void *do_monitor(void *data)
11746 {
11747    int count, res, res2, spoint, pollres=0;
11748    struct dahdi_pvt *i;
11749    struct dahdi_pvt *last = NULL;
11750    struct dahdi_pvt *doomed;
11751    time_t thispass = 0, lastpass = 0;
11752    int found;
11753    char buf[1024];
11754    struct pollfd *pfds=NULL;
11755    int lastalloc = -1;
11756    /* This thread monitors all the frame relay interfaces which are not yet in use
11757       (and thus do not have a separate thread) indefinitely */
11758    /* From here on out, we die whenever asked */
11759 #if 0
11760    if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) {
11761       ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n");
11762       return NULL;
11763    }
11764    ast_debug(1, "Monitor starting...\n");
11765 #endif
11766    pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
11767 
11768    pthread_cleanup_push(monitor_pfds_clean, &pfds);
11769    for (;;) {
11770       /* Lock the interface list */
11771       ast_mutex_lock(&iflock);
11772       if (!pfds || (lastalloc != ifcount)) {
11773          if (pfds) {
11774             ast_free(pfds);
11775             pfds = NULL;
11776          }
11777          if (ifcount) {
11778             if (!(pfds = ast_calloc(1, ifcount * sizeof(*pfds)))) {
11779                ast_mutex_unlock(&iflock);
11780                return NULL;
11781             }
11782          }
11783          lastalloc = ifcount;
11784       }
11785       /* Build the stuff we're going to poll on, that is the socket of every
11786          dahdi_pvt that does not have an associated owner channel */
11787       count = 0;
11788       for (i = iflist; i; i = i->next) {
11789          ast_mutex_lock(&i->lock);
11790          if (pfds && (i->subs[SUB_REAL].dfd > -1) && i->sig && (!i->radio) && !(i->sig & SIG_MFCR2)) {
11791             if (analog_lib_handles(i->sig, i->radio, i->oprmode)) {
11792                struct analog_pvt *p = i->sig_pvt;
11793 
11794                if (!p) {
11795                   ast_log(LOG_ERROR, "No sig_pvt?\n");
11796                } else if (!p->owner && !p->subs[SUB_REAL].owner) {
11797                   /* This needs to be watched, as it lacks an owner */
11798                   pfds[count].fd = i->subs[SUB_REAL].dfd;
11799                   pfds[count].events = POLLPRI;
11800                   pfds[count].revents = 0;
11801                   /* Message waiting or r2 channels also get watched for reading */
11802                   if (i->cidspill || i->mwisendactive || i->mwimonitor_fsk || 
11803                      (i->cid_start == CID_START_DTMF_NOALERT && (i->sig == SIG_FXSLS || i->sig == SIG_FXSGS || i->sig == SIG_FXSKS))) {
11804                      pfds[count].events |= POLLIN;
11805                   }
11806                   count++;
11807                }
11808             } else {
11809                if (!i->owner && !i->subs[SUB_REAL].owner && !i->mwimonitoractive ) {
11810                   /* This needs to be watched, as it lacks an owner */
11811                   pfds[count].fd = i->subs[SUB_REAL].dfd;
11812                   pfds[count].events = POLLPRI;
11813                   pfds[count].revents = 0;
11814                   /* If we are monitoring for VMWI or sending CID, we need to
11815                      read from the channel as well */
11816                   if (i->cidspill || i->mwisendactive || i->mwimonitor_fsk ||
11817                      (i->cid_start == CID_START_DTMF_NOALERT && (i->sig == SIG_FXSLS || i->sig == SIG_FXSGS || i->sig == SIG_FXSKS))) {
11818                      pfds[count].events |= POLLIN;
11819                   }
11820                   count++;
11821                }
11822             }
11823          }
11824          ast_mutex_unlock(&i->lock);
11825       }
11826       /* Okay, now that we know what to do, release the interface lock */
11827       ast_mutex_unlock(&iflock);
11828 
11829       pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
11830       pthread_testcancel();
11831       /* Wait at least a second for something to happen */
11832       res = poll(pfds, count, 1000);
11833       pthread_testcancel();
11834       pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
11835 
11836       /* Okay, poll has finished.  Let's see what happened.  */
11837       if (res < 0) {
11838          if ((errno != EAGAIN) && (errno != EINTR))
11839             ast_log(LOG_WARNING, "poll return %d: %s\n", res, strerror(errno));
11840          continue;
11841       }
11842       /* Alright, lock the interface list again, and let's look and see what has
11843          happened */
11844       ast_mutex_lock(&iflock);
11845       found = 0;
11846       spoint = 0;
11847       lastpass = thispass;
11848       thispass = time(NULL);
11849       doomed = NULL;
11850       for (i = iflist;; i = i->next) {
11851          if (doomed) {
11852             int res;
11853             res = dahdi_destroy_channel_bynum(doomed->channel);
11854             if (res != RESULT_SUCCESS) {
11855                ast_log(LOG_WARNING, "Couldn't find channel to destroy, hopefully another destroy operation just happened.\n");
11856             }
11857             doomed = NULL;
11858          }
11859          if (!i) {
11860             break;
11861          }
11862 
11863          if (thispass != lastpass) {
11864             if (!found && ((i == last) || ((i == iflist) && !last))) {
11865                last = i;
11866                if (last) {
11867                   struct analog_pvt *analog_p = last->sig_pvt;
11868                   /* Only allow MWI to be initiated on a quiescent fxs port */
11869                   if (analog_p
11870                      && !last->mwisendactive
11871                      && (last->sig & __DAHDI_SIG_FXO)
11872                      && !analog_p->fxsoffhookstate
11873                      && !last->owner
11874                      && !ast_strlen_zero(last->mailbox)
11875                      && (thispass - analog_p->onhooktime > 3)) {
11876                      res = has_voicemail(last);
11877                      if (analog_p->msgstate != res) {
11878                         /* Set driver resources for signalling VMWI */
11879                         res2 = ioctl(last->subs[SUB_REAL].dfd, DAHDI_VMWI, &res);
11880                         if (res2) {
11881                            /* TODO: This message will ALWAYS be generated on some cards; any way to restrict it to those cards where it is interesting? */
11882                            ast_debug(3, "Unable to control message waiting led on channel %d: %s\n", last->channel, strerror(errno));
11883                         }
11884                         /* If enabled for FSK spill then initiate it */
11885                         if (mwi_send_init(last)) {
11886                            ast_log(LOG_WARNING, "Unable to initiate mwi send sequence on channel %d\n", last->channel);
11887                         }
11888                         analog_p->msgstate = res;
11889                         found ++;
11890                      }
11891                   }
11892                   last = last->next;
11893                }
11894             }
11895          }
11896          if ((i->subs[SUB_REAL].dfd > -1) && i->sig) {
11897             if (i->radio && !i->owner)
11898             {
11899                res = dahdi_get_event(i->subs[SUB_REAL].dfd);
11900                if (res)
11901                {
11902                   ast_debug(1, "Monitor doohicky got event %s on radio channel %d\n", event2str(res), i->channel);
11903                   /* Don't hold iflock while handling init events */
11904                   ast_mutex_unlock(&iflock);
11905                   if (analog_lib_handles(i->sig, i->radio, i->oprmode))
11906                      doomed = (struct dahdi_pvt *) analog_handle_init_event(i->sig_pvt, dahdievent_to_analogevent(res));
11907                   else
11908                      doomed = handle_init_event(i, res);
11909                   ast_mutex_lock(&iflock);
11910                }
11911                continue;
11912             }
11913             pollres = ast_fdisset(pfds, i->subs[SUB_REAL].dfd, count, &spoint);
11914             if (pollres & POLLIN) {
11915                if (i->owner || i->subs[SUB_REAL].owner) {
11916 #ifdef HAVE_PRI
11917                   if (!i->pri)
11918 #endif
11919                      ast_log(LOG_WARNING, "Whoa....  I'm owned but found (%d) in read...\n", i->subs[SUB_REAL].dfd);
11920                   continue;
11921                }
11922                if (!i->mwimonitor_fsk && !i->mwisendactive  && i->cid_start != CID_START_DTMF_NOALERT) {
11923                   ast_log(LOG_WARNING, "Whoa....  I'm not looking for MWI or sending MWI but am reading (%d)...\n", i->subs[SUB_REAL].dfd);
11924                   continue;
11925                }
11926                res = read(i->subs[SUB_REAL].dfd, buf, sizeof(buf));
11927                if (res > 0) {
11928                   if (i->mwimonitor_fsk) {
11929                      if (calc_energy((unsigned char *) buf, res, AST_LAW(i)) > mwilevel) {
11930                         pthread_attr_t attr;
11931                         pthread_t threadid;
11932                         struct mwi_thread_data *mtd;
11933 
11934                         pthread_attr_init(&attr);
11935                         pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
11936 
11937                         ast_log(LOG_DEBUG, "Maybe some MWI on port %d!\n", i->channel);
11938                         if ((mtd = ast_calloc(1, sizeof(*mtd)))) {
11939                            mtd->pvt = i;
11940                            memcpy(mtd->buf, buf, res);
11941                            mtd->len = res;
11942                            i->mwimonitoractive = 1;
11943                            if (ast_pthread_create_background(&threadid, &attr, mwi_thread, mtd)) {
11944                               ast_log(LOG_WARNING, "Unable to start mwi thread on channel %d\n", i->channel);
11945                               i->mwimonitoractive = 0;
11946                               ast_free(mtd);
11947                            }
11948                         }
11949                      }
11950                   /* If configured to check for a DTMF CID spill that comes without alert (e.g no polarity reversal) */
11951                   } else if (i->cid_start == CID_START_DTMF_NOALERT) {
11952                      int energy;
11953                      struct timeval now;
11954                      /* State machine dtmfcid_holdoff_state allows for the line to settle
11955                       * before checking agin for dtmf energy.  Presently waits for 500 mS before checking again 
11956                      */
11957                      if (1 == i->dtmfcid_holdoff_state) {
11958                         gettimeofday(&i->dtmfcid_delay, NULL);
11959                         i->dtmfcid_holdoff_state = 2;
11960                      } else if (2 == i->dtmfcid_holdoff_state) {
11961                         gettimeofday(&now, NULL);
11962                         if ((int)(now.tv_sec - i->dtmfcid_delay.tv_sec) * 1000000 + (int)now.tv_usec - (int)i->dtmfcid_delay.tv_usec > 500000) {
11963                            i->dtmfcid_holdoff_state = 0;
11964                         }
11965                      } else {
11966                         energy = calc_energy((unsigned char *) buf, res, AST_LAW(i));
11967                         if (!i->mwisendactive && energy > dtmfcid_level) {
11968                            pthread_t threadid;
11969                            struct ast_channel *chan;
11970                            ast_mutex_unlock(&iflock);
11971                            if (analog_lib_handles(i->sig, i->radio, i->oprmode)) {
11972                               /* just in case this event changes or somehow destroys a channel, set doomed here too */
11973                               doomed = analog_handle_init_event(i->sig_pvt, ANALOG_EVENT_DTMFCID);  
11974                               i->dtmfcid_holdoff_state = 1;
11975                            } else {
11976                               chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL);
11977                               if (!chan) {
11978                                  ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
11979                               } else {
11980                                  res = ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan);
11981                                  if (res) {
11982                                     ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11983                                     ast_hangup(chan);
11984                                  } else {
11985                                     i->dtmfcid_holdoff_state = 1;
11986                                  }
11987                               }
11988                            }
11989                            ast_mutex_lock(&iflock);
11990                         }
11991                      }
11992                   }
11993                   if (i->mwisendactive) {
11994                      mwi_send_process_buffer(i, res);
11995                   }
11996                } else {
11997                   ast_log(LOG_WARNING, "Read failed with %d: %s\n", res, strerror(errno));
11998                }
11999             }
12000             if (pollres & POLLPRI) {
12001                if (i->owner || i->subs[SUB_REAL].owner) {
12002 #ifdef HAVE_PRI
12003                   if (!i->pri)
12004 #endif
12005                      ast_log(LOG_WARNING, "Whoa....  I'm owned but found (%d)...\n", i->subs[SUB_REAL].dfd);
12006                   continue;
12007                }
12008                res = dahdi_get_event(i->subs[SUB_REAL].dfd);
12009                ast_debug(1, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel);
12010                /* Don't hold iflock while handling init events */
12011                ast_mutex_unlock(&iflock);
12012                if (0 == i->mwisendactive || 0 == mwi_send_process_event(i, res)) {
12013                   if (analog_lib_handles(i->sig, i->radio, i->oprmode))
12014                      doomed = (struct dahdi_pvt *) analog_handle_init_event(i->sig_pvt, dahdievent_to_analogevent(res));
12015                   else
12016                      doomed = handle_init_event(i, res);
12017                }
12018                ast_mutex_lock(&iflock);
12019             }
12020          }
12021       }
12022       ast_mutex_unlock(&iflock);
12023    }
12024    /* Never reached */
12025    pthread_cleanup_pop(1);
12026    return NULL;
12027 
12028 }
12029 
12030 static int restart_monitor(void)
12031 {
12032    /* If we're supposed to be stopped -- stay stopped */
12033    if (monitor_thread == AST_PTHREADT_STOP)
12034       return 0;
12035    ast_mutex_lock(&monlock);
12036    if (monitor_thread == pthread_self()) {
12037       ast_mutex_unlock(&monlock);
12038       ast_log(LOG_WARNING, "Cannot kill myself\n");
12039       return -1;
12040    }
12041    if (monitor_thread != AST_PTHREADT_NULL) {
12042       /* Wake up the thread */
12043       pthread_kill(monitor_thread, SIGURG);
12044    } else {
12045       /* Start a new monitor */
12046       if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) {
12047          ast_mutex_unlock(&monlock);
12048          ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
12049          return -1;
12050       }
12051    }
12052    ast_mutex_unlock(&monlock);
12053    return 0;
12054 }
12055 
12056 #if defined(HAVE_PRI)
12057 static int pri_resolve_span(int *span, int channel, int offset, struct dahdi_spaninfo *si)
12058 {
12059    int x;
12060    int trunkgroup;
12061    /* Get appropriate trunk group if there is one */
12062    trunkgroup = pris[*span].mastertrunkgroup;
12063    if (trunkgroup) {
12064       /* Select a specific trunk group */
12065       for (x = 0; x < NUM_SPANS; x++) {
12066          if (pris[x].pri.trunkgroup == trunkgroup) {
12067             *span = x;
12068             return 0;
12069          }
12070       }
12071       ast_log(LOG_WARNING, "Channel %d on span %d configured to use nonexistent trunk group %d\n", channel, *span, trunkgroup);
12072       *span = -1;
12073    } else {
12074       if (pris[*span].pri.trunkgroup) {
12075          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);
12076          *span = -1;
12077       } else if (pris[*span].mastertrunkgroup) {
12078          ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is already part of trunk group %d\n", *span, pris[*span].mastertrunkgroup);
12079          *span = -1;
12080       } else {
12081          if (si->totalchans == 31) {
12082             /* E1 */
12083             pris[*span].dchannels[0] = 16 + offset;
12084          } else if (si->totalchans == 24) {
12085             /* T1 or J1 */
12086             pris[*span].dchannels[0] = 24 + offset;
12087          } else if (si->totalchans == 3) {
12088             /* BRI */
12089             pris[*span].dchannels[0] = 3 + offset;
12090          } else {
12091             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);
12092             *span = -1;
12093             return 0;
12094          }
12095          pris[*span].pri.span = *span + 1;
12096       }
12097    }
12098    return 0;
12099 }
12100 #endif   /* defined(HAVE_PRI) */
12101 
12102 #if defined(HAVE_PRI)
12103 static int pri_create_trunkgroup(int trunkgroup, int *channels)
12104 {
12105    struct dahdi_spaninfo si;
12106    struct dahdi_params p;
12107    int fd;
12108    int span;
12109    int ospan=0;
12110    int x,y;
12111    for (x = 0; x < NUM_SPANS; x++) {
12112       if (pris[x].pri.trunkgroup == trunkgroup) {
12113          ast_log(LOG_WARNING, "Trunk group %d already exists on span %d, Primary d-channel %d\n", trunkgroup, x + 1, pris[x].dchannels[0]);
12114          return -1;
12115       }
12116    }
12117    for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
12118       if (!channels[y])
12119          break;
12120       memset(&si, 0, sizeof(si));
12121       memset(&p, 0, sizeof(p));
12122       fd = open("/dev/dahdi/channel", O_RDWR);
12123       if (fd < 0) {
12124          ast_log(LOG_WARNING, "Failed to open channel: %s\n", strerror(errno));
12125          return -1;
12126       }
12127       x = channels[y];
12128       if (ioctl(fd, DAHDI_SPECIFY, &x)) {
12129          ast_log(LOG_WARNING, "Failed to specify channel %d: %s\n", channels[y], strerror(errno));
12130          close(fd);
12131          return -1;
12132       }
12133       if (ioctl(fd, DAHDI_GET_PARAMS, &p)) {
12134          ast_log(LOG_WARNING, "Failed to get channel parameters for channel %d: %s\n", channels[y], strerror(errno));
12135          return -1;
12136       }
12137       if (ioctl(fd, DAHDI_SPANSTAT, &si)) {
12138          ast_log(LOG_WARNING, "Failed go get span information on channel %d (span %d): %s\n", channels[y], p.spanno, strerror(errno));
12139          close(fd);
12140          return -1;
12141       }
12142       span = p.spanno - 1;
12143       if (pris[span].pri.trunkgroup) {
12144          ast_log(LOG_WARNING, "Span %d is already provisioned for trunk group %d\n", span + 1, pris[span].pri.trunkgroup);
12145          close(fd);
12146          return -1;
12147       }
12148       if (pris[span].pri.pvts[0]) {
12149          ast_log(LOG_WARNING, "Span %d is already provisioned with channels (implicit PRI maybe?)\n", span + 1);
12150          close(fd);
12151          return -1;
12152       }
12153       if (!y) {
12154          pris[span].pri.trunkgroup = trunkgroup;
12155          ospan = span;
12156       }
12157       pris[ospan].dchannels[y] = channels[y];
12158       pris[span].pri.span = span + 1;
12159       close(fd);
12160    }
12161    return 0;
12162 }
12163 #endif   /* defined(HAVE_PRI) */
12164 
12165 #if defined(HAVE_PRI)
12166 static int pri_create_spanmap(int span, int trunkgroup, int logicalspan)
12167 {
12168    if (pris[span].mastertrunkgroup) {
12169       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);
12170       return -1;
12171    }
12172    pris[span].mastertrunkgroup = trunkgroup;
12173    pris[span].prilogicalspan = logicalspan;
12174    return 0;
12175 }
12176 #endif   /* defined(HAVE_PRI) */
12177 
12178 #if defined(HAVE_SS7)
12179 static unsigned int parse_pointcode(const char *pcstring)
12180 {
12181    unsigned int code1, code2, code3;
12182    int numvals;
12183 
12184    numvals = sscanf(pcstring, "%30d-%30d-%30d", &code1, &code2, &code3);
12185    if (numvals == 1)
12186       return code1;
12187    if (numvals == 3)
12188       return (code1 << 16) | (code2 << 8) | code3;
12189 
12190    return 0;
12191 }
12192 #endif   /* defined(HAVE_SS7) */
12193 
12194 #if defined(HAVE_SS7)
12195 static struct dahdi_ss7 * ss7_resolve_linkset(int linkset)
12196 {
12197    if ((linkset < 0) || (linkset >= NUM_SPANS))
12198       return NULL;
12199    else
12200       return &linksets[linkset - 1];
12201 }
12202 #endif   /* defined(HAVE_SS7) */
12203 
12204 #ifdef HAVE_OPENR2
12205 static void dahdi_r2_destroy_links(void)
12206 {
12207    int i = 0;
12208    if (!r2links) {
12209       return;
12210    }
12211    for (; i < r2links_count; i++) {
12212       if (r2links[i]->r2master != AST_PTHREADT_NULL) {
12213          pthread_cancel(r2links[i]->r2master);
12214          pthread_join(r2links[i]->r2master, NULL);
12215          openr2_context_delete(r2links[i]->protocol_context);
12216       }
12217       ast_free(r2links[i]);
12218    }
12219    ast_free(r2links);
12220    r2links = NULL;
12221    r2links_count = 0;
12222 }
12223 
12224 /* This is an artificial convenient capacity, to keep at most a full E1 of channels in a single thread */
12225 #define R2_LINK_CAPACITY 30
12226 static struct dahdi_mfcr2 *dahdi_r2_get_link(const struct dahdi_chan_conf *conf)
12227 {
12228    struct dahdi_mfcr2 *new_r2link = NULL;
12229    struct dahdi_mfcr2 **new_r2links = NULL;
12230 
12231    /* Only create a new R2 link if 
12232       1. This is the first link requested
12233       2. Configuration changed 
12234       3. We got more channels than supported per link */
12235    if (!r2links_count ||
12236        memcmp(&conf->mfcr2, &r2links[r2links_count - 1]->conf, sizeof(conf->mfcr2)) ||
12237       (r2links[r2links_count - 1]->numchans == R2_LINK_CAPACITY)) {
12238       new_r2link = ast_calloc(1, sizeof(**r2links));
12239       if (!new_r2link) {
12240          ast_log(LOG_ERROR, "Cannot allocate R2 link!\n");
12241          return NULL;
12242       }
12243       new_r2links = ast_realloc(r2links, ((r2links_count + 1) * sizeof(*r2links)));
12244       if (!new_r2links) {
12245          ast_log(LOG_ERROR, "Cannot allocate R2 link!\n");
12246          ast_free(new_r2link);
12247          return NULL;
12248       }
12249       r2links = new_r2links;
12250       new_r2link->r2master = AST_PTHREADT_NULL;
12251       r2links[r2links_count] = new_r2link;
12252       r2links_count++;
12253       ast_log(LOG_DEBUG, "Created new R2 link!\n");
12254    }
12255    return r2links[r2links_count - 1];
12256 }
12257 
12258 static int dahdi_r2_set_context(struct dahdi_mfcr2 *r2_link, const struct dahdi_chan_conf *conf)
12259 {
12260    char tmplogdir[] = "/tmp";
12261    char logdir[OR2_MAX_PATH];
12262    int threshold = 0;
12263    int snres = 0;
12264    r2_link->protocol_context = openr2_context_new(NULL, &dahdi_r2_event_iface,
12265          &dahdi_r2_transcode_iface, conf->mfcr2.variant, conf->mfcr2.max_ani,
12266          conf->mfcr2.max_dnis);
12267    if (!r2_link->protocol_context) {
12268       return -1;
12269    }
12270    openr2_context_set_log_level(r2_link->protocol_context, conf->mfcr2.loglevel);
12271    openr2_context_set_ani_first(r2_link->protocol_context, conf->mfcr2.get_ani_first);
12272 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
12273    openr2_context_set_skip_category_request(r2_link->protocol_context, conf->mfcr2.skip_category_request);
12274 #endif
12275    openr2_context_set_mf_threshold(r2_link->protocol_context, threshold);
12276    openr2_context_set_mf_back_timeout(r2_link->protocol_context, conf->mfcr2.mfback_timeout);
12277    openr2_context_set_metering_pulse_timeout(r2_link->protocol_context, conf->mfcr2.metering_pulse_timeout);
12278    openr2_context_set_double_answer(r2_link->protocol_context, conf->mfcr2.double_answer);
12279    openr2_context_set_immediate_accept(r2_link->protocol_context, conf->mfcr2.immediate_accept);
12280    if (ast_strlen_zero(conf->mfcr2.logdir)) {
12281       if (openr2_context_set_log_directory(r2_link->protocol_context, tmplogdir)) {
12282          ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir);
12283       }
12284    } else {
12285       snres = snprintf(logdir, sizeof(logdir), "%s/%s/%s", ast_config_AST_LOG_DIR, "mfcr2", conf->mfcr2.logdir);
12286       if (snres >= sizeof(logdir)) {
12287          ast_log(LOG_ERROR, "MFC/R2 logging directory truncated, using %s\n", tmplogdir);
12288          if (openr2_context_set_log_directory(r2_link->protocol_context, tmplogdir)) {
12289             ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir);
12290          }
12291       } else {
12292          if (openr2_context_set_log_directory(r2_link->protocol_context, logdir)) {
12293             ast_log(LOG_ERROR, "Failed setting MFC/R2 log directory %s\n", logdir);
12294          }
12295       }
12296    }
12297    if (!ast_strlen_zero(conf->mfcr2.r2proto_file)) {
12298       if (openr2_context_configure_from_advanced_file(r2_link->protocol_context, conf->mfcr2.r2proto_file)) {
12299          ast_log(LOG_ERROR, "Failed to configure r2context from advanced configuration file %s\n", conf->mfcr2.r2proto_file);
12300       }
12301    }
12302    /* Save the configuration used to setup this link */
12303    memcpy(&r2_link->conf, conf, sizeof(r2_link->conf));
12304    return 0;
12305 }
12306 #endif
12307 
12308 /* converts a DAHDI sigtype to signalling as can be configured from
12309  * chan_dahdi.conf.
12310  * While both have basically the same values, this will later be the
12311  * place to add filters and sanity checks
12312  */
12313 static int sigtype_to_signalling(int sigtype)
12314 {
12315    return sigtype;
12316 }
12317 
12318 /*!
12319  * \internal
12320  * \brief Get file name and channel number from (subdir,number)
12321  *
12322  * \param subdir name of the subdirectory under /dev/dahdi/
12323  * \param channel name of device file under /dev/dahdi/<subdir>/
12324  * \param path buffer to put file name in
12325  * \param pathlen maximal length of path
12326  *
12327  * \retval minor number of dahdi channel.
12328  * \retval -errno on error.
12329  */
12330 static int device2chan(const char *subdir, int channel, char *path, int pathlen)
12331 {
12332    struct stat stbuf;
12333    int      num;
12334 
12335    snprintf(path, pathlen, "/dev/dahdi/%s/%d", subdir, channel);
12336    if (stat(path, &stbuf) < 0) {
12337       ast_log(LOG_ERROR, "stat(%s) failed: %s\n", path, strerror(errno));
12338       return -errno;
12339    }
12340    if (!S_ISCHR(stbuf.st_mode)) {
12341       ast_log(LOG_ERROR, "%s: Not a character device file\n", path);
12342       return -EINVAL;
12343    }
12344    num = minor(stbuf.st_rdev);
12345    ast_log(LOG_DEBUG, "%s -> %d\n", path, num);
12346    return num;
12347 
12348 }
12349 
12350 /*!
12351  * \internal
12352  * \brief Initialize/create a channel interface.
12353  *
12354  * \param channel Channel interface number to initialize/create.
12355  * \param conf Configuration parameters to initialize interface with.
12356  * \param reloading What we are doing now:
12357  * 0 - initial module load,
12358  * 1 - module reload,
12359  * 2 - module restart
12360  *
12361  * \retval Interface-pointer initialized/created
12362  * \retval NULL if error
12363  */
12364 static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf, int reloading)
12365 {
12366    /* Make a dahdi_pvt structure for this interface */
12367    struct dahdi_pvt *tmp;/*!< Current channel structure initializing */
12368    char fn[80];
12369    struct dahdi_bufferinfo bi;
12370 
12371    int res;
12372 #if defined(HAVE_PRI)
12373    int span = 0;
12374 #endif   /* defined(HAVE_PRI) */
12375    int here = 0;/*!< TRUE if the channel interface already exists. */
12376    int x;
12377    struct analog_pvt *analog_p = NULL;
12378    struct dahdi_params p;
12379 #if defined(HAVE_PRI)
12380    struct dahdi_spaninfo si;
12381    struct sig_pri_chan *pri_chan = NULL;
12382 #endif   /* defined(HAVE_PRI) */
12383 #if defined(HAVE_SS7)
12384    struct sig_ss7_chan *ss7_chan = NULL;
12385 #endif   /* defined(HAVE_SS7) */
12386 
12387    /* Search channel interface list to see if it already exists. */
12388    for (tmp = iflist; tmp; tmp = tmp->next) {
12389       if (!tmp->destroy) {
12390          if (tmp->channel == channel) {
12391             /* The channel interface already exists. */
12392             here = 1;
12393             break;
12394          }
12395          if (tmp->channel > channel) {
12396             /* No way it can be in the sorted list. */
12397             tmp = NULL;
12398             break;
12399          }
12400       }
12401    }
12402 
12403    if (!here && reloading != 1) {
12404       tmp = ast_calloc(1, sizeof(*tmp));
12405       if (!tmp) {
12406          return NULL;
12407       }
12408       tmp->cc_params = ast_cc_config_params_init();
12409       if (!tmp->cc_params) {
12410          ast_free(tmp);
12411          return NULL;
12412       }
12413       ast_mutex_init(&tmp->lock);
12414       ifcount++;
12415       for (x = 0; x < 3; x++)
12416          tmp->subs[x].dfd = -1;
12417       tmp->channel = channel;
12418       tmp->priindication_oob = conf->chan.priindication_oob;
12419    }
12420 
12421    if (tmp) {
12422       int chan_sig = conf->chan.sig;
12423 
12424       /* If there are variables in tmp before it is updated to match the new config, clear them */
12425       if (reloading && tmp->vars) {
12426          ast_variables_destroy(tmp->vars);
12427          tmp->vars = NULL;
12428       }
12429 
12430 
12431       if (!here) {
12432          /* Can only get here if this is a new channel interface being created. */
12433          if ((channel != CHAN_PSEUDO)) {
12434             int count = 0;
12435 
12436             snprintf(fn, sizeof(fn), "%d", channel);
12437             /* Open non-blocking */
12438             tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
12439             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 */
12440                usleep(1);
12441                tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
12442                count++;
12443             }
12444             /* Allocate a DAHDI structure */
12445             if (tmp->subs[SUB_REAL].dfd < 0) {
12446                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);
12447                destroy_dahdi_pvt(tmp);
12448                return NULL;
12449             }
12450             memset(&p, 0, sizeof(p));
12451             res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
12452             if (res < 0) {
12453                ast_log(LOG_ERROR, "Unable to get parameters: %s\n", strerror(errno));
12454                destroy_dahdi_pvt(tmp);
12455                return NULL;
12456             }
12457             if (conf->is_sig_auto)
12458                chan_sig = sigtype_to_signalling(p.sigtype);
12459             if (p.sigtype != (chan_sig & 0x3ffff)) {
12460                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));
12461                destroy_dahdi_pvt(tmp);
12462                return NULL;
12463             }
12464             tmp->law_default = p.curlaw;
12465             tmp->law = p.curlaw;
12466             tmp->span = p.spanno;
12467 #if defined(HAVE_PRI)
12468             span = p.spanno - 1;
12469 #endif   /* defined(HAVE_PRI) */
12470          } else {
12471             chan_sig = 0;
12472          }
12473          tmp->sig = chan_sig;
12474          tmp->outsigmod = conf->chan.outsigmod;
12475 
12476          if (analog_lib_handles(chan_sig, tmp->radio, tmp->oprmode)) {
12477             analog_p = analog_new(dahdisig_to_analogsig(chan_sig), &dahdi_analog_callbacks, tmp);
12478             if (!analog_p) {
12479                destroy_dahdi_pvt(tmp);
12480                return NULL;
12481             }
12482             tmp->sig_pvt = analog_p;
12483          }
12484 #if defined(HAVE_SS7)
12485          if (chan_sig == SIG_SS7) {
12486             struct dahdi_ss7 *ss7;
12487             int clear = 0;
12488 
12489             if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &clear)) {
12490                ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
12491                destroy_dahdi_pvt(tmp);
12492                return NULL;
12493             }
12494 
12495             ss7 = ss7_resolve_linkset(cur_linkset);
12496             if (!ss7) {
12497                ast_log(LOG_ERROR, "Unable to find linkset %d\n", cur_linkset);
12498                destroy_dahdi_pvt(tmp);
12499                return NULL;
12500             }
12501             ss7->ss7.span = cur_linkset;
12502             if (cur_cicbeginswith < 0) {
12503                ast_log(LOG_ERROR, "Need to set cicbeginswith for the channels!\n");
12504                destroy_dahdi_pvt(tmp);
12505                return NULL;
12506             }
12507             ss7_chan = sig_ss7_chan_new(tmp, &dahdi_ss7_callbacks, &ss7->ss7);
12508             if (!ss7_chan) {
12509                destroy_dahdi_pvt(tmp);
12510                return NULL;
12511             }
12512             tmp->sig_pvt = ss7_chan;
12513             tmp->ss7 = &ss7->ss7;
12514 
12515             ss7_chan->channel = tmp->channel;
12516             ss7_chan->cic = cur_cicbeginswith++;
12517 
12518             /* DB: Add CIC's DPC information */
12519             ss7_chan->dpc = cur_defaultdpc;
12520 
12521             ss7->ss7.pvts[ss7->ss7.numchans++] = ss7_chan;
12522 
12523             ast_copy_string(ss7->ss7.internationalprefix, conf->ss7.ss7.internationalprefix, sizeof(ss7->ss7.internationalprefix));
12524             ast_copy_string(ss7->ss7.nationalprefix, conf->ss7.ss7.nationalprefix, sizeof(ss7->ss7.nationalprefix));
12525             ast_copy_string(ss7->ss7.subscriberprefix, conf->ss7.ss7.subscriberprefix, sizeof(ss7->ss7.subscriberprefix));
12526             ast_copy_string(ss7->ss7.unknownprefix, conf->ss7.ss7.unknownprefix, sizeof(ss7->ss7.unknownprefix));
12527 
12528             ss7->ss7.called_nai = conf->ss7.ss7.called_nai;
12529             ss7->ss7.calling_nai = conf->ss7.ss7.calling_nai;
12530          }
12531 #endif   /* defined(HAVE_SS7) */
12532 #ifdef HAVE_OPENR2
12533          if (chan_sig == SIG_MFCR2) {
12534             struct dahdi_mfcr2 *r2_link;
12535             r2_link = dahdi_r2_get_link(conf);
12536             if (!r2_link) {
12537                ast_log(LOG_WARNING, "Cannot get another R2 DAHDI context!\n");
12538                destroy_dahdi_pvt(tmp);
12539                return NULL;
12540             }
12541             if (!r2_link->protocol_context && dahdi_r2_set_context(r2_link, conf)) {
12542                ast_log(LOG_ERROR, "Cannot create OpenR2 protocol context.\n");
12543                destroy_dahdi_pvt(tmp);
12544                return NULL;
12545             }
12546             if (r2_link->numchans == ARRAY_LEN(r2_link->pvts)) {
12547                ast_log(LOG_ERROR, "Cannot add more channels to this link!\n");
12548                destroy_dahdi_pvt(tmp);
12549                return NULL;
12550             }
12551             r2_link->pvts[r2_link->numchans++] = tmp;
12552             tmp->r2chan = openr2_chan_new_from_fd(r2_link->protocol_context,
12553                                         tmp->subs[SUB_REAL].dfd,
12554                                         NULL, NULL);
12555             if (!tmp->r2chan) {
12556                openr2_liberr_t err = openr2_context_get_last_error(r2_link->protocol_context);
12557                ast_log(LOG_ERROR, "Cannot create OpenR2 channel: %s\n", openr2_context_error_string(err));
12558                destroy_dahdi_pvt(tmp);
12559                return NULL;
12560             }
12561             tmp->mfcr2 = r2_link;
12562             if (conf->mfcr2.call_files) {
12563                openr2_chan_enable_call_files(tmp->r2chan);
12564             }
12565             openr2_chan_set_client_data(tmp->r2chan, tmp);
12566             /* cast seems to be needed to get rid of the annoying warning regarding format attribute  */
12567             openr2_chan_set_logging_func(tmp->r2chan, (openr2_logging_func_t)dahdi_r2_on_chan_log);
12568             openr2_chan_set_log_level(tmp->r2chan, conf->mfcr2.loglevel);
12569             tmp->mfcr2_category = conf->mfcr2.category;
12570             tmp->mfcr2_charge_calls = conf->mfcr2.charge_calls;
12571             tmp->mfcr2_allow_collect_calls = conf->mfcr2.allow_collect_calls;
12572             tmp->mfcr2_forced_release = conf->mfcr2.forced_release;
12573             tmp->mfcr2_accept_on_offer = conf->mfcr2.accept_on_offer;
12574             tmp->mfcr2call = 0;
12575             tmp->mfcr2_dnis_index = 0;
12576             tmp->mfcr2_ani_index = 0;
12577          }
12578 #endif
12579 #ifdef HAVE_PRI
12580          if (dahdi_sig_pri_lib_handles(chan_sig)) {
12581             int offset;
12582             int matchesdchan;
12583             int x,y;
12584             int myswitchtype = 0;
12585 
12586             offset = 0;
12587             if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &offset)) {
12588                ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
12589                destroy_dahdi_pvt(tmp);
12590                return NULL;
12591             }
12592             if (span >= NUM_SPANS) {
12593                ast_log(LOG_ERROR, "Channel %d does not lie on a span I know of (%d)\n", channel, span);
12594                destroy_dahdi_pvt(tmp);
12595                return NULL;
12596             } else {
12597                si.spanno = 0;
12598                if (ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SPANSTAT,&si) == -1) {
12599                   ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno));
12600                   destroy_dahdi_pvt(tmp);
12601                   return NULL;
12602                }
12603                /* Store the logical span first based upon the real span */
12604                tmp->logicalspan = pris[span].prilogicalspan;
12605                pri_resolve_span(&span, channel, (channel - p.chanpos), &si);
12606                if (span < 0) {
12607                   ast_log(LOG_WARNING, "Channel %d: Unable to find locate channel/trunk group!\n", channel);
12608                   destroy_dahdi_pvt(tmp);
12609                   return NULL;
12610                }
12611                myswitchtype = conf->pri.pri.switchtype;
12612                /* Make sure this isn't a d-channel */
12613                matchesdchan=0;
12614                for (x = 0; x < NUM_SPANS; x++) {
12615                   for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
12616                      if (pris[x].dchannels[y] == tmp->channel) {
12617                         matchesdchan = 1;
12618                         break;
12619                      }
12620                   }
12621                }
12622                if (!matchesdchan) {
12623                   if (pris[span].pri.nodetype && (pris[span].pri.nodetype != conf->pri.pri.nodetype)) {
12624                      ast_log(LOG_ERROR, "Span %d is already a %s node\n", span + 1, pri_node2str(pris[span].pri.nodetype));
12625                      destroy_dahdi_pvt(tmp);
12626                      return NULL;
12627                   }
12628                   if (pris[span].pri.switchtype && (pris[span].pri.switchtype != myswitchtype)) {
12629                      ast_log(LOG_ERROR, "Span %d is already a %s switch\n", span + 1, pri_switch2str(pris[span].pri.switchtype));
12630                      destroy_dahdi_pvt(tmp);
12631                      return NULL;
12632                   }
12633                   if ((pris[span].pri.dialplan) && (pris[span].pri.dialplan != conf->pri.pri.dialplan)) {
12634                      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));
12635                      destroy_dahdi_pvt(tmp);
12636                      return NULL;
12637                   }
12638                   if (!ast_strlen_zero(pris[span].pri.idledial) && strcmp(pris[span].pri.idledial, conf->pri.pri.idledial)) {
12639                      ast_log(LOG_ERROR, "Span %d already has idledial '%s'.\n", span + 1, conf->pri.pri.idledial);
12640                      destroy_dahdi_pvt(tmp);
12641                      return NULL;
12642                   }
12643                   if (!ast_strlen_zero(pris[span].pri.idleext) && strcmp(pris[span].pri.idleext, conf->pri.pri.idleext)) {
12644                      ast_log(LOG_ERROR, "Span %d already has idleext '%s'.\n", span + 1, conf->pri.pri.idleext);
12645                      destroy_dahdi_pvt(tmp);
12646                      return NULL;
12647                   }
12648                   if (pris[span].pri.minunused && (pris[span].pri.minunused != conf->pri.pri.minunused)) {
12649                      ast_log(LOG_ERROR, "Span %d already has minunused of %d.\n", span + 1, conf->pri.pri.minunused);
12650                      destroy_dahdi_pvt(tmp);
12651                      return NULL;
12652                   }
12653                   if (pris[span].pri.minidle && (pris[span].pri.minidle != conf->pri.pri.minidle)) {
12654                      ast_log(LOG_ERROR, "Span %d already has minidle of %d.\n", span + 1, conf->pri.pri.minidle);
12655                      destroy_dahdi_pvt(tmp);
12656                      return NULL;
12657                   }
12658                   if (pris[span].pri.numchans >= ARRAY_LEN(pris[span].pri.pvts)) {
12659                      ast_log(LOG_ERROR, "Unable to add channel %d: Too many channels in trunk group %d!\n", channel,
12660                         pris[span].pri.trunkgroup);
12661                      destroy_dahdi_pvt(tmp);
12662                      return NULL;
12663                   }
12664 
12665                   ast_debug(4, "Adding callbacks %p to chan %d\n", &dahdi_pri_callbacks, tmp->channel);
12666                   pri_chan = sig_pri_chan_new(tmp, &dahdi_pri_callbacks, &pris[span].pri, tmp->logicalspan, p.chanpos, pris[span].mastertrunkgroup);
12667                   if (!pri_chan) {
12668                      destroy_dahdi_pvt(tmp);
12669                      return NULL;
12670                   }
12671                   tmp->sig_pvt = pri_chan;
12672                   tmp->pri = &pris[span].pri;
12673 
12674                   tmp->priexclusive = conf->chan.priexclusive;
12675 
12676                   if (!tmp->pri->cc_params) {
12677                      tmp->pri->cc_params = ast_cc_config_params_init();
12678                      if (!tmp->pri->cc_params) {
12679                         destroy_dahdi_pvt(tmp);
12680                         return NULL;
12681                      }
12682                   }
12683                   ast_cc_copy_config_params(tmp->pri->cc_params,
12684                      conf->chan.cc_params);
12685 
12686                   pris[span].pri.sig = chan_sig;
12687                   pris[span].pri.nodetype = conf->pri.pri.nodetype;
12688                   pris[span].pri.switchtype = myswitchtype;
12689                   pris[span].pri.nsf = conf->pri.pri.nsf;
12690                   pris[span].pri.dialplan = conf->pri.pri.dialplan;
12691                   pris[span].pri.localdialplan = conf->pri.pri.localdialplan;
12692                   pris[span].pri.pvts[pris[span].pri.numchans++] = tmp->sig_pvt;
12693                   pris[span].pri.minunused = conf->pri.pri.minunused;
12694                   pris[span].pri.minidle = conf->pri.pri.minidle;
12695                   pris[span].pri.overlapdial = conf->pri.pri.overlapdial;
12696                   pris[span].pri.qsigchannelmapping = conf->pri.pri.qsigchannelmapping;
12697                   pris[span].pri.discardremoteholdretrieval = conf->pri.pri.discardremoteholdretrieval;
12698 #if defined(HAVE_PRI_SERVICE_MESSAGES)
12699                   pris[span].pri.enable_service_message_support = conf->pri.pri.enable_service_message_support;
12700 #endif   /* defined(HAVE_PRI_SERVICE_MESSAGES) */
12701 #ifdef HAVE_PRI_INBANDDISCONNECT
12702                   pris[span].pri.inbanddisconnect = conf->pri.pri.inbanddisconnect;
12703 #endif
12704 #if defined(HAVE_PRI_CALL_HOLD)
12705                   pris[span].pri.hold_disconnect_transfer =
12706                      conf->pri.pri.hold_disconnect_transfer;
12707 #endif   /* defined(HAVE_PRI_CALL_HOLD) */
12708 #if defined(HAVE_PRI_CCSS)
12709                   pris[span].pri.cc_ptmp_recall_mode =
12710                      conf->pri.pri.cc_ptmp_recall_mode;
12711                   pris[span].pri.cc_qsig_signaling_link_req =
12712                      conf->pri.pri.cc_qsig_signaling_link_req;
12713                   pris[span].pri.cc_qsig_signaling_link_rsp =
12714                      conf->pri.pri.cc_qsig_signaling_link_rsp;
12715 #endif   /* defined(HAVE_PRI_CCSS) */
12716 #if defined(HAVE_PRI_CALL_WAITING)
12717                   pris[span].pri.max_call_waiting_calls =
12718                      conf->pri.pri.max_call_waiting_calls;
12719                   pris[span].pri.allow_call_waiting_calls =
12720                      conf->pri.pri.allow_call_waiting_calls;
12721 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
12722                   pris[span].pri.transfer = conf->chan.transfer;
12723                   pris[span].pri.facilityenable = conf->pri.pri.facilityenable;
12724 #if defined(HAVE_PRI_L2_PERSISTENCE)
12725                   pris[span].pri.l2_persistence = conf->pri.pri.l2_persistence;
12726 #endif   /* defined(HAVE_PRI_L2_PERSISTENCE) */
12727 #if defined(HAVE_PRI_AOC_EVENTS)
12728                   pris[span].pri.aoc_passthrough_flag = conf->pri.pri.aoc_passthrough_flag;
12729                   pris[span].pri.aoce_delayhangup = conf->pri.pri.aoce_delayhangup;
12730 #endif   /* defined(HAVE_PRI_AOC_EVENTS) */
12731                   if (chan_sig == SIG_BRI_PTMP) {
12732                      pris[span].pri.layer1_ignored = conf->pri.pri.layer1_ignored;
12733                   } else {
12734                      /* Option does not apply to this line type. */
12735                      pris[span].pri.layer1_ignored = 0;
12736                   }
12737                   pris[span].pri.append_msn_to_user_tag = conf->pri.pri.append_msn_to_user_tag;
12738                   pris[span].pri.inband_on_setup_ack = conf->pri.pri.inband_on_setup_ack;
12739                   pris[span].pri.inband_on_proceeding = conf->pri.pri.inband_on_proceeding;
12740                   ast_copy_string(pris[span].pri.initial_user_tag, conf->chan.cid_tag, sizeof(pris[span].pri.initial_user_tag));
12741                   ast_copy_string(pris[span].pri.msn_list, conf->pri.pri.msn_list, sizeof(pris[span].pri.msn_list));
12742 #if defined(HAVE_PRI_MWI)
12743                   ast_copy_string(pris[span].pri.mwi_mailboxes,
12744                      conf->pri.pri.mwi_mailboxes,
12745                      sizeof(pris[span].pri.mwi_mailboxes));
12746 #endif   /* defined(HAVE_PRI_MWI) */
12747                   ast_copy_string(pris[span].pri.idledial, conf->pri.pri.idledial, sizeof(pris[span].pri.idledial));
12748                   ast_copy_string(pris[span].pri.idleext, conf->pri.pri.idleext, sizeof(pris[span].pri.idleext));
12749                   ast_copy_string(pris[span].pri.internationalprefix, conf->pri.pri.internationalprefix, sizeof(pris[span].pri.internationalprefix));
12750                   ast_copy_string(pris[span].pri.nationalprefix, conf->pri.pri.nationalprefix, sizeof(pris[span].pri.nationalprefix));
12751                   ast_copy_string(pris[span].pri.localprefix, conf->pri.pri.localprefix, sizeof(pris[span].pri.localprefix));
12752                   ast_copy_string(pris[span].pri.privateprefix, conf->pri.pri.privateprefix, sizeof(pris[span].pri.privateprefix));
12753                   ast_copy_string(pris[span].pri.unknownprefix, conf->pri.pri.unknownprefix, sizeof(pris[span].pri.unknownprefix));
12754                   pris[span].pri.resetinterval = conf->pri.pri.resetinterval;
12755 
12756                   for (x = 0; x < PRI_MAX_TIMERS; x++) {
12757                      pris[span].pri.pritimers[x] = conf->pri.pri.pritimers[x];
12758                   }
12759 
12760 #if defined(HAVE_PRI_CALL_WAITING)
12761                   /* Channel initial config parameters. */
12762                   pris[span].pri.ch_cfg.stripmsd = conf->chan.stripmsd;
12763                   pris[span].pri.ch_cfg.hidecallerid = conf->chan.hidecallerid;
12764                   pris[span].pri.ch_cfg.hidecalleridname = conf->chan.hidecalleridname;
12765                   pris[span].pri.ch_cfg.immediate = conf->chan.immediate;
12766                   pris[span].pri.ch_cfg.priexclusive = conf->chan.priexclusive;
12767                   pris[span].pri.ch_cfg.priindication_oob = conf->chan.priindication_oob;
12768                   pris[span].pri.ch_cfg.use_callerid = conf->chan.use_callerid;
12769                   pris[span].pri.ch_cfg.use_callingpres = conf->chan.use_callingpres;
12770                   ast_copy_string(pris[span].pri.ch_cfg.context, conf->chan.context, sizeof(pris[span].pri.ch_cfg.context));
12771                   ast_copy_string(pris[span].pri.ch_cfg.mohinterpret, conf->chan.mohinterpret, sizeof(pris[span].pri.ch_cfg.mohinterpret));
12772 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
12773                } else {
12774                   ast_log(LOG_ERROR, "Channel %d is reserved for D-channel.\n", p.chanpos);
12775                   destroy_dahdi_pvt(tmp);
12776                   return NULL;
12777                }
12778             }
12779          }
12780 #endif
12781       } else {
12782          /* already exists in interface list */
12783          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));
12784          chan_sig = tmp->sig;
12785          if (tmp->subs[SUB_REAL].dfd > -1) {
12786             memset(&p, 0, sizeof(p));
12787             res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
12788          }
12789       }
12790       /* Adjust starttime on loopstart and kewlstart trunks to reasonable values */
12791       switch (chan_sig) {
12792       case SIG_FXSKS:
12793       case SIG_FXSLS:
12794       case SIG_EM:
12795       case SIG_EM_E1:
12796       case SIG_EMWINK:
12797       case SIG_FEATD:
12798       case SIG_FEATDMF:
12799       case SIG_FEATDMF_TA:
12800       case SIG_FEATB:
12801       case SIG_E911:
12802       case SIG_SF:
12803       case SIG_SFWINK:
12804       case SIG_FGC_CAMA:
12805       case SIG_FGC_CAMAMF:
12806       case SIG_SF_FEATD:
12807       case SIG_SF_FEATDMF:
12808       case SIG_SF_FEATB:
12809          p.starttime = 250;
12810          break;
12811       }
12812 
12813       if (tmp->radio) {
12814          /* XXX Waiting to hear back from Jim if these should be adjustable XXX */
12815          p.channo = channel;
12816          p.rxwinktime = 1;
12817          p.rxflashtime = 1;
12818          p.starttime = 1;
12819          p.debouncetime = 5;
12820       } else {
12821          p.channo = channel;
12822          /* Override timing settings based on config file */
12823          if (conf->timing.prewinktime >= 0)
12824             p.prewinktime = conf->timing.prewinktime;
12825          if (conf->timing.preflashtime >= 0)
12826             p.preflashtime = conf->timing.preflashtime;
12827          if (conf->timing.winktime >= 0)
12828             p.winktime = conf->timing.winktime;
12829          if (conf->timing.flashtime >= 0)
12830             p.flashtime = conf->timing.flashtime;
12831          if (conf->timing.starttime >= 0)
12832             p.starttime = conf->timing.starttime;
12833          if (conf->timing.rxwinktime >= 0)
12834             p.rxwinktime = conf->timing.rxwinktime;
12835          if (conf->timing.rxflashtime >= 0)
12836             p.rxflashtime = conf->timing.rxflashtime;
12837          if (conf->timing.debouncetime >= 0)
12838             p.debouncetime = conf->timing.debouncetime;
12839       }
12840 
12841       /* don't set parms on a pseudo-channel */
12842       if (tmp->subs[SUB_REAL].dfd >= 0)
12843       {
12844          res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_PARAMS, &p);
12845          if (res < 0) {
12846             ast_log(LOG_ERROR, "Unable to set parameters: %s\n", strerror(errno));
12847             destroy_dahdi_pvt(tmp);
12848             return NULL;
12849          }
12850       }
12851 #if 1
12852       if (!here && (tmp->subs[SUB_REAL].dfd > -1)) {
12853          memset(&bi, 0, sizeof(bi));
12854          res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
12855          if (!res) {
12856             bi.txbufpolicy = conf->chan.buf_policy;
12857             bi.rxbufpolicy = conf->chan.buf_policy;
12858             bi.numbufs = conf->chan.buf_no;
12859             res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
12860             if (res < 0) {
12861                ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", channel, strerror(errno));
12862             }
12863          } else {
12864             ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", channel, strerror(errno));
12865          }
12866          tmp->buf_policy = conf->chan.buf_policy;
12867          tmp->buf_no = conf->chan.buf_no;
12868          tmp->usefaxbuffers = conf->chan.usefaxbuffers;
12869          tmp->faxbuf_policy = conf->chan.faxbuf_policy;
12870          tmp->faxbuf_no = conf->chan.faxbuf_no;
12871          /* This is not as gnarly as it may first appear.  If the ioctl above failed, we'd be setting
12872           * tmp->bufsize to zero which would cause subsequent faxbuffer-related ioctl calls to fail.
12873           * The reason the ioctl call above failed should to be determined before worrying about the
12874           * faxbuffer-related ioctl calls */
12875          tmp->bufsize = bi.bufsize;
12876       }
12877 #endif
12878       tmp->immediate = conf->chan.immediate;
12879       tmp->transfertobusy = conf->chan.transfertobusy;
12880       if (chan_sig & __DAHDI_SIG_FXS) {
12881          tmp->mwimonitor_fsk = conf->chan.mwimonitor_fsk;
12882          tmp->mwimonitor_neon = conf->chan.mwimonitor_neon;
12883          tmp->mwimonitor_rpas = conf->chan.mwimonitor_rpas;
12884       }
12885       tmp->ringt_base = ringt_base;
12886       tmp->firstradio = 0;
12887       if ((chan_sig == SIG_FXOKS) || (chan_sig == SIG_FXOLS) || (chan_sig == SIG_FXOGS))
12888          tmp->permcallwaiting = conf->chan.callwaiting;
12889       else
12890          tmp->permcallwaiting = 0;
12891       /* Flag to destroy the channel must be cleared on new mkif.  Part of changes for reload to work */
12892       tmp->destroy = 0;
12893       tmp->drings = conf->chan.drings;
12894 
12895       /* 10 is a nice default. */
12896       if (tmp->drings.ringnum[0].range == 0)
12897          tmp->drings.ringnum[0].range = 10;
12898       if (tmp->drings.ringnum[1].range == 0)
12899          tmp->drings.ringnum[1].range = 10;
12900       if (tmp->drings.ringnum[2].range == 0)
12901          tmp->drings.ringnum[2].range = 10;
12902 
12903       tmp->usedistinctiveringdetection = usedistinctiveringdetection;
12904       tmp->callwaitingcallerid = conf->chan.callwaitingcallerid;
12905       tmp->threewaycalling = conf->chan.threewaycalling;
12906       tmp->adsi = conf->chan.adsi;
12907       tmp->use_smdi = conf->chan.use_smdi;
12908       tmp->permhidecallerid = conf->chan.hidecallerid;
12909       tmp->hidecalleridname = conf->chan.hidecalleridname;
12910       tmp->callreturn = conf->chan.callreturn;
12911       tmp->echocancel = conf->chan.echocancel;
12912       tmp->echotraining = conf->chan.echotraining;
12913       tmp->pulse = conf->chan.pulse;
12914       if (tmp->echocancel.head.tap_length) {
12915          tmp->echocanbridged = conf->chan.echocanbridged;
12916       } else {
12917          if (conf->chan.echocanbridged)
12918             ast_log(LOG_NOTICE, "echocancelwhenbridged requires echocancel to be enabled; ignoring\n");
12919          tmp->echocanbridged = 0;
12920       }
12921       tmp->busydetect = conf->chan.busydetect;
12922       tmp->busycount = conf->chan.busycount;
12923       tmp->busycompare = conf->chan.busycompare;
12924       tmp->busytonelength = conf->chan.busytonelength;
12925       tmp->busyquietlength = conf->chan.busyquietlength;
12926       tmp->busyfuzziness = conf->chan.busyfuzziness;
12927       tmp->silencethreshold = conf->chan.silencethreshold;
12928       tmp->callprogress = conf->chan.callprogress;
12929       tmp->waitfordialtone = conf->chan.waitfordialtone;
12930       tmp->cancallforward = conf->chan.cancallforward;
12931       tmp->dtmfrelax = conf->chan.dtmfrelax;
12932       tmp->callwaiting = tmp->permcallwaiting;
12933       tmp->hidecallerid = tmp->permhidecallerid;
12934       tmp->channel = channel;
12935       tmp->stripmsd = conf->chan.stripmsd;
12936       tmp->use_callerid = conf->chan.use_callerid;
12937       tmp->cid_signalling = conf->chan.cid_signalling;
12938       tmp->cid_start = conf->chan.cid_start;
12939       tmp->dahditrcallerid = conf->chan.dahditrcallerid;
12940       tmp->restrictcid = conf->chan.restrictcid;
12941       tmp->use_callingpres = conf->chan.use_callingpres;
12942       if (tmp->usedistinctiveringdetection) {
12943          if (!tmp->use_callerid) {
12944             ast_log(LOG_NOTICE, "Distinctive Ring detect requires 'usecallerid' be on\n");
12945             tmp->use_callerid = 1;
12946          }
12947       }
12948 
12949       if (tmp->cid_signalling == CID_SIG_SMDI) {
12950          if (!tmp->use_smdi) {
12951             ast_log(LOG_WARNING, "SMDI callerid requires SMDI to be enabled, enabling...\n");
12952             tmp->use_smdi = 1;
12953          }
12954       }
12955       if (tmp->use_smdi) {
12956          tmp->smdi_iface = ast_smdi_interface_find(conf->smdi_port);
12957          if (!(tmp->smdi_iface)) {
12958             ast_log(LOG_ERROR, "Invalid SMDI port specfied, disabling SMDI support\n");
12959             tmp->use_smdi = 0;
12960          }
12961       }
12962 
12963       ast_copy_string(tmp->accountcode, conf->chan.accountcode, sizeof(tmp->accountcode));
12964       tmp->amaflags = conf->chan.amaflags;
12965       if (!here) {
12966          tmp->confno = -1;
12967          tmp->propconfno = -1;
12968       }
12969       tmp->canpark = conf->chan.canpark;
12970       tmp->transfer = conf->chan.transfer;
12971       ast_copy_string(tmp->defcontext,conf->chan.context,sizeof(tmp->defcontext));
12972       ast_copy_string(tmp->language, conf->chan.language, sizeof(tmp->language));
12973       ast_copy_string(tmp->mohinterpret, conf->chan.mohinterpret, sizeof(tmp->mohinterpret));
12974       ast_copy_string(tmp->mohsuggest, conf->chan.mohsuggest, sizeof(tmp->mohsuggest));
12975       ast_copy_string(tmp->context, conf->chan.context, sizeof(tmp->context));
12976       ast_copy_string(tmp->parkinglot, conf->chan.parkinglot, sizeof(tmp->parkinglot));
12977       tmp->cid_ton = 0;
12978       if (analog_lib_handles(tmp->sig, tmp->radio, tmp->oprmode)) {
12979          ast_copy_string(tmp->cid_num, conf->chan.cid_num, sizeof(tmp->cid_num));
12980          ast_copy_string(tmp->cid_name, conf->chan.cid_name, sizeof(tmp->cid_name));
12981       } else {
12982          tmp->cid_num[0] = '\0';
12983          tmp->cid_name[0] = '\0';
12984       }
12985 #if defined(HAVE_PRI)
12986       if (dahdi_sig_pri_lib_handles(tmp->sig)) {
12987          tmp->cid_tag[0] = '\0';
12988       } else
12989 #endif   /* defined(HAVE_PRI) */
12990       {
12991          ast_copy_string(tmp->cid_tag, conf->chan.cid_tag, sizeof(tmp->cid_tag));
12992       }
12993       tmp->cid_subaddr[0] = '\0';
12994       ast_copy_string(tmp->mailbox, conf->chan.mailbox, sizeof(tmp->mailbox));
12995       if (channel != CHAN_PSEUDO && !ast_strlen_zero(tmp->mailbox)) {
12996          char *mailbox, *context;
12997          mailbox = context = ast_strdupa(tmp->mailbox);
12998          strsep(&context, "@");
12999          if (ast_strlen_zero(context))
13000             context = "default";
13001          tmp->mwi_event_sub = ast_event_subscribe(AST_EVENT_MWI, mwi_event_cb, "Dahdi MWI subscription", NULL,
13002             AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
13003             AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
13004             AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS,
13005             AST_EVENT_IE_END);
13006       }
13007 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
13008       tmp->mwisend_setting = conf->chan.mwisend_setting;
13009       tmp->mwisend_fsk  = conf->chan.mwisend_fsk;
13010       tmp->mwisend_rpas = conf->chan.mwisend_rpas;
13011 #endif
13012 
13013       tmp->group = conf->chan.group;
13014       tmp->callgroup = conf->chan.callgroup;
13015       tmp->pickupgroup= conf->chan.pickupgroup;
13016       if (conf->chan.vars) {
13017          struct ast_variable *v, *tmpvar;
13018                    for (v = conf->chan.vars ; v ; v = v->next) {
13019                          if ((tmpvar = ast_variable_new(v->name, v->value, v->file))) {
13020                                   tmpvar->next = tmp->vars;
13021                                    tmp->vars = tmpvar;
13022                            }
13023                   }
13024       }
13025       tmp->cid_rxgain = conf->chan.cid_rxgain;
13026       tmp->rxgain = conf->chan.rxgain;
13027       tmp->txgain = conf->chan.txgain;
13028       tmp->txdrc = conf->chan.txdrc;
13029       tmp->rxdrc = conf->chan.rxdrc;
13030       tmp->tonezone = conf->chan.tonezone;
13031       if (tmp->subs[SUB_REAL].dfd > -1) {
13032          set_actual_gain(tmp->subs[SUB_REAL].dfd, tmp->rxgain, tmp->txgain, tmp->rxdrc, tmp->txdrc, tmp->law);
13033          if (tmp->dsp)
13034             ast_dsp_set_digitmode(tmp->dsp, DSP_DIGITMODE_DTMF | tmp->dtmfrelax);
13035          update_conf(tmp);
13036          if (!here) {
13037             switch (chan_sig) {
13038             case SIG_PRI_LIB_HANDLE_CASES:
13039             case SIG_SS7:
13040             case SIG_MFCR2:
13041                break;
13042             default:
13043                /* Hang it up to be sure it's good */
13044                dahdi_set_hook(tmp->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
13045                break;
13046             }
13047          }
13048          ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SETTONEZONE,&tmp->tonezone);
13049          if ((res = get_alarms(tmp)) != DAHDI_ALARM_NONE) {
13050             /* the dchannel is down so put the channel in alarm */
13051             switch (tmp->sig) {
13052 #ifdef HAVE_PRI
13053             case SIG_PRI_LIB_HANDLE_CASES:
13054                sig_pri_set_alarm(tmp->sig_pvt, 1);
13055                break;
13056 #endif
13057 #if defined(HAVE_SS7)
13058             case SIG_SS7:
13059                sig_ss7_set_alarm(tmp->sig_pvt, 1);
13060                break;
13061 #endif   /* defined(HAVE_SS7) */
13062             default:
13063                /* The only sig submodule left should be sig_analog. */
13064                analog_p = tmp->sig_pvt;
13065                if (analog_p) {
13066                   analog_p->inalarm = 1;
13067                }
13068                tmp->inalarm = 1;
13069                break;
13070             }
13071             handle_alarms(tmp, res);
13072          }
13073       }
13074 
13075       tmp->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
13076       tmp->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
13077       tmp->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
13078       tmp->sendcalleridafter = conf->chan.sendcalleridafter;
13079       ast_cc_copy_config_params(tmp->cc_params, conf->chan.cc_params);
13080 
13081       if (!here) {
13082          tmp->locallyblocked = 0;
13083          tmp->remotelyblocked = 0;
13084          switch (tmp->sig) {
13085 #if defined(HAVE_PRI)
13086          case SIG_PRI_LIB_HANDLE_CASES:
13087             tmp->inservice = 1;/* Inservice until actually implemented. */
13088 #if defined(HAVE_PRI_SERVICE_MESSAGES)
13089             ((struct sig_pri_chan *) tmp->sig_pvt)->service_status = 0;
13090             if (chan_sig == SIG_PRI) {
13091                char db_chan_name[20];
13092                char db_answer[5];
13093 
13094                /*
13095                 * Initialize the active out-of-service status
13096                 * and delete any record if the feature is not enabled.
13097                 */
13098                snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, tmp->span, tmp->channel);
13099                if (!ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) {
13100                   unsigned *why;
13101 
13102                   why = &((struct sig_pri_chan *) tmp->sig_pvt)->service_status;
13103                   if (tmp->pri->enable_service_message_support) {
13104                      char state;
13105 
13106                      sscanf(db_answer, "%1c:%30u", &state, why);
13107 
13108                      /* Ensure that only the implemented bits could be set.*/
13109                      *why &= (SRVST_NEAREND | SRVST_FAREND);
13110                   }
13111                   if (!*why) {
13112                      ast_db_del(db_chan_name, SRVST_DBKEY);
13113                   }
13114                }
13115             }
13116 #endif   /* defined(HAVE_PRI_SERVICE_MESSAGES) */
13117             break;
13118 #endif   /* defined(HAVE_PRI) */
13119 #if defined(HAVE_SS7)
13120          case SIG_SS7:
13121             tmp->inservice = 0;
13122             break;
13123 #endif   /* defined(HAVE_SS7) */
13124          default:
13125              /* We default to in service on protocols that don't have a reset */
13126             tmp->inservice = 1;
13127             break;
13128          }
13129       }
13130 
13131       switch (tmp->sig) {
13132 #if defined(HAVE_PRI)
13133       case SIG_PRI_LIB_HANDLE_CASES:
13134          if (pri_chan) {
13135             pri_chan->channel = tmp->channel;
13136             pri_chan->hidecallerid = tmp->hidecallerid;
13137             pri_chan->hidecalleridname = tmp->hidecalleridname;
13138             pri_chan->immediate = tmp->immediate;
13139             pri_chan->inalarm = tmp->inalarm;
13140             pri_chan->priexclusive = tmp->priexclusive;
13141             pri_chan->priindication_oob = tmp->priindication_oob;
13142             pri_chan->use_callerid = tmp->use_callerid;
13143             pri_chan->use_callingpres = tmp->use_callingpres;
13144             ast_copy_string(pri_chan->context, tmp->context,
13145                sizeof(pri_chan->context));
13146             ast_copy_string(pri_chan->mohinterpret, tmp->mohinterpret,
13147                sizeof(pri_chan->mohinterpret));
13148             pri_chan->stripmsd = tmp->stripmsd;
13149          }
13150          break;
13151 #endif   /* defined(HAVE_PRI) */
13152 #if defined(HAVE_SS7)
13153       case SIG_SS7:
13154          if (ss7_chan) {
13155             ss7_chan->inalarm = tmp->inalarm;
13156 
13157             ss7_chan->stripmsd = tmp->stripmsd;
13158             ss7_chan->hidecallerid = tmp->hidecallerid;
13159             ss7_chan->use_callerid = tmp->use_callerid;
13160             ss7_chan->use_callingpres = tmp->use_callingpres;
13161             ss7_chan->immediate = tmp->immediate;
13162             ss7_chan->locallyblocked = tmp->locallyblocked;
13163             ss7_chan->remotelyblocked = tmp->remotelyblocked;
13164             ast_copy_string(ss7_chan->context, tmp->context,
13165                sizeof(ss7_chan->context));
13166             ast_copy_string(ss7_chan->mohinterpret, tmp->mohinterpret,
13167                sizeof(ss7_chan->mohinterpret));
13168          }
13169          break;
13170 #endif   /* defined(HAVE_SS7) */
13171       default:
13172          /* The only sig submodule left should be sig_analog. */
13173          analog_p = tmp->sig_pvt;
13174          if (analog_p) {
13175             analog_p->channel = tmp->channel;
13176             analog_p->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
13177             analog_p->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
13178             analog_p->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
13179             analog_p->permcallwaiting = conf->chan.callwaiting; /* permcallwaiting possibly modified in analog_config_complete */
13180             analog_p->callreturn = conf->chan.callreturn;
13181             analog_p->cancallforward = conf->chan.cancallforward;
13182             analog_p->canpark = conf->chan.canpark;
13183             analog_p->dahditrcallerid = conf->chan.dahditrcallerid;
13184             analog_p->immediate = conf->chan.immediate;
13185             analog_p->permhidecallerid = conf->chan.permhidecallerid;
13186             analog_p->pulse = conf->chan.pulse;
13187             analog_p->threewaycalling = conf->chan.threewaycalling;
13188             analog_p->transfer = conf->chan.transfer;
13189             analog_p->transfertobusy = conf->chan.transfertobusy;
13190             analog_p->use_callerid = tmp->use_callerid;
13191             analog_p->use_smdi = tmp->use_smdi;
13192             analog_p->smdi_iface = tmp->smdi_iface;
13193             analog_p->outsigmod = ANALOG_SIG_NONE;
13194             analog_p->echotraining = conf->chan.echotraining;
13195             analog_p->cid_signalling = conf->chan.cid_signalling;
13196             analog_p->stripmsd = conf->chan.stripmsd;
13197             switch (conf->chan.cid_start) {
13198             case CID_START_POLARITY:
13199                analog_p->cid_start = ANALOG_CID_START_POLARITY;
13200                break;
13201             case CID_START_POLARITY_IN:
13202                analog_p->cid_start = ANALOG_CID_START_POLARITY_IN;
13203                break;
13204             case CID_START_DTMF_NOALERT:
13205                analog_p->cid_start = ANALOG_CID_START_DTMF_NOALERT;
13206                break;
13207             default:
13208                analog_p->cid_start = ANALOG_CID_START_RING;
13209                break;
13210             }
13211             analog_p->callwaitingcallerid = conf->chan.callwaitingcallerid;
13212             analog_p->ringt = conf->chan.ringt;
13213             analog_p->ringt_base = ringt_base;
13214             analog_p->onhooktime = time(NULL);
13215             if (chan_sig & __DAHDI_SIG_FXO) {
13216                memset(&p, 0, sizeof(p));
13217                res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
13218                if (!res) {
13219                   analog_p->fxsoffhookstate = p.rxisoffhook;
13220                }
13221 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
13222                res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_VMWI_CONFIG, &tmp->mwisend_setting);
13223 #endif
13224             }
13225             analog_p->msgstate = -1;
13226 
13227             ast_copy_string(analog_p->mohsuggest, conf->chan.mohsuggest, sizeof(analog_p->mohsuggest));
13228             ast_copy_string(analog_p->cid_num, conf->chan.cid_num, sizeof(analog_p->cid_num));
13229             ast_copy_string(analog_p->cid_name, conf->chan.cid_name, sizeof(analog_p->cid_name));
13230 
13231             analog_config_complete(analog_p);
13232          }
13233          break;
13234       }
13235 #if defined(HAVE_PRI)
13236       if (tmp->channel == CHAN_PSEUDO) {
13237          /*
13238           * Save off pseudo channel buffer policy values for dynamic creation of
13239           * no B channel interfaces.
13240           */
13241          dahdi_pseudo_parms.buf_no = tmp->buf_no;
13242          dahdi_pseudo_parms.buf_policy = tmp->buf_policy;
13243          dahdi_pseudo_parms.faxbuf_no = tmp->faxbuf_no;
13244          dahdi_pseudo_parms.faxbuf_policy = tmp->faxbuf_policy;
13245       }
13246 #endif   /* defined(HAVE_PRI) */
13247    }
13248    if (tmp && !here) {
13249       /* Add the new channel interface to the sorted channel interface list. */
13250       dahdi_iflist_insert(tmp);
13251    }
13252    return tmp;
13253 }
13254 
13255 static int is_group_or_channel_match(struct dahdi_pvt *p, int span, ast_group_t groupmatch, int *groupmatched, int channelmatch, int *channelmatched)
13256 {
13257 #if defined(HAVE_PRI)
13258    if (0 < span) {
13259       /* The channel must be on the specified PRI span. */
13260       if (!p->pri || p->pri->span != span) {
13261          return 0;
13262       }
13263       if (!groupmatch && channelmatch == -1) {
13264          /* Match any group since it only needs to be on the PRI span. */
13265          *groupmatched = 1;
13266          return 1;
13267       }
13268    }
13269 #endif   /* defined(HAVE_PRI) */
13270    /* check group matching */
13271    if (groupmatch) {
13272       if ((p->group & groupmatch) != groupmatch)
13273          /* Doesn't match the specified group, try the next one */
13274          return 0;
13275       *groupmatched = 1;
13276    }
13277    /* Check to see if we have a channel match */
13278    if (channelmatch != -1) {
13279       if (p->channel != channelmatch)
13280          /* Doesn't match the specified channel, try the next one */
13281          return 0;
13282       *channelmatched = 1;
13283    }
13284 
13285    return 1;
13286 }
13287 
13288 static int available(struct dahdi_pvt **pvt, int is_specific_channel)
13289 {
13290    struct dahdi_pvt *p = *pvt;
13291 
13292    if (p->inalarm)
13293       return 0;
13294 
13295    if (analog_lib_handles(p->sig, p->radio, p->oprmode))
13296       return analog_available(p->sig_pvt);
13297 
13298    switch (p->sig) {
13299 #if defined(HAVE_PRI)
13300    case SIG_PRI_LIB_HANDLE_CASES:
13301       {
13302          struct sig_pri_chan *pvt_chan;
13303          int res;
13304 
13305          pvt_chan = p->sig_pvt;
13306          res = sig_pri_available(&pvt_chan, is_specific_channel);
13307          *pvt = pvt_chan->chan_pvt;
13308          return res;
13309       }
13310 #endif   /* defined(HAVE_PRI) */
13311 #if defined(HAVE_SS7)
13312    case SIG_SS7:
13313       return sig_ss7_available(p->sig_pvt);
13314 #endif   /* defined(HAVE_SS7) */
13315    default:
13316       break;
13317    }
13318 
13319    if (p->locallyblocked || p->remotelyblocked) {
13320       return 0;
13321    }
13322 
13323    /* If no owner definitely available */
13324    if (!p->owner) {
13325 #ifdef HAVE_OPENR2
13326       /* Trust MFC/R2 */
13327       if (p->mfcr2) {
13328          if (p->mfcr2call) {
13329             return 0;
13330          } else {
13331             return 1;
13332          }
13333       }
13334 #endif
13335       return 1;
13336    }
13337 
13338    return 0;
13339 }
13340 
13341 #if defined(HAVE_PRI)
13342 #if defined(HAVE_PRI_CALL_WAITING)
13343 /*!
13344  * \internal
13345  * \brief Init the private channel configuration using the span controller.
13346  * \since 1.8
13347  *
13348  * \param priv Channel to init the configuration.
13349  * \param pri sig_pri PRI control structure.
13350  *
13351  * \note Assumes the pri->lock is already obtained.
13352  *
13353  * \return Nothing
13354  */
13355 static void my_pri_init_config(void *priv, struct sig_pri_span *pri)
13356 {
13357    struct dahdi_pvt *pvt = priv;
13358 
13359    pvt->stripmsd = pri->ch_cfg.stripmsd;
13360    pvt->hidecallerid = pri->ch_cfg.hidecallerid;
13361    pvt->hidecalleridname = pri->ch_cfg.hidecalleridname;
13362    pvt->immediate = pri->ch_cfg.immediate;
13363    pvt->priexclusive = pri->ch_cfg.priexclusive;
13364    pvt->priindication_oob = pri->ch_cfg.priindication_oob;
13365    pvt->use_callerid = pri->ch_cfg.use_callerid;
13366    pvt->use_callingpres = pri->ch_cfg.use_callingpres;
13367    ast_copy_string(pvt->context, pri->ch_cfg.context, sizeof(pvt->context));
13368    ast_copy_string(pvt->mohinterpret, pri->ch_cfg.mohinterpret, sizeof(pvt->mohinterpret));
13369 }
13370 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
13371 #endif   /* defined(HAVE_PRI) */
13372 
13373 #if defined(HAVE_PRI)
13374 /*!
13375  * \internal
13376  * \brief Create a no B channel interface.
13377  * \since 1.8
13378  *
13379  * \param pri sig_pri span controller to add interface.
13380  *
13381  * \note Assumes the pri->lock is already obtained.
13382  *
13383  * \retval array-index into private pointer array on success.
13384  * \retval -1 on error.
13385  */
13386 static int dahdi_new_pri_nobch_channel(struct sig_pri_span *pri)
13387 {
13388    int pvt_idx;
13389    int res;
13390    unsigned idx;
13391    struct dahdi_pvt *pvt;
13392    struct sig_pri_chan *chan;
13393    struct dahdi_bufferinfo bi;
13394 
13395    static int nobch_channel = CHAN_PSEUDO;
13396 
13397    /* Find spot in the private pointer array for new interface. */
13398    for (pvt_idx = 0; pvt_idx < pri->numchans; ++pvt_idx) {
13399       if (!pri->pvts[pvt_idx]) {
13400          break;
13401       }
13402    }
13403    if (pri->numchans == pvt_idx) {
13404       if (ARRAY_LEN(pri->pvts) <= pvt_idx) {
13405          ast_log(LOG_ERROR, "Unable to add a no-B-channel interface!\n");
13406          return -1;
13407       }
13408 
13409       /* Add new spot to the private pointer array. */
13410       pri->pvts[pvt_idx] = NULL;
13411       ++pri->numchans;
13412    }
13413 
13414    pvt = ast_calloc(1, sizeof(*pvt));
13415    if (!pvt) {
13416       return -1;
13417    }
13418    pvt->cc_params = ast_cc_config_params_init();
13419    if (!pvt->cc_params) {
13420       ast_free(pvt);
13421       return -1;
13422    }
13423    ast_mutex_init(&pvt->lock);
13424    for (idx = 0; idx < ARRAY_LEN(pvt->subs); ++idx) {
13425       pvt->subs[idx].dfd = -1;
13426    }
13427    pvt->buf_no = dahdi_pseudo_parms.buf_no;
13428    pvt->buf_policy = dahdi_pseudo_parms.buf_policy;
13429    pvt->faxbuf_no = dahdi_pseudo_parms.faxbuf_no;
13430    pvt->faxbuf_policy = dahdi_pseudo_parms.faxbuf_policy;
13431 
13432    chan = sig_pri_chan_new(pvt, &dahdi_pri_callbacks, pri, 0, 0, 0);
13433    if (!chan) {
13434       destroy_dahdi_pvt(pvt);
13435       return -1;
13436    }
13437    chan->no_b_channel = 1;
13438 
13439    /*
13440     * Pseudo channel companding law.
13441     * Needed for outgoing call waiting calls.
13442     * XXX May need to make this determined by switchtype or user option.
13443     */
13444    pvt->law_default = DAHDI_LAW_ALAW;
13445 
13446    pvt->sig = pri->sig;
13447    pvt->outsigmod = -1;
13448    pvt->pri = pri;
13449    pvt->sig_pvt = chan;
13450    pri->pvts[pvt_idx] = chan;
13451 
13452    pvt->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo");
13453    if (pvt->subs[SUB_REAL].dfd < 0) {
13454       ast_log(LOG_ERROR, "Unable to open no B channel interface pseudo channel: %s\n",
13455          strerror(errno));
13456       destroy_dahdi_pvt(pvt);
13457       return -1;
13458    }
13459    memset(&bi, 0, sizeof(bi));
13460    res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
13461    if (!res) {
13462       pvt->bufsize = bi.bufsize;
13463       bi.txbufpolicy = pvt->buf_policy;
13464       bi.rxbufpolicy = pvt->buf_policy;
13465       bi.numbufs = pvt->buf_no;
13466       res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
13467       if (res < 0) {
13468          ast_log(LOG_WARNING,
13469             "Unable to set buffer policy on no B channel interface: %s\n",
13470             strerror(errno));
13471       }
13472    } else
13473       ast_log(LOG_WARNING,
13474          "Unable to check buffer policy on no B channel interface: %s\n",
13475          strerror(errno));
13476 
13477    --nobch_channel;
13478    if (CHAN_PSEUDO < nobch_channel) {
13479       nobch_channel = CHAN_PSEUDO - 1;
13480    }
13481    pvt->channel = nobch_channel;
13482    pvt->span = pri->span;
13483    chan->channel = pvt->channel;
13484 
13485    dahdi_nobch_insert(pri, pvt);
13486 
13487    return pvt_idx;
13488 }
13489 #endif   /* defined(HAVE_PRI) */
13490 
13491 /* This function can *ONLY* be used for copying pseudo (CHAN_PSEUDO) private
13492    structures; it makes no attempt to safely copy regular channel private
13493    structures that might contain reference-counted object pointers and other
13494    scary bits
13495 */
13496 static struct dahdi_pvt *duplicate_pseudo(struct dahdi_pvt *src)
13497 {
13498    struct dahdi_pvt *p;
13499    struct dahdi_bufferinfo bi;
13500    int res;
13501 
13502    p = ast_malloc(sizeof(*p));
13503    if (!p) {
13504       return NULL;
13505    }
13506    *p = *src;
13507 
13508    /* Must deep copy the cc_params. */
13509    p->cc_params = ast_cc_config_params_init();
13510    if (!p->cc_params) {
13511       ast_free(p);
13512       return NULL;
13513    }
13514    ast_cc_copy_config_params(p->cc_params, src->cc_params);
13515 
13516    p->which_iflist = DAHDI_IFLIST_NONE;
13517    p->next = NULL;
13518    p->prev = NULL;
13519    ast_mutex_init(&p->lock);
13520    p->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo");
13521    if (p->subs[SUB_REAL].dfd < 0) {
13522       ast_log(LOG_ERROR, "Unable to dup channel: %s\n", strerror(errno));
13523       destroy_dahdi_pvt(p);
13524       return NULL;
13525    }
13526    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
13527    if (!res) {
13528       bi.txbufpolicy = src->buf_policy;
13529       bi.rxbufpolicy = src->buf_policy;
13530       bi.numbufs = src->buf_no;
13531       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
13532       if (res < 0) {
13533          ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel: %s\n", strerror(errno));
13534       }
13535    } else
13536       ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel: %s\n", strerror(errno));
13537    p->destroy = 1;
13538    dahdi_iflist_insert(p);
13539    return p;
13540 }
13541 
13542 struct dahdi_starting_point {
13543    /*! Group matching mask.  Zero if not specified. */
13544    ast_group_t groupmatch;
13545    /*! DAHDI channel to match with.  -1 if not specified. */
13546    int channelmatch;
13547    /*! Round robin saved search location index. (Valid if roundrobin TRUE) */
13548    int rr_starting_point;
13549    /*! ISDN span where channels can be picked (Zero if not specified) */
13550    int span;
13551    /*! Analog channel distinctive ring cadance index. */
13552    int cadance;
13553    /*! Dialing option. c/r/d if present and valid. */
13554    char opt;
13555    /*! TRUE if to search the channel list backwards. */
13556    char backwards;
13557    /*! TRUE if search is done with round robin sequence. */
13558    char roundrobin;
13559 };
13560 static struct dahdi_pvt *determine_starting_point(const char *data, struct dahdi_starting_point *param)
13561 {
13562    char *dest;
13563    char *s;
13564    int x;
13565    int res = 0;
13566    struct dahdi_pvt *p;
13567    char *subdir = NULL;
13568    AST_DECLARE_APP_ARGS(args,
13569       AST_APP_ARG(group);  /* channel/group token */
13570       //AST_APP_ARG(ext);  /* extension token */
13571       //AST_APP_ARG(opts); /* options token */
13572       AST_APP_ARG(other);  /* Any remining unused arguments */
13573    );
13574 
13575    /*
13576     * data is ---v
13577     * Dial(DAHDI/pseudo[/extension[/options]])
13578     * Dial(DAHDI/<channel#>[c|r<cadance#>|d][/extension[/options]])
13579     * Dial(DAHDI/<subdir>!<channel#>[c|r<cadance#>|d][/extension[/options]])
13580     * Dial(DAHDI/i<span>[/extension[/options]])
13581     * Dial(DAHDI/[i<span>-](g|G|r|R)<group#(0-63)>[c|r<cadance#>|d][/extension[/options]])
13582     *
13583     * i - ISDN span channel restriction.
13584     *     Used by CC to ensure that the CC recall goes out the same span.
13585     *     Also to make ISDN channel names dialable when the sequence number
13586     *     is stripped off.  (Used by DTMF attended transfer feature.)
13587     *
13588     * g - channel group allocation search forward
13589     * G - channel group allocation search backward
13590     * r - channel group allocation round robin search forward
13591     * R - channel group allocation round robin search backward
13592     *
13593     * c - Wait for DTMF digit to confirm answer
13594     * r<cadance#> - Set distintive ring cadance number
13595     * d - Force bearer capability for ISDN/SS7 call to digital.
13596     */
13597 
13598    if (data) {
13599       dest = ast_strdupa(data);
13600    } else {
13601       ast_log(LOG_WARNING, "Channel requested with no data\n");
13602       return NULL;
13603    }
13604    AST_NONSTANDARD_APP_ARGS(args, dest, '/');
13605    if (!args.argc || ast_strlen_zero(args.group)) {
13606       ast_log(LOG_WARNING, "No channel/group specified\n");
13607       return NULL;
13608    }
13609 
13610    /* Initialize the output parameters */
13611    memset(param, 0, sizeof(*param));
13612    param->channelmatch = -1;
13613 
13614    if (strchr(args.group, '!') != NULL) {
13615       char *prev = args.group;
13616       while ((s = strchr(prev, '!')) != NULL) {
13617          *s++ = '/';
13618          prev = s;
13619       }
13620       *(prev - 1) = '\0';
13621       subdir = args.group;
13622       args.group = prev;
13623    } else if (args.group[0] == 'i') {
13624       /* Extract the ISDN span channel restriction specifier. */
13625       res = sscanf(args.group + 1, "%30d", &x);
13626       if (res < 1) {
13627          ast_log(LOG_WARNING, "Unable to determine ISDN span for data %s\n", data);
13628          return NULL;
13629       }
13630       param->span = x;
13631 
13632       /* Remove the ISDN span channel restriction specifier. */
13633       s = strchr(args.group, '-');
13634       if (!s) {
13635          /* Search all groups since we are ISDN span restricted. */
13636          return iflist;
13637       }
13638       args.group = s + 1;
13639       res = 0;
13640    }
13641    if (toupper(args.group[0]) == 'G' || toupper(args.group[0])=='R') {
13642       /* Retrieve the group number */
13643       s = args.group + 1;
13644       res = sscanf(s, "%30d%1c%30d", &x, &param->opt, &param->cadance);
13645       if (res < 1) {
13646          ast_log(LOG_WARNING, "Unable to determine group for data %s\n", data);
13647          return NULL;
13648       }
13649       param->groupmatch = ((ast_group_t) 1 << x);
13650 
13651       if (toupper(args.group[0]) == 'G') {
13652          if (args.group[0] == 'G') {
13653             param->backwards = 1;
13654             p = ifend;
13655          } else
13656             p = iflist;
13657       } else {
13658          if (ARRAY_LEN(round_robin) <= x) {
13659             ast_log(LOG_WARNING, "Round robin index %d out of range for data %s\n",
13660                x, data);
13661             return NULL;
13662          }
13663          if (args.group[0] == 'R') {
13664             param->backwards = 1;
13665             p = round_robin[x] ? round_robin[x]->prev : ifend;
13666             if (!p)
13667                p = ifend;
13668          } else {
13669             p = round_robin[x] ? round_robin[x]->next : iflist;
13670             if (!p)
13671                p = iflist;
13672          }
13673          param->roundrobin = 1;
13674          param->rr_starting_point = x;
13675       }
13676    } else {
13677       s = args.group;
13678       if (!strcasecmp(s, "pseudo")) {
13679          /* Special case for pseudo */
13680          x = CHAN_PSEUDO;
13681          param->channelmatch = x;
13682       } else {
13683          res = sscanf(s, "%30d%1c%30d", &x, &param->opt, &param->cadance);
13684          if (res < 1) {
13685             ast_log(LOG_WARNING, "Unable to determine channel for data %s\n", data);
13686             return NULL;
13687          } else {
13688             param->channelmatch = x;
13689          }
13690       }
13691       if (subdir) {
13692          char path[PATH_MAX];
13693          struct stat stbuf;
13694 
13695          snprintf(path, sizeof(path), "/dev/dahdi/%s/%d",
13696                subdir, param->channelmatch);
13697          if (stat(path, &stbuf) < 0) {
13698             ast_log(LOG_WARNING, "stat(%s) failed: %s\n",
13699                   path, strerror(errno));
13700             return NULL;
13701          }
13702          if (!S_ISCHR(stbuf.st_mode)) {
13703             ast_log(LOG_ERROR, "%s: Not a character device file\n",
13704                   path);
13705             return NULL;
13706          }
13707          param->channelmatch = minor(stbuf.st_rdev);
13708       }
13709 
13710       p = iflist;
13711    }
13712 
13713    if (param->opt == 'r' && res < 3) {
13714       ast_log(LOG_WARNING, "Distinctive ring missing identifier in '%s'\n", data);
13715       param->opt = '\0';
13716    }
13717 
13718    return p;
13719 }
13720 
13721 static struct ast_channel *dahdi_request(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause)
13722 {
13723    int callwait = 0;
13724    struct dahdi_pvt *p;
13725    struct ast_channel *tmp = NULL;
13726    struct dahdi_pvt *exitpvt;
13727    int channelmatched = 0;
13728    int groupmatched = 0;
13729 #if defined(HAVE_PRI) || defined(HAVE_SS7)
13730    int transcapdigital = 0;
13731 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
13732    struct dahdi_starting_point start;
13733 
13734    ast_mutex_lock(&iflock);
13735    p = determine_starting_point(data, &start);
13736    if (!p) {
13737       /* We couldn't determine a starting point, which likely means badly-formatted channel name. Abort! */
13738       ast_mutex_unlock(&iflock);
13739       return NULL;
13740    }
13741 
13742    /* Search for an unowned channel */
13743    exitpvt = p;
13744    while (p && !tmp) {
13745       if (start.roundrobin)
13746          round_robin[start.rr_starting_point] = p;
13747 
13748       if (is_group_or_channel_match(p, start.span, start.groupmatch, &groupmatched, start.channelmatch, &channelmatched)
13749          && available(&p, channelmatched)) {
13750          ast_debug(1, "Using channel %d\n", p->channel);
13751 
13752          callwait = (p->owner != NULL);
13753 #ifdef HAVE_OPENR2
13754          if (p->mfcr2) {
13755             ast_mutex_lock(&p->lock);
13756             if (p->mfcr2call) {
13757                ast_mutex_unlock(&p->lock);
13758                ast_log(LOG_DEBUG, "Yay!, someone just beat us in the race for channel %d.\n", p->channel);
13759                goto next;
13760             }
13761             p->mfcr2call = 1;
13762             ast_mutex_unlock(&p->lock);
13763          }
13764 #endif
13765          if (p->channel == CHAN_PSEUDO) {
13766             p = duplicate_pseudo(p);
13767             if (!p) {
13768                break;
13769             }
13770          }
13771 
13772          p->distinctivering = 0;
13773          /* Make special notes */
13774          switch (start.opt) {
13775          case '\0':
13776             /* No option present. */
13777             break;
13778          case 'c':
13779             /* Confirm answer */
13780             p->confirmanswer = 1;
13781             break;
13782          case 'r':
13783             /* Distinctive ring */
13784             p->distinctivering = start.cadance;
13785             break;
13786          case 'd':
13787 #if defined(HAVE_PRI) || defined(HAVE_SS7)
13788             /* If this is an ISDN call, make it digital */
13789             transcapdigital = AST_TRANS_CAP_DIGITAL;
13790 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
13791             break;
13792          default:
13793             ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", start.opt, (char *)data);
13794             break;
13795          }
13796 
13797          p->outgoing = 1;
13798          if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
13799             tmp = analog_request(p->sig_pvt, &callwait, requestor);
13800 #ifdef HAVE_PRI
13801          } else if (dahdi_sig_pri_lib_handles(p->sig)) {
13802             /*
13803              * We already have the B channel reserved for this call.  We
13804              * just need to make sure that dahdi_hangup() has completed
13805              * cleaning up before continuing.
13806              */
13807             ast_mutex_lock(&p->lock);
13808             ast_mutex_unlock(&p->lock);
13809 
13810             sig_pri_extract_called_num_subaddr(p->sig_pvt, data, p->dnid,
13811                sizeof(p->dnid));
13812             tmp = sig_pri_request(p->sig_pvt, SIG_PRI_DEFLAW, requestor, transcapdigital);
13813 #endif
13814 #if defined(HAVE_SS7)
13815          } else if (p->sig == SIG_SS7) {
13816             tmp = sig_ss7_request(p->sig_pvt, SIG_SS7_DEFLAW, requestor, transcapdigital);
13817 #endif   /* defined(HAVE_SS7) */
13818          } else {
13819             tmp = dahdi_new(p, AST_STATE_RESERVED, 0, p->owner ? SUB_CALLWAIT : SUB_REAL, 0, requestor ? requestor->linkedid : "");
13820          }
13821          if (!tmp) {
13822             p->outgoing = 0;
13823 #if defined(HAVE_PRI)
13824             switch (p->sig) {
13825             case SIG_PRI_LIB_HANDLE_CASES:
13826 #if defined(HAVE_PRI_CALL_WAITING)
13827                if (((struct sig_pri_chan *) p->sig_pvt)->is_call_waiting) {
13828                   ((struct sig_pri_chan *) p->sig_pvt)->is_call_waiting = 0;
13829                   ast_atomic_fetchadd_int(&p->pri->num_call_waiting_calls, -1);
13830                }
13831 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
13832                /*
13833                 * This should be the last thing to clear when we are done with
13834                 * the channel.
13835                 */
13836                ((struct sig_pri_chan *) p->sig_pvt)->allocated = 0;
13837                break;
13838             default:
13839                break;
13840             }
13841 #endif   /* defined(HAVE_PRI) */
13842          } else {
13843             snprintf(p->dialstring, sizeof(p->dialstring), "DAHDI/%s", (char *) data);
13844          }
13845          break;
13846       }
13847 #ifdef HAVE_OPENR2
13848 next:
13849 #endif
13850       if (start.backwards) {
13851          p = p->prev;
13852          if (!p)
13853             p = ifend;
13854       } else {
13855          p = p->next;
13856          if (!p)
13857             p = iflist;
13858       }
13859       /* stop when you roll to the one that we started from */
13860       if (p == exitpvt)
13861          break;
13862    }
13863    ast_mutex_unlock(&iflock);
13864    restart_monitor();
13865    if (cause && !tmp) {
13866       if (callwait || channelmatched) {
13867          *cause = AST_CAUSE_BUSY;
13868       } else if (groupmatched) {
13869          *cause = AST_CAUSE_CONGESTION;
13870       } else {
13871          /*
13872           * We did not match any channel requested.
13873           * Dialplan error requesting non-existant channel?
13874           */
13875       }
13876    }
13877 
13878    return tmp;
13879 }
13880 
13881 /*!
13882  * \internal
13883  * \brief Determine the device state for a given DAHDI device if we can.
13884  * \since 1.8
13885  *
13886  * \param data DAHDI device name after "DAHDI/".
13887  *
13888  * \retval device_state enum ast_device_state value.
13889  * \retval AST_DEVICE_UNKNOWN if we could not determine the device's state.
13890  */
13891 static int dahdi_devicestate(void *data)
13892 {
13893 #if defined(HAVE_PRI)
13894    char *device;
13895    unsigned span;
13896    int res;
13897 
13898    device = data;
13899 
13900    if (*device != 'I') {
13901       /* The request is not for an ISDN span device. */
13902       return AST_DEVICE_UNKNOWN;
13903    }
13904    res = sscanf(device, "I%30u", &span);
13905    if (res != 1 || !span || NUM_SPANS < span) {
13906       /* Bad format for ISDN span device name. */
13907       return AST_DEVICE_UNKNOWN;
13908    }
13909    device = strchr(device, '/');
13910    if (!device) {
13911       /* Bad format for ISDN span device name. */
13912       return AST_DEVICE_UNKNOWN;
13913    }
13914 
13915    /*
13916     * Since there are currently no other span devstate's defined,
13917     * it must be congestion.
13918     */
13919 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
13920    ++device;
13921    if (!strcmp(device, "congestion"))
13922 #endif   /* defined(THRESHOLD_DEVSTATE_PLACEHOLDER) */
13923    {
13924       return pris[span - 1].pri.congestion_devstate;
13925    }
13926 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
13927    else if (!strcmp(device, "threshold")) {
13928       return pris[span - 1].pri.threshold_devstate;
13929    }
13930    return AST_DEVICE_UNKNOWN;
13931 #endif   /* defined(THRESHOLD_DEVSTATE_PLACEHOLDER) */
13932 #else
13933    return AST_DEVICE_UNKNOWN;
13934 #endif   /* defined(HAVE_PRI) */
13935 }
13936 
13937 /*!
13938  * \brief Callback made when dial failed to get a channel out of dahdi_request().
13939  * \since 1.8
13940  *
13941  * \param inbound Incoming asterisk channel.
13942  * \param dest Same dial string passed to dahdi_request().
13943  * \param callback Callback into CC core to announce a busy channel available for CC.
13944  *
13945  * \details
13946  * This callback acts like a forked dial with all prongs of the fork busy.
13947  * Essentially, for each channel that could have taken the call, indicate that
13948  * it is busy.
13949  *
13950  * \retval 0 on success.
13951  * \retval -1 on error.
13952  */
13953 static int dahdi_cc_callback(struct ast_channel *inbound, const char *dest, ast_cc_callback_fn callback)
13954 {
13955    struct dahdi_pvt *p;
13956    struct dahdi_pvt *exitpvt;
13957    struct dahdi_starting_point start;
13958    int groupmatched = 0;
13959    int channelmatched = 0;
13960 
13961    ast_mutex_lock(&iflock);
13962    p = determine_starting_point(dest, &start);
13963    if (!p) {
13964       ast_mutex_unlock(&iflock);
13965       return -1;
13966    }
13967    exitpvt = p;
13968    for (;;) {
13969       if (is_group_or_channel_match(p, start.span, start.groupmatch, &groupmatched, start.channelmatch, &channelmatched)) {
13970          /* We found a potential match. call the callback */
13971          struct ast_str *device_name;
13972          char *dash;
13973          const char *monitor_type;
13974          char dialstring[AST_CHANNEL_NAME];
13975          char full_device_name[AST_CHANNEL_NAME];
13976 
13977          switch (ast_get_cc_monitor_policy(p->cc_params)) {
13978          case AST_CC_MONITOR_NEVER:
13979             break;
13980          case AST_CC_MONITOR_NATIVE:
13981          case AST_CC_MONITOR_ALWAYS:
13982          case AST_CC_MONITOR_GENERIC:
13983 #if defined(HAVE_PRI)
13984             if (dahdi_sig_pri_lib_handles(p->sig)) {
13985                /*
13986                 * ISDN is in a trunk busy condition so we need to monitor
13987                 * the span congestion device state.
13988                 */
13989                snprintf(full_device_name, sizeof(full_device_name),
13990                   "DAHDI/I%d/congestion", p->pri->span);
13991             } else
13992 #endif   /* defined(HAVE_PRI) */
13993             {
13994 #if defined(HAVE_PRI)
13995                device_name = create_channel_name(p, 1, "");
13996 #else
13997                device_name = create_channel_name(p);
13998 #endif   /* defined(HAVE_PRI) */
13999                snprintf(full_device_name, sizeof(full_device_name), "DAHDI/%s",
14000                   device_name ? ast_str_buffer(device_name) : "");
14001                ast_free(device_name);
14002                /*
14003                 * The portion after the '-' in the channel name is either a random
14004                 * number, a sequence number, or a subchannel number. None are
14005                 * necessary so strip them off.
14006                 */
14007                dash = strrchr(full_device_name, '-');
14008                if (dash) {
14009                   *dash = '\0';
14010                }
14011             }
14012             snprintf(dialstring, sizeof(dialstring), "DAHDI/%s", dest);
14013 
14014             /*
14015              * Analog can only do generic monitoring.
14016              * ISDN is in a trunk busy condition and any "device" is going
14017              * to be busy until a B channel becomes available.  The generic
14018              * monitor can do this task.
14019              */
14020             monitor_type = AST_CC_GENERIC_MONITOR_TYPE;
14021             callback(inbound,
14022 #if defined(HAVE_PRI)
14023                p->pri ? p->pri->cc_params : p->cc_params,
14024 #else
14025                p->cc_params,
14026 #endif   /* defined(HAVE_PRI) */
14027                monitor_type, full_device_name, dialstring, NULL);
14028             break;
14029          }
14030       }
14031       p = start.backwards ? p->prev : p->next;
14032       if (!p) {
14033          p = start.backwards ? ifend : iflist;
14034       }
14035       if (p == exitpvt) {
14036          break;
14037       }
14038    }
14039    ast_mutex_unlock(&iflock);
14040    return 0;
14041 }
14042 
14043 #if defined(HAVE_SS7)
14044 static void dahdi_ss7_message(struct ss7 *ss7, char *s)
14045 {
14046    int i;
14047 
14048    if (ss7) {
14049       for (i = 0; i < NUM_SPANS; i++) {
14050          if (linksets[i].ss7.ss7 == ss7) {
14051             ast_verbose("[%d] %s", i + 1, s);
14052             return;
14053          }
14054       }
14055    }
14056    ast_verbose("%s", s);
14057 }
14058 #endif   /* defined(HAVE_SS7) */
14059 
14060 #if defined(HAVE_SS7)
14061 static void dahdi_ss7_error(struct ss7 *ss7, char *s)
14062 {
14063    int i;
14064 
14065    if (ss7) {
14066       for (i = 0; i < NUM_SPANS; i++) {
14067          if (linksets[i].ss7.ss7 == ss7) {
14068             ast_log(LOG_ERROR, "[%d] %s", i + 1, s);
14069             return;
14070          }
14071       }
14072    }
14073    ast_log(LOG_ERROR, "%s", s);
14074 }
14075 #endif   /* defined(HAVE_SS7) */
14076 
14077 #if defined(HAVE_OPENR2)
14078 static void *mfcr2_monitor(void *data)
14079 {
14080    struct dahdi_mfcr2 *mfcr2 = data;
14081    /* we should be using pthread_key_create
14082       and allocate pollers dynamically.
14083       I think do_monitor() could be leaking, since it
14084       could be cancelled at any time and is not
14085       using thread keys, why?, */
14086    struct pollfd pollers[ARRAY_LEN(mfcr2->pvts)];
14087    int res = 0;
14088    int i = 0;
14089    int oldstate = 0;
14090    int quit_loop = 0;
14091    int maxsleep = 20;
14092    int was_idle = 0;
14093    int pollsize = 0;
14094    /* now that we're ready to get calls, unblock our side and
14095       get current line state */
14096    for (i = 0; i < mfcr2->numchans; i++) {
14097       openr2_chan_set_idle(mfcr2->pvts[i]->r2chan);
14098       openr2_chan_handle_cas(mfcr2->pvts[i]->r2chan);
14099    }
14100    while (1) {
14101       /* we trust here that the mfcr2 channel list will not ever change once
14102          the module is loaded */
14103       pollsize = 0;
14104       for (i = 0; i < mfcr2->numchans; i++) {
14105          pollers[i].revents = 0;
14106          pollers[i].events = 0;
14107          if (mfcr2->pvts[i]->owner) {
14108             continue;
14109          }
14110          if (!mfcr2->pvts[i]->r2chan) {
14111             ast_log(LOG_DEBUG, "Wow, no r2chan on channel %d\n", mfcr2->pvts[i]->channel);
14112             quit_loop = 1;
14113             break;
14114          }
14115          openr2_chan_enable_read(mfcr2->pvts[i]->r2chan);
14116          pollers[i].events = POLLIN | POLLPRI;
14117          pollers[i].fd = mfcr2->pvts[i]->subs[SUB_REAL].dfd;
14118          pollsize++;
14119       }
14120       if (quit_loop) {
14121          break;
14122       }
14123       if (pollsize == 0) {
14124          if (!was_idle) {
14125             ast_log(LOG_DEBUG, "Monitor thread going idle since everybody has an owner\n");
14126             was_idle = 1;
14127          }
14128          poll(NULL, 0, maxsleep);
14129          continue;
14130       }
14131       was_idle = 0;
14132       /* probably poll() is a valid cancel point, lets just be on the safe side
14133          by calling pthread_testcancel */
14134       pthread_testcancel();
14135       res = poll(pollers, mfcr2->numchans, maxsleep);
14136       pthread_testcancel();
14137       if ((res < 0) && (errno != EINTR)) {
14138          ast_log(LOG_ERROR, "going out, poll failed: %s\n", strerror(errno));
14139          break;
14140       }
14141       /* do we want to allow to cancel while processing events? */
14142       pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate);
14143       for (i = 0; i < mfcr2->numchans; i++) {
14144          if (pollers[i].revents & POLLPRI || pollers[i].revents & POLLIN) {
14145             openr2_chan_process_event(mfcr2->pvts[i]->r2chan);
14146          }
14147       }
14148       pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
14149    }
14150    ast_log(LOG_NOTICE, "Quitting MFC/R2 monitor thread\n");
14151    return 0;
14152 }
14153 #endif /* HAVE_OPENR2 */
14154 
14155 #if defined(HAVE_PRI)
14156 static void dahdi_pri_message(struct pri *pri, char *s)
14157 {
14158    int x;
14159    int y;
14160    int dchan = -1;
14161    int span = -1;
14162    int dchancount = 0;
14163 
14164    if (pri) {
14165       for (x = 0; x < NUM_SPANS; x++) {
14166          for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
14167             if (pris[x].pri.dchans[y]) {
14168                dchancount++;
14169             }
14170 
14171             if (pris[x].pri.dchans[y] == pri) {
14172                dchan = y;
14173             }
14174          }
14175          if (dchan >= 0) {
14176             span = x;
14177             break;
14178          }
14179          dchancount = 0;
14180       }
14181       if (-1 < span) {
14182          if (1 < dchancount) {
14183             ast_verbose("[PRI Span: %d D-Channel: %d] %s", span + 1, dchan, s);
14184          } else {
14185             ast_verbose("PRI Span: %d %s", span + 1, s);
14186          }
14187       } else {
14188          ast_verbose("PRI Span: ? %s", s);
14189       }
14190    } else {
14191       ast_verbose("PRI Span: ? %s", s);
14192    }
14193 
14194    ast_mutex_lock(&pridebugfdlock);
14195 
14196    if (pridebugfd >= 0) {
14197       if (write(pridebugfd, s, strlen(s)) < 0) {
14198          ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
14199       }
14200    }
14201 
14202    ast_mutex_unlock(&pridebugfdlock);
14203 }
14204 #endif   /* defined(HAVE_PRI) */
14205 
14206 #if defined(HAVE_PRI)
14207 static void dahdi_pri_error(struct pri *pri, char *s)
14208 {
14209    int x;
14210    int y;
14211    int dchan = -1;
14212    int span = -1;
14213    int dchancount = 0;
14214 
14215    if (pri) {
14216       for (x = 0; x < NUM_SPANS; x++) {
14217          for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
14218             if (pris[x].pri.dchans[y]) {
14219                dchancount++;
14220             }
14221 
14222             if (pris[x].pri.dchans[y] == pri) {
14223                dchan = y;
14224             }
14225          }
14226          if (dchan >= 0) {
14227             span = x;
14228             break;
14229          }
14230          dchancount = 0;
14231       }
14232       if (-1 < span) {
14233          if (1 < dchancount) {
14234             ast_log(LOG_ERROR, "[PRI Span: %d D-Channel: %d] %s", span + 1, dchan, s);
14235          } else {
14236             ast_log(LOG_ERROR, "PRI Span: %d %s", span + 1, s);
14237          }
14238       } else {
14239          ast_log(LOG_ERROR, "PRI Span: ? %s", s);
14240       }
14241    } else {
14242       ast_log(LOG_ERROR, "PRI Span: ? %s", s);
14243    }
14244 
14245    ast_mutex_lock(&pridebugfdlock);
14246 
14247    if (pridebugfd >= 0) {
14248       if (write(pridebugfd, s, strlen(s)) < 0) {
14249          ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
14250       }
14251    }
14252 
14253    ast_mutex_unlock(&pridebugfdlock);
14254 }
14255 #endif   /* defined(HAVE_PRI) */
14256 
14257 #if defined(HAVE_PRI)
14258 static int prepare_pri(struct dahdi_pri *pri)
14259 {
14260    int i, res, x;
14261    struct dahdi_params p;
14262    struct dahdi_bufferinfo bi;
14263    struct dahdi_spaninfo si;
14264 
14265    pri->pri.calls = &dahdi_pri_callbacks;
14266 
14267    for (i = 0; i < SIG_PRI_NUM_DCHANS; i++) {
14268       if (!pri->dchannels[i])
14269          break;
14270       pri->pri.fds[i] = open("/dev/dahdi/channel", O_RDWR);
14271       x = pri->dchannels[i];
14272       if ((pri->pri.fds[i] < 0) || (ioctl(pri->pri.fds[i],DAHDI_SPECIFY,&x) == -1)) {
14273          ast_log(LOG_ERROR, "Unable to open D-channel %d (%s)\n", x, strerror(errno));
14274          return -1;
14275       }
14276       memset(&p, 0, sizeof(p));
14277       res = ioctl(pri->pri.fds[i], DAHDI_GET_PARAMS, &p);
14278       if (res) {
14279          dahdi_close_pri_fd(pri, i);
14280          ast_log(LOG_ERROR, "Unable to get parameters for D-channel %d (%s)\n", x, strerror(errno));
14281          return -1;
14282       }
14283       if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC)) {
14284          dahdi_close_pri_fd(pri, i);
14285          ast_log(LOG_ERROR, "D-channel %d is not in HDLC/FCS mode.\n", x);
14286          return -1;
14287       }
14288       memset(&si, 0, sizeof(si));
14289       res = ioctl(pri->pri.fds[i], DAHDI_SPANSTAT, &si);
14290       if (res) {
14291          dahdi_close_pri_fd(pri, i);
14292          ast_log(LOG_ERROR, "Unable to get span state for D-channel %d (%s)\n", x, strerror(errno));
14293       }
14294       if (!si.alarms) {
14295          pri_event_noalarm(&pri->pri, i, 1);
14296       } else {
14297          pri_event_alarm(&pri->pri, i, 1);
14298       }
14299       memset(&bi, 0, sizeof(bi));
14300       bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
14301       bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
14302       bi.numbufs = 32;
14303       bi.bufsize = 1024;
14304       if (ioctl(pri->pri.fds[i], DAHDI_SET_BUFINFO, &bi)) {
14305          ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", x, strerror(errno));
14306          dahdi_close_pri_fd(pri, i);
14307          return -1;
14308       }
14309       pri->pri.dchan_logical_span[i] = pris[p.spanno - 1].prilogicalspan;
14310    }
14311    return 0;
14312 }
14313 #endif   /* defined(HAVE_PRI) */
14314 
14315 #if defined(HAVE_PRI)
14316 static char *complete_span_helper(const char *line, const char *word, int pos, int state, int rpos)
14317 {
14318    int which, span;
14319    char *ret = NULL;
14320 
14321    if (pos != rpos)
14322       return ret;
14323 
14324    for (which = span = 0; span < NUM_SPANS; span++) {
14325       if (pris[span].pri.pri && ++which > state) {
14326          if (ast_asprintf(&ret, "%d", span + 1) < 0) {   /* user indexes start from 1 */
14327             ret = NULL;
14328          }
14329          break;
14330       }
14331    }
14332    return ret;
14333 }
14334 #endif   /* defined(HAVE_PRI) */
14335 
14336 #if defined(HAVE_PRI)
14337 static char *complete_span_4(const char *line, const char *word, int pos, int state)
14338 {
14339    return complete_span_helper(line,word,pos,state,3);
14340 }
14341 #endif   /* defined(HAVE_PRI) */
14342 
14343 #if defined(HAVE_PRI)
14344 static char *handle_pri_set_debug_file(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14345 {
14346    int myfd;
14347    switch (cmd) {
14348    case CLI_INIT:
14349       e->command = "pri set debug file";
14350       e->usage = "Usage: pri set debug file [output-file]\n"
14351          "       Sends PRI debug output to the specified output file\n";
14352       return NULL;
14353    case CLI_GENERATE:
14354       return NULL;
14355    }
14356    if (a->argc < 5)
14357       return CLI_SHOWUSAGE;
14358 
14359    if (ast_strlen_zero(a->argv[4]))
14360       return CLI_SHOWUSAGE;
14361 
14362    myfd = open(a->argv[4], O_CREAT|O_WRONLY, AST_FILE_MODE);
14363    if (myfd < 0) {
14364       ast_cli(a->fd, "Unable to open '%s' for writing\n", a->argv[4]);
14365       return CLI_SUCCESS;
14366    }
14367 
14368    ast_mutex_lock(&pridebugfdlock);
14369 
14370    if (pridebugfd >= 0)
14371       close(pridebugfd);
14372 
14373    pridebugfd = myfd;
14374    ast_copy_string(pridebugfilename,a->argv[4],sizeof(pridebugfilename));
14375    ast_mutex_unlock(&pridebugfdlock);
14376    ast_cli(a->fd, "PRI debug output will be sent to '%s'\n", a->argv[4]);
14377    return CLI_SUCCESS;
14378 }
14379 #endif   /* defined(HAVE_PRI) */
14380 
14381 #if defined(HAVE_PRI)
14382 static char *handle_pri_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14383 {
14384    int span;
14385    int x;
14386    int level = 0;
14387    switch (cmd) {
14388    case CLI_INIT:
14389       e->command = "pri set debug {on|off|0|1|2} span";
14390       e->usage =
14391          "Usage: pri set debug {<level>|on|off} span <span>\n"
14392          "       Enables debugging on a given PRI span\n";
14393       return NULL;
14394    case CLI_GENERATE:
14395       return complete_span_4(a->line, a->word, a->pos, a->n);
14396    }
14397    if (a->argc < 6) {
14398       return CLI_SHOWUSAGE;
14399    }
14400 
14401    if (!strcasecmp(a->argv[3], "on")) {
14402       level = 1;
14403    } else if (!strcasecmp(a->argv[3], "off")) {
14404       level = 0;
14405    } else {
14406       level = atoi(a->argv[3]);
14407    }
14408    span = atoi(a->argv[5]);
14409    if ((span < 1) || (span > NUM_SPANS)) {
14410       ast_cli(a->fd, "Invalid span %s.  Should be a number %d to %d\n", a->argv[5], 1, NUM_SPANS);
14411       return CLI_SUCCESS;
14412    }
14413    if (!pris[span-1].pri.pri) {
14414       ast_cli(a->fd, "No PRI running on span %d\n", span);
14415       return CLI_SUCCESS;
14416    }
14417 
14418    /* Set debug level in libpri */
14419    for (x = 0; x < SIG_PRI_NUM_DCHANS; x++) {
14420       if (pris[span - 1].pri.dchans[x]) {
14421          switch (level) {
14422          case 0:
14423             pri_set_debug(pris[span - 1].pri.dchans[x], 0);
14424             break;
14425          case 1:
14426             pri_set_debug(pris[span - 1].pri.dchans[x], SIG_PRI_DEBUG_NORMAL);
14427             break;
14428          default:
14429             pri_set_debug(pris[span - 1].pri.dchans[x], SIG_PRI_DEBUG_INTENSE);
14430             break;
14431          }
14432       }
14433    }
14434    if (level == 0) {
14435       /* Close the debugging file if it's set */
14436       ast_mutex_lock(&pridebugfdlock);
14437       if (0 <= pridebugfd) {
14438          close(pridebugfd);
14439          pridebugfd = -1;
14440          ast_cli(a->fd, "Disabled PRI debug output to file '%s'\n",
14441             pridebugfilename);
14442       }
14443       ast_mutex_unlock(&pridebugfdlock);
14444    }
14445    pris[span - 1].pri.debug = (level) ? 1 : 0;
14446    ast_cli(a->fd, "%s debugging on span %d\n", (level) ? "Enabled" : "Disabled", span);
14447    return CLI_SUCCESS;
14448 }
14449 #endif   /* defined(HAVE_PRI) */
14450 
14451 #if defined(HAVE_PRI)
14452 #if defined(HAVE_PRI_SERVICE_MESSAGES)
14453 static char *handle_pri_service_generic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a, int changestatus)
14454 {
14455    unsigned *why;
14456    int channel;
14457    int trunkgroup;
14458    int x, y, fd = a->fd;
14459    int interfaceid = 0;
14460    char db_chan_name[20], db_answer[5];
14461    struct dahdi_pvt *tmp;
14462    struct dahdi_pri *pri;
14463 
14464    if (a->argc < 5 || a->argc > 6)
14465       return CLI_SHOWUSAGE;
14466    if (strchr(a->argv[4], ':')) {
14467       if (sscanf(a->argv[4], "%30d:%30d", &trunkgroup, &channel) != 2)
14468          return CLI_SHOWUSAGE;
14469       if ((trunkgroup < 1) || (channel < 1))
14470          return CLI_SHOWUSAGE;
14471       pri = NULL;
14472       for (x=0;x<NUM_SPANS;x++) {
14473          if (pris[x].pri.trunkgroup == trunkgroup) {
14474             pri = pris + x;
14475             break;
14476          }
14477       }
14478       if (!pri) {
14479          ast_cli(fd, "No such trunk group %d\n", trunkgroup);
14480          return CLI_FAILURE;
14481       }
14482    } else
14483       channel = atoi(a->argv[4]);
14484 
14485    if (a->argc == 6)
14486       interfaceid = atoi(a->argv[5]);
14487 
14488    /* either servicing a D-Channel */
14489    for (x = 0; x < NUM_SPANS; x++) {
14490       for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
14491          if (pris[x].dchannels[y] == channel) {
14492             pri = pris + x;
14493             if (pri->pri.enable_service_message_support) {
14494                ast_mutex_lock(&pri->pri.lock);
14495                pri_maintenance_service(pri->pri.pri, interfaceid, -1, changestatus);
14496                ast_mutex_unlock(&pri->pri.lock);
14497             } else {
14498                ast_cli(fd,
14499                   "\n\tThis operation has not been enabled in chan_dahdi.conf, set 'service_message_support=yes' to use this operation.\n"
14500                   "\tNote only 4ESS, 5ESS, and NI2 switch types are supported.\n\n");
14501             }
14502             return CLI_SUCCESS;
14503          }
14504       }
14505    }
14506 
14507    /* or servicing a B-Channel */
14508    ast_mutex_lock(&iflock);
14509    for (tmp = iflist; tmp; tmp = tmp->next) {
14510       if (tmp->pri && tmp->channel == channel) {
14511          ast_mutex_unlock(&iflock);
14512          ast_mutex_lock(&tmp->pri->lock);
14513          if (!tmp->pri->enable_service_message_support) {
14514             ast_mutex_unlock(&tmp->pri->lock);
14515             ast_cli(fd,
14516                "\n\tThis operation has not been enabled in chan_dahdi.conf, set 'service_message_support=yes' to use this operation.\n"
14517                "\tNote only 4ESS, 5ESS, and NI2 switch types are supported.\n\n");
14518             return CLI_SUCCESS;
14519          }
14520          snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, tmp->span, channel);
14521          why = &((struct sig_pri_chan *) tmp->sig_pvt)->service_status;
14522          switch(changestatus) {
14523          case 0: /* enable */
14524             /* Near end wants to be in service now. */
14525             ast_db_del(db_chan_name, SRVST_DBKEY);
14526             *why &= ~SRVST_NEAREND;
14527             if (*why) {
14528                snprintf(db_answer, sizeof(db_answer), "%s:%u", SRVST_TYPE_OOS, *why);
14529                ast_db_put(db_chan_name, SRVST_DBKEY, db_answer);
14530             } else {
14531                dahdi_pri_update_span_devstate(tmp->pri);
14532             }
14533             break;
14534          /* case 1:  -- loop */
14535          case 2: /* disable */
14536             /* Near end wants to be out-of-service now. */
14537             ast_db_del(db_chan_name, SRVST_DBKEY);
14538             *why |= SRVST_NEAREND;
14539             snprintf(db_answer, sizeof(db_answer), "%s:%u", SRVST_TYPE_OOS, *why);
14540             ast_db_put(db_chan_name, SRVST_DBKEY, db_answer);
14541             dahdi_pri_update_span_devstate(tmp->pri);
14542             break;
14543          /* case 3:  -- continuity */
14544          /* case 4:  -- shutdown */
14545          default:
14546             ast_log(LOG_WARNING, "Unsupported changestatus: '%d'\n", changestatus);
14547             break;
14548          }
14549          pri_maintenance_bservice(tmp->pri->pri, tmp->sig_pvt, changestatus);
14550          ast_mutex_unlock(&tmp->pri->lock);
14551          return CLI_SUCCESS;
14552       }
14553    }
14554    ast_mutex_unlock(&iflock);
14555 
14556    ast_cli(fd, "Unable to find given channel %d, possibly not a PRI\n", channel);
14557    return CLI_FAILURE;
14558 }
14559 
14560 static char *handle_pri_service_enable_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14561 {
14562    switch (cmd) {
14563    case CLI_INIT:
14564       e->command = "pri service enable channel";
14565       e->usage =
14566          "Usage: pri service enable channel <channel> [<interface id>]\n"
14567          "       Send an AT&T / NFAS / CCS ANSI T1.607 maintenance message\n"
14568          "  to restore a channel to service, with optional interface id\n"
14569          "  as agreed upon with remote switch operator\n";
14570       return NULL;
14571    case CLI_GENERATE:
14572       return NULL;
14573    }
14574    return handle_pri_service_generic(e, cmd, a, 0);
14575 }
14576 
14577 static char *handle_pri_service_disable_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14578 {
14579    switch (cmd) {
14580    case CLI_INIT:
14581       e->command = "pri service disable channel";
14582       e->usage =
14583          "Usage: pri service disable channel <chan num> [<interface id>]\n"
14584          "  Send an AT&T / NFAS / CCS ANSI T1.607 maintenance message\n"
14585          "  to remove a channel from service, with optional interface id\n"
14586          "  as agreed upon with remote switch operator\n";
14587       return NULL;
14588    case CLI_GENERATE:
14589       return NULL;
14590    }
14591    return handle_pri_service_generic(e, cmd, a, 2);
14592 }
14593 #endif   /* defined(HAVE_PRI_SERVICE_MESSAGES) */
14594 #endif   /* defined(HAVE_PRI) */
14595 
14596 #if defined(HAVE_PRI)
14597 static char *handle_pri_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14598 {
14599    int span;
14600 
14601    switch (cmd) {
14602    case CLI_INIT:
14603       e->command = "pri show channels";
14604       e->usage =
14605          "Usage: pri show channels\n"
14606          "       Displays PRI channel information such as the current mapping\n"
14607          "       of DAHDI B channels to Asterisk channel names and which calls\n"
14608          "       are on hold or call-waiting.  Calls on hold or call-waiting\n"
14609          "       are not associated with any B channel.\n";
14610       return NULL;
14611    case CLI_GENERATE:
14612       return NULL;
14613    }
14614 
14615    if (a->argc != 3)
14616       return CLI_SHOWUSAGE;
14617 
14618    sig_pri_cli_show_channels_header(a->fd);
14619    for (span = 0; span < NUM_SPANS; ++span) {
14620       if (pris[span].pri.pri) {
14621          sig_pri_cli_show_channels(a->fd, &pris[span].pri);
14622       }
14623    }
14624    return CLI_SUCCESS;
14625 }
14626 #endif   /* defined(HAVE_PRI) */
14627 
14628 #if defined(HAVE_PRI)
14629 static char *handle_pri_show_spans(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14630 {
14631    int span;
14632 
14633    switch (cmd) {
14634    case CLI_INIT:
14635       e->command = "pri show spans";
14636       e->usage =
14637          "Usage: pri show spans\n"
14638          "       Displays PRI span information\n";
14639       return NULL;
14640    case CLI_GENERATE:
14641       return NULL;
14642    }
14643 
14644    if (a->argc != 3)
14645       return CLI_SHOWUSAGE;
14646 
14647    for (span = 0; span < NUM_SPANS; span++) {
14648       if (pris[span].pri.pri) {
14649          sig_pri_cli_show_spans(a->fd, span + 1, &pris[span].pri);
14650       }
14651    }
14652    return CLI_SUCCESS;
14653 }
14654 #endif   /* defined(HAVE_PRI) */
14655 
14656 #if defined(HAVE_PRI)
14657 #define container_of(ptr, type, member) \
14658    ((type *)((char *)(ptr) - offsetof(type, member)))
14659 /*!
14660  * \internal
14661  * \brief Destroy a D-Channel of a PRI span
14662  * \since 12
14663  *
14664  * \param pri the pri span
14665  *
14666  * \return TRUE if the span was valid and we attempted destroying.
14667  *
14668  * Shuts down a span and destroys its D-Channel. Further destruction
14669  * of the B-channels using dahdi_destroy_channel() would probably be required
14670  * for the B-Channels.
14671  */
14672 static int pri_destroy_dchan(struct sig_pri_span *pri)
14673 {
14674    int i;
14675    struct dahdi_pri* dahdi_pri;
14676 
14677    if (!pri->master || (pri->master == AST_PTHREADT_NULL)) {
14678       return 0;
14679    }
14680    pthread_cancel(pri->master);
14681    pthread_join(pri->master, NULL);
14682 
14683    /* The 'struct dahdi_pri' that contains our 'struct sig_pri_span' */
14684    dahdi_pri = container_of(pri, struct dahdi_pri, pri);
14685    for (i = 0; i < SIG_PRI_NUM_DCHANS; i++) {
14686       ast_debug(4, "closing pri_fd %d\n", i);
14687       dahdi_close_pri_fd(dahdi_pri, i);
14688    }
14689    pri->pri = NULL;
14690    ast_debug(1, "PRI span %d destroyed\n", pri->span);
14691    return 1;
14692 }
14693 
14694 static char *handle_pri_destroy_span(struct ast_cli_entry *e, int cmd,
14695       struct ast_cli_args *a)
14696 {
14697    int span;
14698    int i;
14699    int res;
14700 
14701    switch (cmd) {
14702    case CLI_INIT:
14703       e->command = "pri destroy span";
14704       e->usage =
14705          "Usage: pri destroy span <span>\n"
14706          "       Destorys D-channel of span and its B-channels.\n"
14707          "  DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n";
14708       return NULL;
14709    case CLI_GENERATE:
14710       return complete_span_4(a->line, a->word, a->pos, a->n);
14711    }
14712 
14713    if (a->argc < 4) {
14714       return CLI_SHOWUSAGE;
14715    }
14716    res = sscanf(a->argv[3], "%30d", &span);
14717    if ((res != 1) || span < 1 || span > NUM_SPANS) {
14718       ast_cli(a->fd,
14719          "Invalid span '%s'.  Should be a number from %d to %d\n",
14720          a->argv[3], 1, NUM_SPANS);
14721       return CLI_SUCCESS;
14722    }
14723    if (!pris[span - 1].pri.pri) {
14724       ast_cli(a->fd, "No PRI running on span %d\n", span);
14725       return CLI_SUCCESS;
14726    }
14727 
14728    for (i = 0; i < pris[span - 1].pri.numchans; i++) {
14729       int channel;
14730       struct sig_pri_chan *pvt = pris[span - 1].pri.pvts[i];
14731 
14732       if (!pvt) {
14733          continue;
14734       }
14735       channel = pvt->channel;
14736       ast_debug(2, "About to destroy B-channel %d.\n", channel);
14737       dahdi_destroy_channel_bynum(channel);
14738    }
14739    ast_debug(2, "About to destroy D-channel of span %d.\n", span);
14740    pri_destroy_dchan(&pris[span - 1].pri);
14741 
14742    return CLI_SUCCESS;
14743 }
14744 
14745 #endif   /* defined(HAVE_PRI) */
14746 
14747 #if defined(HAVE_PRI)
14748 static char *handle_pri_show_span(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14749 {
14750    int span;
14751 
14752    switch (cmd) {
14753    case CLI_INIT:
14754       e->command = "pri show span";
14755       e->usage =
14756          "Usage: pri show span <span>\n"
14757          "       Displays PRI Information on a given PRI span\n";
14758       return NULL;
14759    case CLI_GENERATE:
14760       return complete_span_4(a->line, a->word, a->pos, a->n);
14761    }
14762 
14763    if (a->argc < 4)
14764       return CLI_SHOWUSAGE;
14765    span = atoi(a->argv[3]);
14766    if ((span < 1) || (span > NUM_SPANS)) {
14767       ast_cli(a->fd, "Invalid span '%s'.  Should be a number from %d to %d\n", a->argv[3], 1, NUM_SPANS);
14768       return CLI_SUCCESS;
14769    }
14770    if (!pris[span-1].pri.pri) {
14771       ast_cli(a->fd, "No PRI running on span %d\n", span);
14772       return CLI_SUCCESS;
14773    }
14774 
14775    sig_pri_cli_show_span(a->fd, pris[span-1].dchannels, &pris[span-1].pri);
14776 
14777    return CLI_SUCCESS;
14778 }
14779 #endif   /* defined(HAVE_PRI) */
14780 
14781 #if defined(HAVE_PRI)
14782 static char *handle_pri_show_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14783 {
14784    int x;
14785    int span;
14786    int count=0;
14787    int debug;
14788 
14789    switch (cmd) {
14790    case CLI_INIT:
14791       e->command = "pri show debug";
14792       e->usage =
14793          "Usage: pri show debug\n"
14794          "  Show the debug state of pri spans\n";
14795       return NULL;
14796    case CLI_GENERATE:
14797       return NULL;
14798    }
14799 
14800    for (span = 0; span < NUM_SPANS; span++) {
14801       if (pris[span].pri.pri) {
14802          for (x = 0; x < SIG_PRI_NUM_DCHANS; x++) {
14803             if (pris[span].pri.dchans[x]) {
14804                debug = pri_get_debug(pris[span].pri.dchans[x]);
14805                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" );
14806                count++;
14807             }
14808          }
14809       }
14810 
14811    }
14812    ast_mutex_lock(&pridebugfdlock);
14813    if (pridebugfd >= 0)
14814       ast_cli(a->fd, "Logging PRI debug to file %s\n", pridebugfilename);
14815    ast_mutex_unlock(&pridebugfdlock);
14816 
14817    if (!count)
14818       ast_cli(a->fd, "No PRI running\n");
14819    return CLI_SUCCESS;
14820 }
14821 #endif   /* defined(HAVE_PRI) */
14822 
14823 #if defined(HAVE_PRI)
14824 static char *handle_pri_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14825 {
14826    switch (cmd) {
14827    case CLI_INIT:
14828       e->command = "pri show version";
14829       e->usage =
14830          "Usage: pri show version\n"
14831          "Show libpri version information\n";
14832       return NULL;
14833    case CLI_GENERATE:
14834       return NULL;
14835    }
14836 
14837    ast_cli(a->fd, "libpri version: %s\n", pri_get_version());
14838 
14839    return CLI_SUCCESS;
14840 }
14841 #endif   /* defined(HAVE_PRI) */
14842 
14843 #if defined(HAVE_PRI)
14844 static struct ast_cli_entry dahdi_pri_cli[] = {
14845    AST_CLI_DEFINE(handle_pri_debug, "Enables PRI debugging on a span"),
14846 #if defined(HAVE_PRI_SERVICE_MESSAGES)
14847    AST_CLI_DEFINE(handle_pri_service_enable_channel, "Return a channel to service"),
14848    AST_CLI_DEFINE(handle_pri_service_disable_channel, "Remove a channel from service"),
14849 #endif   /* defined(HAVE_PRI_SERVICE_MESSAGES) */
14850    AST_CLI_DEFINE(handle_pri_show_channels, "Displays PRI channel information"),
14851    AST_CLI_DEFINE(handle_pri_show_spans, "Displays PRI span information"),
14852    AST_CLI_DEFINE(handle_pri_show_span, "Displays PRI span information"),
14853    AST_CLI_DEFINE(handle_pri_destroy_span, "Destroy a PRI span"),
14854    AST_CLI_DEFINE(handle_pri_show_debug, "Displays current PRI debug settings"),
14855    AST_CLI_DEFINE(handle_pri_set_debug_file, "Sends PRI debug output to the specified file"),
14856    AST_CLI_DEFINE(handle_pri_version, "Displays libpri version"),
14857 };
14858 #endif   /* defined(HAVE_PRI) */
14859 
14860 #ifdef HAVE_OPENR2
14861 
14862 static char *handle_mfcr2_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14863 {
14864    switch (cmd) {
14865    case CLI_INIT:
14866       e->command = "mfcr2 show version";
14867       e->usage =
14868          "Usage: mfcr2 show version\n"
14869          "       Shows the version of the OpenR2 library being used.\n";
14870       return NULL;
14871    case CLI_GENERATE:
14872       return NULL;
14873    }
14874    ast_cli(a->fd, "OpenR2 version: %s, revision: %s\n", openr2_get_version(), openr2_get_revision());
14875    return CLI_SUCCESS;
14876 }
14877 
14878 static char *handle_mfcr2_show_variants(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14879 {
14880 #define FORMAT "%4s %40s\n"
14881    int i = 0;
14882    int numvariants = 0;
14883    const openr2_variant_entry_t *variants;
14884    switch (cmd) {
14885    case CLI_INIT:
14886       e->command = "mfcr2 show variants";
14887       e->usage =
14888          "Usage: mfcr2 show variants\n"
14889          "       Shows the list of MFC/R2 variants supported.\n";
14890       return NULL;
14891    case CLI_GENERATE:
14892       return NULL;
14893    }
14894    if (!(variants = openr2_proto_get_variant_list(&numvariants))) {
14895       ast_cli(a->fd, "Failed to get list of variants.\n");
14896       return CLI_FAILURE;
14897    }
14898    ast_cli(a->fd, FORMAT, "Variant Code", "Country");
14899    for (i = 0; i < numvariants; i++) {
14900       ast_cli(a->fd, FORMAT, variants[i].name, variants[i].country);
14901    }
14902    return CLI_SUCCESS;
14903 #undef FORMAT
14904 }
14905 
14906 static char *handle_mfcr2_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14907 {
14908 #define FORMAT "%4s %-7.7s %-7.7s %-8.8s %-9.9s %-16.16s %-8.8s %-8.8s\n"
14909    int filtertype = 0;
14910    int targetnum = 0;
14911    char channo[5];
14912    char anino[5];
14913    char dnisno[5];
14914    struct dahdi_pvt *p;
14915    openr2_context_t *r2context;
14916    openr2_variant_t r2variant;
14917    switch (cmd) {
14918    case CLI_INIT:
14919       e->command = "mfcr2 show channels [group|context]";
14920       e->usage =
14921          "Usage: mfcr2 show channels [group <group> | context <context>]\n"
14922          "       Shows the DAHDI channels configured with MFC/R2 signaling.\n";
14923       return NULL;
14924    case CLI_GENERATE:
14925       return NULL;
14926    }
14927    if (!((a->argc == 3) || (a->argc == 5))) {
14928       return CLI_SHOWUSAGE;
14929    }
14930    if (a->argc == 5) {
14931       if (!strcasecmp(a->argv[3], "group")) {
14932          targetnum = atoi(a->argv[4]);
14933          if ((targetnum < 0) || (targetnum > 63))
14934             return CLI_SHOWUSAGE;
14935          targetnum = 1 << targetnum;
14936          filtertype = 1;
14937       } else if (!strcasecmp(a->argv[3], "context")) {
14938          filtertype = 2;
14939       } else {
14940          return CLI_SHOWUSAGE;
14941       }
14942    }
14943    ast_cli(a->fd, FORMAT, "Chan", "Variant", "Max ANI", "Max DNIS", "ANI First", "Immediate Accept", "Tx CAS", "Rx CAS");
14944    ast_mutex_lock(&iflock);
14945    for (p = iflist; p; p = p->next) {
14946       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14947          continue;
14948       }
14949       if (filtertype) {
14950          switch(filtertype) {
14951          case 1: /* mfcr2 show channels group <group> */
14952             if (p->group != targetnum) {
14953                continue;
14954             }
14955             break;
14956          case 2: /* mfcr2 show channels context <context> */
14957             if (strcasecmp(p->context, a->argv[4])) {
14958                continue;
14959             }
14960             break;
14961          default:
14962             ;
14963          }
14964       }
14965       r2context = openr2_chan_get_context(p->r2chan);
14966       r2variant = openr2_context_get_variant(r2context);
14967       snprintf(channo, sizeof(channo), "%d", p->channel);
14968       snprintf(anino, sizeof(anino), "%d", openr2_context_get_max_ani(r2context));
14969       snprintf(dnisno, sizeof(dnisno), "%d", openr2_context_get_max_dnis(r2context));
14970       ast_cli(a->fd, FORMAT, channo, openr2_proto_get_variant_string(r2variant),
14971             anino, dnisno, openr2_context_get_ani_first(r2context) ? "Yes" : "No",
14972             openr2_context_get_immediate_accept(r2context) ? "Yes" : "No",
14973             openr2_chan_get_tx_cas_string(p->r2chan), openr2_chan_get_rx_cas_string(p->r2chan));
14974    }
14975    ast_mutex_unlock(&iflock);
14976    return CLI_SUCCESS;
14977 #undef FORMAT
14978 }
14979 
14980 static char *handle_mfcr2_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14981 {
14982    struct dahdi_pvt *p = NULL;
14983    int channo = 0;
14984    char *toklevel = NULL;
14985    char *saveptr = NULL;
14986    char *logval = NULL;
14987    openr2_log_level_t loglevel = OR2_LOG_NOTHING;
14988    openr2_log_level_t tmplevel = OR2_LOG_NOTHING;
14989    switch (cmd) {
14990    case CLI_INIT:
14991       e->command = "mfcr2 set debug";
14992       e->usage =
14993          "Usage: mfcr2 set debug <loglevel> <channel>\n"
14994          "       Set a new logging level for the specified channel.\n"
14995          "       If no channel is specified the logging level will be applied to all channels.\n";
14996       return NULL;
14997    case CLI_GENERATE:
14998       return NULL;
14999    }
15000    if (a->argc < 4) {
15001       return CLI_SHOWUSAGE;
15002    }
15003    channo = (a->argc == 5) ? atoi(a->argv[4]) : -1;
15004    logval = ast_strdupa(a->argv[3]);
15005    toklevel = strtok_r(logval, ",", &saveptr);
15006    if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
15007       ast_cli(a->fd, "Invalid MFC/R2 logging level '%s'.\n", a->argv[3]);
15008       return CLI_FAILURE;
15009    } else if (OR2_LOG_NOTHING == tmplevel) {
15010       loglevel = tmplevel;
15011    } else {
15012       loglevel |= tmplevel;
15013       while ((toklevel = strtok_r(NULL, ",", &saveptr))) {
15014          if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
15015             ast_cli(a->fd, "Ignoring invalid logging level: '%s'.\n", toklevel);
15016             continue;
15017          }
15018          loglevel |= tmplevel;
15019       }
15020    }
15021    ast_mutex_lock(&iflock);
15022    for (p = iflist; p; p = p->next) {
15023       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
15024          continue;
15025       }
15026       if ((channo != -1) && (p->channel != channo )) {
15027          continue;
15028       }
15029       openr2_chan_set_log_level(p->r2chan, loglevel);
15030       if (channo != -1) {
15031          ast_cli(a->fd, "MFC/R2 debugging set to '%s' for channel %d.\n", a->argv[3], p->channel);
15032          break;
15033       }
15034    }
15035    if ((channo != -1) && !p) {
15036       ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
15037    }
15038    if (channo == -1) {
15039       ast_cli(a->fd, "MFC/R2 debugging set to '%s' for all channels.\n", a->argv[3]);
15040    }
15041    ast_mutex_unlock(&iflock);
15042    return CLI_SUCCESS;
15043 }
15044 
15045 static char *handle_mfcr2_call_files(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15046 {
15047    struct dahdi_pvt *p = NULL;
15048    int channo = 0;
15049    switch (cmd) {
15050    case CLI_INIT:
15051       e->command = "mfcr2 call files [on|off]";
15052       e->usage =
15053          "Usage: mfcr2 call files [on|off] <channel>\n"
15054          "       Enable call files creation on the specified channel.\n"
15055          "       If no channel is specified call files creation policy will be applied to all channels.\n";
15056       return NULL;
15057    case CLI_GENERATE:
15058       return NULL;
15059    }
15060    if (a->argc < 4) {
15061       return CLI_SHOWUSAGE;
15062    }
15063    channo = (a->argc == 5) ? atoi(a->argv[4]) : -1;
15064    ast_mutex_lock(&iflock);
15065    for (p = iflist; p; p = p->next) {
15066       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
15067          continue;
15068       }
15069       if ((channo != -1) && (p->channel != channo )) {
15070          continue;
15071       }
15072       if (ast_true(a->argv[3])) {
15073          openr2_chan_enable_call_files(p->r2chan);
15074       } else {
15075          openr2_chan_disable_call_files(p->r2chan);
15076       }
15077       if (channo != -1) {
15078          if (ast_true(a->argv[3])) {
15079             ast_cli(a->fd, "MFC/R2 call files enabled for channel %d.\n", p->channel);
15080          } else {
15081             ast_cli(a->fd, "MFC/R2 call files disabled for channel %d.\n", p->channel);
15082          }
15083          break;
15084       }
15085    }
15086    if ((channo != -1) && !p) {
15087       ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
15088    }
15089    if (channo == -1) {
15090       if (ast_true(a->argv[3])) {
15091          ast_cli(a->fd, "MFC/R2 Call files enabled for all channels.\n");
15092       } else {
15093          ast_cli(a->fd, "MFC/R2 Call files disabled for all channels.\n");
15094       }
15095    }
15096    ast_mutex_unlock(&iflock);
15097    return CLI_SUCCESS;
15098 }
15099 
15100 static char *handle_mfcr2_set_idle(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15101 {
15102    struct dahdi_pvt *p = NULL;
15103    int channo = 0;
15104    switch (cmd) {
15105    case CLI_INIT:
15106       e->command = "mfcr2 set idle";
15107       e->usage =
15108          "Usage: mfcr2 set idle <channel>\n"
15109          "       DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n"
15110          "       Force the given channel into IDLE state.\n"
15111          "       If no channel is specified, all channels will be set to IDLE.\n";
15112       return NULL;
15113    case CLI_GENERATE:
15114       return NULL;
15115    }
15116    channo = (a->argc == 4) ? atoi(a->argv[3]) : -1;
15117    ast_mutex_lock(&iflock);
15118    for (p = iflist; p; p = p->next) {
15119       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
15120          continue;
15121       }
15122       if ((channo != -1) && (p->channel != channo )) {
15123          continue;
15124       }
15125       openr2_chan_set_idle(p->r2chan);
15126       ast_mutex_lock(&p->lock);
15127       p->locallyblocked = 0;
15128       p->mfcr2call = 0;
15129       ast_mutex_unlock(&p->lock);
15130       if (channo != -1) {
15131          break;
15132       }
15133    }
15134    if ((channo != -1) && !p) {
15135       ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
15136    }
15137    ast_mutex_unlock(&iflock);
15138    return CLI_SUCCESS;
15139 }
15140 
15141 static char *handle_mfcr2_set_blocked(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15142 {
15143    struct dahdi_pvt *p = NULL;
15144    int channo = 0;
15145    switch (cmd) {
15146    case CLI_INIT:
15147       e->command = "mfcr2 set blocked";
15148       e->usage =
15149          "Usage: mfcr2 set blocked <channel>\n"
15150          "       DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n"
15151          "       Force the given channel into BLOCKED state.\n"
15152          "       If no channel is specified, all channels will be set to BLOCKED.\n";
15153       return NULL;
15154    case CLI_GENERATE:
15155       return NULL;
15156    }
15157    channo = (a->argc == 4) ? atoi(a->argv[3]) : -1;
15158    ast_mutex_lock(&iflock);
15159    for (p = iflist; p; p = p->next) {
15160       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
15161          continue;
15162       }
15163       if ((channo != -1) && (p->channel != channo )) {
15164          continue;
15165       }
15166       openr2_chan_set_blocked(p->r2chan);
15167       ast_mutex_lock(&p->lock);
15168       p->locallyblocked = 1;
15169       ast_mutex_unlock(&p->lock);
15170       if (channo != -1) {
15171          break;
15172       }
15173    }
15174    if ((channo != -1) && !p) {
15175       ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
15176    }
15177    ast_mutex_unlock(&iflock);
15178    return CLI_SUCCESS;
15179 }
15180 
15181 static struct ast_cli_entry dahdi_mfcr2_cli[] = {
15182    AST_CLI_DEFINE(handle_mfcr2_version, "Show OpenR2 library version"),
15183    AST_CLI_DEFINE(handle_mfcr2_show_variants, "Show supported MFC/R2 variants"),
15184    AST_CLI_DEFINE(handle_mfcr2_show_channels, "Show MFC/R2 channels"),
15185    AST_CLI_DEFINE(handle_mfcr2_set_debug, "Set MFC/R2 channel logging level"),
15186    AST_CLI_DEFINE(handle_mfcr2_call_files, "Enable/Disable MFC/R2 call files"),
15187    AST_CLI_DEFINE(handle_mfcr2_set_idle, "Reset MFC/R2 channel forcing it to IDLE"),
15188    AST_CLI_DEFINE(handle_mfcr2_set_blocked, "Reset MFC/R2 channel forcing it to BLOCKED"),
15189 };
15190 
15191 #endif /* HAVE_OPENR2 */
15192 
15193 static char *dahdi_destroy_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15194 {
15195    int channel;
15196    int ret;
15197    switch (cmd) {
15198    case CLI_INIT:
15199       e->command = "dahdi destroy channel";
15200       e->usage =
15201          "Usage: dahdi destroy channel <chan num>\n"
15202          "  DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.  Immediately removes a given channel, whether it is in use or not\n";
15203       return NULL;
15204    case CLI_GENERATE:
15205       return NULL;
15206    }
15207    if (a->argc != 4)
15208       return CLI_SHOWUSAGE;
15209 
15210    channel = atoi(a->argv[3]);
15211    ret = dahdi_destroy_channel_bynum(channel);
15212    return ( RESULT_SUCCESS == ret ) ? CLI_SUCCESS : CLI_FAILURE;
15213 }
15214 
15215 static void dahdi_softhangup_all(void)
15216 {
15217    struct dahdi_pvt *p;
15218 retry:
15219    ast_mutex_lock(&iflock);
15220    for (p = iflist; p; p = p->next) {
15221       ast_mutex_lock(&p->lock);
15222       if (p->owner && !p->restartpending) {
15223          if (ast_channel_trylock(p->owner)) {
15224             if (option_debug > 2)
15225                ast_verbose("Avoiding deadlock\n");
15226             /* Avoid deadlock since you're not supposed to lock iflock or pvt before a channel */
15227             ast_mutex_unlock(&p->lock);
15228             ast_mutex_unlock(&iflock);
15229             goto retry;
15230          }
15231          if (option_debug > 2)
15232             ast_verbose("Softhanging up on %s\n", p->owner->name);
15233          ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_EXPLICIT);
15234          p->restartpending = 1;
15235          num_restart_pending++;
15236          ast_channel_unlock(p->owner);
15237       }
15238       ast_mutex_unlock(&p->lock);
15239    }
15240    ast_mutex_unlock(&iflock);
15241 }
15242 
15243 static int setup_dahdi(int reload);
15244 static int dahdi_restart(void)
15245 {
15246 #if defined(HAVE_PRI) || defined(HAVE_SS7)
15247    int i, j;
15248 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
15249    int cancel_code;
15250    struct dahdi_pvt *p;
15251 
15252    ast_mutex_lock(&restart_lock);
15253    ast_verb(1, "Destroying channels and reloading DAHDI configuration.\n");
15254    dahdi_softhangup_all();
15255    ast_verb(4, "Initial softhangup of all DAHDI channels complete.\n");
15256 #ifdef HAVE_OPENR2
15257    dahdi_r2_destroy_links();
15258 #endif
15259 
15260 #if defined(HAVE_PRI)
15261    for (i = 0; i < NUM_SPANS; i++) {
15262       if (pris[i].pri.master && (pris[i].pri.master != AST_PTHREADT_NULL)) {
15263          cancel_code = pthread_cancel(pris[i].pri.master);
15264          pthread_kill(pris[i].pri.master, SIGURG);
15265          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);
15266          pthread_join(pris[i].pri.master, NULL);
15267          ast_debug(4, "Joined thread of span %d\n", i);
15268       }
15269    }
15270 #endif
15271 
15272 #if defined(HAVE_SS7)
15273    for (i = 0; i < NUM_SPANS; i++) {
15274       if (linksets[i].ss7.master && (linksets[i].ss7.master != AST_PTHREADT_NULL)) {
15275          cancel_code = pthread_cancel(linksets[i].ss7.master);
15276          pthread_kill(linksets[i].ss7.master, SIGURG);
15277          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);
15278          pthread_join(linksets[i].ss7.master, NULL);
15279          ast_debug(4, "Joined thread of span %d\n", i);
15280       }
15281    }
15282 #endif   /* defined(HAVE_SS7) */
15283 
15284    ast_mutex_lock(&monlock);
15285    if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
15286       cancel_code = pthread_cancel(monitor_thread);
15287       pthread_kill(monitor_thread, SIGURG);
15288       ast_debug(4, "Waiting to join monitor thread with pid=%p, cancel_code=%d\n", (void *) monitor_thread, cancel_code);
15289       pthread_join(monitor_thread, NULL);
15290       ast_debug(4, "Joined monitor thread\n");
15291    }
15292    monitor_thread = AST_PTHREADT_NULL; /* prepare to restart thread in setup_dahdi once channels are reconfigured */
15293 
15294    ast_mutex_lock(&ss_thread_lock);
15295    while (ss_thread_count > 0) { /* let ss_threads finish and run dahdi_hangup before dahvi_pvts are destroyed */
15296       int x = DAHDI_FLASH;
15297       ast_debug(3, "Waiting on %d analog_ss_thread(s) to finish\n", ss_thread_count);
15298 
15299       ast_mutex_lock(&iflock);
15300       for (p = iflist; p; p = p->next) {
15301          if (p->owner) {
15302             /* important to create an event for dahdi_wait_event to register so that all analog_ss_threads terminate */
15303             ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
15304          }
15305       }
15306       ast_mutex_unlock(&iflock);
15307       ast_cond_wait(&ss_thread_complete, &ss_thread_lock);
15308    }
15309 
15310    /* ensure any created channels before monitor threads were stopped are hungup */
15311    dahdi_softhangup_all();
15312    ast_verb(4, "Final softhangup of all DAHDI channels complete.\n");
15313    destroy_all_channels();
15314    memset(round_robin, 0, sizeof(round_robin));
15315    ast_debug(1, "Channels destroyed. Now re-reading config. %d active channels remaining.\n", ast_active_channels());
15316 
15317    ast_mutex_unlock(&monlock);
15318 
15319 #ifdef HAVE_PRI
15320    for (i = 0; i < NUM_SPANS; i++) {
15321       for (j = 0; j < SIG_PRI_NUM_DCHANS; j++)
15322          dahdi_close_pri_fd(&(pris[i]), j);
15323    }
15324 
15325    memset(pris, 0, sizeof(pris));
15326    for (i = 0; i < NUM_SPANS; i++) {
15327       sig_pri_init_pri(&pris[i].pri);
15328    }
15329    pri_set_error(dahdi_pri_error);
15330    pri_set_message(dahdi_pri_message);
15331 #endif
15332 #if defined(HAVE_SS7)
15333    for (i = 0; i < NUM_SPANS; i++) {
15334       for (j = 0; j < SIG_SS7_NUM_DCHANS; j++)
15335          dahdi_close_ss7_fd(&(linksets[i]), j);
15336    }
15337 
15338    memset(linksets, 0, sizeof(linksets));
15339    for (i = 0; i < NUM_SPANS; i++) {
15340       sig_ss7_init_linkset(&linksets[i].ss7);
15341    }
15342    ss7_set_error(dahdi_ss7_error);
15343    ss7_set_message(dahdi_ss7_message);
15344 #endif   /* defined(HAVE_SS7) */
15345 
15346    if (setup_dahdi(2) != 0) {
15347       ast_log(LOG_WARNING, "Reload channels from dahdi config failed!\n");
15348       ast_mutex_unlock(&ss_thread_lock);
15349       return 1;
15350    }
15351    ast_mutex_unlock(&ss_thread_lock);
15352    ast_mutex_unlock(&restart_lock);
15353    return 0;
15354 }
15355 
15356 static char *dahdi_restart_cmd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15357 {
15358    switch (cmd) {
15359    case CLI_INIT:
15360       e->command = "dahdi restart";
15361       e->usage =
15362          "Usage: dahdi restart\n"
15363          "  Restarts the DAHDI channels: destroys them all and then\n"
15364          "  re-reads them from chan_dahdi.conf.\n"
15365          "  Note that this will STOP any running CALL on DAHDI channels.\n"
15366          "";
15367       return NULL;
15368    case CLI_GENERATE:
15369       return NULL;
15370    }
15371    if (a->argc != 2)
15372       return CLI_SHOWUSAGE;
15373 
15374    if (dahdi_restart() != 0)
15375       return CLI_FAILURE;
15376    return CLI_SUCCESS;
15377 }
15378 
15379 static int action_dahdirestart(struct mansession *s, const struct message *m)
15380 {
15381    if (dahdi_restart() != 0) {
15382       astman_send_error(s, m, "Failed rereading DAHDI configuration");
15383       return 1;
15384    }
15385    astman_send_ack(s, m, "DAHDIRestart: Success");
15386    return 0;
15387 }
15388 
15389 static char *dahdi_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15390 {
15391 #define FORMAT "%7s %-15.15s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
15392 #define FORMAT2 "%7s %-15.15s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
15393    ast_group_t targetnum = 0;
15394    int filtertype = 0;
15395    struct dahdi_pvt *tmp = NULL;
15396    char tmps[20] = "";
15397    char statestr[20] = "";
15398    char blockstr[20] = "";
15399 
15400    switch (cmd) {
15401    case CLI_INIT:
15402       e->command = "dahdi show channels [group|context]";
15403       e->usage =
15404          "Usage: dahdi show channels [ group <group> | context <context> ]\n"
15405          "  Shows a list of available channels with optional filtering\n"
15406          "  <group> must be a number between 0 and 63\n";
15407       return NULL;
15408    case CLI_GENERATE:
15409       return NULL;
15410    }
15411 
15412    /* syntax: dahdi show channels [ group <group> | context <context> ] */
15413 
15414    if (!((a->argc == 3) || (a->argc == 5)))
15415       return CLI_SHOWUSAGE;
15416 
15417    if (a->argc == 5) {
15418       if (!strcasecmp(a->argv[3], "group")) {
15419          targetnum = atoi(a->argv[4]);
15420          if (63 < targetnum) {
15421             return CLI_SHOWUSAGE;
15422          }
15423          targetnum = ((ast_group_t) 1) << targetnum;
15424          filtertype = 1;
15425       } else if (!strcasecmp(a->argv[3], "context")) {
15426          filtertype = 2;
15427       }
15428    }
15429 
15430    ast_cli(a->fd, FORMAT2, "Chan", "Extension", "Context", "Language", "MOH Interpret", "Blocked", "State");
15431    ast_mutex_lock(&iflock);
15432    for (tmp = iflist; tmp; tmp = tmp->next) {
15433       if (filtertype) {
15434          switch(filtertype) {
15435          case 1: /* dahdi show channels group <group> */
15436             if (!(tmp->group & targetnum)) {
15437                continue;
15438             }
15439             break;
15440          case 2: /* dahdi show channels context <context> */
15441             if (strcasecmp(tmp->context, a->argv[4])) {
15442                continue;
15443             }
15444             break;
15445          default:
15446             break;
15447          }
15448       }
15449       if (tmp->channel > 0) {
15450          snprintf(tmps, sizeof(tmps), "%d", tmp->channel);
15451       } else
15452          ast_copy_string(tmps, "pseudo", sizeof(tmps));
15453 
15454       if (tmp->locallyblocked)
15455          blockstr[0] = 'L';
15456       else
15457          blockstr[0] = ' ';
15458 
15459       if (tmp->remotelyblocked)
15460          blockstr[1] = 'R';
15461       else
15462          blockstr[1] = ' ';
15463 
15464       blockstr[2] = '\0';
15465 
15466       snprintf(statestr, sizeof(statestr), "%s", "In Service");
15467 
15468       ast_cli(a->fd, FORMAT, tmps, tmp->exten, tmp->context, tmp->language, tmp->mohinterpret, blockstr, statestr);
15469    }
15470    ast_mutex_unlock(&iflock);
15471    return CLI_SUCCESS;
15472 #undef FORMAT
15473 #undef FORMAT2
15474 }
15475 
15476 static char *dahdi_show_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15477 {
15478    int channel;
15479    struct dahdi_pvt *tmp = NULL;
15480    struct dahdi_confinfo ci;
15481    struct dahdi_params ps;
15482    int x;
15483 
15484    switch (cmd) {
15485    case CLI_INIT:
15486       e->command = "dahdi show channel";
15487       e->usage =
15488          "Usage: dahdi show channel <chan num>\n"
15489          "  Detailed information about a given channel\n";
15490       return NULL;
15491    case CLI_GENERATE:
15492       return NULL;
15493    }
15494 
15495    if (a->argc != 4)
15496       return CLI_SHOWUSAGE;
15497 
15498    channel = atoi(a->argv[3]);
15499 
15500    ast_mutex_lock(&iflock);
15501    for (tmp = iflist; tmp; tmp = tmp->next) {
15502       if (tmp->channel == channel) {
15503          ast_cli(a->fd, "Channel: %d\n", tmp->channel);
15504          ast_cli(a->fd, "File Descriptor: %d\n", tmp->subs[SUB_REAL].dfd);
15505          ast_cli(a->fd, "Span: %d\n", tmp->span);
15506          ast_cli(a->fd, "Extension: %s\n", tmp->exten);
15507          ast_cli(a->fd, "Dialing: %s\n", tmp->dialing ? "yes" : "no");
15508          ast_cli(a->fd, "Context: %s\n", tmp->context);
15509          ast_cli(a->fd, "Caller ID: %s\n", tmp->cid_num);
15510          ast_cli(a->fd, "Calling TON: %d\n", tmp->cid_ton);
15511 #if defined(HAVE_PRI)
15512 #if defined(HAVE_PRI_SUBADDR)
15513          ast_cli(a->fd, "Caller ID subaddress: %s\n", tmp->cid_subaddr);
15514 #endif   /* defined(HAVE_PRI_SUBADDR) */
15515 #endif   /* defined(HAVE_PRI) */
15516          ast_cli(a->fd, "Caller ID name: %s\n", tmp->cid_name);
15517          ast_cli(a->fd, "Mailbox: %s\n", S_OR(tmp->mailbox, "none"));
15518          if (tmp->vars) {
15519             struct ast_variable *v;
15520             ast_cli(a->fd, "Variables:\n");
15521             for (v = tmp->vars ; v ; v = v->next)
15522                ast_cli(a->fd, "       %s = %s\n", v->name, v->value);
15523          }
15524          ast_cli(a->fd, "Destroy: %d\n", tmp->destroy);
15525          ast_cli(a->fd, "InAlarm: %d\n", tmp->inalarm);
15526          ast_cli(a->fd, "Signalling Type: %s\n", sig2str(tmp->sig));
15527          ast_cli(a->fd, "Radio: %d\n", tmp->radio);
15528          ast_cli(a->fd, "Owner: %s\n", tmp->owner ? tmp->owner->name : "<None>");
15529          ast_cli(a->fd, "Real: %s%s%s\n", tmp->subs[SUB_REAL].owner ? tmp->subs[SUB_REAL].owner->name : "<None>", tmp->subs[SUB_REAL].inthreeway ? " (Confed)" : "", tmp->subs[SUB_REAL].linear ? " (Linear)" : "");
15530          ast_cli(a->fd, "Callwait: %s%s%s\n", tmp->subs[SUB_CALLWAIT].owner ? tmp->subs[SUB_CALLWAIT].owner->name : "<None>", tmp->subs[SUB_CALLWAIT].inthreeway ? " (Confed)" : "", tmp->subs[SUB_CALLWAIT].linear ? " (Linear)" : "");
15531          ast_cli(a->fd, "Threeway: %s%s%s\n", tmp->subs[SUB_THREEWAY].owner ? tmp->subs[SUB_THREEWAY].owner->name : "<None>", tmp->subs[SUB_THREEWAY].inthreeway ? " (Confed)" : "", tmp->subs[SUB_THREEWAY].linear ? " (Linear)" : "");
15532          ast_cli(a->fd, "Confno: %d\n", tmp->confno);
15533          ast_cli(a->fd, "Propagated Conference: %d\n", tmp->propconfno);
15534          ast_cli(a->fd, "Real in conference: %d\n", tmp->inconference);
15535          ast_cli(a->fd, "DSP: %s\n", tmp->dsp ? "yes" : "no");
15536          ast_cli(a->fd, "Busy Detection: %s\n", tmp->busydetect ? "yes" : "no");
15537          if (tmp->busydetect) {
15538 #if defined(BUSYDETECT_TONEONLY)
15539             ast_cli(a->fd, "    Busy Detector Helper: BUSYDETECT_TONEONLY\n");
15540 #elif defined(BUSYDETECT_COMPARE_TONE_AND_SILENCE)
15541             ast_cli(a->fd, "    Busy Detector Helper: BUSYDETECT_COMPARE_TONE_AND_SILENCE\n");
15542 #endif
15543 #ifdef BUSYDETECT_DEBUG
15544             ast_cli(a->fd, "    Busy Detector Debug: Enabled\n");
15545 #endif
15546             ast_cli(a->fd, "    Busy Count: %d\n", tmp->busycount);
15547             ast_cli(a->fd, "    Busy Pattern: %d,%d\n", tmp->busytonelength, tmp->busyquietlength);
15548          }
15549          ast_cli(a->fd, "TDD: %s\n", tmp->tdd ? "yes" : "no");
15550          ast_cli(a->fd, "Relax DTMF: %s\n", tmp->dtmfrelax ? "yes" : "no");
15551          ast_cli(a->fd, "Dialing/CallwaitCAS: %d/%d\n", tmp->dialing, tmp->callwaitcas);
15552          ast_cli(a->fd, "Default law: %s\n", tmp->law_default == DAHDI_LAW_MULAW ? "ulaw" : tmp->law_default == DAHDI_LAW_ALAW ? "alaw" : "unknown");
15553          ast_cli(a->fd, "Fax Handled: %s\n", tmp->faxhandled ? "yes" : "no");
15554          ast_cli(a->fd, "Pulse phone: %s\n", tmp->pulsedial ? "yes" : "no");
15555          ast_cli(a->fd, "Gains (RX/TX): %.2f/%.2f\n", tmp->rxgain, tmp->txgain);
15556          ast_cli(a->fd, "Dynamic Range Compression (RX/TX): %.2f/%.2f\n", tmp->rxdrc, tmp->txdrc);
15557          ast_cli(a->fd, "DND: %s\n", dahdi_dnd(tmp, -1) ? "yes" : "no");
15558          ast_cli(a->fd, "Echo Cancellation:\n");
15559 
15560          if (tmp->echocancel.head.tap_length) {
15561             ast_cli(a->fd, "\t%u taps\n", tmp->echocancel.head.tap_length);
15562             for (x = 0; x < tmp->echocancel.head.param_count; x++) {
15563                ast_cli(a->fd, "\t\t%s: %dd\n", tmp->echocancel.params[x].name, tmp->echocancel.params[x].value);
15564             }
15565             ast_cli(a->fd, "\t%scurrently %s\n", tmp->echocanbridged ? "" : "(unless TDM bridged) ", tmp->echocanon ? "ON" : "OFF");
15566          } else {
15567             ast_cli(a->fd, "\tnone\n");
15568          }
15569          ast_cli(a->fd, "Wait for dialtone: %dms\n", tmp->waitfordialtone);
15570          if (tmp->master)
15571             ast_cli(a->fd, "Master Channel: %d\n", tmp->master->channel);
15572          for (x = 0; x < MAX_SLAVES; x++) {
15573             if (tmp->slaves[x])
15574                ast_cli(a->fd, "Slave Channel: %d\n", tmp->slaves[x]->channel);
15575          }
15576 #ifdef HAVE_OPENR2
15577          if (tmp->mfcr2) {
15578             char calldir[OR2_MAX_PATH];
15579             openr2_context_t *r2context = openr2_chan_get_context(tmp->r2chan);
15580             openr2_variant_t r2variant = openr2_context_get_variant(r2context);
15581             ast_cli(a->fd, "MFC/R2 MF State: %s\n", openr2_chan_get_mf_state_string(tmp->r2chan));
15582             ast_cli(a->fd, "MFC/R2 MF Group: %s\n", openr2_chan_get_mf_group_string(tmp->r2chan));
15583             ast_cli(a->fd, "MFC/R2 State: %s\n", openr2_chan_get_r2_state_string(tmp->r2chan));
15584             ast_cli(a->fd, "MFC/R2 Call State: %s\n", openr2_chan_get_call_state_string(tmp->r2chan));
15585             ast_cli(a->fd, "MFC/R2 Call Files Enabled: %s\n", openr2_chan_get_call_files_enabled(tmp->r2chan) ? "Yes" : "No");
15586             ast_cli(a->fd, "MFC/R2 Variant: %s\n", openr2_proto_get_variant_string(r2variant));
15587             ast_cli(a->fd, "MFC/R2 Max ANI: %d\n", openr2_context_get_max_ani(r2context));
15588             ast_cli(a->fd, "MFC/R2 Max DNIS: %d\n", openr2_context_get_max_dnis(r2context));
15589             ast_cli(a->fd, "MFC/R2 Get ANI First: %s\n", openr2_context_get_ani_first(r2context) ? "Yes" : "No");
15590 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
15591             ast_cli(a->fd, "MFC/R2 Skip Category Request: %s\n", openr2_context_get_skip_category_request(r2context) ? "Yes" : "No");
15592 #endif
15593             ast_cli(a->fd, "MFC/R2 Immediate Accept: %s\n", openr2_context_get_immediate_accept(r2context) ? "Yes" : "No");
15594             ast_cli(a->fd, "MFC/R2 Accept on Offer: %s\n", tmp->mfcr2_accept_on_offer ? "Yes" : "No");
15595             ast_cli(a->fd, "MFC/R2 Charge Calls: %s\n", tmp->mfcr2_charge_calls ? "Yes" : "No");
15596             ast_cli(a->fd, "MFC/R2 Allow Collect Calls: %s\n", tmp->mfcr2_allow_collect_calls ? "Yes" : "No");
15597             ast_cli(a->fd, "MFC/R2 Forced Release: %s\n", tmp->mfcr2_forced_release ? "Yes" : "No");
15598             ast_cli(a->fd, "MFC/R2 MF Back Timeout: %dms\n", openr2_context_get_mf_back_timeout(r2context));
15599             ast_cli(a->fd, "MFC/R2 R2 Metering Pulse Timeout: %dms\n", openr2_context_get_metering_pulse_timeout(r2context));
15600             ast_cli(a->fd, "MFC/R2 Rx CAS: %s\n", openr2_chan_get_rx_cas_string(tmp->r2chan));
15601             ast_cli(a->fd, "MFC/R2 Tx CAS: %s\n", openr2_chan_get_tx_cas_string(tmp->r2chan));
15602             ast_cli(a->fd, "MFC/R2 MF Tx Signal: %d\n", openr2_chan_get_tx_mf_signal(tmp->r2chan));
15603             ast_cli(a->fd, "MFC/R2 MF Rx Signal: %d\n", openr2_chan_get_rx_mf_signal(tmp->r2chan));
15604             ast_cli(a->fd, "MFC/R2 Call Files Directory: %s\n", openr2_context_get_log_directory(r2context, calldir, sizeof(calldir)));
15605          }
15606 #endif
15607 #if defined(HAVE_SS7)
15608          if (tmp->ss7) {
15609             struct sig_ss7_chan *chan = tmp->sig_pvt;
15610 
15611             ast_cli(a->fd, "CIC: %d\n", chan->cic);
15612          }
15613 #endif   /* defined(HAVE_SS7) */
15614 #ifdef HAVE_PRI
15615          if (tmp->pri) {
15616             struct sig_pri_chan *chan = tmp->sig_pvt;
15617 
15618             ast_cli(a->fd, "PRI Flags: ");
15619             if (chan->resetting != SIG_PRI_RESET_IDLE) {
15620                ast_cli(a->fd, "Resetting=%u ", chan->resetting);
15621             }
15622             if (chan->call)
15623                ast_cli(a->fd, "Call ");
15624             if (chan->allocated) {
15625                ast_cli(a->fd, "Allocated ");
15626             }
15627             ast_cli(a->fd, "\n");
15628             if (tmp->logicalspan)
15629                ast_cli(a->fd, "PRI Logical Span: %d\n", tmp->logicalspan);
15630             else
15631                ast_cli(a->fd, "PRI Logical Span: Implicit\n");
15632          }
15633 #endif
15634          memset(&ci, 0, sizeof(ci));
15635          ps.channo = tmp->channel;
15636          if (tmp->subs[SUB_REAL].dfd > -1) {
15637             memset(&ci, 0, sizeof(ci));
15638             if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
15639                ast_cli(a->fd, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci.confno, (unsigned)ci.confmode);
15640             }
15641             if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONFMUTE, &x)) {
15642                ast_cli(a->fd, "Actual Confmute: %s\n", x ? "Yes" : "No");
15643             }
15644             memset(&ps, 0, sizeof(ps));
15645             if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
15646                ast_log(LOG_WARNING, "Failed to get parameters on channel %d: %s\n", tmp->channel, strerror(errno));
15647             } else {
15648                ast_cli(a->fd, "Hookstate (FXS only): %s\n", ps.rxisoffhook ? "Offhook" : "Onhook");
15649             }
15650          }
15651          if (ISTRUNK(tmp)) {
15652             ast_cli(a->fd, "Call Progress: %s\n", tmp->callprogress ? "yes" : "no");  
15653             if (!ast_strlen_zero(progzone))
15654                ast_cli(a->fd, "Progress Zone: %s\n", progzone);
15655             ast_cli(a->fd, "Busy Detect: %s\n", tmp->busydetect ? "yes" : "no");  
15656             if(tmp->busydetect) {
15657                ast_cli(a->fd, "Busy Count: %d\n", tmp->busycount);
15658                if(tmp->busytonelength > 0) {
15659                   ast_cli(a->fd, "Busy Pattern:\n");
15660                   ast_cli(a->fd, " -- Tone Length: %6d ms\n", tmp->busytonelength);
15661                   if (tmp->busyquietlength > 0) 
15662                      ast_cli(a->fd, " -- Quiet Length: %6d ms\n", tmp->busyquietlength);
15663                   else 
15664                      ast_cli(a->fd, " -- Detect Tone Only\n");
15665                   if(tmp->busyfuzziness > 0)
15666                      ast_cli(a->fd, "Busy Pattern Fuziness: %d\n", tmp->busyfuzziness);
15667                }
15668             }
15669          }
15670          ast_mutex_unlock(&iflock);
15671          return CLI_SUCCESS;
15672       }
15673    }
15674    ast_mutex_unlock(&iflock);
15675 
15676    ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15677    return CLI_FAILURE;
15678 }
15679 
15680 static char *handle_dahdi_show_cadences(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15681 {
15682    int i, j;
15683    switch (cmd) {
15684    case CLI_INIT:
15685       e->command = "dahdi show cadences";
15686       e->usage =
15687          "Usage: dahdi show cadences\n"
15688          "       Shows all cadences currently defined\n";
15689       return NULL;
15690    case CLI_GENERATE:
15691       return NULL;
15692    }
15693    for (i = 0; i < num_cadence; i++) {
15694       char output[1024];
15695       char tmp[16], tmp2[64];
15696       snprintf(tmp, sizeof(tmp), "r%d: ", i + 1);
15697       term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output));
15698 
15699       for (j = 0; j < 16; j++) {
15700          if (cadences[i].ringcadence[j] == 0)
15701             break;
15702          snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]);
15703          if (cidrings[i] * 2 - 1 == j)
15704             term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1);
15705          else
15706             term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1);
15707          if (j != 0)
15708             strncat(output, ",", sizeof(output) - strlen(output) - 1);
15709          strncat(output, tmp2, sizeof(output) - strlen(output) - 1);
15710       }
15711       ast_cli(a->fd,"%s\n",output);
15712    }
15713    return CLI_SUCCESS;
15714 }
15715 
15716 /* Based on irqmiss.c */
15717 static char *dahdi_show_status(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15718 {
15719    #define FORMAT "%-40.40s %-7.7s %-6d %-6d %-6d %-3.3s %-4.4s %-8.8s %s\n"
15720    #define FORMAT2 "%-40.40s %-7.7s %-6.6s %-6.6s %-6.6s %-3.3s %-4.4s %-8.8s %s\n"
15721    int span;
15722    int res;
15723    char alarmstr[50];
15724 
15725    int ctl;
15726    struct dahdi_spaninfo s;
15727 
15728    switch (cmd) {
15729    case CLI_INIT:
15730       e->command = "dahdi show status";
15731       e->usage =
15732          "Usage: dahdi show status\n"
15733          "       Shows a list of DAHDI cards with status\n";
15734       return NULL;
15735    case CLI_GENERATE:
15736       return NULL;
15737    }
15738    ctl = open("/dev/dahdi/ctl", O_RDWR);
15739    if (ctl < 0) {
15740       ast_cli(a->fd, "No DAHDI found. Unable to open /dev/dahdi/ctl: %s\n", strerror(errno));
15741       return CLI_FAILURE;
15742    }
15743    ast_cli(a->fd, FORMAT2, "Description", "Alarms", "IRQ", "bpviol", "CRC", "Framing", "Coding", "Options", "LBO");
15744 
15745    for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
15746       s.spanno = span;
15747       res = ioctl(ctl, DAHDI_SPANSTAT, &s);
15748       if (res) {
15749          continue;
15750       }
15751       alarmstr[0] = '\0';
15752       if (s.alarms > 0) {
15753          if (s.alarms & DAHDI_ALARM_BLUE)
15754             strcat(alarmstr, "BLU/");
15755          if (s.alarms & DAHDI_ALARM_YELLOW)
15756             strcat(alarmstr, "YEL/");
15757          if (s.alarms & DAHDI_ALARM_RED)
15758             strcat(alarmstr, "RED/");
15759          if (s.alarms & DAHDI_ALARM_LOOPBACK)
15760             strcat(alarmstr, "LB/");
15761          if (s.alarms & DAHDI_ALARM_RECOVER)
15762             strcat(alarmstr, "REC/");
15763          if (s.alarms & DAHDI_ALARM_NOTOPEN)
15764             strcat(alarmstr, "NOP/");
15765          if (!strlen(alarmstr))
15766             strcat(alarmstr, "UUU/");
15767          if (strlen(alarmstr)) {
15768             /* Strip trailing / */
15769             alarmstr[strlen(alarmstr) - 1] = '\0';
15770          }
15771       } else {
15772          if (s.numchans)
15773             strcpy(alarmstr, "OK");
15774          else
15775             strcpy(alarmstr, "UNCONFIGURED");
15776       }
15777 
15778       ast_cli(a->fd, FORMAT, s.desc, alarmstr, s.irqmisses, s.bpvcount, s.crc4count,
15779          s.lineconfig & DAHDI_CONFIG_D4 ? "D4" :
15780          s.lineconfig & DAHDI_CONFIG_ESF ? "ESF" :
15781          s.lineconfig & DAHDI_CONFIG_CCS ? "CCS" :
15782          "CAS",
15783          s.lineconfig & DAHDI_CONFIG_B8ZS ? "B8ZS" :
15784          s.lineconfig & DAHDI_CONFIG_HDB3 ? "HDB3" :
15785          s.lineconfig & DAHDI_CONFIG_AMI ? "AMI" :
15786          "Unk",
15787          s.lineconfig & DAHDI_CONFIG_CRC4 ?
15788             s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" :
15789             s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "YEL" : "",
15790          lbostr[s.lbo]
15791          );
15792    }
15793    close(ctl);
15794 
15795    return CLI_SUCCESS;
15796 #undef FORMAT
15797 #undef FORMAT2
15798 }
15799 
15800 static char *dahdi_show_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15801 {
15802    int pseudo_fd = -1;
15803    struct dahdi_versioninfo vi;
15804 
15805    switch (cmd) {
15806    case CLI_INIT:
15807       e->command = "dahdi show version";
15808       e->usage =
15809          "Usage: dahdi show version\n"
15810          "       Shows the DAHDI version in use\n";
15811       return NULL;
15812    case CLI_GENERATE:
15813       return NULL;
15814    }
15815    if ((pseudo_fd = open("/dev/dahdi/ctl", O_RDONLY)) < 0) {
15816       ast_cli(a->fd, "Failed to open control file to get version.\n");
15817       return CLI_SUCCESS;
15818    }
15819 
15820    strcpy(vi.version, "Unknown");
15821    strcpy(vi.echo_canceller, "Unknown");
15822 
15823    if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi))
15824       ast_cli(a->fd, "Failed to get DAHDI version: %s\n", strerror(errno));
15825    else
15826       ast_cli(a->fd, "DAHDI Version: %s Echo Canceller: %s\n", vi.version, vi.echo_canceller);
15827 
15828    close(pseudo_fd);
15829 
15830    return CLI_SUCCESS;
15831 }
15832 
15833 static char *dahdi_set_hwgain(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15834 {
15835    int channel;
15836    int gain;
15837    int tx;
15838    struct dahdi_hwgain hwgain;
15839    struct dahdi_pvt *tmp = NULL;
15840 
15841    switch (cmd) {
15842    case CLI_INIT:
15843       e->command = "dahdi set hwgain {rx|tx}";
15844       e->usage =
15845          "Usage: dahdi set hwgain <rx|tx> <chan#> <gain>\n"
15846          "   Sets the hardware gain on a given channel.  Changes take effect\n"
15847          "   immediately whether the channel is in use or not.\n"
15848          "\n"
15849          "   <rx|tx> which direction do you want to change (relative to our module)\n"
15850          "   <chan num> is the channel number relative to the device\n"
15851          "   <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n"
15852          "\n"
15853          "   Please note:\n"
15854          "   * This is currently the only way to set hwgain by the channel driver.\n"
15855          "   * hwgain is only supportable by hardware with analog ports because\n"
15856          "     hwgain works on the analog side of an analog-digital conversion.\n";
15857       return NULL;
15858    case CLI_GENERATE:
15859       return NULL;
15860    }
15861 
15862    if (a->argc != 6)
15863       return CLI_SHOWUSAGE;
15864 
15865    if (!strcasecmp("rx", a->argv[3]))
15866       tx = 0; /* rx */
15867    else if (!strcasecmp("tx", a->argv[3]))
15868       tx = 1; /* tx */
15869    else
15870       return CLI_SHOWUSAGE;
15871 
15872    channel = atoi(a->argv[4]);
15873    gain = atof(a->argv[5])*10.0;
15874 
15875    ast_mutex_lock(&iflock);
15876 
15877    for (tmp = iflist; tmp; tmp = tmp->next) {
15878 
15879       if (tmp->channel != channel)
15880          continue;
15881 
15882       if (tmp->subs[SUB_REAL].dfd == -1)
15883          break;
15884 
15885       hwgain.newgain = gain;
15886       hwgain.tx = tx;
15887       if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_HWGAIN, &hwgain) < 0) {
15888          ast_cli(a->fd, "Unable to set the hardware gain for channel %d: %s\n", channel, strerror(errno));
15889          ast_mutex_unlock(&iflock);
15890          return CLI_FAILURE;
15891       }
15892       ast_cli(a->fd, "hardware %s gain set to %d (%.1f dB) on channel %d\n",
15893          tx ? "tx" : "rx", gain, (float)gain/10.0, channel);
15894       break;
15895    }
15896 
15897    ast_mutex_unlock(&iflock);
15898 
15899    if (tmp)
15900       return CLI_SUCCESS;
15901 
15902    ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15903    return CLI_FAILURE;
15904 
15905 }
15906 
15907 static char *dahdi_set_swgain(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15908 {
15909    int channel;
15910    float gain;
15911    int tx;
15912    int res;
15913    struct dahdi_pvt *tmp = NULL;
15914 
15915    switch (cmd) {
15916    case CLI_INIT:
15917       e->command = "dahdi set swgain {rx|tx}";
15918       e->usage =
15919          "Usage: dahdi set swgain <rx|tx> <chan#> <gain>\n"
15920          "   Sets the software gain on a given channel and overrides the\n"
15921          "   value provided at module loadtime.  Changes take effect\n"
15922          "   immediately whether the channel is in use or not.\n"
15923          "\n"
15924          "   <rx|tx> which direction do you want to change (relative to our module)\n"
15925          "   <chan num> is the channel number relative to the device\n"
15926          "   <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
15927       return NULL;
15928    case CLI_GENERATE:
15929       return NULL;
15930    }
15931 
15932    if (a->argc != 6)
15933       return CLI_SHOWUSAGE;
15934 
15935    if (!strcasecmp("rx", a->argv[3]))
15936       tx = 0; /* rx */
15937    else if (!strcasecmp("tx", a->argv[3]))
15938       tx = 1; /* tx */
15939    else
15940       return CLI_SHOWUSAGE;
15941 
15942    channel = atoi(a->argv[4]);
15943    gain = atof(a->argv[5]);
15944 
15945    ast_mutex_lock(&iflock);
15946    for (tmp = iflist; tmp; tmp = tmp->next) {
15947 
15948       if (tmp->channel != channel)
15949          continue;
15950 
15951       if (tmp->subs[SUB_REAL].dfd == -1)
15952          break;
15953 
15954       if (tx)
15955          res = set_actual_txgain(tmp->subs[SUB_REAL].dfd, gain, tmp->txdrc, tmp->law);
15956       else
15957          res = set_actual_rxgain(tmp->subs[SUB_REAL].dfd, gain, tmp->rxdrc, tmp->law);
15958 
15959       if (res) {
15960          ast_cli(a->fd, "Unable to set the software gain for channel %d\n", channel);
15961          ast_mutex_unlock(&iflock);
15962          return CLI_FAILURE;
15963       }
15964 
15965       ast_cli(a->fd, "software %s gain set to %.1f on channel %d\n",
15966          tx ? "tx" : "rx", gain, channel);
15967 
15968       if (tx) {
15969          tmp->txgain = gain;
15970       } else {
15971          tmp->rxgain = gain;
15972       }
15973       break;
15974    }
15975    ast_mutex_unlock(&iflock);
15976 
15977    if (tmp)
15978       return CLI_SUCCESS;
15979 
15980    ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15981    return CLI_FAILURE;
15982 
15983 }
15984 
15985 static char *dahdi_set_dnd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15986 {
15987    int channel;
15988    int on;
15989    struct dahdi_pvt *dahdi_chan = NULL;
15990 
15991    switch (cmd) {
15992    case CLI_INIT:
15993       e->command = "dahdi set dnd";
15994       e->usage =
15995          "Usage: dahdi set dnd <chan#> <on|off>\n"
15996          "  Sets/resets DND (Do Not Disturb) mode on a channel.\n"
15997          "  Changes take effect immediately.\n"
15998          "  <chan num> is the channel number\n"
15999          "  <on|off> Enable or disable DND mode?\n"
16000          ;
16001       return NULL;
16002    case CLI_GENERATE:
16003       return NULL;
16004    }
16005 
16006    if (a->argc != 5)
16007       return CLI_SHOWUSAGE;
16008 
16009    if ((channel = atoi(a->argv[3])) <= 0) {
16010       ast_cli(a->fd, "Expected channel number, got '%s'\n", a->argv[3]);
16011       return CLI_SHOWUSAGE;
16012    }
16013 
16014    if (ast_true(a->argv[4]))
16015       on = 1;
16016    else if (ast_false(a->argv[4]))
16017       on = 0;
16018    else {
16019       ast_cli(a->fd, "Expected 'on' or 'off', got '%s'\n", a->argv[4]);
16020       return CLI_SHOWUSAGE;
16021    }
16022 
16023    ast_mutex_lock(&iflock);
16024    for (dahdi_chan = iflist; dahdi_chan; dahdi_chan = dahdi_chan->next) {
16025       if (dahdi_chan->channel != channel)
16026          continue;
16027 
16028       /* Found the channel. Actually set it */
16029       dahdi_dnd(dahdi_chan, on);
16030       break;
16031    }
16032    ast_mutex_unlock(&iflock);
16033 
16034    if (!dahdi_chan) {
16035       ast_cli(a->fd, "Unable to find given channel %d\n", channel);
16036       return CLI_FAILURE;
16037    }
16038 
16039    return CLI_SUCCESS;
16040 }
16041 
16042 static struct ast_cli_entry dahdi_cli[] = {
16043    AST_CLI_DEFINE(handle_dahdi_show_cadences, "List cadences"),
16044    AST_CLI_DEFINE(dahdi_show_channels, "Show active DAHDI channels"),
16045    AST_CLI_DEFINE(dahdi_show_channel, "Show information on a channel"),
16046    AST_CLI_DEFINE(dahdi_destroy_channel, "Destroy a channel"),
16047    AST_CLI_DEFINE(dahdi_restart_cmd, "Fully restart DAHDI channels"),
16048    AST_CLI_DEFINE(dahdi_show_status, "Show all DAHDI cards status"),
16049    AST_CLI_DEFINE(dahdi_show_version, "Show the DAHDI version in use"),
16050    AST_CLI_DEFINE(dahdi_set_hwgain, "Set hardware gain on a channel"),
16051    AST_CLI_DEFINE(dahdi_set_swgain, "Set software gain on a channel"),
16052    AST_CLI_DEFINE(dahdi_set_dnd, "Sets/resets DND (Do Not Disturb) mode on a channel"),
16053 };
16054 
16055 #define TRANSFER  0
16056 #define HANGUP    1
16057 
16058 static int dahdi_fake_event(struct dahdi_pvt *p, int mode)
16059 {
16060    if (p) {
16061       switch (mode) {
16062       case TRANSFER:
16063          p->fake_event = DAHDI_EVENT_WINKFLASH;
16064          break;
16065       case HANGUP:
16066          p->fake_event = DAHDI_EVENT_ONHOOK;
16067          break;
16068       default:
16069          ast_log(LOG_WARNING, "I don't know how to handle transfer event with this: %d on channel %s\n",mode, p->owner->name);
16070       }
16071    }
16072    return 0;
16073 }
16074 static struct dahdi_pvt *find_channel(int channel)
16075 {
16076    struct dahdi_pvt *p;
16077 
16078    ast_mutex_lock(&iflock);
16079    for (p = iflist; p; p = p->next) {
16080       if (p->channel == channel) {
16081          break;
16082       }
16083    }
16084    ast_mutex_unlock(&iflock);
16085    return p;
16086 }
16087 
16088 /*!
16089  * \internal
16090  * \brief Get private struct using given numeric channel string.
16091  *
16092  * \param channel Numeric channel number string get private struct.
16093  *
16094  * \retval pvt on success.
16095  * \retval NULL on error.
16096  */
16097 static struct dahdi_pvt *find_channel_from_str(const char *channel)
16098 {
16099    int chan_num;
16100 
16101    if (sscanf(channel, "%30d", &chan_num) != 1) {
16102       /* Not numeric string. */
16103       return NULL;
16104    }
16105 
16106    return find_channel(chan_num);
16107 }
16108 
16109 static int action_dahdidndon(struct mansession *s, const struct message *m)
16110 {
16111    struct dahdi_pvt *p;
16112    const char *channel = astman_get_header(m, "DAHDIChannel");
16113 
16114    if (ast_strlen_zero(channel)) {
16115       astman_send_error(s, m, "No channel specified");
16116       return 0;
16117    }
16118    p = find_channel_from_str(channel);
16119    if (!p) {
16120       astman_send_error(s, m, "No such channel");
16121       return 0;
16122    }
16123    dahdi_dnd(p, 1);
16124    astman_send_ack(s, m, "DND Enabled");
16125    return 0;
16126 }
16127 
16128 static int action_dahdidndoff(struct mansession *s, const struct message *m)
16129 {
16130    struct dahdi_pvt *p;
16131    const char *channel = astman_get_header(m, "DAHDIChannel");
16132 
16133    if (ast_strlen_zero(channel)) {
16134       astman_send_error(s, m, "No channel specified");
16135       return 0;
16136    }
16137    p = find_channel_from_str(channel);
16138    if (!p) {
16139       astman_send_error(s, m, "No such channel");
16140       return 0;
16141    }
16142    dahdi_dnd(p, 0);
16143    astman_send_ack(s, m, "DND Disabled");
16144    return 0;
16145 }
16146 
16147 static int action_transfer(struct mansession *s, const struct message *m)
16148 {
16149    struct dahdi_pvt *p;
16150    const char *channel = astman_get_header(m, "DAHDIChannel");
16151 
16152    if (ast_strlen_zero(channel)) {
16153       astman_send_error(s, m, "No channel specified");
16154       return 0;
16155    }
16156    p = find_channel_from_str(channel);
16157    if (!p) {
16158       astman_send_error(s, m, "No such channel");
16159       return 0;
16160    }
16161    if (!analog_lib_handles(p->sig, 0, 0)) {
16162       astman_send_error(s, m, "Channel signaling is not analog");
16163       return 0;
16164    }
16165    dahdi_fake_event(p,TRANSFER);
16166    astman_send_ack(s, m, "DAHDITransfer");
16167    return 0;
16168 }
16169 
16170 static int action_transferhangup(struct mansession *s, const struct message *m)
16171 {
16172    struct dahdi_pvt *p;
16173    const char *channel = astman_get_header(m, "DAHDIChannel");
16174 
16175    if (ast_strlen_zero(channel)) {
16176       astman_send_error(s, m, "No channel specified");
16177       return 0;
16178    }
16179    p = find_channel_from_str(channel);
16180    if (!p) {
16181       astman_send_error(s, m, "No such channel");
16182       return 0;
16183    }
16184    if (!analog_lib_handles(p->sig, 0, 0)) {
16185       astman_send_error(s, m, "Channel signaling is not analog");
16186       return 0;
16187    }
16188    dahdi_fake_event(p,HANGUP);
16189    astman_send_ack(s, m, "DAHDIHangup");
16190    return 0;
16191 }
16192 
16193 static int action_dahdidialoffhook(struct mansession *s, const struct message *m)
16194 {
16195    struct dahdi_pvt *p;
16196    const char *channel = astman_get_header(m, "DAHDIChannel");
16197    const char *number = astman_get_header(m, "Number");
16198    int i;
16199 
16200    if (ast_strlen_zero(channel)) {
16201       astman_send_error(s, m, "No channel specified");
16202       return 0;
16203    }
16204    if (ast_strlen_zero(number)) {
16205       astman_send_error(s, m, "No number specified");
16206       return 0;
16207    }
16208    p = find_channel_from_str(channel);
16209    if (!p) {
16210       astman_send_error(s, m, "No such channel");
16211       return 0;
16212    }
16213    if (!p->owner) {
16214       astman_send_error(s, m, "Channel does not have it's owner");
16215       return 0;
16216    }
16217    for (i = 0; i < strlen(number); i++) {
16218       struct ast_frame f = { AST_FRAME_DTMF, .subclass.integer = number[i] };
16219       dahdi_queue_frame(p, &f);
16220    }
16221    astman_send_ack(s, m, "DAHDIDialOffhook");
16222    return 0;
16223 }
16224 
16225 static int action_dahdishowchannels(struct mansession *s, const struct message *m)
16226 {
16227    struct dahdi_pvt *tmp = NULL;
16228    const char *id = astman_get_header(m, "ActionID");
16229    const char *dahdichannel = astman_get_header(m, "DAHDIChannel");
16230    char idText[256] = "";
16231    int channels = 0;
16232    int dahdichanquery;
16233 
16234    if (!dahdichannel || sscanf(dahdichannel, "%30d", &dahdichanquery) != 1) {
16235       /* Not numeric string. */
16236       dahdichanquery = -1;
16237    }
16238 
16239    astman_send_ack(s, m, "DAHDI channel status will follow");
16240    if (!ast_strlen_zero(id))
16241       snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
16242 
16243    ast_mutex_lock(&iflock);
16244 
16245    for (tmp = iflist; tmp; tmp = tmp->next) {
16246       if (tmp->channel > 0) {
16247          int alm;
16248 
16249          /* If a specific channel is queried for, only deliver status for that channel */
16250          if (dahdichanquery > 0 && tmp->channel != dahdichanquery)
16251             continue;
16252 
16253          alm = get_alarms(tmp);
16254          channels++;
16255          if (tmp->owner) {
16256             /* Add data if we have a current call */
16257             astman_append(s,
16258                "Event: DAHDIShowChannels\r\n"
16259                "DAHDIChannel: %d\r\n"
16260                "Channel: %s\r\n"
16261                "Uniqueid: %s\r\n"
16262                "AccountCode: %s\r\n"
16263                "Signalling: %s\r\n"
16264                "SignallingCode: %d\r\n"
16265                "Context: %s\r\n"
16266                "DND: %s\r\n"
16267                "Alarm: %s\r\n"
16268                "%s"
16269                "\r\n",
16270                tmp->channel,
16271                tmp->owner->name,
16272                tmp->owner->uniqueid,
16273                tmp->owner->accountcode,
16274                sig2str(tmp->sig),
16275                tmp->sig,
16276                tmp->context,
16277                dahdi_dnd(tmp, -1) ? "Enabled" : "Disabled",
16278                alarm2str(alm), idText);
16279          } else {
16280             astman_append(s,
16281                "Event: DAHDIShowChannels\r\n"
16282                "DAHDIChannel: %d\r\n"
16283                "Signalling: %s\r\n"
16284                "SignallingCode: %d\r\n"
16285                "Context: %s\r\n"
16286                "DND: %s\r\n"
16287                "Alarm: %s\r\n"
16288                "%s"
16289                "\r\n",
16290                tmp->channel, sig2str(tmp->sig), tmp->sig,
16291                tmp->context,
16292                dahdi_dnd(tmp, -1) ? "Enabled" : "Disabled",
16293                alarm2str(alm), idText);
16294          }
16295       }
16296    }
16297 
16298    ast_mutex_unlock(&iflock);
16299 
16300    astman_append(s,
16301       "Event: DAHDIShowChannelsComplete\r\n"
16302       "%s"
16303       "Items: %d\r\n"
16304       "\r\n",
16305       idText,
16306       channels);
16307    return 0;
16308 }
16309 
16310 #if defined(HAVE_SS7)
16311 static int linkset_addsigchan(int sigchan)
16312 {
16313    struct dahdi_ss7 *link;
16314    int res;
16315    int curfd;
16316    struct dahdi_params params;
16317    struct dahdi_bufferinfo bi;
16318    struct dahdi_spaninfo si;
16319 
16320    if (sigchan < 0) {
16321       ast_log(LOG_ERROR, "Invalid sigchan!\n");
16322       return -1;
16323    }
16324    if (cur_ss7type < 0) {
16325       ast_log(LOG_ERROR, "Unspecified or invalid ss7type\n");
16326       return -1;
16327    }
16328    if (cur_pointcode < 0) {
16329       ast_log(LOG_ERROR, "Unspecified pointcode!\n");
16330       return -1;
16331    }
16332    if (cur_adjpointcode < 0) {
16333       ast_log(LOG_ERROR, "Unspecified adjpointcode!\n");
16334       return -1;
16335    }
16336    if (cur_defaultdpc < 0) {
16337       ast_log(LOG_ERROR, "Unspecified defaultdpc!\n");
16338       return -1;
16339    }
16340    if (cur_networkindicator < 0) {
16341       ast_log(LOG_ERROR, "Invalid networkindicator!\n");
16342       return -1;
16343    }
16344    link = ss7_resolve_linkset(cur_linkset);
16345    if (!link) {
16346       ast_log(LOG_ERROR, "Invalid linkset number.  Must be between 1 and %d\n", NUM_SPANS + 1);
16347       return -1;
16348    }
16349    if (link->ss7.numsigchans >= SIG_SS7_NUM_DCHANS) {
16350       ast_log(LOG_ERROR, "Too many sigchans on linkset %d\n", cur_linkset);
16351       return -1;
16352    }
16353 
16354    curfd = link->ss7.numsigchans;
16355 
16356    /* Open signaling channel */
16357    link->ss7.fds[curfd] = open("/dev/dahdi/channel", O_RDWR, 0600);
16358    if (link->ss7.fds[curfd] < 0) {
16359       ast_log(LOG_ERROR, "Unable to open SS7 sigchan %d (%s)\n", sigchan,
16360          strerror(errno));
16361       return -1;
16362    }
16363    if (ioctl(link->ss7.fds[curfd], DAHDI_SPECIFY, &sigchan) == -1) {
16364       dahdi_close_ss7_fd(link, curfd);
16365       ast_log(LOG_ERROR, "Unable to specify SS7 sigchan %d (%s)\n", sigchan,
16366          strerror(errno));
16367       return -1;
16368    }
16369 
16370    /* Get signaling channel parameters */
16371    memset(&params, 0, sizeof(params));
16372    res = ioctl(link->ss7.fds[curfd], DAHDI_GET_PARAMS, &params);
16373    if (res) {
16374       dahdi_close_ss7_fd(link, curfd);
16375       ast_log(LOG_ERROR, "Unable to get parameters for sigchan %d (%s)\n", sigchan,
16376          strerror(errno));
16377       return -1;
16378    }
16379    if (params.sigtype != DAHDI_SIG_HDLCFCS
16380       && params.sigtype != DAHDI_SIG_HARDHDLC
16381       && params.sigtype != DAHDI_SIG_MTP2) {
16382       dahdi_close_ss7_fd(link, curfd);
16383       ast_log(LOG_ERROR, "sigchan %d is not in HDLC/FCS mode.\n", sigchan);
16384       return -1;
16385    }
16386 
16387    /* Set signaling channel buffer policy. */
16388    memset(&bi, 0, sizeof(bi));
16389    bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
16390    bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
16391    bi.numbufs = 32;
16392    bi.bufsize = 512;
16393    if (ioctl(link->ss7.fds[curfd], DAHDI_SET_BUFINFO, &bi)) {
16394       ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n",
16395          sigchan, strerror(errno));
16396       dahdi_close_ss7_fd(link, curfd);
16397       return -1;
16398    }
16399 
16400    /* Get current signaling channel alarm status. */
16401    memset(&si, 0, sizeof(si));
16402    res = ioctl(link->ss7.fds[curfd], DAHDI_SPANSTAT, &si);
16403    if (res) {
16404       dahdi_close_ss7_fd(link, curfd);
16405       ast_log(LOG_ERROR, "Unable to get span state for sigchan %d (%s)\n", sigchan,
16406          strerror(errno));
16407    }
16408 
16409    res = sig_ss7_add_sigchan(&link->ss7, curfd, cur_ss7type,
16410       (params.sigtype == DAHDI_SIG_MTP2)
16411          ? SS7_TRANSPORT_DAHDIMTP2
16412          : SS7_TRANSPORT_DAHDIDCHAN,
16413       si.alarms, cur_networkindicator, cur_pointcode, cur_adjpointcode);
16414    if (res) {
16415       dahdi_close_ss7_fd(link, curfd);
16416       return -1;
16417    }
16418 
16419    ++link->ss7.numsigchans;
16420 
16421    return 0;
16422 }
16423 #endif   /* defined(HAVE_SS7) */
16424 
16425 #if defined(HAVE_SS7)
16426 static char *handle_ss7_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16427 {
16428    int span;
16429    switch (cmd) {
16430    case CLI_INIT:
16431       e->command = "ss7 set debug {on|off} linkset";
16432       e->usage =
16433          "Usage: ss7 set debug {on|off} linkset <linkset>\n"
16434          "       Enables debugging on a given SS7 linkset\n";
16435       return NULL;
16436    case CLI_GENERATE:
16437       return NULL;
16438    }
16439    if (a->argc < 6)
16440       return CLI_SHOWUSAGE;
16441    span = atoi(a->argv[5]);
16442    if ((span < 1) || (span > NUM_SPANS)) {
16443       ast_cli(a->fd, "Invalid linkset %s.  Should be a number from %d to %d\n", a->argv[5], 1, NUM_SPANS);
16444       return CLI_SUCCESS;
16445    }
16446    if (!linksets[span-1].ss7.ss7) {
16447       ast_cli(a->fd, "No SS7 running on linkset %d\n", span);
16448    } else {
16449       if (!strcasecmp(a->argv[3], "on")) {
16450          linksets[span - 1].ss7.debug = 1;
16451          ss7_set_debug(linksets[span-1].ss7.ss7, SIG_SS7_DEBUG);
16452          ast_cli(a->fd, "Enabled debugging on linkset %d\n", span);
16453       } else {
16454          linksets[span - 1].ss7.debug = 0;
16455          ss7_set_debug(linksets[span-1].ss7.ss7, 0);
16456          ast_cli(a->fd, "Disabled debugging on linkset %d\n", span);
16457       }
16458    }
16459 
16460    return CLI_SUCCESS;
16461 }
16462 #endif   /* defined(HAVE_SS7) */
16463 
16464 #if defined(HAVE_SS7)
16465 static char *handle_ss7_block_cic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16466 {
16467    int linkset, cic;
16468    int blocked = -1, i;
16469    switch (cmd) {
16470    case CLI_INIT:
16471       e->command = "ss7 block cic";
16472       e->usage =
16473          "Usage: ss7 block cic <linkset> <CIC>\n"
16474          "       Sends a remote blocking request for the given CIC on the specified linkset\n";
16475       return NULL;
16476    case CLI_GENERATE:
16477       return NULL;
16478    }
16479    if (a->argc == 5)
16480       linkset = atoi(a->argv[3]);
16481    else
16482       return CLI_SHOWUSAGE;
16483 
16484    if ((linkset < 1) || (linkset > NUM_SPANS)) {
16485       ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16486       return CLI_SUCCESS;
16487    }
16488 
16489    if (!linksets[linkset-1].ss7.ss7) {
16490       ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16491       return CLI_SUCCESS;
16492    }
16493 
16494    cic = atoi(a->argv[4]);
16495 
16496    if (cic < 1) {
16497       ast_cli(a->fd, "Invalid CIC specified!\n");
16498       return CLI_SUCCESS;
16499    }
16500 
16501    for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
16502       if (linksets[linkset-1].ss7.pvts[i]->cic == cic) {
16503          blocked = linksets[linkset-1].ss7.pvts[i]->locallyblocked;
16504          if (!blocked) {
16505             ast_mutex_lock(&linksets[linkset-1].ss7.lock);
16506             isup_blo(linksets[linkset-1].ss7.ss7, cic, linksets[linkset-1].ss7.pvts[i]->dpc);
16507             ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
16508          }
16509       }
16510    }
16511 
16512    if (blocked < 0) {
16513       ast_cli(a->fd, "Invalid CIC specified!\n");
16514       return CLI_SUCCESS;
16515    }
16516 
16517    if (!blocked)
16518       ast_cli(a->fd, "Sent blocking request for linkset %d on CIC %d\n", linkset, cic);
16519    else
16520       ast_cli(a->fd, "CIC %d already locally blocked\n", cic);
16521 
16522    /* Break poll on the linkset so it sends our messages */
16523    pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
16524 
16525    return CLI_SUCCESS;
16526 }
16527 #endif   /* defined(HAVE_SS7) */
16528 
16529 #if defined(HAVE_SS7)
16530 static char *handle_ss7_block_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16531 {
16532    int linkset;
16533    int i;
16534    switch (cmd) {
16535    case CLI_INIT:
16536       e->command = "ss7 block linkset";
16537       e->usage =
16538          "Usage: ss7 block linkset <linkset number>\n"
16539          "       Sends a remote blocking request for all CICs on the given linkset\n";
16540       return NULL;
16541    case CLI_GENERATE:
16542       return NULL;
16543    }
16544    if (a->argc == 4)
16545       linkset = atoi(a->argv[3]);
16546    else
16547       return CLI_SHOWUSAGE;
16548 
16549    if ((linkset < 1) || (linkset > NUM_SPANS)) {
16550       ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16551       return CLI_SUCCESS;
16552    }
16553 
16554    if (!linksets[linkset-1].ss7.ss7) {
16555       ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16556       return CLI_SUCCESS;
16557    }
16558 
16559    for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
16560       ast_cli(a->fd, "Sending remote blocking request on CIC %d\n", linksets[linkset-1].ss7.pvts[i]->cic);
16561       ast_mutex_lock(&linksets[linkset-1].ss7.lock);
16562       isup_blo(linksets[linkset-1].ss7.ss7, linksets[linkset-1].ss7.pvts[i]->cic, linksets[linkset-1].ss7.pvts[i]->dpc);
16563       ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
16564    }
16565 
16566    /* Break poll on the linkset so it sends our messages */
16567    pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
16568 
16569    return CLI_SUCCESS;
16570 }
16571 #endif   /* defined(HAVE_SS7) */
16572 
16573 #if defined(HAVE_SS7)
16574 static char *handle_ss7_unblock_cic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16575 {
16576    int linkset, cic;
16577    int i, blocked = -1;
16578    switch (cmd) {
16579    case CLI_INIT:
16580       e->command = "ss7 unblock cic";
16581       e->usage =
16582          "Usage: ss7 unblock cic <linkset> <CIC>\n"
16583          "       Sends a remote unblocking request for the given CIC on the specified linkset\n";
16584       return NULL;
16585    case CLI_GENERATE:
16586       return NULL;
16587    }
16588 
16589    if (a->argc == 5)
16590       linkset = atoi(a->argv[3]);
16591    else
16592       return CLI_SHOWUSAGE;
16593 
16594    if ((linkset < 1) || (linkset > NUM_SPANS)) {
16595       ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16596       return CLI_SUCCESS;
16597    }
16598 
16599    if (!linksets[linkset-1].ss7.ss7) {
16600       ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16601       return CLI_SUCCESS;
16602    }
16603 
16604    cic = atoi(a->argv[4]);
16605 
16606    if (cic < 1) {
16607       ast_cli(a->fd, "Invalid CIC specified!\n");
16608       return CLI_SUCCESS;
16609    }
16610 
16611    for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
16612       if (linksets[linkset-1].ss7.pvts[i]->cic == cic) {
16613          blocked = linksets[linkset-1].ss7.pvts[i]->locallyblocked;
16614          if (blocked) {
16615             ast_mutex_lock(&linksets[linkset-1].ss7.lock);
16616             isup_ubl(linksets[linkset-1].ss7.ss7, cic, linksets[linkset-1].ss7.pvts[i]->dpc);
16617             ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
16618          }
16619       }
16620    }
16621 
16622    if (blocked > 0)
16623       ast_cli(a->fd, "Sent unblocking request for linkset %d on CIC %d\n", linkset, cic);
16624 
16625    /* Break poll on the linkset so it sends our messages */
16626    pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
16627 
16628    return CLI_SUCCESS;
16629 }
16630 #endif   /* defined(HAVE_SS7) */
16631 
16632 #if defined(HAVE_SS7)
16633 static char *handle_ss7_unblock_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16634 {
16635    int linkset;
16636    int i;
16637    switch (cmd) {
16638    case CLI_INIT:
16639       e->command = "ss7 unblock linkset";
16640       e->usage =
16641          "Usage: ss7 unblock linkset <linkset number>\n"
16642          "       Sends a remote unblocking request for all CICs on the specified linkset\n";
16643       return NULL;
16644    case CLI_GENERATE:
16645       return NULL;
16646    }
16647 
16648    if (a->argc == 4)
16649       linkset = atoi(a->argv[3]);
16650    else
16651       return CLI_SHOWUSAGE;
16652 
16653    if ((linkset < 1) || (linkset > NUM_SPANS)) {
16654       ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16655       return CLI_SUCCESS;
16656    }
16657 
16658    if (!linksets[linkset-1].ss7.ss7) {
16659       ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16660       return CLI_SUCCESS;
16661    }
16662 
16663    for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
16664       ast_cli(a->fd, "Sending remote unblock request on CIC %d\n", linksets[linkset-1].ss7.pvts[i]->cic);
16665       ast_mutex_lock(&linksets[linkset-1].ss7.lock);
16666       isup_ubl(linksets[linkset-1].ss7.ss7, linksets[linkset-1].ss7.pvts[i]->cic, linksets[linkset-1].ss7.pvts[i]->dpc);
16667       ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
16668    }
16669 
16670    /* Break poll on the linkset so it sends our messages */
16671    pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
16672 
16673    return CLI_SUCCESS;
16674 }
16675 #endif   /* defined(HAVE_SS7) */
16676 
16677 #if defined(HAVE_SS7)
16678 static char *handle_ss7_show_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16679 {
16680    int linkset;
16681    struct sig_ss7_linkset *ss7;
16682    switch (cmd) {
16683    case CLI_INIT:
16684       e->command = "ss7 show linkset";
16685       e->usage =
16686          "Usage: ss7 show linkset <span>\n"
16687          "       Shows the status of an SS7 linkset.\n";
16688       return NULL;
16689    case CLI_GENERATE:
16690       return NULL;
16691    }
16692 
16693    if (a->argc < 4)
16694       return CLI_SHOWUSAGE;
16695    linkset = atoi(a->argv[3]);
16696    if ((linkset < 1) || (linkset > NUM_SPANS)) {
16697       ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16698       return CLI_SUCCESS;
16699    }
16700    ss7 = &linksets[linkset - 1].ss7;
16701    if (!ss7->ss7) {
16702       ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16703       return CLI_SUCCESS;
16704    }
16705 
16706    ast_cli(a->fd, "SS7 linkset %d status: %s\n", linkset, (ss7->state == LINKSET_STATE_UP) ? "Up" : "Down");
16707 
16708    return CLI_SUCCESS;
16709 }
16710 #endif   /* defined(HAVE_SS7) */
16711 
16712 #if defined(HAVE_SS7)
16713 static char *handle_ss7_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16714 {
16715    int linkset;
16716 
16717    switch (cmd) {
16718    case CLI_INIT:
16719       e->command = "ss7 show channels";
16720       e->usage =
16721          "Usage: ss7 show channels\n"
16722          "       Displays SS7 channel information at a glance.\n";
16723       return NULL;
16724    case CLI_GENERATE:
16725       return NULL;
16726    }
16727 
16728    if (a->argc != 3)
16729       return CLI_SHOWUSAGE;
16730 
16731    sig_ss7_cli_show_channels_header(a->fd);
16732    for (linkset = 0; linkset < NUM_SPANS; ++linkset) {
16733       if (linksets[linkset].ss7.ss7) {
16734          sig_ss7_cli_show_channels(a->fd, &linksets[linkset].ss7);
16735       }
16736    }
16737    return CLI_SUCCESS;
16738 }
16739 #endif   /* defined(HAVE_SS7) */
16740 
16741 #if defined(HAVE_SS7)
16742 static char *handle_ss7_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16743 {
16744    switch (cmd) {
16745    case CLI_INIT:
16746       e->command = "ss7 show version";
16747       e->usage =
16748          "Usage: ss7 show version\n"
16749          "  Show the libss7 version\n";
16750       return NULL;
16751    case CLI_GENERATE:
16752       return NULL;
16753    }
16754 
16755    ast_cli(a->fd, "libss7 version: %s\n", ss7_get_version());
16756 
16757    return CLI_SUCCESS;
16758 }
16759 #endif   /* defined(HAVE_SS7) */
16760 
16761 #if defined(HAVE_SS7)
16762 static struct ast_cli_entry dahdi_ss7_cli[] = {
16763    AST_CLI_DEFINE(handle_ss7_debug, "Enables SS7 debugging on a linkset"),
16764    AST_CLI_DEFINE(handle_ss7_block_cic, "Blocks the given CIC"),
16765    AST_CLI_DEFINE(handle_ss7_unblock_cic, "Unblocks the given CIC"),
16766    AST_CLI_DEFINE(handle_ss7_block_linkset, "Blocks all CICs on a linkset"),
16767    AST_CLI_DEFINE(handle_ss7_unblock_linkset, "Unblocks all CICs on a linkset"),
16768    AST_CLI_DEFINE(handle_ss7_show_linkset, "Shows the status of a linkset"),
16769    AST_CLI_DEFINE(handle_ss7_show_channels, "Displays SS7 channel information"),
16770    AST_CLI_DEFINE(handle_ss7_version, "Displays libss7 version"),
16771 };
16772 #endif   /* defined(HAVE_SS7) */
16773 
16774 #if defined(HAVE_PRI)
16775 #if defined(HAVE_PRI_CCSS)
16776 /*!
16777  * \internal
16778  * \brief CC agent initialization.
16779  * \since 1.8
16780  *
16781  * \param agent CC core agent control.
16782  * \param chan Original channel the agent will attempt to recall.
16783  *
16784  * \details
16785  * This callback is called when the CC core is initialized.  Agents should allocate
16786  * any private data necessary for the call and assign it to the private_data
16787  * on the agent.  Additionally, if any ast_cc_agent_flags are pertinent to the
16788  * specific agent type, they should be set in this function as well.
16789  *
16790  * \retval 0 on success.
16791  * \retval -1 on error.
16792  */
16793 static int dahdi_pri_cc_agent_init(struct ast_cc_agent *agent, struct ast_channel *chan)
16794 {
16795    struct dahdi_pvt *pvt;
16796    struct sig_pri_chan *pvt_chan;
16797    int res;
16798 
16799    ast_assert(!strcmp(chan->tech->type, "DAHDI"));
16800 
16801    pvt = chan->tech_pvt;
16802    if (dahdi_sig_pri_lib_handles(pvt->sig)) {
16803       pvt_chan = pvt->sig_pvt;
16804    } else {
16805       pvt_chan = NULL;
16806    }
16807    if (!pvt_chan) {
16808       return -1;
16809    }
16810 
16811    ast_module_ref(ast_module_info->self);
16812 
16813    res = sig_pri_cc_agent_init(agent, pvt_chan);
16814    if (res) {
16815       ast_module_unref(ast_module_info->self);
16816    }
16817    return res;
16818 }
16819 #endif   /* defined(HAVE_PRI_CCSS) */
16820 #endif   /* defined(HAVE_PRI) */
16821 
16822 #if defined(HAVE_PRI)
16823 #if defined(HAVE_PRI_CCSS)
16824 /*!
16825  * \internal
16826  * \brief Destroy private data on the agent.
16827  * \since 1.8
16828  *
16829  * \param agent CC core agent control.
16830  *
16831  * \details
16832  * The core will call this function upon completion
16833  * or failure of CC.
16834  *
16835  * \return Nothing
16836  */
16837 static void dahdi_pri_cc_agent_destructor(struct ast_cc_agent *agent)
16838 {
16839    sig_pri_cc_agent_destructor(agent);
16840 
16841    ast_module_unref(ast_module_info->self);
16842 }
16843 #endif   /* defined(HAVE_PRI_CCSS) */
16844 #endif   /* defined(HAVE_PRI) */
16845 
16846 #if defined(HAVE_PRI)
16847 #if defined(HAVE_PRI_CCSS)
16848 static struct ast_cc_agent_callbacks dahdi_pri_cc_agent_callbacks = {
16849    .type = dahdi_pri_cc_type,
16850    .init = dahdi_pri_cc_agent_init,
16851    .start_offer_timer = sig_pri_cc_agent_start_offer_timer,
16852    .stop_offer_timer = sig_pri_cc_agent_stop_offer_timer,
16853    .respond = sig_pri_cc_agent_req_rsp,
16854    .status_request = sig_pri_cc_agent_status_req,
16855    .stop_ringing = sig_pri_cc_agent_stop_ringing,
16856    .party_b_free = sig_pri_cc_agent_party_b_free,
16857    .start_monitoring = sig_pri_cc_agent_start_monitoring,
16858    .callee_available = sig_pri_cc_agent_callee_available,
16859    .destructor = dahdi_pri_cc_agent_destructor,
16860 };
16861 #endif   /* defined(HAVE_PRI_CCSS) */
16862 #endif   /* defined(HAVE_PRI) */
16863 
16864 #if defined(HAVE_PRI)
16865 #if defined(HAVE_PRI_CCSS)
16866 static struct ast_cc_monitor_callbacks dahdi_pri_cc_monitor_callbacks = {
16867    .type = dahdi_pri_cc_type,
16868    .request_cc = sig_pri_cc_monitor_req_cc,
16869    .suspend = sig_pri_cc_monitor_suspend,
16870    .unsuspend = sig_pri_cc_monitor_unsuspend,
16871    .status_response = sig_pri_cc_monitor_status_rsp,
16872    .cancel_available_timer = sig_pri_cc_monitor_cancel_available_timer,
16873    .destructor = sig_pri_cc_monitor_destructor,
16874 };
16875 #endif   /* defined(HAVE_PRI_CCSS) */
16876 #endif   /* defined(HAVE_PRI) */
16877 
16878 static int __unload_module(void)
16879 {
16880    struct dahdi_pvt *p;
16881 #if defined(HAVE_PRI) || defined(HAVE_SS7)
16882    int i, j;
16883 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
16884 
16885 #ifdef HAVE_PRI
16886    for (i = 0; i < NUM_SPANS; i++) {
16887       if (pris[i].pri.master != AST_PTHREADT_NULL) {
16888          pthread_cancel(pris[i].pri.master);
16889          pthread_kill(pris[i].pri.master, SIGURG);
16890       }
16891    }
16892    ast_cli_unregister_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
16893    ast_unregister_application(dahdi_send_keypad_facility_app);
16894 #ifdef HAVE_PRI_PROG_W_CAUSE
16895    ast_unregister_application(dahdi_send_callrerouting_facility_app);
16896 #endif
16897 #endif
16898 #if defined(HAVE_SS7)
16899    for (i = 0; i < NUM_SPANS; i++) {
16900       if (linksets[i].ss7.master != AST_PTHREADT_NULL) {
16901          pthread_cancel(linksets[i].ss7.master);
16902          pthread_kill(linksets[i].ss7.master, SIGURG);
16903       }
16904    }
16905    ast_cli_unregister_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
16906 #endif   /* defined(HAVE_SS7) */
16907 #if defined(HAVE_OPENR2)
16908    dahdi_r2_destroy_links();
16909    ast_cli_unregister_multiple(dahdi_mfcr2_cli, ARRAY_LEN(dahdi_mfcr2_cli));
16910    ast_unregister_application(dahdi_accept_r2_call_app);
16911 #endif
16912 
16913    ast_cli_unregister_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli));
16914    ast_manager_unregister("DAHDIDialOffhook");
16915    ast_manager_unregister("DAHDIHangup");
16916    ast_manager_unregister("DAHDITransfer");
16917    ast_manager_unregister("DAHDIDNDoff");
16918    ast_manager_unregister("DAHDIDNDon");
16919    ast_manager_unregister("DAHDIShowChannels");
16920    ast_manager_unregister("DAHDIRestart");
16921    ast_data_unregister(NULL);
16922    ast_channel_unregister(&dahdi_tech);
16923 
16924    /* Hangup all interfaces if they have an owner */
16925    ast_mutex_lock(&iflock);
16926    for (p = iflist; p; p = p->next) {
16927       if (p->owner)
16928          ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
16929    }
16930    ast_mutex_unlock(&iflock);
16931 
16932    ast_mutex_lock(&monlock);
16933    if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
16934       pthread_cancel(monitor_thread);
16935       pthread_kill(monitor_thread, SIGURG);
16936       pthread_join(monitor_thread, NULL);
16937    }
16938    monitor_thread = AST_PTHREADT_STOP;
16939    ast_mutex_unlock(&monlock);
16940 
16941    destroy_all_channels();
16942 
16943 #if defined(HAVE_PRI)
16944    for (i = 0; i < NUM_SPANS; i++) {
16945       if (pris[i].pri.master && (pris[i].pri.master != AST_PTHREADT_NULL)) {
16946          pthread_join(pris[i].pri.master, NULL);
16947       }
16948       for (j = 0; j < SIG_PRI_NUM_DCHANS; j++) {
16949          dahdi_close_pri_fd(&(pris[i]), j);
16950       }
16951       sig_pri_stop_pri(&pris[i].pri);
16952    }
16953 #if defined(HAVE_PRI_CCSS)
16954    ast_cc_agent_unregister(&dahdi_pri_cc_agent_callbacks);
16955    ast_cc_monitor_unregister(&dahdi_pri_cc_monitor_callbacks);
16956 #endif   /* defined(HAVE_PRI_CCSS) */
16957    sig_pri_unload();
16958 #endif
16959 
16960 #if defined(HAVE_SS7)
16961    for (i = 0; i < NUM_SPANS; i++) {
16962       if (linksets[i].ss7.master && (linksets[i].ss7.master != AST_PTHREADT_NULL)) {
16963          pthread_join(linksets[i].ss7.master, NULL);
16964       }
16965       for (j = 0; j < SIG_SS7_NUM_DCHANS; j++) {
16966          dahdi_close_ss7_fd(&(linksets[i]), j);
16967       }
16968    }
16969 #endif   /* defined(HAVE_SS7) */
16970    ast_cond_destroy(&ss_thread_complete);
16971    return 0;
16972 }
16973 
16974 static int unload_module(void)
16975 {
16976 #if defined(HAVE_PRI) || defined(HAVE_SS7)
16977    int y;
16978 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
16979 #ifdef HAVE_PRI
16980    for (y = 0; y < NUM_SPANS; y++)
16981       ast_mutex_destroy(&pris[y].pri.lock);
16982 #endif
16983 #if defined(HAVE_SS7)
16984    for (y = 0; y < NUM_SPANS; y++)
16985       ast_mutex_destroy(&linksets[y].ss7.lock);
16986 #endif   /* defined(HAVE_SS7) */
16987    return __unload_module();
16988 }
16989 
16990 static void string_replace(char *str, int char1, int char2)
16991 {
16992    for (; *str; str++) {
16993       if (*str == char1) {
16994          *str = char2;
16995       }
16996    }
16997 }
16998 
16999 static char *parse_spanchan(char *chanstr, char **subdir)
17000 {
17001    char *p;
17002 
17003    if ((p = strrchr(chanstr, '!')) == NULL) {
17004       *subdir = NULL;
17005       return chanstr;
17006    }
17007    *p++ = '\0';
17008    string_replace(chanstr, '!', '/');
17009    *subdir = chanstr;
17010    return p;
17011 }
17012 
17013 static int build_channels(struct dahdi_chan_conf *conf, const char *value, int reload, int lineno, int *found_pseudo)
17014 {
17015    char *c, *chan;
17016    char *subdir;
17017    int x, start, finish;
17018    struct dahdi_pvt *tmp;
17019 
17020    if ((reload == 0) && (conf->chan.sig < 0) && !conf->is_sig_auto) {
17021       ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n");
17022       return -1;
17023    }
17024 
17025    c = ast_strdupa(value);
17026    c = parse_spanchan(c, &subdir);
17027 
17028    while ((chan = strsep(&c, ","))) {
17029       if (sscanf(chan, "%30d-%30d", &start, &finish) == 2) {
17030          /* Range */
17031       } else if (sscanf(chan, "%30d", &start)) {
17032          /* Just one */
17033          finish = start;
17034       } else if (!strcasecmp(chan, "pseudo")) {
17035          finish = start = CHAN_PSEUDO;
17036          if (found_pseudo)
17037             *found_pseudo = 1;
17038       } else {
17039          ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan);
17040          return -1;
17041       }
17042       if (finish < start) {
17043          ast_log(LOG_WARNING, "Sillyness: %d < %d\n", start, finish);
17044          x = finish;
17045          finish = start;
17046          start = x;
17047       }
17048 
17049       for (x = start; x <= finish; x++) {
17050          char fn[PATH_MAX];
17051          int real_channel = x;
17052 
17053          if (!ast_strlen_zero(subdir)) {
17054             real_channel = device2chan(subdir, x, fn, sizeof(fn));
17055             if (real_channel < 0) {
17056                if (conf->ignore_failed_channels) {
17057                   ast_log(LOG_WARNING, "Failed configuring %s!%d, (got %d). But moving on to others.\n",
17058                         subdir, x, real_channel);
17059                   continue;
17060                } else {
17061                   ast_log(LOG_ERROR, "Failed configuring %s!%d, (got %d).\n",
17062                         subdir, x, real_channel);
17063                   return -1;
17064                }
17065             }
17066          }
17067          tmp = mkintf(real_channel, conf, reload);
17068 
17069          if (tmp) {
17070             ast_verb(3, "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", real_channel, sig2str(tmp->sig));
17071          } else {
17072             ast_log(LOG_ERROR, "Unable to %s channel '%s'\n",
17073                   (reload == 1) ? "reconfigure" : "register", value);
17074             return -1;
17075          }
17076       }
17077    }
17078 
17079    return 0;
17080 }
17081 
17082 /** The length of the parameters list of 'dahdichan'.
17083  * \todo Move definition of MAX_CHANLIST_LEN to a proper place. */
17084 #define MAX_CHANLIST_LEN 80
17085 
17086 static void process_echocancel(struct dahdi_chan_conf *confp, const char *data, unsigned int line)
17087 {
17088    char *parse = ast_strdupa(data);
17089    char *params[DAHDI_MAX_ECHOCANPARAMS + 1];
17090    unsigned int param_count;
17091    unsigned int x;
17092 
17093    if (!(param_count = ast_app_separate_args(parse, ',', params, ARRAY_LEN(params))))
17094       return;
17095 
17096    memset(&confp->chan.echocancel, 0, sizeof(confp->chan.echocancel));
17097 
17098    /* first parameter is tap length, process it here */
17099 
17100    x = ast_strlen_zero(params[0]) ? 0 : atoi(params[0]);
17101 
17102    if ((x == 32) || (x == 64) || (x == 128) || (x == 256) || (x == 512) || (x == 1024))
17103       confp->chan.echocancel.head.tap_length = x;
17104    else if ((confp->chan.echocancel.head.tap_length = ast_true(params[0])))
17105       confp->chan.echocancel.head.tap_length = 128;
17106 
17107    /* now process any remaining parameters */
17108 
17109    for (x = 1; x < param_count; x++) {
17110       struct {
17111          char *name;
17112          char *value;
17113       } param;
17114 
17115       if (ast_app_separate_args(params[x], '=', (char **) &param, 2) < 1) {
17116          ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %u: '%s'\n", line, params[x]);
17117          continue;
17118       }
17119 
17120       if (ast_strlen_zero(param.name) || (strlen(param.name) > sizeof(confp->chan.echocancel.params[0].name)-1)) {
17121          ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %u: '%s'\n", line, param.name);
17122          continue;
17123       }
17124 
17125       strcpy(confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].name, param.name);
17126 
17127       if (param.value) {
17128          if (sscanf(param.value, "%30d", &confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].value) != 1) {
17129             ast_log(LOG_WARNING, "Invalid echocancel parameter value supplied at line %u: '%s'\n", line, param.value);
17130             continue;
17131          }
17132       }
17133       confp->chan.echocancel.head.param_count++;
17134    }
17135 }
17136 
17137 /*! process_dahdi() - ignore keyword 'channel' and similar */
17138 #define PROC_DAHDI_OPT_NOCHAN  (1 << 0)
17139 /*! process_dahdi() - No warnings on non-existing cofiguration keywords */
17140 #define PROC_DAHDI_OPT_NOWARN  (1 << 1)
17141 
17142 static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct ast_variable *v, int reload, int options)
17143 {
17144    struct dahdi_pvt *tmp;
17145    int y;
17146    int found_pseudo = 0;
17147    struct ast_variable *dahdichan = NULL;
17148 
17149    for (; v; v = v->next) {
17150       if (!ast_jb_read_conf(&global_jbconf, v->name, v->value))
17151          continue;
17152 
17153       /* Create the interface list */
17154       if (!strcasecmp(v->name, "channel") || !strcasecmp(v->name, "channels")) {
17155          if (options & PROC_DAHDI_OPT_NOCHAN) {
17156             ast_log(LOG_WARNING, "Channel '%s' ignored.\n", v->value);
17157             continue;
17158          }
17159          if (build_channels(confp, v->value, reload, v->lineno, &found_pseudo)) {
17160             if (confp->ignore_failed_channels) {
17161                ast_log(LOG_WARNING, "Channel '%s' failure ignored: ignore_failed_channels.\n", v->value);
17162                continue;
17163             } else {
17164                return -1;
17165             }
17166          }
17167          ast_log(LOG_DEBUG, "Channel '%s' configured.\n", v->value);
17168       } else if (!strcasecmp(v->name, "ignore_failed_channels")) {
17169          confp->ignore_failed_channels = ast_true(v->value);
17170       } else if (!strcasecmp(v->name, "buffers")) {
17171          if (parse_buffers_policy(v->value, &confp->chan.buf_no, &confp->chan.buf_policy)) {
17172             ast_log(LOG_WARNING, "Using default buffer policy.\n");
17173             confp->chan.buf_no = numbufs;
17174             confp->chan.buf_policy = DAHDI_POLICY_IMMEDIATE;
17175          }
17176       } else if (!strcasecmp(v->name, "faxbuffers")) {
17177          if (!parse_buffers_policy(v->value, &confp->chan.faxbuf_no, &confp->chan.faxbuf_policy)) {
17178             confp->chan.usefaxbuffers = 1;
17179          }
17180       } else if (!strcasecmp(v->name, "dahdichan")) {
17181          /* Only process the last dahdichan value. */
17182          dahdichan = v;
17183       } else if (!strcasecmp(v->name, "usedistinctiveringdetection")) {
17184          usedistinctiveringdetection = ast_true(v->value);
17185       } else if (!strcasecmp(v->name, "distinctiveringaftercid")) {
17186          distinctiveringaftercid = ast_true(v->value);
17187       } else if (!strcasecmp(v->name, "dring1context")) {
17188          ast_copy_string(confp->chan.drings.ringContext[0].contextData,v->value,sizeof(confp->chan.drings.ringContext[0].contextData));
17189       } else if (!strcasecmp(v->name, "dring2context")) {
17190          ast_copy_string(confp->chan.drings.ringContext[1].contextData,v->value,sizeof(confp->chan.drings.ringContext[1].contextData));
17191       } else if (!strcasecmp(v->name, "dring3context")) {
17192          ast_copy_string(confp->chan.drings.ringContext[2].contextData,v->value,sizeof(confp->chan.drings.ringContext[2].contextData));
17193       } else if (!strcasecmp(v->name, "dring1range")) {
17194          confp->chan.drings.ringnum[0].range = atoi(v->value);
17195       } else if (!strcasecmp(v->name, "dring2range")) {
17196          confp->chan.drings.ringnum[1].range = atoi(v->value);
17197       } else if (!strcasecmp(v->name, "dring3range")) {
17198          confp->chan.drings.ringnum[2].range = atoi(v->value);
17199       } else if (!strcasecmp(v->name, "dring1")) {
17200          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]);
17201       } else if (!strcasecmp(v->name, "dring2")) {
17202          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]);
17203       } else if (!strcasecmp(v->name, "dring3")) {
17204          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]);
17205       } else if (!strcasecmp(v->name, "usecallerid")) {
17206          confp->chan.use_callerid = ast_true(v->value);
17207       } else if (!strcasecmp(v->name, "cidsignalling")) {
17208          if (!strcasecmp(v->value, "bell"))
17209             confp->chan.cid_signalling = CID_SIG_BELL;
17210          else if (!strcasecmp(v->value, "v23"))
17211             confp->chan.cid_signalling = CID_SIG_V23;
17212          else if (!strcasecmp(v->value, "dtmf"))
17213             confp->chan.cid_signalling = CID_SIG_DTMF;
17214          else if (!strcasecmp(v->value, "smdi"))
17215             confp->chan.cid_signalling = CID_SIG_SMDI;
17216          else if (!strcasecmp(v->value, "v23_jp"))
17217             confp->chan.cid_signalling = CID_SIG_V23_JP;
17218          else if (ast_true(v->value))
17219             confp->chan.cid_signalling = CID_SIG_BELL;
17220       } else if (!strcasecmp(v->name, "cidstart")) {
17221          if (!strcasecmp(v->value, "ring"))
17222             confp->chan.cid_start = CID_START_RING;
17223          else if (!strcasecmp(v->value, "polarity_in"))
17224             confp->chan.cid_start = CID_START_POLARITY_IN;
17225          else if (!strcasecmp(v->value, "polarity"))
17226             confp->chan.cid_start = CID_START_POLARITY;
17227          else if (!strcasecmp(v->value, "dtmf"))
17228             confp->chan.cid_start = CID_START_DTMF_NOALERT;
17229          else if (ast_true(v->value))
17230             confp->chan.cid_start = CID_START_RING;
17231       } else if (!strcasecmp(v->name, "threewaycalling")) {
17232          confp->chan.threewaycalling = ast_true(v->value);
17233       } else if (!strcasecmp(v->name, "cancallforward")) {
17234          confp->chan.cancallforward = ast_true(v->value);
17235       } else if (!strcasecmp(v->name, "relaxdtmf")) {
17236          if (ast_true(v->value))
17237             confp->chan.dtmfrelax = DSP_DIGITMODE_RELAXDTMF;
17238          else
17239             confp->chan.dtmfrelax = 0;
17240       } else if (!strcasecmp(v->name, "mailbox")) {
17241          ast_copy_string(confp->chan.mailbox, v->value, sizeof(confp->chan.mailbox));
17242       } else if (!strcasecmp(v->name, "hasvoicemail")) {
17243          if (ast_true(v->value) && ast_strlen_zero(confp->chan.mailbox)) {
17244             ast_copy_string(confp->chan.mailbox, cat, sizeof(confp->chan.mailbox));
17245          }
17246       } else if (!strcasecmp(v->name, "adsi")) {
17247          confp->chan.adsi = ast_true(v->value);
17248       } else if (!strcasecmp(v->name, "usesmdi")) {
17249          confp->chan.use_smdi = ast_true(v->value);
17250       } else if (!strcasecmp(v->name, "smdiport")) {
17251          ast_copy_string(confp->smdi_port, v->value, sizeof(confp->smdi_port));
17252       } else if (!strcasecmp(v->name, "transfer")) {
17253          confp->chan.transfer = ast_true(v->value);
17254       } else if (!strcasecmp(v->name, "canpark")) {
17255          confp->chan.canpark = ast_true(v->value);
17256       } else if (!strcasecmp(v->name, "echocancelwhenbridged")) {
17257          confp->chan.echocanbridged = ast_true(v->value);
17258       } else if (!strcasecmp(v->name, "busydetect")) {
17259          confp->chan.busydetect = ast_true(v->value);
17260       } else if (!strcasecmp(v->name, "busycount")) {
17261          confp->chan.busycount = atoi(v->value);
17262       } else if (!strcasecmp(v->name, "silencethreshold")) {
17263          confp->chan.silencethreshold = atoi(v->value);
17264       } else if (!strcasecmp(v->name, "busycompare")) {
17265          confp->chan.busycompare = ast_true(v->value);
17266       } else if (!strcasecmp(v->name, "busypattern")) {
17267          if (sscanf(v->value, "%30d,%30d", &confp->chan.busytonelength, &confp->chan.busyquietlength) != 2) {
17268             ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength,quietlength at line %d.\n", v->lineno);
17269          }
17270          int count = sscanf(v->value, "%d,%d", &confp->chan.busytonelength, &confp->chan.busyquietlength);
17271          if (count == 1)
17272             confp->chan.busyquietlength = 0;
17273          else if (count < 1)
17274             ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength[,quietlength] at line %d.\n", v->lineno);
17275       } else if (!strcasecmp(v->name, "busyfuzziness")) {
17276          confp->chan.busyfuzziness = atoi(v->value);
17277       } else if (!strcasecmp(v->name, "callprogress")) {
17278          confp->chan.callprogress &= ~CALLPROGRESS_PROGRESS;
17279          if (ast_true(v->value))
17280             confp->chan.callprogress |= CALLPROGRESS_PROGRESS;
17281       } else if (!strcasecmp(v->name, "waitfordialtone")) {
17282          confp->chan.waitfordialtone = atoi(v->value);
17283       } else if (!strcasecmp(v->name, "faxdetect")) {
17284          confp->chan.callprogress &= ~CALLPROGRESS_FAX;
17285          if (!strcasecmp(v->value, "incoming")) {
17286             confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING;
17287          } else if (!strcasecmp(v->value, "outgoing")) {
17288             confp->chan.callprogress |= CALLPROGRESS_FAX_OUTGOING;
17289          } else if (!strcasecmp(v->value, "both") || ast_true(v->value))
17290             confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING;
17291       } else if (!strcasecmp(v->name, "echocancel")) {
17292          process_echocancel(confp, v->value, v->lineno);
17293       } else if (!strcasecmp(v->name, "echotraining")) {
17294          if (sscanf(v->value, "%30d", &y) == 1) {
17295             if ((y < 10) || (y > 4000)) {
17296                ast_log(LOG_WARNING, "Echo training time must be within the range of 10 to 4000 ms at line %d.\n", v->lineno);
17297             } else {
17298                confp->chan.echotraining = y;
17299             }
17300          } else if (ast_true(v->value)) {
17301             confp->chan.echotraining = 400;
17302          } else
17303             confp->chan.echotraining = 0;
17304       } else if (!strcasecmp(v->name, "hidecallerid")) {
17305          confp->chan.hidecallerid = ast_true(v->value);
17306       } else if (!strcasecmp(v->name, "hidecalleridname")) {
17307          confp->chan.hidecalleridname = ast_true(v->value);
17308       } else if (!strcasecmp(v->name, "pulsedial")) {
17309          confp->chan.pulse = ast_true(v->value);
17310       } else if (!strcasecmp(v->name, "callreturn")) {
17311          confp->chan.callreturn = ast_true(v->value);
17312       } else if (!strcasecmp(v->name, "callwaiting")) {
17313          confp->chan.callwaiting = ast_true(v->value);
17314       } else if (!strcasecmp(v->name, "callwaitingcallerid")) {
17315          confp->chan.callwaitingcallerid = ast_true(v->value);
17316       } else if (!strcasecmp(v->name, "context")) {
17317          ast_copy_string(confp->chan.context, v->value, sizeof(confp->chan.context));
17318       } else if (!strcasecmp(v->name, "language")) {
17319          ast_copy_string(confp->chan.language, v->value, sizeof(confp->chan.language));
17320       } else if (!strcasecmp(v->name, "progzone")) {
17321          ast_copy_string(progzone, v->value, sizeof(progzone));
17322       } else if (!strcasecmp(v->name, "mohinterpret")
17323          ||!strcasecmp(v->name, "musiconhold") || !strcasecmp(v->name, "musicclass")) {
17324          ast_copy_string(confp->chan.mohinterpret, v->value, sizeof(confp->chan.mohinterpret));
17325       } else if (!strcasecmp(v->name, "mohsuggest")) {
17326          ast_copy_string(confp->chan.mohsuggest, v->value, sizeof(confp->chan.mohsuggest));
17327       } else if (!strcasecmp(v->name, "parkinglot")) {
17328          ast_copy_string(confp->chan.parkinglot, v->value, sizeof(confp->chan.parkinglot));
17329       } else if (!strcasecmp(v->name, "stripmsd")) {
17330          ast_log(LOG_NOTICE, "Configuration option \"%s\" has been deprecated. Please use dialplan instead\n", v->name);
17331          confp->chan.stripmsd = atoi(v->value);
17332       } else if (!strcasecmp(v->name, "jitterbuffers")) {
17333          numbufs = atoi(v->value);
17334       } else if (!strcasecmp(v->name, "group")) {
17335          confp->chan.group = ast_get_group(v->value);
17336       } else if (!strcasecmp(v->name, "callgroup")) {
17337          if (!strcasecmp(v->value, "none"))
17338             confp->chan.callgroup = 0;
17339          else
17340             confp->chan.callgroup = ast_get_group(v->value);
17341       } else if (!strcasecmp(v->name, "pickupgroup")) {
17342          if (!strcasecmp(v->value, "none"))
17343             confp->chan.pickupgroup = 0;
17344          else
17345             confp->chan.pickupgroup = ast_get_group(v->value);
17346       } else if (!strcasecmp(v->name, "setvar")) {
17347          char *varname = ast_strdupa(v->value), *varval = NULL;
17348          struct ast_variable *tmpvar;
17349          if (varname && (varval = strchr(varname, '='))) {
17350             *varval++ = '\0';
17351             if ((tmpvar = ast_variable_new(varname, varval, ""))) {
17352                tmpvar->next = confp->chan.vars;
17353                confp->chan.vars = tmpvar;
17354             }
17355          }
17356       } else if (!strcasecmp(v->name, "immediate")) {
17357          confp->chan.immediate = ast_true(v->value);
17358       } else if (!strcasecmp(v->name, "transfertobusy")) {
17359          confp->chan.transfertobusy = ast_true(v->value);
17360       } else if (!strcasecmp(v->name, "mwimonitor")) {
17361          confp->chan.mwimonitor_neon = 0;
17362          confp->chan.mwimonitor_fsk = 0;
17363          confp->chan.mwimonitor_rpas = 0;
17364          if (strcasestr(v->value, "fsk")) {
17365             confp->chan.mwimonitor_fsk = 1;
17366          }
17367          if (strcasestr(v->value, "rpas")) {
17368             confp->chan.mwimonitor_rpas = 1;
17369          }
17370          if (strcasestr(v->value, "neon")) {
17371             confp->chan.mwimonitor_neon = 1;
17372          }
17373          /* If set to true or yes, assume that simple fsk is desired */
17374          if (ast_true(v->value)) {
17375             confp->chan.mwimonitor_fsk = 1;
17376          }
17377       } else if (!strcasecmp(v->name, "cid_rxgain")) {
17378          if (sscanf(v->value, "%30f", &confp->chan.cid_rxgain) != 1) {
17379             ast_log(LOG_WARNING, "Invalid cid_rxgain: %s at line %d.\n", v->value, v->lineno);
17380          }
17381       } else if (!strcasecmp(v->name, "rxgain")) {
17382          if (sscanf(v->value, "%30f", &confp->chan.rxgain) != 1) {
17383             ast_log(LOG_WARNING, "Invalid rxgain: %s at line %d.\n", v->value, v->lineno);
17384          }
17385       } else if (!strcasecmp(v->name, "txgain")) {
17386          if (sscanf(v->value, "%30f", &confp->chan.txgain) != 1) {
17387             ast_log(LOG_WARNING, "Invalid txgain: %s at line %d.\n", v->value, v->lineno);
17388          }
17389       } else if (!strcasecmp(v->name, "txdrc")) {
17390          if (sscanf(v->value, "%f", &confp->chan.txdrc) != 1) {
17391             ast_log(LOG_WARNING, "Invalid txdrc: %s\n", v->value);
17392          }
17393       } else if (!strcasecmp(v->name, "rxdrc")) {
17394          if (sscanf(v->value, "%f", &confp->chan.rxdrc) != 1) {
17395             ast_log(LOG_WARNING, "Invalid rxdrc: %s\n", v->value);
17396          }
17397       } else if (!strcasecmp(v->name, "tonezone")) {
17398          if (sscanf(v->value, "%30d", &confp->chan.tonezone) != 1) {
17399             ast_log(LOG_WARNING, "Invalid tonezone: %s at line %d.\n", v->value, v->lineno);
17400          }
17401       } else if (!strcasecmp(v->name, "callerid")) {
17402          if (!strcasecmp(v->value, "asreceived")) {
17403             confp->chan.cid_num[0] = '\0';
17404             confp->chan.cid_name[0] = '\0';
17405          } else {
17406             ast_callerid_split(v->value, confp->chan.cid_name, sizeof(confp->chan.cid_name), confp->chan.cid_num, sizeof(confp->chan.cid_num));
17407          }
17408       } else if (!strcasecmp(v->name, "fullname")) {
17409          ast_copy_string(confp->chan.cid_name, v->value, sizeof(confp->chan.cid_name));
17410       } else if (!strcasecmp(v->name, "cid_number")) {
17411          ast_copy_string(confp->chan.cid_num, v->value, sizeof(confp->chan.cid_num));
17412       } else if (!strcasecmp(v->name, "cid_tag")) {
17413          ast_copy_string(confp->chan.cid_tag, v->value, sizeof(confp->chan.cid_tag));
17414       } else if (!strcasecmp(v->name, "useincomingcalleridondahditransfer")) {
17415          confp->chan.dahditrcallerid = ast_true(v->value);
17416       } else if (!strcasecmp(v->name, "restrictcid")) {
17417          confp->chan.restrictcid = ast_true(v->value);
17418       } else if (!strcasecmp(v->name, "usecallingpres")) {
17419          confp->chan.use_callingpres = ast_true(v->value);
17420       } else if (!strcasecmp(v->name, "accountcode")) {
17421          ast_copy_string(confp->chan.accountcode, v->value, sizeof(confp->chan.accountcode));
17422       } else if (!strcasecmp(v->name, "amaflags")) {
17423          y = ast_cdr_amaflags2int(v->value);
17424          if (y < 0)
17425             ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d.\n", v->value, v->lineno);
17426          else
17427             confp->chan.amaflags = y;
17428       } else if (!strcasecmp(v->name, "polarityonanswerdelay")) {
17429          confp->chan.polarityonanswerdelay = atoi(v->value);
17430       } else if (!strcasecmp(v->name, "answeronpolarityswitch")) {
17431          confp->chan.answeronpolarityswitch = ast_true(v->value);
17432       } else if (!strcasecmp(v->name, "hanguponpolarityswitch")) {
17433          confp->chan.hanguponpolarityswitch = ast_true(v->value);
17434       } else if (!strcasecmp(v->name, "sendcalleridafter")) {
17435          confp->chan.sendcalleridafter = atoi(v->value);
17436       } else if (!strcasecmp(v->name, "mwimonitornotify")) {
17437          ast_copy_string(mwimonitornotify, v->value, sizeof(mwimonitornotify));
17438       } else if (ast_cc_is_config_param(v->name)) {
17439          ast_cc_set_param(confp->chan.cc_params, v->name, v->value);
17440       } else if (!strcasecmp(v->name, "mwisendtype")) {
17441 #ifndef HAVE_DAHDI_LINEREVERSE_VMWI  /* backward compatibility for older dahdi VMWI implementation */
17442          if (!strcasecmp(v->value, "rpas")) { /* Ring Pulse Alert Signal */
17443             mwisend_rpas = 1;
17444          } else {
17445             mwisend_rpas = 0;
17446          }
17447 #else
17448          /* Default is fsk, to turn it off you must specify nofsk */
17449          memset(&confp->chan.mwisend_setting, 0, sizeof(confp->chan.mwisend_setting));
17450          if (strcasestr(v->value, "nofsk")) {      /* NoFSK */
17451             confp->chan.mwisend_fsk = 0;
17452          } else {             /* Default FSK */
17453             confp->chan.mwisend_fsk = 1;
17454          }
17455          if (strcasestr(v->value, "rpas")) {       /* Ring Pulse Alert Signal, normally followed by FSK */
17456             confp->chan.mwisend_rpas = 1;
17457          } else {
17458             confp->chan.mwisend_rpas = 0;
17459          }
17460          if (strcasestr(v->value, "lrev")) {       /* Line Reversal */
17461             confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_LREV;
17462          }
17463          if (strcasestr(v->value, "hvdc")) {       /* HV 90VDC */
17464             confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_HVDC;
17465          }
17466          if ( (strcasestr(v->value, "neon")) || (strcasestr(v->value, "hvac")) ){   /* 90V DC pulses */
17467             confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_HVAC;
17468          }
17469 #endif
17470       } else if (reload != 1) {
17471           if (!strcasecmp(v->name, "signalling") || !strcasecmp(v->name, "signaling")) {
17472             int orig_radio = confp->chan.radio;
17473             int orig_outsigmod = confp->chan.outsigmod;
17474             int orig_auto = confp->is_sig_auto;
17475 
17476             confp->chan.radio = 0;
17477             confp->chan.outsigmod = -1;
17478             confp->is_sig_auto = 0;
17479             if (!strcasecmp(v->value, "em")) {
17480                confp->chan.sig = SIG_EM;
17481             } else if (!strcasecmp(v->value, "em_e1")) {
17482                confp->chan.sig = SIG_EM_E1;
17483             } else if (!strcasecmp(v->value, "em_w")) {
17484                confp->chan.sig = SIG_EMWINK;
17485             } else if (!strcasecmp(v->value, "fxs_ls")) {
17486                confp->chan.sig = SIG_FXSLS;
17487             } else if (!strcasecmp(v->value, "fxs_gs")) {
17488                confp->chan.sig = SIG_FXSGS;
17489             } else if (!strcasecmp(v->value, "fxs_ks")) {
17490                confp->chan.sig = SIG_FXSKS;
17491             } else if (!strcasecmp(v->value, "fxo_ls")) {
17492                confp->chan.sig = SIG_FXOLS;
17493             } else if (!strcasecmp(v->value, "fxo_gs")) {
17494                confp->chan.sig = SIG_FXOGS;
17495             } else if (!strcasecmp(v->value, "fxo_ks")) {
17496                confp->chan.sig = SIG_FXOKS;
17497             } else if (!strcasecmp(v->value, "fxs_rx")) {
17498                confp->chan.sig = SIG_FXSKS;
17499                confp->chan.radio = 1;
17500             } else if (!strcasecmp(v->value, "fxo_rx")) {
17501                confp->chan.sig = SIG_FXOLS;
17502                confp->chan.radio = 1;
17503             } else if (!strcasecmp(v->value, "fxs_tx")) {
17504                confp->chan.sig = SIG_FXSLS;
17505                confp->chan.radio = 1;
17506             } else if (!strcasecmp(v->value, "fxo_tx")) {
17507                confp->chan.sig = SIG_FXOGS;
17508                confp->chan.radio = 1;
17509             } else if (!strcasecmp(v->value, "em_rx")) {
17510                confp->chan.sig = SIG_EM;
17511                confp->chan.radio = 1;
17512             } else if (!strcasecmp(v->value, "em_tx")) {
17513                confp->chan.sig = SIG_EM;
17514                confp->chan.radio = 1;
17515             } else if (!strcasecmp(v->value, "em_rxtx")) {
17516                confp->chan.sig = SIG_EM;
17517                confp->chan.radio = 2;
17518             } else if (!strcasecmp(v->value, "em_txrx")) {
17519                confp->chan.sig = SIG_EM;
17520                confp->chan.radio = 2;
17521             } else if (!strcasecmp(v->value, "sf")) {
17522                confp->chan.sig = SIG_SF;
17523             } else if (!strcasecmp(v->value, "sf_w")) {
17524                confp->chan.sig = SIG_SFWINK;
17525             } else if (!strcasecmp(v->value, "sf_featd")) {
17526                confp->chan.sig = SIG_FEATD;
17527             } else if (!strcasecmp(v->value, "sf_featdmf")) {
17528                confp->chan.sig = SIG_FEATDMF;
17529             } else if (!strcasecmp(v->value, "sf_featb")) {
17530                confp->chan.sig = SIG_SF_FEATB;
17531             } else if (!strcasecmp(v->value, "sf")) {
17532                confp->chan.sig = SIG_SF;
17533             } else if (!strcasecmp(v->value, "sf_rx")) {
17534                confp->chan.sig = SIG_SF;
17535                confp->chan.radio = 1;
17536             } else if (!strcasecmp(v->value, "sf_tx")) {
17537                confp->chan.sig = SIG_SF;
17538                confp->chan.radio = 1;
17539             } else if (!strcasecmp(v->value, "sf_rxtx")) {
17540                confp->chan.sig = SIG_SF;
17541                confp->chan.radio = 2;
17542             } else if (!strcasecmp(v->value, "sf_txrx")) {
17543                confp->chan.sig = SIG_SF;
17544                confp->chan.radio = 2;
17545             } else if (!strcasecmp(v->value, "featd")) {
17546                confp->chan.sig = SIG_FEATD;
17547             } else if (!strcasecmp(v->value, "featdmf")) {
17548                confp->chan.sig = SIG_FEATDMF;
17549             } else if (!strcasecmp(v->value, "featdmf_ta")) {
17550                confp->chan.sig = SIG_FEATDMF_TA;
17551             } else if (!strcasecmp(v->value, "e911")) {
17552                confp->chan.sig = SIG_E911;
17553             } else if (!strcasecmp(v->value, "fgccama")) {
17554                confp->chan.sig = SIG_FGC_CAMA;
17555             } else if (!strcasecmp(v->value, "fgccamamf")) {
17556                confp->chan.sig = SIG_FGC_CAMAMF;
17557             } else if (!strcasecmp(v->value, "featb")) {
17558                confp->chan.sig = SIG_FEATB;
17559 #ifdef HAVE_PRI
17560             } else if (!strcasecmp(v->value, "pri_net")) {
17561                confp->chan.sig = SIG_PRI;
17562                confp->pri.pri.nodetype = PRI_NETWORK;
17563             } else if (!strcasecmp(v->value, "pri_cpe")) {
17564                confp->chan.sig = SIG_PRI;
17565                confp->pri.pri.nodetype = PRI_CPE;
17566             } else if (!strcasecmp(v->value, "bri_cpe")) {
17567                confp->chan.sig = SIG_BRI;
17568                confp->pri.pri.nodetype = PRI_CPE;
17569             } else if (!strcasecmp(v->value, "bri_net")) {
17570                confp->chan.sig = SIG_BRI;
17571                confp->pri.pri.nodetype = PRI_NETWORK;
17572             } else if (!strcasecmp(v->value, "bri_cpe_ptmp")) {
17573                confp->chan.sig = SIG_BRI_PTMP;
17574                confp->pri.pri.nodetype = PRI_CPE;
17575             } else if (!strcasecmp(v->value, "bri_net_ptmp")) {
17576 #if defined(HAVE_PRI_CALL_HOLD)
17577                confp->chan.sig = SIG_BRI_PTMP;
17578                confp->pri.pri.nodetype = PRI_NETWORK;
17579 #else
17580                ast_log(LOG_WARNING, "How cool would it be if someone implemented this mode!  For now, sucks for you. (line %d)\n", v->lineno);
17581 #endif   /* !defined(HAVE_PRI_CALL_HOLD) */
17582 #endif
17583 #if defined(HAVE_SS7)
17584             } else if (!strcasecmp(v->value, "ss7")) {
17585                confp->chan.sig = SIG_SS7;
17586 #endif   /* defined(HAVE_SS7) */
17587 #ifdef HAVE_OPENR2
17588             } else if (!strcasecmp(v->value, "mfcr2")) {
17589                confp->chan.sig = SIG_MFCR2;
17590 #endif
17591             } else if (!strcasecmp(v->value, "auto")) {
17592                confp->is_sig_auto = 1;
17593             } else {
17594                confp->chan.outsigmod = orig_outsigmod;
17595                confp->chan.radio = orig_radio;
17596                confp->is_sig_auto = orig_auto;
17597                ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
17598             }
17599           } else if (!strcasecmp(v->name, "outsignalling") || !strcasecmp(v->name, "outsignaling")) {
17600             if (!strcasecmp(v->value, "em")) {
17601                confp->chan.outsigmod = SIG_EM;
17602             } else if (!strcasecmp(v->value, "em_e1")) {
17603                confp->chan.outsigmod = SIG_EM_E1;
17604             } else if (!strcasecmp(v->value, "em_w")) {
17605                confp->chan.outsigmod = SIG_EMWINK;
17606             } else if (!strcasecmp(v->value, "sf")) {
17607                confp->chan.outsigmod = SIG_SF;
17608             } else if (!strcasecmp(v->value, "sf_w")) {
17609                confp->chan.outsigmod = SIG_SFWINK;
17610             } else if (!strcasecmp(v->value, "sf_featd")) {
17611                confp->chan.outsigmod = SIG_FEATD;
17612             } else if (!strcasecmp(v->value, "sf_featdmf")) {
17613                confp->chan.outsigmod = SIG_FEATDMF;
17614             } else if (!strcasecmp(v->value, "sf_featb")) {
17615                confp->chan.outsigmod = SIG_SF_FEATB;
17616             } else if (!strcasecmp(v->value, "sf")) {
17617                confp->chan.outsigmod = SIG_SF;
17618             } else if (!strcasecmp(v->value, "featd")) {
17619                confp->chan.outsigmod = SIG_FEATD;
17620             } else if (!strcasecmp(v->value, "featdmf")) {
17621                confp->chan.outsigmod = SIG_FEATDMF;
17622             } else if (!strcasecmp(v->value, "featdmf_ta")) {
17623                confp->chan.outsigmod = SIG_FEATDMF_TA;
17624             } else if (!strcasecmp(v->value, "e911")) {
17625                confp->chan.outsigmod = SIG_E911;
17626             } else if (!strcasecmp(v->value, "fgccama")) {
17627                confp->chan.outsigmod = SIG_FGC_CAMA;
17628             } else if (!strcasecmp(v->value, "fgccamamf")) {
17629                confp->chan.outsigmod = SIG_FGC_CAMAMF;
17630             } else if (!strcasecmp(v->value, "featb")) {
17631                confp->chan.outsigmod = SIG_FEATB;
17632             } else {
17633                ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
17634             }
17635 #ifdef HAVE_PRI
17636          } else if (!strcasecmp(v->name, "pridialplan")) {
17637             if (!strcasecmp(v->value, "national")) {
17638                confp->pri.pri.dialplan = PRI_NATIONAL_ISDN + 1;
17639             } else if (!strcasecmp(v->value, "unknown")) {
17640                confp->pri.pri.dialplan = PRI_UNKNOWN + 1;
17641             } else if (!strcasecmp(v->value, "private")) {
17642                confp->pri.pri.dialplan = PRI_PRIVATE + 1;
17643             } else if (!strcasecmp(v->value, "international")) {
17644                confp->pri.pri.dialplan = PRI_INTERNATIONAL_ISDN + 1;
17645             } else if (!strcasecmp(v->value, "local")) {
17646                confp->pri.pri.dialplan = PRI_LOCAL_ISDN + 1;
17647             } else if (!strcasecmp(v->value, "dynamic")) {
17648                confp->pri.pri.dialplan = -1;
17649             } else if (!strcasecmp(v->value, "redundant")) {
17650                confp->pri.pri.dialplan = -2;
17651             } else {
17652                ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno);
17653             }
17654          } else if (!strcasecmp(v->name, "prilocaldialplan")) {
17655             if (!strcasecmp(v->value, "national")) {
17656                confp->pri.pri.localdialplan = PRI_NATIONAL_ISDN + 1;
17657             } else if (!strcasecmp(v->value, "unknown")) {
17658                confp->pri.pri.localdialplan = PRI_UNKNOWN + 1;
17659             } else if (!strcasecmp(v->value, "private")) {
17660                confp->pri.pri.localdialplan = PRI_PRIVATE + 1;
17661             } else if (!strcasecmp(v->value, "international")) {
17662                confp->pri.pri.localdialplan = PRI_INTERNATIONAL_ISDN + 1;
17663             } else if (!strcasecmp(v->value, "local")) {
17664                confp->pri.pri.localdialplan = PRI_LOCAL_ISDN + 1;
17665             } else if (!strcasecmp(v->value, "dynamic")) {
17666                confp->pri.pri.localdialplan = -1;
17667             } else if (!strcasecmp(v->value, "redundant")) {
17668                confp->pri.pri.localdialplan = -2;
17669             } else {
17670                ast_log(LOG_WARNING, "Unknown PRI localdialplan '%s' at line %d.\n", v->value, v->lineno);
17671             }
17672          } else if (!strcasecmp(v->name, "switchtype")) {
17673             if (!strcasecmp(v->value, "national"))
17674                confp->pri.pri.switchtype = PRI_SWITCH_NI2;
17675             else if (!strcasecmp(v->value, "ni1"))
17676                confp->pri.pri.switchtype = PRI_SWITCH_NI1;
17677             else if (!strcasecmp(v->value, "dms100"))
17678                confp->pri.pri.switchtype = PRI_SWITCH_DMS100;
17679             else if (!strcasecmp(v->value, "4ess"))
17680                confp->pri.pri.switchtype = PRI_SWITCH_ATT4ESS;
17681             else if (!strcasecmp(v->value, "5ess"))
17682                confp->pri.pri.switchtype = PRI_SWITCH_LUCENT5E;
17683             else if (!strcasecmp(v->value, "euroisdn"))
17684                confp->pri.pri.switchtype = PRI_SWITCH_EUROISDN_E1;
17685             else if (!strcasecmp(v->value, "qsig"))
17686                confp->pri.pri.switchtype = PRI_SWITCH_QSIG;
17687             else {
17688                ast_log(LOG_ERROR, "Unknown switchtype '%s' at line %d.\n", v->value, v->lineno);
17689                return -1;
17690             }
17691          } else if (!strcasecmp(v->name, "msn")) {
17692             ast_copy_string(confp->pri.pri.msn_list, v->value,
17693                sizeof(confp->pri.pri.msn_list));
17694          } else if (!strcasecmp(v->name, "nsf")) {
17695             if (!strcasecmp(v->value, "sdn"))
17696                confp->pri.pri.nsf = PRI_NSF_SDN;
17697             else if (!strcasecmp(v->value, "megacom"))
17698                confp->pri.pri.nsf = PRI_NSF_MEGACOM;
17699             else if (!strcasecmp(v->value, "tollfreemegacom"))
17700                confp->pri.pri.nsf = PRI_NSF_TOLL_FREE_MEGACOM;
17701             else if (!strcasecmp(v->value, "accunet"))
17702                confp->pri.pri.nsf = PRI_NSF_ACCUNET;
17703             else if (!strcasecmp(v->value, "none"))
17704                confp->pri.pri.nsf = PRI_NSF_NONE;
17705             else {
17706                ast_log(LOG_WARNING, "Unknown network-specific facility '%s' at line %d.\n", v->value, v->lineno);
17707                confp->pri.pri.nsf = PRI_NSF_NONE;
17708             }
17709          } else if (!strcasecmp(v->name, "priindication")) {
17710             if (!strcasecmp(v->value, "outofband"))
17711                confp->chan.priindication_oob = 1;
17712             else if (!strcasecmp(v->value, "inband"))
17713                confp->chan.priindication_oob = 0;
17714             else
17715                ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d.\n",
17716                   v->value, v->lineno);
17717          } else if (!strcasecmp(v->name, "priexclusive")) {
17718             confp->chan.priexclusive = ast_true(v->value);
17719          } else if (!strcasecmp(v->name, "internationalprefix")) {
17720             ast_copy_string(confp->pri.pri.internationalprefix, v->value, sizeof(confp->pri.pri.internationalprefix));
17721          } else if (!strcasecmp(v->name, "nationalprefix")) {
17722             ast_copy_string(confp->pri.pri.nationalprefix, v->value, sizeof(confp->pri.pri.nationalprefix));
17723          } else if (!strcasecmp(v->name, "localprefix")) {
17724             ast_copy_string(confp->pri.pri.localprefix, v->value, sizeof(confp->pri.pri.localprefix));
17725          } else if (!strcasecmp(v->name, "privateprefix")) {
17726             ast_copy_string(confp->pri.pri.privateprefix, v->value, sizeof(confp->pri.pri.privateprefix));
17727          } else if (!strcasecmp(v->name, "unknownprefix")) {
17728             ast_copy_string(confp->pri.pri.unknownprefix, v->value, sizeof(confp->pri.pri.unknownprefix));
17729          } else if (!strcasecmp(v->name, "resetinterval")) {
17730             if (!strcasecmp(v->value, "never"))
17731                confp->pri.pri.resetinterval = -1;
17732             else if (atoi(v->value) >= 60)
17733                confp->pri.pri.resetinterval = atoi(v->value);
17734             else
17735                ast_log(LOG_WARNING, "'%s' is not a valid reset interval, should be >= 60 seconds or 'never' at line %d.\n",
17736                   v->value, v->lineno);
17737          } else if (!strcasecmp(v->name, "minunused")) {
17738             confp->pri.pri.minunused = atoi(v->value);
17739          } else if (!strcasecmp(v->name, "minidle")) {
17740             confp->pri.pri.minidle = atoi(v->value);
17741          } else if (!strcasecmp(v->name, "idleext")) {
17742             ast_copy_string(confp->pri.pri.idleext, v->value, sizeof(confp->pri.pri.idleext));
17743          } else if (!strcasecmp(v->name, "idledial")) {
17744             ast_copy_string(confp->pri.pri.idledial, v->value, sizeof(confp->pri.pri.idledial));
17745          } else if (!strcasecmp(v->name, "overlapdial")) {
17746             if (ast_true(v->value)) {
17747                confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
17748             } else if (!strcasecmp(v->value, "incoming")) {
17749                confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_INCOMING;
17750             } else if (!strcasecmp(v->value, "outgoing")) {
17751                confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_OUTGOING;
17752             } else if (!strcasecmp(v->value, "both") || ast_true(v->value)) {
17753                confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
17754             } else {
17755                confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_NONE;
17756             }
17757 #ifdef HAVE_PRI_PROG_W_CAUSE
17758          } else if (!strcasecmp(v->name, "qsigchannelmapping")) {
17759             if (!strcasecmp(v->value, "logical")) {
17760                confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_LOGICAL;
17761             } else if (!strcasecmp(v->value, "physical")) {
17762                confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL;
17763             } else {
17764                confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL;
17765             }
17766 #endif
17767          } else if (!strcasecmp(v->name, "discardremoteholdretrieval")) {
17768             confp->pri.pri.discardremoteholdretrieval = ast_true(v->value);
17769 #if defined(HAVE_PRI_SERVICE_MESSAGES)
17770          } else if (!strcasecmp(v->name, "service_message_support")) {
17771             /* assuming switchtype for this channel group has been configured already */
17772             if ((confp->pri.pri.switchtype == PRI_SWITCH_ATT4ESS 
17773                || confp->pri.pri.switchtype == PRI_SWITCH_LUCENT5E
17774                || confp->pri.pri.switchtype == PRI_SWITCH_NI2) && ast_true(v->value)) {
17775                confp->pri.pri.enable_service_message_support = 1;
17776             } else {
17777                confp->pri.pri.enable_service_message_support = 0;
17778             }
17779 #endif   /* defined(HAVE_PRI_SERVICE_MESSAGES) */
17780 #ifdef HAVE_PRI_INBANDDISCONNECT
17781          } else if (!strcasecmp(v->name, "inbanddisconnect")) {
17782             confp->pri.pri.inbanddisconnect = ast_true(v->value);
17783 #endif
17784          } else if (!strcasecmp(v->name, "pritimer")) {
17785 #ifdef PRI_GETSET_TIMERS
17786             char tmp[20];
17787             char *timerc;
17788             char *c;
17789             int timer;
17790             int timeridx;
17791 
17792             ast_copy_string(tmp, v->value, sizeof(tmp));
17793             c = tmp;
17794             timerc = strsep(&c, ",");
17795             if (!ast_strlen_zero(timerc) && !ast_strlen_zero(c)) {
17796                timeridx = pri_timer2idx(timerc);
17797                timer = atoi(c);
17798                if (timeridx < 0 || PRI_MAX_TIMERS <= timeridx) {
17799                   ast_log(LOG_WARNING,
17800                      "'%s' is not a valid ISDN timer at line %d.\n", timerc,
17801                      v->lineno);
17802                } else if (!timer) {
17803                   ast_log(LOG_WARNING,
17804                      "'%s' is not a valid value for ISDN timer '%s' at line %d.\n",
17805                      c, timerc, v->lineno);
17806                } else {
17807                   confp->pri.pri.pritimers[timeridx] = timer;
17808                }
17809             } else {
17810                ast_log(LOG_WARNING,
17811                   "'%s' is not a valid ISDN timer configuration string at line %d.\n",
17812                   v->value, v->lineno);
17813             }
17814 #endif /* PRI_GETSET_TIMERS */
17815          } else if (!strcasecmp(v->name, "facilityenable")) {
17816             confp->pri.pri.facilityenable = ast_true(v->value);
17817 #if defined(HAVE_PRI_AOC_EVENTS)
17818          } else if (!strcasecmp(v->name, "aoc_enable")) {
17819             confp->pri.pri.aoc_passthrough_flag = 0;
17820             if (strchr(v->value, 's') || strchr(v->value, 'S')) {
17821                confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_S;
17822             }
17823             if (strchr(v->value, 'd') || strchr(v->value, 'D')) {
17824                confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_D;
17825             }
17826             if (strchr(v->value, 'e') || strchr(v->value, 'E')) {
17827                confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_E;
17828             }
17829          } else if (!strcasecmp(v->name, "aoce_delayhangup")) {
17830             confp->pri.pri.aoce_delayhangup = ast_true(v->value);
17831 #endif   /* defined(HAVE_PRI_AOC_EVENTS) */
17832 #if defined(HAVE_PRI_CALL_HOLD)
17833          } else if (!strcasecmp(v->name, "hold_disconnect_transfer")) {
17834             confp->pri.pri.hold_disconnect_transfer = ast_true(v->value);
17835 #endif   /* defined(HAVE_PRI_CALL_HOLD) */
17836 #if defined(HAVE_PRI_CCSS)
17837          } else if (!strcasecmp(v->name, "cc_ptmp_recall_mode")) {
17838             if (!strcasecmp(v->value, "global")) {
17839                confp->pri.pri.cc_ptmp_recall_mode = 0;/* globalRecall */
17840             } else if (!strcasecmp(v->value, "specific")) {
17841                confp->pri.pri.cc_ptmp_recall_mode = 1;/* specificRecall */
17842             } else {
17843                confp->pri.pri.cc_ptmp_recall_mode = 1;/* specificRecall */
17844             }
17845          } else if (!strcasecmp(v->name, "cc_qsig_signaling_link_req")) {
17846             if (!strcasecmp(v->value, "release")) {
17847                confp->pri.pri.cc_qsig_signaling_link_req = 0;/* release */
17848             } else if (!strcasecmp(v->value, "retain")) {
17849                confp->pri.pri.cc_qsig_signaling_link_req = 1;/* retain */
17850             } else if (!strcasecmp(v->value, "do_not_care")) {
17851                confp->pri.pri.cc_qsig_signaling_link_req = 2;/* do-not-care */
17852             } else {
17853                confp->pri.pri.cc_qsig_signaling_link_req = 1;/* retain */
17854             }
17855          } else if (!strcasecmp(v->name, "cc_qsig_signaling_link_rsp")) {
17856             if (!strcasecmp(v->value, "release")) {
17857                confp->pri.pri.cc_qsig_signaling_link_rsp = 0;/* release */
17858             } else if (!strcasecmp(v->value, "retain")) {
17859                confp->pri.pri.cc_qsig_signaling_link_rsp = 1;/* retain */
17860             } else {
17861                confp->pri.pri.cc_qsig_signaling_link_rsp = 1;/* retain */
17862             }
17863 #endif   /* defined(HAVE_PRI_CCSS) */
17864 #if defined(HAVE_PRI_CALL_WAITING)
17865          } else if (!strcasecmp(v->name, "max_call_waiting_calls")) {
17866             confp->pri.pri.max_call_waiting_calls = atoi(v->value);
17867             if (confp->pri.pri.max_call_waiting_calls < 0) {
17868                /* Negative values are not allowed. */
17869                confp->pri.pri.max_call_waiting_calls = 0;
17870             }
17871          } else if (!strcasecmp(v->name, "allow_call_waiting_calls")) {
17872             confp->pri.pri.allow_call_waiting_calls = ast_true(v->value);
17873 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
17874 #if defined(HAVE_PRI_MWI)
17875          } else if (!strcasecmp(v->name, "mwi_mailboxes")) {
17876             ast_copy_string(confp->pri.pri.mwi_mailboxes, v->value,
17877                sizeof(confp->pri.pri.mwi_mailboxes));
17878 #endif   /* defined(HAVE_PRI_MWI) */
17879          } else if (!strcasecmp(v->name, "append_msn_to_cid_tag")) {
17880             confp->pri.pri.append_msn_to_user_tag = ast_true(v->value);
17881          } else if (!strcasecmp(v->name, "inband_on_setup_ack")) {
17882             confp->pri.pri.inband_on_setup_ack = ast_true(v->value);
17883          } else if (!strcasecmp(v->name, "inband_on_proceeding")) {
17884             confp->pri.pri.inband_on_proceeding = ast_true(v->value);
17885          } else if (!strcasecmp(v->name, "layer1_presence")) {
17886             if (!strcasecmp(v->value, "required")) {
17887                confp->pri.pri.layer1_ignored = 0;
17888             } else if (!strcasecmp(v->value, "ignore")) {
17889                confp->pri.pri.layer1_ignored = 1;
17890             } else {
17891                /* Default */
17892                confp->pri.pri.layer1_ignored = 0;
17893             }
17894 #if defined(HAVE_PRI_L2_PERSISTENCE)
17895          } else if (!strcasecmp(v->name, "layer2_persistence")) {
17896             if (!strcasecmp(v->value, "keep_up")) {
17897                confp->pri.pri.l2_persistence = PRI_L2_PERSISTENCE_KEEP_UP;
17898             } else if (!strcasecmp(v->value, "leave_down")) {
17899                confp->pri.pri.l2_persistence = PRI_L2_PERSISTENCE_LEAVE_DOWN;
17900             } else {
17901                confp->pri.pri.l2_persistence = PRI_L2_PERSISTENCE_DEFAULT;
17902             }
17903 #endif   /* defined(HAVE_PRI_L2_PERSISTENCE) */
17904 #endif /* HAVE_PRI */
17905 #if defined(HAVE_SS7)
17906          } else if (!strcasecmp(v->name, "ss7type")) {
17907             if (!strcasecmp(v->value, "itu")) {
17908                cur_ss7type = SS7_ITU;
17909             } else if (!strcasecmp(v->value, "ansi")) {
17910                cur_ss7type = SS7_ANSI;
17911             } else
17912                ast_log(LOG_WARNING, "'%s' is an unknown ss7 switch type at line %d.!\n", v->value, v->lineno);
17913          } else if (!strcasecmp(v->name, "linkset")) {
17914             cur_linkset = atoi(v->value);
17915          } else if (!strcasecmp(v->name, "pointcode")) {
17916             cur_pointcode = parse_pointcode(v->value);
17917          } else if (!strcasecmp(v->name, "adjpointcode")) {
17918             cur_adjpointcode = parse_pointcode(v->value);
17919          } else if (!strcasecmp(v->name, "defaultdpc")) {
17920             cur_defaultdpc = parse_pointcode(v->value);
17921          } else if (!strcasecmp(v->name, "cicbeginswith")) {
17922             cur_cicbeginswith = atoi(v->value);
17923          } else if (!strcasecmp(v->name, "networkindicator")) {
17924             if (!strcasecmp(v->value, "national"))
17925                cur_networkindicator = SS7_NI_NAT;
17926             else if (!strcasecmp(v->value, "national_spare"))
17927                cur_networkindicator = SS7_NI_NAT_SPARE;
17928             else if (!strcasecmp(v->value, "international"))
17929                cur_networkindicator = SS7_NI_INT;
17930             else if (!strcasecmp(v->value, "international_spare"))
17931                cur_networkindicator = SS7_NI_INT_SPARE;
17932             else
17933                cur_networkindicator = -1;
17934          } else if (!strcasecmp(v->name, "ss7_internationalprefix")) {
17935             ast_copy_string(confp->ss7.ss7.internationalprefix, v->value, sizeof(confp->ss7.ss7.internationalprefix));
17936          } else if (!strcasecmp(v->name, "ss7_nationalprefix")) {
17937             ast_copy_string(confp->ss7.ss7.nationalprefix, v->value, sizeof(confp->ss7.ss7.nationalprefix));
17938          } else if (!strcasecmp(v->name, "ss7_subscriberprefix")) {
17939             ast_copy_string(confp->ss7.ss7.subscriberprefix, v->value, sizeof(confp->ss7.ss7.subscriberprefix));
17940          } else if (!strcasecmp(v->name, "ss7_unknownprefix")) {
17941             ast_copy_string(confp->ss7.ss7.unknownprefix, v->value, sizeof(confp->ss7.ss7.unknownprefix));
17942          } else if (!strcasecmp(v->name, "ss7_called_nai")) {
17943             if (!strcasecmp(v->value, "national")) {
17944                confp->ss7.ss7.called_nai = SS7_NAI_NATIONAL;
17945             } else if (!strcasecmp(v->value, "international")) {
17946                confp->ss7.ss7.called_nai = SS7_NAI_INTERNATIONAL;
17947             } else if (!strcasecmp(v->value, "subscriber")) {
17948                confp->ss7.ss7.called_nai = SS7_NAI_SUBSCRIBER;
17949             } else if (!strcasecmp(v->value, "unknown")) {
17950                confp->ss7.ss7.called_nai = SS7_NAI_UNKNOWN;
17951             } else if (!strcasecmp(v->value, "dynamic")) {
17952                confp->ss7.ss7.called_nai = SS7_NAI_DYNAMIC;
17953             } else {
17954                ast_log(LOG_WARNING, "Unknown SS7 called_nai '%s' at line %d.\n", v->value, v->lineno);
17955             }
17956          } else if (!strcasecmp(v->name, "ss7_calling_nai")) {
17957             if (!strcasecmp(v->value, "national")) {
17958                confp->ss7.ss7.calling_nai = SS7_NAI_NATIONAL;
17959             } else if (!strcasecmp(v->value, "international")) {
17960                confp->ss7.ss7.calling_nai = SS7_NAI_INTERNATIONAL;
17961             } else if (!strcasecmp(v->value, "subscriber")) {
17962                confp->ss7.ss7.calling_nai = SS7_NAI_SUBSCRIBER;
17963             } else if (!strcasecmp(v->value, "unknown")) {
17964                confp->ss7.ss7.calling_nai = SS7_NAI_UNKNOWN;
17965             } else if (!strcasecmp(v->value, "dynamic")) {
17966                confp->ss7.ss7.calling_nai = SS7_NAI_DYNAMIC;
17967             } else {
17968                ast_log(LOG_WARNING, "Unknown SS7 calling_nai '%s' at line %d.\n", v->value, v->lineno);
17969             }
17970          } else if (!strcasecmp(v->name, "sigchan")) {
17971             int sigchan, res;
17972             sigchan = atoi(v->value);
17973             res = linkset_addsigchan(sigchan);
17974             if (res < 0)
17975                return -1;
17976 
17977          } else if (!strcasecmp(v->name, "ss7_explicitacm")) {
17978             struct dahdi_ss7 *link;
17979             link = ss7_resolve_linkset(cur_linkset);
17980             if (!link) {
17981                ast_log(LOG_ERROR, "Invalid linkset number.  Must be between 1 and %d\n", NUM_SPANS + 1);
17982                return -1;
17983             }
17984             if (ast_true(v->value))
17985                link->ss7.flags |= LINKSET_FLAG_EXPLICITACM;
17986 #endif   /* defined(HAVE_SS7) */
17987 #ifdef HAVE_OPENR2
17988          } else if (!strcasecmp(v->name, "mfcr2_advanced_protocol_file")) {
17989             ast_copy_string(confp->mfcr2.r2proto_file, v->value, sizeof(confp->mfcr2.r2proto_file));
17990             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);
17991          } else if (!strcasecmp(v->name, "mfcr2_logdir")) {
17992             ast_copy_string(confp->mfcr2.logdir, v->value, sizeof(confp->mfcr2.logdir));
17993          } else if (!strcasecmp(v->name, "mfcr2_variant")) {
17994             confp->mfcr2.variant = openr2_proto_get_variant(v->value);
17995             if (OR2_VAR_UNKNOWN == confp->mfcr2.variant) {
17996                ast_log(LOG_WARNING, "Unknown MFC/R2 variant '%s' at line %d, defaulting to ITU.\n", v->value, v->lineno);
17997                confp->mfcr2.variant = OR2_VAR_ITU;
17998             }
17999          } else if (!strcasecmp(v->name, "mfcr2_mfback_timeout")) {
18000             confp->mfcr2.mfback_timeout = atoi(v->value);
18001             if (!confp->mfcr2.mfback_timeout) {
18002                ast_log(LOG_WARNING, "MF timeout of 0? hum, I will protect you from your ignorance. Setting default.\n");
18003                confp->mfcr2.mfback_timeout = -1;
18004             } else if (confp->mfcr2.mfback_timeout > 0 && confp->mfcr2.mfback_timeout < 500) {
18005                ast_log(LOG_WARNING, "MF timeout less than 500ms is not recommended, you have been warned!\n");
18006             }
18007          } else if (!strcasecmp(v->name, "mfcr2_metering_pulse_timeout")) {
18008             confp->mfcr2.metering_pulse_timeout = atoi(v->value);
18009             if (confp->mfcr2.metering_pulse_timeout > 500) {
18010                ast_log(LOG_WARNING, "Metering pulse timeout greater than 500ms is not recommended, you have been warned!\n");
18011             }
18012          } else if (!strcasecmp(v->name, "mfcr2_get_ani_first")) {
18013             confp->mfcr2.get_ani_first = ast_true(v->value) ? 1 : 0;
18014          } else if (!strcasecmp(v->name, "mfcr2_double_answer")) {
18015             confp->mfcr2.double_answer = ast_true(v->value) ? 1 : 0;
18016          } else if (!strcasecmp(v->name, "mfcr2_charge_calls")) {
18017             confp->mfcr2.charge_calls = ast_true(v->value) ? 1 : 0;
18018          } else if (!strcasecmp(v->name, "mfcr2_accept_on_offer")) {
18019             confp->mfcr2.accept_on_offer = ast_true(v->value) ? 1 : 0;
18020          } else if (!strcasecmp(v->name, "mfcr2_allow_collect_calls")) {
18021             confp->mfcr2.allow_collect_calls = ast_true(v->value) ? 1 : 0;
18022          } else if (!strcasecmp(v->name, "mfcr2_forced_release")) {
18023             confp->mfcr2.forced_release = ast_true(v->value) ? 1 : 0;
18024          } else if (!strcasecmp(v->name, "mfcr2_immediate_accept")) {
18025             confp->mfcr2.immediate_accept = ast_true(v->value) ? 1 : 0;
18026 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
18027          } else if (!strcasecmp(v->name, "mfcr2_skip_category")) {
18028             confp->mfcr2.skip_category_request = ast_true(v->value) ? 1 : 0;
18029 #endif
18030          } else if (!strcasecmp(v->name, "mfcr2_call_files")) {
18031             confp->mfcr2.call_files = ast_true(v->value) ? 1 : 0;
18032          } else if (!strcasecmp(v->name, "mfcr2_max_ani")) {
18033             confp->mfcr2.max_ani = atoi(v->value);
18034             if (confp->mfcr2.max_ani >= AST_MAX_EXTENSION){
18035                confp->mfcr2.max_ani = AST_MAX_EXTENSION - 1;
18036             }
18037          } else if (!strcasecmp(v->name, "mfcr2_max_dnis")) {
18038             confp->mfcr2.max_dnis = atoi(v->value);
18039             if (confp->mfcr2.max_dnis >= AST_MAX_EXTENSION){
18040                confp->mfcr2.max_dnis = AST_MAX_EXTENSION - 1;
18041             }
18042          } else if (!strcasecmp(v->name, "mfcr2_category")) {
18043             confp->mfcr2.category = openr2_proto_get_category(v->value);
18044             if (OR2_CALLING_PARTY_CATEGORY_UNKNOWN == confp->mfcr2.category) {
18045                confp->mfcr2.category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER;
18046                ast_log(LOG_WARNING, "Invalid MFC/R2 caller category '%s' at line %d. Using national subscriber as default.\n",
18047                      v->value, v->lineno);
18048             }
18049          } else if (!strcasecmp(v->name, "mfcr2_logging")) {
18050             openr2_log_level_t tmplevel;
18051             char *clevel;
18052             char *logval = ast_strdupa(v->value);
18053             while (logval) {
18054                clevel = strsep(&logval,",");
18055                if (-1 == (tmplevel = openr2_log_get_level(clevel))) {
18056                   ast_log(LOG_WARNING, "Ignoring invalid logging level: '%s' at line %d.\n", clevel, v->lineno);
18057                   continue;
18058                }
18059                confp->mfcr2.loglevel |= tmplevel;
18060             }
18061 #endif /* HAVE_OPENR2 */
18062          } else if (!strcasecmp(v->name, "cadence")) {
18063             /* setup to scan our argument */
18064             int element_count, c[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
18065             int i;
18066             struct dahdi_ring_cadence new_cadence;
18067             int cid_location = -1;
18068             int firstcadencepos = 0;
18069             char original_args[80];
18070             int cadence_is_ok = 1;
18071 
18072             ast_copy_string(original_args, v->value, sizeof(original_args));
18073             /* 16 cadences allowed (8 pairs) */
18074             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]);
18075 
18076             /* Cadence must be even (on/off) */
18077             if (element_count % 2 == 1) {
18078                ast_log(LOG_ERROR, "Must be a silence duration for each ring duration: %s at line %d.\n", original_args, v->lineno);
18079                cadence_is_ok = 0;
18080             }
18081 
18082             /* Ring cadences cannot be negative */
18083             for (i = 0; i < element_count; i++) {
18084                if (c[i] == 0) {
18085                   ast_log(LOG_ERROR, "Ring or silence duration cannot be zero: %s at line %d.\n", original_args, v->lineno);
18086                   cadence_is_ok = 0;
18087                   break;
18088                } else if (c[i] < 0) {
18089                   if (i % 2 == 1) {
18090                      /* Silence duration, negative possibly okay */
18091                      if (cid_location == -1) {
18092                         cid_location = i;
18093                         c[i] *= -1;
18094                      } else {
18095                         ast_log(LOG_ERROR, "CID location specified twice: %s at line %d.\n", original_args, v->lineno);
18096                         cadence_is_ok = 0;
18097                         break;
18098                      }
18099                   } else {
18100                      if (firstcadencepos == 0) {
18101                         firstcadencepos = i; /* only recorded to avoid duplicate specification */
18102                                  /* duration will be passed negative to the DAHDI driver */
18103                      } else {
18104                          ast_log(LOG_ERROR, "First cadence position specified twice: %s at line %d.\n", original_args, v->lineno);
18105                         cadence_is_ok = 0;
18106                         break;
18107                      }
18108                   }
18109                }
18110             }
18111 
18112             /* Substitute our scanned cadence */
18113             for (i = 0; i < 16; i++) {
18114                new_cadence.ringcadence[i] = c[i];
18115             }
18116 
18117             if (cadence_is_ok) {
18118                /* ---we scanned it without getting annoyed; now some sanity checks--- */
18119                if (element_count < 2) {
18120                   ast_log(LOG_ERROR, "Minimum cadence is ring,pause: %s at line %d.\n", original_args, v->lineno);
18121                } else {
18122                   if (cid_location == -1) {
18123                      /* user didn't say; default to first pause */
18124                      cid_location = 1;
18125                   } else {
18126                      /* convert element_index to cidrings value */
18127                      cid_location = (cid_location + 1) / 2;
18128                   }
18129                   /* ---we like their cadence; try to install it--- */
18130                   if (!user_has_defined_cadences++)
18131                      /* this is the first user-defined cadence; clear the default user cadences */
18132                      num_cadence = 0;
18133                   if ((num_cadence+1) >= NUM_CADENCE_MAX)
18134                      ast_log(LOG_ERROR, "Already %d cadences; can't add another: %s at line %d.\n", NUM_CADENCE_MAX, original_args, v->lineno);
18135                   else {
18136                      cadences[num_cadence] = new_cadence;
18137                      cidrings[num_cadence++] = cid_location;
18138                      ast_verb(3, "cadence 'r%d' added: %s\n",num_cadence,original_args);
18139                   }
18140                }
18141             }
18142          } else if (!strcasecmp(v->name, "ringtimeout")) {
18143             ringt_base = (atoi(v->value) * 8) / READ_SIZE;
18144          } else if (!strcasecmp(v->name, "prewink")) {
18145             confp->timing.prewinktime = atoi(v->value);
18146          } else if (!strcasecmp(v->name, "preflash")) {
18147             confp->timing.preflashtime = atoi(v->value);
18148          } else if (!strcasecmp(v->name, "wink")) {
18149             confp->timing.winktime = atoi(v->value);
18150          } else if (!strcasecmp(v->name, "flash")) {
18151             confp->timing.flashtime = atoi(v->value);
18152          } else if (!strcasecmp(v->name, "start")) {
18153             confp->timing.starttime = atoi(v->value);
18154          } else if (!strcasecmp(v->name, "rxwink")) {
18155             confp->timing.rxwinktime = atoi(v->value);
18156          } else if (!strcasecmp(v->name, "rxflash")) {
18157             confp->timing.rxflashtime = atoi(v->value);
18158          } else if (!strcasecmp(v->name, "debounce")) {
18159             confp->timing.debouncetime = atoi(v->value);
18160          } else if (!strcasecmp(v->name, "toneduration")) {
18161             int toneduration;
18162             int ctlfd;
18163             int res;
18164             struct dahdi_dialparams dps;
18165 
18166             ctlfd = open("/dev/dahdi/ctl", O_RDWR);
18167             if (ctlfd == -1) {
18168                ast_log(LOG_ERROR, "Unable to open /dev/dahdi/ctl to set toneduration at line %d.\n", v->lineno);
18169                return -1;
18170             }
18171 
18172             toneduration = atoi(v->value);
18173             if (toneduration > -1) {
18174                memset(&dps, 0, sizeof(dps));
18175 
18176                dps.dtmf_tonelen = dps.mfv1_tonelen = toneduration;
18177                res = ioctl(ctlfd, DAHDI_SET_DIALPARAMS, &dps);
18178                if (res < 0) {
18179                   ast_log(LOG_ERROR, "Invalid tone duration: %d ms at line %d: %s\n", toneduration, v->lineno, strerror(errno));
18180                   close(ctlfd);
18181                   return -1;
18182                }
18183             }
18184             close(ctlfd);
18185          } else if (!strcasecmp(v->name, "defaultcic")) {
18186             ast_copy_string(defaultcic, v->value, sizeof(defaultcic));
18187          } else if (!strcasecmp(v->name, "defaultozz")) {
18188             ast_copy_string(defaultozz, v->value, sizeof(defaultozz));
18189          } else if (!strcasecmp(v->name, "mwilevel")) {
18190             mwilevel = atoi(v->value);
18191          } else if (!strcasecmp(v->name, "dtmfcidlevel")) {
18192             dtmfcid_level = atoi(v->value);
18193          } else if (!strcasecmp(v->name, "reportalarms")) {
18194             if (!strcasecmp(v->value, "all"))
18195                report_alarms = REPORT_CHANNEL_ALARMS | REPORT_SPAN_ALARMS;
18196             if (!strcasecmp(v->value, "none"))
18197                report_alarms = 0;
18198             else if (!strcasecmp(v->value, "channels"))
18199                report_alarms = REPORT_CHANNEL_ALARMS;
18200             else if (!strcasecmp(v->value, "spans"))
18201                report_alarms = REPORT_SPAN_ALARMS;
18202           }
18203       } else if (!(options & PROC_DAHDI_OPT_NOWARN) )
18204          ast_log(LOG_WARNING, "Ignoring any changes to '%s' (on reload) at line %d.\n", v->name, v->lineno);
18205    }
18206 
18207    /* Since confp has already filled invidual dahdi_pvt objects with channels at this point, clear the variables in confp's pvt. */
18208    if (confp->chan.vars) {
18209       ast_variables_destroy(confp->chan.vars);
18210       confp->chan.vars = NULL;
18211    }
18212 
18213    if (dahdichan) {
18214       /* Process the deferred dahdichan value. */
18215       if (build_channels(confp, dahdichan->value, reload, dahdichan->lineno,
18216          &found_pseudo)) {
18217          if (confp->ignore_failed_channels) {
18218             ast_log(LOG_WARNING,
18219                "Dahdichan '%s' failure ignored: ignore_failed_channels.\n",
18220                dahdichan->value);
18221          } else {
18222             return -1;
18223          }
18224       }
18225    }
18226 
18227    /* mark the first channels of each DAHDI span to watch for their span alarms */
18228    for (tmp = iflist, y=-1; tmp; tmp = tmp->next) {
18229       if (!tmp->destroy && tmp->span != y) {
18230          tmp->manages_span_alarms = 1;
18231          y = tmp->span; 
18232       } else {
18233          tmp->manages_span_alarms = 0;
18234       }
18235    }
18236 
18237    /*< \todo why check for the pseudo in the per-channel section.
18238     * Any actual use for manual setup of the pseudo channel? */
18239    if (!found_pseudo && reload != 1 && !(options & PROC_DAHDI_OPT_NOCHAN)) {
18240       /* use the default configuration for a channel, so
18241          that any settings from real configured channels
18242          don't "leak" into the pseudo channel config
18243       */
18244       struct dahdi_chan_conf conf = dahdi_chan_conf_default();
18245 
18246       if (conf.chan.cc_params) {
18247          tmp = mkintf(CHAN_PSEUDO, &conf, reload);
18248       } else {
18249          tmp = NULL;
18250       }
18251       if (tmp) {
18252          ast_verb(3, "Automatically generated pseudo channel\n");
18253       } else {
18254          ast_log(LOG_WARNING, "Unable to register pseudo channel!\n");
18255       }
18256       ast_cc_config_params_destroy(conf.chan.cc_params);
18257    }
18258    return 0;
18259 }
18260 
18261 /*!
18262  * \internal
18263  * \brief Deep copy struct dahdi_chan_conf.
18264  * \since 1.8
18265  *
18266  * \param dest Destination.
18267  * \param src Source.
18268  *
18269  * \return Nothing
18270  */
18271 static void deep_copy_dahdi_chan_conf(struct dahdi_chan_conf *dest, const struct dahdi_chan_conf *src)
18272 {
18273    struct ast_cc_config_params *cc_params;
18274 
18275    cc_params = dest->chan.cc_params;
18276    *dest = *src;
18277    dest->chan.cc_params = cc_params;
18278    ast_cc_copy_config_params(dest->chan.cc_params, src->chan.cc_params);
18279 }
18280 
18281 /*!
18282  * \internal
18283  * \brief Setup DAHDI channel driver.
18284  *
18285  * \param reload enum: load_module(0), reload(1), restart(2).
18286  * \param default_conf Default config parameters.  So cc_params can be properly destroyed.
18287  * \param base_conf Default config parameters per section.  So cc_params can be properly destroyed.
18288  * \param conf Local config parameters.  So cc_params can be properly destroyed.
18289  *
18290  * \retval 0 on success.
18291  * \retval -1 on error.
18292  */
18293 static int setup_dahdi_int(int reload, struct dahdi_chan_conf *default_conf, struct dahdi_chan_conf *base_conf, struct dahdi_chan_conf *conf)
18294 {
18295    struct ast_config *cfg;
18296    struct ast_config *ucfg;
18297    struct ast_variable *v;
18298    struct ast_flags config_flags = { reload == 1 ? CONFIG_FLAG_FILEUNCHANGED : 0 };
18299    const char *chans;
18300    const char *cat;
18301    int res;
18302 
18303 #ifdef HAVE_PRI
18304    char *c;
18305    int spanno;
18306    int i;
18307    int logicalspan;
18308    int trunkgroup;
18309    int dchannels[SIG_PRI_NUM_DCHANS];
18310 #endif
18311    int have_cfg_now;
18312    static int had_cfg_before = 1;/* So initial load will complain if we don't have cfg. */
18313 
18314    cfg = ast_config_load(config, config_flags);
18315    have_cfg_now = !!cfg;
18316    if (!cfg) {
18317       /* Error if we have no config file */
18318       if (had_cfg_before) {
18319          ast_log(LOG_ERROR, "Unable to load config %s\n", config);
18320          ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
18321       }
18322       cfg = ast_config_new();/* Dummy config */
18323       if (!cfg) {
18324          return 0;
18325       }
18326       ucfg = ast_config_load("users.conf", config_flags);
18327       if (ucfg == CONFIG_STATUS_FILEUNCHANGED) {
18328          ast_config_destroy(cfg);
18329          return 0;
18330       }
18331       if (ucfg == CONFIG_STATUS_FILEINVALID) {
18332          ast_log(LOG_ERROR, "File users.conf cannot be parsed.  Aborting.\n");
18333          ast_config_destroy(cfg);
18334          return 0;
18335       }
18336    } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
18337       ucfg = ast_config_load("users.conf", config_flags);
18338       if (ucfg == CONFIG_STATUS_FILEUNCHANGED) {
18339          return 0;
18340       }
18341       if (ucfg == CONFIG_STATUS_FILEINVALID) {
18342          ast_log(LOG_ERROR, "File users.conf cannot be parsed.  Aborting.\n");
18343          return 0;
18344       }
18345       ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
18346       cfg = ast_config_load(config, config_flags);
18347       have_cfg_now = !!cfg;
18348       if (!cfg) {
18349          if (had_cfg_before) {
18350             /* We should have been able to load the config. */
18351             ast_log(LOG_ERROR, "Bad. Unable to load config %s\n", config);
18352             ast_config_destroy(ucfg);
18353             return 0;
18354          }
18355          cfg = ast_config_new();/* Dummy config */
18356          if (!cfg) {
18357             ast_config_destroy(ucfg);
18358             return 0;
18359          }
18360       } else if (cfg == CONFIG_STATUS_FILEINVALID) {
18361          ast_log(LOG_ERROR, "File %s cannot be parsed.  Aborting.\n", config);
18362          ast_config_destroy(ucfg);
18363          return 0;
18364       }
18365    } else if (cfg == CONFIG_STATUS_FILEINVALID) {
18366       ast_log(LOG_ERROR, "File %s cannot be parsed.  Aborting.\n", config);
18367       return 0;
18368    } else {
18369       ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
18370       ucfg = ast_config_load("users.conf", config_flags);
18371       if (ucfg == CONFIG_STATUS_FILEINVALID) {
18372          ast_log(LOG_ERROR, "File users.conf cannot be parsed.  Aborting.\n");
18373          ast_config_destroy(cfg);
18374          return 0;
18375       }
18376    }
18377    had_cfg_before = have_cfg_now;
18378 
18379    /* It's a little silly to lock it, but we might as well just to be sure */
18380    ast_mutex_lock(&iflock);
18381 #ifdef HAVE_PRI
18382    if (reload != 1) {
18383       /* Process trunkgroups first */
18384       v = ast_variable_browse(cfg, "trunkgroups");
18385       while (v) {
18386          if (!strcasecmp(v->name, "trunkgroup")) {
18387             trunkgroup = atoi(v->value);
18388             if (trunkgroup > 0) {
18389                if ((c = strchr(v->value, ','))) {
18390                   i = 0;
18391                   memset(dchannels, 0, sizeof(dchannels));
18392                   while (c && (i < SIG_PRI_NUM_DCHANS)) {
18393                      dchannels[i] = atoi(c + 1);
18394                      if (dchannels[i] < 0) {
18395                         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);
18396                      } else
18397                         i++;
18398                      c = strchr(c + 1, ',');
18399                   }
18400                   if (i) {
18401                      if (pri_create_trunkgroup(trunkgroup, dchannels)) {
18402                         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);
18403                   } else
18404                         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");
18405                   } else
18406                      ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
18407                } else
18408                   ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
18409             } else
18410                ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of chan_dahdi.conf\n", v->lineno);
18411          } else if (!strcasecmp(v->name, "spanmap")) {
18412             spanno = atoi(v->value);
18413             if (spanno > 0) {
18414                if ((c = strchr(v->value, ','))) {
18415                   trunkgroup = atoi(c + 1);
18416                   if (trunkgroup > 0) {
18417                      if ((c = strchr(c + 1, ',')))
18418                         logicalspan = atoi(c + 1);
18419                      else
18420                         logicalspan = 0;
18421                      if (logicalspan >= 0) {
18422                         if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) {
18423                            ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
18424                      } else
18425                            ast_verb(2, "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
18426                      } else
18427                         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);
18428                   } else
18429                      ast_log(LOG_WARNING, "Trunk group must be a postive number at line %d of chan_dahdi.conf\n", v->lineno);
18430                } else
18431                   ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of chan_dahdi.conf\n", v->lineno);
18432             } else
18433                ast_log(LOG_WARNING, "Span number must be a postive integer at line %d of chan_dahdi.conf\n", v->lineno);
18434          } else {
18435             ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name);
18436          }
18437          v = v->next;
18438       }
18439    }
18440 #endif
18441 
18442    /* Copy the default jb config over global_jbconf */
18443    memcpy(&global_jbconf, &default_jbconf, sizeof(global_jbconf));
18444 
18445    mwimonitornotify[0] = '\0';
18446 
18447    v = ast_variable_browse(cfg, "channels");
18448    if ((res = process_dahdi(base_conf,
18449       "" /* Must be empty for the channels category.  Silly voicemail mailbox. */,
18450       v, reload, 0))) {
18451       ast_mutex_unlock(&iflock);
18452       ast_config_destroy(cfg);
18453       if (ucfg) {
18454          ast_config_destroy(ucfg);
18455       }
18456       return res;
18457    }
18458 
18459    /* Now get configuration from all normal sections in chan_dahdi.conf: */
18460    for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) {
18461       /* [channels] and [trunkgroups] are used. Let's also reserve
18462        * [globals] and [general] for future use
18463        */
18464       if (!strcasecmp(cat, "general") ||
18465          !strcasecmp(cat, "trunkgroups") ||
18466          !strcasecmp(cat, "globals") ||
18467          !strcasecmp(cat, "channels")) {
18468          continue;
18469       }
18470 
18471       chans = ast_variable_retrieve(cfg, cat, "dahdichan");
18472       if (ast_strlen_zero(chans)) {
18473          /* Section is useless without a dahdichan value present. */
18474          continue;
18475       }
18476 
18477       /* Copy base_conf to conf. */
18478       deep_copy_dahdi_chan_conf(conf, base_conf);
18479 
18480       if ((res = process_dahdi(conf, cat, ast_variable_browse(cfg, cat), reload, PROC_DAHDI_OPT_NOCHAN))) {
18481          ast_mutex_unlock(&iflock);
18482          ast_config_destroy(cfg);
18483          if (ucfg) {
18484             ast_config_destroy(ucfg);
18485          }
18486          return res;
18487       }
18488    }
18489 
18490    ast_config_destroy(cfg);
18491 
18492    if (ucfg) {
18493       /* Reset base_conf, so things don't leak from chan_dahdi.conf */
18494       deep_copy_dahdi_chan_conf(base_conf, default_conf);
18495       process_dahdi(base_conf,
18496          "" /* Must be empty for the general category.  Silly voicemail mailbox. */,
18497          ast_variable_browse(ucfg, "general"), 1, 0);
18498 
18499       for (cat = ast_category_browse(ucfg, NULL); cat ; cat = ast_category_browse(ucfg, cat)) {
18500          if (!strcasecmp(cat, "general")) {
18501             continue;
18502          }
18503 
18504          chans = ast_variable_retrieve(ucfg, cat, "dahdichan");
18505          if (ast_strlen_zero(chans)) {
18506             /* Section is useless without a dahdichan value present. */
18507             continue;
18508          }
18509 
18510          /* Copy base_conf to conf. */
18511          deep_copy_dahdi_chan_conf(conf, base_conf);
18512 
18513          if ((res = process_dahdi(conf, cat, ast_variable_browse(ucfg, cat), reload, PROC_DAHDI_OPT_NOCHAN | PROC_DAHDI_OPT_NOWARN))) {
18514             ast_config_destroy(ucfg);
18515             ast_mutex_unlock(&iflock);
18516             return res;
18517          }
18518       }
18519       ast_config_destroy(ucfg);
18520    }
18521    ast_mutex_unlock(&iflock);
18522 
18523 #ifdef HAVE_PRI
18524    if (reload != 1) {
18525       int x;
18526       for (x = 0; x < NUM_SPANS; x++) {
18527          if (pris[x].pri.pvts[0]) {
18528             prepare_pri(pris + x);
18529             if (sig_pri_start_pri(&pris[x].pri)) {
18530                ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1);
18531                return -1;
18532             } else
18533                ast_verb(2, "Starting D-Channel on span %d\n", x + 1);
18534          }
18535       }
18536    }
18537 #endif
18538 #if defined(HAVE_SS7)
18539    if (reload != 1) {
18540       int x;
18541       for (x = 0; x < NUM_SPANS; x++) {
18542          if (linksets[x].ss7.ss7) {
18543             linksets[x].ss7.calls = &dahdi_ss7_callbacks;
18544             if (ast_pthread_create(&linksets[x].ss7.master, NULL, ss7_linkset, &linksets[x].ss7)) {
18545                ast_log(LOG_ERROR, "Unable to start SS7 linkset on span %d\n", x + 1);
18546                return -1;
18547             } else
18548                ast_verb(2, "Starting SS7 linkset on span %d\n", x + 1);
18549          }
18550       }
18551    }
18552 #endif   /* defined(HAVE_SS7) */
18553 #ifdef HAVE_OPENR2
18554    if (reload != 1) {
18555       int x;
18556       for (x = 0; x < r2links_count; x++) {
18557          if (ast_pthread_create(&r2links[x]->r2master, NULL, mfcr2_monitor, r2links[x])) {
18558             ast_log(LOG_ERROR, "Unable to start R2 monitor on channel group %d\n", x + 1);
18559             return -1;
18560          } else {
18561             ast_verb(2, "Starting R2 monitor on channel group %d\n", x + 1);
18562          }
18563       }
18564    }
18565 #endif
18566    /* And start the monitor for the first time */
18567    restart_monitor();
18568    return 0;
18569 }
18570 
18571 /*!
18572  * \internal
18573  * \brief Setup DAHDI channel driver.
18574  *
18575  * \param reload enum: load_module(0), reload(1), restart(2).
18576  *
18577  * \retval 0 on success.
18578  * \retval -1 on error.
18579  */
18580 static int setup_dahdi(int reload)
18581 {
18582    int res;
18583    struct dahdi_chan_conf default_conf = dahdi_chan_conf_default();
18584    struct dahdi_chan_conf base_conf = dahdi_chan_conf_default();
18585    struct dahdi_chan_conf conf = dahdi_chan_conf_default();
18586 
18587    if (default_conf.chan.cc_params && base_conf.chan.cc_params && conf.chan.cc_params) {
18588       res = setup_dahdi_int(reload, &default_conf, &base_conf, &conf);
18589    } else {
18590       res = -1;
18591    }
18592    ast_cc_config_params_destroy(default_conf.chan.cc_params);
18593    ast_cc_config_params_destroy(base_conf.chan.cc_params);
18594    ast_cc_config_params_destroy(conf.chan.cc_params);
18595 
18596    return res;
18597 }
18598 
18599 /*!
18600  * \internal
18601  * \brief Callback used to generate the dahdi status tree.
18602  * \param[in] search The search pattern tree.
18603  * \retval NULL on error.
18604  * \retval non-NULL The generated tree.
18605  */
18606 static int dahdi_status_data_provider_get(const struct ast_data_search *search,
18607       struct ast_data *data_root)
18608 {
18609    int ctl, res, span;
18610    struct ast_data *data_span, *data_alarms;
18611    struct dahdi_spaninfo s;
18612 
18613    ctl = open("/dev/dahdi/ctl", O_RDWR);
18614    if (ctl < 0) {
18615       ast_log(LOG_ERROR, "No DAHDI found. Unable to open /dev/dahdi/ctl: %s\n", strerror(errno));
18616       return -1;
18617    }
18618    for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
18619       s.spanno = span;
18620       res = ioctl(ctl, DAHDI_SPANSTAT, &s);
18621       if (res) {
18622          continue;
18623       }
18624 
18625       data_span = ast_data_add_node(data_root, "span");
18626       if (!data_span) {
18627          continue;
18628       }
18629       ast_data_add_str(data_span, "description", s.desc);
18630 
18631       /* insert the alarms status */
18632       data_alarms = ast_data_add_node(data_span, "alarms");
18633       if (!data_alarms) {
18634          continue;
18635       }
18636 
18637       ast_data_add_bool(data_alarms, "BLUE", s.alarms & DAHDI_ALARM_BLUE);
18638       ast_data_add_bool(data_alarms, "YELLOW", s.alarms & DAHDI_ALARM_YELLOW);
18639       ast_data_add_bool(data_alarms, "RED", s.alarms & DAHDI_ALARM_RED);
18640       ast_data_add_bool(data_alarms, "LOOPBACK", s.alarms & DAHDI_ALARM_LOOPBACK);
18641       ast_data_add_bool(data_alarms, "RECOVER", s.alarms & DAHDI_ALARM_RECOVER);
18642       ast_data_add_bool(data_alarms, "NOTOPEN", s.alarms & DAHDI_ALARM_NOTOPEN);
18643 
18644       ast_data_add_int(data_span, "irqmisses", s.irqmisses);
18645       ast_data_add_int(data_span, "bpviol", s.bpvcount);
18646       ast_data_add_int(data_span, "crc4", s.crc4count);
18647       ast_data_add_str(data_span, "framing", s.lineconfig & DAHDI_CONFIG_D4 ? "D4" :
18648                      s.lineconfig & DAHDI_CONFIG_ESF ? "ESF" :
18649                      s.lineconfig & DAHDI_CONFIG_CCS ? "CCS" :
18650                      "CAS");
18651       ast_data_add_str(data_span, "coding",  s.lineconfig & DAHDI_CONFIG_B8ZS ? "B8ZS" :
18652                      s.lineconfig & DAHDI_CONFIG_HDB3 ? "HDB3" :
18653                      s.lineconfig & DAHDI_CONFIG_AMI ? "AMI" :
18654                      "Unknown");
18655       ast_data_add_str(data_span, "options", s.lineconfig & DAHDI_CONFIG_CRC4 ?
18656                      s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" :
18657                      s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "YEL" : "");
18658       ast_data_add_str(data_span, "lbo", lbostr[s.lbo]);
18659 
18660       /* if this span doesn't match remove it. */
18661       if (!ast_data_search_match(search, data_span)) {
18662          ast_data_remove_node(data_root, data_span);
18663       }
18664    }
18665    close(ctl);
18666 
18667    return 0;
18668 }
18669 
18670 /*!
18671  * \internal
18672  * \brief Callback used to generate the dahdi channels tree.
18673  * \param[in] search The search pattern tree.
18674  * \retval NULL on error.
18675  * \retval non-NULL The generated tree.
18676  */
18677 static int dahdi_channels_data_provider_get(const struct ast_data_search *search,
18678       struct ast_data *data_root)
18679 {
18680    struct dahdi_pvt *tmp;
18681    struct ast_data *data_channel;
18682 
18683    ast_mutex_lock(&iflock);
18684    for (tmp = iflist; tmp; tmp = tmp->next) {
18685       data_channel = ast_data_add_node(data_root, "channel");
18686       if (!data_channel) {
18687          continue;
18688       }
18689 
18690       ast_data_add_structure(dahdi_pvt, data_channel, tmp);
18691 
18692       /* if this channel doesn't match remove it. */
18693       if (!ast_data_search_match(search, data_channel)) {
18694          ast_data_remove_node(data_root, data_channel);
18695       }
18696    }
18697    ast_mutex_unlock(&iflock);
18698 
18699    return 0;
18700 }
18701 
18702 /*!
18703  * \internal
18704  * \brief Callback used to generate the dahdi channels tree.
18705  * \param[in] search The search pattern tree.
18706  * \retval NULL on error.
18707  * \retval non-NULL The generated tree.
18708  */
18709 static int dahdi_version_data_provider_get(const struct ast_data_search *search,
18710       struct ast_data *data_root)
18711 {
18712    int pseudo_fd = -1;
18713    struct dahdi_versioninfo vi = {
18714       .version = "Unknown",
18715       .echo_canceller = "Unknown"
18716    };
18717 
18718    if ((pseudo_fd = open("/dev/dahdi/ctl", O_RDONLY)) < 0) {
18719       ast_log(LOG_ERROR, "Failed to open control file to get version.\n");
18720       return -1;
18721    }
18722 
18723    if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi)) {
18724       ast_log(LOG_ERROR, "Failed to get DAHDI version: %s\n", strerror(errno));
18725    }
18726 
18727    close(pseudo_fd);
18728 
18729    ast_data_add_str(data_root, "value", vi.version);
18730    ast_data_add_str(data_root, "echocanceller", vi.echo_canceller);
18731 
18732    return 0;
18733 }
18734 
18735 static const struct ast_data_handler dahdi_status_data_provider = {
18736    .version = AST_DATA_HANDLER_VERSION,
18737    .get = dahdi_status_data_provider_get
18738 };
18739 
18740 static const struct ast_data_handler dahdi_channels_data_provider = {
18741    .version = AST_DATA_HANDLER_VERSION,
18742    .get = dahdi_channels_data_provider_get
18743 };
18744 
18745 static const struct ast_data_handler dahdi_version_data_provider = {
18746    .version = AST_DATA_HANDLER_VERSION,
18747    .get = dahdi_version_data_provider_get
18748 };
18749 
18750 static const struct ast_data_entry dahdi_data_providers[] = {
18751    AST_DATA_ENTRY("asterisk/channel/dahdi/status", &dahdi_status_data_provider),
18752    AST_DATA_ENTRY("asterisk/channel/dahdi/channels", &dahdi_channels_data_provider),
18753    AST_DATA_ENTRY("asterisk/channel/dahdi/version", &dahdi_version_data_provider)
18754 };
18755 
18756 static int load_module(void)
18757 {
18758    int res;
18759 #if defined(HAVE_PRI) || defined(HAVE_SS7)
18760    int y;
18761 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
18762 
18763 #ifdef HAVE_PRI
18764    memset(pris, 0, sizeof(pris));
18765    for (y = 0; y < NUM_SPANS; y++) {
18766       sig_pri_init_pri(&pris[y].pri);
18767    }
18768    pri_set_error(dahdi_pri_error);
18769    pri_set_message(dahdi_pri_message);
18770    ast_register_application_xml(dahdi_send_keypad_facility_app, dahdi_send_keypad_facility_exec);
18771 #ifdef HAVE_PRI_PROG_W_CAUSE
18772    ast_register_application_xml(dahdi_send_callrerouting_facility_app, dahdi_send_callrerouting_facility_exec);
18773 #endif
18774 #if defined(HAVE_PRI_CCSS)
18775    if (ast_cc_agent_register(&dahdi_pri_cc_agent_callbacks)
18776       || ast_cc_monitor_register(&dahdi_pri_cc_monitor_callbacks)) {
18777       __unload_module();
18778       return AST_MODULE_LOAD_FAILURE;
18779    }
18780 #endif   /* defined(HAVE_PRI_CCSS) */
18781    if (sig_pri_load(
18782 #if defined(HAVE_PRI_CCSS)
18783       dahdi_pri_cc_type
18784 #else
18785       NULL
18786 #endif   /* defined(HAVE_PRI_CCSS) */
18787       )) {
18788       __unload_module();
18789       return AST_MODULE_LOAD_FAILURE;
18790    }
18791 #endif
18792 #if defined(HAVE_SS7)
18793    memset(linksets, 0, sizeof(linksets));
18794    for (y = 0; y < NUM_SPANS; y++) {
18795       sig_ss7_init_linkset(&linksets[y].ss7);
18796    }
18797    ss7_set_error(dahdi_ss7_error);
18798    ss7_set_message(dahdi_ss7_message);
18799 #endif   /* defined(HAVE_SS7) */
18800    res = setup_dahdi(0);
18801    /* Make sure we can register our DAHDI channel type */
18802    if (res)
18803       return AST_MODULE_LOAD_DECLINE;
18804    if (ast_channel_register(&dahdi_tech)) {
18805       ast_log(LOG_ERROR, "Unable to register channel class 'DAHDI'\n");
18806       __unload_module();
18807       return AST_MODULE_LOAD_FAILURE;
18808    }
18809 #ifdef HAVE_PRI
18810    ast_cli_register_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
18811 #endif
18812 #if defined(HAVE_SS7)
18813    ast_cli_register_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
18814 #endif   /* defined(HAVE_SS7) */
18815 #ifdef HAVE_OPENR2
18816    ast_cli_register_multiple(dahdi_mfcr2_cli, ARRAY_LEN(dahdi_mfcr2_cli));
18817    ast_register_application_xml(dahdi_accept_r2_call_app, dahdi_accept_r2_call_exec);
18818 #endif
18819 
18820    ast_cli_register_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli));
18821    /* register all the data providers */
18822    ast_data_register_multiple(dahdi_data_providers, ARRAY_LEN(dahdi_data_providers));
18823    memset(round_robin, 0, sizeof(round_robin));
18824    ast_manager_register_xml("DAHDITransfer", 0, action_transfer);
18825    ast_manager_register_xml("DAHDIHangup", 0, action_transferhangup);
18826    ast_manager_register_xml("DAHDIDialOffhook", 0, action_dahdidialoffhook);
18827    ast_manager_register_xml("DAHDIDNDon", 0, action_dahdidndon);
18828    ast_manager_register_xml("DAHDIDNDoff", 0, action_dahdidndoff);
18829    ast_manager_register_xml("DAHDIShowChannels", 0, action_dahdishowchannels);
18830    ast_manager_register_xml("DAHDIRestart", 0, action_dahdirestart);
18831 
18832    ast_cond_init(&ss_thread_complete, NULL);
18833 
18834    return res;
18835 }
18836 
18837 static int dahdi_sendtext(struct ast_channel *c, const char *text)
18838 {
18839 #define  END_SILENCE_LEN 400
18840 #define  HEADER_MS 50
18841 #define  TRAILER_MS 5
18842 #define  HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8)
18843 #define  ASCII_BYTES_PER_CHAR 80
18844 
18845    unsigned char *buf,*mybuf;
18846    struct dahdi_pvt *p = c->tech_pvt;
18847    struct pollfd fds[1];
18848    int size,res,fd,len,x;
18849    int bytes=0;
18850    /* Initial carrier (imaginary) */
18851    float cr = 1.0;
18852    float ci = 0.0;
18853    float scont = 0.0;
18854    int idx;
18855 
18856    idx = dahdi_get_index(c, p, 0);
18857    if (idx < 0) {
18858       ast_log(LOG_WARNING, "Huh?  I don't exist?\n");
18859       return -1;
18860    }
18861    if (!text[0]) return(0); /* if nothing to send, don't */
18862    if ((!p->tdd) && (!p->mate)) return(0);  /* if not in TDD mode, just return */
18863    if (p->mate)
18864       buf = ast_malloc(((strlen(text) + 1) * ASCII_BYTES_PER_CHAR) + END_SILENCE_LEN + HEADER_LEN);
18865    else
18866       buf = ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN);
18867    if (!buf)
18868       return -1;
18869    mybuf = buf;
18870    if (p->mate) {
18871       int codec = AST_LAW(p);
18872       for (x = 0; x < HEADER_MS; x++) {   /* 50 ms of Mark */
18873          PUT_CLID_MARKMS;
18874       }
18875       /* Put actual message */
18876       for (x = 0; text[x]; x++) {
18877          PUT_CLID(text[x]);
18878       }
18879       for (x = 0; x < TRAILER_MS; x++) {  /* 5 ms of Mark */
18880          PUT_CLID_MARKMS;
18881       }
18882       len = bytes;
18883       buf = mybuf;
18884    } else {
18885       len = tdd_generate(p->tdd, buf, text);
18886       if (len < 1) {
18887          ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text));
18888          ast_free(mybuf);
18889          return -1;
18890       }
18891    }
18892    memset(buf + len, 0x7f, END_SILENCE_LEN);
18893    len += END_SILENCE_LEN;
18894    fd = p->subs[idx].dfd;
18895    while (len) {
18896       if (ast_check_hangup(c)) {
18897          ast_free(mybuf);
18898          return -1;
18899       }
18900       size = len;
18901       if (size > READ_SIZE)
18902          size = READ_SIZE;
18903       fds[0].fd = fd;
18904       fds[0].events = POLLOUT | POLLPRI;
18905       fds[0].revents = 0;
18906       res = poll(fds, 1, -1);
18907       if (!res) {
18908          ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
18909          continue;
18910       }
18911       /* if got exception */
18912       if (fds[0].revents & POLLPRI) {
18913          ast_free(mybuf);
18914          return -1;
18915       }
18916       if (!(fds[0].revents & POLLOUT)) {
18917          ast_debug(1, "write fd not ready on channel %d\n", p->channel);
18918          continue;
18919       }
18920       res = write(fd, buf, size);
18921       if (res != size) {
18922          if (res == -1) {
18923             ast_free(mybuf);
18924             return -1;
18925          }
18926          ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
18927          break;
18928       }
18929       len -= size;
18930       buf += size;
18931    }
18932    ast_free(mybuf);
18933    return(0);
18934 }
18935 
18936 
18937 static int reload(void)
18938 {
18939    int res = 0;
18940 
18941    res = setup_dahdi(1);
18942    if (res) {
18943       ast_log(LOG_WARNING, "Reload of chan_dahdi.so is unsuccessful!\n");
18944       return -1;
18945    }
18946    return 0;
18947 }
18948 
18949 /* This is a workaround so that menuselect displays a proper description
18950  * AST_MODULE_INFO(, , "DAHDI Telephony"
18951  */
18952 
18953 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, tdesc,
18954    .load = load_module,
18955    .unload = unload_module,
18956    .reload = reload,
18957    .load_pri = AST_MODPRI_CHANNEL_DRIVER,
18958       .nonoptreq = "res_smdi",
18959    );

Generated on 7 Aug 2019 for Asterisk - The Open Source Telephony Project by  doxygen 1.6.1