Mon Oct 8 12:38:58 2012

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: 370017 $")
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 #ifdef HAVE_PRI
00075 #include "sig_pri.h"
00076 #endif
00077 
00078 #if defined(HAVE_SS7)
00079 #include "sig_ss7.h"
00080 #endif   /* defined(HAVE_SS7) */
00081 
00082 #ifdef HAVE_OPENR2
00083 /* put this here until sig_mfcr2 comes along */
00084 #define SIG_MFCR2_MAX_CHANNELS   672      /*!< No more than a DS3 per trunk group */
00085 #include <openr2.h>
00086 #endif
00087 
00088 #include "asterisk/lock.h"
00089 #include "asterisk/channel.h"
00090 #include "asterisk/config.h"
00091 #include "asterisk/module.h"
00092 #include "asterisk/pbx.h"
00093 #include "asterisk/file.h"
00094 #include "asterisk/ulaw.h"
00095 #include "asterisk/alaw.h"
00096 #include "asterisk/callerid.h"
00097 #include "asterisk/adsi.h"
00098 #include "asterisk/cli.h"
00099 #include "asterisk/cdr.h"
00100 #include "asterisk/cel.h"
00101 #include "asterisk/features.h"
00102 #include "asterisk/musiconhold.h"
00103 #include "asterisk/say.h"
00104 #include "asterisk/tdd.h"
00105 #include "asterisk/app.h"
00106 #include "asterisk/dsp.h"
00107 #include "asterisk/astdb.h"
00108 #include "asterisk/manager.h"
00109 #include "asterisk/causes.h"
00110 #include "asterisk/term.h"
00111 #include "asterisk/utils.h"
00112 #include "asterisk/transcap.h"
00113 #include "asterisk/stringfields.h"
00114 #include "asterisk/abstract_jb.h"
00115 #include "asterisk/smdi.h"
00116 #include "asterisk/astobj.h"
00117 #include "asterisk/event.h"
00118 #include "asterisk/devicestate.h"
00119 #include "asterisk/paths.h"
00120 #include "asterisk/ccss.h"
00121 #include "asterisk/data.h"
00122 
00123 /*** DOCUMENTATION
00124    <application name="DAHDISendKeypadFacility" language="en_US">
00125       <synopsis>
00126          Send digits out of band over a PRI.
00127       </synopsis>
00128       <syntax>
00129          <parameter name="digits" required="true" />
00130       </syntax>
00131       <description>
00132          <para>This application will send the given string of digits in a Keypad
00133          Facility IE over the current channel.</para>
00134       </description>
00135    </application>
00136    <application name="DAHDISendCallreroutingFacility" language="en_US">
00137       <synopsis>
00138          Send an ISDN call rerouting/deflection facility message.
00139       </synopsis>
00140       <syntax argsep=",">
00141          <parameter name="destination" required="true">
00142             <para>Destination number.</para>
00143          </parameter>
00144          <parameter name="original">
00145             <para>Original called number.</para>
00146          </parameter>
00147          <parameter name="reason">
00148             <para>Diversion reason, if not specified defaults to <literal>unknown</literal></para>
00149          </parameter>
00150       </syntax>
00151       <description>
00152          <para>This application will send an ISDN switch specific call
00153          rerouting/deflection facility message over the current channel.
00154          Supported switches depend upon the version of libpri in use.</para>
00155       </description>
00156    </application>
00157    <application name="DAHDIAcceptR2Call" language="en_US">
00158       <synopsis>
00159          Accept an R2 call if its not already accepted (you still need to answer it)
00160       </synopsis>
00161       <syntax>
00162          <parameter name="charge" required="true">
00163             <para>Yes or No.</para>
00164             <para>Whether you want to accept the call with charge or without charge.</para>
00165          </parameter>
00166       </syntax>
00167       <description>
00168          <para>This application will Accept the R2 call either with charge or no charge.</para>
00169       </description>
00170    </application>
00171    <manager name="DAHDITransfer" language="en_US">
00172       <synopsis>
00173          Transfer DAHDI Channel.
00174       </synopsis>
00175       <syntax>
00176          <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
00177          <parameter name="DAHDIChannel" required="true">
00178             <para>DAHDI channel number to transfer.</para>
00179          </parameter>
00180       </syntax>
00181       <description>
00182          <para>Simulate a flash hook event by the user connected to the channel.</para>
00183          <note><para>Valid only for analog channels.</para></note>
00184       </description>
00185    </manager>
00186    <manager name="DAHDIHangup" language="en_US">
00187       <synopsis>
00188          Hangup DAHDI Channel.
00189       </synopsis>
00190       <syntax>
00191          <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
00192          <parameter name="DAHDIChannel" required="true">
00193             <para>DAHDI channel number to hangup.</para>
00194          </parameter>
00195       </syntax>
00196       <description>
00197          <para>Simulate an on-hook event by the user connected to the channel.</para>
00198          <note><para>Valid only for analog channels.</para></note>
00199       </description>
00200    </manager>
00201    <manager name="DAHDIDialOffhook" language="en_US">
00202       <synopsis>
00203          Dial over DAHDI channel while offhook.
00204       </synopsis>
00205       <syntax>
00206          <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
00207          <parameter name="DAHDIChannel" required="true">
00208             <para>DAHDI channel number to dial digits.</para>
00209          </parameter>
00210          <parameter name="Number" required="true">
00211             <para>Digits to dial.</para>
00212          </parameter>
00213       </syntax>
00214       <description>
00215          <para>Generate DTMF control frames to the bridged peer.</para>
00216       </description>
00217    </manager>
00218    <manager name="DAHDIDNDon" language="en_US">
00219       <synopsis>
00220          Toggle DAHDI channel Do Not Disturb status ON.
00221       </synopsis>
00222       <syntax>
00223          <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
00224          <parameter name="DAHDIChannel" required="true">
00225             <para>DAHDI channel number to set DND on.</para>
00226          </parameter>
00227       </syntax>
00228       <description>
00229          <para>Equivalent to the CLI command "dahdi set dnd <variable>channel</variable> on".</para>
00230          <note><para>Feature only supported by analog channels.</para></note>
00231       </description>
00232    </manager>
00233    <manager name="DAHDIDNDoff" language="en_US">
00234       <synopsis>
00235          Toggle DAHDI channel Do Not Disturb status OFF.
00236       </synopsis>
00237       <syntax>
00238          <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
00239          <parameter name="DAHDIChannel" required="true">
00240             <para>DAHDI channel number to set DND off.</para>
00241          </parameter>
00242       </syntax>
00243       <description>
00244          <para>Equivalent to the CLI command "dahdi set dnd <variable>channel</variable> off".</para>
00245          <note><para>Feature only supported by analog channels.</para></note>
00246       </description>
00247    </manager>
00248    <manager name="DAHDIShowChannels" language="en_US">
00249       <synopsis>
00250          Show status of DAHDI channels.
00251       </synopsis>
00252       <syntax>
00253          <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
00254          <parameter name="DAHDIChannel">
00255             <para>Specify the specific channel number to show.  Show all channels if zero or not present.</para>
00256          </parameter>
00257       </syntax>
00258       <description>
00259          <para>Similar to the CLI command "dahdi show channels".</para>
00260       </description>
00261    </manager>
00262    <manager name="DAHDIRestart" language="en_US">
00263       <synopsis>
00264          Fully Restart DAHDI channels (terminates calls).
00265       </synopsis>
00266       <syntax>
00267          <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
00268       </syntax>
00269       <description>
00270          <para>Equivalent to the CLI command "dahdi restart".</para>
00271       </description>
00272    </manager>
00273  ***/
00274 
00275 #define SMDI_MD_WAIT_TIMEOUT 1500 /* 1.5 seconds */
00276 
00277 static const char * const lbostr[] = {
00278 "0 db (CSU)/0-133 feet (DSX-1)",
00279 "133-266 feet (DSX-1)",
00280 "266-399 feet (DSX-1)",
00281 "399-533 feet (DSX-1)",
00282 "533-655 feet (DSX-1)",
00283 "-7.5db (CSU)",
00284 "-15db (CSU)",
00285 "-22.5db (CSU)"
00286 };
00287 
00288 /*! Global jitterbuffer configuration - by default, jb is disabled
00289  *  \note Values shown here match the defaults shown in chan_dahdi.conf.sample */
00290 static struct ast_jb_conf default_jbconf =
00291 {
00292    .flags = 0,
00293    .max_size = 200,
00294    .resync_threshold = 1000,
00295    .impl = "fixed",
00296    .target_extra = 40,
00297 };
00298 static struct ast_jb_conf global_jbconf;
00299 
00300 /*!
00301  * \note Define ZHONE_HACK to cause us to go off hook and then back on hook when
00302  * the user hangs up to reset the state machine so ring works properly.
00303  * This is used to be able to support kewlstart by putting the zhone in
00304  * groundstart mode since their forward disconnect supervision is entirely
00305  * broken even though their documentation says it isn't and their support
00306  * is entirely unwilling to provide any assistance with their channel banks
00307  * even though their web site says they support their products for life.
00308  */
00309 /* #define ZHONE_HACK */
00310 
00311 /*! \brief Typically, how many rings before we should send Caller*ID */
00312 #define DEFAULT_CIDRINGS 1
00313 
00314 #define AST_LAW(p) (((p)->law == DAHDI_LAW_ALAW) ? AST_FORMAT_ALAW : AST_FORMAT_ULAW)
00315 
00316 
00317 /*! \brief Signaling types that need to use MF detection should be placed in this macro */
00318 #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))
00319 
00320 static const char tdesc[] = "DAHDI Telephony Driver"
00321 #if defined(HAVE_PRI) || defined(HAVE_SS7) || defined(HAVE_OPENR2)
00322    " w/"
00323    #if defined(HAVE_PRI)
00324       "PRI"
00325    #endif   /* defined(HAVE_PRI) */
00326    #if defined(HAVE_SS7)
00327       #if defined(HAVE_PRI)
00328       " & "
00329       #endif   /* defined(HAVE_PRI) */
00330       "SS7"
00331    #endif   /* defined(HAVE_SS7) */
00332    #if defined(HAVE_OPENR2)
00333       #if defined(HAVE_PRI) || defined(HAVE_SS7)
00334       " & "
00335       #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
00336       "MFC/R2"
00337    #endif   /* defined(HAVE_OPENR2) */
00338 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) || defined(HAVE_OPENR2) */
00339 ;
00340 
00341 static const char config[] = "chan_dahdi.conf";
00342 
00343 #define SIG_EM    DAHDI_SIG_EM
00344 #define SIG_EMWINK   (0x0100000 | DAHDI_SIG_EM)
00345 #define SIG_FEATD (0x0200000 | DAHDI_SIG_EM)
00346 #define  SIG_FEATDMF (0x0400000 | DAHDI_SIG_EM)
00347 #define  SIG_FEATB   (0x0800000 | DAHDI_SIG_EM)
00348 #define  SIG_E911 (0x1000000 | DAHDI_SIG_EM)
00349 #define  SIG_FEATDMF_TA (0x2000000 | DAHDI_SIG_EM)
00350 #define  SIG_FGC_CAMA   (0x4000000 | DAHDI_SIG_EM)
00351 #define  SIG_FGC_CAMAMF (0x8000000 | DAHDI_SIG_EM)
00352 #define SIG_FXSLS DAHDI_SIG_FXSLS
00353 #define SIG_FXSGS DAHDI_SIG_FXSGS
00354 #define SIG_FXSKS DAHDI_SIG_FXSKS
00355 #define SIG_FXOLS DAHDI_SIG_FXOLS
00356 #define SIG_FXOGS DAHDI_SIG_FXOGS
00357 #define SIG_FXOKS DAHDI_SIG_FXOKS
00358 #define SIG_PRI      DAHDI_SIG_CLEAR
00359 #define SIG_BRI      (0x2000000 | DAHDI_SIG_CLEAR)
00360 #define SIG_BRI_PTMP (0X4000000 | DAHDI_SIG_CLEAR)
00361 #define SIG_SS7      (0x1000000 | DAHDI_SIG_CLEAR)
00362 #define SIG_MFCR2    DAHDI_SIG_CAS
00363 #define  SIG_SF      DAHDI_SIG_SF
00364 #define SIG_SFWINK   (0x0100000 | DAHDI_SIG_SF)
00365 #define SIG_SF_FEATD (0x0200000 | DAHDI_SIG_SF)
00366 #define  SIG_SF_FEATDMF (0x0400000 | DAHDI_SIG_SF)
00367 #define  SIG_SF_FEATB   (0x0800000 | DAHDI_SIG_SF)
00368 #define SIG_EM_E1 DAHDI_SIG_EM_E1
00369 
00370 #ifdef LOTS_OF_SPANS
00371 #define NUM_SPANS DAHDI_MAX_SPANS
00372 #else
00373 #define NUM_SPANS       32
00374 #endif
00375 
00376 #define CHAN_PSEUDO  -2
00377 
00378 #define CALLPROGRESS_PROGRESS    1
00379 #define CALLPROGRESS_FAX_OUTGOING   2
00380 #define CALLPROGRESS_FAX_INCOMING   4
00381 #define CALLPROGRESS_FAX      (CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING)
00382 
00383 #define NUM_CADENCE_MAX 25
00384 static int num_cadence = 4;
00385 static int user_has_defined_cadences = 0;
00386 
00387 static struct dahdi_ring_cadence cadences[NUM_CADENCE_MAX] = {
00388    { { 125, 125, 2000, 4000 } },       /*!< Quick chirp followed by normal ring */
00389    { { 250, 250, 500, 1000, 250, 250, 500, 4000 } }, /*!< British style ring */
00390    { { 125, 125, 125, 125, 125, 4000 } }, /*!< Three short bursts */
00391    { { 1000, 500, 2500, 5000 } },   /*!< Long ring */
00392 };
00393 
00394 /*! \brief cidrings says in which pause to transmit the cid information, where the first pause
00395  * is 1, the second pause is 2 and so on.
00396  */
00397 
00398 static int cidrings[NUM_CADENCE_MAX] = {
00399    2,                            /*!< Right after first long ring */
00400    4,                            /*!< Right after long part */
00401    3,                            /*!< After third chirp */
00402    2,                            /*!< Second spell */
00403 };
00404 
00405 /* ETSI EN300 659-1 specifies the ring pulse between 200 and 300 mS */
00406 static struct dahdi_ring_cadence AS_RP_cadence = {{250, 10000}};
00407 
00408 #define ISTRUNK(p) ((p->sig == SIG_FXSLS) || (p->sig == SIG_FXSKS) || \
00409          (p->sig == SIG_FXSGS) || (p->sig == SIG_PRI))
00410 
00411 #define CANBUSYDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */)
00412 #define CANPROGRESSDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */)
00413 
00414 static char defaultcic[64] = "";
00415 static char defaultozz[64] = "";
00416 
00417 /*! Run this script when the MWI state changes on an FXO line, if mwimonitor is enabled */
00418 static char mwimonitornotify[PATH_MAX] = "";
00419 #ifndef HAVE_DAHDI_LINEREVERSE_VMWI
00420 static int  mwisend_rpas = 0;
00421 #endif
00422 
00423 static char progzone[10] = "";
00424 
00425 static int usedistinctiveringdetection = 0;
00426 static int distinctiveringaftercid = 0;
00427 
00428 static int numbufs = 4;
00429 
00430 static int mwilevel = 512;
00431 static int dtmfcid_level = 256;
00432 
00433 #define REPORT_CHANNEL_ALARMS 1
00434 #define REPORT_SPAN_ALARMS    2 
00435 static int report_alarms = REPORT_CHANNEL_ALARMS;
00436 
00437 #ifdef HAVE_PRI
00438 static int pridebugfd = -1;
00439 static char pridebugfilename[1024] = "";
00440 #endif
00441 
00442 /*! \brief Wait up to 16 seconds for first digit (FXO logic) */
00443 static int firstdigittimeout = 16000;
00444 
00445 /*! \brief How long to wait for following digits (FXO logic) */
00446 static int gendigittimeout = 8000;
00447 
00448 /*! \brief How long to wait for an extra digit, if there is an ambiguous match */
00449 static int matchdigittimeout = 3000;
00450 
00451 /*! \brief Protect the interface list (of dahdi_pvt's) */
00452 AST_MUTEX_DEFINE_STATIC(iflock);
00453 
00454 
00455 static int ifcount = 0;
00456 
00457 #ifdef HAVE_PRI
00458 AST_MUTEX_DEFINE_STATIC(pridebugfdlock);
00459 #endif
00460 
00461 /*! \brief Protect the monitoring thread, so only one process can kill or start it, and not
00462    when it's doing something critical. */
00463 AST_MUTEX_DEFINE_STATIC(monlock);
00464 
00465 /*! \brief This is the thread for the monitor which checks for input on the channels
00466    which are not currently in use. */
00467 static pthread_t monitor_thread = AST_PTHREADT_NULL;
00468 static ast_cond_t ss_thread_complete;
00469 AST_MUTEX_DEFINE_STATIC(ss_thread_lock);
00470 AST_MUTEX_DEFINE_STATIC(restart_lock);
00471 static int ss_thread_count = 0;
00472 static int num_restart_pending = 0;
00473 
00474 static int restart_monitor(void);
00475 
00476 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);
00477 
00478 static int dahdi_sendtext(struct ast_channel *c, const char *text);
00479 
00480 static void mwi_event_cb(const struct ast_event *event, void *userdata)
00481 {
00482    /* This module does not handle MWI in an event-based manner.  However, it
00483     * subscribes to MWI for each mailbox that is configured so that the core
00484     * knows that we care about it.  Then, chan_dahdi will get the MWI from the
00485     * event cache instead of checking the mailbox directly. */
00486 }
00487 
00488 /*! \brief Avoid the silly dahdi_getevent which ignores a bunch of events */
00489 static inline int dahdi_get_event(int fd)
00490 {
00491    int j;
00492    if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
00493       return -1;
00494    return j;
00495 }
00496 
00497 /*! \brief Avoid the silly dahdi_waitevent which ignores a bunch of events */
00498 static inline int dahdi_wait_event(int fd)
00499 {
00500    int i, j = 0;
00501    i = DAHDI_IOMUX_SIGEVENT;
00502    if (ioctl(fd, DAHDI_IOMUX, &i) == -1)
00503       return -1;
00504    if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
00505       return -1;
00506    return j;
00507 }
00508 
00509 /*! Chunk size to read -- we use 20ms chunks to make things happy. */
00510 #define READ_SIZE 160
00511 
00512 #define MASK_AVAIL      (1 << 0) /*!< Channel available for PRI use */
00513 #define MASK_INUSE      (1 << 1) /*!< Channel currently in use */
00514 
00515 #define CALLWAITING_SILENT_SAMPLES     ((300 * 8) / READ_SIZE) /*!< 300 ms */
00516 #define CALLWAITING_REPEAT_SAMPLES     ((10000 * 8) / READ_SIZE) /*!< 10,000 ms */
00517 #define CALLWAITING_SUPPRESS_SAMPLES   ((100 * 8) / READ_SIZE) /*!< 100 ms */
00518 #define CIDCW_EXPIRE_SAMPLES        ((500 * 8) / READ_SIZE) /*!< 500 ms */
00519 #define MIN_MS_SINCE_FLASH          ((2000) )   /*!< 2000 ms */
00520 #define DEFAULT_RINGT               ((8000 * 8) / READ_SIZE) /*!< 8,000 ms */
00521 
00522 struct dahdi_pvt;
00523 
00524 /*!
00525  * \brief Configured ring timeout base.
00526  * \note Value computed from "ringtimeout" read in from chan_dahdi.conf if it exists.
00527  */
00528 static int ringt_base = DEFAULT_RINGT;
00529 
00530 #if defined(HAVE_SS7)
00531 
00532 struct dahdi_ss7 {
00533    struct sig_ss7_linkset ss7;
00534 };
00535 
00536 static struct dahdi_ss7 linksets[NUM_SPANS];
00537 
00538 static int cur_ss7type = -1;
00539 static int cur_linkset = -1;
00540 static int cur_pointcode = -1;
00541 static int cur_cicbeginswith = -1;
00542 static int cur_adjpointcode = -1;
00543 static int cur_networkindicator = -1;
00544 static int cur_defaultdpc = -1;
00545 #endif   /* defined(HAVE_SS7) */
00546 
00547 #ifdef HAVE_OPENR2
00548 struct dahdi_mfcr2 {
00549    pthread_t r2master;            /*!< Thread of master */
00550    openr2_context_t *protocol_context;    /*!< OpenR2 context handle */
00551    struct dahdi_pvt *pvts[SIG_MFCR2_MAX_CHANNELS];     /*!< Member channel pvt structs */
00552    int numchans;                          /*!< Number of channels in this R2 block */
00553    int monitored_count;                   /*!< Number of channels being monitored */
00554 };
00555 
00556 struct dahdi_mfcr2_conf {
00557    openr2_variant_t variant;
00558    int mfback_timeout;
00559    int metering_pulse_timeout;
00560    int max_ani;
00561    int max_dnis;
00562    signed int get_ani_first:2;
00563 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
00564    signed int skip_category_request:2;
00565 #endif
00566    unsigned int call_files:1;
00567    unsigned int allow_collect_calls:1;
00568    unsigned int charge_calls:1;
00569    unsigned int accept_on_offer:1;
00570    unsigned int forced_release:1;
00571    unsigned int double_answer:1;
00572    signed int immediate_accept:2;
00573    char logdir[OR2_MAX_PATH];
00574    char r2proto_file[OR2_MAX_PATH];
00575    openr2_log_level_t loglevel;
00576    openr2_calling_party_category_t category;
00577 };
00578 
00579 /* malloc'd array of malloc'd r2links */
00580 static struct dahdi_mfcr2 **r2links;
00581 /* how many r2links have been malloc'd */
00582 static int r2links_count = 0;
00583 
00584 #endif /* HAVE_OPENR2 */
00585 
00586 #ifdef HAVE_PRI
00587 
00588 struct dahdi_pri {
00589    int dchannels[SIG_PRI_NUM_DCHANS];     /*!< What channel are the dchannels on */
00590    int mastertrunkgroup;               /*!< What trunk group is our master */
00591    int prilogicalspan;                 /*!< Logical span number within trunk group */
00592    struct sig_pri_span pri;
00593 };
00594 
00595 static struct dahdi_pri pris[NUM_SPANS];
00596 
00597 #if defined(HAVE_PRI_CCSS)
00598 /*! DAHDI PRI CCSS agent and monitor type name. */
00599 static const char dahdi_pri_cc_type[] = "DAHDI/PRI";
00600 #endif   /* defined(HAVE_PRI_CCSS) */
00601 
00602 #else
00603 /*! Shut up the compiler */
00604 struct dahdi_pri;
00605 #endif
00606 
00607 #define SUB_REAL  0        /*!< Active call */
00608 #define SUB_CALLWAIT 1        /*!< Call-Waiting call on hold */
00609 #define SUB_THREEWAY 2        /*!< Three-way call */
00610 
00611 /* Polarity states */
00612 #define POLARITY_IDLE   0
00613 #define POLARITY_REV    1
00614 
00615 
00616 struct distRingData {
00617    int ring[3];
00618    int range;
00619 };
00620 struct ringContextData {
00621    char contextData[AST_MAX_CONTEXT];
00622 };
00623 struct dahdi_distRings {
00624    struct distRingData ringnum[3];
00625    struct ringContextData ringContext[3];
00626 };
00627 
00628 static const char * const subnames[] = {
00629    "Real",
00630    "Callwait",
00631    "Threeway"
00632 };
00633 
00634 struct dahdi_subchannel {
00635    int dfd;
00636    struct ast_channel *owner;
00637    int chan;
00638    short buffer[AST_FRIENDLY_OFFSET/2 + READ_SIZE];
00639    struct ast_frame f;     /*!< One frame for each channel.  How did this ever work before? */
00640    unsigned int needringing:1;
00641    unsigned int needbusy:1;
00642    unsigned int needcongestion:1;
00643    unsigned int needanswer:1;
00644    unsigned int needflash:1;
00645    unsigned int needhold:1;
00646    unsigned int needunhold:1;
00647    unsigned int linear:1;
00648    unsigned int inthreeway:1;
00649    struct dahdi_confinfo curconf;
00650 };
00651 
00652 #define CONF_USER_REAL     (1 << 0)
00653 #define CONF_USER_THIRDCALL   (1 << 1)
00654 
00655 #define MAX_SLAVES   4
00656 
00657 /* States for sending MWI message
00658  * First three states are required for send Ring Pulse Alert Signal
00659  */
00660 typedef enum {
00661    MWI_SEND_NULL = 0,
00662    MWI_SEND_SA,
00663    MWI_SEND_SA_WAIT,
00664    MWI_SEND_PAUSE,
00665    MWI_SEND_SPILL,
00666    MWI_SEND_CLEANUP,
00667    MWI_SEND_DONE,
00668 } mwisend_states;
00669 
00670 struct mwisend_info {
00671    struct   timeval  pause;
00672    mwisend_states    mwisend_current;
00673 };
00674 
00675 /*! Specify the lists dahdi_pvt can be put in. */
00676 enum DAHDI_IFLIST {
00677    DAHDI_IFLIST_NONE,   /*!< The dahdi_pvt is not in any list. */
00678    DAHDI_IFLIST_MAIN,   /*!< The dahdi_pvt is in the main interface list */
00679 #if defined(HAVE_PRI)
00680    DAHDI_IFLIST_NO_B_CHAN, /*!< The dahdi_pvt is in a no B channel interface list */
00681 #endif   /* defined(HAVE_PRI) */
00682 };
00683 
00684 struct dahdi_pvt {
00685    ast_mutex_t lock;             /*!< Channel private lock. */
00686    struct callerid_state *cs;
00687    struct ast_channel *owner;       /*!< Our current active owner (if applicable) */
00688                      /*!< Up to three channels can be associated with this call */
00689 
00690    struct dahdi_subchannel sub_unused;    /*!< Just a safety precaution */
00691    struct dahdi_subchannel subs[3];       /*!< Sub-channels */
00692    struct dahdi_confinfo saveconf;        /*!< Saved conference info */
00693 
00694    struct dahdi_pvt *slaves[MAX_SLAVES];     /*!< Slave to us (follows our conferencing) */
00695    struct dahdi_pvt *master;           /*!< Master to us (we follow their conferencing) */
00696    int inconference;          /*!< If our real should be in the conference */
00697 
00698    int bufsize;                /*!< Size of the buffers */
00699    int buf_no;             /*!< Number of buffers */
00700    int buf_policy;            /*!< Buffer policy */
00701    int faxbuf_no;              /*!< Number of Fax buffers */
00702    int faxbuf_policy;          /*!< Fax buffer policy */
00703    int sig;             /*!< Signalling style */
00704    /*!
00705     * \brief Nonzero if the signaling type is sent over a radio.
00706     * \note Set to a couple of nonzero values but it is only tested like a boolean.
00707     */
00708    int radio;
00709    int outsigmod;             /*!< Outbound Signalling style (modifier) */
00710    int oprmode;               /*!< "Operator Services" mode */
00711    struct dahdi_pvt *oprpeer;          /*!< "Operator Services" peer tech_pvt ptr */
00712    /*! \brief Amount of gain to increase during caller id */
00713    float cid_rxgain;
00714    /*! \brief Rx gain set by chan_dahdi.conf */
00715    float rxgain;
00716    /*! \brief Tx gain set by chan_dahdi.conf */
00717    float txgain;
00718 
00719    float txdrc; /*!< Dynamic Range Compression factor. a number between 1 and 6ish */
00720    float rxdrc;
00721    
00722    int tonezone;              /*!< tone zone for this chan, or -1 for default */
00723    enum DAHDI_IFLIST which_iflist;  /*!< Which interface list is this structure listed? */
00724    struct dahdi_pvt *next;          /*!< Next channel in list */
00725    struct dahdi_pvt *prev;          /*!< Prev channel in list */
00726 
00727    /* flags */
00728 
00729    /*!
00730     * \brief TRUE if ADSI (Analog Display Services Interface) available
00731     * \note Set from the "adsi" value read in from chan_dahdi.conf
00732     */
00733    unsigned int adsi:1;
00734    /*!
00735     * \brief TRUE if we can use a polarity reversal to mark when an outgoing
00736     * call is answered by the remote party.
00737     * \note Set from the "answeronpolarityswitch" value read in from chan_dahdi.conf
00738     */
00739    unsigned int answeronpolarityswitch:1;
00740    /*!
00741     * \brief TRUE if busy detection is enabled.
00742     * (Listens for the beep-beep busy pattern.)
00743     * \note Set from the "busydetect" value read in from chan_dahdi.conf
00744     */
00745    unsigned int busydetect:1;
00746    /*!
00747     * \brief TRUE if call return is enabled.
00748     * (*69, if your dialplan doesn't catch this first)
00749     * \note Set from the "callreturn" value read in from chan_dahdi.conf
00750     */
00751    unsigned int callreturn:1;
00752    /*!
00753     * \brief TRUE if busy extensions will hear the call-waiting tone
00754     * and can use hook-flash to switch between callers.
00755     * \note Can be disabled by dialing *70.
00756     * \note Initialized with the "callwaiting" value read in from chan_dahdi.conf
00757     */
00758    unsigned int callwaiting:1;
00759    /*!
00760     * \brief TRUE if send caller ID for Call Waiting
00761     * \note Set from the "callwaitingcallerid" value read in from chan_dahdi.conf
00762     */
00763    unsigned int callwaitingcallerid:1;
00764    /*!
00765     * \brief TRUE if support for call forwarding enabled.
00766     * Dial *72 to enable call forwarding.
00767     * Dial *73 to disable call forwarding.
00768     * \note Set from the "cancallforward" value read in from chan_dahdi.conf
00769     */
00770    unsigned int cancallforward:1;
00771    /*!
00772     * \brief TRUE if support for call parking is enabled.
00773     * \note Set from the "canpark" value read in from chan_dahdi.conf
00774     */
00775    unsigned int canpark:1;
00776    /*! \brief TRUE if to wait for a DTMF digit to confirm answer */
00777    unsigned int confirmanswer:1;
00778    /*!
00779     * \brief TRUE if the channel is to be destroyed on hangup.
00780     * (Used by pseudo channels.)
00781     */
00782    unsigned int destroy:1;
00783    unsigned int didtdd:1;           /*!< flag to say its done it once */
00784    /*! \brief TRUE if analog type line dialed no digits in Dial() */
00785    unsigned int dialednone:1;
00786    /*!
00787     * \brief TRUE if in the process of dialing digits or sending something.
00788     * \note This is used as a receive squelch for ISDN until connected.
00789     */
00790    unsigned int dialing:1;
00791    /*! \brief TRUE if the transfer capability of the call is digital. */
00792    unsigned int digital:1;
00793    /*! \brief TRUE if Do-Not-Disturb is enabled, present only for non sig_analog */
00794    unsigned int dnd:1;
00795    /*! \brief XXX BOOLEAN Purpose??? */
00796    unsigned int echobreak:1;
00797    /*!
00798     * \brief TRUE if echo cancellation enabled when bridged.
00799     * \note Initialized with the "echocancelwhenbridged" value read in from chan_dahdi.conf
00800     * \note Disabled if the echo canceller is not setup.
00801     */
00802    unsigned int echocanbridged:1;
00803    /*! \brief TRUE if echo cancellation is turned on. */
00804    unsigned int echocanon:1;
00805    /*! \brief TRUE if a fax tone has already been handled. */
00806    unsigned int faxhandled:1;
00807    /*! TRUE if dynamic faxbuffers are configured for use, default is OFF */
00808    unsigned int usefaxbuffers:1;
00809    /*! TRUE while buffer configuration override is in use */
00810    unsigned int bufferoverrideinuse:1;
00811    /*! \brief TRUE if over a radio and dahdi_read() has been called. */
00812    unsigned int firstradio:1;
00813    /*!
00814     * \brief TRUE if the call will be considered "hung up" on a polarity reversal.
00815     * \note Set from the "hanguponpolarityswitch" value read in from chan_dahdi.conf
00816     */
00817    unsigned int hanguponpolarityswitch:1;
00818    /*! \brief TRUE if DTMF detection needs to be done by hardware. */
00819    unsigned int hardwaredtmf:1;
00820    /*!
00821     * \brief TRUE if the outgoing caller ID is blocked/hidden.
00822     * \note Caller ID can be disabled by dialing *67.
00823     * \note Caller ID can be enabled by dialing *82.
00824     * \note Initialized with the "hidecallerid" value read in from chan_dahdi.conf
00825     */
00826    unsigned int hidecallerid:1;
00827    /*!
00828     * \brief TRUE if hide just the name not the number for legacy PBX use.
00829     * \note Only applies to PRI channels.
00830     * \note Set from the "hidecalleridname" value read in from chan_dahdi.conf
00831     */
00832    unsigned int hidecalleridname:1;
00833    /*! \brief TRUE if DTMF detection is disabled. */
00834    unsigned int ignoredtmf:1;
00835    /*!
00836     * \brief TRUE if the channel should be answered immediately
00837     * without attempting to gather any digits.
00838     * \note Set from the "immediate" value read in from chan_dahdi.conf
00839     */
00840    unsigned int immediate:1;
00841    /*! \brief TRUE if in an alarm condition. */
00842    unsigned int inalarm:1;
00843    /*! \brief TRUE if TDD in MATE mode */
00844    unsigned int mate:1;
00845    /*! \brief TRUE if we originated the call leg. */
00846    unsigned int outgoing:1;
00847    /* unsigned int overlapdial:1;         unused and potentially confusing */
00848    /*!
00849     * \brief TRUE if busy extensions will hear the call-waiting tone
00850     * and can use hook-flash to switch between callers.
00851     * \note Set from the "callwaiting" value read in from chan_dahdi.conf
00852     */
00853    unsigned int permcallwaiting:1;
00854    /*!
00855     * \brief TRUE if the outgoing caller ID is blocked/restricted/hidden.
00856     * \note Set from the "hidecallerid" value read in from chan_dahdi.conf
00857     */
00858    unsigned int permhidecallerid:1;
00859    /*!
00860     * \brief TRUE if PRI congestion/busy indications are sent out-of-band.
00861     * \note Set from the "priindication" value read in from chan_dahdi.conf
00862     */
00863    unsigned int priindication_oob:1;
00864    /*!
00865     * \brief TRUE if PRI B channels are always exclusively selected.
00866     * \note Set from the "priexclusive" value read in from chan_dahdi.conf
00867     */
00868    unsigned int priexclusive:1;
00869    /*!
00870     * \brief TRUE if we will pulse dial.
00871     * \note Set from the "pulsedial" value read in from chan_dahdi.conf
00872     */
00873    unsigned int pulse:1;
00874    /*! \brief TRUE if a pulsed digit was detected. (Pulse dial phone detected) */
00875    unsigned int pulsedial:1;
00876    unsigned int restartpending:1;      /*!< flag to ensure counted only once for restart */
00877    /*!
00878     * \brief TRUE if caller ID is restricted.
00879     * \note Set but not used.  Should be deleted.  Redundant with permhidecallerid.
00880     * \note Set from the "restrictcid" value read in from chan_dahdi.conf
00881     */
00882    unsigned int restrictcid:1;
00883    /*!
00884     * \brief TRUE if three way calling is enabled
00885     * \note Set from the "threewaycalling" value read in from chan_dahdi.conf
00886     */
00887    unsigned int threewaycalling:1;
00888    /*!
00889     * \brief TRUE if call transfer is enabled
00890     * \note For FXS ports (either direct analog or over T1/E1):
00891     *   Support flash-hook call transfer
00892     * \note For digital ports using ISDN PRI protocols:
00893     *   Support switch-side transfer (called 2BCT, RLT or other names)
00894     * \note Set from the "transfer" value read in from chan_dahdi.conf
00895     */
00896    unsigned int transfer:1;
00897    /*!
00898     * \brief TRUE if caller ID is used on this channel.
00899     * \note PRI and SS7 spans will save caller ID from the networking peer.
00900     * \note FXS ports will generate the caller ID spill.
00901     * \note FXO ports will listen for the caller ID spill.
00902     * \note Set from the "usecallerid" value read in from chan_dahdi.conf
00903     */
00904    unsigned int use_callerid:1;
00905    /*!
00906     * \brief TRUE if we will use the calling presentation setting
00907     * from the Asterisk channel for outgoing calls.
00908     * \note Only applies to PRI and SS7 channels.
00909     * \note Set from the "usecallingpres" value read in from chan_dahdi.conf
00910     */
00911    unsigned int use_callingpres:1;
00912    /*!
00913     * \brief TRUE if distinctive rings are to be detected.
00914     * \note For FXO lines
00915     * \note Set indirectly from the "usedistinctiveringdetection" value read in from chan_dahdi.conf
00916     */
00917    unsigned int usedistinctiveringdetection:1;
00918    /*!
00919     * \brief TRUE if we should use the callerid from incoming call on dahdi transfer.
00920     * \note Set from the "useincomingcalleridondahditransfer" value read in from chan_dahdi.conf
00921     */
00922    unsigned int dahditrcallerid:1;
00923    /*!
00924     * \brief TRUE if allowed to flash-transfer to busy channels.
00925     * \note Set from the "transfertobusy" value read in from chan_dahdi.conf
00926     */
00927    unsigned int transfertobusy:1;
00928    /*!
00929     * \brief TRUE if the FXO port monitors for neon type MWI indications from the other end.
00930     * \note Set if the "mwimonitor" value read in contains "neon" from chan_dahdi.conf
00931     */
00932    unsigned int mwimonitor_neon:1;
00933    /*!
00934     * \brief TRUE if the FXO port monitors for fsk type MWI indications from the other end.
00935     * \note Set if the "mwimonitor" value read in contains "fsk" from chan_dahdi.conf
00936     */
00937    unsigned int mwimonitor_fsk:1;
00938    /*!
00939     * \brief TRUE if the FXO port monitors for rpas precursor to fsk MWI indications from the other end.
00940     * \note RPAS - Ring Pulse Alert Signal
00941     * \note Set if the "mwimonitor" value read in contains "rpas" from chan_dahdi.conf
00942     */
00943    unsigned int mwimonitor_rpas:1;
00944    /*! \brief TRUE if an MWI monitor thread is currently active */
00945    unsigned int mwimonitoractive:1;
00946    /*! \brief TRUE if a MWI message sending thread is active */
00947    unsigned int mwisendactive:1;
00948    /*!
00949     * \brief TRUE if channel is out of reset and ready
00950     * \note Set but not used.
00951     */
00952    unsigned int inservice:1;
00953    /*!
00954     * \brief TRUE if the channel is locally blocked.
00955     * \note Applies to SS7 and MFCR2 channels.
00956     */
00957    unsigned int locallyblocked:1;
00958    /*!
00959     * \brief TRUE if the channel is remotely blocked.
00960     * \note Applies to SS7 and MFCR2 channels.
00961     */
00962    unsigned int remotelyblocked:1;
00963    /*!
00964     * \brief TRUE if the channel alarms will be managed also as Span ones
00965     * \note Applies to all channels
00966     */
00967    unsigned int manages_span_alarms:1;
00968 
00969 #if defined(HAVE_PRI)
00970    struct sig_pri_span *pri;
00971    int logicalspan;
00972 #endif
00973    /*!
00974     * \brief TRUE if SMDI (Simplified Message Desk Interface) is enabled
00975     * \note Set from the "usesmdi" value read in from chan_dahdi.conf
00976     */
00977    unsigned int use_smdi:1;
00978    struct mwisend_info mwisend_data;
00979    /*! \brief The SMDI interface to get SMDI messages from. */
00980    struct ast_smdi_interface *smdi_iface;
00981 
00982    /*! \brief Distinctive Ring data */
00983    struct dahdi_distRings drings;
00984 
00985    /*!
00986     * \brief The configured context for incoming calls.
00987     * \note The "context" string read in from chan_dahdi.conf
00988     */
00989    char context[AST_MAX_CONTEXT];
00990    /*!
00991     * \brief Saved context string.
00992     */
00993    char defcontext[AST_MAX_CONTEXT];
00994    /*! \brief Extension to use in the dialplan. */
00995    char exten[AST_MAX_EXTENSION];
00996    /*!
00997     * \brief Language configured for calls.
00998     * \note The "language" string read in from chan_dahdi.conf
00999     */
01000    char language[MAX_LANGUAGE];
01001    /*!
01002     * \brief The configured music-on-hold class to use for calls.
01003     * \note The "musicclass" or "mohinterpret" or "musiconhold" string read in from chan_dahdi.conf
01004     */
01005    char mohinterpret[MAX_MUSICCLASS];
01006    /*!
01007     * \brief Suggested music-on-hold class for peer channel to use for calls.
01008     * \note The "mohsuggest" string read in from chan_dahdi.conf
01009     */
01010    char mohsuggest[MAX_MUSICCLASS];
01011    char parkinglot[AST_MAX_EXTENSION]; /*!< Parking lot for this channel */
01012 #if defined(HAVE_PRI) || defined(HAVE_SS7)
01013    /*! \brief Automatic Number Identification number (Alternate PRI caller ID number) */
01014    char cid_ani[AST_MAX_EXTENSION];
01015 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
01016    /*! \brief Automatic Number Identification code from PRI */
01017    int cid_ani2;
01018    /*! \brief Caller ID number from an incoming call. */
01019    char cid_num[AST_MAX_EXTENSION];
01020    /*!
01021     * \brief Caller ID tag from incoming call
01022     * \note the "cid_tag" string read in from chan_dahdi.conf
01023     */
01024    char cid_tag[AST_MAX_EXTENSION];
01025    /*! \brief Caller ID Q.931 TON/NPI field values.  Set by PRI. Zero otherwise. */
01026    int cid_ton;
01027    /*! \brief Caller ID name from an incoming call. */
01028    char cid_name[AST_MAX_EXTENSION];
01029    /*! \brief Caller ID subaddress from an incoming call. */
01030    char cid_subaddr[AST_MAX_EXTENSION];
01031    char *origcid_num;            /*!< malloced original callerid */
01032    char *origcid_name;           /*!< malloced original callerid */
01033    /*! \brief Call waiting number. */
01034    char callwait_num[AST_MAX_EXTENSION];
01035    /*! \brief Call waiting name. */
01036    char callwait_name[AST_MAX_EXTENSION];
01037    /*! \brief Redirecting Directory Number Information Service (RDNIS) number */
01038    char rdnis[AST_MAX_EXTENSION];
01039    /*! \brief Dialed Number Identifier */
01040    char dnid[AST_MAX_EXTENSION];
01041    /*!
01042     * \brief Bitmapped groups this belongs to.
01043     * \note The "group" bitmapped group string read in from chan_dahdi.conf
01044     */
01045    ast_group_t group;
01046    /*! \brief Default call PCM encoding format: DAHDI_LAW_ALAW or DAHDI_LAW_MULAW. */
01047    int law_default;
01048    /*! \brief Active PCM encoding format: DAHDI_LAW_ALAW or DAHDI_LAW_MULAW */
01049    int law;
01050    int confno;             /*!< Our conference */
01051    int confusers;             /*!< Who is using our conference */
01052    int propconfno;               /*!< Propagated conference number */
01053    /*!
01054     * \brief Bitmapped call groups this belongs to.
01055     * \note The "callgroup" bitmapped group string read in from chan_dahdi.conf
01056     */
01057    ast_group_t callgroup;
01058    /*!
01059     * \brief Bitmapped pickup groups this belongs to.
01060     * \note The "pickupgroup" bitmapped group string read in from chan_dahdi.conf
01061     */
01062    ast_group_t pickupgroup;
01063    /*!
01064     * \brief Channel variable list with associated values to set when a channel is created.
01065     * \note The "setvar" strings read in from chan_dahdi.conf
01066     */
01067    struct ast_variable *vars;
01068    int channel;               /*!< Channel Number */
01069    int span;               /*!< Span number */
01070    time_t guardtime;          /*!< Must wait this much time before using for new call */
01071    int cid_signalling;           /*!< CID signalling type bell202 or v23 */
01072    int cid_start;             /*!< CID start indicator, polarity or ring or DTMF without warning event */
01073    int dtmfcid_holdoff_state;    /*!< State indicator that allows for line to settle before checking for dtmf energy */
01074    struct timeval dtmfcid_delay;  /*!< Time value used for allow line to settle */
01075    int callingpres;           /*!< The value of calling presentation that we're going to use when placing a PRI call */
01076    int callwaitingrepeat;           /*!< How many samples to wait before repeating call waiting */
01077    int cidcwexpire;           /*!< When to stop waiting for CID/CW CAS response (In samples) */
01078    int cid_suppress_expire;      /*!< How many samples to suppress after a CID spill. */
01079    /*! \brief Analog caller ID waveform sample buffer */
01080    unsigned char *cidspill;
01081    /*! \brief Position in the cidspill buffer to send out next. */
01082    int cidpos;
01083    /*! \brief Length of the cidspill buffer containing samples. */
01084    int cidlen;
01085    /*! \brief Ring timeout timer?? */
01086    int ringt;
01087    /*!
01088     * \brief Ring timeout base.
01089     * \note Value computed indirectly from "ringtimeout" read in from chan_dahdi.conf
01090     */
01091    int ringt_base;
01092    /*!
01093     * \brief Number of most significant digits/characters to strip from the dialed number.
01094     * \note Feature is deprecated.  Use dialplan logic.
01095     * \note The characters are stripped before the PRI TON/NPI prefix
01096     * characters are processed.
01097     */
01098    int stripmsd;
01099    /*!
01100     * \brief TRUE if Call Waiting (CW) CPE Alert Signal (CAS) is being sent.
01101     * \note
01102     * After CAS is sent, the call waiting caller id will be sent if the phone
01103     * gives a positive reply.
01104     */
01105    int callwaitcas;
01106    /*! \brief Number of call waiting rings. */
01107    int callwaitrings;
01108    /*! \brief Echo cancel parameters. */
01109    struct {
01110       struct dahdi_echocanparams head;
01111       struct dahdi_echocanparam params[DAHDI_MAX_ECHOCANPARAMS];
01112    } echocancel;
01113    /*!
01114     * \brief Echo training time. 0 = disabled
01115     * \note Set from the "echotraining" value read in from chan_dahdi.conf
01116     */
01117    int echotraining;
01118    /*! \brief Filled with 'w'.  XXX Purpose?? */
01119    char echorest[20];
01120    /*!
01121     * \brief Number of times to see "busy" tone before hanging up.
01122     * \note Set from the "busycount" value read in from chan_dahdi.conf
01123     */
01124    int busycount;
01125    /*!
01126     * \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
01127     * \note Set from the "busycompare" value read in from chan_dahdi.conf
01128     */
01129    int busycompare;
01130    /*!
01131     * \brief Lenght of "tone" in ms.
01132     * \note Set from the "busypattern" value read in from chan_dahdi.conf
01133     */
01134    int busytonelength;
01135    /*!
01136     * \brief Lenght of "silence" in ms.
01137     * \note Set from the "busypattern" value read in from chan_dahdi.conf
01138     */
01139    int busyquietlength;
01140    /*!
01141     * \brief  Maximun percentage difference allowed between measured and actual pattern
01142     * \note Set from the "busyfuzziness" value read in from chan_dahdi.conf
01143     */
01144    int busyfuzziness;
01145    /*!
01146     * \brief Maximun signal average level considered as silence in this channel
01147     * \note Set from the "silencethreshold" value read in from chan_dahdi.conf
01148     */
01149    int silencethreshold;
01150    /*!
01151     * \brief Bitmapped call progress detection flags. CALLPROGRESS_xxx values.
01152     * \note Bits set from the "callprogress" and "faxdetect" values read in from chan_dahdi.conf
01153     */
01154    int callprogress;
01155    /*!
01156     * \brief Number of milliseconds to wait for dialtone.
01157     * \note Set from the "waitfordialtone" value read in from chan_dahdi.conf
01158     */
01159    int waitfordialtone;
01160    struct timeval waitingfordt;        /*!< Time we started waiting for dialtone */
01161    struct timeval flashtime;        /*!< Last flash-hook time */
01162    /*! \brief Opaque DSP configuration structure. */
01163    struct ast_dsp *dsp;
01164    /*! \brief DAHDI dial operation command struct for ioctl() call. */
01165    struct dahdi_dialoperation dop;
01166    int whichwink;             /*!< SIG_FEATDMF_TA Which wink are we on? */
01167    /*! \brief Second part of SIG_FEATDMF_TA wink operation. */
01168    char finaldial[64];
01169    char accountcode[AST_MAX_ACCOUNT_CODE];      /*!< Account code */
01170    int amaflags;              /*!< AMA Flags */
01171    struct tdd_state *tdd;           /*!< TDD flag */
01172    /*! \brief Accumulated call forwarding number. */
01173    char call_forward[AST_MAX_EXTENSION];
01174    /*!
01175     * \brief Voice mailbox location.
01176     * \note Set from the "mailbox" string read in from chan_dahdi.conf
01177     */
01178    char mailbox[AST_MAX_EXTENSION];
01179    /*! \brief Opaque event subscription parameters for message waiting indication support. */
01180    struct ast_event_sub *mwi_event_sub;
01181    /*! \brief Delayed dialing for E911.  Overlap digits for ISDN. */
01182    char dialdest[256];
01183 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
01184    struct dahdi_vmwi_info mwisend_setting;            /*!< Which VMWI methods to use */
01185    unsigned int mwisend_fsk: 1;     /*! Variable for enabling FSK MWI handling in chan_dahdi */
01186    unsigned int mwisend_rpas:1;     /*! Variable for enabling Ring Pulse Alert before MWI FSK Spill */
01187 #endif
01188    int distinctivering;          /*!< Which distinctivering to use */
01189    int dtmfrelax;             /*!< whether to run in relaxed DTMF mode */
01190    /*! \brief Holding place for event injected from outside normal operation. */
01191    int fake_event;
01192    /*!
01193     * \brief Minimal time period (ms) between the answer polarity
01194     * switch and hangup polarity switch.
01195     */
01196    int polarityonanswerdelay;
01197    /*! \brief Start delay time if polarityonanswerdelay is nonzero. */
01198    struct timeval polaritydelaytv;
01199    /*!
01200     * \brief Send caller ID on FXS after this many rings. Set to 1 for US.
01201     * \note Set from the "sendcalleridafter" value read in from chan_dahdi.conf
01202     */
01203    int sendcalleridafter;
01204    /*! \brief Current line interface polarity. POLARITY_IDLE, POLARITY_REV */
01205    int polarity;
01206    /*! \brief DSP feature flags: DSP_FEATURE_xxx */
01207    int dsp_features;
01208 #if defined(HAVE_SS7)
01209    /*! \brief SS7 control parameters */
01210    struct sig_ss7_linkset *ss7;
01211 #endif   /* defined(HAVE_SS7) */
01212 #ifdef HAVE_OPENR2
01213    struct dahdi_mfcr2 *mfcr2;
01214    openr2_chan_t *r2chan;
01215    openr2_calling_party_category_t mfcr2_recvd_category;
01216    openr2_calling_party_category_t mfcr2_category;
01217    int mfcr2_dnis_index;
01218    int mfcr2_ani_index;
01219    int mfcr2call:1;
01220    int mfcr2_answer_pending:1;
01221    int mfcr2_charge_calls:1;
01222    int mfcr2_allow_collect_calls:1;
01223    int mfcr2_forced_release:1;
01224    int mfcr2_dnis_matched:1;
01225    int mfcr2_call_accepted:1;
01226    int mfcr2_progress:1;
01227    int mfcr2_accept_on_offer:1;
01228 #endif
01229    /*! \brief DTMF digit in progress.  0 when no digit in progress. */
01230    char begindigit;
01231    /*! \brief TRUE if confrence is muted. */
01232    int muting;
01233    void *sig_pvt;
01234    struct ast_cc_config_params *cc_params;
01235    /* DAHDI channel names may differ greatly from the
01236     * string that was provided to an app such as Dial. We
01237     * need to save the original string passed to dahdi_request
01238     * for call completion purposes. This way, we can replicate
01239     * the original dialed string later.
01240     */
01241    char dialstring[AST_CHANNEL_NAME];
01242 };
01243 
01244 #define DATA_EXPORT_DAHDI_PVT(MEMBER)              \
01245    MEMBER(dahdi_pvt, cid_rxgain, AST_DATA_DOUBLE)        \
01246    MEMBER(dahdi_pvt, rxgain, AST_DATA_DOUBLE)         \
01247    MEMBER(dahdi_pvt, txgain, AST_DATA_DOUBLE)         \
01248    MEMBER(dahdi_pvt, txdrc, AST_DATA_DOUBLE)       \
01249    MEMBER(dahdi_pvt, rxdrc, AST_DATA_DOUBLE)       \
01250    MEMBER(dahdi_pvt, adsi, AST_DATA_BOOLEAN)       \
01251    MEMBER(dahdi_pvt, answeronpolarityswitch, AST_DATA_BOOLEAN) \
01252    MEMBER(dahdi_pvt, busydetect, AST_DATA_BOOLEAN)       \
01253    MEMBER(dahdi_pvt, callreturn, AST_DATA_BOOLEAN)       \
01254    MEMBER(dahdi_pvt, callwaiting, AST_DATA_BOOLEAN)      \
01255    MEMBER(dahdi_pvt, callwaitingcallerid, AST_DATA_BOOLEAN) \
01256    MEMBER(dahdi_pvt, cancallforward, AST_DATA_BOOLEAN)      \
01257    MEMBER(dahdi_pvt, canpark, AST_DATA_BOOLEAN)       \
01258    MEMBER(dahdi_pvt, confirmanswer, AST_DATA_BOOLEAN)    \
01259    MEMBER(dahdi_pvt, destroy, AST_DATA_BOOLEAN)       \
01260    MEMBER(dahdi_pvt, didtdd, AST_DATA_BOOLEAN)        \
01261    MEMBER(dahdi_pvt, dialednone, AST_DATA_BOOLEAN)       \
01262    MEMBER(dahdi_pvt, dialing, AST_DATA_BOOLEAN)       \
01263    MEMBER(dahdi_pvt, digital, AST_DATA_BOOLEAN)       \
01264    MEMBER(dahdi_pvt, dnd, AST_DATA_BOOLEAN)        \
01265    MEMBER(dahdi_pvt, echobreak, AST_DATA_BOOLEAN)        \
01266    MEMBER(dahdi_pvt, echocanbridged, AST_DATA_BOOLEAN)      \
01267    MEMBER(dahdi_pvt, echocanon, AST_DATA_BOOLEAN)        \
01268    MEMBER(dahdi_pvt, faxhandled, AST_DATA_BOOLEAN)       \
01269    MEMBER(dahdi_pvt, usefaxbuffers, AST_DATA_BOOLEAN)    \
01270    MEMBER(dahdi_pvt, bufferoverrideinuse, AST_DATA_BOOLEAN) \
01271    MEMBER(dahdi_pvt, firstradio, AST_DATA_BOOLEAN)       \
01272    MEMBER(dahdi_pvt, hanguponpolarityswitch, AST_DATA_BOOLEAN) \
01273    MEMBER(dahdi_pvt, hardwaredtmf, AST_DATA_BOOLEAN)     \
01274    MEMBER(dahdi_pvt, hidecallerid, AST_DATA_BOOLEAN)     \
01275    MEMBER(dahdi_pvt, hidecalleridname, AST_DATA_BOOLEAN)    \
01276    MEMBER(dahdi_pvt, ignoredtmf, AST_DATA_BOOLEAN)       \
01277    MEMBER(dahdi_pvt, immediate, AST_DATA_BOOLEAN)        \
01278    MEMBER(dahdi_pvt, inalarm, AST_DATA_BOOLEAN)       \
01279    MEMBER(dahdi_pvt, mate, AST_DATA_BOOLEAN)       \
01280    MEMBER(dahdi_pvt, outgoing, AST_DATA_BOOLEAN)         \
01281    MEMBER(dahdi_pvt, permcallwaiting, AST_DATA_BOOLEAN)     \
01282    MEMBER(dahdi_pvt, priindication_oob, AST_DATA_BOOLEAN)      \
01283    MEMBER(dahdi_pvt, priexclusive, AST_DATA_BOOLEAN)     \
01284    MEMBER(dahdi_pvt, pulse, AST_DATA_BOOLEAN)         \
01285    MEMBER(dahdi_pvt, pulsedial, AST_DATA_BOOLEAN)        \
01286    MEMBER(dahdi_pvt, restartpending, AST_DATA_BOOLEAN)      \
01287    MEMBER(dahdi_pvt, restrictcid, AST_DATA_BOOLEAN)      \
01288    MEMBER(dahdi_pvt, threewaycalling, AST_DATA_BOOLEAN)     \
01289    MEMBER(dahdi_pvt, transfer, AST_DATA_BOOLEAN)         \
01290    MEMBER(dahdi_pvt, use_callerid, AST_DATA_BOOLEAN)     \
01291    MEMBER(dahdi_pvt, use_callingpres, AST_DATA_BOOLEAN)     \
01292    MEMBER(dahdi_pvt, usedistinctiveringdetection, AST_DATA_BOOLEAN)  \
01293    MEMBER(dahdi_pvt, dahditrcallerid, AST_DATA_BOOLEAN)        \
01294    MEMBER(dahdi_pvt, transfertobusy, AST_DATA_BOOLEAN)         \
01295    MEMBER(dahdi_pvt, mwimonitor_neon, AST_DATA_BOOLEAN)        \
01296    MEMBER(dahdi_pvt, mwimonitor_fsk, AST_DATA_BOOLEAN)         \
01297    MEMBER(dahdi_pvt, mwimonitor_rpas, AST_DATA_BOOLEAN)        \
01298    MEMBER(dahdi_pvt, mwimonitoractive, AST_DATA_BOOLEAN)       \
01299    MEMBER(dahdi_pvt, mwisendactive, AST_DATA_BOOLEAN)       \
01300    MEMBER(dahdi_pvt, inservice, AST_DATA_BOOLEAN)           \
01301    MEMBER(dahdi_pvt, locallyblocked, AST_DATA_BOOLEAN)         \
01302    MEMBER(dahdi_pvt, remotelyblocked, AST_DATA_BOOLEAN)        \
01303    MEMBER(dahdi_pvt, manages_span_alarms, AST_DATA_BOOLEAN)    \
01304    MEMBER(dahdi_pvt, use_smdi, AST_DATA_BOOLEAN)            \
01305    MEMBER(dahdi_pvt, context, AST_DATA_STRING)           \
01306    MEMBER(dahdi_pvt, defcontext, AST_DATA_STRING)           \
01307    MEMBER(dahdi_pvt, exten, AST_DATA_STRING)          \
01308    MEMBER(dahdi_pvt, language, AST_DATA_STRING)          \
01309    MEMBER(dahdi_pvt, mohinterpret, AST_DATA_STRING)         \
01310    MEMBER(dahdi_pvt, mohsuggest, AST_DATA_STRING)           \
01311    MEMBER(dahdi_pvt, parkinglot, AST_DATA_STRING)
01312 
01313 AST_DATA_STRUCTURE(dahdi_pvt, DATA_EXPORT_DAHDI_PVT);
01314 
01315 static struct dahdi_pvt *iflist = NULL;   /*!< Main interface list start */
01316 static struct dahdi_pvt *ifend = NULL; /*!< Main interface list end */
01317 
01318 #if defined(HAVE_PRI)
01319 static struct dahdi_parms_pseudo {
01320    int buf_no;             /*!< Number of buffers */
01321    int buf_policy;            /*!< Buffer policy */
01322    int faxbuf_no;              /*!< Number of Fax buffers */
01323    int faxbuf_policy;          /*!< Fax buffer policy */
01324 } dahdi_pseudo_parms;
01325 #endif   /* defined(HAVE_PRI) */
01326 
01327 /*! \brief Channel configuration from chan_dahdi.conf .
01328  * This struct is used for parsing the [channels] section of chan_dahdi.conf.
01329  * Generally there is a field here for every possible configuration item.
01330  *
01331  * The state of fields is saved along the parsing and whenever a 'channel'
01332  * statement is reached, the current dahdi_chan_conf is used to configure the
01333  * channel (struct dahdi_pvt)
01334  *
01335  * \see dahdi_chan_init for the default values.
01336  */
01337 struct dahdi_chan_conf {
01338    struct dahdi_pvt chan;
01339 #ifdef HAVE_PRI
01340    struct dahdi_pri pri;
01341 #endif
01342 
01343 #if defined(HAVE_SS7)
01344    struct dahdi_ss7 ss7;
01345 #endif   /* defined(HAVE_SS7) */
01346 
01347 #ifdef HAVE_OPENR2
01348    struct dahdi_mfcr2_conf mfcr2;
01349 #endif
01350    struct dahdi_params timing;
01351    int is_sig_auto; /*!< Use channel signalling from DAHDI? */
01352    /*! Continue configuration even if a channel is not there. */
01353    int ignore_failed_channels;
01354 
01355    /*!
01356     * \brief The serial port to listen for SMDI data on
01357     * \note Set from the "smdiport" string read in from chan_dahdi.conf
01358     */
01359    char smdi_port[SMDI_MAX_FILENAME_LEN];
01360 };
01361 
01362 /*! returns a new dahdi_chan_conf with default values (by-value) */
01363 static struct dahdi_chan_conf dahdi_chan_conf_default(void)
01364 {
01365    /* recall that if a field is not included here it is initialized
01366     * to 0 or equivalent
01367     */
01368    struct dahdi_chan_conf conf = {
01369 #ifdef HAVE_PRI
01370       .pri.pri = {
01371          .nsf = PRI_NSF_NONE,
01372          .switchtype = PRI_SWITCH_NI2,
01373          .dialplan = PRI_UNKNOWN + 1,
01374          .localdialplan = PRI_NATIONAL_ISDN + 1,
01375          .nodetype = PRI_CPE,
01376          .qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL,
01377 
01378 #if defined(HAVE_PRI_CCSS)
01379          .cc_ptmp_recall_mode = 1,/* specificRecall */
01380          .cc_qsig_signaling_link_req = 1,/* retain */
01381          .cc_qsig_signaling_link_rsp = 1,/* retain */
01382 #endif   /* defined(HAVE_PRI_CCSS) */
01383 
01384          .minunused = 2,
01385          .idleext = "",
01386          .idledial = "",
01387          .internationalprefix = "",
01388          .nationalprefix = "",
01389          .localprefix = "",
01390          .privateprefix = "",
01391          .unknownprefix = "",
01392          .resetinterval = -1,
01393       },
01394 #endif
01395 #if defined(HAVE_SS7)
01396       .ss7.ss7 = {
01397          .called_nai = SS7_NAI_NATIONAL,
01398          .calling_nai = SS7_NAI_NATIONAL,
01399          .internationalprefix = "",
01400          .nationalprefix = "",
01401          .subscriberprefix = "",
01402          .unknownprefix = ""
01403       },
01404 #endif   /* defined(HAVE_SS7) */
01405 #ifdef HAVE_OPENR2
01406       .mfcr2 = {
01407          .variant = OR2_VAR_ITU,
01408          .mfback_timeout = -1,
01409          .metering_pulse_timeout = -1,
01410          .max_ani = 10,
01411          .max_dnis = 4,
01412          .get_ani_first = -1,
01413 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
01414          .skip_category_request = -1,
01415 #endif
01416          .call_files = 0,
01417          .allow_collect_calls = 0,
01418          .charge_calls = 1,
01419          .accept_on_offer = 1,
01420          .forced_release = 0,
01421          .double_answer = 0,
01422          .immediate_accept = -1,
01423          .logdir = "",
01424          .r2proto_file = "",
01425          .loglevel = OR2_LOG_ERROR | OR2_LOG_WARNING,
01426          .category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER
01427       },
01428 #endif
01429       .chan = {
01430          .context = "default",
01431          .cid_num = "",
01432          .cid_name = "",
01433          .cid_tag = "",
01434          .mohinterpret = "default",
01435          .mohsuggest = "",
01436          .parkinglot = "",
01437          .transfertobusy = 1,
01438 
01439          .cid_signalling = CID_SIG_BELL,
01440          .cid_start = CID_START_RING,
01441          .dahditrcallerid = 0,
01442          .use_callerid = 1,
01443          .sig = -1,
01444          .outsigmod = -1,
01445 
01446          .cid_rxgain = +5.0,
01447 
01448          .tonezone = -1,
01449 
01450          .echocancel.head.tap_length = 1,
01451 
01452          .busycount = 3,
01453          .busycompare = 0,
01454          .busytonelength = 0,
01455          .busyquietlength = 0,
01456          .busyfuzziness = 0,
01457          .silencethreshold = 0,
01458 
01459          .accountcode = "",
01460 
01461          .mailbox = "",
01462 
01463 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
01464          .mwisend_fsk = 1,
01465 #endif
01466          .polarityonanswerdelay = 600,
01467 
01468          .sendcalleridafter = DEFAULT_CIDRINGS,
01469 
01470          .buf_policy = DAHDI_POLICY_IMMEDIATE,
01471          .buf_no = numbufs,
01472          .usefaxbuffers = 0,
01473          .cc_params = ast_cc_config_params_init(),
01474       },
01475       .timing = {
01476          .prewinktime = -1,
01477          .preflashtime = -1,
01478          .winktime = -1,
01479          .flashtime = -1,
01480          .starttime = -1,
01481          .rxwinktime = -1,
01482          .rxflashtime = -1,
01483          .debouncetime = -1
01484       },
01485       .is_sig_auto = 1,
01486       .smdi_port = "/dev/ttyS0",
01487    };
01488 
01489    return conf;
01490 }
01491 
01492 
01493 static struct ast_channel *dahdi_request(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause);
01494 static int dahdi_digit_begin(struct ast_channel *ast, char digit);
01495 static int dahdi_digit_end(struct ast_channel *ast, char digit, unsigned int duration);
01496 static int dahdi_sendtext(struct ast_channel *c, const char *text);
01497 static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout);
01498 static int dahdi_hangup(struct ast_channel *ast);
01499 static int dahdi_answer(struct ast_channel *ast);
01500 static struct ast_frame *dahdi_read(struct ast_channel *ast);
01501 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame);
01502 static struct ast_frame *dahdi_exception(struct ast_channel *ast);
01503 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen);
01504 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
01505 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen);
01506 static int dahdi_queryoption(struct ast_channel *chan, int option, void *data, int *datalen);
01507 static int dahdi_func_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len);
01508 static int dahdi_func_write(struct ast_channel *chan, const char *function, char *data, const char *value);
01509 static int dahdi_devicestate(void *data);
01510 static int dahdi_cc_callback(struct ast_channel *inbound, const char *dest, ast_cc_callback_fn callback);
01511 
01512 static const struct ast_channel_tech dahdi_tech = {
01513    .type = "DAHDI",
01514    .description = tdesc,
01515    .capabilities = AST_FORMAT_SLINEAR | AST_FORMAT_ULAW | AST_FORMAT_ALAW,
01516    .requester = dahdi_request,
01517    .send_digit_begin = dahdi_digit_begin,
01518    .send_digit_end = dahdi_digit_end,
01519    .send_text = dahdi_sendtext,
01520    .call = dahdi_call,
01521    .hangup = dahdi_hangup,
01522    .answer = dahdi_answer,
01523    .read = dahdi_read,
01524    .write = dahdi_write,
01525    .bridge = dahdi_bridge,
01526    .exception = dahdi_exception,
01527    .indicate = dahdi_indicate,
01528    .fixup = dahdi_fixup,
01529    .setoption = dahdi_setoption,
01530    .queryoption = dahdi_queryoption,
01531    .func_channel_read = dahdi_func_read,
01532    .func_channel_write = dahdi_func_write,
01533    .devicestate = dahdi_devicestate,
01534    .cc_callback = dahdi_cc_callback,
01535 };
01536 
01537 #define GET_CHANNEL(p) ((p)->channel)
01538 
01539 #define SIG_PRI_LIB_HANDLE_CASES \
01540    SIG_PRI:                \
01541    case SIG_BRI:              \
01542    case SIG_BRI_PTMP
01543 
01544 /*!
01545  * \internal
01546  * \brief Determine if sig_pri handles the signaling.
01547  * \since 1.8
01548  *
01549  * \param signaling Signaling to determine if is for sig_pri.
01550  *
01551  * \return TRUE if the signaling is for sig_pri.
01552  */
01553 static inline int dahdi_sig_pri_lib_handles(int signaling)
01554 {
01555    int handles;
01556 
01557    switch (signaling) {
01558    case SIG_PRI_LIB_HANDLE_CASES:
01559       handles = 1;
01560       break;
01561    default:
01562       handles = 0;
01563       break;
01564    }
01565 
01566    return handles;
01567 }
01568 
01569 static enum analog_sigtype dahdisig_to_analogsig(int sig)
01570 {
01571    switch (sig) {
01572    case SIG_FXOLS:
01573       return ANALOG_SIG_FXOLS;
01574    case SIG_FXOGS:
01575       return ANALOG_SIG_FXOGS;
01576    case SIG_FXOKS:
01577       return ANALOG_SIG_FXOKS;
01578    case SIG_FXSLS:
01579       return ANALOG_SIG_FXSLS;
01580    case SIG_FXSGS:
01581       return ANALOG_SIG_FXSGS;
01582    case SIG_FXSKS:
01583       return ANALOG_SIG_FXSKS;
01584    case SIG_EMWINK:
01585       return ANALOG_SIG_EMWINK;
01586    case SIG_EM:
01587       return ANALOG_SIG_EM;
01588    case SIG_EM_E1:
01589       return ANALOG_SIG_EM_E1;
01590    case SIG_FEATD:
01591       return ANALOG_SIG_FEATD;
01592    case SIG_FEATDMF:
01593       return ANALOG_SIG_FEATDMF;
01594    case SIG_E911:
01595       return SIG_E911;
01596    case SIG_FGC_CAMA:
01597       return ANALOG_SIG_FGC_CAMA;
01598    case SIG_FGC_CAMAMF:
01599       return ANALOG_SIG_FGC_CAMAMF;
01600    case SIG_FEATB:
01601       return ANALOG_SIG_FEATB;
01602    case SIG_SFWINK:
01603       return ANALOG_SIG_SFWINK;
01604    case SIG_SF:
01605       return ANALOG_SIG_SF;
01606    case SIG_SF_FEATD:
01607       return ANALOG_SIG_SF_FEATD;
01608    case SIG_SF_FEATDMF:
01609       return ANALOG_SIG_SF_FEATDMF;
01610    case SIG_FEATDMF_TA:
01611       return ANALOG_SIG_FEATDMF_TA;
01612    case SIG_SF_FEATB:
01613       return ANALOG_SIG_FEATB;
01614    default:
01615       return -1;
01616    }
01617 }
01618 
01619 
01620 static int analog_tone_to_dahditone(enum analog_tone tone)
01621 {
01622    switch (tone) {
01623    case ANALOG_TONE_RINGTONE:
01624       return DAHDI_TONE_RINGTONE;
01625    case ANALOG_TONE_STUTTER:
01626       return DAHDI_TONE_STUTTER;
01627    case ANALOG_TONE_CONGESTION:
01628       return DAHDI_TONE_CONGESTION;
01629    case ANALOG_TONE_DIALTONE:
01630       return DAHDI_TONE_DIALTONE;
01631    case ANALOG_TONE_DIALRECALL:
01632       return DAHDI_TONE_DIALRECALL;
01633    case ANALOG_TONE_INFO:
01634       return DAHDI_TONE_INFO;
01635    default:
01636       return -1;
01637    }
01638 }
01639 
01640 static int analogsub_to_dahdisub(enum analog_sub analogsub)
01641 {
01642    int index;
01643 
01644    switch (analogsub) {
01645    case ANALOG_SUB_REAL:
01646       index = SUB_REAL;
01647       break;
01648    case ANALOG_SUB_CALLWAIT:
01649       index = SUB_CALLWAIT;
01650       break;
01651    case ANALOG_SUB_THREEWAY:
01652       index = SUB_THREEWAY;
01653       break;
01654    default:
01655       ast_log(LOG_ERROR, "Unidentified sub!\n");
01656       index = SUB_REAL;
01657    }
01658 
01659    return index;
01660 }
01661 
01662 static enum analog_event dahdievent_to_analogevent(int event);
01663 static int bump_gains(struct dahdi_pvt *p);
01664 static int dahdi_setlinear(int dfd, int linear);
01665 
01666 static int my_start_cid_detect(void *pvt, int cid_signalling)
01667 {
01668    struct dahdi_pvt *p = pvt;
01669    int index = SUB_REAL;
01670    p->cs = callerid_new(cid_signalling);
01671    if (!p->cs) {
01672       ast_log(LOG_ERROR, "Unable to alloc callerid\n");
01673       return -1;
01674    }
01675    bump_gains(p);
01676    dahdi_setlinear(p->subs[index].dfd, 0);
01677 
01678    return 0;
01679 }
01680 
01681 static int my_stop_cid_detect(void *pvt)
01682 {
01683    struct dahdi_pvt *p = pvt;
01684    int index = SUB_REAL;
01685    if (p->cs)
01686       callerid_free(p->cs);
01687    dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
01688    return 0;
01689 }
01690 
01691 static int my_get_callerid(void *pvt, char *namebuf, char *numbuf, enum analog_event *ev, size_t timeout)
01692 {
01693    struct dahdi_pvt *p = pvt;
01694    struct analog_pvt *analog_p = p->sig_pvt;
01695    struct pollfd poller;
01696    char *name, *num;
01697    int index = SUB_REAL;
01698    int res;
01699    unsigned char buf[256];
01700    int flags;
01701 
01702    poller.fd = p->subs[SUB_REAL].dfd;
01703    poller.events = POLLPRI | POLLIN;
01704    poller.revents = 0;
01705 
01706    res = poll(&poller, 1, timeout);
01707 
01708    if (poller.revents & POLLPRI) {
01709       *ev = dahdievent_to_analogevent(dahdi_get_event(p->subs[SUB_REAL].dfd));
01710       return 1;
01711    }
01712 
01713    if (poller.revents & POLLIN) {
01714       /*** NOTES ***/
01715       /* Change API: remove cid_signalling from get_callerid, add a new start_cid_detect and stop_cid_detect function
01716        * to enable slin mode and allocate cid detector. get_callerid should be able to be called any number of times until
01717        * either a timeout occurs or CID is detected (returns 0). returning 1 should be event received, and -1 should be
01718        * a failure and die, and returning 2 means no event was received. */
01719       res = read(p->subs[index].dfd, buf, sizeof(buf));
01720       if (res < 0) {
01721          if (errno != ELAST) {
01722             ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
01723             callerid_free(p->cs);
01724             return -1;
01725          }
01726       }
01727 
01728       if (analog_p->ringt > 0) {
01729          if (!(--analog_p->ringt)) {
01730             /* only return if we timeout from a ring event */
01731             return -1;
01732          }
01733       }
01734 
01735       if (p->cid_signalling == CID_SIG_V23_JP) {
01736          res = callerid_feed_jp(p->cs, buf, res, AST_LAW(p));
01737       } else {
01738          res = callerid_feed(p->cs, buf, res, AST_LAW(p));
01739       }
01740       if (res < 0) {
01741          /*
01742           * The previous diagnostic message output likely
01743           * explains why it failed.
01744           */
01745          ast_log(LOG_WARNING, "Failed to decode CallerID\n");
01746          return -1;
01747       }
01748 
01749       if (res == 1) {
01750          callerid_get(p->cs, &name, &num, &flags);
01751          if (name)
01752             ast_copy_string(namebuf, name, ANALOG_MAX_CID);
01753          if (num)
01754             ast_copy_string(numbuf, num, ANALOG_MAX_CID);
01755 
01756          ast_debug(1, "CallerID number: %s, name: %s, flags=%d\n", num, name, flags);
01757          return 0;
01758       }
01759    }
01760 
01761    *ev = ANALOG_EVENT_NONE;
01762    return 2;
01763 }
01764 
01765 static const char *event2str(int event);
01766 static int restore_gains(struct dahdi_pvt *p);
01767 
01768 static int my_distinctive_ring(struct ast_channel *chan, void *pvt, int idx, int *ringdata)
01769 {
01770    unsigned char buf[256];
01771    int distMatches;
01772    int curRingData[RING_PATTERNS];
01773    int receivedRingT;
01774    int counter1;
01775    int counter;
01776    int i;
01777    int res;
01778    int checkaftercid = 0;
01779 
01780    struct dahdi_pvt *p = pvt;
01781    struct analog_pvt *analog_p = p->sig_pvt;
01782 
01783    if (ringdata == NULL) {
01784       ringdata = curRingData;
01785    } else {
01786       checkaftercid = 1;
01787    }
01788 
01789    /* We must have a ring by now, so, if configured, lets try to listen for
01790     * distinctive ringing */
01791    if ((checkaftercid && distinctiveringaftercid) || !checkaftercid) {
01792       /* Clear the current ring data array so we don't have old data in it. */
01793       for (receivedRingT = 0; receivedRingT < RING_PATTERNS; receivedRingT++)
01794          ringdata[receivedRingT] = 0;
01795       receivedRingT = 0;
01796       if (checkaftercid && distinctiveringaftercid)
01797          ast_verb(3, "Detecting post-CID distinctive ring\n");
01798       /* Check to see if context is what it should be, if not set to be. */
01799       else if (strcmp(p->context,p->defcontext) != 0) {
01800          ast_copy_string(p->context, p->defcontext, sizeof(p->context));
01801          ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
01802       }
01803 
01804       for (;;) {
01805          i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
01806          if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
01807             ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
01808             ast_hangup(chan);
01809             return 1;
01810          }
01811          if (i & DAHDI_IOMUX_SIGEVENT) {
01812             res = dahdi_get_event(p->subs[idx].dfd);
01813             if (res == DAHDI_EVENT_NOALARM) {
01814                p->inalarm = 0;
01815                analog_p->inalarm = 0;
01816             }
01817             ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
01818             res = 0;
01819             /* Let us detect distinctive ring */
01820 
01821             ringdata[receivedRingT] = analog_p->ringt;
01822 
01823             if (analog_p->ringt < analog_p->ringt_base/2)
01824                break;
01825             /* Increment the ringT counter so we can match it against
01826                values in chan_dahdi.conf for distinctive ring */
01827             if (++receivedRingT == RING_PATTERNS)
01828                break;
01829          } else if (i & DAHDI_IOMUX_READ) {
01830             res = read(p->subs[idx].dfd, buf, sizeof(buf));
01831             if (res < 0) {
01832                if (errno != ELAST) {
01833                   ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
01834                   ast_hangup(chan);
01835                   return 1;
01836                }
01837                break;
01838             }
01839             if (analog_p->ringt > 0) {
01840                if (!(--analog_p->ringt)) {
01841                   res = -1;
01842                   break;
01843                }
01844             }
01845          }
01846       }
01847    }
01848    if ((checkaftercid && usedistinctiveringdetection) || !checkaftercid) {
01849       /* this only shows up if you have n of the dring patterns filled in */
01850       ast_verb(3, "Detected ring pattern: %d,%d,%d\n",ringdata[0],ringdata[1],ringdata[2]);
01851       for (counter = 0; counter < 3; counter++) {
01852       /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this channel */
01853          distMatches = 0;
01854          /* this only shows up if you have n of the dring patterns filled in */
01855          ast_verb(3, "Checking %d,%d,%d\n",
01856                p->drings.ringnum[counter].ring[0],
01857                p->drings.ringnum[counter].ring[1],
01858                p->drings.ringnum[counter].ring[2]);
01859          for (counter1 = 0; counter1 < 3; counter1++) {
01860             ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
01861             if (p->drings.ringnum[counter].ring[counter1] == -1) {
01862                ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
01863                ringdata[counter1]);
01864                distMatches++;
01865             } else if (ringdata[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
01866                               ringdata[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
01867                ast_verb(3, "Ring pattern matched in range: %d to %d\n",
01868                (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
01869                (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
01870                distMatches++;
01871             }
01872          }
01873 
01874          if (distMatches == 3) {
01875             /* The ring matches, set the context to whatever is for distinctive ring.. */
01876             ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context));
01877             ast_copy_string(chan->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(chan->context));
01878             ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
01879             break;
01880          }
01881       }
01882    }
01883    /* Restore linear mode (if appropriate) for Caller*ID processing */
01884    dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
01885    restore_gains(p);
01886 
01887    return 0;
01888 }
01889 
01890 static int my_stop_callwait(void *pvt)
01891 {
01892    struct dahdi_pvt *p = pvt;
01893    p->callwaitingrepeat = 0;
01894    p->cidcwexpire = 0;
01895    p->cid_suppress_expire = 0;
01896 
01897    return 0;
01898 }
01899 
01900 static int send_callerid(struct dahdi_pvt *p);
01901 static int save_conference(struct dahdi_pvt *p);
01902 static int restore_conference(struct dahdi_pvt *p);
01903 
01904 static int my_callwait(void *pvt)
01905 {
01906    struct dahdi_pvt *p = pvt;
01907    p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
01908    if (p->cidspill) {
01909       ast_log(LOG_WARNING, "Spill already exists?!?\n");
01910       ast_free(p->cidspill);
01911    }
01912 
01913    /*
01914     * SAS: Subscriber Alert Signal, 440Hz for 300ms
01915     * CAS: CPE Alert Signal, 2130Hz * 2750Hz sine waves
01916     */
01917    if (!(p->cidspill = ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE * 4)))
01918       return -1;
01919    save_conference(p);
01920    /* Silence */
01921    memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
01922    if (!p->callwaitrings && p->callwaitingcallerid) {
01923       ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
01924       p->callwaitcas = 1;
01925       p->cidlen = 2400 + 680 + READ_SIZE * 4;
01926    } else {
01927       ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
01928       p->callwaitcas = 0;
01929       p->cidlen = 2400 + READ_SIZE * 4;
01930    }
01931    p->cidpos = 0;
01932    send_callerid(p);
01933 
01934    return 0;
01935 }
01936 
01937 static int my_send_callerid(void *pvt, int cwcid, struct ast_party_caller *caller)
01938 {
01939    struct dahdi_pvt *p = pvt;
01940 
01941    ast_debug(2, "Starting cid spill\n");
01942 
01943    if (p->cidspill) {
01944       ast_log(LOG_WARNING, "cidspill already exists??\n");
01945       ast_free(p->cidspill);
01946    }
01947 
01948    if ((p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) {
01949       if (cwcid == 0) {
01950          p->cidlen = ast_callerid_generate(p->cidspill,
01951             caller->id.name.str,
01952             caller->id.number.str,
01953             AST_LAW(p));
01954       } else {
01955          ast_verb(3, "CPE supports Call Waiting Caller*ID.  Sending '%s/%s'\n",
01956             caller->id.name.str, caller->id.number.str);
01957          p->callwaitcas = 0;
01958          p->cidcwexpire = 0;
01959          p->cidlen = ast_callerid_callwaiting_generate(p->cidspill,
01960             caller->id.name.str,
01961             caller->id.number.str,
01962             AST_LAW(p));
01963          p->cidlen += READ_SIZE * 4;
01964       }
01965       p->cidpos = 0;
01966       p->cid_suppress_expire = 0;
01967       send_callerid(p);
01968    }
01969    return 0;
01970 }
01971 
01972 static int my_dsp_reset_and_flush_digits(void *pvt)
01973 {
01974    struct dahdi_pvt *p = pvt;
01975    if (p->dsp)
01976       ast_dsp_digitreset(p->dsp);
01977 
01978    return 0;
01979 }
01980 
01981 static int my_dsp_set_digitmode(void *pvt, enum analog_dsp_digitmode mode)
01982 {
01983    struct dahdi_pvt *p = pvt;
01984 
01985    if (p->channel == CHAN_PSEUDO)
01986       ast_log(LOG_ERROR, "You have assumed incorrectly sir!\n");
01987 
01988    if (mode == ANALOG_DIGITMODE_DTMF) {
01989       /* If we do hardware dtmf, no need for a DSP */
01990       if (p->hardwaredtmf) {
01991          if (p->dsp) {
01992             ast_dsp_free(p->dsp);
01993             p->dsp = NULL;
01994          }
01995          return 0;
01996       }
01997 
01998       if (!p->dsp) {
01999          p->dsp = ast_dsp_new();
02000          if (!p->dsp) {
02001             ast_log(LOG_ERROR, "Unable to allocate DSP\n");
02002             return -1;
02003          }
02004       }
02005 
02006       ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
02007    } else if (mode == ANALOG_DIGITMODE_MF) {
02008       if (!p->dsp) {
02009          p->dsp = ast_dsp_new();
02010          if (!p->dsp) {
02011             ast_log(LOG_ERROR, "Unable to allocate DSP\n");
02012             return -1;
02013          }
02014       }
02015       ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
02016    }
02017    return 0;
02018 }
02019 
02020 static int dahdi_wink(struct dahdi_pvt *p, int index);
02021 
02022 static int my_wink(void *pvt, enum analog_sub sub)
02023 {
02024    struct dahdi_pvt *p = pvt;
02025    int index = analogsub_to_dahdisub(sub);
02026    if (index != SUB_REAL) {
02027       ast_log(LOG_ERROR, "We used a sub other than SUB_REAL (incorrect assumption sir)\n");
02028    }
02029    return dahdi_wink(p, index);
02030 }
02031 
02032 static void wakeup_sub(struct dahdi_pvt *p, int a);
02033 
02034 static int reset_conf(struct dahdi_pvt *p);
02035 
02036 static inline int dahdi_confmute(struct dahdi_pvt *p, int muted);
02037 
02038 static void my_handle_dtmf(void *pvt, struct ast_channel *ast, enum analog_sub analog_index, struct ast_frame **dest)
02039 {
02040    struct ast_frame *f = *dest;
02041    struct dahdi_pvt *p = pvt;
02042    int idx = analogsub_to_dahdisub(analog_index);
02043 
02044    ast_debug(1, "%s DTMF digit: 0x%02X '%c' on %s\n",
02045       f->frametype == AST_FRAME_DTMF_BEGIN ? "Begin" : "End",
02046       f->subclass.integer, f->subclass.integer, ast->name);
02047 
02048    if (f->subclass.integer == 'f') {
02049       if (f->frametype == AST_FRAME_DTMF_END) {
02050          /* Fax tone -- Handle and return NULL */
02051          if ((p->callprogress & CALLPROGRESS_FAX) && !p->faxhandled) {
02052             /* If faxbuffers are configured, use them for the fax transmission */
02053             if (p->usefaxbuffers && !p->bufferoverrideinuse) {
02054                struct dahdi_bufferinfo bi = {
02055                   .txbufpolicy = p->faxbuf_policy,
02056                   .bufsize = p->bufsize,
02057                   .numbufs = p->faxbuf_no
02058                };
02059                int res;
02060 
02061                if ((res = ioctl(p->subs[idx].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
02062                   ast_log(LOG_WARNING, "Channel '%s' unable to set buffer policy, reason: %s\n", ast->name, strerror(errno));
02063                } else {
02064                   p->bufferoverrideinuse = 1;
02065                }
02066             }
02067             p->faxhandled = 1;
02068             if (p->dsp) {
02069                p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
02070                ast_dsp_set_features(p->dsp, p->dsp_features);
02071                ast_debug(1, "Disabling FAX tone detection on %s after tone received\n", ast->name);
02072             }
02073             if (strcmp(ast->exten, "fax")) {
02074                const char *target_context = S_OR(ast->macrocontext, ast->context);
02075 
02076                /* We need to unlock 'ast' here because ast_exists_extension has the
02077                 * potential to start autoservice on the channel. Such action is prone
02078                 * to deadlock.
02079                 */
02080                ast_mutex_unlock(&p->lock);
02081                ast_channel_unlock(ast);
02082                if (ast_exists_extension(ast, target_context, "fax", 1,
02083                   S_COR(ast->caller.id.number.valid, ast->caller.id.number.str, NULL))) {
02084                   ast_channel_lock(ast);
02085                   ast_mutex_lock(&p->lock);
02086                   ast_verb(3, "Redirecting %s to fax extension\n", ast->name);
02087                   /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
02088                   pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten);
02089                   if (ast_async_goto(ast, target_context, "fax", 1))
02090                      ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context);
02091                } else {
02092                   ast_channel_lock(ast);
02093                   ast_mutex_lock(&p->lock);
02094                   ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
02095                }
02096             } else {
02097                ast_debug(1, "Already in a fax extension, not redirecting\n");
02098             }
02099          } else {
02100             ast_debug(1, "Fax already handled\n");
02101          }
02102          dahdi_confmute(p, 0);
02103       }
02104       p->subs[idx].f.frametype = AST_FRAME_NULL;
02105       p->subs[idx].f.subclass.integer = 0;
02106       *dest = &p->subs[idx].f;
02107    }
02108 }
02109 
02110 static void my_lock_private(void *pvt)
02111 {
02112    struct dahdi_pvt *p = pvt;
02113    ast_mutex_lock(&p->lock);
02114 }
02115 
02116 static void my_unlock_private(void *pvt)
02117 {
02118    struct dahdi_pvt *p = pvt;
02119    ast_mutex_unlock(&p->lock);
02120 }
02121 
02122 static void my_deadlock_avoidance_private(void *pvt)
02123 {
02124    struct dahdi_pvt *p = pvt;
02125 
02126    DEADLOCK_AVOIDANCE(&p->lock);
02127 }
02128 
02129 /*!
02130  * \internal
02131  * \brief Post an AMI DAHDI channel association event.
02132  * \since 1.8
02133  *
02134  * \param p DAHDI private pointer
02135  * \param chan Channel associated with the private pointer
02136  *
02137  * \return Nothing
02138  */
02139 static void dahdi_ami_channel_event(struct dahdi_pvt *p, struct ast_channel *chan)
02140 {
02141    char ch_name[20];
02142 
02143    if (p->channel < CHAN_PSEUDO) {
02144       /* No B channel */
02145       snprintf(ch_name, sizeof(ch_name), "no-media (%d)", p->channel);
02146    } else if (p->channel == CHAN_PSEUDO) {
02147       /* Pseudo channel */
02148       strcpy(ch_name, "pseudo");
02149    } else {
02150       /* Real channel */
02151       snprintf(ch_name, sizeof(ch_name), "%d", p->channel);
02152    }
02153    ast_manager_event(chan, EVENT_FLAG_CALL, "DAHDIChannel",
02154       "Channel: %s\r\n"
02155       "Uniqueid: %s\r\n"
02156       "DAHDISpan: %d\r\n"
02157       "DAHDIChannel: %s\r\n",
02158       chan->name,
02159       chan->uniqueid,
02160       p->span,
02161       ch_name);
02162 }
02163 
02164 #ifdef HAVE_PRI
02165 /*!
02166  * \internal
02167  * \brief Post an AMI DAHDI channel association event.
02168  * \since 1.8
02169  *
02170  * \param pvt DAHDI private pointer
02171  * \param chan Channel associated with the private pointer
02172  *
02173  * \return Nothing
02174  */
02175 static void my_ami_channel_event(void *pvt, struct ast_channel *chan)
02176 {
02177    struct dahdi_pvt *p = pvt;
02178 
02179    dahdi_ami_channel_event(p, chan);
02180 }
02181 #endif
02182 
02183 /* linear_mode = 0 - turn linear mode off, >0 - turn linear mode on
02184 *  returns the last value of the linear setting 
02185 */ 
02186 static int my_set_linear_mode(void *pvt, enum analog_sub sub, int linear_mode)
02187 {
02188    struct dahdi_pvt *p = pvt;
02189    int oldval;
02190    int idx = analogsub_to_dahdisub(sub);
02191    
02192    dahdi_setlinear(p->subs[idx].dfd, linear_mode);
02193    oldval = p->subs[idx].linear;
02194    p->subs[idx].linear = linear_mode ? 1 : 0;
02195    return oldval;
02196 }
02197 
02198 static void my_set_inthreeway(void *pvt, enum analog_sub sub, int inthreeway)
02199 {
02200    struct dahdi_pvt *p = pvt;
02201    int idx = analogsub_to_dahdisub(sub);
02202 
02203    p->subs[idx].inthreeway = inthreeway;
02204 }
02205 
02206 static int get_alarms(struct dahdi_pvt *p);
02207 static void handle_alarms(struct dahdi_pvt *p, int alms);
02208 static void my_get_and_handle_alarms(void *pvt)
02209 {
02210    int res;
02211    struct dahdi_pvt *p = pvt;
02212 
02213    res = get_alarms(p);
02214    handle_alarms(p, res);
02215 }
02216 
02217 static void *my_get_sigpvt_bridged_channel(struct ast_channel *chan)
02218 {
02219    struct dahdi_pvt *p = ast_bridged_channel(chan)->tech_pvt;
02220    if (p)
02221       return p->sig_pvt;
02222    else
02223       return NULL;
02224 }
02225 
02226 static int my_get_sub_fd(void *pvt, enum analog_sub sub)
02227 {
02228    struct dahdi_pvt *p = pvt;
02229    int dahdi_sub = analogsub_to_dahdisub(sub);
02230    return p->subs[dahdi_sub].dfd;
02231 }
02232 
02233 static void my_set_cadence(void *pvt, int *cid_rings, struct ast_channel *ast)
02234 {
02235    struct dahdi_pvt *p = pvt;
02236 
02237    /* Choose proper cadence */
02238    if ((p->distinctivering > 0) && (p->distinctivering <= num_cadence)) {
02239       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &cadences[p->distinctivering - 1]))
02240          ast_log(LOG_WARNING, "Unable to set distinctive ring cadence %d on '%s': %s\n", p->distinctivering, ast->name, strerror(errno));
02241       *cid_rings = cidrings[p->distinctivering - 1];
02242    } else {
02243       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, NULL))
02244          ast_log(LOG_WARNING, "Unable to reset default ring on '%s': %s\n", ast->name, strerror(errno));
02245       *cid_rings = p->sendcalleridafter;
02246    }
02247 }
02248 
02249 static void my_set_alarm(void *pvt, int in_alarm)
02250 {
02251    struct dahdi_pvt *p = pvt;
02252 
02253    p->inalarm = in_alarm;
02254 }
02255 
02256 static void my_set_dialing(void *pvt, int is_dialing)
02257 {
02258    struct dahdi_pvt *p = pvt;
02259 
02260    p->dialing = is_dialing;
02261 }
02262 
02263 static void my_set_outgoing(void *pvt, int is_outgoing)
02264 {
02265    struct dahdi_pvt *p = pvt;
02266 
02267    p->outgoing = is_outgoing;
02268 }
02269 
02270 #if defined(HAVE_PRI) || defined(HAVE_SS7)
02271 static void my_set_digital(void *pvt, int is_digital)
02272 {
02273    struct dahdi_pvt *p = pvt;
02274 
02275    p->digital = is_digital;
02276 }
02277 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
02278 
02279 #if defined(HAVE_SS7)
02280 static void my_set_inservice(void *pvt, int is_inservice)
02281 {
02282    struct dahdi_pvt *p = pvt;
02283 
02284    p->inservice = is_inservice;
02285 }
02286 #endif   /* defined(HAVE_SS7) */
02287 
02288 #if defined(HAVE_SS7)
02289 static void my_set_locallyblocked(void *pvt, int is_blocked)
02290 {
02291    struct dahdi_pvt *p = pvt;
02292 
02293    p->locallyblocked = is_blocked;
02294 }
02295 #endif   /* defined(HAVE_SS7) */
02296 
02297 #if defined(HAVE_SS7)
02298 static void my_set_remotelyblocked(void *pvt, int is_blocked)
02299 {
02300    struct dahdi_pvt *p = pvt;
02301 
02302    p->remotelyblocked = is_blocked;
02303 }
02304 #endif   /* defined(HAVE_SS7) */
02305 
02306 static void my_set_ringtimeout(void *pvt, int ringt)
02307 {
02308    struct dahdi_pvt *p = pvt;
02309    p->ringt = ringt;
02310 }
02311 
02312 static void my_set_waitingfordt(void *pvt, struct ast_channel *ast)
02313 {
02314    struct dahdi_pvt *p = pvt;
02315 
02316    if (p->waitfordialtone && CANPROGRESSDETECT(p) && p->dsp) {
02317       ast_log(LOG_DEBUG, "Defer dialing for %dms or dialtone\n", p->waitfordialtone);
02318       gettimeofday(&p->waitingfordt, NULL);
02319       ast_setstate(ast, AST_STATE_OFFHOOK);
02320    }
02321 }
02322 
02323 static int my_check_waitingfordt(void *pvt)
02324 {
02325    struct dahdi_pvt *p = pvt;
02326 
02327    if (p->waitingfordt.tv_usec) {
02328       return 1;
02329    }
02330 
02331    return 0;
02332 }
02333 
02334 static void my_set_confirmanswer(void *pvt, int flag)
02335 {
02336    struct dahdi_pvt *p = pvt;
02337    p->confirmanswer = flag;
02338 }
02339 
02340 static int my_check_confirmanswer(void *pvt)
02341 {
02342    struct dahdi_pvt *p = pvt;
02343    if (p->confirmanswer) {
02344       return 1;
02345    }
02346 
02347    return 0;
02348 }
02349 
02350 static void my_set_callwaiting(void *pvt, int callwaiting_enable)
02351 {
02352    struct dahdi_pvt *p = pvt;
02353 
02354    p->callwaiting = callwaiting_enable;
02355 }
02356 
02357 static void my_cancel_cidspill(void *pvt)
02358 {
02359    struct dahdi_pvt *p = pvt;
02360 
02361    ast_free(p->cidspill);
02362    p->cidspill = NULL;
02363    restore_conference(p);
02364 }
02365 
02366 static int my_confmute(void *pvt, int mute)
02367 {
02368    struct dahdi_pvt *p = pvt;
02369    return dahdi_confmute(p, mute);
02370 }
02371 
02372 static void my_set_pulsedial(void *pvt, int flag)
02373 {
02374    struct dahdi_pvt *p = pvt;
02375    p->pulsedial = flag;
02376 }
02377 
02378 static void my_set_new_owner(void *pvt, struct ast_channel *new_owner)
02379 {
02380    struct dahdi_pvt *p = pvt;
02381 
02382    p->owner = new_owner;
02383 }
02384 
02385 static const char *my_get_orig_dialstring(void *pvt)
02386 {
02387    struct dahdi_pvt *p = pvt;
02388 
02389    return p->dialstring;
02390 }
02391 
02392 static void my_increase_ss_count(void)
02393 {
02394    ast_mutex_lock(&ss_thread_lock);
02395    ss_thread_count++;
02396    ast_mutex_unlock(&ss_thread_lock);
02397 }
02398 
02399 static void my_decrease_ss_count(void)
02400 {
02401    ast_mutex_lock(&ss_thread_lock);
02402    ss_thread_count--;
02403    ast_cond_signal(&ss_thread_complete);
02404    ast_mutex_unlock(&ss_thread_lock);
02405 }
02406 
02407 static void my_all_subchannels_hungup(void *pvt)
02408 {
02409    struct dahdi_pvt *p = pvt;
02410    int res, law;
02411 
02412    p->faxhandled = 0;
02413    p->didtdd = 0;
02414 
02415    if (p->dsp) {
02416       ast_dsp_free(p->dsp);
02417       p->dsp = NULL;
02418    }
02419 
02420    p->law = p->law_default;
02421    law = p->law_default;
02422    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
02423    if (res < 0)
02424       ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
02425 
02426    dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
02427 
02428 #if 1
02429    {
02430    int i;
02431    p->owner = NULL;
02432    /* Cleanup owners here */
02433    for (i = 0; i < 3; i++) {
02434       p->subs[i].owner = NULL;
02435    }
02436    }
02437 #endif
02438 
02439    reset_conf(p);
02440    if (num_restart_pending == 0) {
02441       restart_monitor();
02442    }
02443 }
02444 
02445 static int conf_del(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index);
02446 
02447 static int my_conf_del(void *pvt, enum analog_sub sub)
02448 {
02449    struct dahdi_pvt *p = pvt;
02450    int x = analogsub_to_dahdisub(sub);
02451 
02452    return conf_del(p, &p->subs[x], x);
02453 }
02454 
02455 static int conf_add(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index, int slavechannel);
02456 
02457 static int my_conf_add(void *pvt, enum analog_sub sub)
02458 {
02459    struct dahdi_pvt *p = pvt;
02460    int x = analogsub_to_dahdisub(sub);
02461 
02462    return conf_add(p, &p->subs[x], x, 0);
02463 }
02464 
02465 static int isslavenative(struct dahdi_pvt *p, struct dahdi_pvt **out);
02466 
02467 static int my_complete_conference_update(void *pvt, int needconference)
02468 {
02469    struct dahdi_pvt *p = pvt;
02470    int needconf = needconference;
02471    int x;
02472    int useslavenative;
02473    struct dahdi_pvt *slave = NULL;
02474 
02475    useslavenative = isslavenative(p, &slave);
02476 
02477    /* If we have a slave, add him to our conference now. or DAX
02478       if this is slave native */
02479    for (x = 0; x < MAX_SLAVES; x++) {
02480       if (p->slaves[x]) {
02481          if (useslavenative)
02482             conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
02483          else {
02484             conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
02485             needconf++;
02486          }
02487       }
02488    }
02489    /* If we're supposed to be in there, do so now */
02490    if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
02491       if (useslavenative)
02492          conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
02493       else {
02494          conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
02495          needconf++;
02496       }
02497    }
02498    /* If we have a master, add ourselves to his conference */
02499    if (p->master) {
02500       if (isslavenative(p->master, NULL)) {
02501          conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
02502       } else {
02503          conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
02504       }
02505    }
02506    if (!needconf) {
02507       /* Nobody is left (or should be left) in our conference.
02508          Kill it. */
02509       p->confno = -1;
02510    }
02511 
02512    return 0;
02513 }
02514 
02515 static int check_for_conference(struct dahdi_pvt *p);
02516 
02517 static int my_check_for_conference(void *pvt)
02518 {
02519    struct dahdi_pvt *p = pvt;
02520    return check_for_conference(p);
02521 }
02522 
02523 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)
02524 {
02525    struct dahdi_pvt *p = pvt;
02526    int da, db;
02527    int tchan;
02528    int tinthreeway;
02529 
02530    da = analogsub_to_dahdisub(a);
02531    db = analogsub_to_dahdisub(b);
02532 
02533    tchan = p->subs[da].chan;
02534    p->subs[da].chan = p->subs[db].chan;
02535    p->subs[db].chan = tchan;
02536 
02537    tinthreeway = p->subs[da].inthreeway;
02538    p->subs[da].inthreeway = p->subs[db].inthreeway;
02539    p->subs[db].inthreeway = tinthreeway;
02540 
02541    p->subs[da].owner = ast_a;
02542    p->subs[db].owner = ast_b;
02543 
02544    if (ast_a)
02545       ast_channel_set_fd(ast_a, 0, p->subs[da].dfd);
02546    if (ast_b)
02547       ast_channel_set_fd(ast_b, 0, p->subs[db].dfd);
02548 
02549    wakeup_sub(p, a);
02550    wakeup_sub(p, b);
02551 
02552    return;
02553 }
02554 
02555 static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpbx, int idx, int law, const char *linkedid);
02556 
02557 static struct ast_channel *my_new_analog_ast_channel(void *pvt, int state, int startpbx, enum analog_sub sub, const struct ast_channel *requestor)
02558 {
02559    struct dahdi_pvt *p = pvt;
02560    int dsub = analogsub_to_dahdisub(sub);
02561 
02562    return dahdi_new(p, state, startpbx, dsub, 0, requestor ? requestor->linkedid : "");
02563 }
02564 
02565 #if defined(HAVE_PRI) || defined(HAVE_SS7)
02566 static int dahdi_setlaw(int dfd, int law)
02567 {
02568    int res;
02569    res = ioctl(dfd, DAHDI_SETLAW, &law);
02570    if (res)
02571       return res;
02572    return 0;
02573 }
02574 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
02575 
02576 #if defined(HAVE_PRI)
02577 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)
02578 {
02579    struct dahdi_pvt *p = pvt;
02580    int audio;
02581    int newlaw = -1;
02582 
02583    switch (p->sig) {
02584    case SIG_PRI_LIB_HANDLE_CASES:
02585       if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
02586          /* PRI nobch pseudo channel.  Does not handle ioctl(DAHDI_AUDIOMODE) */
02587          break;
02588       }
02589       /* Fall through */
02590    default:
02591       /* Set to audio mode at this point */
02592       audio = 1;
02593       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &audio) == -1) {
02594          ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n",
02595             p->channel, audio, strerror(errno));
02596       }
02597       break;
02598    }
02599 
02600    if (law != SIG_PRI_DEFLAW) {
02601       dahdi_setlaw(p->subs[SUB_REAL].dfd, (law == SIG_PRI_ULAW) ? DAHDI_LAW_MULAW : DAHDI_LAW_ALAW);
02602    }
02603 
02604    ast_copy_string(p->exten, exten, sizeof(p->exten));
02605 
02606    switch (law) {
02607       case SIG_PRI_DEFLAW:
02608          newlaw = 0;
02609          break;
02610       case SIG_PRI_ALAW:
02611          newlaw = DAHDI_LAW_ALAW;
02612          break;
02613       case SIG_PRI_ULAW:
02614          newlaw = DAHDI_LAW_MULAW;
02615          break;
02616    }
02617    return dahdi_new(p, state, 0, SUB_REAL, newlaw, requestor ? requestor->linkedid : "");
02618 }
02619 #endif   /* defined(HAVE_PRI) */
02620 
02621 static int set_actual_gain(int fd, float rxgain, float txgain, float rxdrc, float txdrc, int law);
02622 
02623 #if defined(HAVE_PRI) || defined(HAVE_SS7)
02624 /*!
02625  * \internal
02626  * \brief Open the PRI/SS7 channel media path.
02627  * \since 1.8
02628  *
02629  * \param p Channel private control structure.
02630  *
02631  * \return Nothing
02632  */
02633 static void my_pri_ss7_open_media(void *p)
02634 {
02635    struct dahdi_pvt *pvt = p;
02636    int res;
02637    int dfd;
02638    int set_val;
02639 
02640    dfd = pvt->subs[SUB_REAL].dfd;
02641 
02642    /* Open the media path. */
02643    set_val = 1;
02644    res = ioctl(dfd, DAHDI_AUDIOMODE, &set_val);
02645    if (res < 0) {
02646       ast_log(LOG_WARNING, "Unable to enable audio mode on channel %d (%s)\n",
02647          pvt->channel, strerror(errno));
02648    }
02649 
02650    /* Set correct companding law for this call. */
02651    res = dahdi_setlaw(dfd, pvt->law);
02652    if (res < 0) {
02653       ast_log(LOG_WARNING, "Unable to set law on channel %d\n", pvt->channel);
02654    }
02655 
02656    /* Set correct gain for this call. */
02657    if (pvt->digital) {
02658       res = set_actual_gain(dfd, 0, 0, pvt->rxdrc, pvt->txdrc, pvt->law);
02659    } else {
02660       res = set_actual_gain(dfd, pvt->rxgain, pvt->txgain, pvt->rxdrc, pvt->txdrc,
02661          pvt->law);
02662    }
02663    if (res < 0) {
02664       ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", pvt->channel);
02665    }
02666 
02667    if (pvt->dsp_features && pvt->dsp) {
02668       ast_dsp_set_features(pvt->dsp, pvt->dsp_features);
02669       pvt->dsp_features = 0;
02670    }
02671 }
02672 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
02673 
02674 #if defined(HAVE_PRI)
02675 /*!
02676  * \internal
02677  * \brief Ask DAHDI to dial the given dial string.
02678  * \since 1.8.11
02679  *
02680  * \param p Channel private control structure.
02681  * \param dial_string String to pass to DAHDI to dial.
02682  *
02683  * \note The channel private lock needs to be held when calling.
02684  *
02685  * \return Nothing
02686  */
02687 static void my_pri_dial_digits(void *p, const char *dial_string)
02688 {
02689    struct dahdi_dialoperation zo = {
02690       .op = DAHDI_DIAL_OP_APPEND,
02691    };
02692    struct dahdi_pvt *pvt = p;
02693    int res;
02694 
02695    snprintf(zo.dialstr, sizeof(zo.dialstr), "T%s", dial_string);
02696    ast_debug(1, "Channel %d: Sending '%s' to DAHDI_DIAL.\n", pvt->channel, zo.dialstr);
02697    res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo);
02698    if (res) {
02699       ast_log(LOG_WARNING, "Channel %d: Couldn't dial '%s': %s\n",
02700          pvt->channel, dial_string, strerror(errno));
02701    } else {
02702       pvt->dialing = 1;
02703    }
02704 }
02705 #endif   /* defined(HAVE_PRI) */
02706 
02707 static int unalloc_sub(struct dahdi_pvt *p, int x);
02708 
02709 static int my_unallocate_sub(void *pvt, enum analog_sub analogsub)
02710 {
02711    struct dahdi_pvt *p = pvt;
02712 
02713    return unalloc_sub(p, analogsub_to_dahdisub(analogsub));
02714 }
02715 
02716 static int alloc_sub(struct dahdi_pvt *p, int x);
02717 
02718 static int my_allocate_sub(void *pvt, enum analog_sub analogsub)
02719 {
02720    struct dahdi_pvt *p = pvt;
02721 
02722    return alloc_sub(p, analogsub_to_dahdisub(analogsub));
02723 }
02724 
02725 static int has_voicemail(struct dahdi_pvt *p);
02726 
02727 static int my_has_voicemail(void *pvt)
02728 {
02729    struct dahdi_pvt *p = pvt;
02730 
02731    return has_voicemail(p);
02732 }
02733 
02734 static int my_play_tone(void *pvt, enum analog_sub sub, enum analog_tone tone)
02735 {
02736    struct dahdi_pvt *p = pvt;
02737    int index;
02738 
02739    index = analogsub_to_dahdisub(sub);
02740 
02741    return tone_zone_play_tone(p->subs[index].dfd, analog_tone_to_dahditone(tone));
02742 }
02743 
02744 static enum analog_event dahdievent_to_analogevent(int event)
02745 {
02746    enum analog_event res;
02747 
02748    switch (event) {
02749    case DAHDI_EVENT_ONHOOK:
02750       res = ANALOG_EVENT_ONHOOK;
02751       break;
02752    case DAHDI_EVENT_RINGOFFHOOK:
02753       res = ANALOG_EVENT_RINGOFFHOOK;
02754       break;
02755    case DAHDI_EVENT_WINKFLASH:
02756       res = ANALOG_EVENT_WINKFLASH;
02757       break;
02758    case DAHDI_EVENT_ALARM:
02759       res = ANALOG_EVENT_ALARM;
02760       break;
02761    case DAHDI_EVENT_NOALARM:
02762       res = ANALOG_EVENT_NOALARM;
02763       break;
02764    case DAHDI_EVENT_DIALCOMPLETE:
02765       res = ANALOG_EVENT_DIALCOMPLETE;
02766       break;
02767    case DAHDI_EVENT_RINGERON:
02768       res = ANALOG_EVENT_RINGERON;
02769       break;
02770    case DAHDI_EVENT_RINGEROFF:
02771       res = ANALOG_EVENT_RINGEROFF;
02772       break;
02773    case DAHDI_EVENT_HOOKCOMPLETE:
02774       res = ANALOG_EVENT_HOOKCOMPLETE;
02775       break;
02776    case DAHDI_EVENT_PULSE_START:
02777       res = ANALOG_EVENT_PULSE_START;
02778       break;
02779    case DAHDI_EVENT_POLARITY:
02780       res = ANALOG_EVENT_POLARITY;
02781       break;
02782    case DAHDI_EVENT_RINGBEGIN:
02783       res = ANALOG_EVENT_RINGBEGIN;
02784       break;
02785    case DAHDI_EVENT_EC_DISABLED:
02786       res = ANALOG_EVENT_EC_DISABLED;
02787       break;
02788    case DAHDI_EVENT_REMOVED:
02789       res = ANALOG_EVENT_REMOVED;
02790       break;
02791    case DAHDI_EVENT_NEONMWI_ACTIVE:
02792       res = ANALOG_EVENT_NEONMWI_ACTIVE;
02793       break;
02794    case DAHDI_EVENT_NEONMWI_INACTIVE:
02795       res = ANALOG_EVENT_NEONMWI_INACTIVE;
02796       break;
02797 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
02798    case DAHDI_EVENT_TX_CED_DETECTED:
02799       res = ANALOG_EVENT_TX_CED_DETECTED;
02800       break;
02801    case DAHDI_EVENT_RX_CED_DETECTED:
02802       res = ANALOG_EVENT_RX_CED_DETECTED;
02803       break;
02804    case DAHDI_EVENT_EC_NLP_DISABLED:
02805       res = ANALOG_EVENT_EC_NLP_DISABLED;
02806       break;
02807    case DAHDI_EVENT_EC_NLP_ENABLED:
02808       res = ANALOG_EVENT_EC_NLP_ENABLED;
02809       break;
02810 #endif
02811    case DAHDI_EVENT_PULSEDIGIT:
02812       res = ANALOG_EVENT_PULSEDIGIT;
02813       break;
02814    case DAHDI_EVENT_DTMFDOWN:
02815       res = ANALOG_EVENT_DTMFDOWN;
02816       break;
02817    case DAHDI_EVENT_DTMFUP:
02818       res = ANALOG_EVENT_DTMFUP;
02819       break;
02820    default:
02821       switch(event & 0xFFFF0000) {
02822       case DAHDI_EVENT_PULSEDIGIT:
02823       case DAHDI_EVENT_DTMFDOWN:
02824       case DAHDI_EVENT_DTMFUP:
02825          /* The event includes a digit number in the low word.
02826           * Converting it to a 'enum analog_event' would remove
02827           * that information. Thus it is returned as-is.
02828           */
02829          return event;
02830       }
02831 
02832       res = ANALOG_EVENT_ERROR;
02833       break;
02834    }
02835 
02836    return res;
02837 }
02838 
02839 static inline int dahdi_wait_event(int fd);
02840 
02841 static int my_wait_event(void *pvt)
02842 {
02843    struct dahdi_pvt *p = pvt;
02844 
02845    return dahdi_wait_event(p->subs[SUB_REAL].dfd);
02846 }
02847 
02848 static int my_get_event(void *pvt)
02849 {
02850    struct dahdi_pvt *p = pvt;
02851    int res;
02852 
02853    if (p->fake_event) {
02854       res = p->fake_event;
02855       p->fake_event = 0;
02856    } else
02857       res = dahdi_get_event(p->subs[SUB_REAL].dfd);
02858 
02859    return dahdievent_to_analogevent(res);
02860 }
02861 
02862 static int my_is_off_hook(void *pvt)
02863 {
02864    struct dahdi_pvt *p = pvt;
02865    int res;
02866    struct dahdi_params par;
02867 
02868    memset(&par, 0, sizeof(par));
02869 
02870    if (p->subs[SUB_REAL].dfd > -1)
02871       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
02872    else {
02873       /* Assume not off hook on CVRS */
02874       res = 0;
02875       par.rxisoffhook = 0;
02876    }
02877    if (res) {
02878       ast_log(LOG_WARNING, "Unable to check hook state on channel %d: %s\n", p->channel, strerror(errno));
02879    }
02880 
02881    if ((p->sig == SIG_FXSKS) || (p->sig == SIG_FXSGS)) {
02882       /* When "onhook" that means no battery on the line, and thus
02883       it is out of service..., if it's on a TDM card... If it's a channel
02884       bank, there is no telling... */
02885       return (par.rxbits > -1) || par.rxisoffhook;
02886    }
02887 
02888    return par.rxisoffhook;
02889 }
02890 
02891 static void dahdi_enable_ec(struct dahdi_pvt *p);
02892 static void dahdi_disable_ec(struct dahdi_pvt *p);
02893 
02894 static int my_set_echocanceller(void *pvt, int enable)
02895 {
02896    struct dahdi_pvt *p = pvt;
02897 
02898    if (enable)
02899       dahdi_enable_ec(p);
02900    else
02901       dahdi_disable_ec(p);
02902 
02903    return 0;
02904 }
02905 
02906 static int dahdi_ring_phone(struct dahdi_pvt *p);
02907 
02908 static int my_ring(void *pvt)
02909 {
02910    struct dahdi_pvt *p = pvt;
02911 
02912    return dahdi_ring_phone(p);
02913 }
02914 
02915 static int my_flash(void *pvt)
02916 {
02917    struct dahdi_pvt *p = pvt;
02918    int func = DAHDI_FLASH;
02919    return ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &func);
02920 }
02921 
02922 static inline int dahdi_set_hook(int fd, int hs);
02923 
02924 static int my_off_hook(void *pvt)
02925 {
02926    struct dahdi_pvt *p = pvt;
02927    return dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
02928 }
02929 
02930 static void my_set_needringing(void *pvt, int value)
02931 {
02932    struct dahdi_pvt *p = pvt;
02933    p->subs[SUB_REAL].needringing = value;
02934 }
02935 
02936 static void my_set_polarity(void *pvt, int value)
02937 {
02938    struct dahdi_pvt *p = pvt;
02939 
02940    if (p->channel == CHAN_PSEUDO) {
02941       return;
02942    }
02943    p->polarity = value;
02944    ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETPOLARITY, &value);
02945 }
02946 
02947 static void my_start_polarityswitch(void *pvt)
02948 {
02949    struct dahdi_pvt *p = pvt;
02950 
02951    if (p->answeronpolarityswitch || p->hanguponpolarityswitch) {
02952       my_set_polarity(pvt, 0);
02953    }
02954 }
02955 
02956 static void my_answer_polarityswitch(void *pvt)
02957 {
02958    struct dahdi_pvt *p = pvt;
02959 
02960    if (!p->answeronpolarityswitch) {
02961       return;
02962    }
02963 
02964    my_set_polarity(pvt, 1);
02965 }
02966 
02967 static void my_hangup_polarityswitch(void *pvt)
02968 {
02969    struct dahdi_pvt *p = pvt;
02970 
02971    if (!p->hanguponpolarityswitch) {
02972       return;
02973    }
02974 
02975    if (p->answeronpolarityswitch) {
02976       my_set_polarity(pvt, 0);
02977    } else {
02978       my_set_polarity(pvt, 1);
02979    }
02980 }
02981 
02982 static int my_start(void *pvt)
02983 {
02984    struct dahdi_pvt *p = pvt;
02985    int x = DAHDI_START;
02986 
02987    return ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
02988 }
02989 
02990 static int my_dial_digits(void *pvt, enum analog_sub sub, struct analog_dialoperation *dop)
02991 {
02992    int index = analogsub_to_dahdisub(sub);
02993    int res;
02994    struct dahdi_pvt *p = pvt;
02995    struct dahdi_dialoperation ddop;
02996 
02997    if (dop->op != ANALOG_DIAL_OP_REPLACE) {
02998       ast_log(LOG_ERROR, "Fix the dial_digits callback!\n");
02999       return -1;
03000    }
03001 
03002    if (sub != ANALOG_SUB_REAL) {
03003       ast_log(LOG_ERROR, "Trying to dial_digits '%s' on channel %d subchannel %d\n",
03004          dop->dialstr, p->channel, sub);
03005       return -1;
03006    }
03007 
03008    ddop.op = DAHDI_DIAL_OP_REPLACE;
03009    ast_copy_string(ddop.dialstr, dop->dialstr, sizeof(ddop.dialstr));
03010 
03011    ast_debug(1, "Channel %d: Sending '%s' to DAHDI_DIAL.\n", p->channel, ddop.dialstr);
03012 
03013    res = ioctl(p->subs[index].dfd, DAHDI_DIAL, &ddop);
03014    if (res == -1) {
03015       ast_debug(1, "DAHDI_DIAL ioctl failed on %s: %s\n", p->owner->name, strerror(errno));
03016    }
03017 
03018    return res;
03019 }
03020 
03021 static void dahdi_train_ec(struct dahdi_pvt *p);
03022 
03023 static int my_train_echocanceller(void *pvt)
03024 {
03025    struct dahdi_pvt *p = pvt;
03026 
03027    dahdi_train_ec(p);
03028 
03029    return 0;
03030 }
03031 
03032 static int my_is_dialing(void *pvt, enum analog_sub sub)
03033 {
03034    struct dahdi_pvt *p = pvt;
03035    int index;
03036    int x;
03037 
03038    index = analogsub_to_dahdisub(sub);
03039 
03040    if (ioctl(p->subs[index].dfd, DAHDI_DIALING, &x)) {
03041       ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed!\n");
03042       return -1;
03043    }
03044 
03045    return x;
03046 }
03047 
03048 static int my_on_hook(void *pvt)
03049 {
03050    struct dahdi_pvt *p = pvt;
03051    return dahdi_set_hook(p->subs[ANALOG_SUB_REAL].dfd, DAHDI_ONHOOK);
03052 }
03053 
03054 #if defined(HAVE_PRI)
03055 static void my_pri_fixup_chans(void *chan_old, void *chan_new)
03056 {
03057    struct dahdi_pvt *old_chan = chan_old;
03058    struct dahdi_pvt *new_chan = chan_new;
03059 
03060    new_chan->owner = old_chan->owner;
03061    old_chan->owner = NULL;
03062    if (new_chan->owner) {
03063       new_chan->owner->tech_pvt = new_chan;
03064       new_chan->owner->fds[0] = new_chan->subs[SUB_REAL].dfd;
03065       new_chan->subs[SUB_REAL].owner = old_chan->subs[SUB_REAL].owner;
03066       old_chan->subs[SUB_REAL].owner = NULL;
03067    }
03068    /* Copy any DSP that may be present */
03069    new_chan->dsp = old_chan->dsp;
03070    new_chan->dsp_features = old_chan->dsp_features;
03071    old_chan->dsp = NULL;
03072    old_chan->dsp_features = 0;
03073 
03074    /* Transfer flags from the old channel. */
03075    new_chan->dialing = old_chan->dialing;
03076    new_chan->digital = old_chan->digital;
03077    new_chan->outgoing = old_chan->outgoing;
03078    old_chan->dialing = 0;
03079    old_chan->digital = 0;
03080    old_chan->outgoing = 0;
03081 
03082    /* More stuff to transfer to the new channel. */
03083    new_chan->law = old_chan->law;
03084    strcpy(new_chan->dialstring, old_chan->dialstring);
03085 }
03086 #endif   /* defined(HAVE_PRI) */
03087 
03088 #if defined(HAVE_PRI)
03089 static int sig_pri_tone_to_dahditone(enum sig_pri_tone tone)
03090 {
03091    switch (tone) {
03092    case SIG_PRI_TONE_RINGTONE:
03093       return DAHDI_TONE_RINGTONE;
03094    case SIG_PRI_TONE_STUTTER:
03095       return DAHDI_TONE_STUTTER;
03096    case SIG_PRI_TONE_CONGESTION:
03097       return DAHDI_TONE_CONGESTION;
03098    case SIG_PRI_TONE_DIALTONE:
03099       return DAHDI_TONE_DIALTONE;
03100    case SIG_PRI_TONE_DIALRECALL:
03101       return DAHDI_TONE_DIALRECALL;
03102    case SIG_PRI_TONE_INFO:
03103       return DAHDI_TONE_INFO;
03104    case SIG_PRI_TONE_BUSY:
03105       return DAHDI_TONE_BUSY;
03106    default:
03107       return -1;
03108    }
03109 }
03110 #endif   /* defined(HAVE_PRI) */
03111 
03112 #if defined(HAVE_PRI)
03113 static void my_handle_dchan_exception(struct sig_pri_span *pri, int index)
03114 {
03115    int x;
03116 
03117    ioctl(pri->fds[index], DAHDI_GETEVENT, &x);
03118    switch (x) {
03119    case DAHDI_EVENT_NONE:
03120       break;
03121    case DAHDI_EVENT_ALARM:
03122    case DAHDI_EVENT_NOALARM:
03123       if (sig_pri_is_alarm_ignored(pri)) {
03124          break;
03125       }
03126       /* Fall through */
03127    default:
03128       ast_log(LOG_NOTICE, "PRI got event: %s (%d) on D-channel of span %d\n",
03129          event2str(x), x, pri->span);
03130       break;
03131    }
03132    /* Keep track of alarm state */
03133    switch (x) {
03134    case DAHDI_EVENT_ALARM:
03135       pri_event_alarm(pri, index, 0);
03136       break;
03137    case DAHDI_EVENT_NOALARM:
03138       pri_event_noalarm(pri, index, 0);
03139       break;
03140    default:
03141       break;
03142    }
03143 }
03144 #endif   /* defined(HAVE_PRI) */
03145 
03146 #if defined(HAVE_PRI)
03147 static int my_pri_play_tone(void *pvt, enum sig_pri_tone tone)
03148 {
03149    struct dahdi_pvt *p = pvt;
03150 
03151    return tone_zone_play_tone(p->subs[SUB_REAL].dfd, sig_pri_tone_to_dahditone(tone));
03152 }
03153 #endif   /* defined(HAVE_PRI) */
03154 
03155 #if defined(HAVE_PRI) || defined(HAVE_SS7)
03156 /*!
03157  * \internal
03158  * \brief Set the caller id information.
03159  * \since 1.8
03160  *
03161  * \param pvt DAHDI private structure
03162  * \param caller Caller-id information to set.
03163  *
03164  * \return Nothing
03165  */
03166 static void my_set_callerid(void *pvt, const struct ast_party_caller *caller)
03167 {
03168    struct dahdi_pvt *p = pvt;
03169 
03170    ast_copy_string(p->cid_num,
03171       S_COR(caller->id.number.valid, caller->id.number.str, ""),
03172       sizeof(p->cid_num));
03173    ast_copy_string(p->cid_name,
03174       S_COR(caller->id.name.valid, caller->id.name.str, ""),
03175       sizeof(p->cid_name));
03176    ast_copy_string(p->cid_subaddr,
03177       S_COR(caller->id.subaddress.valid, caller->id.subaddress.str, ""),
03178       sizeof(p->cid_subaddr));
03179    p->cid_ton = caller->id.number.plan;
03180    p->callingpres = ast_party_id_presentation(&caller->id);
03181    if (caller->id.tag) {
03182       ast_copy_string(p->cid_tag, caller->id.tag, sizeof(p->cid_tag));
03183    }
03184    ast_copy_string(p->cid_ani,
03185       S_COR(caller->ani.number.valid, caller->ani.number.str, ""),
03186       sizeof(p->cid_ani));
03187    p->cid_ani2 = caller->ani2;
03188 }
03189 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
03190 
03191 #if defined(HAVE_PRI) || defined(HAVE_SS7)
03192 /*!
03193  * \internal
03194  * \brief Set the Dialed Number Identifier.
03195  * \since 1.8
03196  *
03197  * \param pvt DAHDI private structure
03198  * \param dnid Dialed Number Identifier string.
03199  *
03200  * \return Nothing
03201  */
03202 static void my_set_dnid(void *pvt, const char *dnid)
03203 {
03204    struct dahdi_pvt *p = pvt;
03205 
03206    ast_copy_string(p->dnid, dnid, sizeof(p->dnid));
03207 }
03208 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
03209 
03210 #if defined(HAVE_PRI)
03211 /*!
03212  * \internal
03213  * \brief Set the Redirecting Directory Number Information Service (RDNIS).
03214  * \since 1.8
03215  *
03216  * \param pvt DAHDI private structure
03217  * \param rdnis Redirecting Directory Number Information Service (RDNIS) string.
03218  *
03219  * \return Nothing
03220  */
03221 static void my_set_rdnis(void *pvt, const char *rdnis)
03222 {
03223    struct dahdi_pvt *p = pvt;
03224 
03225    ast_copy_string(p->rdnis, rdnis, sizeof(p->rdnis));
03226 }
03227 #endif   /* defined(HAVE_PRI) */
03228 
03229 #if defined(HAVE_PRI)
03230 /*!
03231  * \internal
03232  * \brief Make a dialstring for native ISDN CC to recall properly.
03233  * \since 1.8
03234  *
03235  * \param priv Channel private control structure.
03236  * \param buf Where to put the modified dialstring.
03237  * \param buf_size Size of modified dialstring buffer.
03238  *
03239  * \details
03240  * original dialstring:
03241  * DAHDI/[i<span>-](g|G|r|R)<group#(0-63)>[c|r<cadance#>|d][/extension[/options]]
03242  *
03243  * The modified dialstring will have prefixed the channel-group section
03244  * with the ISDN channel restriction.
03245  *
03246  * buf:
03247  * DAHDI/i<span>-(g|G|r|R)<group#(0-63)>[c|r<cadance#>|d][/extension[/options]]
03248  *
03249  * The routine will check to see if the ISDN channel restriction is already
03250  * in the original dialstring.
03251  *
03252  * \return Nothing
03253  */
03254 static void my_pri_make_cc_dialstring(void *priv, char *buf, size_t buf_size)
03255 {
03256    char *dial;
03257    struct dahdi_pvt *pvt;
03258    AST_DECLARE_APP_ARGS(args,
03259       AST_APP_ARG(tech);   /* channel technology token */
03260       AST_APP_ARG(group);  /* channel/group token */
03261       //AST_APP_ARG(ext);  /* extension token */
03262       //AST_APP_ARG(opts); /* options token */
03263       //AST_APP_ARG(other);   /* Any remining unused arguments */
03264    );
03265 
03266    pvt = priv;
03267    dial = ast_strdupa(pvt->dialstring);
03268    AST_NONSTANDARD_APP_ARGS(args, dial, '/');
03269    if (!args.tech) {
03270       ast_copy_string(buf, pvt->dialstring, buf_size);
03271       return;
03272    }
03273    if (!args.group) {
03274       /* Append the ISDN span channel restriction to the dialstring. */
03275       snprintf(buf, buf_size, "%s/i%d-", args.tech, pvt->pri->span);
03276       return;
03277    }
03278    if (isdigit(args.group[0]) || args.group[0] == 'i' || strchr(args.group, '!')) {
03279       /* The ISDN span channel restriction is not needed or already
03280        * in the dialstring. */
03281       ast_copy_string(buf, pvt->dialstring, buf_size);
03282       return;
03283    }
03284    /* Insert the ISDN span channel restriction into the dialstring. */
03285    snprintf(buf, buf_size, "%s/i%d-%s", args.tech, pvt->pri->span, args.group);
03286 }
03287 #endif   /* defined(HAVE_PRI) */
03288 
03289 #if defined(HAVE_PRI)
03290 /*!
03291  * \internal
03292  * \brief Reevaluate the PRI span device state.
03293  * \since 1.8
03294  *
03295  * \param pri Asterisk D channel control structure.
03296  *
03297  * \return Nothing
03298  *
03299  * \note Assumes the pri->lock is already obtained.
03300  */
03301 static void dahdi_pri_update_span_devstate(struct sig_pri_span *pri)
03302 {
03303    unsigned idx;
03304    unsigned num_b_chans;   /* Number of B channels provisioned on the span. */
03305    unsigned in_use;     /* Number of B channels in use on the span. */
03306    unsigned in_alarm;      /* TRUE if the span is in alarm condition. */
03307    enum ast_device_state new_state;
03308 
03309    /* Count the number of B channels and the number of B channels in use. */
03310    num_b_chans = 0;
03311    in_use = 0;
03312    in_alarm = 1;
03313    for (idx = pri->numchans; idx--;) {
03314       if (pri->pvts[idx] && !pri->pvts[idx]->no_b_channel) {
03315          /* This is a B channel interface. */
03316          ++num_b_chans;
03317          if (!sig_pri_is_chan_available(pri->pvts[idx])) {
03318             ++in_use;
03319          }
03320          if (!pri->pvts[idx]->inalarm) {
03321             /* There is a channel that is not in alarm. */
03322             in_alarm = 0;
03323          }
03324       }
03325    }
03326 
03327    /* Update the span congestion device state and report any change. */
03328    if (in_alarm) {
03329       new_state = AST_DEVICE_UNAVAILABLE;
03330    } else {
03331       new_state = num_b_chans == in_use ? AST_DEVICE_BUSY : AST_DEVICE_NOT_INUSE;
03332    }
03333    if (pri->congestion_devstate != new_state) {
03334       pri->congestion_devstate = new_state;
03335       ast_devstate_changed(AST_DEVICE_UNKNOWN, "DAHDI/I%d/congestion", pri->span);
03336    }
03337 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
03338    /* Update the span threshold device state and report any change. */
03339    if (in_alarm) {
03340       new_state = AST_DEVICE_UNAVAILABLE;
03341    } else if (!in_use) {
03342       new_state = AST_DEVICE_NOT_INUSE;
03343    } else if (!pri->user_busy_threshold) {
03344       new_state = in_use < num_b_chans ? AST_DEVICE_INUSE : AST_DEVICE_BUSY;
03345    } else {
03346       new_state = in_use < pri->user_busy_threshold ? AST_DEVICE_INUSE
03347          : AST_DEVICE_BUSY;
03348    }
03349    if (pri->threshold_devstate != new_state) {
03350       pri->threshold_devstate = new_state;
03351       ast_devstate_changed(AST_DEVICE_UNKNOWN, "DAHDI/I%d/threshold", pri->span);
03352    }
03353 #endif   /* defined(THRESHOLD_DEVSTATE_PLACEHOLDER) */
03354 }
03355 #endif   /* defined(HAVE_PRI) */
03356 
03357 #if defined(HAVE_PRI)
03358 /*!
03359  * \internal
03360  * \brief Reference this module.
03361  * \since 1.8
03362  *
03363  * \return Nothing
03364  */
03365 static void my_module_ref(void)
03366 {
03367    ast_module_ref(ast_module_info->self);
03368 }
03369 #endif   /* defined(HAVE_PRI) */
03370 
03371 #if defined(HAVE_PRI)
03372 /*!
03373  * \internal
03374  * \brief Unreference this module.
03375  * \since 1.8
03376  *
03377  * \return Nothing
03378  */
03379 static void my_module_unref(void)
03380 {
03381    ast_module_unref(ast_module_info->self);
03382 }
03383 #endif   /* defined(HAVE_PRI) */
03384 
03385 #if defined(HAVE_PRI)
03386 #if defined(HAVE_PRI_CALL_WAITING)
03387 static void my_pri_init_config(void *priv, struct sig_pri_span *pri);
03388 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
03389 static int dahdi_new_pri_nobch_channel(struct sig_pri_span *pri);
03390 
03391 static struct sig_pri_callback dahdi_pri_callbacks =
03392 {
03393    .handle_dchan_exception = my_handle_dchan_exception,
03394    .play_tone = my_pri_play_tone,
03395    .set_echocanceller = my_set_echocanceller,
03396    .dsp_reset_and_flush_digits = my_dsp_reset_and_flush_digits,
03397    .lock_private = my_lock_private,
03398    .unlock_private = my_unlock_private,
03399    .new_ast_channel = my_new_pri_ast_channel,
03400    .fixup_chans = my_pri_fixup_chans,
03401    .set_alarm = my_set_alarm,
03402    .set_dialing = my_set_dialing,
03403    .set_outgoing = my_set_outgoing,
03404    .set_digital = my_set_digital,
03405    .set_callerid = my_set_callerid,
03406    .set_dnid = my_set_dnid,
03407    .set_rdnis = my_set_rdnis,
03408    .new_nobch_intf = dahdi_new_pri_nobch_channel,
03409 #if defined(HAVE_PRI_CALL_WAITING)
03410    .init_config = my_pri_init_config,
03411 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
03412    .get_orig_dialstring = my_get_orig_dialstring,
03413    .make_cc_dialstring = my_pri_make_cc_dialstring,
03414    .update_span_devstate = dahdi_pri_update_span_devstate,
03415    .module_ref = my_module_ref,
03416    .module_unref = my_module_unref,
03417    .dial_digits = my_pri_dial_digits,
03418    .open_media = my_pri_ss7_open_media,
03419    .ami_channel_event = my_ami_channel_event,
03420 };
03421 #endif   /* defined(HAVE_PRI) */
03422 
03423 #if defined(HAVE_SS7)
03424 /*!
03425  * \internal
03426  * \brief Handle the SS7 link exception.
03427  * \since 1.8
03428  *
03429  * \param linkset Controlling linkset for the channel.
03430  * \param which Link index of the signaling channel.
03431  *
03432  * \return Nothing
03433  */
03434 static void my_handle_link_exception(struct sig_ss7_linkset *linkset, int which)
03435 {
03436    int event;
03437 
03438    if (ioctl(linkset->fds[which], DAHDI_GETEVENT, &event)) {
03439       ast_log(LOG_ERROR, "SS7: Error in exception retrieval on span %d/%d!\n",
03440          linkset->span, which);
03441       return;
03442    }
03443    switch (event) {
03444    case DAHDI_EVENT_NONE:
03445       break;
03446    case DAHDI_EVENT_ALARM:
03447       ast_log(LOG_ERROR, "SS7 got event: %s(%d) on span %d/%d\n",
03448          event2str(event), event, linkset->span, which);
03449       sig_ss7_link_alarm(linkset, which);
03450       break;
03451    case DAHDI_EVENT_NOALARM:
03452       ast_log(LOG_ERROR, "SS7 got event: %s(%d) on span %d/%d\n",
03453          event2str(event), event, linkset->span, which);
03454       sig_ss7_link_noalarm(linkset, which);
03455       break;
03456    default:
03457       ast_log(LOG_NOTICE, "SS7 got event: %s(%d) on span %d/%d\n",
03458          event2str(event), event, linkset->span, which);
03459       break;
03460    }
03461 }
03462 #endif   /* defined(HAVE_SS7) */
03463 
03464 #if defined(HAVE_SS7)
03465 static void my_ss7_set_loopback(void *pvt, int enable)
03466 {
03467    struct dahdi_pvt *p = pvt;
03468 
03469    if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_LOOPBACK, &enable)) {
03470       ast_log(LOG_WARNING, "Unable to set loopback on channel %d: %s\n", p->channel,
03471          strerror(errno));
03472    }
03473 }
03474 #endif   /* defined(HAVE_SS7) */
03475 
03476 #if defined(HAVE_SS7)
03477 /*!
03478  * \internal
03479  * \brief Create a new asterisk channel structure for SS7.
03480  * \since 1.8
03481  *
03482  * \param pvt Private channel structure.
03483  * \param state Initial state of new channel.
03484  * \param law Combanding law to use.
03485  * \param exten Dialplan extension for incoming call.
03486  * \param requestor Channel requesting this new channel.
03487  *
03488  * \retval ast_channel on success.
03489  * \retval NULL on error.
03490  */
03491 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)
03492 {
03493    struct dahdi_pvt *p = pvt;
03494    int audio;
03495    int newlaw;
03496 
03497    /* Set to audio mode at this point */
03498    audio = 1;
03499    if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &audio) == -1)
03500       ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n",
03501          p->channel, audio, strerror(errno));
03502 
03503    if (law != SIG_SS7_DEFLAW) {
03504       dahdi_setlaw(p->subs[SUB_REAL].dfd,
03505          (law == SIG_SS7_ULAW) ? DAHDI_LAW_MULAW : DAHDI_LAW_ALAW);
03506    }
03507 
03508    ast_copy_string(p->exten, exten, sizeof(p->exten));
03509 
03510    newlaw = -1;
03511    switch (law) {
03512    case SIG_SS7_DEFLAW:
03513       newlaw = 0;
03514       break;
03515    case SIG_SS7_ALAW:
03516       newlaw = DAHDI_LAW_ALAW;
03517       break;
03518    case SIG_SS7_ULAW:
03519       newlaw = DAHDI_LAW_MULAW;
03520       break;
03521    }
03522    return dahdi_new(p, state, 0, SUB_REAL, newlaw, requestor ? requestor->linkedid : "");
03523 }
03524 #endif   /* defined(HAVE_SS7) */
03525 
03526 #if defined(HAVE_SS7)
03527 static int sig_ss7_tone_to_dahditone(enum sig_ss7_tone tone)
03528 {
03529    switch (tone) {
03530    case SIG_SS7_TONE_RINGTONE:
03531       return DAHDI_TONE_RINGTONE;
03532    case SIG_SS7_TONE_STUTTER:
03533       return DAHDI_TONE_STUTTER;
03534    case SIG_SS7_TONE_CONGESTION:
03535       return DAHDI_TONE_CONGESTION;
03536    case SIG_SS7_TONE_DIALTONE:
03537       return DAHDI_TONE_DIALTONE;
03538    case SIG_SS7_TONE_DIALRECALL:
03539       return DAHDI_TONE_DIALRECALL;
03540    case SIG_SS7_TONE_INFO:
03541       return DAHDI_TONE_INFO;
03542    case SIG_SS7_TONE_BUSY:
03543       return DAHDI_TONE_BUSY;
03544    default:
03545       return -1;
03546    }
03547 }
03548 #endif   /* defined(HAVE_SS7) */
03549 
03550 #if defined(HAVE_SS7)
03551 static int my_ss7_play_tone(void *pvt, enum sig_ss7_tone tone)
03552 {
03553    struct dahdi_pvt *p = pvt;
03554 
03555    return tone_zone_play_tone(p->subs[SUB_REAL].dfd, sig_ss7_tone_to_dahditone(tone));
03556 }
03557 #endif   /* defined(HAVE_SS7) */
03558 
03559 #if defined(HAVE_SS7)
03560 static struct sig_ss7_callback dahdi_ss7_callbacks =
03561 {
03562    .lock_private = my_lock_private,
03563    .unlock_private = my_unlock_private,
03564 
03565    .set_echocanceller = my_set_echocanceller,
03566    .set_loopback = my_ss7_set_loopback,
03567 
03568    .new_ast_channel = my_new_ss7_ast_channel,
03569    .play_tone = my_ss7_play_tone,
03570 
03571    .handle_link_exception = my_handle_link_exception,
03572    .set_alarm = my_set_alarm,
03573    .set_dialing = my_set_dialing,
03574    .set_outgoing = my_set_outgoing,
03575    .set_digital = my_set_digital,
03576    .set_inservice = my_set_inservice,
03577    .set_locallyblocked = my_set_locallyblocked,
03578    .set_remotelyblocked = my_set_remotelyblocked,
03579    .set_callerid = my_set_callerid,
03580    .set_dnid = my_set_dnid,
03581    .open_media = my_pri_ss7_open_media,
03582 };
03583 #endif   /* defined(HAVE_SS7) */
03584 
03585 /*!
03586  * \brief Send MWI state change
03587  *
03588  * \arg mailbox_full This is the mailbox associated with the FXO line that the
03589  *      MWI state has changed on.
03590  * \arg thereornot This argument should simply be set to 1 or 0, to indicate
03591  *      whether there are messages waiting or not.
03592  *
03593  *  \return nothing
03594  *
03595  * This function does two things:
03596  *
03597  * 1) It generates an internal Asterisk event notifying any other module that
03598  *    cares about MWI that the state of a mailbox has changed.
03599  *
03600  * 2) It runs the script specified by the mwimonitornotify option to allow
03601  *    some custom handling of the state change.
03602  */
03603 static void notify_message(char *mailbox_full, int thereornot)
03604 {
03605    char s[sizeof(mwimonitornotify) + 80];
03606    struct ast_event *event;
03607    char *mailbox, *context;
03608 
03609    /* Strip off @default */
03610    context = mailbox = ast_strdupa(mailbox_full);
03611    strsep(&context, "@");
03612    if (ast_strlen_zero(context))
03613       context = "default";
03614 
03615    if (!(event = ast_event_new(AST_EVENT_MWI,
03616          AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
03617          AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
03618          AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot,
03619          AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot,
03620          AST_EVENT_IE_END))) {
03621       return;
03622    }
03623 
03624    ast_event_queue_and_cache(event);
03625 
03626    if (!ast_strlen_zero(mailbox) && !ast_strlen_zero(mwimonitornotify)) {
03627       snprintf(s, sizeof(s), "%s %s %d", mwimonitornotify, mailbox, thereornot);
03628       ast_safe_system(s);
03629    }
03630 }
03631 
03632 static void my_handle_notify_message(struct ast_channel *chan, void *pvt, int cid_flags, int neon_mwievent)
03633 {
03634    struct dahdi_pvt *p = pvt;
03635 
03636    if (neon_mwievent > -1 && !p->mwimonitor_neon)
03637       return;
03638 
03639    if (neon_mwievent == ANALOG_EVENT_NEONMWI_ACTIVE || cid_flags & CID_MSGWAITING) {
03640       ast_log(LOG_NOTICE, "MWI: Channel %d message waiting, mailbox %s\n", p->channel, p->mailbox);
03641       notify_message(p->mailbox, 1);
03642    } else if (neon_mwievent == ANALOG_EVENT_NEONMWI_INACTIVE || cid_flags & CID_NOMSGWAITING) {
03643       ast_log(LOG_NOTICE, "MWI: Channel %d no message waiting, mailbox %s\n", p->channel, p->mailbox);
03644       notify_message(p->mailbox, 0);
03645    }
03646    /* If the CID had Message waiting payload, assume that this for MWI only and hangup the call */
03647    /* If generated using Ring Pulse Alert, then ring has been answered as a call and needs to be hungup */
03648    if (neon_mwievent == -1 && p->mwimonitor_rpas) {
03649       ast_hangup(chan);
03650       return;
03651    }
03652 }
03653 
03654 static int my_have_progressdetect(void *pvt)
03655 {
03656    struct dahdi_pvt *p = pvt;
03657 
03658    if ((p->callprogress & CALLPROGRESS_PROGRESS)
03659       && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
03660       return 1;
03661    } else {
03662       /* Don't have progress detection. */
03663       return 0;
03664    }
03665 }
03666 
03667 static struct analog_callback dahdi_analog_callbacks =
03668 {
03669    .play_tone = my_play_tone,
03670    .get_event = my_get_event,
03671    .wait_event = my_wait_event,
03672    .is_off_hook = my_is_off_hook,
03673    .set_echocanceller = my_set_echocanceller,
03674    .ring = my_ring,
03675    .flash = my_flash,
03676    .off_hook = my_off_hook,
03677    .dial_digits = my_dial_digits,
03678    .train_echocanceller = my_train_echocanceller,
03679    .on_hook = my_on_hook,
03680    .is_dialing = my_is_dialing,
03681    .allocate_sub = my_allocate_sub,
03682    .unallocate_sub = my_unallocate_sub,
03683    .swap_subs = my_swap_subchannels,
03684    .has_voicemail = my_has_voicemail,
03685    .check_for_conference = my_check_for_conference,
03686    .conf_add = my_conf_add,
03687    .conf_del = my_conf_del,
03688    .complete_conference_update = my_complete_conference_update,
03689    .start = my_start,
03690    .all_subchannels_hungup = my_all_subchannels_hungup,
03691    .lock_private = my_lock_private,
03692    .unlock_private = my_unlock_private,
03693    .deadlock_avoidance_private = my_deadlock_avoidance_private,
03694    .handle_dtmf = my_handle_dtmf,
03695    .wink = my_wink,
03696    .new_ast_channel = my_new_analog_ast_channel,
03697    .dsp_set_digitmode = my_dsp_set_digitmode,
03698    .dsp_reset_and_flush_digits = my_dsp_reset_and_flush_digits,
03699    .send_callerid = my_send_callerid,
03700    .callwait = my_callwait,
03701    .stop_callwait = my_stop_callwait,
03702    .get_callerid = my_get_callerid,
03703    .start_cid_detect = my_start_cid_detect,
03704    .stop_cid_detect = my_stop_cid_detect,
03705    .handle_notify_message = my_handle_notify_message,
03706    .increase_ss_count = my_increase_ss_count,
03707    .decrease_ss_count = my_decrease_ss_count,
03708    .distinctive_ring = my_distinctive_ring,
03709    .set_linear_mode = my_set_linear_mode,
03710    .set_inthreeway = my_set_inthreeway,
03711    .get_and_handle_alarms = my_get_and_handle_alarms,
03712    .get_sigpvt_bridged_channel = my_get_sigpvt_bridged_channel,
03713    .get_sub_fd = my_get_sub_fd,
03714    .set_cadence = my_set_cadence,
03715    .set_alarm = my_set_alarm,
03716    .set_dialing = my_set_dialing,
03717    .set_outgoing = my_set_outgoing,
03718    .set_ringtimeout = my_set_ringtimeout,
03719    .set_waitingfordt = my_set_waitingfordt,
03720    .check_waitingfordt = my_check_waitingfordt,
03721    .set_confirmanswer = my_set_confirmanswer,
03722    .check_confirmanswer = my_check_confirmanswer,
03723    .set_callwaiting = my_set_callwaiting,
03724    .cancel_cidspill = my_cancel_cidspill,
03725    .confmute = my_confmute,
03726    .set_pulsedial = my_set_pulsedial,
03727    .set_new_owner = my_set_new_owner,
03728    .get_orig_dialstring = my_get_orig_dialstring,
03729    .set_needringing = my_set_needringing,
03730    .set_polarity = my_set_polarity,
03731    .start_polarityswitch = my_start_polarityswitch,
03732    .answer_polarityswitch = my_answer_polarityswitch,
03733    .hangup_polarityswitch = my_hangup_polarityswitch,
03734    .have_progressdetect = my_have_progressdetect,
03735 };
03736 
03737 /*! Round robin search locations. */
03738 static struct dahdi_pvt *round_robin[32];
03739 
03740 #define dahdi_get_index(ast, p, nullok)   _dahdi_get_index(ast, p, nullok, __PRETTY_FUNCTION__, __LINE__)
03741 static int _dahdi_get_index(struct ast_channel *ast, struct dahdi_pvt *p, int nullok, const char *fname, unsigned long line)
03742 {
03743    int res;
03744    if (p->subs[SUB_REAL].owner == ast)
03745       res = 0;
03746    else if (p->subs[SUB_CALLWAIT].owner == ast)
03747       res = 1;
03748    else if (p->subs[SUB_THREEWAY].owner == ast)
03749       res = 2;
03750    else {
03751       res = -1;
03752       if (!nullok)
03753          ast_log(LOG_WARNING,
03754             "Unable to get index for '%s' on channel %d (%s(), line %lu)\n",
03755             ast ? ast->name : "", p->channel, fname, line);
03756    }
03757    return res;
03758 }
03759 
03760 /*!
03761  * \internal
03762  * \brief Obtain the specified subchannel owner lock if the owner exists.
03763  *
03764  * \param pvt Channel private struct.
03765  * \param sub_idx Subchannel owner to lock.
03766  *
03767  * \note Assumes the pvt->lock is already obtained.
03768  *
03769  * \note
03770  * Because deadlock avoidance may have been necessary, you need to confirm
03771  * the state of things before continuing.
03772  *
03773  * \return Nothing
03774  */
03775 static void dahdi_lock_sub_owner(struct dahdi_pvt *pvt, int sub_idx)
03776 {
03777    for (;;) {
03778       if (!pvt->subs[sub_idx].owner) {
03779          /* No subchannel owner pointer */
03780          break;
03781       }
03782       if (!ast_channel_trylock(pvt->subs[sub_idx].owner)) {
03783          /* Got subchannel owner lock */
03784          break;
03785       }
03786       /* We must unlock the private to avoid the possibility of a deadlock */
03787       DEADLOCK_AVOIDANCE(&pvt->lock);
03788    }
03789 }
03790 
03791 static void wakeup_sub(struct dahdi_pvt *p, int a)
03792 {
03793    dahdi_lock_sub_owner(p, a);
03794    if (p->subs[a].owner) {
03795       ast_queue_frame(p->subs[a].owner, &ast_null_frame);
03796       ast_channel_unlock(p->subs[a].owner);
03797    }
03798 }
03799 
03800 static void dahdi_queue_frame(struct dahdi_pvt *p, struct ast_frame *f)
03801 {
03802    for (;;) {
03803       if (p->owner) {
03804          if (ast_channel_trylock(p->owner)) {
03805             DEADLOCK_AVOIDANCE(&p->lock);
03806          } else {
03807             ast_queue_frame(p->owner, f);
03808             ast_channel_unlock(p->owner);
03809             break;
03810          }
03811       } else
03812          break;
03813    }
03814 }
03815 
03816 static void handle_clear_alarms(struct dahdi_pvt *p)
03817 {
03818 #if defined(HAVE_PRI)
03819    if (dahdi_sig_pri_lib_handles(p->sig) && sig_pri_is_alarm_ignored(p->pri)) {
03820       return;
03821    }
03822 #endif   /* defined(HAVE_PRI) */
03823 
03824    if (report_alarms & REPORT_CHANNEL_ALARMS) {
03825       ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel);
03826       manager_event(EVENT_FLAG_SYSTEM, "AlarmClear", "Channel: %d\r\n", p->channel);
03827    }
03828    if (report_alarms & REPORT_SPAN_ALARMS && p->manages_span_alarms) {
03829       ast_log(LOG_NOTICE, "Alarm cleared on span %d\n", p->span);
03830       manager_event(EVENT_FLAG_SYSTEM, "SpanAlarmClear", "Span: %d\r\n", p->span);
03831    }
03832 }
03833 
03834 #ifdef HAVE_OPENR2
03835 
03836 static int dahdi_r2_answer(struct dahdi_pvt *p)
03837 {
03838    int res = 0;
03839    /* openr2 1.1.0 and older does not even define OR2_LIB_INTERFACE
03840    * and does not has support for openr2_chan_answer_call_with_mode
03841    *  */
03842 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
03843    const char *double_answer = pbx_builtin_getvar_helper(p->owner, "MFCR2_DOUBLE_ANSWER");
03844    int wants_double_answer = ast_true(double_answer) ? 1 : 0;
03845    if (!double_answer) {
03846       /* this still can result in double answer if the channel context
03847       * was configured that way */
03848       res = openr2_chan_answer_call(p->r2chan);
03849    } else if (wants_double_answer) {
03850       res = openr2_chan_answer_call_with_mode(p->r2chan, OR2_ANSWER_DOUBLE);
03851    } else {
03852       res = openr2_chan_answer_call_with_mode(p->r2chan, OR2_ANSWER_SIMPLE);
03853    }
03854 #else
03855    res = openr2_chan_answer_call(p->r2chan);
03856 #endif
03857    return res;
03858 }
03859 
03860 
03861 
03862 /* should be called with the ast_channel locked */
03863 static openr2_calling_party_category_t dahdi_r2_get_channel_category(struct ast_channel *c)
03864 {
03865    openr2_calling_party_category_t cat;
03866    const char *catstr = pbx_builtin_getvar_helper(c, "MFCR2_CATEGORY");
03867    struct dahdi_pvt *p = c->tech_pvt;
03868    if (ast_strlen_zero(catstr)) {
03869       ast_debug(1, "No MFC/R2 category specified for chan %s, using default %s\n",
03870             c->name, openr2_proto_get_category_string(p->mfcr2_category));
03871       return p->mfcr2_category;
03872    }
03873    if ((cat = openr2_proto_get_category(catstr)) == OR2_CALLING_PARTY_CATEGORY_UNKNOWN) {
03874       ast_log(LOG_WARNING, "Invalid category specified '%s' for chan %s, using default %s\n",
03875             catstr, c->name, openr2_proto_get_category_string(p->mfcr2_category));
03876       return p->mfcr2_category;
03877    }
03878    ast_debug(1, "Using category %s\n", catstr);
03879    return cat;
03880 }
03881 
03882 static void dahdi_r2_on_call_init(openr2_chan_t *r2chan)
03883 {
03884    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
03885    ast_mutex_lock(&p->lock);
03886    if (p->mfcr2call) {
03887       ast_mutex_unlock(&p->lock);
03888       /* TODO: This can happen when some other thread just finished dahdi_request requesting this very same
03889          interface but has not yet seized the line (dahdi_call), and the far end wins and seize the line,
03890          can we avoid this somehow?, at this point when dahdi_call send the seize, it is likely that since
03891          the other end will see our seize as a forced release and drop the call, we will see an invalid
03892          pattern that will be seen and treated as protocol error. */
03893       ast_log(LOG_ERROR, "Collision of calls on chan %d detected!.\n", openr2_chan_get_number(r2chan));
03894       return;
03895    }
03896    p->mfcr2call = 1;
03897    /* better safe than sorry ... */
03898    p->cid_name[0] = '\0';
03899    p->cid_num[0] = '\0';
03900    p->cid_subaddr[0] = '\0';
03901    p->rdnis[0] = '\0';
03902    p->exten[0] = '\0';
03903    p->mfcr2_ani_index = '\0';
03904    p->mfcr2_dnis_index = '\0';
03905    p->mfcr2_dnis_matched = 0;
03906    p->mfcr2_answer_pending = 0;
03907    p->mfcr2_call_accepted = 0;
03908    ast_mutex_unlock(&p->lock);
03909    ast_verbose("New MFC/R2 call detected on chan %d.\n", openr2_chan_get_number(r2chan));
03910 }
03911 
03912 static void dahdi_r2_on_hardware_alarm(openr2_chan_t *r2chan, int alarm)
03913 {
03914    int res;
03915    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
03916    ast_mutex_lock(&p->lock);
03917    p->inalarm = alarm ? 1 : 0;
03918    if (p->inalarm) {
03919       res = get_alarms(p);
03920       handle_alarms(p, res);
03921    } else {
03922       handle_clear_alarms(p);
03923    }
03924    ast_mutex_unlock(&p->lock);
03925 }
03926 
03927 static void dahdi_r2_on_os_error(openr2_chan_t *r2chan, int errorcode)
03928 {
03929    ast_log(LOG_ERROR, "OS error on chan %d: %s\n", openr2_chan_get_number(r2chan), strerror(errorcode));
03930 }
03931 
03932 static void dahdi_r2_on_protocol_error(openr2_chan_t *r2chan, openr2_protocol_error_t reason)
03933 {
03934    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
03935    ast_log(LOG_ERROR, "MFC/R2 protocol error on chan %d: %s\n", openr2_chan_get_number(r2chan), openr2_proto_get_error(reason));
03936    if (p->owner) {
03937       p->owner->hangupcause = AST_CAUSE_PROTOCOL_ERROR;
03938       p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
03939    }
03940    ast_mutex_lock(&p->lock);
03941    p->mfcr2call = 0;
03942    ast_mutex_unlock(&p->lock);
03943 }
03944 
03945 static void dahdi_r2_disconnect_call(struct dahdi_pvt *p, openr2_call_disconnect_cause_t cause)
03946 {
03947    if (openr2_chan_disconnect_call(p->r2chan, cause)) {
03948       ast_log(LOG_NOTICE, "Bad! failed to disconnect call on channel %d with reason %s, hope for the best!\n",
03949          p->channel, openr2_proto_get_disconnect_string(cause));
03950       /* force the chan to idle and release the call flag now since we will not see a clean on_call_end */
03951       openr2_chan_set_idle(p->r2chan);
03952       ast_mutex_lock(&p->lock);
03953       p->mfcr2call = 0;
03954       ast_mutex_unlock(&p->lock);
03955    }
03956 }
03957 
03958 static void dahdi_r2_on_call_offered(openr2_chan_t *r2chan, const char *ani, const char *dnis, openr2_calling_party_category_t category)
03959 {
03960    struct dahdi_pvt *p;
03961    struct ast_channel *c;
03962    ast_verbose("MFC/R2 call offered on chan %d. ANI = %s, DNIS = %s, Category = %s\n",
03963          openr2_chan_get_number(r2chan), ani ? ani : "(restricted)", dnis,
03964          openr2_proto_get_category_string(category));
03965    p = openr2_chan_get_client_data(r2chan);
03966    /* if collect calls are not allowed and this is a collect call, reject it! */
03967    if (!p->mfcr2_allow_collect_calls && category == OR2_CALLING_PARTY_CATEGORY_COLLECT_CALL) {
03968       ast_log(LOG_NOTICE, "Rejecting MFC/R2 collect call\n");
03969       dahdi_r2_disconnect_call(p, OR2_CAUSE_COLLECT_CALL_REJECTED);
03970       return;
03971    }
03972    ast_mutex_lock(&p->lock);
03973    p->mfcr2_recvd_category = category;
03974    /* if we're not supposed to use CID, clear whatever we have */
03975    if (!p->use_callerid) {
03976       ast_log(LOG_DEBUG, "No CID allowed in configuration, CID is being cleared!\n");
03977       p->cid_num[0] = 0;
03978       p->cid_name[0] = 0;
03979    }
03980    /* if we're supposed to answer immediately, clear DNIS and set 's' exten */
03981    if (p->immediate || !openr2_context_get_max_dnis(openr2_chan_get_context(r2chan))) {
03982       ast_log(LOG_DEBUG, "Setting exten => s because of immediate or 0 DNIS configured\n");
03983       p->exten[0] = 's';
03984       p->exten[1] = 0;
03985    }
03986    ast_mutex_unlock(&p->lock);
03987    if (!ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
03988       ast_log(LOG_NOTICE, "MFC/R2 call on channel %d requested non-existent extension '%s' in context '%s'. Rejecting call.\n",
03989             p->channel, p->exten, p->context);
03990       dahdi_r2_disconnect_call(p, OR2_CAUSE_UNALLOCATED_NUMBER);
03991       return;
03992    }
03993    if (!p->mfcr2_accept_on_offer) {
03994       /* The user wants us to start the PBX thread right away without accepting the call first */
03995       c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, NULL);
03996       if (c) {
03997          /* Done here, don't disable reading now since we still need to generate MF tones to accept
03998             the call or reject it and detect the tone off condition of the other end, all of this
03999             will be done in the PBX thread now */
04000          return;
04001       }
04002       ast_log(LOG_WARNING, "Unable to create PBX channel in DAHDI channel %d\n", p->channel);
04003       dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER);
04004    } else if (p->mfcr2_charge_calls) {
04005       ast_log(LOG_DEBUG, "Accepting MFC/R2 call with charge on chan %d\n", p->channel);
04006       openr2_chan_accept_call(r2chan, OR2_CALL_WITH_CHARGE);
04007    } else {
04008       ast_log(LOG_DEBUG, "Accepting MFC/R2 call with no charge on chan %d\n", p->channel);
04009       openr2_chan_accept_call(r2chan, OR2_CALL_NO_CHARGE);
04010    }
04011 }
04012 
04013 static void dahdi_r2_on_call_end(openr2_chan_t *r2chan)
04014 {
04015    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04016    ast_verbose("MFC/R2 call end on channel %d\n", p->channel);
04017    ast_mutex_lock(&p->lock);
04018    p->mfcr2call = 0;
04019    ast_mutex_unlock(&p->lock);
04020 }
04021 
04022 static void dahdi_enable_ec(struct dahdi_pvt *p);
04023 static void dahdi_r2_on_call_accepted(openr2_chan_t *r2chan, openr2_call_mode_t mode)
04024 {
04025    struct dahdi_pvt *p = NULL;
04026    struct ast_channel *c = NULL;
04027    p = openr2_chan_get_client_data(r2chan);
04028    dahdi_enable_ec(p);
04029    p->mfcr2_call_accepted = 1;
04030    /* if it's an incoming call ... */
04031    if (OR2_DIR_BACKWARD == openr2_chan_get_direction(r2chan)) {
04032       ast_verbose("MFC/R2 call has been accepted on backward channel %d\n", openr2_chan_get_number(r2chan));
04033       /* If accept on offer is not set, it means at this point the PBX thread is already
04034          launched (was launched in the 'on call offered' handler) and therefore this callback
04035          is being executed already in the PBX thread rather than the monitor thread, don't launch
04036          any other thread, just disable the openr2 reading and answer the call if needed */
04037       if (!p->mfcr2_accept_on_offer) {
04038          openr2_chan_disable_read(r2chan);
04039          if (p->mfcr2_answer_pending) {
04040             ast_log(LOG_DEBUG, "Answering MFC/R2 call after accepting it on chan %d\n", openr2_chan_get_number(r2chan));
04041             dahdi_r2_answer(p);
04042          }
04043          return;
04044       }
04045       c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, NULL);
04046       if (c) {
04047          /* chan_dahdi will take care of reading from now on in the PBX thread, tell the
04048             library to forget about it */
04049          openr2_chan_disable_read(r2chan);
04050          return;
04051       }
04052       ast_log(LOG_WARNING, "Unable to create PBX channel in DAHDI channel %d\n", p->channel);
04053       /* failed to create the channel, bail out and report it as an out of order line */
04054       dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER);
04055       return;
04056    }
04057    /* this is an outgoing call, no need to launch the PBX thread, most likely we're in one already */
04058    ast_verbose("MFC/R2 call has been accepted on forward channel %d\n", p->channel);
04059    p->subs[SUB_REAL].needringing = 1;
04060    p->dialing = 0;
04061    /* chan_dahdi will take care of reading from now on in the PBX thread, tell the library to forget about it */
04062    openr2_chan_disable_read(r2chan);
04063 }
04064 
04065 static void dahdi_r2_on_call_answered(openr2_chan_t *r2chan)
04066 {
04067    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04068    ast_verbose("MFC/R2 call has been answered on channel %d\n", openr2_chan_get_number(r2chan));
04069    p->subs[SUB_REAL].needanswer = 1;
04070 }
04071 
04072 static void dahdi_r2_on_call_read(openr2_chan_t *r2chan, const unsigned char *buf, int buflen)
04073 {
04074    /*ast_log(LOG_DEBUG, "Read data from dahdi channel %d\n", openr2_chan_get_number(r2chan));*/
04075 }
04076 
04077 static int dahdi_r2_cause_to_ast_cause(openr2_call_disconnect_cause_t cause)
04078 {
04079    switch (cause) {
04080    case OR2_CAUSE_BUSY_NUMBER:
04081       return AST_CAUSE_BUSY;
04082    case OR2_CAUSE_NETWORK_CONGESTION:
04083       return AST_CAUSE_CONGESTION;
04084    case OR2_CAUSE_OUT_OF_ORDER:
04085       return AST_CAUSE_DESTINATION_OUT_OF_ORDER;
04086    case OR2_CAUSE_UNALLOCATED_NUMBER:
04087       return AST_CAUSE_UNREGISTERED;
04088    case OR2_CAUSE_NO_ANSWER:
04089       return AST_CAUSE_NO_ANSWER;
04090    case OR2_CAUSE_NORMAL_CLEARING:
04091       return AST_CAUSE_NORMAL_CLEARING;
04092    case OR2_CAUSE_UNSPECIFIED:
04093    default:
04094       return AST_CAUSE_NOTDEFINED;
04095    }
04096 }
04097 
04098 static void dahdi_r2_on_call_disconnect(openr2_chan_t *r2chan, openr2_call_disconnect_cause_t cause)
04099 {
04100    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04101    ast_verbose("MFC/R2 call disconnected on channel %d\n", openr2_chan_get_number(r2chan));
04102    ast_mutex_lock(&p->lock);
04103    if (!p->owner) {
04104       ast_mutex_unlock(&p->lock);
04105       /* no owner, therefore we can't use dahdi_hangup to disconnect, do it right now */
04106       dahdi_r2_disconnect_call(p, OR2_CAUSE_NORMAL_CLEARING);
04107       return;
04108    }
04109    /* when we have an owner we don't call dahdi_r2_disconnect_call here, that will
04110       be done in dahdi_hangup */
04111    if (p->owner->_state == AST_STATE_UP) {
04112       p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
04113       ast_mutex_unlock(&p->lock);
04114    } else if (openr2_chan_get_direction(r2chan) == OR2_DIR_FORWARD) {
04115       /* being the forward side we must report what happened to the call to whoever requested it */
04116       switch (cause) {
04117       case OR2_CAUSE_BUSY_NUMBER:
04118          p->subs[SUB_REAL].needbusy = 1;
04119          break;
04120       case OR2_CAUSE_NETWORK_CONGESTION:
04121       case OR2_CAUSE_OUT_OF_ORDER:
04122       case OR2_CAUSE_UNALLOCATED_NUMBER:
04123       case OR2_CAUSE_NO_ANSWER:
04124       case OR2_CAUSE_UNSPECIFIED:
04125       case OR2_CAUSE_NORMAL_CLEARING:
04126          p->subs[SUB_REAL].needcongestion = 1;
04127          break;
04128       default:
04129          p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
04130       }
04131       ast_mutex_unlock(&p->lock);
04132    } else {
04133       ast_mutex_unlock(&p->lock);
04134       /* being the backward side and not UP yet, we only need to request hangup */
04135       /* TODO: what about doing this same thing when were AST_STATE_UP? */
04136       ast_queue_hangup_with_cause(p->owner, dahdi_r2_cause_to_ast_cause(cause));
04137    }
04138 }
04139 
04140 static void dahdi_r2_write_log(openr2_log_level_t level, char *logmessage)
04141 {
04142    switch (level) {
04143    case OR2_LOG_NOTICE:
04144       ast_verbose("%s", logmessage);
04145       break;
04146    case OR2_LOG_WARNING:
04147       ast_log(LOG_WARNING, "%s", logmessage);
04148       break;
04149    case OR2_LOG_ERROR:
04150       ast_log(LOG_ERROR, "%s", logmessage);
04151       break;
04152    case OR2_LOG_STACK_TRACE:
04153    case OR2_LOG_MF_TRACE:
04154    case OR2_LOG_CAS_TRACE:
04155    case OR2_LOG_DEBUG:
04156    case OR2_LOG_EX_DEBUG:
04157       ast_log(LOG_DEBUG, "%s", logmessage);
04158       break;
04159    default:
04160       ast_log(LOG_WARNING, "We should handle logging level %d here.\n", level);
04161       ast_log(LOG_DEBUG, "%s", logmessage);
04162       break;
04163    }
04164 }
04165 
04166 static void dahdi_r2_on_line_blocked(openr2_chan_t *r2chan)
04167 {
04168    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04169    ast_mutex_lock(&p->lock);
04170    p->remotelyblocked = 1;
04171    ast_mutex_unlock(&p->lock);
04172    ast_log(LOG_NOTICE, "Far end blocked on chan %d\n", openr2_chan_get_number(r2chan));
04173 }
04174 
04175 static void dahdi_r2_on_line_idle(openr2_chan_t *r2chan)
04176 {
04177    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04178    ast_mutex_lock(&p->lock);
04179    p->remotelyblocked = 0;
04180    ast_mutex_unlock(&p->lock);
04181    ast_log(LOG_NOTICE, "Far end unblocked on chan %d\n", openr2_chan_get_number(r2chan));
04182 }
04183 
04184 static void dahdi_r2_on_context_log(openr2_context_t *r2context, openr2_log_level_t level, const char *fmt, va_list ap)
04185    __attribute__((format (printf, 3, 0)));
04186 static void dahdi_r2_on_context_log(openr2_context_t *r2context, openr2_log_level_t level, const char *fmt, va_list ap)
04187 {
04188 #define CONTEXT_TAG "Context - "
04189    char logmsg[256];
04190    char completemsg[sizeof(logmsg) + sizeof(CONTEXT_TAG) - 1];
04191    vsnprintf(logmsg, sizeof(logmsg), fmt, ap);
04192    snprintf(completemsg, sizeof(completemsg), CONTEXT_TAG "%s", logmsg);
04193    dahdi_r2_write_log(level, completemsg);
04194 #undef CONTEXT_TAG
04195 }
04196 
04197 static void dahdi_r2_on_chan_log(openr2_chan_t *r2chan, openr2_log_level_t level, const char *fmt, va_list ap)
04198    __attribute__((format (printf, 3, 0)));
04199 static void dahdi_r2_on_chan_log(openr2_chan_t *r2chan, openr2_log_level_t level, const char *fmt, va_list ap)
04200 {
04201 #define CHAN_TAG "Chan "
04202    char logmsg[256];
04203    char completemsg[sizeof(logmsg) + sizeof(CHAN_TAG) - 1];
04204    vsnprintf(logmsg, sizeof(logmsg), fmt, ap);
04205    snprintf(completemsg, sizeof(completemsg), CHAN_TAG "%d - %s", openr2_chan_get_number(r2chan), logmsg);
04206    dahdi_r2_write_log(level, completemsg);
04207 }
04208 
04209 static int dahdi_r2_on_dnis_digit_received(openr2_chan_t *r2chan, char digit)
04210 {
04211    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04212    /* if 'immediate' is set, let's stop requesting DNIS */
04213    if (p->immediate) {
04214       return 0;
04215    }
04216    p->exten[p->mfcr2_dnis_index] = digit;
04217    p->rdnis[p->mfcr2_dnis_index] = digit;
04218    p->mfcr2_dnis_index++;
04219    p->exten[p->mfcr2_dnis_index] = 0;
04220    p->rdnis[p->mfcr2_dnis_index] = 0;
04221    /* if the DNIS is a match and cannot match more, stop requesting DNIS */
04222    if ((p->mfcr2_dnis_matched ||
04223        (ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num) && (p->mfcr2_dnis_matched = 1))) &&
04224        !ast_matchmore_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
04225       return 0;
04226    }
04227    /* otherwise keep going */
04228    return 1;
04229 }
04230 
04231 static void dahdi_r2_on_ani_digit_received(openr2_chan_t *r2chan, char digit)
04232 {
04233    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04234    p->cid_num[p->mfcr2_ani_index] = digit;
04235    p->cid_name[p->mfcr2_ani_index] = digit;
04236    p->mfcr2_ani_index++;
04237    p->cid_num[p->mfcr2_ani_index] = 0;
04238    p->cid_name[p->mfcr2_ani_index] = 0;
04239 }
04240 
04241 static void dahdi_r2_on_billing_pulse_received(openr2_chan_t *r2chan)
04242 {
04243    ast_verbose("MFC/R2 billing pulse received on channel %d\n", openr2_chan_get_number(r2chan));
04244 }
04245 
04246 static openr2_event_interface_t dahdi_r2_event_iface = {
04247    .on_call_init = dahdi_r2_on_call_init,
04248    .on_call_offered = dahdi_r2_on_call_offered,
04249    .on_call_accepted = dahdi_r2_on_call_accepted,
04250    .on_call_answered = dahdi_r2_on_call_answered,
04251    .on_call_disconnect = dahdi_r2_on_call_disconnect,
04252    .on_call_end = dahdi_r2_on_call_end,
04253    .on_call_read = dahdi_r2_on_call_read,
04254    .on_hardware_alarm = dahdi_r2_on_hardware_alarm,
04255    .on_os_error = dahdi_r2_on_os_error,
04256    .on_protocol_error = dahdi_r2_on_protocol_error,
04257    .on_line_blocked = dahdi_r2_on_line_blocked,
04258    .on_line_idle = dahdi_r2_on_line_idle,
04259    /* cast seems to be needed to get rid of the annoying warning regarding format attribute  */
04260    .on_context_log = (openr2_handle_context_logging_func)dahdi_r2_on_context_log,
04261    .on_dnis_digit_received = dahdi_r2_on_dnis_digit_received,
04262    .on_ani_digit_received = dahdi_r2_on_ani_digit_received,
04263    /* so far we do nothing with billing pulses */
04264    .on_billing_pulse_received = dahdi_r2_on_billing_pulse_received
04265 };
04266 
04267 static inline int16_t dahdi_r2_alaw_to_linear(uint8_t sample)
04268 {
04269    return AST_ALAW(sample);
04270 }
04271 
04272 static inline uint8_t dahdi_r2_linear_to_alaw(int sample)
04273 {
04274    return AST_LIN2A(sample);
04275 }
04276 
04277 static openr2_transcoder_interface_t dahdi_r2_transcode_iface = {
04278    dahdi_r2_alaw_to_linear,
04279    dahdi_r2_linear_to_alaw
04280 };
04281 
04282 #endif /* HAVE_OPENR2 */
04283 
04284 static void swap_subs(struct dahdi_pvt *p, int a, int b)
04285 {
04286    int tchan;
04287    int tinthreeway;
04288    struct ast_channel *towner;
04289 
04290    ast_debug(1, "Swapping %d and %d\n", a, b);
04291 
04292    tchan = p->subs[a].chan;
04293    towner = p->subs[a].owner;
04294    tinthreeway = p->subs[a].inthreeway;
04295 
04296    p->subs[a].chan = p->subs[b].chan;
04297    p->subs[a].owner = p->subs[b].owner;
04298    p->subs[a].inthreeway = p->subs[b].inthreeway;
04299 
04300    p->subs[b].chan = tchan;
04301    p->subs[b].owner = towner;
04302    p->subs[b].inthreeway = tinthreeway;
04303 
04304    if (p->subs[a].owner)
04305       ast_channel_set_fd(p->subs[a].owner, 0, p->subs[a].dfd);
04306    if (p->subs[b].owner)
04307       ast_channel_set_fd(p->subs[b].owner, 0, p->subs[b].dfd);
04308    wakeup_sub(p, a);
04309    wakeup_sub(p, b);
04310 }
04311 
04312 static int dahdi_open(char *fn)
04313 {
04314    int fd;
04315    int isnum;
04316    int chan = 0;
04317    int bs;
04318    int x;
04319    isnum = 1;
04320    for (x = 0; x < strlen(fn); x++) {
04321       if (!isdigit(fn[x])) {
04322          isnum = 0;
04323          break;
04324       }
04325    }
04326    if (isnum) {
04327       chan = atoi(fn);
04328       if (chan < 1) {
04329          ast_log(LOG_WARNING, "Invalid channel number '%s'\n", fn);
04330          return -1;
04331       }
04332       fn = "/dev/dahdi/channel";
04333    }
04334    fd = open(fn, O_RDWR | O_NONBLOCK);
04335    if (fd < 0) {
04336       ast_log(LOG_WARNING, "Unable to open '%s': %s\n", fn, strerror(errno));
04337       return -1;
04338    }
04339    if (chan) {
04340       if (ioctl(fd, DAHDI_SPECIFY, &chan)) {
04341          x = errno;
04342          close(fd);
04343          errno = x;
04344          ast_log(LOG_WARNING, "Unable to specify channel %d: %s\n", chan, strerror(errno));
04345          return -1;
04346       }
04347    }
04348    bs = READ_SIZE;
04349    if (ioctl(fd, DAHDI_SET_BLOCKSIZE, &bs) == -1) {
04350       ast_log(LOG_WARNING, "Unable to set blocksize '%d': %s\n", bs,  strerror(errno));
04351       x = errno;
04352       close(fd);
04353       errno = x;
04354       return -1;
04355    }
04356    return fd;
04357 }
04358 
04359 static void dahdi_close(int fd)
04360 {
04361    if (fd > 0)
04362       close(fd);
04363 }
04364 
04365 static void dahdi_close_sub(struct dahdi_pvt *chan_pvt, int sub_num)
04366 {
04367    dahdi_close(chan_pvt->subs[sub_num].dfd);
04368    chan_pvt->subs[sub_num].dfd = -1;
04369 }
04370 
04371 #if defined(HAVE_PRI)
04372 static void dahdi_close_pri_fd(struct dahdi_pri *pri, int fd_num)
04373 {
04374    dahdi_close(pri->pri.fds[fd_num]);
04375    pri->pri.fds[fd_num] = -1;
04376 }
04377 #endif   /* defined(HAVE_PRI) */
04378 
04379 #if defined(HAVE_SS7)
04380 static void dahdi_close_ss7_fd(struct dahdi_ss7 *ss7, int fd_num)
04381 {
04382    dahdi_close(ss7->ss7.fds[fd_num]);
04383    ss7->ss7.fds[fd_num] = -1;
04384 }
04385 #endif   /* defined(HAVE_SS7) */
04386 
04387 static int dahdi_setlinear(int dfd, int linear)
04388 {
04389    return ioctl(dfd, DAHDI_SETLINEAR, &linear);
04390 }
04391 
04392 
04393 static int alloc_sub(struct dahdi_pvt *p, int x)
04394 {
04395    struct dahdi_bufferinfo bi;
04396    int res;
04397    if (p->subs[x].dfd >= 0) {
04398       ast_log(LOG_WARNING, "%s subchannel of %d already in use\n", subnames[x], p->channel);
04399       return -1;
04400    }
04401 
04402    p->subs[x].dfd = dahdi_open("/dev/dahdi/pseudo");
04403    if (p->subs[x].dfd <= -1) {
04404       ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno));
04405       return -1;
04406    }
04407 
04408    res = ioctl(p->subs[x].dfd, DAHDI_GET_BUFINFO, &bi);
04409    if (!res) {
04410       bi.txbufpolicy = p->buf_policy;
04411       bi.rxbufpolicy = p->buf_policy;
04412       bi.numbufs = p->buf_no;
04413       res = ioctl(p->subs[x].dfd, DAHDI_SET_BUFINFO, &bi);
04414       if (res < 0) {
04415          ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", x, strerror(errno));
04416       }
04417    } else
04418       ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", x, strerror(errno));
04419 
04420    if (ioctl(p->subs[x].dfd, DAHDI_CHANNO, &p->subs[x].chan) == 1) {
04421       ast_log(LOG_WARNING, "Unable to get channel number for pseudo channel on FD %d: %s\n", p->subs[x].dfd, strerror(errno));
04422       dahdi_close_sub(p, x);
04423       p->subs[x].dfd = -1;
04424       return -1;
04425    }
04426    ast_debug(1, "Allocated %s subchannel on FD %d channel %d\n", subnames[x], p->subs[x].dfd, p->subs[x].chan);
04427    return 0;
04428 }
04429 
04430 static int unalloc_sub(struct dahdi_pvt *p, int x)
04431 {
04432    if (!x) {
04433       ast_log(LOG_WARNING, "Trying to unalloc the real channel %d?!?\n", p->channel);
04434       return -1;
04435    }
04436    ast_debug(1, "Released sub %d of channel %d\n", x, p->channel);
04437    dahdi_close_sub(p, x);
04438    p->subs[x].linear = 0;
04439    p->subs[x].chan = 0;
04440    p->subs[x].owner = NULL;
04441    p->subs[x].inthreeway = 0;
04442    p->polarity = POLARITY_IDLE;
04443    memset(&p->subs[x].curconf, 0, sizeof(p->subs[x].curconf));
04444    return 0;
04445 }
04446 
04447 static int digit_to_dtmfindex(char digit)
04448 {
04449    if (isdigit(digit))
04450       return DAHDI_TONE_DTMF_BASE + (digit - '0');
04451    else if (digit >= 'A' && digit <= 'D')
04452       return DAHDI_TONE_DTMF_A + (digit - 'A');
04453    else if (digit >= 'a' && digit <= 'd')
04454       return DAHDI_TONE_DTMF_A + (digit - 'a');
04455    else if (digit == '*')
04456       return DAHDI_TONE_DTMF_s;
04457    else if (digit == '#')
04458       return DAHDI_TONE_DTMF_p;
04459    else
04460       return -1;
04461 }
04462 
04463 static int dahdi_digit_begin(struct ast_channel *chan, char digit)
04464 {
04465    struct dahdi_pvt *pvt;
04466    int idx;
04467    int dtmf = -1;
04468    int res;
04469 
04470    pvt = chan->tech_pvt;
04471 
04472    ast_mutex_lock(&pvt->lock);
04473 
04474    idx = dahdi_get_index(chan, pvt, 0);
04475 
04476    if ((idx != SUB_REAL) || !pvt->owner)
04477       goto out;
04478 
04479 #ifdef HAVE_PRI
04480    switch (pvt->sig) {
04481    case SIG_PRI_LIB_HANDLE_CASES:
04482       res = sig_pri_digit_begin(pvt->sig_pvt, chan, digit);
04483       if (!res)
04484          goto out;
04485       break;
04486    default:
04487       break;
04488    }
04489 #endif
04490    if ((dtmf = digit_to_dtmfindex(digit)) == -1)
04491       goto out;
04492 
04493    if (pvt->pulse || ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &dtmf)) {
04494       struct dahdi_dialoperation zo = {
04495          .op = DAHDI_DIAL_OP_APPEND,
04496       };
04497 
04498       zo.dialstr[0] = 'T';
04499       zo.dialstr[1] = digit;
04500       zo.dialstr[2] = '\0';
04501       if ((res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo)))
04502          ast_log(LOG_WARNING, "Channel %s couldn't dial digit %c: %s\n",
04503             chan->name, digit, strerror(errno));
04504       else
04505          pvt->dialing = 1;
04506    } else {
04507       ast_debug(1, "Channel %s started VLDTMF digit '%c'\n",
04508          chan->name, digit);
04509       pvt->dialing = 1;
04510       pvt->begindigit = digit;
04511    }
04512 
04513 out:
04514    ast_mutex_unlock(&pvt->lock);
04515 
04516    return 0;
04517 }
04518 
04519 static int dahdi_digit_end(struct ast_channel *chan, char digit, unsigned int duration)
04520 {
04521    struct dahdi_pvt *pvt;
04522    int res = 0;
04523    int idx;
04524    int x;
04525 
04526    pvt = chan->tech_pvt;
04527 
04528    ast_mutex_lock(&pvt->lock);
04529 
04530    idx = dahdi_get_index(chan, pvt, 0);
04531 
04532    if ((idx != SUB_REAL) || !pvt->owner || pvt->pulse)
04533       goto out;
04534 
04535 #ifdef HAVE_PRI
04536    /* This means that the digit was already sent via PRI signalling */
04537    if (dahdi_sig_pri_lib_handles(pvt->sig) && !pvt->begindigit) {
04538       goto out;
04539    }
04540 #endif
04541 
04542    if (pvt->begindigit) {
04543       x = -1;
04544       ast_debug(1, "Channel %s ending VLDTMF digit '%c'\n",
04545          chan->name, digit);
04546       res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &x);
04547       pvt->dialing = 0;
04548       pvt->begindigit = 0;
04549    }
04550 
04551 out:
04552    ast_mutex_unlock(&pvt->lock);
04553 
04554    return res;
04555 }
04556 
04557 static const char * const events[] = {
04558    "No event",
04559    "On hook",
04560    "Ring/Answered",
04561    "Wink/Flash",
04562    "Alarm",
04563    "No more alarm",
04564    "HDLC Abort",
04565    "HDLC Overrun",
04566    "HDLC Bad FCS",
04567    "Dial Complete",
04568    "Ringer On",
04569    "Ringer Off",
04570    "Hook Transition Complete",
04571    "Bits Changed",
04572    "Pulse Start",
04573    "Timer Expired",
04574    "Timer Ping",
04575    "Polarity Reversal",
04576    "Ring Begin",
04577 };
04578 
04579 static struct {
04580    int alarm;
04581    char *name;
04582 } alarms[] = {
04583    { DAHDI_ALARM_RED, "Red Alarm" },
04584    { DAHDI_ALARM_YELLOW, "Yellow Alarm" },
04585    { DAHDI_ALARM_BLUE, "Blue Alarm" },
04586    { DAHDI_ALARM_RECOVER, "Recovering" },
04587    { DAHDI_ALARM_LOOPBACK, "Loopback" },
04588    { DAHDI_ALARM_NOTOPEN, "Not Open" },
04589    { DAHDI_ALARM_NONE, "None" },
04590 };
04591 
04592 static char *alarm2str(int alm)
04593 {
04594    int x;
04595    for (x = 0; x < ARRAY_LEN(alarms); x++) {
04596       if (alarms[x].alarm & alm)
04597          return alarms[x].name;
04598    }
04599    return alm ? "Unknown Alarm" : "No Alarm";
04600 }
04601 
04602 static const char *event2str(int event)
04603 {
04604    static char buf[256];
04605    if ((event < (ARRAY_LEN(events))) && (event > -1))
04606       return events[event];
04607    sprintf(buf, "Event %d", event); /* safe */
04608    return buf;
04609 }
04610 
04611 static char *dahdi_sig2str(int sig)
04612 {
04613    static char buf[256];
04614    switch (sig) {
04615    case SIG_EM:
04616       return "E & M Immediate";
04617    case SIG_EMWINK:
04618       return "E & M Wink";
04619    case SIG_EM_E1:
04620       return "E & M E1";
04621    case SIG_FEATD:
04622       return "Feature Group D (DTMF)";
04623    case SIG_FEATDMF:
04624       return "Feature Group D (MF)";
04625    case SIG_FEATDMF_TA:
04626       return "Feature Groud D (MF) Tandem Access";
04627    case SIG_FEATB:
04628       return "Feature Group B (MF)";
04629    case SIG_E911:
04630       return "E911 (MF)";
04631    case SIG_FGC_CAMA:
04632       return "FGC/CAMA (Dialpulse)";
04633    case SIG_FGC_CAMAMF:
04634       return "FGC/CAMA (MF)";
04635    case SIG_FXSLS:
04636       return "FXS Loopstart";
04637    case SIG_FXSGS:
04638       return "FXS Groundstart";
04639    case SIG_FXSKS:
04640       return "FXS Kewlstart";
04641    case SIG_FXOLS:
04642       return "FXO Loopstart";
04643    case SIG_FXOGS:
04644       return "FXO Groundstart";
04645    case SIG_FXOKS:
04646       return "FXO Kewlstart";
04647    case SIG_PRI:
04648       return "ISDN PRI";
04649    case SIG_BRI:
04650       return "ISDN BRI Point to Point";
04651    case SIG_BRI_PTMP:
04652       return "ISDN BRI Point to MultiPoint";
04653    case SIG_SS7:
04654       return "SS7";
04655    case SIG_MFCR2:
04656       return "MFC/R2";
04657    case SIG_SF:
04658       return "SF (Tone) Immediate";
04659    case SIG_SFWINK:
04660       return "SF (Tone) Wink";
04661    case SIG_SF_FEATD:
04662       return "SF (Tone) with Feature Group D (DTMF)";
04663    case SIG_SF_FEATDMF:
04664       return "SF (Tone) with Feature Group D (MF)";
04665    case SIG_SF_FEATB:
04666       return "SF (Tone) with Feature Group B (MF)";
04667    case 0:
04668       return "Pseudo";
04669    default:
04670       snprintf(buf, sizeof(buf), "Unknown signalling %d", sig);
04671       return buf;
04672    }
04673 }
04674 
04675 #define sig2str dahdi_sig2str
04676 
04677 static int analog_lib_handles(int signalling, int radio, int oprmode)
04678 {
04679    switch (signalling) {
04680    case SIG_FXOLS:
04681    case SIG_FXOGS:
04682    case SIG_FXOKS:
04683    case SIG_FXSLS:
04684    case SIG_FXSGS:
04685    case SIG_FXSKS:
04686    case SIG_EMWINK:
04687    case SIG_EM:
04688    case SIG_EM_E1:
04689    case SIG_FEATD:
04690    case SIG_FEATDMF:
04691    case SIG_E911:
04692    case SIG_FGC_CAMA:
04693    case SIG_FGC_CAMAMF:
04694    case SIG_FEATB:
04695    case SIG_SFWINK:
04696    case SIG_SF:
04697    case SIG_SF_FEATD:
04698    case SIG_SF_FEATDMF:
04699    case SIG_FEATDMF_TA:
04700    case SIG_SF_FEATB:
04701       break;
04702    default:
04703       /* The rest of the function should cover the remainder of signalling types */
04704       return 0;
04705    }
04706 
04707    if (radio)
04708       return 0;
04709 
04710    if (oprmode)
04711       return 0;
04712 
04713    return 1;
04714 }
04715 
04716 static int conf_add(struct dahdi_pvt *p, struct dahdi_subchannel *c, int idx, int slavechannel)
04717 {
04718    /* If the conference already exists, and we're already in it
04719       don't bother doing anything */
04720    struct dahdi_confinfo zi;
04721 
04722    memset(&zi, 0, sizeof(zi));
04723    zi.chan = 0;
04724 
04725    if (slavechannel > 0) {
04726       /* If we have only one slave, do a digital mon */
04727       zi.confmode = DAHDI_CONF_DIGITALMON;
04728       zi.confno = slavechannel;
04729    } else {
04730       if (!idx) {
04731          /* Real-side and pseudo-side both participate in conference */
04732          zi.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER |
04733             DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER;
04734       } else
04735          zi.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER;
04736       zi.confno = p->confno;
04737    }
04738    if ((zi.confno == c->curconf.confno) && (zi.confmode == c->curconf.confmode))
04739       return 0;
04740    if (c->dfd < 0)
04741       return 0;
04742    if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
04743       ast_log(LOG_WARNING, "Failed to add %d to conference %d/%d: %s\n", c->dfd, zi.confmode, zi.confno, strerror(errno));
04744       return -1;
04745    }
04746    if (slavechannel < 1) {
04747       p->confno = zi.confno;
04748    }
04749    c->curconf = zi;
04750    ast_debug(1, "Added %d to conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
04751    return 0;
04752 }
04753 
04754 static int isourconf(struct dahdi_pvt *p, struct dahdi_subchannel *c)
04755 {
04756    /* If they're listening to our channel, they're ours */
04757    if ((p->channel == c->curconf.confno) && (c->curconf.confmode == DAHDI_CONF_DIGITALMON))
04758       return 1;
04759    /* If they're a talker on our (allocated) conference, they're ours */
04760    if ((p->confno > 0) && (p->confno == c->curconf.confno) && (c->curconf.confmode & DAHDI_CONF_TALKER))
04761       return 1;
04762    return 0;
04763 }
04764 
04765 static int conf_del(struct dahdi_pvt *p, struct dahdi_subchannel *c, int idx)
04766 {
04767    struct dahdi_confinfo zi;
04768    if (/* Can't delete if there's no dfd */
04769       (c->dfd < 0) ||
04770       /* Don't delete from the conference if it's not our conference */
04771       !isourconf(p, c)
04772       /* Don't delete if we don't think it's conferenced at all (implied) */
04773       ) return 0;
04774    memset(&zi, 0, sizeof(zi));
04775    if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
04776       ast_log(LOG_WARNING, "Failed to drop %d from conference %d/%d: %s\n", c->dfd, c->curconf.confmode, c->curconf.confno, strerror(errno));
04777       return -1;
04778    }
04779    ast_debug(1, "Removed %d from conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
04780    memcpy(&c->curconf, &zi, sizeof(c->curconf));
04781    return 0;
04782 }
04783 
04784 static int isslavenative(struct dahdi_pvt *p, struct dahdi_pvt **out)
04785 {
04786    int x;
04787    int useslavenative;
04788    struct dahdi_pvt *slave = NULL;
04789    /* Start out optimistic */
04790    useslavenative = 1;
04791    /* Update conference state in a stateless fashion */
04792    for (x = 0; x < 3; x++) {
04793       /* Any three-way calling makes slave native mode *definitely* out
04794          of the question */
04795       if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway)
04796          useslavenative = 0;
04797    }
04798    /* If we don't have any 3-way calls, check to see if we have
04799       precisely one slave */
04800    if (useslavenative) {
04801       for (x = 0; x < MAX_SLAVES; x++) {
04802          if (p->slaves[x]) {
04803             if (slave) {
04804                /* Whoops already have a slave!  No
04805                   slave native and stop right away */
04806                slave = NULL;
04807                useslavenative = 0;
04808                break;
04809             } else {
04810                /* We have one slave so far */
04811                slave = p->slaves[x];
04812             }
04813          }
04814       }
04815    }
04816    /* If no slave, slave native definitely out */
04817    if (!slave)
04818       useslavenative = 0;
04819    else if (slave->law != p->law) {
04820       useslavenative = 0;
04821       slave = NULL;
04822    }
04823    if (out)
04824       *out = slave;
04825    return useslavenative;
04826 }
04827 
04828 static int reset_conf(struct dahdi_pvt *p)
04829 {
04830    p->confno = -1;
04831    memset(&p->subs[SUB_REAL].curconf, 0, sizeof(p->subs[SUB_REAL].curconf));
04832    if (p->subs[SUB_REAL].dfd > -1) {
04833       struct dahdi_confinfo zi;
04834 
04835       memset(&zi, 0, sizeof(zi));
04836       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &zi))
04837          ast_log(LOG_WARNING, "Failed to reset conferencing on channel %d: %s\n", p->channel, strerror(errno));
04838    }
04839    return 0;
04840 }
04841 
04842 static int update_conf(struct dahdi_pvt *p)
04843 {
04844    int needconf = 0;
04845    int x;
04846    int useslavenative;
04847    struct dahdi_pvt *slave = NULL;
04848 
04849    useslavenative = isslavenative(p, &slave);
04850    /* Start with the obvious, general stuff */
04851    for (x = 0; x < 3; x++) {
04852       /* Look for three way calls */
04853       if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) {
04854          conf_add(p, &p->subs[x], x, 0);
04855          needconf++;
04856       } else {
04857          conf_del(p, &p->subs[x], x);
04858       }
04859    }
04860    /* If we have a slave, add him to our conference now. or DAX
04861       if this is slave native */
04862    for (x = 0; x < MAX_SLAVES; x++) {
04863       if (p->slaves[x]) {
04864          if (useslavenative)
04865             conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
04866          else {
04867             conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
04868             needconf++;
04869          }
04870       }
04871    }
04872    /* If we're supposed to be in there, do so now */
04873    if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
04874       if (useslavenative)
04875          conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
04876       else {
04877          conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
04878          needconf++;
04879       }
04880    }
04881    /* If we have a master, add ourselves to his conference */
04882    if (p->master) {
04883       if (isslavenative(p->master, NULL)) {
04884          conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
04885       } else {
04886          conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
04887       }
04888    }
04889    if (!needconf) {
04890       /* Nobody is left (or should be left) in our conference.
04891          Kill it. */
04892       p->confno = -1;
04893    }
04894    ast_debug(1, "Updated conferencing on %d, with %d conference users\n", p->channel, needconf);
04895    return 0;
04896 }
04897 
04898 static void dahdi_enable_ec(struct dahdi_pvt *p)
04899 {
04900    int res;
04901    if (!p)
04902       return;
04903    if (p->echocanon) {
04904       ast_debug(1, "Echo cancellation already on\n");
04905       return;
04906    }
04907    if (p->digital) {
04908       ast_debug(1, "Echo cancellation isn't required on digital connection\n");
04909       return;
04910    }
04911    if (p->echocancel.head.tap_length) {
04912 #if defined(HAVE_PRI) || defined(HAVE_SS7)
04913       switch (p->sig) {
04914 #if defined(HAVE_PRI)
04915       case SIG_PRI_LIB_HANDLE_CASES:
04916          if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
04917             /*
04918              * PRI nobch pseudo channel.  Does not need ec anyway.
04919              * Does not handle ioctl(DAHDI_AUDIOMODE)
04920              */
04921             return;
04922          }
04923          /* Fall through */
04924 #endif   /* defined(HAVE_PRI) */
04925 #if defined(HAVE_SS7)
04926       case SIG_SS7:
04927 #endif   /* defined(HAVE_SS7) */
04928          {
04929             int x = 1;
04930 
04931             res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x);
04932             if (res)
04933                ast_log(LOG_WARNING,
04934                   "Unable to enable audio mode on channel %d (%s)\n",
04935                   p->channel, strerror(errno));
04936          }
04937          break;
04938       default:
04939          break;
04940       }
04941 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
04942       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &p->echocancel);
04943       if (res) {
04944          ast_log(LOG_WARNING, "Unable to enable echo cancellation on channel %d (%s)\n", p->channel, strerror(errno));
04945       } else {
04946          p->echocanon = 1;
04947          ast_debug(1, "Enabled echo cancellation on channel %d\n", p->channel);
04948       }
04949    } else
04950       ast_debug(1, "No echo cancellation requested\n");
04951 }
04952 
04953 static void dahdi_train_ec(struct dahdi_pvt *p)
04954 {
04955    int x;
04956    int res;
04957 
04958    if (p && p->echocanon && p->echotraining) {
04959       x = p->echotraining;
04960       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOTRAIN, &x);
04961       if (res)
04962          ast_log(LOG_WARNING, "Unable to request echo training on channel %d: %s\n", p->channel, strerror(errno));
04963       else
04964          ast_debug(1, "Engaged echo training on channel %d\n", p->channel);
04965    } else {
04966       ast_debug(1, "No echo training requested\n");
04967    }
04968 }
04969 
04970 static void dahdi_disable_ec(struct dahdi_pvt *p)
04971 {
04972    int res;
04973 
04974    if (p->echocanon) {
04975       struct dahdi_echocanparams ecp = { .tap_length = 0 };
04976 
04977       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &ecp);
04978 
04979       if (res)
04980          ast_log(LOG_WARNING, "Unable to disable echo cancellation on channel %d: %s\n", p->channel, strerror(errno));
04981       else
04982          ast_debug(1, "Disabled echo cancellation on channel %d\n", p->channel);
04983    }
04984 
04985    p->echocanon = 0;
04986 }
04987 
04988 /* perform a dynamic range compression transform on the given sample */
04989 static int drc_sample(int sample, float drc)
04990 {
04991    float neg;
04992    float shallow, steep;
04993    float max = SHRT_MAX;
04994    
04995    neg = (sample < 0 ? -1 : 1);
04996    steep = drc*sample;
04997    shallow = neg*(max-max/drc)+(float)sample/drc;
04998    if (abs(steep) < abs(shallow)) {
04999       sample = steep;
05000    }
05001    else {
05002       sample = shallow;
05003    }
05004 
05005    return sample;
05006 }
05007 
05008 
05009 static void fill_txgain(struct dahdi_gains *g, float gain, float drc, int law)
05010 {
05011    int j;
05012    int k;
05013 
05014    float linear_gain = pow(10.0, gain / 20.0);
05015 
05016    switch (law) {
05017    case DAHDI_LAW_ALAW:
05018       for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
05019          if (gain || drc) {
05020             k = AST_ALAW(j);
05021             if (drc) {
05022                k = drc_sample(k, drc);
05023             }
05024             k = (float)k*linear_gain;
05025             if (k > 32767) k = 32767;
05026             if (k < -32767) k = -32767;
05027             g->txgain[j] = AST_LIN2A(k);
05028          } else {
05029             g->txgain[j] = j;
05030          }
05031       }
05032       break;
05033    case DAHDI_LAW_MULAW:
05034       for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
05035          if (gain || drc) {
05036             k = AST_MULAW(j);
05037             if (drc) {
05038                k = drc_sample(k, drc);
05039             }
05040             k = (float)k*linear_gain;
05041             if (k > 32767) k = 32767;
05042             if (k < -32767) k = -32767;
05043             g->txgain[j] = AST_LIN2MU(k);
05044 
05045          } else {
05046             g->txgain[j] = j;
05047          }
05048       }
05049       break;
05050    }
05051 }
05052 
05053 static void fill_rxgain(struct dahdi_gains *g, float gain, float drc, int law)
05054 {
05055    int j;
05056    int k;
05057    float linear_gain = pow(10.0, gain / 20.0);
05058 
05059    switch (law) {
05060    case DAHDI_LAW_ALAW:
05061       for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
05062          if (gain || drc) {
05063             k = AST_ALAW(j);
05064             if (drc) {
05065                k = drc_sample(k, drc);
05066             }
05067             k = (float)k*linear_gain;
05068             if (k > 32767) k = 32767;
05069             if (k < -32767) k = -32767;
05070             g->rxgain[j] = AST_LIN2A(k);
05071          } else {
05072             g->rxgain[j] = j;
05073          }
05074       }
05075       break;
05076    case DAHDI_LAW_MULAW:
05077       for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
05078          if (gain || drc) {
05079             k = AST_MULAW(j);
05080             if (drc) {
05081                k = drc_sample(k, drc);
05082             }
05083             k = (float)k*linear_gain;
05084             if (k > 32767) k = 32767;
05085             if (k < -32767) k = -32767;
05086             g->rxgain[j] = AST_LIN2MU(k);
05087          } else {
05088             g->rxgain[j] = j;
05089          }
05090       }
05091       break;
05092    }
05093 }
05094 
05095 static int set_actual_txgain(int fd, float gain, float drc, int law)
05096 {
05097    struct dahdi_gains g;
05098    int res;
05099 
05100    memset(&g, 0, sizeof(g));
05101    res = ioctl(fd, DAHDI_GETGAINS, &g);
05102    if (res) {
05103       ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
05104       return res;
05105    }
05106 
05107    fill_txgain(&g, gain, drc, law);
05108 
05109    return ioctl(fd, DAHDI_SETGAINS, &g);
05110 }
05111 
05112 static int set_actual_rxgain(int fd, float gain, float drc, int law)
05113 {
05114    struct dahdi_gains g;
05115    int res;
05116 
05117    memset(&g, 0, sizeof(g));
05118    res = ioctl(fd, DAHDI_GETGAINS, &g);
05119    if (res) {
05120       ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
05121       return res;
05122    }
05123 
05124    fill_rxgain(&g, gain, drc, law);
05125 
05126    return ioctl(fd, DAHDI_SETGAINS, &g);
05127 }
05128 
05129 static int set_actual_gain(int fd, float rxgain, float txgain, float rxdrc, float txdrc, int law)
05130 {
05131    return set_actual_txgain(fd, txgain, txdrc, law) | set_actual_rxgain(fd, rxgain, rxdrc, law);
05132 }
05133 
05134 static int bump_gains(struct dahdi_pvt *p)
05135 {
05136    int res;
05137 
05138    /* Bump receive gain by value stored in cid_rxgain */
05139    res = set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain + p->cid_rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
05140    if (res) {
05141       ast_log(LOG_WARNING, "Unable to bump gain: %s\n", strerror(errno));
05142       return -1;
05143    }
05144 
05145    return 0;
05146 }
05147 
05148 static int restore_gains(struct dahdi_pvt *p)
05149 {
05150    int res;
05151 
05152    res = set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
05153    if (res) {
05154       ast_log(LOG_WARNING, "Unable to restore gains: %s\n", strerror(errno));
05155       return -1;
05156    }
05157 
05158    return 0;
05159 }
05160 
05161 static inline int dahdi_set_hook(int fd, int hs)
05162 {
05163    int x, res;
05164 
05165    x = hs;
05166    res = ioctl(fd, DAHDI_HOOK, &x);
05167 
05168    if (res < 0) {
05169       if (errno == EINPROGRESS)
05170          return 0;
05171       ast_log(LOG_WARNING, "DAHDI hook failed returned %d (trying %d): %s\n", res, hs, strerror(errno));
05172       /* will expectedly fail if phone is off hook during operation, such as during a restart */
05173    }
05174 
05175    return res;
05176 }
05177 
05178 static inline int dahdi_confmute(struct dahdi_pvt *p, int muted)
05179 {
05180    int x, res;
05181 
05182    x = muted;
05183 #if defined(HAVE_PRI) || defined(HAVE_SS7)
05184    switch (p->sig) {
05185 #if defined(HAVE_PRI)
05186    case SIG_PRI_LIB_HANDLE_CASES:
05187       if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
05188          /* PRI nobch pseudo channel.  Does not handle ioctl(DAHDI_AUDIOMODE) */
05189          break;
05190       }
05191       /* Fall through */
05192 #endif   /* defined(HAVE_PRI) */
05193 #if defined(HAVE_SS7)
05194    case SIG_SS7:
05195 #endif   /* defined(HAVE_SS7) */
05196       {
05197          int y = 1;
05198 
05199          res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &y);
05200          if (res)
05201             ast_log(LOG_WARNING, "Unable to set audio mode on %d: %s\n",
05202                p->channel, strerror(errno));
05203       }
05204       break;
05205    default:
05206       break;
05207    }
05208 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
05209    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_CONFMUTE, &x);
05210    if (res < 0)
05211       ast_log(LOG_WARNING, "DAHDI confmute(%d) failed on channel %d: %s\n", muted, p->channel, strerror(errno));
05212    return res;
05213 }
05214 
05215 static int save_conference(struct dahdi_pvt *p)
05216 {
05217    struct dahdi_confinfo c;
05218    int res;
05219    if (p->saveconf.confmode) {
05220       ast_log(LOG_WARNING, "Can't save conference -- already in use\n");
05221       return -1;
05222    }
05223    p->saveconf.chan = 0;
05224    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &p->saveconf);
05225    if (res) {
05226       ast_log(LOG_WARNING, "Unable to get conference info: %s\n", strerror(errno));
05227       p->saveconf.confmode = 0;
05228       return -1;
05229    }
05230    memset(&c, 0, sizeof(c));
05231    c.confmode = DAHDI_CONF_NORMAL;
05232    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &c);
05233    if (res) {
05234       ast_log(LOG_WARNING, "Unable to set conference info: %s\n", strerror(errno));
05235       return -1;
05236    }
05237    ast_debug(1, "Disabled conferencing\n");
05238    return 0;
05239 }
05240 
05241 static int restore_conference(struct dahdi_pvt *p)
05242 {
05243    int res;
05244    if (p->saveconf.confmode) {
05245       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &p->saveconf);
05246       p->saveconf.confmode = 0;
05247       if (res) {
05248          ast_log(LOG_WARNING, "Unable to restore conference info: %s\n", strerror(errno));
05249          return -1;
05250       }
05251       ast_debug(1, "Restored conferencing\n");
05252    }
05253    return 0;
05254 }
05255 
05256 static int send_cwcidspill(struct dahdi_pvt *p)
05257 {
05258    p->callwaitcas = 0;
05259    p->cidcwexpire = 0;
05260    p->cid_suppress_expire = 0;
05261    if (!(p->cidspill = ast_malloc(MAX_CALLERID_SIZE)))
05262       return -1;
05263    p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, p->callwait_name, p->callwait_num, AST_LAW(p));
05264    /* Make sure we account for the end */
05265    p->cidlen += READ_SIZE * 4;
05266    p->cidpos = 0;
05267    send_callerid(p);
05268    ast_verb(3, "CPE supports Call Waiting Caller*ID.  Sending '%s/%s'\n", p->callwait_name, p->callwait_num);
05269    return 0;
05270 }
05271 
05272 static int has_voicemail(struct dahdi_pvt *p)
05273 {
05274    int new_msgs;
05275    struct ast_event *event;
05276    char *mailbox, *context;
05277 
05278    mailbox = context = ast_strdupa(p->mailbox);
05279    strsep(&context, "@");
05280    if (ast_strlen_zero(context))
05281       context = "default";
05282 
05283    event = ast_event_get_cached(AST_EVENT_MWI,
05284       AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
05285       AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
05286       AST_EVENT_IE_END);
05287 
05288    if (event) {
05289       new_msgs = ast_event_get_ie_uint(event, AST_EVENT_IE_NEWMSGS);
05290       ast_event_destroy(event);
05291    } else
05292       new_msgs = ast_app_has_voicemail(p->mailbox, NULL);
05293 
05294    return new_msgs;
05295 }
05296 
05297 
05298 
05299 static int send_callerid(struct dahdi_pvt *p)
05300 {
05301    /* Assumes spill in p->cidspill, p->cidlen in length and we're p->cidpos into it */
05302    int res;
05303    /* Take out of linear mode if necessary */
05304    if (p->subs[SUB_REAL].linear) {
05305       p->subs[SUB_REAL].linear = 0;
05306       dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
05307    }
05308    while (p->cidpos < p->cidlen) {
05309       res = write(p->subs[SUB_REAL].dfd, p->cidspill + p->cidpos, p->cidlen - p->cidpos);
05310       ast_debug(4, "writing callerid at pos %d of %d, res = %d\n", p->cidpos, p->cidlen, res);
05311       if (res < 0) {
05312          if (errno == EAGAIN)
05313             return 0;
05314          else {
05315             ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
05316             return -1;
05317          }
05318       }
05319       if (!res)
05320          return 0;
05321       p->cidpos += res;
05322    }
05323    p->cid_suppress_expire = CALLWAITING_SUPPRESS_SAMPLES;
05324    ast_free(p->cidspill);
05325    p->cidspill = NULL;
05326    if (p->callwaitcas) {
05327       /* Wait for CID/CW to expire */
05328       p->cidcwexpire = CIDCW_EXPIRE_SAMPLES;
05329       p->cid_suppress_expire = p->cidcwexpire;
05330    } else
05331       restore_conference(p);
05332    return 0;
05333 }
05334 
05335 static int dahdi_callwait(struct ast_channel *ast)
05336 {
05337    struct dahdi_pvt *p = ast->tech_pvt;
05338    p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
05339    if (p->cidspill) {
05340       ast_log(LOG_WARNING, "Spill already exists?!?\n");
05341       ast_free(p->cidspill);
05342    }
05343 
05344    /*
05345     * SAS: Subscriber Alert Signal, 440Hz for 300ms
05346     * CAS: CPE Alert Signal, 2130Hz * 2750Hz sine waves
05347     */
05348    if (!(p->cidspill = ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE * 4)))
05349       return -1;
05350    save_conference(p);
05351    /* Silence */
05352    memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
05353    if (!p->callwaitrings && p->callwaitingcallerid) {
05354       ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
05355       p->callwaitcas = 1;
05356       p->cidlen = 2400 + 680 + READ_SIZE * 4;
05357    } else {
05358       ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
05359       p->callwaitcas = 0;
05360       p->cidlen = 2400 + READ_SIZE * 4;
05361    }
05362    p->cidpos = 0;
05363    send_callerid(p);
05364 
05365    return 0;
05366 }
05367 
05368 static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout)
05369 {
05370    struct dahdi_pvt *p = ast->tech_pvt;
05371    int x, res, mysig;
05372    char dest[256]; /* must be same length as p->dialdest */
05373 
05374    ast_mutex_lock(&p->lock);
05375    ast_copy_string(dest, rdest, sizeof(dest));
05376    ast_copy_string(p->dialdest, rdest, sizeof(p->dialdest));
05377    if ((ast->_state == AST_STATE_BUSY)) {
05378       p->subs[SUB_REAL].needbusy = 1;
05379       ast_mutex_unlock(&p->lock);
05380       return 0;
05381    }
05382    if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
05383       ast_log(LOG_WARNING, "dahdi_call called on %s, neither down nor reserved\n", ast->name);
05384       ast_mutex_unlock(&p->lock);
05385       return -1;
05386    }
05387    p->waitingfordt.tv_sec = 0;
05388    p->dialednone = 0;
05389    if ((p->radio || (p->oprmode < 0)))  /* if a radio channel, up immediately */
05390    {
05391       /* Special pseudo -- automatically up */
05392       ast_setstate(ast, AST_STATE_UP);
05393       ast_mutex_unlock(&p->lock);
05394       return 0;
05395    }
05396    x = DAHDI_FLUSH_READ | DAHDI_FLUSH_WRITE;
05397    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
05398    if (res)
05399       ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", p->channel, strerror(errno));
05400    p->outgoing = 1;
05401 
05402    if (IS_DIGITAL(ast->transfercapability)){
05403       set_actual_gain(p->subs[SUB_REAL].dfd, 0, 0, p->rxdrc, p->txdrc, p->law);
05404    } else {
05405       set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
05406    }  
05407 
05408 #ifdef HAVE_PRI
05409    if (dahdi_sig_pri_lib_handles(p->sig)) {
05410       res = sig_pri_call(p->sig_pvt, ast, rdest, timeout,
05411          (p->law == DAHDI_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW);
05412       ast_mutex_unlock(&p->lock);
05413       return res;
05414    }
05415 #endif
05416 
05417 #if defined(HAVE_SS7)
05418    if (p->sig == SIG_SS7) {
05419       res = sig_ss7_call(p->sig_pvt, ast, rdest);
05420       ast_mutex_unlock(&p->lock);
05421       return res;
05422    }
05423 #endif   /* defined(HAVE_SS7) */
05424 
05425    /* If this is analog signalling we can exit here */
05426    if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
05427       p->callwaitrings = 0;
05428       res = analog_call(p->sig_pvt, ast, rdest, timeout);
05429       ast_mutex_unlock(&p->lock);
05430       return res;
05431    }
05432 
05433    mysig = p->outsigmod > -1 ? p->outsigmod : p->sig;
05434    switch (mysig) {
05435    case 0:
05436       /* Special pseudo -- automatically up*/
05437       ast_setstate(ast, AST_STATE_UP);
05438       break;
05439    case SIG_MFCR2:
05440       break;
05441    default:
05442       ast_debug(1, "not yet implemented\n");
05443       ast_mutex_unlock(&p->lock);
05444       return -1;
05445    }
05446 
05447 #ifdef HAVE_OPENR2
05448    if (p->mfcr2) {
05449       openr2_calling_party_category_t chancat;
05450       int callres = 0;
05451       char *c, *l;
05452 
05453       /* We'll get it in a moment -- but use dialdest to store pre-setup_ack digits */
05454       p->dialdest[0] = '\0';
05455 
05456       c = strchr(dest, '/');
05457       if (c) {
05458          c++;
05459       } else {
05460          c = "";
05461       }
05462       if (!p->hidecallerid) {
05463          l = ast->connected.id.number.valid ? ast->connected.id.number.str : NULL;
05464       } else {
05465          l = NULL;
05466       }
05467       if (strlen(c) < p->stripmsd) {
05468          ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
05469          ast_mutex_unlock(&p->lock);
05470          return -1;
05471       }
05472       p->dialing = 1;
05473       chancat = dahdi_r2_get_channel_category(ast);
05474       callres = openr2_chan_make_call(p->r2chan, l, (c + p->stripmsd), chancat);
05475       if (-1 == callres) {
05476          ast_mutex_unlock(&p->lock);
05477          ast_log(LOG_ERROR, "unable to make new MFC/R2 call!\n");
05478          return -1;
05479       }
05480       p->mfcr2_call_accepted = 0;
05481       p->mfcr2_progress = 0;
05482       ast_setstate(ast, AST_STATE_DIALING);
05483    }
05484 #endif /* HAVE_OPENR2 */
05485    ast_mutex_unlock(&p->lock);
05486    return 0;
05487 }
05488 
05489 /*!
05490  * \internal
05491  * \brief Insert the given chan_dahdi interface structure into the interface list.
05492  * \since 1.8
05493  *
05494  * \param pvt chan_dahdi private interface structure to insert.
05495  *
05496  * \details
05497  * The interface list is a doubly linked list sorted by the chan_dahdi channel number.
05498  * Any duplicates are inserted after the existing entries.
05499  *
05500  * \note The new interface must not already be in the list.
05501  *
05502  * \return Nothing
05503  */
05504 static void dahdi_iflist_insert(struct dahdi_pvt *pvt)
05505 {
05506    struct dahdi_pvt *cur;
05507 
05508    pvt->which_iflist = DAHDI_IFLIST_MAIN;
05509 
05510    /* Find place in middle of list for the new interface. */
05511    for (cur = iflist; cur; cur = cur->next) {
05512       if (pvt->channel < cur->channel) {
05513          /* New interface goes before the current interface. */
05514          pvt->prev = cur->prev;
05515          pvt->next = cur;
05516          if (cur->prev) {
05517             /* Insert into the middle of the list. */
05518             cur->prev->next = pvt;
05519          } else {
05520             /* Insert at head of list. */
05521             iflist = pvt;
05522          }
05523          cur->prev = pvt;
05524          return;
05525       }
05526    }
05527 
05528    /* New interface goes onto the end of the list */
05529    pvt->prev = ifend;
05530    pvt->next = NULL;
05531    if (ifend) {
05532       ifend->next = pvt;
05533    }
05534    ifend = pvt;
05535    if (!iflist) {
05536       /* List was empty */
05537       iflist = pvt;
05538    }
05539 }
05540 
05541 /*!
05542  * \internal
05543  * \brief Extract the given chan_dahdi interface structure from the interface list.
05544  * \since 1.8
05545  *
05546  * \param pvt chan_dahdi private interface structure to extract.
05547  *
05548  * \note
05549  * The given interface structure can be either in the interface list or a stand alone
05550  * structure that has not been put in the list if the next and prev pointers are NULL.
05551  *
05552  * \return Nothing
05553  */
05554 static void dahdi_iflist_extract(struct dahdi_pvt *pvt)
05555 {
05556    /* Extract from the forward chain. */
05557    if (pvt->prev) {
05558       pvt->prev->next = pvt->next;
05559    } else if (iflist == pvt) {
05560       /* Node is at the head of the list. */
05561       iflist = pvt->next;
05562    }
05563 
05564    /* Extract from the reverse chain. */
05565    if (pvt->next) {
05566       pvt->next->prev = pvt->prev;
05567    } else if (ifend == pvt) {
05568       /* Node is at the end of the list. */
05569       ifend = pvt->prev;
05570    }
05571 
05572    /* Node is no longer in the list. */
05573    pvt->which_iflist = DAHDI_IFLIST_NONE;
05574    pvt->prev = NULL;
05575    pvt->next = NULL;
05576 }
05577 
05578 #if defined(HAVE_PRI)
05579 /*!
05580  * \internal
05581  * \brief Insert the given chan_dahdi interface structure into the no B channel list.
05582  * \since 1.8
05583  *
05584  * \param pri sig_pri span control structure holding no B channel list.
05585  * \param pvt chan_dahdi private interface structure to insert.
05586  *
05587  * \details
05588  * The interface list is a doubly linked list sorted by the chan_dahdi channel number.
05589  * Any duplicates are inserted after the existing entries.
05590  *
05591  * \note The new interface must not already be in the list.
05592  *
05593  * \return Nothing
05594  */
05595 static void dahdi_nobch_insert(struct sig_pri_span *pri, struct dahdi_pvt *pvt)
05596 {
05597    struct dahdi_pvt *cur;
05598 
05599    pvt->which_iflist = DAHDI_IFLIST_NO_B_CHAN;
05600 
05601    /* Find place in middle of list for the new interface. */
05602    for (cur = pri->no_b_chan_iflist; cur; cur = cur->next) {
05603       if (pvt->channel < cur->channel) {
05604          /* New interface goes before the current interface. */
05605          pvt->prev = cur->prev;
05606          pvt->next = cur;
05607          if (cur->prev) {
05608             /* Insert into the middle of the list. */
05609             cur->prev->next = pvt;
05610          } else {
05611             /* Insert at head of list. */
05612             pri->no_b_chan_iflist = pvt;
05613          }
05614          cur->prev = pvt;
05615          return;
05616       }
05617    }
05618 
05619    /* New interface goes onto the end of the list */
05620    pvt->prev = pri->no_b_chan_end;
05621    pvt->next = NULL;
05622    if (pri->no_b_chan_end) {
05623       ((struct dahdi_pvt *) pri->no_b_chan_end)->next = pvt;
05624    }
05625    pri->no_b_chan_end = pvt;
05626    if (!pri->no_b_chan_iflist) {
05627       /* List was empty */
05628       pri->no_b_chan_iflist = pvt;
05629    }
05630 }
05631 #endif   /* defined(HAVE_PRI) */
05632 
05633 #if defined(HAVE_PRI)
05634 /*!
05635  * \internal
05636  * \brief Extract the given chan_dahdi interface structure from the no B channel list.
05637  * \since 1.8
05638  *
05639  * \param pri sig_pri span control structure holding no B channel list.
05640  * \param pvt chan_dahdi private interface structure to extract.
05641  *
05642  * \note
05643  * The given interface structure can be either in the interface list or a stand alone
05644  * structure that has not been put in the list if the next and prev pointers are NULL.
05645  *
05646  * \return Nothing
05647  */
05648 static void dahdi_nobch_extract(struct sig_pri_span *pri, struct dahdi_pvt *pvt)
05649 {
05650    /* Extract from the forward chain. */
05651    if (pvt->prev) {
05652       pvt->prev->next = pvt->next;
05653    } else if (pri->no_b_chan_iflist == pvt) {
05654       /* Node is at the head of the list. */
05655       pri->no_b_chan_iflist = pvt->next;
05656    }
05657 
05658    /* Extract from the reverse chain. */
05659    if (pvt->next) {
05660       pvt->next->prev = pvt->prev;
05661    } else if (pri->no_b_chan_end == pvt) {
05662       /* Node is at the end of the list. */
05663       pri->no_b_chan_end = pvt->prev;
05664    }
05665 
05666    /* Node is no longer in the list. */
05667    pvt->which_iflist = DAHDI_IFLIST_NONE;
05668    pvt->prev = NULL;
05669    pvt->next = NULL;
05670 }
05671 #endif   /* defined(HAVE_PRI) */
05672 
05673 #if defined(HAVE_PRI)
05674 /*!
05675  * \internal
05676  * \brief Unlink the channel interface from the PRI private pointer array.
05677  * \since 1.8
05678  *
05679  * \param pvt chan_dahdi private interface structure to unlink.
05680  *
05681  * \return Nothing
05682  */
05683 static void dahdi_unlink_pri_pvt(struct dahdi_pvt *pvt)
05684 {
05685    unsigned idx;
05686    struct sig_pri_span *pri;
05687 
05688    pri = pvt->pri;
05689    if (!pri) {
05690       /* Not PRI signaling so cannot be in a PRI private pointer array. */
05691       return;
05692    }
05693    ast_mutex_lock(&pri->lock);
05694    for (idx = 0; idx < pri->numchans; ++idx) {
05695       if (pri->pvts[idx] == pvt->sig_pvt) {
05696          pri->pvts[idx] = NULL;
05697          ast_mutex_unlock(&pri->lock);
05698          return;
05699       }
05700    }
05701    ast_mutex_unlock(&pri->lock);
05702 }
05703 #endif   /* defined(HAVE_PRI) */
05704 
05705 #if defined(HAVE_SS7)
05706 /*!
05707  * \internal
05708  * \brief Unlink the channel interface from the SS7 private pointer array.
05709  * \since 1.8
05710  *
05711  * \param pvt chan_dahdi private interface structure to unlink.
05712  *
05713  * \return Nothing
05714  */
05715 static void dahdi_unlink_ss7_pvt(struct dahdi_pvt *pvt)
05716 {
05717    unsigned idx;
05718    struct sig_ss7_linkset *ss7;
05719 
05720    ss7 = pvt->ss7;
05721    if (!ss7) {
05722       /* Not SS7 signaling so cannot be in a SS7 private pointer array. */
05723       return;
05724    }
05725    ast_mutex_lock(&ss7->lock);
05726    for (idx = 0; idx < ss7->numchans; ++idx) {
05727       if (ss7->pvts[idx] == pvt->sig_pvt) {
05728          ss7->pvts[idx] = NULL;
05729          ast_mutex_unlock(&ss7->lock);
05730          return;
05731       }
05732    }
05733    ast_mutex_unlock(&ss7->lock);
05734 }
05735 #endif   /* defined(HAVE_SS7) */
05736 
05737 static struct dahdi_pvt *find_next_iface_in_span(struct dahdi_pvt *cur)
05738 {
05739    if (cur->next && cur->next->span == cur->span) {
05740       return cur->next;
05741    } else if (cur->prev && cur->prev->span == cur->span) {
05742       return cur->prev;
05743    }
05744 
05745    return NULL;
05746 }
05747 
05748 static void destroy_dahdi_pvt(struct dahdi_pvt *pvt)
05749 {
05750    struct dahdi_pvt *p = pvt;
05751 
05752    if (p->manages_span_alarms) {
05753       struct dahdi_pvt *next = find_next_iface_in_span(p);
05754       if (next) {
05755          next->manages_span_alarms = 1;
05756       }
05757    }
05758 
05759    /* Remove channel from the list */
05760 #if defined(HAVE_PRI)
05761    dahdi_unlink_pri_pvt(p);
05762 #endif   /* defined(HAVE_PRI) */
05763 #if defined(HAVE_SS7)
05764    dahdi_unlink_ss7_pvt(p);
05765 #endif   /* defined(HAVE_SS7) */
05766    switch (pvt->which_iflist) {
05767    case DAHDI_IFLIST_NONE:
05768       break;
05769    case DAHDI_IFLIST_MAIN:
05770       dahdi_iflist_extract(p);
05771       break;
05772 #if defined(HAVE_PRI)
05773    case DAHDI_IFLIST_NO_B_CHAN:
05774       if (p->pri) {
05775          dahdi_nobch_extract(p->pri, p);
05776       }
05777       break;
05778 #endif   /* defined(HAVE_PRI) */
05779    }
05780 
05781    if (p->sig_pvt) {
05782       if (analog_lib_handles(p->sig, 0, 0)) {
05783          analog_delete(p->sig_pvt);
05784       }
05785       switch (p->sig) {
05786 #if defined(HAVE_PRI)
05787       case SIG_PRI_LIB_HANDLE_CASES:
05788          sig_pri_chan_delete(p->sig_pvt);
05789          break;
05790 #endif   /* defined(HAVE_PRI) */
05791 #if defined(HAVE_SS7)
05792       case SIG_SS7:
05793          sig_ss7_chan_delete(p->sig_pvt);
05794          break;
05795 #endif   /* defined(HAVE_SS7) */
05796       default:
05797          break;
05798       }
05799    }
05800    ast_free(p->cidspill);
05801    if (p->use_smdi)
05802       ast_smdi_interface_unref(p->smdi_iface);
05803    if (p->mwi_event_sub)
05804       ast_event_unsubscribe(p->mwi_event_sub);
05805    if (p->vars) {
05806       ast_variables_destroy(p->vars);
05807    }
05808    if (p->cc_params) {
05809       ast_cc_config_params_destroy(p->cc_params);
05810    }
05811    ast_mutex_destroy(&p->lock);
05812    dahdi_close_sub(p, SUB_REAL);
05813    if (p->owner)
05814       p->owner->tech_pvt = NULL;
05815    ast_free(p);
05816 }
05817 
05818 static void destroy_channel(struct dahdi_pvt *cur, int now)
05819 {
05820    int i;
05821 
05822    if (!now) {
05823       /* Do not destroy the channel now if it is owned by someone. */
05824       if (cur->owner) {
05825          return;
05826       }
05827       for (i = 0; i < 3; i++) {
05828          if (cur->subs[i].owner) {
05829             return;
05830          }
05831       }
05832    }
05833    destroy_dahdi_pvt(cur);
05834 }
05835 
05836 static void destroy_all_channels(void)
05837 {
05838    int chan;
05839 #if defined(HAVE_PRI)
05840    unsigned span;
05841    struct sig_pri_span *pri;
05842 #endif   /* defined(HAVE_PRI) */
05843    struct dahdi_pvt *p;
05844 
05845    while (num_restart_pending) {
05846       usleep(1);
05847    }
05848 
05849    ast_mutex_lock(&iflock);
05850    /* Destroy all the interfaces and free their memory */
05851    while (iflist) {
05852       p = iflist;
05853 
05854       chan = p->channel;
05855 #if defined(HAVE_PRI_SERVICE_MESSAGES)
05856       {
05857          char db_chan_name[20];
05858          char db_answer[5];
05859          char state;
05860          int why = -1;
05861 
05862          snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, p->span, chan);
05863          if (!ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) {
05864             sscanf(db_answer, "%1c:%30d", &state, &why);
05865          }
05866          if (!why) {
05867             /* SRVST persistence is not required */
05868             ast_db_del(db_chan_name, SRVST_DBKEY);
05869          }
05870       }
05871 #endif   /* defined(HAVE_PRI_SERVICE_MESSAGES) */
05872       /* Free associated memory */
05873       destroy_dahdi_pvt(p);
05874       ast_verb(3, "Unregistered channel %d\n", chan);
05875    }
05876    ifcount = 0;
05877    ast_mutex_unlock(&iflock);
05878 
05879 #if defined(HAVE_PRI)
05880    /* Destroy all of the no B channel interface lists */
05881    for (span = 0; span < NUM_SPANS; ++span) {
05882       if (!pris[span].dchannels[0]) {
05883          break;
05884       }
05885       pri = &pris[span].pri;
05886       ast_mutex_lock(&pri->lock);
05887       while (pri->no_b_chan_iflist) {
05888          p = pri->no_b_chan_iflist;
05889 
05890          /* Free associated memory */
05891          destroy_dahdi_pvt(p);
05892       }
05893       ast_mutex_unlock(&pri->lock);
05894    }
05895 #endif   /* defined(HAVE_PRI) */
05896 }
05897 
05898 #if defined(HAVE_PRI)
05899 static char *dahdi_send_keypad_facility_app = "DAHDISendKeypadFacility";
05900 
05901 static int dahdi_send_keypad_facility_exec(struct ast_channel *chan, const char *digits)
05902 {
05903    /* Data will be our digit string */
05904    struct dahdi_pvt *p;
05905 
05906    if (ast_strlen_zero(digits)) {
05907       ast_debug(1, "No digit string sent to application!\n");
05908       return -1;
05909    }
05910 
05911    p = (struct dahdi_pvt *)chan->tech_pvt;
05912 
05913    if (!p) {
05914       ast_debug(1, "Unable to find technology private\n");
05915       return -1;
05916    }
05917 
05918    pri_send_keypad_facility_exec(p->sig_pvt, digits);
05919 
05920    return 0;
05921 }
05922 #endif   /* defined(HAVE_PRI) */
05923 
05924 #if defined(HAVE_PRI)
05925 #if defined(HAVE_PRI_PROG_W_CAUSE)
05926 static char *dahdi_send_callrerouting_facility_app = "DAHDISendCallreroutingFacility";
05927 
05928 static int dahdi_send_callrerouting_facility_exec(struct ast_channel *chan, const char *data)
05929 {
05930    /* Data will be our digit string */
05931    struct dahdi_pvt *pvt;
05932    char *parse;
05933    int res;
05934    AST_DECLARE_APP_ARGS(args,
05935       AST_APP_ARG(destination);
05936       AST_APP_ARG(original);
05937       AST_APP_ARG(reason);
05938    );
05939 
05940    if (ast_strlen_zero(data)) {
05941       ast_log(LOG_DEBUG, "No data sent to application!\n");
05942       return -1;
05943    }
05944    if (chan->tech != &dahdi_tech) {
05945       ast_log(LOG_DEBUG, "Only DAHDI technology accepted!\n");
05946       return -1;
05947    }
05948    pvt = (struct dahdi_pvt *) chan->tech_pvt;
05949    if (!pvt) {
05950       ast_log(LOG_DEBUG, "Unable to find technology private\n");
05951       return -1;
05952    }
05953    switch (pvt->sig) {
05954    case SIG_PRI_LIB_HANDLE_CASES:
05955       break;
05956    default:
05957       ast_log(LOG_DEBUG, "callrerouting attempted on non-ISDN channel %s\n",
05958          chan->name);
05959       return -1;
05960    }
05961 
05962    parse = ast_strdupa(data);
05963    AST_STANDARD_APP_ARGS(args, parse);
05964 
05965    if (ast_strlen_zero(args.destination)) {
05966       ast_log(LOG_WARNING, "callrerouting facility requires at least destination number argument\n");
05967       return -1;
05968    }
05969 
05970    if (ast_strlen_zero(args.original)) {
05971       ast_log(LOG_WARNING, "Callrerouting Facility without original called number argument\n");
05972       args.original = NULL;
05973    }
05974 
05975    if (ast_strlen_zero(args.reason)) {
05976       ast_log(LOG_NOTICE, "Callrerouting Facility without diversion reason argument, defaulting to unknown\n");
05977       args.reason = NULL;
05978    }
05979 
05980    res = pri_send_callrerouting_facility_exec(pvt->sig_pvt, chan->_state,
05981       args.destination, args.original, args.reason);
05982    if (!res) {
05983       /*
05984        * Wait up to 5 seconds for a reply before hanging up this call
05985        * leg if the peer does not disconnect first.
05986        */
05987       ast_safe_sleep(chan, 5000);
05988    }
05989 
05990    return -1;
05991 }
05992 #endif   /* defined(HAVE_PRI_PROG_W_CAUSE) */
05993 #endif   /* defined(HAVE_PRI) */
05994 
05995 #if defined(HAVE_OPENR2)
05996 static const char * const dahdi_accept_r2_call_app = "DAHDIAcceptR2Call";
05997 
05998 static int dahdi_accept_r2_call_exec(struct ast_channel *chan, const char *data)
05999 {
06000    /* data is whether to accept with charge or no charge */
06001    openr2_call_mode_t accept_mode;
06002    int res, timeout, maxloops;
06003    struct ast_frame *f;
06004    struct dahdi_pvt *p;
06005    char *parse;
06006    AST_DECLARE_APP_ARGS(args,
06007          AST_APP_ARG(charge);
06008    );
06009 
06010    if (ast_strlen_zero(data)) {
06011       ast_log(LOG_DEBUG, "No data sent to application!\n");
06012       return -1;
06013    }
06014 
06015    if (chan->tech != &dahdi_tech) {
06016       ast_log(LOG_DEBUG, "Only DAHDI technology accepted!\n");
06017       return -1;
06018    }
06019 
06020    p = (struct dahdi_pvt *)chan->tech_pvt;
06021    if (!p) {
06022       ast_log(LOG_DEBUG, "Unable to find technology private!\n");
06023       return -1;
06024    }
06025 
06026    parse = ast_strdupa(data);
06027    AST_STANDARD_APP_ARGS(args, parse);
06028 
06029    if (ast_strlen_zero(args.charge)) {
06030       ast_log(LOG_WARNING, "DAHDIAcceptR2Call requires 'yes' or 'no' for the charge parameter\n");
06031       return -1;
06032    }
06033 
06034    ast_mutex_lock(&p->lock);
06035    if (!p->mfcr2 || !p->mfcr2call) {
06036       ast_mutex_unlock(&p->lock);
06037       ast_log(LOG_DEBUG, "Channel %s does not seems to be an R2 active channel!\n", chan->name);
06038       return -1;
06039    }
06040 
06041    if (p->mfcr2_call_accepted) {
06042       ast_mutex_unlock(&p->lock);
06043       ast_log(LOG_DEBUG, "MFC/R2 call already accepted on channel %s!\n", chan->name);
06044       return 0;
06045    }
06046    accept_mode = ast_true(args.charge) ? OR2_CALL_WITH_CHARGE : OR2_CALL_NO_CHARGE;
06047    if (openr2_chan_accept_call(p->r2chan, accept_mode)) {
06048       ast_mutex_unlock(&p->lock);
06049       ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n");
06050       return -1;
06051    }
06052    ast_mutex_unlock(&p->lock);
06053 
06054    res = 0;
06055    timeout = 100;
06056    maxloops = 50; /* wait up to 5 seconds */
06057    /* we need to read() until the call is accepted */
06058    while (maxloops > 0) {
06059       maxloops--;
06060       if (ast_check_hangup(chan)) {
06061          break;
06062       }
06063       res = ast_waitfor(chan, timeout);
06064       if (res < 0) {
06065          ast_log(LOG_DEBUG, "ast_waitfor failed on channel %s, going out ...\n", chan->name);
06066          res = -1;
06067          break;
06068       }
06069       if (res == 0) {
06070          continue;
06071       }
06072       f = ast_read(chan);
06073       if (!f) {
06074          ast_log(LOG_DEBUG, "No frame read on channel %s, going out ...\n", chan->name);
06075          res = -1;
06076          break;
06077       }
06078       if (f->frametype == AST_FRAME_CONTROL && f->subclass.integer == AST_CONTROL_HANGUP) {
06079          ast_log(LOG_DEBUG, "Got HANGUP frame on channel %s, going out ...\n", chan->name);
06080          ast_frfree(f);
06081          res = -1;
06082          break;
06083       }
06084       ast_frfree(f);
06085       ast_mutex_lock(&p->lock);
06086       if (p->mfcr2_call_accepted) {
06087          ast_mutex_unlock(&p->lock);
06088          ast_log(LOG_DEBUG, "Accepted MFC/R2 call!\n");
06089          break;
06090       }
06091       ast_mutex_unlock(&p->lock);
06092    }
06093    if (res == -1) {
06094       ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n");
06095    }
06096    return res;
06097 }
06098 
06099 static openr2_call_disconnect_cause_t dahdi_ast_cause_to_r2_cause(int cause)
06100 {
06101    openr2_call_disconnect_cause_t r2cause = OR2_CAUSE_NORMAL_CLEARING;
06102    switch (cause) {
06103    case AST_CAUSE_USER_BUSY:
06104    case AST_CAUSE_CALL_REJECTED:
06105    case AST_CAUSE_INTERWORKING: /* I don't know wtf is this but is used sometimes when ekiga rejects a call */
06106       r2cause = OR2_CAUSE_BUSY_NUMBER;
06107       break;
06108 
06109    case AST_CAUSE_NORMAL_CIRCUIT_CONGESTION:
06110    case AST_CAUSE_SWITCH_CONGESTION:
06111       r2cause = OR2_CAUSE_NETWORK_CONGESTION;
06112       break;
06113 
06114    case AST_CAUSE_UNALLOCATED:
06115       r2cause = OR2_CAUSE_UNALLOCATED_NUMBER;
06116       break;
06117 
06118    case AST_CAUSE_NETWORK_OUT_OF_ORDER:
06119    case AST_CAUSE_DESTINATION_OUT_OF_ORDER:
06120       r2cause = OR2_CAUSE_OUT_OF_ORDER;
06121       break;
06122 
06123    case AST_CAUSE_NO_ANSWER:
06124    case AST_CAUSE_NO_USER_RESPONSE:
06125       r2cause = OR2_CAUSE_NO_ANSWER;
06126       break;
06127 
06128    default:
06129       r2cause = OR2_CAUSE_NORMAL_CLEARING;
06130       break;
06131    }
06132    ast_log(LOG_DEBUG, "ast cause %d resulted in openr2 cause %d/%s\n",
06133          cause, r2cause, openr2_proto_get_disconnect_string(r2cause));
06134    return r2cause;
06135 }
06136 #endif
06137 
06138 static int revert_fax_buffers(struct dahdi_pvt *p, struct ast_channel *ast)
06139 {
06140    if (p->bufferoverrideinuse) {
06141       /* faxbuffers are in use, revert them */
06142       struct dahdi_bufferinfo bi = {
06143          .txbufpolicy = p->buf_policy,
06144          .rxbufpolicy = p->buf_policy,
06145          .bufsize = p->bufsize,
06146          .numbufs = p->buf_no
06147       };
06148       int bpres;
06149 
06150       if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
06151          ast_log(LOG_WARNING, "Channel '%s' unable to revert buffer policy: %s\n", ast->name, strerror(errno));
06152       }
06153       p->bufferoverrideinuse = 0;
06154       return bpres;
06155    }
06156 
06157    return -1;
06158 }
06159 
06160 static int dahdi_hangup(struct ast_channel *ast)
06161 {
06162    int res = 0;
06163    int idx,x;
06164    int law;
06165    /*static int restore_gains(struct dahdi_pvt *p);*/
06166    struct dahdi_pvt *p = ast->tech_pvt;
06167    struct dahdi_params par;
06168 
06169    ast_debug(1, "dahdi_hangup(%s)\n", ast->name);
06170    if (!ast->tech_pvt) {
06171       ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
06172       return 0;
06173    }
06174 
06175    ast_mutex_lock(&p->lock);
06176    p->exten[0] = '\0';
06177    if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
06178       dahdi_confmute(p, 0);
06179       restore_gains(p);
06180       p->ignoredtmf = 0;
06181       p->waitingfordt.tv_sec = 0;
06182 
06183       res = analog_hangup(p->sig_pvt, ast);
06184       revert_fax_buffers(p, ast);
06185 
06186       goto hangup_out;
06187    } else {
06188       p->cid_num[0] = '\0';
06189       p->cid_name[0] = '\0';
06190       p->cid_subaddr[0] = '\0';
06191    }
06192 
06193 #if defined(HAVE_PRI)
06194    if (dahdi_sig_pri_lib_handles(p->sig)) {
06195       x = 1;
06196       ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
06197 
06198       dahdi_confmute(p, 0);
06199       p->muting = 0;
06200       restore_gains(p);
06201       if (p->dsp) {
06202          ast_dsp_free(p->dsp);
06203          p->dsp = NULL;
06204       }
06205       p->ignoredtmf = 0;
06206 
06207       /* Real channel, do some fixup */
06208       p->subs[SUB_REAL].owner = NULL;
06209       p->subs[SUB_REAL].needbusy = 0;
06210       dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
06211 
06212       p->owner = NULL;
06213       p->cid_tag[0] = '\0';
06214       p->ringt = 0;/* Probably not used in this mode.  Reset anyway. */
06215       p->distinctivering = 0;/* Probably not used in this mode. Reset anyway. */
06216       p->confirmanswer = 0;/* Probably not used in this mode. Reset anyway. */
06217       p->outgoing = 0;
06218       p->digital = 0;
06219       p->faxhandled = 0;
06220       p->pulsedial = 0;/* Probably not used in this mode. Reset anyway. */
06221 
06222       revert_fax_buffers(p, ast);
06223 
06224       p->law = p->law_default;
06225       law = p->law_default;
06226       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
06227       if (res < 0) {
06228          ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n",
06229             p->channel, strerror(errno));
06230       }
06231 
06232       sig_pri_hangup(p->sig_pvt, ast);
06233 
06234       tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06235       dahdi_disable_ec(p);
06236 
06237       x = 0;
06238       ast_channel_setoption(ast, AST_OPTION_TDD, &x, sizeof(char), 0);
06239       p->didtdd = 0;/* Probably not used in this mode. Reset anyway. */
06240 
06241       p->rdnis[0] = '\0';
06242       update_conf(p);
06243       reset_conf(p);
06244 
06245       /* Restore data mode */
06246       x = 0;
06247       ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
06248 
06249       if (num_restart_pending == 0) {
06250          restart_monitor();
06251       }
06252       goto hangup_out;
06253    }
06254 #endif   /* defined(HAVE_PRI) */
06255 
06256 #if defined(HAVE_SS7)
06257    if (p->sig == SIG_SS7) {
06258       x = 1;
06259       ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
06260 
06261       dahdi_confmute(p, 0);
06262       p->muting = 0;
06263       restore_gains(p);
06264       if (p->dsp) {
06265          ast_dsp_free(p->dsp);
06266          p->dsp = NULL;
06267       }
06268       p->ignoredtmf = 0;
06269 
06270       /* Real channel, do some fixup */
06271       p->subs[SUB_REAL].owner = NULL;
06272       p->subs[SUB_REAL].needbusy = 0;
06273       dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
06274 
06275       p->owner = NULL;
06276       p->ringt = 0;/* Probably not used in this mode.  Reset anyway. */
06277       p->distinctivering = 0;/* Probably not used in this mode. Reset anyway. */
06278       p->confirmanswer = 0;/* Probably not used in this mode. Reset anyway. */
06279       p->outgoing = 0;
06280       p->digital = 0;
06281       p->faxhandled = 0;
06282       p->pulsedial = 0;/* Probably not used in this mode. Reset anyway. */
06283 
06284       revert_fax_buffers(p, ast);
06285 
06286       p->law = p->law_default;
06287       law = p->law_default;
06288       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
06289       if (res < 0) {
06290          ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n",
06291             p->channel, strerror(errno));
06292       }
06293 
06294       sig_ss7_hangup(p->sig_pvt, ast);
06295 
06296       tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06297       dahdi_disable_ec(p);
06298 
06299       x = 0;
06300       ast_channel_setoption(ast, AST_OPTION_TDD, &x, sizeof(char), 0);
06301       p->didtdd = 0;/* Probably not used in this mode. Reset anyway. */
06302 
06303       update_conf(p);
06304       reset_conf(p);
06305 
06306       /* Restore data mode */
06307       x = 0;
06308       ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
06309 
06310       if (num_restart_pending == 0) {
06311          restart_monitor();
06312       }
06313       goto hangup_out;
06314    }
06315 #endif   /* defined(HAVE_SS7) */
06316 
06317    idx = dahdi_get_index(ast, p, 1);
06318 
06319    dahdi_confmute(p, 0);
06320    p->muting = 0;
06321    restore_gains(p);
06322    if (p->origcid_num) {
06323       ast_copy_string(p->cid_num, p->origcid_num, sizeof(p->cid_num));
06324       ast_free(p->origcid_num);
06325       p->origcid_num = NULL;
06326    }
06327    if (p->origcid_name) {
06328       ast_copy_string(p->cid_name, p->origcid_name, sizeof(p->cid_name));
06329       ast_free(p->origcid_name);
06330       p->origcid_name = NULL;
06331    }
06332    if (p->dsp)
06333       ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
06334 
06335    ast_debug(1, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n",
06336       p->channel, idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
06337    p->ignoredtmf = 0;
06338 
06339    if (idx > -1) {
06340       /* Real channel, do some fixup */
06341       p->subs[idx].owner = NULL;
06342       p->subs[idx].needanswer = 0;
06343       p->subs[idx].needflash = 0;
06344       p->subs[idx].needringing = 0;
06345       p->subs[idx].needbusy = 0;
06346       p->subs[idx].needcongestion = 0;
06347       p->subs[idx].linear = 0;
06348       p->polarity = POLARITY_IDLE;
06349       dahdi_setlinear(p->subs[idx].dfd, 0);
06350       if (idx == SUB_REAL) {
06351          if ((p->subs[SUB_CALLWAIT].dfd > -1) && (p->subs[SUB_THREEWAY].dfd > -1)) {
06352             ast_debug(1, "Normal call hung up with both three way call and a call waiting call in place?\n");
06353             if (p->subs[SUB_CALLWAIT].inthreeway) {
06354                /* We had flipped over to answer a callwait and now it's gone */
06355                ast_debug(1, "We were flipped over to the callwait, moving back and unowning.\n");
06356                /* Move to the call-wait, but un-own us until they flip back. */
06357                swap_subs(p, SUB_CALLWAIT, SUB_REAL);
06358                unalloc_sub(p, SUB_CALLWAIT);
06359                p->owner = NULL;
06360             } else {
06361                /* The three way hung up, but we still have a call wait */
06362                ast_debug(1, "We were in the threeway and have a callwait still.  Ditching the threeway.\n");
06363                swap_subs(p, SUB_THREEWAY, SUB_REAL);
06364                unalloc_sub(p, SUB_THREEWAY);
06365                if (p->subs[SUB_REAL].inthreeway) {
06366                   /* This was part of a three way call.  Immediately make way for
06367                      another call */
06368                   ast_debug(1, "Call was complete, setting owner to former third call\n");
06369                   p->owner = p->subs[SUB_REAL].owner;
06370                } else {
06371                   /* This call hasn't been completed yet...  Set owner to NULL */
06372                   ast_debug(1, "Call was incomplete, setting owner to NULL\n");
06373                   p->owner = NULL;
06374                }
06375                p->subs[SUB_REAL].inthreeway = 0;
06376             }
06377          } else if (p->subs[SUB_CALLWAIT].dfd > -1) {
06378             /* Move to the call-wait and switch back to them. */
06379             swap_subs(p, SUB_CALLWAIT, SUB_REAL);
06380             unalloc_sub(p, SUB_CALLWAIT);
06381             p->owner = p->subs[SUB_REAL].owner;
06382             if (p->owner->_state != AST_STATE_UP)
06383                p->subs[SUB_REAL].needanswer = 1;
06384             if (ast_bridged_channel(p->subs[SUB_REAL].owner))
06385                ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
06386          } else if (p->subs[SUB_THREEWAY].dfd > -1) {
06387             swap_subs(p, SUB_THREEWAY, SUB_REAL);
06388             unalloc_sub(p, SUB_THREEWAY);
06389             if (p->subs[SUB_REAL].inthreeway) {
06390                /* This was part of a three way call.  Immediately make way for
06391                   another call */
06392                ast_debug(1, "Call was complete, setting owner to former third call\n");
06393                p->owner = p->subs[SUB_REAL].owner;
06394             } else {
06395                /* This call hasn't been completed yet...  Set owner to NULL */
06396                ast_debug(1, "Call was incomplete, setting owner to NULL\n");
06397                p->owner = NULL;
06398             }
06399             p->subs[SUB_REAL].inthreeway = 0;
06400          }
06401       } else if (idx == SUB_CALLWAIT) {
06402          /* Ditch the holding callwait call, and immediately make it availabe */
06403          if (p->subs[SUB_CALLWAIT].inthreeway) {
06404             /* This is actually part of a three way, placed on hold.  Place the third part
06405                on music on hold now */
06406             if (p->subs[SUB_THREEWAY].owner && ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
06407                ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
06408                   S_OR(p->mohsuggest, NULL),
06409                   !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
06410             }
06411             p->subs[SUB_THREEWAY].inthreeway = 0;
06412             /* Make it the call wait now */
06413             swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
06414             unalloc_sub(p, SUB_THREEWAY);
06415          } else
06416             unalloc_sub(p, SUB_CALLWAIT);
06417       } else if (idx == SUB_THREEWAY) {
06418          if (p->subs[SUB_CALLWAIT].inthreeway) {
06419             /* The other party of the three way call is currently in a call-wait state.
06420                Start music on hold for them, and take the main guy out of the third call */
06421             if (p->subs[SUB_CALLWAIT].owner && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
06422                ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
06423                   S_OR(p->mohsuggest, NULL),
06424                   !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
06425             }
06426             p->subs[SUB_CALLWAIT].inthreeway = 0;
06427          }
06428          p->subs[SUB_REAL].inthreeway = 0;
06429          /* If this was part of a three way call index, let us make
06430             another three way call */
06431          unalloc_sub(p, SUB_THREEWAY);
06432       } else {
06433          /* This wasn't any sort of call, but how are we an index? */
06434          ast_log(LOG_WARNING, "Index found but not any type of call?\n");
06435       }
06436    }
06437 
06438    if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) {
06439       p->owner = NULL;
06440       p->ringt = 0;
06441       p->distinctivering = 0;
06442       p->confirmanswer = 0;
06443       p->outgoing = 0;
06444       p->digital = 0;
06445       p->faxhandled = 0;
06446       p->pulsedial = 0;
06447       if (p->dsp) {
06448          ast_dsp_free(p->dsp);
06449          p->dsp = NULL;
06450       }
06451 
06452       revert_fax_buffers(p, ast);
06453 
06454       p->law = p->law_default;
06455       law = p->law_default;
06456       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
06457       if (res < 0)
06458          ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
06459       /* Perform low level hangup if no owner left */
06460 #ifdef HAVE_OPENR2
06461       if (p->mfcr2 && p->mfcr2call && openr2_chan_get_direction(p->r2chan) != OR2_DIR_STOPPED) {
06462          ast_log(LOG_DEBUG, "disconnecting MFC/R2 call on chan %d\n", p->channel);
06463          /* If it's an incoming call, check the mfcr2_forced_release setting */
06464          if (openr2_chan_get_direction(p->r2chan) == OR2_DIR_BACKWARD && p->mfcr2_forced_release) {
06465             dahdi_r2_disconnect_call(p, OR2_CAUSE_FORCED_RELEASE);
06466          } else {
06467             const char *r2causestr = pbx_builtin_getvar_helper(ast, "MFCR2_CAUSE");
06468             int r2cause_user = r2causestr ? atoi(r2causestr) : 0;
06469             openr2_call_disconnect_cause_t r2cause = r2cause_user ? dahdi_ast_cause_to_r2_cause(r2cause_user)
06470                                                              : dahdi_ast_cause_to_r2_cause(ast->hangupcause);
06471             dahdi_r2_disconnect_call(p, r2cause);
06472          }
06473       } else if (p->mfcr2call) {
06474          ast_log(LOG_DEBUG, "Clearing call request on channel %d\n", p->channel);
06475          /* since ast_request() was called but not ast_call() we have not yet dialed
06476          and the openr2 stack will not call on_call_end callback, we need to unset
06477          the mfcr2call flag and bump the monitor count so the monitor thread can take
06478          care of this channel events from now on */
06479          p->mfcr2call = 0;
06480       }
06481 #endif
06482       switch (p->sig) {
06483       case SIG_SS7:
06484       case SIG_MFCR2:
06485       case SIG_PRI_LIB_HANDLE_CASES:
06486       case 0:
06487          break;
06488       default:
06489          res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
06490          break;
06491       }
06492       if (res < 0) {
06493          ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast->name);
06494       }
06495       switch (p->sig) {
06496       case SIG_FXOGS:
06497       case SIG_FXOLS:
06498       case SIG_FXOKS:
06499          memset(&par, 0, sizeof(par));
06500          res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
06501          if (!res) {
06502             struct analog_pvt *analog_p = p->sig_pvt;
06503 #if 0
06504             ast_debug(1, "Hanging up channel %d, offhook = %d\n", p->channel, par.rxisoffhook);
06505 #endif
06506             /* If they're off hook, try playing congestion */
06507             if ((par.rxisoffhook) && (!(p->radio || (p->oprmode < 0))))
06508                tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
06509             else
06510                tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06511             analog_p->fxsoffhookstate = par.rxisoffhook;
06512          }
06513          break;
06514       case SIG_FXSGS:
06515       case SIG_FXSLS:
06516       case SIG_FXSKS:
06517          /* Make sure we're not made available for at least two seconds assuming
06518          we were actually used for an inbound or outbound call. */
06519          if (ast->_state != AST_STATE_RESERVED) {
06520             time(&p->guardtime);
06521             p->guardtime += 2;
06522          }
06523          break;
06524       default:
06525          tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06526          break;
06527       }
06528       if (p->sig)
06529          dahdi_disable_ec(p);
06530       x = 0;
06531       ast_channel_setoption(ast,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0);
06532       ast_channel_setoption(ast,AST_OPTION_TDD,&x,sizeof(char),0);
06533       p->didtdd = 0;
06534       p->callwaitcas = 0;
06535       p->callwaiting = p->permcallwaiting;
06536       p->hidecallerid = p->permhidecallerid;
06537       p->waitingfordt.tv_sec = 0;
06538       p->dialing = 0;
06539       p->rdnis[0] = '\0';
06540       update_conf(p);
06541       reset_conf(p);
06542       /* Restore data mode */
06543       switch (p->sig) {
06544       case SIG_PRI_LIB_HANDLE_CASES:
06545       case SIG_SS7:
06546          x = 0;
06547          ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
06548          break;
06549       default:
06550          break;
06551       }
06552       if (num_restart_pending == 0)
06553          restart_monitor();
06554    }
06555 
06556    p->callwaitingrepeat = 0;
06557    p->cidcwexpire = 0;
06558    p->cid_suppress_expire = 0;
06559    p->oprmode = 0;
06560 hangup_out:
06561    ast->tech_pvt = NULL;
06562    ast_free(p->cidspill);
06563    p->cidspill = NULL;
06564 
06565    ast_mutex_unlock(&p->lock);
06566    ast_verb(3, "Hungup '%s'\n", ast->name);
06567 
06568    ast_mutex_lock(&iflock);
06569    if (p->restartpending) {
06570       num_restart_pending--;
06571    }
06572 
06573    if (p->destroy) {
06574       destroy_channel(p, 0);
06575    }
06576    ast_mutex_unlock(&iflock);
06577 
06578    ast_module_unref(ast_module_info->self);
06579    return 0;
06580 }
06581 
06582 static int dahdi_answer(struct ast_channel *ast)
06583 {
06584    struct dahdi_pvt *p = ast->tech_pvt;
06585    int res = 0;
06586    int idx;
06587    ast_setstate(ast, AST_STATE_UP);/*! \todo XXX this is redundantly set by the analog and PRI submodules! */
06588    ast_mutex_lock(&p->lock);
06589    idx = dahdi_get_index(ast, p, 0);
06590    if (idx < 0)
06591       idx = SUB_REAL;
06592    /* nothing to do if a radio channel */
06593    if ((p->radio || (p->oprmode < 0))) {
06594       ast_mutex_unlock(&p->lock);
06595       return 0;
06596    }
06597 
06598    if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
06599       res = analog_answer(p->sig_pvt, ast);
06600       ast_mutex_unlock(&p->lock);
06601       return res;
06602    }
06603 
06604    switch (p->sig) {
06605 #if defined(HAVE_PRI)
06606    case SIG_PRI_LIB_HANDLE_CASES:
06607       res = sig_pri_answer(p->sig_pvt, ast);
06608       break;
06609 #endif   /* defined(HAVE_PRI) */
06610 #if defined(HAVE_SS7)
06611    case SIG_SS7:
06612       res = sig_ss7_answer(p->sig_pvt, ast);
06613       break;
06614 #endif   /* defined(HAVE_SS7) */
06615 #ifdef HAVE_OPENR2
06616    case SIG_MFCR2:
06617       if (!p->mfcr2_call_accepted) {
06618          /* The call was not accepted on offer nor the user, so it must be accepted now before answering,
06619             openr2_chan_answer_call will be called when the callback on_call_accepted is executed */
06620          p->mfcr2_answer_pending = 1;
06621          if (p->mfcr2_charge_calls) {
06622             ast_log(LOG_DEBUG, "Accepting MFC/R2 call with charge before answering on chan %d\n", p->channel);
06623             openr2_chan_accept_call(p->r2chan, OR2_CALL_WITH_CHARGE);
06624          } else {
06625             ast_log(LOG_DEBUG, "Accepting MFC/R2 call with no charge before answering on chan %d\n", p->channel);
06626             openr2_chan_accept_call(p->r2chan, OR2_CALL_NO_CHARGE);
06627          }
06628       } else {
06629          ast_log(LOG_DEBUG, "Answering MFC/R2 call on chan %d\n", p->channel);
06630          dahdi_r2_answer(p);
06631       }
06632       break;
06633 #endif
06634    case 0:
06635       ast_mutex_unlock(&p->lock);
06636       return 0;
06637    default:
06638       ast_log(LOG_WARNING, "Don't know how to answer signalling %d (channel %d)\n", p->sig, p->channel);
06639       res = -1;
06640       break;
06641    }
06642    ast_mutex_unlock(&p->lock);
06643    return res;
06644 }
06645 
06646 static void disable_dtmf_detect(struct dahdi_pvt *p)
06647 {
06648    int val = 0;
06649 
06650    p->ignoredtmf = 1;
06651 
06652    ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
06653 
06654    if (!p->hardwaredtmf && p->dsp) {
06655       p->dsp_features &= ~DSP_FEATURE_DIGIT_DETECT;
06656       ast_dsp_set_features(p->dsp, p->dsp_features);
06657    }
06658 }
06659 
06660 static void enable_dtmf_detect(struct dahdi_pvt *p)
06661 {
06662    int val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
06663 
06664    if (p->channel == CHAN_PSEUDO)
06665       return;
06666 
06667    p->ignoredtmf = 0;
06668 
06669    ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
06670 
06671    if (!p->hardwaredtmf && p->dsp) {
06672       p->dsp_features |= DSP_FEATURE_DIGIT_DETECT;
06673       ast_dsp_set_features(p->dsp, p->dsp_features);
06674    }
06675 }
06676 
06677 static int dahdi_queryoption(struct ast_channel *chan, int option, void *data, int *datalen)
06678 {
06679    char *cp;
06680    struct dahdi_pvt *p = chan->tech_pvt;
06681 
06682    /* all supported options require data */
06683    if (!p || !data || (*datalen < 1)) {
06684       errno = EINVAL;
06685       return -1;
06686    }
06687 
06688    switch (option) {
06689    case AST_OPTION_DIGIT_DETECT:
06690       cp = (char *) data;
06691       *cp = p->ignoredtmf ? 0 : 1;
06692       ast_debug(1, "Reporting digit detection %sabled on %s\n", *cp ? "en" : "dis", chan->name);
06693       break;
06694    case AST_OPTION_FAX_DETECT:
06695       cp = (char *) data;
06696       *cp = (p->dsp_features & DSP_FEATURE_FAX_DETECT) ? 0 : 1;
06697       ast_debug(1, "Reporting fax tone detection %sabled on %s\n", *cp ? "en" : "dis", chan->name);
06698       break;
06699    case AST_OPTION_CC_AGENT_TYPE:
06700 #if defined(HAVE_PRI)
06701 #if defined(HAVE_PRI_CCSS)
06702       if (dahdi_sig_pri_lib_handles(p->sig)) {
06703          ast_copy_string((char *) data, dahdi_pri_cc_type, *datalen);
06704          break;
06705       }
06706 #endif   /* defined(HAVE_PRI_CCSS) */
06707 #endif   /* defined(HAVE_PRI) */
06708       return -1;
06709    default:
06710       return -1;
06711    }
06712 
06713    errno = 0;
06714 
06715    return 0;
06716 }
06717 
06718 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen)
06719 {
06720    char *cp;
06721    signed char *scp;
06722    int x;
06723    int idx;
06724    struct dahdi_pvt *p = chan->tech_pvt, *pp;
06725    struct oprmode *oprmode;
06726 
06727 
06728    /* all supported options require data */
06729    if (!p || !data || (datalen < 1)) {
06730       errno = EINVAL;
06731       return -1;
06732    }
06733 
06734    switch (option) {
06735    case AST_OPTION_TXGAIN:
06736       scp = (signed char *) data;
06737       idx = dahdi_get_index(chan, p, 0);
06738       if (idx < 0) {
06739          ast_log(LOG_WARNING, "No index in TXGAIN?\n");
06740          return -1;
06741       }
06742       ast_debug(1, "Setting actual tx gain on %s to %f\n", chan->name, p->txgain + (float) *scp);
06743       return set_actual_txgain(p->subs[idx].dfd, p->txgain + (float) *scp, p->txdrc, p->law);
06744    case AST_OPTION_RXGAIN:
06745       scp = (signed char *) data;
06746       idx = dahdi_get_index(chan, p, 0);
06747       if (idx < 0) {
06748          ast_log(LOG_WARNING, "No index in RXGAIN?\n");
06749          return -1;
06750       }
06751       ast_debug(1, "Setting actual rx gain on %s to %f\n", chan->name, p->rxgain + (float) *scp);
06752       return set_actual_rxgain(p->subs[idx].dfd, p->rxgain + (float) *scp, p->rxdrc, p->law);
06753    case AST_OPTION_TONE_VERIFY:
06754       if (!p->dsp)
06755          break;
06756       cp = (char *) data;
06757       switch (*cp) {
06758       case 1:
06759          ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",chan->name);
06760          ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | p->dtmfrelax);  /* set mute mode if desired */
06761          break;
06762       case 2:
06763          ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",chan->name);
06764          ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX | p->dtmfrelax);  /* set mute mode if desired */
06765          break;
06766       default:
06767          ast_debug(1, "Set option TONE VERIFY, mode: OFF(0) on %s\n",chan->name);
06768          ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);  /* set mute mode if desired */
06769          break;
06770       }
06771       break;
06772    case AST_OPTION_TDD:
06773       /* turn on or off TDD */
06774       cp = (char *) data;
06775       p->mate = 0;
06776       if (!*cp) { /* turn it off */
06777          ast_debug(1, "Set option TDD MODE, value: OFF(0) on %s\n",chan->name);
06778          if (p->tdd)
06779             tdd_free(p->tdd);
06780          p->tdd = 0;
06781          break;
06782       }
06783       ast_debug(1, "Set option TDD MODE, value: %s(%d) on %s\n",
06784          (*cp == 2) ? "MATE" : "ON", (int) *cp, chan->name);
06785       dahdi_disable_ec(p);
06786       /* otherwise, turn it on */
06787       if (!p->didtdd) { /* if havent done it yet */
06788          unsigned char mybuf[41000];/*! \todo XXX This is an abuse of the stack!! */
06789          unsigned char *buf;
06790          int size, res, fd, len;
06791          struct pollfd fds[1];
06792 
06793          buf = mybuf;
06794          memset(buf, 0x7f, sizeof(mybuf)); /* set to silence */
06795          ast_tdd_gen_ecdisa(buf + 16000, 16000);  /* put in tone */
06796          len = 40000;
06797          idx = dahdi_get_index(chan, p, 0);
06798          if (idx < 0) {
06799             ast_log(LOG_WARNING, "No index in TDD?\n");
06800             return -1;
06801          }
06802          fd = p->subs[idx].dfd;
06803          while (len) {
06804             if (ast_check_hangup(chan))
06805                return -1;
06806             size = len;
06807             if (size > READ_SIZE)
06808                size = READ_SIZE;
06809             fds[0].fd = fd;
06810             fds[0].events = POLLPRI | POLLOUT;
06811             fds[0].revents = 0;
06812             res = poll(fds, 1, -1);
06813             if (!res) {
06814                ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
06815                continue;
06816             }
06817             /* if got exception */
06818             if (fds[0].revents & POLLPRI)
06819                return -1;
06820             if (!(fds[0].revents & POLLOUT)) {
06821                ast_debug(1, "write fd not ready on channel %d\n", p->channel);
06822                continue;
06823             }
06824             res = write(fd, buf, size);
06825             if (res != size) {
06826                if (res == -1) return -1;
06827                ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
06828                break;
06829             }
06830             len -= size;
06831             buf += size;
06832          }
06833          p->didtdd = 1; /* set to have done it now */
06834       }
06835       if (*cp == 2) { /* Mate mode */
06836          if (p->tdd)
06837             tdd_free(p->tdd);
06838          p->tdd = 0;
06839          p->mate = 1;
06840          break;
06841       }
06842       if (!p->tdd) { /* if we don't have one yet */
06843          p->tdd = tdd_new(); /* allocate one */
06844       }
06845       break;
06846    case AST_OPTION_RELAXDTMF:  /* Relax DTMF decoding (or not) */
06847       if (!p->dsp)
06848          break;
06849       cp = (char *) data;
06850       ast_debug(1, "Set option RELAX DTMF, value: %s(%d) on %s\n",
06851          *cp ? "ON" : "OFF", (int) *cp, chan->name);
06852       ast_dsp_set_digitmode(p->dsp, ((*cp) ? DSP_DIGITMODE_RELAXDTMF : DSP_DIGITMODE_DTMF) | p->dtmfrelax);
06853       break;
06854    case AST_OPTION_AUDIO_MODE:  /* Set AUDIO mode (or not) */
06855 #if defined(HAVE_PRI)
06856       if (dahdi_sig_pri_lib_handles(p->sig)
06857          && ((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
06858          /* PRI nobch pseudo channel.  Does not handle ioctl(DAHDI_AUDIOMODE) */
06859          break;
06860       }
06861 #endif   /* defined(HAVE_PRI) */
06862 
06863       cp = (char *) data;
06864       if (!*cp) {
06865          ast_debug(1, "Set option AUDIO MODE, value: OFF(0) on %s\n", chan->name);
06866          x = 0;
06867          dahdi_disable_ec(p);
06868       } else {
06869          ast_debug(1, "Set option AUDIO MODE, value: ON(1) on %s\n", chan->name);
06870          x = 1;
06871       }
06872       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x) == -1)
06873          ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, x, strerror(errno));
06874       break;
06875    case AST_OPTION_OPRMODE:  /* Operator services mode */
06876       oprmode = (struct oprmode *) data;
06877       /* We don't support operator mode across technologies */
06878       if (strcasecmp(chan->tech->type, oprmode->peer->tech->type)) {
06879          ast_log(LOG_NOTICE, "Operator mode not supported on %s to %s calls.\n",
06880                chan->tech->type, oprmode->peer->tech->type);
06881          errno = EINVAL;
06882          return -1;
06883       }
06884       pp = oprmode->peer->tech_pvt;
06885       p->oprmode = pp->oprmode = 0;
06886       /* setup peers */
06887       p->oprpeer = pp;
06888       pp->oprpeer = p;
06889       /* setup modes, if any */
06890       if (oprmode->mode)
06891       {
06892          pp->oprmode = oprmode->mode;
06893          p->oprmode = -oprmode->mode;
06894       }
06895       ast_debug(1, "Set Operator Services mode, value: %d on %s/%s\n",
06896          oprmode->mode, chan->name,oprmode->peer->name);
06897       break;
06898    case AST_OPTION_ECHOCAN:
06899       cp = (char *) data;
06900       if (*cp) {
06901          ast_debug(1, "Enabling echo cancellation on %s\n", chan->name);
06902          dahdi_enable_ec(p);
06903       } else {
06904          ast_debug(1, "Disabling echo cancellation on %s\n", chan->name);
06905          dahdi_disable_ec(p);
06906       }
06907       break;
06908    case AST_OPTION_DIGIT_DETECT:
06909       cp = (char *) data;
06910       ast_debug(1, "%sabling digit detection on %s\n", *cp ? "En" : "Dis", chan->name);
06911       if (*cp) {
06912          enable_dtmf_detect(p);
06913       } else {
06914          disable_dtmf_detect(p);
06915       }
06916       break;
06917    case AST_OPTION_FAX_DETECT:
06918       cp = (char *) data;
06919       if (p->dsp) {
06920          ast_debug(1, "%sabling fax tone detection on %s\n", *cp ? "En" : "Dis", chan->name);
06921          if (*cp) {
06922             p->dsp_features |= DSP_FEATURE_FAX_DETECT;
06923          } else {
06924             p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
06925          }
06926          ast_dsp_set_features(p->dsp, p->dsp_features);
06927       }
06928       break;
06929    default:
06930       return -1;
06931    }
06932    errno = 0;
06933 
06934    return 0;
06935 }
06936 
06937 static int dahdi_func_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len)
06938 {
06939    struct dahdi_pvt *p = chan->tech_pvt;
06940    int res = 0;
06941 
06942    if (!p) {
06943       /* No private structure! */
06944       *buf = '\0';
06945       return -1;
06946    }
06947 
06948    if (!strcasecmp(data, "rxgain")) {
06949       ast_mutex_lock(&p->lock);
06950       snprintf(buf, len, "%f", p->rxgain);
06951       ast_mutex_unlock(&p->lock);
06952    } else if (!strcasecmp(data, "txgain")) {
06953       ast_mutex_lock(&p->lock);
06954       snprintf(buf, len, "%f", p->txgain);
06955       ast_mutex_unlock(&p->lock);
06956    } else if (!strcasecmp(data, "dahdi_channel")) {
06957       ast_mutex_lock(&p->lock);
06958       snprintf(buf, len, "%d", p->channel);
06959       ast_mutex_unlock(&p->lock);
06960    } else if (!strcasecmp(data, "dahdi_span")) {
06961       ast_mutex_lock(&p->lock);
06962       snprintf(buf, len, "%d", p->span);
06963       ast_mutex_unlock(&p->lock);
06964    } else if (!strcasecmp(data, "dahdi_type")) {
06965       ast_mutex_lock(&p->lock);
06966       switch (p->sig) {
06967 #if defined(HAVE_OPENR2)
06968       case SIG_MFCR2:
06969          ast_copy_string(buf, "mfc/r2", len);
06970          break;
06971 #endif   /* defined(HAVE_OPENR2) */
06972 #if defined(HAVE_PRI)
06973       case SIG_PRI_LIB_HANDLE_CASES:
06974          ast_copy_string(buf, "pri", len);
06975          break;
06976 #endif   /* defined(HAVE_PRI) */
06977       case 0:
06978          ast_copy_string(buf, "pseudo", len);
06979          break;
06980 #if defined(HAVE_SS7)
06981       case SIG_SS7:
06982          ast_copy_string(buf, "ss7", len);
06983          break;
06984 #endif   /* defined(HAVE_SS7) */
06985       default:
06986          /* The only thing left is analog ports. */
06987          ast_copy_string(buf, "analog", len);
06988          break;
06989       }
06990       ast_mutex_unlock(&p->lock);
06991 #if defined(HAVE_PRI)
06992 #if defined(HAVE_PRI_REVERSE_CHARGE)
06993    } else if (!strcasecmp(data, "reversecharge")) {
06994       ast_mutex_lock(&p->lock);
06995       switch (p->sig) {
06996       case SIG_PRI_LIB_HANDLE_CASES:
06997          snprintf(buf, len, "%d", ((struct sig_pri_chan *) p->sig_pvt)->reverse_charging_indication);
06998          break;
06999       default:
07000          *buf = '\0';
07001          res = -1;
07002          break;
07003       }
07004       ast_mutex_unlock(&p->lock);
07005 #endif
07006 #if defined(HAVE_PRI_SETUP_KEYPAD)
07007    } else if (!strcasecmp(data, "keypad_digits")) {
07008       ast_mutex_lock(&p->lock);
07009       switch (p->sig) {
07010       case SIG_PRI_LIB_HANDLE_CASES:
07011          ast_copy_string(buf, ((struct sig_pri_chan *) p->sig_pvt)->keypad_digits,
07012             len);
07013          break;
07014       default:
07015          *buf = '\0';
07016          res = -1;
07017          break;
07018       }
07019       ast_mutex_unlock(&p->lock);
07020 #endif   /* defined(HAVE_PRI_SETUP_KEYPAD) */
07021    } else if (!strcasecmp(data, "no_media_path")) {
07022       ast_mutex_lock(&p->lock);
07023       switch (p->sig) {
07024       case SIG_PRI_LIB_HANDLE_CASES:
07025          /*
07026           * TRUE if the call is on hold or is call waiting because
07027           * there is no media path available.
07028           */
07029          snprintf(buf, len, "%d", ((struct sig_pri_chan *) p->sig_pvt)->no_b_channel);
07030          break;
07031       default:
07032          *buf = '\0';
07033          res = -1;
07034          break;
07035       }
07036       ast_mutex_unlock(&p->lock);
07037 #endif   /* defined(HAVE_PRI) */
07038    } else {
07039       *buf = '\0';
07040       res = -1;
07041    }
07042 
07043    return res;
07044 }
07045 
07046 
07047 static int parse_buffers_policy(const char *parse, int *num_buffers, int *policy)
07048 {
07049    int res;
07050    char policy_str[21] = "";
07051 
07052    if ((res = sscanf(parse, "%30d,%20s", num_buffers, policy_str)) != 2) {
07053       ast_log(LOG_WARNING, "Parsing buffer string '%s' failed.\n", parse);
07054       return 1;
07055    }
07056    if (*num_buffers < 0) {
07057       ast_log(LOG_WARNING, "Invalid buffer count given '%d'.\n", *num_buffers);
07058       return -1;
07059    }
07060    if (!strcasecmp(policy_str, "full")) {
07061       *policy = DAHDI_POLICY_WHEN_FULL;
07062    } else if (!strcasecmp(policy_str, "immediate")) {
07063       *policy = DAHDI_POLICY_IMMEDIATE;
07064 #if defined(HAVE_DAHDI_HALF_FULL)
07065    } else if (!strcasecmp(policy_str, "half")) {
07066       *policy = DAHDI_POLICY_HALF_FULL;
07067 #endif
07068    } else {
07069       ast_log(LOG_WARNING, "Invalid policy name given '%s'.\n", policy_str);
07070       return -1;
07071    }
07072 
07073    return 0;
07074 }
07075 
07076 static int dahdi_func_write(struct ast_channel *chan, const char *function, char *data, const char *value)
07077 {
07078    struct dahdi_pvt *p = chan->tech_pvt;
07079    int res = 0;
07080 
07081    if (!p) {
07082       /* No private structure! */
07083       return -1;
07084    }
07085 
07086    if (!strcasecmp(data, "buffers")) {
07087       int num_bufs, policy;
07088 
07089       if (!(parse_buffers_policy(value, &num_bufs, &policy))) {
07090          struct dahdi_bufferinfo bi = {
07091             .txbufpolicy = policy,
07092             .rxbufpolicy = policy,
07093             .bufsize = p->bufsize,
07094             .numbufs = num_bufs,
07095          };
07096          int bpres;
07097 
07098          if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
07099             ast_log(LOG_WARNING, "Channel '%d' unable to override buffer policy: %s\n", p->channel, strerror(errno));
07100          } else {
07101             p->bufferoverrideinuse = 1;
07102          }
07103       } else {
07104          res = -1;
07105       }
07106    } else if (!strcasecmp(data, "echocan_mode")) {
07107       if (!strcasecmp(value, "on")) {
07108          ast_mutex_lock(&p->lock);
07109          dahdi_enable_ec(p);
07110          ast_mutex_unlock(&p->lock);
07111       } else if (!strcasecmp(value, "off")) {
07112          ast_mutex_lock(&p->lock);
07113          dahdi_disable_ec(p);
07114          ast_mutex_unlock(&p->lock);
07115 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
07116       } else if (!strcasecmp(value, "fax")) {
07117          int blah = 1;
07118 
07119          ast_mutex_lock(&p->lock);
07120          if (!p->echocanon) {
07121             dahdi_enable_ec(p);
07122          }
07123          if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_FAX_MODE, &blah)) {
07124             ast_log(LOG_WARNING, "Unable to place echocan into fax mode on channel %d: %s\n", p->channel, strerror(errno));
07125          }
07126          ast_mutex_unlock(&p->lock);
07127       } else if (!strcasecmp(value, "voice")) {
07128          int blah = 0;
07129 
07130          ast_mutex_lock(&p->lock);
07131          if (!p->echocanon) {
07132             dahdi_enable_ec(p);
07133          }
07134          if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_FAX_MODE, &blah)) {
07135             ast_log(LOG_WARNING, "Unable to place echocan into voice mode on channel %d: %s\n", p->channel, strerror(errno));
07136          }
07137          ast_mutex_unlock(&p->lock);
07138 #endif
07139       } else {
07140          ast_log(LOG_WARNING, "Unsupported value '%s' provided for '%s' item.\n", value, data);
07141          res = -1;
07142       }
07143    } else {
07144       res = -1;
07145    }
07146 
07147    return res;
07148 }
07149 
07150 static void dahdi_unlink(struct dahdi_pvt *slave, struct dahdi_pvt *master, int needlock)
07151 {
07152    /* Unlink a specific slave or all slaves/masters from a given master */
07153    int x;
07154    int hasslaves;
07155    if (!master)
07156       return;
07157    if (needlock) {
07158       ast_mutex_lock(&master->lock);
07159       if (slave) {
07160          while (ast_mutex_trylock(&slave->lock)) {
07161             DEADLOCK_AVOIDANCE(&master->lock);
07162          }
07163       }
07164    }
07165    hasslaves = 0;
07166    for (x = 0; x < MAX_SLAVES; x++) {
07167       if (master->slaves[x]) {
07168          if (!slave || (master->slaves[x] == slave)) {
07169             /* Take slave out of the conference */
07170             ast_debug(1, "Unlinking slave %d from %d\n", master->slaves[x]->channel, master->channel);
07171             conf_del(master, &master->slaves[x]->subs[SUB_REAL], SUB_REAL);
07172             conf_del(master->slaves[x], &master->subs[SUB_REAL], SUB_REAL);
07173             master->slaves[x]->master = NULL;
07174             master->slaves[x] = NULL;
07175          } else
07176             hasslaves = 1;
07177       }
07178       if (!hasslaves)
07179          master->inconference = 0;
07180    }
07181    if (!slave) {
07182       if (master->master) {
07183          /* Take master out of the conference */
07184          conf_del(master->master, &master->subs[SUB_REAL], SUB_REAL);
07185          conf_del(master, &master->master->subs[SUB_REAL], SUB_REAL);
07186          hasslaves = 0;
07187          for (x = 0; x < MAX_SLAVES; x++) {
07188             if (master->master->slaves[x] == master)
07189                master->master->slaves[x] = NULL;
07190             else if (master->master->slaves[x])
07191                hasslaves = 1;
07192          }
07193          if (!hasslaves)
07194             master->master->inconference = 0;
07195       }
07196       master->master = NULL;
07197    }
07198    update_conf(master);
07199    if (needlock) {
07200       if (slave)
07201          ast_mutex_unlock(&slave->lock);
07202       ast_mutex_unlock(&master->lock);
07203    }
07204 }
07205 
07206 static void dahdi_link(struct dahdi_pvt *slave, struct dahdi_pvt *master) {
07207    int x;
07208    if (!slave || !master) {
07209       ast_log(LOG_WARNING, "Tried to link to/from NULL??\n");
07210       return;
07211    }
07212    for (x = 0; x < MAX_SLAVES; x++) {
07213       if (!master->slaves[x]) {
07214          master->slaves[x] = slave;
07215          break;
07216       }
07217    }
07218    if (x >= MAX_SLAVES) {
07219       ast_log(LOG_WARNING, "Replacing slave %d with new slave, %d\n", master->slaves[MAX_SLAVES - 1]->channel, slave->channel);
07220       master->slaves[MAX_SLAVES - 1] = slave;
07221    }
07222    if (slave->master)
07223       ast_log(LOG_WARNING, "Replacing master %d with new master, %d\n", slave->master->channel, master->channel);
07224    slave->master = master;
07225 
07226    ast_debug(1, "Making %d slave to master %d at %d\n", slave->channel, master->channel, x);
07227 }
07228 
07229 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)
07230 {
07231    struct ast_channel *who;
07232    struct dahdi_pvt *p0, *p1, *op0, *op1;
07233    struct dahdi_pvt *master = NULL, *slave = NULL;
07234    struct ast_frame *f;
07235    int inconf = 0;
07236    int nothingok = 1;
07237    int ofd0, ofd1;
07238    int oi0, oi1, i0 = -1, i1 = -1, t0, t1;
07239    int os0 = -1, os1 = -1;
07240    int priority = 0;
07241    struct ast_channel *oc0, *oc1;
07242    enum ast_bridge_result res;
07243 #ifdef PRI_2BCT
07244    int triedtopribridge = 0;
07245    q931_call *q931c0;
07246    q931_call *q931c1;
07247 #endif
07248 
07249    /* For now, don't attempt to native bridge if either channel needs DTMF detection.
07250       There is code below to handle it properly until DTMF is actually seen,
07251       but due to currently unresolved issues it's ignored...
07252    */
07253 
07254    if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1))
07255       return AST_BRIDGE_FAILED_NOWARN;
07256 
07257    ast_channel_lock(c0);
07258    while (ast_channel_trylock(c1)) {
07259       CHANNEL_DEADLOCK_AVOIDANCE(c0);
07260    }
07261 
07262    p0 = c0->tech_pvt;
07263    p1 = c1->tech_pvt;
07264    /* cant do pseudo-channels here */
07265    if (!p0 || (!p0->sig) || !p1 || (!p1->sig)) {
07266       ast_channel_unlock(c0);
07267       ast_channel_unlock(c1);
07268       return AST_BRIDGE_FAILED_NOWARN;
07269    }
07270 
07271    oi0 = dahdi_get_index(c0, p0, 0);
07272    oi1 = dahdi_get_index(c1, p1, 0);
07273    if ((oi0 < 0) || (oi1 < 0)) {
07274       ast_channel_unlock(c0);
07275       ast_channel_unlock(c1);
07276       return AST_BRIDGE_FAILED;
07277    }
07278 
07279    op0 = p0 = c0->tech_pvt;
07280    op1 = p1 = c1->tech_pvt;
07281    ofd0 = c0->fds[0];
07282    ofd1 = c1->fds[0];
07283    oc0 = p0->owner;
07284    oc1 = p1->owner;
07285 
07286    if (ast_mutex_trylock(&p0->lock)) {
07287       /* Don't block, due to potential for deadlock */
07288       ast_channel_unlock(c0);
07289       ast_channel_unlock(c1);
07290       ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
07291       return AST_BRIDGE_RETRY;
07292    }
07293    if (ast_mutex_trylock(&p1->lock)) {
07294       /* Don't block, due to potential for deadlock */
07295       ast_mutex_unlock(&p0->lock);
07296       ast_channel_unlock(c0);
07297       ast_channel_unlock(c1);
07298       ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
07299       return AST_BRIDGE_RETRY;
07300    }
07301 
07302    if ((p0->callwaiting && p0->callwaitingcallerid)
07303       || (p1->callwaiting && p1->callwaitingcallerid)) {
07304       /*
07305        * Call Waiting Caller ID requires DTMF detection to know if it
07306        * can send the CID spill.
07307        *
07308        * For now, don't attempt to native bridge if either channel
07309        * needs DTMF detection.  There is code below to handle it
07310        * properly until DTMF is actually seen, but due to currently
07311        * unresolved issues it's ignored...
07312        */
07313       ast_mutex_unlock(&p0->lock);
07314       ast_mutex_unlock(&p1->lock);
07315       ast_channel_unlock(c0);
07316       ast_channel_unlock(c1);
07317       return AST_BRIDGE_FAILED_NOWARN;
07318    }
07319 
07320 #if defined(HAVE_PRI)
07321    if ((dahdi_sig_pri_lib_handles(p0->sig)
07322          && ((struct sig_pri_chan *) p0->sig_pvt)->no_b_channel)
07323       || (dahdi_sig_pri_lib_handles(p1->sig)
07324          && ((struct sig_pri_chan *) p1->sig_pvt)->no_b_channel)) {
07325       /*
07326        * PRI nobch channels (hold and call waiting) are equivalent to
07327        * pseudo channels and cannot be done here.
07328        */
07329       ast_mutex_unlock(&p0->lock);
07330       ast_mutex_unlock(&p1->lock);
07331       ast_channel_unlock(c0);
07332       ast_channel_unlock(c1);
07333       return AST_BRIDGE_FAILED_NOWARN;
07334    }
07335 #endif   /* defined(HAVE_PRI) */
07336 
07337    if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
07338       if (p0->owner && p1->owner) {
07339          /* If we don't have a call-wait in a 3-way, and we aren't in a 3-way, we can be master */
07340          if (!p0->subs[SUB_CALLWAIT].inthreeway && !p1->subs[SUB_REAL].inthreeway) {
07341             master = p0;
07342             slave = p1;
07343             inconf = 1;
07344          } else if (!p1->subs[SUB_CALLWAIT].inthreeway && !p0->subs[SUB_REAL].inthreeway) {
07345             master = p1;
07346             slave = p0;
07347             inconf = 1;
07348          } else {
07349             ast_log(LOG_WARNING, "Huh?  Both calls are callwaits or 3-ways?  That's clever...?\n");
07350             ast_log(LOG_WARNING, "p0: chan %d/%d/CW%d/3W%d, p1: chan %d/%d/CW%d/3W%d\n",
07351                p0->channel,
07352                oi0, (p0->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
07353                p0->subs[SUB_REAL].inthreeway, p0->channel,
07354                oi0, (p1->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
07355                p1->subs[SUB_REAL].inthreeway);
07356          }
07357          nothingok = 0;
07358       }
07359    } else if ((oi0 == SUB_REAL) && (oi1 == SUB_THREEWAY)) {
07360       if (p1->subs[SUB_THREEWAY].inthreeway) {
07361          master = p1;
07362          slave = p0;
07363          nothingok = 0;
07364       }
07365    } else if ((oi0 == SUB_THREEWAY) && (oi1 == SUB_REAL)) {
07366       if (p0->subs[SUB_THREEWAY].inthreeway) {
07367          master = p0;
07368          slave = p1;
07369          nothingok = 0;
07370       }
07371    } else if ((oi0 == SUB_REAL) && (oi1 == SUB_CALLWAIT)) {
07372       /* We have a real and a call wait.  If we're in a three way call, put us in it, otherwise,
07373          don't put us in anything */
07374       if (p1->subs[SUB_CALLWAIT].inthreeway) {
07375          master = p1;
07376          slave = p0;
07377          nothingok = 0;
07378       }
07379    } else if ((oi0 == SUB_CALLWAIT) && (oi1 == SUB_REAL)) {
07380       /* Same as previous */
07381       if (p0->subs[SUB_CALLWAIT].inthreeway) {
07382          master = p0;
07383          slave = p1;
07384          nothingok = 0;
07385       }
07386    }
07387    ast_debug(1, "master: %d, slave: %d, nothingok: %d\n",
07388       master ? master->channel : 0, slave ? slave->channel : 0, nothingok);
07389    if (master && slave) {
07390       /* Stop any tones, or play ringtone as appropriate.  If they're bridged
07391          in an active threeway call with a channel that is ringing, we should
07392          indicate ringing. */
07393       if ((oi1 == SUB_THREEWAY) &&
07394          p1->subs[SUB_THREEWAY].inthreeway &&
07395          p1->subs[SUB_REAL].owner &&
07396          p1->subs[SUB_REAL].inthreeway &&
07397          (p1->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
07398          ast_debug(1,
07399             "Playing ringback on %d/%d(%s) since %d/%d(%s) is in a ringing three-way\n",
07400             p0->channel, oi0, c0->name, p1->channel, oi1, c1->name);
07401          tone_zone_play_tone(p0->subs[oi0].dfd, DAHDI_TONE_RINGTONE);
07402          os1 = p1->subs[SUB_REAL].owner->_state;
07403       } else {
07404          ast_debug(1, "Stopping tones on %d/%d(%s) talking to %d/%d(%s)\n",
07405             p0->channel, oi0, c0->name, p1->channel, oi1, c1->name);
07406          tone_zone_play_tone(p0->subs[oi0].dfd, -1);
07407       }
07408       if ((oi0 == SUB_THREEWAY) &&
07409          p0->subs[SUB_THREEWAY].inthreeway &&
07410          p0->subs[SUB_REAL].owner &&
07411          p0->subs[SUB_REAL].inthreeway &&
07412          (p0->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
07413          ast_debug(1,
07414             "Playing ringback on %d/%d(%s) since %d/%d(%s) is in a ringing three-way\n",
07415             p1->channel, oi1, c1->name, p0->channel, oi0, c0->name);
07416          tone_zone_play_tone(p1->subs[oi1].dfd, DAHDI_TONE_RINGTONE);
07417          os0 = p0->subs[SUB_REAL].owner->_state;
07418       } else {
07419          ast_debug(1, "Stopping tones on %d/%d(%s) talking to %d/%d(%s)\n",
07420             p1->channel, oi1, c1->name, p0->channel, oi0, c0->name);
07421          tone_zone_play_tone(p1->subs[oi1].dfd, -1);
07422       }
07423       if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
07424          if (!p0->echocanbridged || !p1->echocanbridged) {
07425             /* Disable echo cancellation if appropriate */
07426             dahdi_disable_ec(p0);
07427             dahdi_disable_ec(p1);
07428          }
07429       }
07430       dahdi_link(slave, master);
07431       master->inconference = inconf;
07432    } else if (!nothingok)
07433       ast_log(LOG_WARNING, "Can't link %d/%s with %d/%s\n", p0->channel, subnames[oi0], p1->channel, subnames[oi1]);
07434 
07435    update_conf(p0);
07436    update_conf(p1);
07437    t0 = p0->subs[SUB_REAL].inthreeway;
07438    t1 = p1->subs[SUB_REAL].inthreeway;
07439 
07440    ast_mutex_unlock(&p0->lock);
07441    ast_mutex_unlock(&p1->lock);
07442 
07443    ast_channel_unlock(c0);
07444    ast_channel_unlock(c1);
07445 
07446    /* Native bridge failed */
07447    if ((!master || !slave) && !nothingok) {
07448       dahdi_enable_ec(p0);
07449       dahdi_enable_ec(p1);
07450       return AST_BRIDGE_FAILED;
07451    }
07452 
07453    ast_verb(3, "Native bridging %s and %s\n", c0->name, c1->name);
07454 
07455    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
07456       disable_dtmf_detect(op0);
07457 
07458    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
07459       disable_dtmf_detect(op1);
07460 
07461    for (;;) {
07462       struct ast_channel *c0_priority[2] = {c0, c1};
07463       struct ast_channel *c1_priority[2] = {c1, c0};
07464 
07465       /* Here's our main loop...  Start by locking things, looking for private parts,
07466          and then balking if anything is wrong */
07467 
07468       ast_channel_lock(c0);
07469       while (ast_channel_trylock(c1)) {
07470          CHANNEL_DEADLOCK_AVOIDANCE(c0);
07471       }
07472 
07473       p0 = c0->tech_pvt;
07474       p1 = c1->tech_pvt;
07475 
07476       if (op0 == p0)
07477          i0 = dahdi_get_index(c0, p0, 1);
07478       if (op1 == p1)
07479          i1 = dahdi_get_index(c1, p1, 1);
07480 
07481       ast_channel_unlock(c0);
07482       ast_channel_unlock(c1);
07483 
07484       if (!timeoutms ||
07485          (op0 != p0) ||
07486          (op1 != p1) ||
07487          (ofd0 != c0->fds[0]) ||
07488          (ofd1 != c1->fds[0]) ||
07489          (p0->subs[SUB_REAL].owner && (os0 > -1) && (os0 != p0->subs[SUB_REAL].owner->_state)) ||
07490          (p1->subs[SUB_REAL].owner && (os1 > -1) && (os1 != p1->subs[SUB_REAL].owner->_state)) ||
07491          (oc0 != p0->owner) ||
07492          (oc1 != p1->owner) ||
07493          (t0 != p0->subs[SUB_REAL].inthreeway) ||
07494          (t1 != p1->subs[SUB_REAL].inthreeway) ||
07495          (oi0 != i0) ||
07496          (oi1 != i1)) {
07497          ast_debug(1, "Something changed out on %d/%d to %d/%d, returning -3 to restart\n",
07498             op0->channel, oi0, op1->channel, oi1);
07499          res = AST_BRIDGE_RETRY;
07500          goto return_from_bridge;
07501       }
07502 
07503 #ifdef PRI_2BCT
07504       if (!triedtopribridge) {
07505          triedtopribridge = 1;
07506          if (p0->pri && p0->pri == p1->pri && p0->pri->transfer) {
07507             ast_mutex_lock(&p0->pri->lock);
07508             switch (p0->sig) {
07509             case SIG_PRI_LIB_HANDLE_CASES:
07510                q931c0 = ((struct sig_pri_chan *) (p0->sig_pvt))->call;
07511                break;
07512             default:
07513                q931c0 = NULL;
07514                break;
07515             }
07516             switch (p1->sig) {
07517             case SIG_PRI_LIB_HANDLE_CASES:
07518                q931c1 = ((struct sig_pri_chan *) (p1->sig_pvt))->call;
07519                break;
07520             default:
07521                q931c1 = NULL;
07522                break;
07523             }
07524             if (q931c0 && q931c1) {
07525                pri_channel_bridge(q931c0, q931c1);
07526             }
07527             ast_mutex_unlock(&p0->pri->lock);
07528          }
07529       }
07530 #endif
07531 
07532       who = ast_waitfor_n(priority ? c0_priority : c1_priority, 2, &timeoutms);
07533       if (!who) {
07534          ast_debug(1, "Ooh, empty read...\n");
07535          continue;
07536       }
07537       f = ast_read(who);
07538       if (!f || (f->frametype == AST_FRAME_CONTROL)) {
07539          *fo = f;
07540          *rc = who;
07541          res = AST_BRIDGE_COMPLETE;
07542          goto return_from_bridge;
07543       }
07544       if (f->frametype == AST_FRAME_DTMF) {
07545          if ((who == c0) && p0->pulsedial) {
07546             ast_write(c1, f);
07547          } else if ((who == c1) && p1->pulsedial) {
07548             ast_write(c0, f);
07549          } else {
07550             *fo = f;
07551             *rc = who;
07552             res = AST_BRIDGE_COMPLETE;
07553             goto return_from_bridge;
07554          }
07555       }
07556       ast_frfree(f);
07557 
07558       /* Swap who gets priority */
07559       priority = !priority;
07560    }
07561 
07562 return_from_bridge:
07563    if (op0 == p0)
07564       dahdi_enable_ec(p0);
07565 
07566    if (op1 == p1)
07567       dahdi_enable_ec(p1);
07568 
07569    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
07570       enable_dtmf_detect(op0);
07571 
07572    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
07573       enable_dtmf_detect(op1);
07574 
07575    dahdi_unlink(slave, master, 1);
07576 
07577    return res;
07578 }
07579 
07580 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
07581 {
07582    struct dahdi_pvt *p = newchan->tech_pvt;
07583    int x;
07584 
07585    ast_mutex_lock(&p->lock);
07586 
07587    ast_debug(1, "New owner for channel %d is %s\n", p->channel, newchan->name);
07588    if (p->owner == oldchan) {
07589       p->owner = newchan;
07590    }
07591    for (x = 0; x < 3; x++) {
07592       if (p->subs[x].owner == oldchan) {
07593          if (!x) {
07594             dahdi_unlink(NULL, p, 0);
07595          }
07596          p->subs[x].owner = newchan;
07597       }
07598    }
07599    if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
07600       analog_fixup(oldchan, newchan, p->sig_pvt);
07601 #if defined(HAVE_PRI)
07602    } else if (dahdi_sig_pri_lib_handles(p->sig)) {
07603       sig_pri_fixup(oldchan, newchan, p->sig_pvt);
07604 #endif   /* defined(HAVE_PRI) */
07605 #if defined(HAVE_SS7)
07606    } else if (p->sig == SIG_SS7) {
07607       sig_ss7_fixup(oldchan, newchan, p->sig_pvt);
07608 #endif   /* defined(HAVE_SS7) */
07609    }
07610    update_conf(p);
07611 
07612    ast_mutex_unlock(&p->lock);
07613 
07614    if (newchan->_state == AST_STATE_RINGING) {
07615       dahdi_indicate(newchan, AST_CONTROL_RINGING, NULL, 0);
07616    }
07617    return 0;
07618 }
07619 
07620 static int dahdi_ring_phone(struct dahdi_pvt *p)
07621 {
07622    int x;
07623    int res;
07624    /* Make sure our transmit state is on hook */
07625    x = 0;
07626    x = DAHDI_ONHOOK;
07627    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
07628    do {
07629       x = DAHDI_RING;
07630       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
07631       if (res) {
07632          switch (errno) {
07633          case EBUSY:
07634          case EINTR:
07635             /* Wait just in case */
07636             usleep(10000);
07637             continue;
07638          case EINPROGRESS:
07639             res = 0;
07640             break;
07641          default:
07642             ast_log(LOG_WARNING, "Couldn't ring the phone: %s\n", strerror(errno));
07643             res = 0;
07644          }
07645       }
07646    } while (res);
07647    return res;
07648 }
07649 
07650 static void *analog_ss_thread(void *data);
07651 
07652 static int attempt_transfer(struct dahdi_pvt *p)
07653 {
07654    /* In order to transfer, we need at least one of the channels to
07655       actually be in a call bridge.  We can't conference two applications
07656       together (but then, why would we want to?) */
07657    if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
07658       /* The three-way person we're about to transfer to could still be in MOH, so
07659          stop if now if appropriate */
07660       if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner))
07661          ast_queue_control(p->subs[SUB_THREEWAY].owner, AST_CONTROL_UNHOLD);
07662       if (p->subs[SUB_REAL].owner->_state == AST_STATE_RINGING) {
07663          ast_indicate(ast_bridged_channel(p->subs[SUB_REAL].owner), AST_CONTROL_RINGING);
07664       }
07665       if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RING) {
07666          tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE);
07667       }
07668        if (ast_channel_masquerade(p->subs[SUB_THREEWAY].owner, ast_bridged_channel(p->subs[SUB_REAL].owner))) {
07669          ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
07670                ast_bridged_channel(p->subs[SUB_REAL].owner)->name, p->subs[SUB_THREEWAY].owner->name);
07671          return -1;
07672       }
07673       /* Orphan the channel after releasing the lock */
07674       ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
07675       unalloc_sub(p, SUB_THREEWAY);
07676    } else if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
07677       ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
07678       if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RINGING) {
07679          ast_indicate(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), AST_CONTROL_RINGING);
07680       }
07681       if (p->subs[SUB_REAL].owner->_state == AST_STATE_RING) {
07682          tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
07683       }
07684       if (ast_channel_masquerade(p->subs[SUB_REAL].owner, ast_bridged_channel(p->subs[SUB_THREEWAY].owner))) {
07685          ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
07686                ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->name, p->subs[SUB_REAL].owner->name);
07687          return -1;
07688       }
07689       /* Three-way is now the REAL */
07690       swap_subs(p, SUB_THREEWAY, SUB_REAL);
07691       ast_channel_unlock(p->subs[SUB_REAL].owner);
07692       unalloc_sub(p, SUB_THREEWAY);
07693       /* Tell the caller not to hangup */
07694       return 1;
07695    } else {
07696       ast_debug(1, "Neither %s nor %s are in a bridge, nothing to transfer\n",
07697          p->subs[SUB_REAL].owner->name, p->subs[SUB_THREEWAY].owner->name);
07698       p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
07699       return -1;
07700    }
07701    return 0;
07702 }
07703 
07704 static int check_for_conference(struct dahdi_pvt *p)
07705 {
07706    struct dahdi_confinfo ci;
07707    /* Fine if we already have a master, etc */
07708    if (p->master || (p->confno > -1))
07709       return 0;
07710    memset(&ci, 0, sizeof(ci));
07711    if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
07712       ast_log(LOG_WARNING, "Failed to get conference info on channel %d: %s\n", p->channel, strerror(errno));
07713       return 0;
07714    }
07715    /* If we have no master and don't have a confno, then
07716       if we're in a conference, it's probably a MeetMe room or
07717       some such, so don't let us 3-way out! */
07718    if ((p->subs[SUB_REAL].curconf.confno != ci.confno) || (p->subs[SUB_REAL].curconf.confmode != ci.confmode)) {
07719       ast_verb(3, "Avoiding 3-way call when in an external conference\n");
07720       return 1;
07721    }
07722    return 0;
07723 }
07724 
07725 /*! Checks channel for alarms
07726  * \param p a channel to check for alarms.
07727  * \returns the alarms on the span to which the channel belongs, or alarms on
07728  *          the channel if no span alarms.
07729  */
07730 static int get_alarms(struct dahdi_pvt *p)
07731 {
07732    int res;
07733    struct dahdi_spaninfo zi;
07734    struct dahdi_params params;
07735 
07736    memset(&zi, 0, sizeof(zi));
07737    zi.spanno = p->span;
07738 
07739    if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SPANSTAT, &zi)) >= 0) {
07740       if (zi.alarms != DAHDI_ALARM_NONE)
07741          return zi.alarms;
07742    } else {
07743       ast_log(LOG_WARNING, "Unable to determine alarm on channel %d: %s\n", p->channel, strerror(errno));
07744       return 0;
07745    }
07746 
07747    /* No alarms on the span. Check for channel alarms. */
07748    memset(&params, 0, sizeof(params));
07749    if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &params)) >= 0)
07750       return params.chan_alarms;
07751 
07752    ast_log(LOG_WARNING, "Unable to determine alarm on channel %d\n", p->channel);
07753 
07754    return DAHDI_ALARM_NONE;
07755 }
07756 
07757 static void dahdi_handle_dtmf(struct ast_channel *ast, int idx, struct ast_frame **dest)
07758 {
07759    struct dahdi_pvt *p = ast->tech_pvt;
07760    struct ast_frame *f = *dest;
07761 
07762    ast_debug(1, "%s DTMF digit: 0x%02X '%c' on %s\n",
07763       f->frametype == AST_FRAME_DTMF_BEGIN ? "Begin" : "End",
07764       f->subclass.integer, f->subclass.integer, ast->name);
07765 
07766    if (p->confirmanswer) {
07767       if (f->frametype == AST_FRAME_DTMF_END) {
07768          ast_debug(1, "Confirm answer on %s!\n", ast->name);
07769          /* Upon receiving a DTMF digit, consider this an answer confirmation instead
07770             of a DTMF digit */
07771          p->subs[idx].f.frametype = AST_FRAME_CONTROL;
07772          p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
07773          /* Reset confirmanswer so DTMF's will behave properly for the duration of the call */
07774          p->confirmanswer = 0;
07775       } else {
07776          p->subs[idx].f.frametype = AST_FRAME_NULL;
07777          p->subs[idx].f.subclass.integer = 0;
07778       }
07779       *dest = &p->subs[idx].f;
07780    } else if (p->callwaitcas) {
07781       if (f->frametype == AST_FRAME_DTMF_END) {
07782          if ((f->subclass.integer == 'A') || (f->subclass.integer == 'D')) {
07783             ast_debug(1, "Got some DTMF, but it's for the CAS\n");
07784             ast_free(p->cidspill);
07785             p->cidspill = NULL;
07786             send_cwcidspill(p);
07787          }
07788          p->callwaitcas = 0;
07789       }
07790       p->subs[idx].f.frametype = AST_FRAME_NULL;
07791       p->subs[idx].f.subclass.integer = 0;
07792       *dest = &p->subs[idx].f;
07793    } else if (f->subclass.integer == 'f') {
07794       if (f->frametype == AST_FRAME_DTMF_END) {
07795          /* Fax tone -- Handle and return NULL */
07796          if ((p->callprogress & CALLPROGRESS_FAX) && !p->faxhandled) {
07797             /* If faxbuffers are configured, use them for the fax transmission */
07798             if (p->usefaxbuffers && !p->bufferoverrideinuse) {
07799                struct dahdi_bufferinfo bi = {
07800                   .txbufpolicy = p->faxbuf_policy,
07801                   .bufsize = p->bufsize,
07802                   .numbufs = p->faxbuf_no
07803                };
07804                int res;
07805 
07806                if ((res = ioctl(p->subs[idx].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
07807                   ast_log(LOG_WARNING, "Channel '%s' unable to set buffer policy, reason: %s\n", ast->name, strerror(errno));
07808                } else {
07809                   p->bufferoverrideinuse = 1;
07810                }
07811             }
07812             p->faxhandled = 1;
07813             if (p->dsp) {
07814                p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
07815                ast_dsp_set_features(p->dsp, p->dsp_features);
07816                ast_debug(1, "Disabling FAX tone detection on %s after tone received\n", ast->name);
07817             }
07818             if (strcmp(ast->exten, "fax")) {
07819                const char *target_context = S_OR(ast->macrocontext, ast->context);
07820 
07821                /* We need to unlock 'ast' here because ast_exists_extension has the
07822                 * potential to start autoservice on the channel. Such action is prone
07823                 * to deadlock.
07824                 */
07825                ast_mutex_unlock(&p->lock);
07826                ast_channel_unlock(ast);
07827                if (ast_exists_extension(ast, target_context, "fax", 1,
07828                   S_COR(ast->caller.id.number.valid, ast->caller.id.number.str, NULL))) {
07829                   ast_channel_lock(ast);
07830                   ast_mutex_lock(&p->lock);
07831                   ast_verb(3, "Redirecting %s to fax extension\n", ast->name);
07832                   /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
07833                   pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten);
07834                   if (ast_async_goto(ast, target_context, "fax", 1))
07835                      ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context);
07836                } else {
07837                   ast_channel_lock(ast);
07838                   ast_mutex_lock(&p->lock);
07839                   ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
07840                }
07841             } else {
07842                ast_debug(1, "Already in a fax extension, not redirecting\n");
07843             }
07844          } else {
07845             ast_debug(1, "Fax already handled\n");
07846          }
07847          dahdi_confmute(p, 0);
07848       }
07849       p->subs[idx].f.frametype = AST_FRAME_NULL;
07850       p->subs[idx].f.subclass.integer = 0;
07851       *dest = &p->subs[idx].f;
07852    }
07853 }
07854 
07855 static void handle_alarms(struct dahdi_pvt *p, int alms)
07856 {
07857    const char *alarm_str;
07858 
07859 #if defined(HAVE_PRI)
07860    if (dahdi_sig_pri_lib_handles(p->sig) && sig_pri_is_alarm_ignored(p->pri)) {
07861       return;
07862    }
07863 #endif   /* defined(HAVE_PRI) */
07864 
07865    alarm_str = alarm2str(alms);
07866    if (report_alarms & REPORT_CHANNEL_ALARMS) {
07867       ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", p->channel, alarm_str);
07868       manager_event(EVENT_FLAG_SYSTEM, "Alarm",
07869                  "Alarm: %s\r\n"
07870                  "Channel: %d\r\n",
07871                  alarm_str, p->channel);
07872    }
07873 
07874    if (report_alarms & REPORT_SPAN_ALARMS && p->manages_span_alarms) {
07875       ast_log(LOG_WARNING, "Detected alarm on span %d: %s\n", p->span, alarm_str);
07876       manager_event(EVENT_FLAG_SYSTEM, "SpanAlarm",
07877                  "Alarm: %s\r\n"
07878                  "Span: %d\r\n",
07879                  alarm_str, p->span);
07880    }
07881 }
07882 
07883 static struct ast_frame *dahdi_handle_event(struct ast_channel *ast)
07884 {
07885    int res, x;
07886    int idx, mysig;
07887    char *c;
07888    struct dahdi_pvt *p = ast->tech_pvt;
07889    pthread_t threadid;
07890    struct ast_channel *chan;
07891    struct ast_frame *f;
07892 
07893    idx = dahdi_get_index(ast, p, 0);
07894    if (idx < 0) {
07895       return &ast_null_frame;
07896    }
07897    mysig = p->sig;
07898    if (p->outsigmod > -1)
07899       mysig = p->outsigmod;
07900    p->subs[idx].f.frametype = AST_FRAME_NULL;
07901    p->subs[idx].f.subclass.integer = 0;
07902    p->subs[idx].f.datalen = 0;
07903    p->subs[idx].f.samples = 0;
07904    p->subs[idx].f.mallocd = 0;
07905    p->subs[idx].f.offset = 0;
07906    p->subs[idx].f.src = "dahdi_handle_event";
07907    p->subs[idx].f.data.ptr = NULL;
07908    f = &p->subs[idx].f;
07909 
07910    if (p->fake_event) {
07911       res = p->fake_event;
07912       p->fake_event = 0;
07913    } else
07914       res = dahdi_get_event(p->subs[idx].dfd);
07915 
07916    ast_debug(1, "Got event %s(%d) on channel %d (index %d)\n", event2str(res), res, p->channel, idx);
07917 
07918    if (res & (DAHDI_EVENT_PULSEDIGIT | DAHDI_EVENT_DTMFUP)) {
07919       p->pulsedial = (res & DAHDI_EVENT_PULSEDIGIT) ? 1 : 0;
07920       ast_debug(1, "Detected %sdigit '%c'\n", p->pulsedial ? "pulse ": "", res & 0xff);
07921 #if defined(HAVE_PRI)
07922       if (dahdi_sig_pri_lib_handles(p->sig)
07923          && ((struct sig_pri_chan *) p->sig_pvt)->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING
07924          && p->pri
07925          && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
07926          /* absorb event */
07927       } else
07928 #endif   /* defined(HAVE_PRI) */
07929       {
07930          /* Unmute conference */
07931          dahdi_confmute(p, 0);
07932          p->subs[idx].f.frametype = AST_FRAME_DTMF_END;
07933          p->subs[idx].f.subclass.integer = res & 0xff;
07934          dahdi_handle_dtmf(ast, idx, &f);
07935       }
07936       return f;
07937    }
07938 
07939    if (res & DAHDI_EVENT_DTMFDOWN) {
07940       ast_debug(1, "DTMF Down '%c'\n", res & 0xff);
07941 #if defined(HAVE_PRI)
07942       if (dahdi_sig_pri_lib_handles(p->sig)
07943          && ((struct sig_pri_chan *) p->sig_pvt)->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING
07944          && p->pri
07945          && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
07946          /* absorb event */
07947       } else
07948 #endif   /* defined(HAVE_PRI) */
07949       {
07950          /* Mute conference */
07951          dahdi_confmute(p, 1);
07952          p->subs[idx].f.frametype = AST_FRAME_DTMF_BEGIN;
07953          p->subs[idx].f.subclass.integer = res & 0xff;
07954          dahdi_handle_dtmf(ast, idx, &f);
07955       }
07956       return &p->subs[idx].f;
07957    }
07958 
07959    switch (res) {
07960    case DAHDI_EVENT_EC_DISABLED:
07961       ast_verb(3, "Channel %d echo canceler disabled.\n", p->channel);
07962       p->echocanon = 0;
07963       break;
07964 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
07965    case DAHDI_EVENT_TX_CED_DETECTED:
07966       ast_verb(3, "Channel %d detected a CED tone towards the network.\n", p->channel);
07967       break;
07968    case DAHDI_EVENT_RX_CED_DETECTED:
07969       ast_verb(3, "Channel %d detected a CED tone from the network.\n", p->channel);
07970       break;
07971    case DAHDI_EVENT_EC_NLP_DISABLED:
07972       ast_verb(3, "Channel %d echo canceler disabled its NLP.\n", p->channel);
07973       break;
07974    case DAHDI_EVENT_EC_NLP_ENABLED:
07975       ast_verb(3, "Channel %d echo canceler enabled its NLP.\n", p->channel);
07976       break;
07977 #endif
07978    case DAHDI_EVENT_BITSCHANGED:
07979 #ifdef HAVE_OPENR2
07980       if (p->sig != SIG_MFCR2) {
07981          ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig));
07982       } else {
07983          ast_log(LOG_DEBUG, "bits changed in chan %d\n", p->channel);
07984          openr2_chan_handle_cas(p->r2chan);
07985       }
07986 #else
07987       ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig));
07988 #endif
07989       break;
07990    case DAHDI_EVENT_PULSE_START:
07991       /* Stop tone if there's a pulse start and the PBX isn't started */
07992       if (!ast->pbx)
07993          tone_zone_play_tone(p->subs[idx].dfd, -1);
07994       break;
07995    case DAHDI_EVENT_DIALCOMPLETE:
07996       /* DAHDI has completed dialing all digits sent using DAHDI_DIAL. */
07997 #if defined(HAVE_PRI)
07998       if (dahdi_sig_pri_lib_handles(p->sig)) {
07999          if (p->inalarm) {
08000             break;
08001          }
08002          if (ioctl(p->subs[idx].dfd, DAHDI_DIALING, &x) == -1) {
08003             ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed on %s: %s\n", ast->name,
08004                strerror(errno));
08005             return NULL;
08006          }
08007          if (x) {
08008             /* Still dialing in DAHDI driver */
08009             break;
08010          }
08011          /*
08012           * The ast channel is locked and the private may be locked more
08013           * than once.
08014           */
08015          sig_pri_dial_complete(p->sig_pvt, ast);
08016          break;
08017       }
08018 #endif   /* defined(HAVE_PRI) */
08019 #ifdef HAVE_OPENR2
08020       if ((p->sig & SIG_MFCR2) && p->r2chan && ast->_state != AST_STATE_UP) {
08021          /* we don't need to do anything for this event for R2 signaling
08022             if the call is being setup */
08023          break;
08024       }
08025 #endif
08026       if (p->inalarm) break;
08027       if ((p->radio || (p->oprmode < 0))) break;
08028       if (ioctl(p->subs[idx].dfd,DAHDI_DIALING,&x) == -1) {
08029          ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed on %s: %s\n",ast->name, strerror(errno));
08030          return NULL;
08031       }
08032       if (!x) { /* if not still dialing in driver */
08033          dahdi_enable_ec(p);
08034          if (p->echobreak) {
08035             dahdi_train_ec(p);
08036             ast_copy_string(p->dop.dialstr, p->echorest, sizeof(p->dop.dialstr));
08037             p->dop.op = DAHDI_DIAL_OP_REPLACE;
08038             res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
08039             p->echobreak = 0;
08040          } else {
08041             p->dialing = 0;
08042             if ((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) {
08043                /* if thru with dialing after offhook */
08044                if (ast->_state == AST_STATE_DIALING_OFFHOOK) {
08045                   ast_setstate(ast, AST_STATE_UP);
08046                   p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08047                   p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
08048                   break;
08049                } else { /* if to state wait for offhook to dial rest */
08050                   /* we now wait for off hook */
08051                   ast_setstate(ast,AST_STATE_DIALING_OFFHOOK);
08052                }
08053             }
08054             if (ast->_state == AST_STATE_DIALING) {
08055                if ((p->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
08056                   ast_debug(1, "Done dialing, but waiting for progress detection before doing more...\n");
08057                } else if (p->confirmanswer || (!p->dialednone
08058                   && ((mysig == SIG_EM) || (mysig == SIG_EM_E1)
08059                      || (mysig == SIG_EMWINK) || (mysig == SIG_FEATD)
08060                      || (mysig == SIG_FEATDMF_TA) || (mysig == SIG_FEATDMF)
08061                      || (mysig == SIG_E911) || (mysig == SIG_FGC_CAMA)
08062                      || (mysig == SIG_FGC_CAMAMF) || (mysig == SIG_FEATB)
08063                      || (mysig == SIG_SF) || (mysig == SIG_SFWINK)
08064                      || (mysig == SIG_SF_FEATD) || (mysig == SIG_SF_FEATDMF)
08065                      || (mysig == SIG_SF_FEATB)))) {
08066                   ast_setstate(ast, AST_STATE_RINGING);
08067                } else if (!p->answeronpolarityswitch) {
08068                   ast_setstate(ast, AST_STATE_UP);
08069                   p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08070                   p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
08071                   /* If aops=0 and hops=1, this is necessary */
08072                   p->polarity = POLARITY_REV;
08073                } else {
08074                   /* Start clean, so we can catch the change to REV polarity when party answers */
08075                   p->polarity = POLARITY_IDLE;
08076                }
08077             }
08078          }
08079       }
08080       break;
08081    case DAHDI_EVENT_ALARM:
08082       switch (p->sig) {
08083 #if defined(HAVE_PRI)
08084       case SIG_PRI_LIB_HANDLE_CASES:
08085          sig_pri_chan_alarm_notify(p->sig_pvt, 0);
08086          break;
08087 #endif   /* defined(HAVE_PRI) */
08088 #if defined(HAVE_SS7)
08089       case SIG_SS7:
08090          sig_ss7_set_alarm(p->sig_pvt, 1);
08091          break;
08092 #endif   /* defined(HAVE_SS7) */
08093       default:
08094          p->inalarm = 1;
08095          break;
08096       }
08097       res = get_alarms(p);
08098       handle_alarms(p, res);
08099 #ifdef HAVE_PRI
08100       if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
08101          /* fall through intentionally */
08102       } else {
08103          break;
08104       }
08105 #endif
08106 #if defined(HAVE_SS7)
08107       if (p->sig == SIG_SS7)
08108          break;
08109 #endif   /* defined(HAVE_SS7) */
08110 #ifdef HAVE_OPENR2
08111       if (p->sig == SIG_MFCR2)
08112          break;
08113 #endif
08114    case DAHDI_EVENT_ONHOOK:
08115       if (p->radio) {
08116          p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08117          p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_UNKEY;
08118          break;
08119       }
08120       if (p->oprmode < 0)
08121       {
08122          if (p->oprmode != -1) break;
08123          if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
08124          {
08125             /* Make sure it starts ringing */
08126             dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
08127             dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RING);
08128             save_conference(p->oprpeer);
08129             tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
08130          }
08131          break;
08132       }
08133       switch (p->sig) {
08134       case SIG_FXOLS:
08135       case SIG_FXOGS:
08136       case SIG_FXOKS:
08137          /* Check for some special conditions regarding call waiting */
08138          if (idx == SUB_REAL) {
08139             /* The normal line was hung up */
08140             if (p->subs[SUB_CALLWAIT].owner) {
08141                /* There's a call waiting call, so ring the phone, but make it unowned in the mean time */
08142                swap_subs(p, SUB_CALLWAIT, SUB_REAL);
08143                ast_verb(3, "Channel %d still has (callwait) call, ringing phone\n", p->channel);
08144                unalloc_sub(p, SUB_CALLWAIT);
08145 #if 0
08146                p->subs[idx].needanswer = 0;
08147                p->subs[idx].needringing = 0;
08148 #endif
08149                p->callwaitingrepeat = 0;
08150                p->cidcwexpire = 0;
08151                p->cid_suppress_expire = 0;
08152                p->owner = NULL;
08153                /* Don't start streaming audio yet if the incoming call isn't up yet */
08154                if (p->subs[SUB_REAL].owner->_state != AST_STATE_UP)
08155                   p->dialing = 1;
08156                dahdi_ring_phone(p);
08157             } else if (p->subs[SUB_THREEWAY].owner) {
08158                unsigned int mssinceflash;
08159                /* Here we have to retain the lock on both the main channel, the 3-way channel, and
08160                   the private structure -- not especially easy or clean */
08161                while (p->subs[SUB_THREEWAY].owner && ast_channel_trylock(p->subs[SUB_THREEWAY].owner)) {
08162                   /* Yuck, didn't get the lock on the 3-way, gotta release everything and re-grab! */
08163                   DLA_UNLOCK(&p->lock);
08164                   CHANNEL_DEADLOCK_AVOIDANCE(ast);
08165                   /* We can grab ast and p in that order, without worry.  We should make sure
08166                      nothing seriously bad has happened though like some sort of bizarre double
08167                      masquerade! */
08168                   DLA_LOCK(&p->lock);
08169                   if (p->owner != ast) {
08170                      ast_log(LOG_WARNING, "This isn't good...\n");
08171                      return NULL;
08172                   }
08173                }
08174                if (!p->subs[SUB_THREEWAY].owner) {
08175                   ast_log(LOG_NOTICE, "Whoa, threeway disappeared kinda randomly.\n");
08176                   return NULL;
08177                }
08178                mssinceflash = ast_tvdiff_ms(ast_tvnow(), p->flashtime);
08179                ast_debug(1, "Last flash was %d ms ago\n", mssinceflash);
08180                if (mssinceflash < MIN_MS_SINCE_FLASH) {
08181                   /* It hasn't been long enough since the last flashook.  This is probably a bounce on
08182                      hanging up.  Hangup both channels now */
08183                   if (p->subs[SUB_THREEWAY].owner)
08184                      ast_queue_hangup_with_cause(p->subs[SUB_THREEWAY].owner, AST_CAUSE_NO_ANSWER);
08185                   p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08186                   ast_debug(1, "Looks like a bounced flash, hanging up both calls on %d\n", p->channel);
08187                   ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08188                } else if ((ast->pbx) || (ast->_state == AST_STATE_UP)) {
08189                   if (p->transfer) {
08190                      /* In any case this isn't a threeway call anymore */
08191                      p->subs[SUB_REAL].inthreeway = 0;
08192                      p->subs[SUB_THREEWAY].inthreeway = 0;
08193                      /* Only attempt transfer if the phone is ringing; why transfer to busy tone eh? */
08194                      if (!p->transfertobusy && ast->_state == AST_STATE_BUSY) {
08195                         ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08196                         /* Swap subs and dis-own channel */
08197                         swap_subs(p, SUB_THREEWAY, SUB_REAL);
08198                         p->owner = NULL;
08199                         /* Ring the phone */
08200                         dahdi_ring_phone(p);
08201                      } else {
08202                         if ((res = attempt_transfer(p)) < 0) {
08203                            p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08204                            if (p->subs[SUB_THREEWAY].owner)
08205                               ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08206                         } else if (res) {
08207                            /* Don't actually hang up at this point */
08208                            if (p->subs[SUB_THREEWAY].owner)
08209                               ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08210                            break;
08211                         }
08212                      }
08213                   } else {
08214                      p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08215                      if (p->subs[SUB_THREEWAY].owner)
08216                         ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08217                   }
08218                } else {
08219                   ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08220                   /* Swap subs and dis-own channel */
08221                   swap_subs(p, SUB_THREEWAY, SUB_REAL);
08222                   p->owner = NULL;
08223                   /* Ring the phone */
08224                   dahdi_ring_phone(p);
08225                }
08226             }
08227          } else {
08228             ast_log(LOG_WARNING, "Got a hangup and my index is %d?\n", idx);
08229          }
08230          /* Fall through */
08231       default:
08232          dahdi_disable_ec(p);
08233          return NULL;
08234       }
08235       break;
08236    case DAHDI_EVENT_RINGOFFHOOK:
08237       if (p->inalarm) break;
08238       if (p->oprmode < 0)
08239       {
08240          if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
08241          {
08242             /* Make sure it stops ringing */
08243             dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
08244             tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, -1);
08245             restore_conference(p->oprpeer);
08246          }
08247          break;
08248       }
08249       if (p->radio)
08250       {
08251          p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08252          p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_KEY;
08253          break;
08254       }
08255       /* for E911, its supposed to wait for offhook then dial
08256          the second half of the dial string */
08257       if (((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) && (ast->_state == AST_STATE_DIALING_OFFHOOK)) {
08258          c = strchr(p->dialdest, '/');
08259          if (c)
08260             c++;
08261          else
08262             c = p->dialdest;
08263          if (*c) snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*0%s#", c);
08264          else ast_copy_string(p->dop.dialstr,"M*2#", sizeof(p->dop.dialstr));
08265          if (strlen(p->dop.dialstr) > 4) {
08266             memset(p->echorest, 'w', sizeof(p->echorest) - 1);
08267             strcpy(p->echorest + (p->echotraining / 401) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
08268             p->echorest[sizeof(p->echorest) - 1] = '\0';
08269             p->echobreak = 1;
08270             p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
08271          } else
08272             p->echobreak = 0;
08273          if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
08274             int saveerr = errno;
08275 
08276             x = DAHDI_ONHOOK;
08277             ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
08278             ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
08279             return NULL;
08280             }
08281          p->dialing = 1;
08282          return &p->subs[idx].f;
08283       }
08284       switch (p->sig) {
08285       case SIG_FXOLS:
08286       case SIG_FXOGS:
08287       case SIG_FXOKS:
08288          switch (ast->_state) {
08289          case AST_STATE_RINGING:
08290             dahdi_enable_ec(p);
08291             dahdi_train_ec(p);
08292             p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08293             p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
08294             /* Make sure it stops ringing */
08295             p->subs[SUB_REAL].needringing = 0;
08296             dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
08297             ast_debug(1, "channel %d answered\n", p->channel);
08298 
08299             /* Cancel any running CallerID spill */
08300             ast_free(p->cidspill);
08301             p->cidspill = NULL;
08302             restore_conference(p);
08303 
08304             p->dialing = 0;
08305             p->callwaitcas = 0;
08306             if (p->confirmanswer) {
08307                /* Ignore answer if "confirm answer" is enabled */
08308                p->subs[idx].f.frametype = AST_FRAME_NULL;
08309                p->subs[idx].f.subclass.integer = 0;
08310             } else if (!ast_strlen_zero(p->dop.dialstr)) {
08311                /* nick@dccinc.com 4/3/03 - fxo should be able to do deferred dialing */
08312                res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
08313                if (res < 0) {
08314                   ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
08315                   p->dop.dialstr[0] = '\0';
08316                   return NULL;
08317                } else {
08318                   ast_debug(1, "Sent FXO deferred digit string: %s\n", p->dop.dialstr);
08319                   p->subs[idx].f.frametype = AST_FRAME_NULL;
08320                   p->subs[idx].f.subclass.integer = 0;
08321                   p->dialing = 1;
08322                }
08323                p->dop.dialstr[0] = '\0';
08324                ast_setstate(ast, AST_STATE_DIALING);
08325             } else
08326                ast_setstate(ast, AST_STATE_UP);
08327             return &p->subs[idx].f;
08328          case AST_STATE_DOWN:
08329             ast_setstate(ast, AST_STATE_RING);
08330             ast->rings = 1;
08331             p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08332             p->subs[idx].f.subclass.integer = AST_CONTROL_OFFHOOK;
08333             ast_debug(1, "channel %d picked up\n", p->channel);
08334             return &p->subs[idx].f;
08335          case AST_STATE_UP:
08336             /* Make sure it stops ringing */
08337             dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
08338             /* Okay -- probably call waiting*/
08339             if (ast_bridged_channel(p->owner))
08340                ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
08341             p->subs[idx].needunhold = 1;
08342             break;
08343          case AST_STATE_RESERVED:
08344             /* Start up dialtone */
08345             if (has_voicemail(p))
08346                res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
08347             else
08348                res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
08349             break;
08350          default:
08351             ast_log(LOG_WARNING, "FXO phone off hook in weird state %d??\n", ast->_state);
08352          }
08353          break;
08354       case SIG_FXSLS:
08355       case SIG_FXSGS:
08356       case SIG_FXSKS:
08357          if (ast->_state == AST_STATE_RING) {
08358             p->ringt = p->ringt_base;
08359          }
08360 
08361          /* If we get a ring then we cannot be in
08362           * reversed polarity. So we reset to idle */
08363          ast_debug(1, "Setting IDLE polarity due "
08364             "to ring. Old polarity was %d\n",
08365             p->polarity);
08366          p->polarity = POLARITY_IDLE;
08367 
08368          /* Fall through */
08369       case SIG_EM:
08370       case SIG_EM_E1:
08371       case SIG_EMWINK:
08372       case SIG_FEATD:
08373       case SIG_FEATDMF:
08374       case SIG_FEATDMF_TA:
08375       case SIG_E911:
08376       case SIG_FGC_CAMA:
08377       case SIG_FGC_CAMAMF:
08378       case SIG_FEATB:
08379       case SIG_SF:
08380       case SIG_SFWINK:
08381       case SIG_SF_FEATD:
08382       case SIG_SF_FEATDMF:
08383       case SIG_SF_FEATB:
08384          if (ast->_state == AST_STATE_PRERING)
08385             ast_setstate(ast, AST_STATE_RING);
08386          if ((ast->_state == AST_STATE_DOWN) || (ast->_state == AST_STATE_RING)) {
08387             ast_debug(1, "Ring detected\n");
08388             p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08389             p->subs[idx].f.subclass.integer = AST_CONTROL_RING;
08390          } else if (p->outgoing && ((ast->_state == AST_STATE_RINGING) || (ast->_state == AST_STATE_DIALING))) {
08391             ast_debug(1, "Line answered\n");
08392             if (p->confirmanswer) {
08393                p->subs[idx].f.frametype = AST_FRAME_NULL;
08394                p->subs[idx].f.subclass.integer = 0;
08395             } else {
08396                p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08397                p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
08398                ast_setstate(ast, AST_STATE_UP);
08399             }
08400          } else if (ast->_state != AST_STATE_RING)
08401             ast_log(LOG_WARNING, "Ring/Off-hook in strange state %d on channel %d\n", ast->_state, p->channel);
08402          break;
08403       default:
08404          ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
08405       }
08406       break;
08407    case DAHDI_EVENT_RINGBEGIN:
08408       switch (p->sig) {
08409       case SIG_FXSLS:
08410       case SIG_FXSGS:
08411       case SIG_FXSKS:
08412          if (ast->_state == AST_STATE_RING) {
08413             p->ringt = p->ringt_base;
08414          }
08415          break;
08416       }
08417       break;
08418    case DAHDI_EVENT_RINGERON:
08419       break;
08420    case DAHDI_EVENT_NOALARM:
08421       switch (p->sig) {
08422 #if defined(HAVE_PRI)
08423       case SIG_PRI_LIB_HANDLE_CASES:
08424          sig_pri_chan_alarm_notify(p->sig_pvt, 1);
08425          break;
08426 #endif   /* defined(HAVE_PRI) */
08427 #if defined(HAVE_SS7)
08428       case SIG_SS7:
08429          sig_ss7_set_alarm(p->sig_pvt, 0);
08430          break;
08431 #endif   /* defined(HAVE_SS7) */
08432       default:
08433          p->inalarm = 0;
08434          break;
08435       }
08436       handle_clear_alarms(p);
08437       break;
08438    case DAHDI_EVENT_WINKFLASH:
08439       if (p->inalarm) break;
08440       if (p->radio) break;
08441       if (p->oprmode < 0) break;
08442       if (p->oprmode > 1)
08443       {
08444          struct dahdi_params par;
08445 
08446          memset(&par, 0, sizeof(par));
08447          if (ioctl(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par) != -1)
08448          {
08449             if (!par.rxisoffhook)
08450             {
08451                /* Make sure it stops ringing */
08452                dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
08453                dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RING);
08454                save_conference(p);
08455                tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
08456             }
08457          }
08458          break;
08459       }
08460       /* Remember last time we got a flash-hook */
08461       p->flashtime = ast_tvnow();
08462       switch (mysig) {
08463       case SIG_FXOLS:
08464       case SIG_FXOGS:
08465       case SIG_FXOKS:
08466          ast_debug(1, "Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n",
08467             idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
08468 
08469          /* Cancel any running CallerID spill */
08470          ast_free(p->cidspill);
08471          p->cidspill = NULL;
08472          restore_conference(p);
08473          p->callwaitcas = 0;
08474 
08475          if (idx != SUB_REAL) {
08476             ast_log(LOG_WARNING, "Got flash hook with index %d on channel %d?!?\n", idx, p->channel);
08477             goto winkflashdone;
08478          }
08479 
08480          if (p->subs[SUB_CALLWAIT].owner) {
08481             /* Swap to call-wait */
08482             swap_subs(p, SUB_REAL, SUB_CALLWAIT);
08483             tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
08484             p->owner = p->subs[SUB_REAL].owner;
08485             ast_debug(1, "Making %s the new owner\n", p->owner->name);
08486             if (p->owner->_state == AST_STATE_RINGING) {
08487                ast_setstate(p->owner, AST_STATE_UP);
08488                p->subs[SUB_REAL].needanswer = 1;
08489             }
08490             p->callwaitingrepeat = 0;
08491             p->cidcwexpire = 0;
08492             p->cid_suppress_expire = 0;
08493             /* Start music on hold if appropriate */
08494             if (!p->subs[SUB_CALLWAIT].inthreeway && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
08495                ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
08496                   S_OR(p->mohsuggest, NULL),
08497                   !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
08498             }
08499             p->subs[SUB_CALLWAIT].needhold = 1;
08500             if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
08501                ast_queue_control_data(p->subs[SUB_REAL].owner, AST_CONTROL_HOLD,
08502                   S_OR(p->mohsuggest, NULL),
08503                   !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
08504             }
08505             p->subs[SUB_REAL].needunhold = 1;
08506          } else if (!p->subs[SUB_THREEWAY].owner) {
08507             if (!p->threewaycalling) {
08508                /* Just send a flash if no 3-way calling */
08509                p->subs[SUB_REAL].needflash = 1;
08510                goto winkflashdone;
08511             } else if (!check_for_conference(p)) {
08512                char cid_num[256];
08513                char cid_name[256];
08514 
08515                cid_num[0] = 0;
08516                cid_name[0] = 0;
08517                if (p->dahditrcallerid && p->owner) {
08518                   if (p->owner->caller.id.number.valid
08519                      && p->owner->caller.id.number.str) {
08520                      ast_copy_string(cid_num, p->owner->caller.id.number.str,
08521                         sizeof(cid_num));
08522                   }
08523                   if (p->owner->caller.id.name.valid
08524                      && p->owner->caller.id.name.str) {
08525                      ast_copy_string(cid_name, p->owner->caller.id.name.str,
08526                         sizeof(cid_name));
08527                   }
08528                }
08529                /* XXX This section needs much more error checking!!! XXX */
08530                /* Start a 3-way call if feasible */
08531                if (!((ast->pbx) ||
08532                   (ast->_state == AST_STATE_UP) ||
08533                   (ast->_state == AST_STATE_RING))) {
08534                   ast_debug(1, "Flash when call not up or ringing\n");
08535                   goto winkflashdone;
08536                }
08537                if (alloc_sub(p, SUB_THREEWAY)) {
08538                   ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n");
08539                   goto winkflashdone;
08540                }
08541 
08542                /*
08543                 * Make new channel
08544                 *
08545                 * We cannot hold the p or ast locks while creating a new
08546                 * channel.
08547                 */
08548                ast_mutex_unlock(&p->lock);
08549                ast_channel_unlock(ast);
08550                chan = dahdi_new(p, AST_STATE_RESERVED, 0, SUB_THREEWAY, 0, NULL);
08551                ast_channel_lock(ast);
08552                ast_mutex_lock(&p->lock);
08553                if (p->dahditrcallerid) {
08554                   if (!p->origcid_num)
08555                      p->origcid_num = ast_strdup(p->cid_num);
08556                   if (!p->origcid_name)
08557                      p->origcid_name = ast_strdup(p->cid_name);
08558                   ast_copy_string(p->cid_num, cid_num, sizeof(p->cid_num));
08559                   ast_copy_string(p->cid_name, cid_name, sizeof(p->cid_name));
08560                }
08561                /* Swap things around between the three-way and real call */
08562                swap_subs(p, SUB_THREEWAY, SUB_REAL);
08563                /* Disable echo canceller for better dialing */
08564                dahdi_disable_ec(p);
08565                res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALRECALL);
08566                if (res)
08567                   ast_log(LOG_WARNING, "Unable to start dial recall tone on channel %d\n", p->channel);
08568                p->owner = chan;
08569                if (!chan) {
08570                   ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", p->channel);
08571                } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
08572                   ast_log(LOG_WARNING, "Unable to start simple switch on channel %d\n", p->channel);
08573                   res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
08574                   dahdi_enable_ec(p);
08575                   ast_hangup(chan);
08576                } else {
08577                   ast_verb(3, "Started three way call on channel %d\n", p->channel);
08578 
08579                   /* Start music on hold if appropriate */
08580                   if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
08581                      ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
08582                         S_OR(p->mohsuggest, NULL),
08583                         !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
08584                   }
08585                   p->subs[SUB_THREEWAY].needhold = 1;
08586                }
08587             }
08588          } else {
08589             /* Already have a 3 way call */
08590             if (p->subs[SUB_THREEWAY].inthreeway) {
08591                /* Call is already up, drop the last person */
08592                ast_debug(1, "Got flash with three way call up, dropping last call on %d\n", p->channel);
08593                /* If the primary call isn't answered yet, use it */
08594                if ((p->subs[SUB_REAL].owner->_state != AST_STATE_UP) && (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_UP)) {
08595                   /* Swap back -- we're dropping the real 3-way that isn't finished yet*/
08596                   swap_subs(p, SUB_THREEWAY, SUB_REAL);
08597                   p->owner = p->subs[SUB_REAL].owner;
08598                }
08599                /* Drop the last call and stop the conference */
08600                ast_verb(3, "Dropping three-way call on %s\n", p->subs[SUB_THREEWAY].owner->name);
08601                p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08602                p->subs[SUB_REAL].inthreeway = 0;
08603                p->subs[SUB_THREEWAY].inthreeway = 0;
08604             } else {
08605                /* Lets see what we're up to */
08606                if (((ast->pbx) || (ast->_state == AST_STATE_UP)) &&
08607                   (p->transfertobusy || (ast->_state != AST_STATE_BUSY))) {
08608                   int otherindex = SUB_THREEWAY;
08609 
08610                   ast_verb(3, "Building conference call with %s and %s\n",
08611                      p->subs[SUB_THREEWAY].owner->name,
08612                      p->subs[SUB_REAL].owner->name);
08613                   /* Put them in the threeway, and flip */
08614                   p->subs[SUB_THREEWAY].inthreeway = 1;
08615                   p->subs[SUB_REAL].inthreeway = 1;
08616                   if (ast->_state == AST_STATE_UP) {
08617                      swap_subs(p, SUB_THREEWAY, SUB_REAL);
08618                      otherindex = SUB_REAL;
08619                   }
08620                   if (p->subs[otherindex].owner && ast_bridged_channel(p->subs[otherindex].owner))
08621                      ast_queue_control(p->subs[otherindex].owner, AST_CONTROL_UNHOLD);
08622                   p->subs[otherindex].needunhold = 1;
08623                   p->owner = p->subs[SUB_REAL].owner;
08624                } else {
08625                   ast_verb(3, "Dumping incomplete call on on %s\n", p->subs[SUB_THREEWAY].owner->name);
08626                   swap_subs(p, SUB_THREEWAY, SUB_REAL);
08627                   p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08628                   p->owner = p->subs[SUB_REAL].owner;
08629                   if (p->subs[SUB_REAL].owner && ast_bridged_channel(p->subs[SUB_REAL].owner))
08630                      ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
08631                   p->subs[SUB_REAL].needunhold = 1;
08632                   dahdi_enable_ec(p);
08633                }
08634             }
08635          }
08636 winkflashdone:
08637          update_conf(p);
08638          break;
08639       case SIG_EM:
08640       case SIG_EM_E1:
08641       case SIG_FEATD:
08642       case SIG_SF:
08643       case SIG_SFWINK:
08644       case SIG_SF_FEATD:
08645       case SIG_FXSLS:
08646       case SIG_FXSGS:
08647          if (p->dialing)
08648             ast_debug(1, "Ignoring wink on channel %d\n", p->channel);
08649          else
08650             ast_debug(1, "Got wink in weird state %d on channel %d\n", ast->_state, p->channel);
08651          break;
08652       case SIG_FEATDMF_TA:
08653          switch (p->whichwink) {
08654          case 0:
08655             ast_debug(1, "ANI2 set to '%d' and ANI is '%s'\n", p->owner->caller.ani2,
08656                S_COR(p->owner->caller.ani.number.valid,
08657                   p->owner->caller.ani.number.str, ""));
08658             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%d%s#",
08659                p->owner->caller.ani2,
08660                S_COR(p->owner->caller.ani.number.valid,
08661                   p->owner->caller.ani.number.str, ""));
08662             break;
08663          case 1:
08664             ast_copy_string(p->dop.dialstr, p->finaldial, sizeof(p->dop.dialstr));
08665             break;
08666          case 2:
08667             ast_log(LOG_WARNING, "Received unexpected wink on channel of type SIG_FEATDMF_TA\n");
08668             return NULL;
08669          }
08670          p->whichwink++;
08671          /* Fall through */
08672       case SIG_FEATDMF:
08673       case SIG_E911:
08674       case SIG_FGC_CAMAMF:
08675       case SIG_FGC_CAMA:
08676       case SIG_FEATB:
08677       case SIG_SF_FEATDMF:
08678       case SIG_SF_FEATB:
08679       case SIG_EMWINK:
08680          /* FGD MF and EMWINK *Must* wait for wink */
08681          if (!ast_strlen_zero(p->dop.dialstr)) {
08682             res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
08683             if (res < 0) {
08684                ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
08685                p->dop.dialstr[0] = '\0';
08686                return NULL;
08687             } else
08688                ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
08689          }
08690          p->dop.dialstr[0] = '\0';
08691          break;
08692       default:
08693          ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
08694       }
08695       break;
08696    case DAHDI_EVENT_HOOKCOMPLETE:
08697       if (p->inalarm) break;
08698       if ((p->radio || (p->oprmode < 0))) break;
08699       if (p->waitingfordt.tv_sec) break;
08700       switch (mysig) {
08701       case SIG_FXSLS:  /* only interesting for FXS */
08702       case SIG_FXSGS:
08703       case SIG_FXSKS:
08704       case SIG_EM:
08705       case SIG_EM_E1:
08706       case SIG_EMWINK:
08707       case SIG_FEATD:
08708       case SIG_SF:
08709       case SIG_SFWINK:
08710       case SIG_SF_FEATD:
08711          if (!ast_strlen_zero(p->dop.dialstr)) {
08712             res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
08713             if (res < 0) {
08714                ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
08715                p->dop.dialstr[0] = '\0';
08716                return NULL;
08717             } else
08718                ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
08719          }
08720          p->dop.dialstr[0] = '\0';
08721          p->dop.op = DAHDI_DIAL_OP_REPLACE;
08722          break;
08723       case SIG_FEATDMF:
08724       case SIG_FEATDMF_TA:
08725       case SIG_E911:
08726       case SIG_FGC_CAMA:
08727       case SIG_FGC_CAMAMF:
08728       case SIG_FEATB:
08729       case SIG_SF_FEATDMF:
08730       case SIG_SF_FEATB:
08731          ast_debug(1, "Got hook complete in MF FGD, waiting for wink now on channel %d\n",p->channel);
08732          break;
08733       default:
08734          break;
08735       }
08736       break;
08737    case DAHDI_EVENT_POLARITY:
08738       /*
08739        * If we get a Polarity Switch event, check to see
08740        * if we should change the polarity state and
08741        * mark the channel as UP or if this is an indication
08742        * of remote end disconnect.
08743        */
08744       if (p->polarity == POLARITY_IDLE) {
08745          p->polarity = POLARITY_REV;
08746          if (p->answeronpolarityswitch &&
08747             ((ast->_state == AST_STATE_DIALING) ||
08748             (ast->_state == AST_STATE_RINGING))) {
08749             ast_debug(1, "Answering on polarity switch!\n");
08750             ast_setstate(p->owner, AST_STATE_UP);
08751             if (p->hanguponpolarityswitch) {
08752                p->polaritydelaytv = ast_tvnow();
08753             }
08754          } else
08755             ast_debug(1, "Ignore switch to REVERSED Polarity on channel %d, state %d\n", p->channel, ast->_state);
08756       }
08757       /* Removed else statement from here as it was preventing hangups from ever happening*/
08758       /* Added AST_STATE_RING in if statement below to deal with calling party hangups that take place when ringing */
08759       if (p->hanguponpolarityswitch &&
08760          (p->polarityonanswerdelay > 0) &&
08761          (p->polarity == POLARITY_REV) &&
08762          ((ast->_state == AST_STATE_UP) || (ast->_state == AST_STATE_RING)) ) {
08763          /* Added log_debug information below to provide a better indication of what is going on */
08764          ast_debug(1, "Polarity Reversal event occured - DEBUG 1: channel %d, state %d, pol= %d, aonp= %d, honp= %d, pdelay= %d, tv= %" PRIi64 "\n", p->channel, ast->_state, p->polarity, p->answeronpolarityswitch, p->hanguponpolarityswitch, p->polarityonanswerdelay, ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) );
08765 
08766          if (ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) > p->polarityonanswerdelay) {
08767             ast_debug(1, "Polarity Reversal detected and now Hanging up on channel %d\n", p->channel);
08768             ast_softhangup(p->owner, AST_SOFTHANGUP_EXPLICIT);
08769             p->polarity = POLARITY_IDLE;
08770          } else
08771             ast_debug(1, "Polarity Reversal detected but NOT hanging up (too close to answer event) on channel %d, state %d\n", p->channel, ast->_state);
08772 
08773       } else {
08774          p->polarity = POLARITY_IDLE;
08775          ast_debug(1, "Ignoring Polarity switch to IDLE on channel %d, state %d\n", p->channel, ast->_state);
08776       }
08777       /* Added more log_debug information below to provide a better indication of what is going on */
08778       ast_debug(1, "Polarity Reversal event occured - DEBUG 2: channel %d, state %d, pol= %d, aonp= %d, honp= %d, pdelay= %d, tv= %" PRIi64 "\n", p->channel, ast->_state, p->polarity, p->answeronpolarityswitch, p->hanguponpolarityswitch, p->polarityonanswerdelay, ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) );
08779       break;
08780    default:
08781       ast_debug(1, "Dunno what to do with event %d on channel %d\n", res, p->channel);
08782    }
08783    return &p->subs[idx].f;
08784 }
08785 
08786 static struct ast_frame *__dahdi_exception(struct ast_channel *ast)
08787 {
08788    int res;
08789    int idx;
08790    struct ast_frame *f;
08791    int usedindex = -1;
08792    struct dahdi_pvt *p = ast->tech_pvt;
08793 
08794    if ((idx = dahdi_get_index(ast, p, 0)) < 0) {
08795       idx = SUB_REAL;
08796    }
08797 
08798    p->subs[idx].f.frametype = AST_FRAME_NULL;
08799    p->subs[idx].f.datalen = 0;
08800    p->subs[idx].f.samples = 0;
08801    p->subs[idx].f.mallocd = 0;
08802    p->subs[idx].f.offset = 0;
08803    p->subs[idx].f.subclass.integer = 0;
08804    p->subs[idx].f.delivery = ast_tv(0,0);
08805    p->subs[idx].f.src = "dahdi_exception";
08806    p->subs[idx].f.data.ptr = NULL;
08807 
08808 
08809    if ((!p->owner) && (!(p->radio || (p->oprmode < 0)))) {
08810       /* If nobody owns us, absorb the event appropriately, otherwise
08811          we loop indefinitely.  This occurs when, during call waiting, the
08812          other end hangs up our channel so that it no longer exists, but we
08813          have neither FLASH'd nor ONHOOK'd to signify our desire to
08814          change to the other channel. */
08815       if (p->fake_event) {
08816          res = p->fake_event;
08817          p->fake_event = 0;
08818       } else
08819          res = dahdi_get_event(p->subs[SUB_REAL].dfd);
08820       /* Switch to real if there is one and this isn't something really silly... */
08821       if ((res != DAHDI_EVENT_RINGEROFF) && (res != DAHDI_EVENT_RINGERON) &&
08822          (res != DAHDI_EVENT_HOOKCOMPLETE)) {
08823          ast_debug(1, "Restoring owner of channel %d on event %d\n", p->channel, res);
08824          p->owner = p->subs[SUB_REAL].owner;
08825          if (p->owner && ast_bridged_channel(p->owner))
08826             ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
08827          p->subs[SUB_REAL].needunhold = 1;
08828       }
08829       switch (res) {
08830       case DAHDI_EVENT_ONHOOK:
08831          dahdi_disable_ec(p);
08832          if (p->owner) {
08833             ast_verb(3, "Channel %s still has call, ringing phone\n", p->owner->name);
08834             dahdi_ring_phone(p);
08835             p->callwaitingrepeat = 0;
08836             p->cidcwexpire = 0;
08837             p->cid_suppress_expire = 0;
08838          } else
08839             ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
08840          update_conf(p);
08841          break;
08842       case DAHDI_EVENT_RINGOFFHOOK:
08843          dahdi_enable_ec(p);
08844          dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
08845          if (p->owner && (p->owner->_state == AST_STATE_RINGING)) {
08846             p->subs[SUB_REAL].needanswer = 1;
08847             p->dialing = 0;
08848          }
08849          break;
08850       case DAHDI_EVENT_HOOKCOMPLETE:
08851       case DAHDI_EVENT_RINGERON:
08852       case DAHDI_EVENT_RINGEROFF:
08853          /* Do nothing */
08854          break;
08855       case DAHDI_EVENT_WINKFLASH:
08856          p->flashtime = ast_tvnow();
08857          if (p->owner) {
08858             ast_verb(3, "Channel %d flashed to other channel %s\n", p->channel, p->owner->name);
08859             if (p->owner->_state != AST_STATE_UP) {
08860                /* Answer if necessary */
08861                usedindex = dahdi_get_index(p->owner, p, 0);
08862                if (usedindex > -1) {
08863                   p->subs[usedindex].needanswer = 1;
08864                }
08865                ast_setstate(p->owner, AST_STATE_UP);
08866             }
08867             p->callwaitingrepeat = 0;
08868             p->cidcwexpire = 0;
08869             p->cid_suppress_expire = 0;
08870             if (ast_bridged_channel(p->owner))
08871                ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
08872             p->subs[SUB_REAL].needunhold = 1;
08873          } else
08874             ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
08875          update_conf(p);
08876          break;
08877       default:
08878          ast_log(LOG_WARNING, "Don't know how to absorb event %s\n", event2str(res));
08879       }
08880       f = &p->subs[idx].f;
08881       return f;
08882    }
08883    if (!(p->radio || (p->oprmode < 0)))
08884       ast_debug(1, "Exception on %d, channel %d\n", ast->fds[0],p->channel);
08885    /* If it's not us, return NULL immediately */
08886    if (ast != p->owner) {
08887       if (p->owner) {
08888          ast_log(LOG_WARNING, "We're %s, not %s\n", ast->name, p->owner->name);
08889       }
08890       f = &p->subs[idx].f;
08891       return f;
08892    }
08893 
08894    f = dahdi_handle_event(ast);
08895    if (!f) {
08896       const char *name = ast_strdupa(ast->name);
08897 
08898       /* Tell the CDR this DAHDI device hung up */
08899       ast_mutex_unlock(&p->lock);
08900       ast_channel_unlock(ast);
08901       ast_set_hangupsource(ast, name, 0);
08902       ast_channel_lock(ast);
08903       ast_mutex_lock(&p->lock);
08904    }
08905    return f;
08906 }
08907 
08908 static struct ast_frame *dahdi_exception(struct ast_channel *ast)
08909 {
08910    struct dahdi_pvt *p = ast->tech_pvt;
08911    struct ast_frame *f;
08912    ast_mutex_lock(&p->lock);
08913    if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
08914       struct analog_pvt *analog_p = p->sig_pvt;
08915       f = analog_exception(analog_p, ast);
08916    } else {
08917       f = __dahdi_exception(ast);
08918    }
08919    ast_mutex_unlock(&p->lock);
08920    return f;
08921 }
08922 
08923 static struct ast_frame *dahdi_read(struct ast_channel *ast)
08924 {
08925    struct dahdi_pvt *p;
08926    int res;
08927    int idx;
08928    void *readbuf;
08929    struct ast_frame *f;
08930 
08931    /*
08932     * For analog channels, we must do deadlock avoidance because
08933     * analog ports can have more than one Asterisk channel using
08934     * the same private structure.
08935     */
08936    p = ast->tech_pvt;
08937    while (ast_mutex_trylock(&p->lock)) {
08938       CHANNEL_DEADLOCK_AVOIDANCE(ast);
08939 
08940       /*
08941        * For PRI channels, we must refresh the private pointer because
08942        * the call could move to another B channel while the Asterisk
08943        * channel is unlocked.
08944        */
08945       p = ast->tech_pvt;
08946    }
08947 
08948    idx = dahdi_get_index(ast, p, 0);
08949 
08950    /* Hang up if we don't really exist */
08951    if (idx < 0)   {
08952       ast_log(LOG_WARNING, "We don't exist?\n");
08953       ast_mutex_unlock(&p->lock);
08954       return NULL;
08955    }
08956 
08957    if ((p->radio || (p->oprmode < 0)) && p->inalarm) {
08958       ast_mutex_unlock(&p->lock);
08959       return NULL;
08960    }
08961 
08962    p->subs[idx].f.frametype = AST_FRAME_NULL;
08963    p->subs[idx].f.datalen = 0;
08964    p->subs[idx].f.samples = 0;
08965    p->subs[idx].f.mallocd = 0;
08966    p->subs[idx].f.offset = 0;
08967    p->subs[idx].f.subclass.integer = 0;
08968    p->subs[idx].f.delivery = ast_tv(0,0);
08969    p->subs[idx].f.src = "dahdi_read";
08970    p->subs[idx].f.data.ptr = NULL;
08971 
08972    /* make sure it sends initial key state as first frame */
08973    if ((p->radio || (p->oprmode < 0)) && (!p->firstradio))
08974    {
08975       struct dahdi_params ps;
08976 
08977       memset(&ps, 0, sizeof(ps));
08978       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
08979          ast_mutex_unlock(&p->lock);
08980          return NULL;
08981       }
08982       p->firstradio = 1;
08983       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08984       if (ps.rxisoffhook)
08985       {
08986          p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_KEY;
08987       }
08988       else
08989       {
08990          p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_UNKEY;
08991       }
08992       ast_mutex_unlock(&p->lock);
08993       return &p->subs[idx].f;
08994    }
08995    if (p->ringt > 0) {
08996       if (!(--p->ringt)) {
08997          ast_mutex_unlock(&p->lock);
08998          return NULL;
08999       }
09000    }
09001 
09002 #ifdef HAVE_OPENR2
09003    if (p->mfcr2) {
09004       openr2_chan_process_event(p->r2chan);
09005       if (OR2_DIR_FORWARD == openr2_chan_get_direction(p->r2chan)) {
09006          struct ast_frame f = { AST_FRAME_CONTROL, { AST_CONTROL_PROGRESS }, };
09007          /* if the call is already accepted and we already delivered AST_CONTROL_RINGING
09008           * now enqueue a progress frame to bridge the media up */
09009          if (p->mfcr2_call_accepted &&
09010              !p->mfcr2_progress && 
09011              ast->_state == AST_STATE_RINGING) {
09012             ast_log(LOG_DEBUG, "Enqueuing progress frame after R2 accept in chan %d\n", p->channel);
09013             ast_queue_frame(p->owner, &f);
09014             p->mfcr2_progress = 1;
09015          }
09016       }
09017    }
09018 #endif
09019 
09020    if (p->subs[idx].needringing) {
09021       /* Send ringing frame if requested */
09022       p->subs[idx].needringing = 0;
09023       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09024       p->subs[idx].f.subclass.integer = AST_CONTROL_RINGING;
09025       ast_setstate(ast, AST_STATE_RINGING);
09026       ast_mutex_unlock(&p->lock);
09027       return &p->subs[idx].f;
09028    }
09029 
09030    if (p->subs[idx].needbusy) {
09031       /* Send busy frame if requested */
09032       p->subs[idx].needbusy = 0;
09033       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09034       p->subs[idx].f.subclass.integer = AST_CONTROL_BUSY;
09035       ast_mutex_unlock(&p->lock);
09036       return &p->subs[idx].f;
09037    }
09038 
09039    if (p->subs[idx].needcongestion) {
09040       /* Send congestion frame if requested */
09041       p->subs[idx].needcongestion = 0;
09042       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09043       p->subs[idx].f.subclass.integer = AST_CONTROL_CONGESTION;
09044       ast_mutex_unlock(&p->lock);
09045       return &p->subs[idx].f;
09046    }
09047 
09048    if (p->subs[idx].needanswer) {
09049       /* Send answer frame if requested */
09050       p->subs[idx].needanswer = 0;
09051       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09052       p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
09053       ast_mutex_unlock(&p->lock);
09054       return &p->subs[idx].f;
09055    }
09056 #ifdef HAVE_OPENR2
09057    if (p->mfcr2 && openr2_chan_get_read_enabled(p->r2chan)) {
09058       /* openr2 took care of reading and handling any event
09059         (needanswer, needbusy etc), if we continue we will read()
09060         twice, lets just return a null frame. This should only
09061         happen when openr2 is dialing out */
09062       ast_mutex_unlock(&p->lock);
09063       return &ast_null_frame;
09064    }
09065 #endif
09066 
09067    if (p->subs[idx].needflash) {
09068       /* Send answer frame if requested */
09069       p->subs[idx].needflash = 0;
09070       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09071       p->subs[idx].f.subclass.integer = AST_CONTROL_FLASH;
09072       ast_mutex_unlock(&p->lock);
09073       return &p->subs[idx].f;
09074    }
09075 
09076    if (p->subs[idx].needhold) {
09077       /* Send answer frame if requested */
09078       p->subs[idx].needhold = 0;
09079       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09080       p->subs[idx].f.subclass.integer = AST_CONTROL_HOLD;
09081       ast_mutex_unlock(&p->lock);
09082       ast_debug(1, "Sending hold on '%s'\n", ast->name);
09083       return &p->subs[idx].f;
09084    }
09085 
09086    if (p->subs[idx].needunhold) {
09087       /* Send answer frame if requested */
09088       p->subs[idx].needunhold = 0;
09089       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09090       p->subs[idx].f.subclass.integer = AST_CONTROL_UNHOLD;
09091       ast_mutex_unlock(&p->lock);
09092       ast_debug(1, "Sending unhold on '%s'\n", ast->name);
09093       return &p->subs[idx].f;
09094    }
09095 
09096    /*
09097     * If we have a fake_event, fake an exception to handle it only
09098     * if this channel owns the private.
09099     */
09100    if (p->fake_event && p->owner == ast) {
09101       if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
09102          struct analog_pvt *analog_p = p->sig_pvt;
09103 
09104          f = analog_exception(analog_p, ast);
09105       } else {
09106          f = __dahdi_exception(ast);
09107       }
09108       ast_mutex_unlock(&p->lock);
09109       return f;
09110    }
09111 
09112    if (ast->rawreadformat == AST_FORMAT_SLINEAR) {
09113       if (!p->subs[idx].linear) {
09114          p->subs[idx].linear = 1;
09115          res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09116          if (res)
09117             ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to linear mode.\n", p->channel, idx);
09118       }
09119    } else if ((ast->rawreadformat == AST_FORMAT_ULAW) ||
09120       (ast->rawreadformat == AST_FORMAT_ALAW)) {
09121       if (p->subs[idx].linear) {
09122          p->subs[idx].linear = 0;
09123          res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09124          if (res)
09125             ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to companded mode.\n", p->channel, idx);
09126       }
09127    } else {
09128       ast_log(LOG_WARNING, "Don't know how to read frames in format %s\n", ast_getformatname(ast->rawreadformat));
09129       ast_mutex_unlock(&p->lock);
09130       return NULL;
09131    }
09132    readbuf = ((unsigned char *)p->subs[idx].buffer) + AST_FRIENDLY_OFFSET;
09133    CHECK_BLOCKING(ast);
09134    res = read(p->subs[idx].dfd, readbuf, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
09135    ast_clear_flag(ast, AST_FLAG_BLOCKING);
09136    /* Check for hangup */
09137    if (res < 0) {
09138       f = NULL;
09139       if (res == -1) {
09140          if (errno == EAGAIN) {
09141             /* Return "NULL" frame if there is nobody there */
09142             ast_mutex_unlock(&p->lock);
09143             return &p->subs[idx].f;
09144          } else if (errno == ELAST) {
09145             if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
09146                struct analog_pvt *analog_p = p->sig_pvt;
09147                f = analog_exception(analog_p, ast);
09148             } else {
09149                f = __dahdi_exception(ast);
09150             }
09151          } else
09152             ast_log(LOG_WARNING, "dahdi_rec: %s\n", strerror(errno));
09153       }
09154       ast_mutex_unlock(&p->lock);
09155       return f;
09156    }
09157    if (res != (p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE)) {
09158       ast_debug(1, "Short read (%d/%d), must be an event...\n", res, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
09159       if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
09160          struct analog_pvt *analog_p = p->sig_pvt;
09161          f = analog_exception(analog_p, ast);
09162       } else {
09163          f = __dahdi_exception(ast);
09164       }
09165       ast_mutex_unlock(&p->lock);
09166       return f;
09167    }
09168    if (p->tdd) { /* if in TDD mode, see if we receive that */
09169       int c;
09170 
09171       c = tdd_feed(p->tdd,readbuf,READ_SIZE);
09172       if (c < 0) {
09173          ast_debug(1,"tdd_feed failed\n");
09174          ast_mutex_unlock(&p->lock);
09175          return NULL;
09176       }
09177       if (c) { /* if a char to return */
09178          p->subs[idx].f.subclass.integer = 0;
09179          p->subs[idx].f.frametype = AST_FRAME_TEXT;
09180          p->subs[idx].f.mallocd = 0;
09181          p->subs[idx].f.offset = AST_FRIENDLY_OFFSET;
09182          p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET;
09183          p->subs[idx].f.datalen = 1;
09184          *((char *) p->subs[idx].f.data.ptr) = c;
09185          ast_mutex_unlock(&p->lock);
09186          return &p->subs[idx].f;
09187       }
09188    }
09189    if (idx == SUB_REAL) {
09190       /* Ensure the CW timers decrement only on a single subchannel */
09191       if (p->cidcwexpire) {
09192          if (!--p->cidcwexpire) {
09193             /* Expired CID/CW */
09194             ast_verb(3, "CPE does not support Call Waiting Caller*ID.\n");
09195             restore_conference(p);
09196          }
09197       }
09198       if (p->cid_suppress_expire) {
09199          --p->cid_suppress_expire;
09200       }
09201       if (p->callwaitingrepeat) {
09202          if (!--p->callwaitingrepeat) {
09203             /* Expired, Repeat callwaiting tone */
09204             ++p->callwaitrings;
09205             dahdi_callwait(ast);
09206          }
09207       }
09208    }
09209    if (p->subs[idx].linear) {
09210       p->subs[idx].f.datalen = READ_SIZE * 2;
09211    } else
09212       p->subs[idx].f.datalen = READ_SIZE;
09213 
09214    /* Handle CallerID Transmission */
09215    if ((p->owner == ast) && p->cidspill) {
09216       send_callerid(p);
09217    }
09218 
09219    p->subs[idx].f.frametype = AST_FRAME_VOICE;
09220    p->subs[idx].f.subclass.codec = ast->rawreadformat;
09221    p->subs[idx].f.samples = READ_SIZE;
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 / sizeof(p->subs[idx].buffer[0]);
09225 #if 0
09226    ast_debug(1, "Read %d of voice on %s\n", p->subs[idx].f.datalen, ast->name);
09227 #endif
09228    if (p->dialing ||  p->radio || /* Transmitting something */
09229       (idx && (ast->_state != AST_STATE_UP)) || /* Three-way or callwait that isn't up */
09230       ((idx == SUB_CALLWAIT) && !p->subs[SUB_CALLWAIT].inthreeway) /* Inactive and non-confed call-wait */
09231       ) {
09232       /* Whoops, we're still dialing, or in a state where we shouldn't transmit....
09233          don't send anything */
09234       p->subs[idx].f.frametype = AST_FRAME_NULL;
09235       p->subs[idx].f.subclass.integer = 0;
09236       p->subs[idx].f.samples = 0;
09237       p->subs[idx].f.mallocd = 0;
09238       p->subs[idx].f.offset = 0;
09239       p->subs[idx].f.data.ptr = NULL;
09240       p->subs[idx].f.datalen= 0;
09241    }
09242    if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect || p->callprogress || p->waitingfordt.tv_sec) && !idx) {
09243       /* Perform busy detection etc on the dahdi line */
09244       int mute;
09245 
09246       f = ast_dsp_process(ast, p->dsp, &p->subs[idx].f);
09247 
09248       /* Check if DSP code thinks we should be muting this frame and mute the conference if so */
09249       mute = ast_dsp_was_muted(p->dsp);
09250       if (p->muting != mute) {
09251          p->muting = mute;
09252          dahdi_confmute(p, mute);
09253       }
09254 
09255       if (f) {
09256          if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass.integer == AST_CONTROL_BUSY)) {
09257             if ((ast->_state == AST_STATE_UP) && !p->outgoing) {
09258                /* Treat this as a "hangup" instead of a "busy" on the assumption that
09259                   a busy */
09260                ast_frfree(f);
09261                f = NULL;
09262             }
09263          } else if (f->frametype == AST_FRAME_DTMF_BEGIN
09264             || f->frametype == AST_FRAME_DTMF_END) {
09265 #ifdef HAVE_PRI
09266             if (dahdi_sig_pri_lib_handles(p->sig)
09267                && ((struct sig_pri_chan *) p->sig_pvt)->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING
09268                && p->pri
09269                && ((!p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING))
09270                   || (p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)))) {
09271                /* Don't accept in-band DTMF when in overlap dial mode */
09272                ast_debug(1, "Absorbing inband %s DTMF digit: 0x%02X '%c' on %s\n",
09273                   f->frametype == AST_FRAME_DTMF_BEGIN ? "begin" : "end",
09274                   f->subclass.integer, f->subclass.integer, ast->name);
09275 
09276                f->frametype = AST_FRAME_NULL;
09277                f->subclass.integer = 0;
09278             }
09279 #endif
09280             /* DSP clears us of being pulse */
09281             p->pulsedial = 0;
09282          } else if (p->waitingfordt.tv_sec) {
09283             if (ast_tvdiff_ms(ast_tvnow(), p->waitingfordt) >= p->waitfordialtone ) {
09284                p->waitingfordt.tv_sec = 0;
09285                ast_log(LOG_WARNING, "Never saw dialtone on channel %d\n", p->channel);
09286                ast_frfree(f);
09287                f = NULL;
09288             } else if (f->frametype == AST_FRAME_VOICE) {
09289                f->frametype = AST_FRAME_NULL;
09290                f->subclass.integer = 0;
09291                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) {
09292                   p->waitingfordt.tv_sec = 0;
09293                   p->dsp_features &= ~DSP_FEATURE_WAITDIALTONE;
09294                   ast_dsp_set_features(p->dsp, p->dsp_features);
09295                   ast_log(LOG_DEBUG, "Got 10 samples of dialtone!\n");
09296                   if (!ast_strlen_zero(p->dop.dialstr)) { /* Dial deferred digits */
09297                      res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
09298                      if (res < 0) {
09299                         ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d\n", p->channel);
09300                         p->dop.dialstr[0] = '\0';
09301                         ast_mutex_unlock(&p->lock);
09302                         ast_frfree(f);
09303                         return NULL;
09304                      } else {
09305                         ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", p->dop.dialstr);
09306                         p->dialing = 1;
09307                         p->dop.dialstr[0] = '\0';
09308                         p->dop.op = DAHDI_DIAL_OP_REPLACE;
09309                         ast_setstate(ast, AST_STATE_DIALING);
09310                      }
09311                   }
09312                }
09313             }
09314          }
09315       }
09316    } else
09317       f = &p->subs[idx].f;
09318 
09319    if (f) {
09320       switch (f->frametype) {
09321       case AST_FRAME_DTMF_BEGIN:
09322       case AST_FRAME_DTMF_END:
09323          if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
09324             analog_handle_dtmf(p->sig_pvt, ast, idx, &f);
09325          } else {
09326             dahdi_handle_dtmf(ast, idx, &f);
09327          }
09328          break;
09329       case AST_FRAME_VOICE:
09330          if (p->cidspill || p->cid_suppress_expire) {
09331             /* We are/were sending a caller id spill.  Suppress any echo. */
09332             p->subs[idx].f.frametype = AST_FRAME_NULL;
09333             p->subs[idx].f.subclass.integer = 0;
09334             p->subs[idx].f.samples = 0;
09335             p->subs[idx].f.mallocd = 0;
09336             p->subs[idx].f.offset = 0;
09337             p->subs[idx].f.data.ptr = NULL;
09338             p->subs[idx].f.datalen= 0;
09339          }
09340          break;
09341       default:
09342          break;
09343       }
09344    }
09345 
09346    ast_mutex_unlock(&p->lock);
09347    return f;
09348 }
09349 
09350 static int my_dahdi_write(struct dahdi_pvt *p, unsigned char *buf, int len, int idx, int linear)
09351 {
09352    int sent=0;
09353    int size;
09354    int res;
09355    int fd;
09356    fd = p->subs[idx].dfd;
09357    while (len) {
09358       size = len;
09359       if (size > (linear ? READ_SIZE * 2 : READ_SIZE))
09360          size = (linear ? READ_SIZE * 2 : READ_SIZE);
09361       res = write(fd, buf, size);
09362       if (res != size) {
09363          ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
09364          return sent;
09365       }
09366       len -= size;
09367       buf += size;
09368    }
09369    return sent;
09370 }
09371 
09372 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame)
09373 {
09374    struct dahdi_pvt *p = ast->tech_pvt;
09375    int res;
09376    int idx;
09377    idx = dahdi_get_index(ast, p, 0);
09378    if (idx < 0) {
09379       ast_log(LOG_WARNING, "%s doesn't really exist?\n", ast->name);
09380       return -1;
09381    }
09382 
09383    /* Write a frame of (presumably voice) data */
09384    if (frame->frametype != AST_FRAME_VOICE) {
09385       if (frame->frametype != AST_FRAME_IMAGE)
09386          ast_log(LOG_WARNING, "Don't know what to do with frame type '%d'\n", frame->frametype);
09387       return 0;
09388    }
09389    if ((frame->subclass.codec != AST_FORMAT_SLINEAR) &&
09390       (frame->subclass.codec != AST_FORMAT_ULAW) &&
09391       (frame->subclass.codec != AST_FORMAT_ALAW)) {
09392       ast_log(LOG_WARNING, "Cannot handle frames in %s format\n", ast_getformatname(frame->subclass.codec));
09393       return -1;
09394    }
09395    if (p->dialing) {
09396       ast_debug(1, "Dropping frame since I'm still dialing on %s...\n",ast->name);
09397       return 0;
09398    }
09399    if (!p->owner) {
09400       ast_debug(1, "Dropping frame since there is no active owner on %s...\n",ast->name);
09401       return 0;
09402    }
09403    if (p->cidspill) {
09404       ast_debug(1, "Dropping frame since I've still got a callerid spill on %s...\n",
09405          ast->name);
09406       return 0;
09407    }
09408    /* Return if it's not valid data */
09409    if (!frame->data.ptr || !frame->datalen)
09410       return 0;
09411 
09412    if (frame->subclass.codec == AST_FORMAT_SLINEAR) {
09413       if (!p->subs[idx].linear) {
09414          p->subs[idx].linear = 1;
09415          res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09416          if (res)
09417             ast_log(LOG_WARNING, "Unable to set linear mode on channel %d\n", p->channel);
09418       }
09419       res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 1);
09420    } else {
09421       /* x-law already */
09422       if (p->subs[idx].linear) {
09423          p->subs[idx].linear = 0;
09424          res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09425          if (res)
09426             ast_log(LOG_WARNING, "Unable to set companded mode on channel %d\n", p->channel);
09427       }
09428       res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 0);
09429    }
09430    if (res < 0) {
09431       ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
09432       return -1;
09433    }
09434    return 0;
09435 }
09436 
09437 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen)
09438 {
09439    struct dahdi_pvt *p = chan->tech_pvt;
09440    int res=-1;
09441    int idx;
09442    int func = DAHDI_FLASH;
09443 
09444    ast_mutex_lock(&p->lock);
09445    ast_debug(1, "Requested indication %d on channel %s\n", condition, chan->name);
09446    switch (p->sig) {
09447 #if defined(HAVE_PRI)
09448    case SIG_PRI_LIB_HANDLE_CASES:
09449       res = sig_pri_indicate(p->sig_pvt, chan, condition, data, datalen);
09450       ast_mutex_unlock(&p->lock);
09451       return res;
09452 #endif   /* defined(HAVE_PRI) */
09453 #if defined(HAVE_SS7)
09454    case SIG_SS7:
09455       res = sig_ss7_indicate(p->sig_pvt, chan, condition, data, datalen);
09456       ast_mutex_unlock(&p->lock);
09457       return res;
09458 #endif   /* defined(HAVE_SS7) */
09459    default:
09460       break;
09461    }
09462 #ifdef HAVE_OPENR2
09463    if (p->mfcr2 && !p->mfcr2_call_accepted) {
09464       ast_mutex_unlock(&p->lock);
09465       /* if this is an R2 call and the call is not yet accepted, we don't want the
09466          tone indications to mess up with the MF tones */
09467       return 0;
09468    }
09469 #endif
09470    idx = dahdi_get_index(chan, p, 0);
09471    if (idx == SUB_REAL) {
09472       switch (condition) {
09473       case AST_CONTROL_BUSY:
09474          res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_BUSY);
09475          break;
09476       case AST_CONTROL_RINGING:
09477          res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_RINGTONE);
09478 
09479          if (chan->_state != AST_STATE_UP) {
09480             if ((chan->_state != AST_STATE_RING) ||
09481                ((p->sig != SIG_FXSKS) &&
09482              (p->sig != SIG_FXSLS) &&
09483              (p->sig != SIG_FXSGS)))
09484             ast_setstate(chan, AST_STATE_RINGING);
09485          }
09486          break;
09487       case AST_CONTROL_INCOMPLETE:
09488          ast_debug(1, "Received AST_CONTROL_INCOMPLETE on %s\n", chan->name);
09489          /* act as a progress or proceeding, allowing the caller to enter additional numbers */
09490          res = 0;
09491          break;
09492       case AST_CONTROL_PROCEEDING:
09493          ast_debug(1, "Received AST_CONTROL_PROCEEDING on %s\n", chan->name);
09494          /* don't continue in ast_indicate */
09495          res = 0;
09496          break;
09497       case AST_CONTROL_PROGRESS:
09498          ast_debug(1, "Received AST_CONTROL_PROGRESS on %s\n", chan->name);
09499          /* don't continue in ast_indicate */
09500          res = 0;
09501          break;
09502       case AST_CONTROL_CONGESTION:
09503          /* There are many cause codes that generate an AST_CONTROL_CONGESTION. */
09504          switch (chan->hangupcause) {
09505          case AST_CAUSE_USER_BUSY:
09506          case AST_CAUSE_NORMAL_CLEARING:
09507          case 0:/* Cause has not been set. */
09508             /* Supply a more appropriate cause. */
09509             chan->hangupcause = AST_CAUSE_CONGESTION;
09510             break;
09511          default:
09512             break;
09513          }
09514          break;
09515       case AST_CONTROL_HOLD:
09516          ast_moh_start(chan, data, p->mohinterpret);
09517          break;
09518       case AST_CONTROL_UNHOLD:
09519          ast_moh_stop(chan);
09520          break;
09521       case AST_CONTROL_RADIO_KEY:
09522          if (p->radio)
09523             res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
09524          res = 0;
09525          break;
09526       case AST_CONTROL_RADIO_UNKEY:
09527          if (p->radio)
09528             res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_RINGOFF);
09529          res = 0;
09530          break;
09531       case AST_CONTROL_FLASH:
09532          /* flash hookswitch */
09533          if (ISTRUNK(p) && (p->sig != SIG_PRI)) {
09534             /* Clear out the dial buffer */
09535             p->dop.dialstr[0] = '\0';
09536             if ((ioctl(p->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
09537                ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
09538                   chan->name, strerror(errno));
09539             } else
09540                res = 0;
09541          } else
09542             res = 0;
09543          break;
09544       case AST_CONTROL_SRCUPDATE:
09545          res = 0;
09546          break;
09547       case -1:
09548          res = tone_zone_play_tone(p->subs[idx].dfd, -1);
09549          break;
09550       }
09551    } else {
09552       res = 0;
09553    }
09554    ast_mutex_unlock(&p->lock);
09555    return res;
09556 }
09557 
09558 #if defined(HAVE_PRI)
09559 static struct ast_str *create_channel_name(struct dahdi_pvt *i, int is_outgoing, char *address)
09560 #else
09561 static struct ast_str *create_channel_name(struct dahdi_pvt *i)
09562 #endif   /* defined(HAVE_PRI) */
09563 {
09564    struct ast_str *chan_name;
09565    int x, y;
09566 
09567    /* Create the new channel name tail. */
09568    if (!(chan_name = ast_str_create(32))) {
09569       return NULL;
09570    }
09571    if (i->channel == CHAN_PSEUDO) {
09572       ast_str_set(&chan_name, 0, "pseudo-%ld", ast_random());
09573 #if defined(HAVE_PRI)
09574    } else if (i->pri) {
09575       ast_mutex_lock(&i->pri->lock);
09576       y = ++i->pri->new_chan_seq;
09577       if (is_outgoing) {
09578          ast_str_set(&chan_name, 0, "i%d/%s-%x", i->pri->span, address, y);
09579          address[0] = '\0';
09580       } else if (ast_strlen_zero(i->cid_subaddr)) {
09581          /* Put in caller-id number only since there is no subaddress. */
09582          ast_str_set(&chan_name, 0, "i%d/%s-%x", i->pri->span, i->cid_num, y);
09583       } else {
09584          /* Put in caller-id number and subaddress. */
09585          ast_str_set(&chan_name, 0, "i%d/%s:%s-%x", i->pri->span, i->cid_num,
09586             i->cid_subaddr, y);
09587       }
09588       ast_mutex_unlock(&i->pri->lock);
09589 #endif   /* defined(HAVE_PRI) */
09590    } else {
09591       y = 1;
09592       do {
09593          ast_str_set(&chan_name, 0, "%d-%d", i->channel, y);
09594          for (x = 0; x < 3; ++x) {
09595             if (i->subs[x].owner && !strcasecmp(ast_str_buffer(chan_name),
09596                i->subs[x].owner->name + 6)) {
09597                break;
09598             }
09599          }
09600          ++y;
09601       } while (x < 3);
09602    }
09603    return chan_name;
09604 }
09605 
09606 static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpbx, int idx, int law, const char *linkedid)
09607 {
09608    struct ast_channel *tmp;
09609    format_t deflaw;
09610    int x;
09611    int features;
09612    struct ast_str *chan_name;
09613    struct ast_variable *v;
09614    char *dashptr;
09615    char device_name[AST_CHANNEL_NAME];
09616 
09617    if (i->subs[idx].owner) {
09618       ast_log(LOG_WARNING, "Channel %d already has a %s call\n", i->channel,subnames[idx]);
09619       return NULL;
09620    }
09621 
09622 #if defined(HAVE_PRI)
09623    /*
09624     * The dnid has been stuffed with the called-number[:subaddress]
09625     * by dahdi_request() for outgoing calls.
09626     */
09627    chan_name = create_channel_name(i, i->outgoing, i->dnid);
09628 #else
09629    chan_name = create_channel_name(i);
09630 #endif   /* defined(HAVE_PRI) */
09631    if (!chan_name) {
09632       return NULL;
09633    }
09634 
09635    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));
09636    ast_free(chan_name);
09637    if (!tmp)
09638       return NULL;
09639    tmp->tech = &dahdi_tech;
09640 #if defined(HAVE_PRI)
09641    if (i->pri) {
09642       ast_cc_copy_config_params(i->cc_params, i->pri->cc_params);
09643    }
09644 #endif   /* defined(HAVE_PRI) */
09645    ast_channel_cc_params_init(tmp, i->cc_params);
09646    if (law) {
09647       i->law = law;
09648       if (law == DAHDI_LAW_ALAW) {
09649          deflaw = AST_FORMAT_ALAW;
09650       } else {
09651          deflaw = AST_FORMAT_ULAW;
09652       }
09653    } else {
09654       switch (i->sig) {
09655       case SIG_PRI_LIB_HANDLE_CASES:
09656          /* Make sure companding law is known. */
09657          i->law = (i->law_default == DAHDI_LAW_ALAW)
09658             ? DAHDI_LAW_ALAW : DAHDI_LAW_MULAW;
09659          break;
09660       default:
09661          i->law = i->law_default;
09662          break;
09663       }
09664       if (i->law_default == DAHDI_LAW_ALAW) {
09665          deflaw = AST_FORMAT_ALAW;
09666       } else {
09667          deflaw = AST_FORMAT_ULAW;
09668       }
09669    }
09670    ast_channel_set_fd(tmp, 0, i->subs[idx].dfd);
09671    tmp->nativeformats = deflaw;
09672    /* Start out assuming ulaw since it's smaller :) */
09673    tmp->rawreadformat = deflaw;
09674    tmp->readformat = deflaw;
09675    tmp->rawwriteformat = deflaw;
09676    tmp->writeformat = deflaw;
09677    i->subs[idx].linear = 0;
09678    dahdi_setlinear(i->subs[idx].dfd, i->subs[idx].linear);
09679    features = 0;
09680    if (idx == SUB_REAL) {
09681       if (i->busydetect && CANBUSYDETECT(i))
09682          features |= DSP_FEATURE_BUSY_DETECT;
09683       if ((i->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(i))
09684          features |= DSP_FEATURE_CALL_PROGRESS;
09685       if ((i->waitfordialtone) && CANPROGRESSDETECT(i))
09686          features |= DSP_FEATURE_WAITDIALTONE;
09687       if ((!i->outgoing && (i->callprogress & CALLPROGRESS_FAX_INCOMING)) ||
09688          (i->outgoing && (i->callprogress & CALLPROGRESS_FAX_OUTGOING))) {
09689          features |= DSP_FEATURE_FAX_DETECT;
09690       }
09691       x = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
09692       if (ioctl(i->subs[idx].dfd, DAHDI_TONEDETECT, &x)) {
09693          i->hardwaredtmf = 0;
09694          features |= DSP_FEATURE_DIGIT_DETECT;
09695       } else if (NEED_MFDETECT(i)) {
09696          i->hardwaredtmf = 1;
09697          features |= DSP_FEATURE_DIGIT_DETECT;
09698       }
09699    }
09700    if (features) {
09701       if (i->dsp) {
09702          ast_debug(1, "Already have a dsp on %s?\n", tmp->name);
09703       } else {
09704          if (i->channel != CHAN_PSEUDO)
09705             i->dsp = ast_dsp_new();
09706          else
09707             i->dsp = NULL;
09708          if (i->dsp) {
09709             i->dsp_features = features;
09710 #if defined(HAVE_PRI) || defined(HAVE_SS7)
09711             /* We cannot do progress detection until receive PROGRESS message */
09712             if (i->outgoing && (dahdi_sig_pri_lib_handles(i->sig) || (i->sig == SIG_SS7))) {
09713                /* Remember requested DSP features, don't treat
09714                   talking as ANSWER */
09715                i->dsp_features = features & ~DSP_PROGRESS_TALK;
09716                features = 0;
09717             }
09718 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
09719             ast_dsp_set_features(i->dsp, features);
09720             ast_dsp_set_digitmode(i->dsp, DSP_DIGITMODE_DTMF | i->dtmfrelax);
09721             if (!ast_strlen_zero(progzone))
09722                ast_dsp_set_call_progress_zone(i->dsp, progzone);
09723             if (i->busydetect && CANBUSYDETECT(i)) {
09724                if(i->silencethreshold > 0)
09725                   ast_dsp_set_threshold(i->dsp, i->silencethreshold);
09726                ast_dsp_set_busy_count(i->dsp, i->busycount);
09727                if(i->busytonelength > 0)
09728                   ast_dsp_set_busy_pattern(i->dsp, i->busytonelength, i->busyquietlength, i->busyfuzziness);
09729                if((i->busytonelength == i->busyquietlength) && i->busycompare)
09730                   ast_dsp_set_busy_compare(i->dsp, i->busycompare);
09731             }
09732          }
09733       }
09734    }
09735 
09736    if (state == AST_STATE_RING)
09737       tmp->rings = 1;
09738    tmp->tech_pvt = i;
09739    if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) {
09740       /* Only FXO signalled stuff can be picked up */
09741       tmp->callgroup = i->callgroup;
09742       tmp->pickupgroup = i->pickupgroup;
09743    }
09744    if (!ast_strlen_zero(i->parkinglot))
09745       ast_string_field_set(tmp, parkinglot, i->parkinglot);
09746    if (!ast_strlen_zero(i->language))
09747       ast_string_field_set(tmp, language, i->language);
09748    if (!i->owner)
09749       i->owner = tmp;
09750    if (!ast_strlen_zero(i->accountcode))
09751       ast_string_field_set(tmp, accountcode, i->accountcode);
09752    if (i->amaflags)
09753       tmp->amaflags = i->amaflags;
09754    i->subs[idx].owner = tmp;
09755    ast_copy_string(tmp->context, i->context, sizeof(tmp->context));
09756    if (!analog_lib_handles(i->sig, i->radio, i->oprmode)) {
09757       ast_string_field_set(tmp, call_forward, i->call_forward);
09758    }
09759    /* If we've been told "no ADSI" then enforce it */
09760    if (!i->adsi)
09761       tmp->adsicpe = AST_ADSI_UNAVAILABLE;
09762    if (!ast_strlen_zero(i->exten))
09763       ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten));
09764    if (!ast_strlen_zero(i->rdnis)) {
09765       tmp->redirecting.from.number.valid = 1;
09766       tmp->redirecting.from.number.str = ast_strdup(i->rdnis);
09767    }
09768    if (!ast_strlen_zero(i->dnid)) {
09769       tmp->dialed.number.str = ast_strdup(i->dnid);
09770    }
09771 
09772    /* Don't use ast_set_callerid() here because it will
09773     * generate a needless NewCallerID event */
09774 #if defined(HAVE_PRI) || defined(HAVE_SS7)
09775    if (!ast_strlen_zero(i->cid_ani)) {
09776       tmp->caller.ani.number.valid = 1;
09777       tmp->caller.ani.number.str = ast_strdup(i->cid_ani);
09778    } else if (!ast_strlen_zero(i->cid_num)) {
09779       tmp->caller.ani.number.valid = 1;
09780       tmp->caller.ani.number.str = ast_strdup(i->cid_num);
09781    }
09782 #else
09783    if (!ast_strlen_zero(i->cid_num)) {
09784       tmp->caller.ani.number.valid = 1;
09785       tmp->caller.ani.number.str = ast_strdup(i->cid_num);
09786    }
09787 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
09788    tmp->caller.id.name.presentation = i->callingpres;
09789    tmp->caller.id.number.presentation = i->callingpres;
09790    tmp->caller.id.number.plan = i->cid_ton;
09791    tmp->caller.ani2 = i->cid_ani2;
09792    tmp->caller.id.tag = ast_strdup(i->cid_tag);
09793    /* clear the fake event in case we posted one before we had ast_channel */
09794    i->fake_event = 0;
09795    /* Assure there is no confmute on this channel */
09796    dahdi_confmute(i, 0);
09797    i->muting = 0;
09798    /* Configure the new channel jb */
09799    ast_jb_configure(tmp, &global_jbconf);
09800 
09801    /* Set initial device state */
09802    ast_copy_string(device_name, tmp->name, sizeof(device_name));
09803    dashptr = strrchr(device_name, '-');
09804    if (dashptr) {
09805       *dashptr = '\0';
09806    }
09807    ast_devstate_changed_literal(AST_DEVICE_UNKNOWN, device_name);
09808 
09809    for (v = i->vars ; v ; v = v->next)
09810       pbx_builtin_setvar_helper(tmp, v->name, v->value);
09811 
09812    ast_module_ref(ast_module_info->self);
09813 
09814    dahdi_ami_channel_event(i, tmp);
09815    if (startpbx) {
09816 #ifdef HAVE_OPENR2
09817       if (i->mfcr2call) {
09818          pbx_builtin_setvar_helper(tmp, "MFCR2_CATEGORY", openr2_proto_get_category_string(i->mfcr2_recvd_category));
09819       }
09820 #endif
09821       if (ast_pbx_start(tmp)) {
09822          ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
09823          ast_hangup(tmp);
09824          return NULL;
09825       }
09826    }
09827    return tmp;
09828 }
09829 
09830 
09831 static int my_getsigstr(struct ast_channel *chan, char *str, const char *term, int ms)
09832 {
09833    char c;
09834 
09835    *str = 0; /* start with empty output buffer */
09836    for (;;)
09837    {
09838       /* Wait for the first digit (up to specified ms). */
09839       c = ast_waitfordigit(chan, ms);
09840       /* if timeout, hangup or error, return as such */
09841       if (c < 1)
09842          return c;
09843       *str++ = c;
09844       *str = 0;
09845       if (strchr(term, c))
09846          return 1;
09847    }
09848 }
09849 
09850 static int dahdi_wink(struct dahdi_pvt *p, int idx)
09851 {
09852    int j;
09853    dahdi_set_hook(p->subs[idx].dfd, DAHDI_WINK);
09854    for (;;)
09855    {
09856       /* set bits of interest */
09857       j = DAHDI_IOMUX_SIGEVENT;
09858       /* wait for some happening */
09859       if (ioctl(p->subs[idx].dfd,DAHDI_IOMUX,&j) == -1) return(-1);
09860       /* exit loop if we have it */
09861       if (j & DAHDI_IOMUX_SIGEVENT) break;
09862    }
09863    /* get the event info */
09864    if (ioctl(p->subs[idx].dfd,DAHDI_GETEVENT,&j) == -1) return(-1);
09865    return 0;
09866 }
09867 
09868 /*! \brief enable or disable the chan_dahdi Do-Not-Disturb mode for a DAHDI channel
09869  * \param dahdichan "Physical" DAHDI channel (e.g: DAHDI/5)
09870  * \param flag on 1 to enable, 0 to disable, -1 return dnd value
09871  *
09872  * chan_dahdi has a DND (Do Not Disturb) mode for each dahdichan (physical
09873  * DAHDI channel). Use this to enable or disable it.
09874  *
09875  * \bug the use of the word "channel" for those dahdichans is really confusing.
09876  */
09877 static int dahdi_dnd(struct dahdi_pvt *dahdichan, int flag)
09878 {
09879    if (analog_lib_handles(dahdichan->sig, dahdichan->radio, dahdichan->oprmode)) {
09880       return analog_dnd(dahdichan->sig_pvt, flag);
09881    }
09882 
09883    if (flag == -1) {
09884       return dahdichan->dnd;
09885    }
09886 
09887    /* Do not disturb */
09888    dahdichan->dnd = flag;
09889    ast_verb(3, "%s DND on channel %d\n",
09890          flag? "Enabled" : "Disabled",
09891          dahdichan->channel);
09892    manager_event(EVENT_FLAG_SYSTEM, "DNDState",
09893          "Channel: DAHDI/%d\r\n"
09894          "Status: %s\r\n", dahdichan->channel,
09895          flag? "enabled" : "disabled");
09896 
09897    return 0;
09898 }
09899 
09900 static int canmatch_featurecode(const char *exten)
09901 {
09902    int extlen = strlen(exten);
09903    const char *pickup_ext;
09904    if (!extlen) {
09905       return 1;
09906    }
09907    pickup_ext = ast_pickup_ext();
09908    if (extlen < strlen(pickup_ext) && !strncmp(pickup_ext, exten, extlen)) {
09909       return 1;
09910    }
09911    /* hardcoded features are *60, *67, *69, *70, *72, *73, *78, *79, *82, *0 */
09912    if (exten[0] == '*' && extlen < 3) {
09913       if (extlen == 1) {
09914          return 1;
09915       }
09916       /* "*0" should be processed before it gets here */
09917       switch (exten[1]) {
09918       case '6':
09919       case '7':
09920       case '8':
09921          return 1;
09922       }
09923    }
09924    return 0;
09925 }
09926 
09927 static void *analog_ss_thread(void *data)
09928 {
09929    struct ast_channel *chan = data;
09930    struct dahdi_pvt *p = chan->tech_pvt;
09931    char exten[AST_MAX_EXTENSION] = "";
09932    char exten2[AST_MAX_EXTENSION] = "";
09933    unsigned char buf[256];
09934    char dtmfcid[300];
09935    char dtmfbuf[300];
09936    struct callerid_state *cs = NULL;
09937    char *name = NULL, *number = NULL;
09938    int distMatches;
09939    int curRingData[3];
09940    int receivedRingT;
09941    int counter1;
09942    int counter;
09943    int samples = 0;
09944    struct ast_smdi_md_message *smdi_msg = NULL;
09945    int flags = 0;
09946    int i;
09947    int timeout;
09948    int getforward = 0;
09949    char *s1, *s2;
09950    int len = 0;
09951    int res;
09952    int idx;
09953 
09954    ast_mutex_lock(&ss_thread_lock);
09955    ss_thread_count++;
09956    ast_mutex_unlock(&ss_thread_lock);
09957    /* in the bizarre case where the channel has become a zombie before we
09958       even get started here, abort safely
09959    */
09960    if (!p) {
09961       ast_log(LOG_WARNING, "Channel became a zombie before simple switch could be started (%s)\n", chan->name);
09962       ast_hangup(chan);
09963       goto quit;
09964    }
09965    ast_verb(3, "Starting simple switch on '%s'\n", chan->name);
09966    idx = dahdi_get_index(chan, p, 1);
09967    if (idx < 0) {
09968       ast_log(LOG_WARNING, "Huh?\n");
09969       ast_hangup(chan);
09970       goto quit;
09971    }
09972    if (p->dsp)
09973       ast_dsp_digitreset(p->dsp);
09974    switch (p->sig) {
09975    case SIG_FEATD:
09976    case SIG_FEATDMF:
09977    case SIG_FEATDMF_TA:
09978    case SIG_E911:
09979    case SIG_FGC_CAMAMF:
09980    case SIG_FEATB:
09981    case SIG_EMWINK:
09982    case SIG_SF_FEATD:
09983    case SIG_SF_FEATDMF:
09984    case SIG_SF_FEATB:
09985    case SIG_SFWINK:
09986       if (dahdi_wink(p, idx))
09987          goto quit;
09988       /* Fall through */
09989    case SIG_EM:
09990    case SIG_EM_E1:
09991    case SIG_SF:
09992    case SIG_FGC_CAMA:
09993       res = tone_zone_play_tone(p->subs[idx].dfd, -1);
09994       if (p->dsp)
09995          ast_dsp_digitreset(p->dsp);
09996       /* set digit mode appropriately */
09997       if (p->dsp) {
09998          if (NEED_MFDETECT(p))
09999             ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
10000          else
10001             ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
10002       }
10003       memset(dtmfbuf, 0, sizeof(dtmfbuf));
10004       /* Wait for the first digit only if immediate=no */
10005       if (!p->immediate)
10006          /* Wait for the first digit (up to 5 seconds). */
10007          res = ast_waitfordigit(chan, 5000);
10008       else
10009          res = 0;
10010       if (res > 0) {
10011          /* save first char */
10012          dtmfbuf[0] = res;
10013          switch (p->sig) {
10014          case SIG_FEATD:
10015          case SIG_SF_FEATD:
10016             res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
10017             if (res > 0)
10018                res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
10019             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
10020             break;
10021          case SIG_FEATDMF_TA:
10022             res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
10023             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
10024             if (dahdi_wink(p, idx)) goto quit;
10025             dtmfbuf[0] = 0;
10026             /* Wait for the first digit (up to 5 seconds). */
10027             res = ast_waitfordigit(chan, 5000);
10028             if (res <= 0) break;
10029             dtmfbuf[0] = res;
10030             /* fall through intentionally */
10031          case SIG_FEATDMF:
10032          case SIG_E911:
10033          case SIG_FGC_CAMAMF:
10034          case SIG_SF_FEATDMF:
10035             res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
10036             /* if international caca, do it again to get real ANO */
10037             if ((p->sig == SIG_FEATDMF) && (dtmfbuf[1] != '0') && (strlen(dtmfbuf) != 14))
10038             {
10039                if (dahdi_wink(p, idx)) goto quit;
10040                dtmfbuf[0] = 0;
10041                /* Wait for the first digit (up to 5 seconds). */
10042                res = ast_waitfordigit(chan, 5000);
10043                if (res <= 0) break;
10044                dtmfbuf[0] = res;
10045                res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
10046             }
10047             if (res > 0) {
10048                /* if E911, take off hook */
10049                if (p->sig == SIG_E911)
10050                   dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
10051                res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "#", 3000);
10052             }
10053             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
10054             break;
10055          case SIG_FEATB:
10056          case SIG_SF_FEATB:
10057             res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
10058             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
10059             break;
10060          case SIG_EMWINK:
10061             /* if we received a '*', we are actually receiving Feature Group D
10062                dial syntax, so use that mode; otherwise, fall through to normal
10063                mode
10064             */
10065             if (res == '*') {
10066                res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
10067                if (res > 0)
10068                   res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
10069                if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
10070                break;
10071             }
10072          default:
10073             /* If we got the first digit, get the rest */
10074             len = 1;
10075             dtmfbuf[len] = '\0';
10076             while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
10077                if (ast_exists_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
10078                   timeout = matchdigittimeout;
10079                } else {
10080                   timeout = gendigittimeout;
10081                }
10082                res = ast_waitfordigit(chan, timeout);
10083                if (res < 0) {
10084                   ast_debug(1, "waitfordigit returned < 0...\n");
10085                   ast_hangup(chan);
10086                   goto quit;
10087                } else if (res) {
10088                   dtmfbuf[len++] = res;
10089                   dtmfbuf[len] = '\0';
10090                } else {
10091                   break;
10092                }
10093             }
10094             break;
10095          }
10096       }
10097       if (res == -1) {
10098          ast_log(LOG_WARNING, "getdtmf on channel %d: %s\n", p->channel, strerror(errno));
10099          ast_hangup(chan);
10100          goto quit;
10101       } else if (res < 0) {
10102          ast_debug(1, "Got hung up before digits finished\n");
10103          ast_hangup(chan);
10104          goto quit;
10105       }
10106 
10107       if (p->sig == SIG_FGC_CAMA) {
10108          char anibuf[100];
10109 
10110          if (ast_safe_sleep(chan,1000) == -1) {
10111             ast_hangup(chan);
10112             goto quit;
10113          }
10114          dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
10115          ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
10116          res = my_getsigstr(chan, anibuf, "#", 10000);
10117          if ((res > 0) && (strlen(anibuf) > 2)) {
10118             if (anibuf[strlen(anibuf) - 1] == '#')
10119                anibuf[strlen(anibuf) - 1] = 0;
10120             ast_set_callerid(chan, anibuf + 2, NULL, anibuf + 2);
10121          }
10122          ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
10123       }
10124 
10125       ast_copy_string(exten, dtmfbuf, sizeof(exten));
10126       if (ast_strlen_zero(exten))
10127          ast_copy_string(exten, "s", sizeof(exten));
10128       if (p->sig == SIG_FEATD || p->sig == SIG_EMWINK) {
10129          /* Look for Feature Group D on all E&M Wink and Feature Group D trunks */
10130          if (exten[0] == '*') {
10131             char *stringp=NULL;
10132             ast_copy_string(exten2, exten, sizeof(exten2));
10133             /* Parse out extension and callerid */
10134             stringp=exten2 +1;
10135             s1 = strsep(&stringp, "*");
10136             s2 = strsep(&stringp, "*");
10137             if (s2) {
10138                if (!ast_strlen_zero(p->cid_num))
10139                   ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
10140                else
10141                   ast_set_callerid(chan, s1, NULL, s1);
10142                ast_copy_string(exten, s2, sizeof(exten));
10143             } else
10144                ast_copy_string(exten, s1, sizeof(exten));
10145          } else if (p->sig == SIG_FEATD)
10146             ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d.  Assuming E&M Wink instead\n", p->channel);
10147       }
10148       if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
10149          if (exten[0] == '*') {
10150             char *stringp=NULL;
10151             ast_copy_string(exten2, exten, sizeof(exten2));
10152             /* Parse out extension and callerid */
10153             stringp=exten2 +1;
10154             s1 = strsep(&stringp, "#");
10155             s2 = strsep(&stringp, "#");
10156             if (s2) {
10157                if (!ast_strlen_zero(p->cid_num))
10158                   ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
10159                else
10160                   if (*(s1 + 2))
10161                      ast_set_callerid(chan, s1 + 2, NULL, s1 + 2);
10162                ast_copy_string(exten, s2 + 1, sizeof(exten));
10163             } else
10164                ast_copy_string(exten, s1 + 2, sizeof(exten));
10165          } else
10166             ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d.  Assuming E&M Wink instead\n", p->channel);
10167       }
10168       if ((p->sig == SIG_E911) || (p->sig == SIG_FGC_CAMAMF)) {
10169          if (exten[0] == '*') {
10170             char *stringp=NULL;
10171             ast_copy_string(exten2, exten, sizeof(exten2));
10172             /* Parse out extension and callerid */
10173             stringp=exten2 +1;
10174             s1 = strsep(&stringp, "#");
10175             s2 = strsep(&stringp, "#");
10176             if (s2 && (*(s2 + 1) == '0')) {
10177                if (*(s2 + 2))
10178                   ast_set_callerid(chan, s2 + 2, NULL, s2 + 2);
10179             }
10180             if (s1)  ast_copy_string(exten, s1, sizeof(exten));
10181             else ast_copy_string(exten, "911", sizeof(exten));
10182          } else
10183             ast_log(LOG_WARNING, "Got a non-E911/FGC CAMA input on channel %d.  Assuming E&M Wink instead\n", p->channel);
10184       }
10185       if (p->sig == SIG_FEATB) {
10186          if (exten[0] == '*') {
10187             char *stringp=NULL;
10188             ast_copy_string(exten2, exten, sizeof(exten2));
10189             /* Parse out extension and callerid */
10190             stringp=exten2 +1;
10191             s1 = strsep(&stringp, "#");
10192             ast_copy_string(exten, exten2 + 1, sizeof(exten));
10193          } else
10194             ast_log(LOG_WARNING, "Got a non-Feature Group B input on channel %d.  Assuming E&M Wink instead\n", p->channel);
10195       }
10196       if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
10197          dahdi_wink(p, idx);
10198          /* some switches require a minimum guard time between
10199             the last FGD wink and something that answers
10200             immediately. This ensures it */
10201          if (ast_safe_sleep(chan, 100)) {
10202             ast_hangup(chan);
10203             goto quit;
10204          }
10205       }
10206       dahdi_enable_ec(p);
10207       if (NEED_MFDETECT(p)) {
10208          if (p->dsp) {
10209             if (!p->hardwaredtmf)
10210                ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
10211             else {
10212                ast_dsp_free(p->dsp);
10213                p->dsp = NULL;
10214             }
10215          }
10216       }
10217 
10218       if (ast_exists_extension(chan, chan->context, exten, 1,
10219          S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
10220          ast_copy_string(chan->exten, exten, sizeof(chan->exten));
10221          if (p->dsp) ast_dsp_digitreset(p->dsp);
10222          res = ast_pbx_run(chan);
10223          if (res) {
10224             ast_log(LOG_WARNING, "PBX exited non-zero\n");
10225             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10226          }
10227          goto quit;
10228       } else {
10229          ast_verb(2, "Unknown extension '%s' in context '%s' requested\n", exten, chan->context);
10230          sleep(2);
10231          res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_INFO);
10232          if (res < 0)
10233             ast_log(LOG_WARNING, "Unable to start special tone on %d\n", p->channel);
10234          else
10235             sleep(1);
10236          res = ast_streamfile(chan, "ss-noservice", chan->language);
10237          if (res >= 0)
10238             ast_waitstream(chan, "");
10239          res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10240          ast_hangup(chan);
10241          goto quit;
10242       }
10243       break;
10244    case SIG_FXOLS:
10245    case SIG_FXOGS:
10246    case SIG_FXOKS:
10247       /* Read the first digit */
10248       timeout = firstdigittimeout;
10249       /* If starting a threeway call, never timeout on the first digit so someone
10250          can use flash-hook as a "hold" feature */
10251       if (p->subs[SUB_THREEWAY].owner)
10252          timeout = 999999;
10253       while (len < AST_MAX_EXTENSION-1) {
10254          /* Read digit unless it's supposed to be immediate, in which case the
10255             only answer is 's' */
10256          if (p->immediate)
10257             res = 's';
10258          else
10259             res = ast_waitfordigit(chan, timeout);
10260          timeout = 0;
10261          if (res < 0) {
10262             ast_debug(1, "waitfordigit returned < 0...\n");
10263             res = tone_zone_play_tone(p->subs[idx].dfd, -1);
10264             ast_hangup(chan);
10265             goto quit;
10266          } else if (res) {
10267             ast_debug(1,"waitfordigit returned '%c' (%d), timeout = %d\n", res, res, timeout);
10268             exten[len++]=res;
10269             exten[len] = '\0';
10270          }
10271          if (!ast_ignore_pattern(chan->context, exten))
10272             tone_zone_play_tone(p->subs[idx].dfd, -1);
10273          else
10274             tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
10275          if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num) && !ast_parking_ext_valid(exten, chan, chan->context)) {
10276             if (!res || !ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
10277                if (getforward) {
10278                   /* Record this as the forwarding extension */
10279                   ast_copy_string(p->call_forward, exten, sizeof(p->call_forward));
10280                   ast_verb(3, "Setting call forward to '%s' on channel %d\n", p->call_forward, p->channel);
10281                   res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10282                   if (res)
10283                      break;
10284                   usleep(500000);
10285                   res = tone_zone_play_tone(p->subs[idx].dfd, -1);
10286                   sleep(1);
10287                   memset(exten, 0, sizeof(exten));
10288                   res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
10289                   len = 0;
10290                   getforward = 0;
10291                } else {
10292                   res = tone_zone_play_tone(p->subs[idx].dfd, -1);
10293                   ast_copy_string(chan->exten, exten, sizeof(chan->exten));
10294                   if (!ast_strlen_zero(p->cid_num)) {
10295                      if (!p->hidecallerid)
10296                         ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
10297                      else
10298                         ast_set_callerid(chan, NULL, NULL, p->cid_num);
10299                   }
10300                   if (!ast_strlen_zero(p->cid_name)) {
10301                      if (!p->hidecallerid)
10302                         ast_set_callerid(chan, NULL, p->cid_name, NULL);
10303                   }
10304                   ast_setstate(chan, AST_STATE_RING);
10305                   dahdi_enable_ec(p);
10306                   res = ast_pbx_run(chan);
10307                   if (res) {
10308                      ast_log(LOG_WARNING, "PBX exited non-zero\n");
10309                      res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10310                   }
10311                   goto quit;
10312                }
10313             } else {
10314                /* It's a match, but they just typed a digit, and there is an ambiguous match,
10315                   so just set the timeout to matchdigittimeout and wait some more */
10316                timeout = matchdigittimeout;
10317             }
10318          } else if (res == 0) {
10319             ast_debug(1, "not enough digits (and no ambiguous match)...\n");
10320             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10321             dahdi_wait_event(p->subs[idx].dfd);
10322             ast_hangup(chan);
10323             goto quit;
10324          } else if (p->callwaiting && !strcmp(exten, "*70")) {
10325             ast_verb(3, "Disabling call waiting on %s\n", chan->name);
10326             /* Disable call waiting if enabled */
10327             p->callwaiting = 0;
10328             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10329             if (res) {
10330                ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
10331                   chan->name, strerror(errno));
10332             }
10333             len = 0;
10334             ioctl(p->subs[idx].dfd,DAHDI_CONFDIAG,&len);
10335             memset(exten, 0, sizeof(exten));
10336             timeout = firstdigittimeout;
10337 
10338          } else if (!strcmp(exten,ast_pickup_ext())) {
10339             /* Scan all channels and see if there are any
10340              * ringing channels that have call groups
10341              * that equal this channels pickup group
10342              */
10343             if (idx == SUB_REAL) {
10344                /* Switch us from Third call to Call Wait */
10345                if (p->subs[SUB_THREEWAY].owner) {
10346                   /* If you make a threeway call and the *8# a call, it should actually
10347                      look like a callwait */
10348                   alloc_sub(p, SUB_CALLWAIT);
10349                   swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
10350                   unalloc_sub(p, SUB_THREEWAY);
10351                }
10352                dahdi_enable_ec(p);
10353                if (ast_pickup_call(chan)) {
10354                   ast_debug(1, "No call pickup possible...\n");
10355                   res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10356                   dahdi_wait_event(p->subs[idx].dfd);
10357                }
10358                ast_hangup(chan);
10359                goto quit;
10360             } else {
10361                ast_log(LOG_WARNING, "Huh?  Got *8# on call not on real\n");
10362                ast_hangup(chan);
10363                goto quit;
10364             }
10365 
10366          } else if (!p->hidecallerid && !strcmp(exten, "*67")) {
10367             ast_verb(3, "Disabling Caller*ID on %s\n", chan->name);
10368             /* Disable Caller*ID if enabled */
10369             p->hidecallerid = 1;
10370             ast_party_number_free(&chan->caller.id.number);
10371             ast_party_number_init(&chan->caller.id.number);
10372             ast_party_name_free(&chan->caller.id.name);
10373             ast_party_name_init(&chan->caller.id.name);
10374             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10375             if (res) {
10376                ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
10377                   chan->name, strerror(errno));
10378             }
10379             len = 0;
10380             memset(exten, 0, sizeof(exten));
10381             timeout = firstdigittimeout;
10382          } else if (p->callreturn && !strcmp(exten, "*69")) {
10383             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10384             break;
10385          } else if (!strcmp(exten, "*78")) {
10386             dahdi_dnd(p, 1);
10387             /* Do not disturb */
10388             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10389             getforward = 0;
10390             memset(exten, 0, sizeof(exten));
10391             len = 0;
10392          } else if (!strcmp(exten, "*79")) {
10393             dahdi_dnd(p, 0);
10394             /* Do not disturb */
10395             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10396             getforward = 0;
10397             memset(exten, 0, sizeof(exten));
10398             len = 0;
10399          } else if (p->cancallforward && !strcmp(exten, "*72")) {
10400             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10401             getforward = 1;
10402             memset(exten, 0, sizeof(exten));
10403             len = 0;
10404          } else if (p->cancallforward && !strcmp(exten, "*73")) {
10405             ast_verb(3, "Cancelling call forwarding on channel %d\n", p->channel);
10406             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10407             memset(p->call_forward, 0, sizeof(p->call_forward));
10408             getforward = 0;
10409             memset(exten, 0, sizeof(exten));
10410             len = 0;
10411          } else if ((p->transfer || p->canpark) && ast_parking_ext_valid(exten, chan, chan->context) &&
10412                   p->subs[SUB_THREEWAY].owner &&
10413                   ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
10414             /* This is a three way call, the main call being a real channel,
10415                and we're parking the first call. */
10416             ast_masq_park_call_exten(ast_bridged_channel(p->subs[SUB_THREEWAY].owner),
10417                chan, exten, chan->context, 0, NULL);
10418             ast_verb(3, "Parking call to '%s'\n", chan->name);
10419             break;
10420          } else if (p->hidecallerid && !strcmp(exten, "*82")) {
10421             ast_verb(3, "Enabling Caller*ID on %s\n", chan->name);
10422             /* Enable Caller*ID if enabled */
10423             p->hidecallerid = 0;
10424             ast_set_callerid(chan, p->cid_num, p->cid_name, NULL);
10425             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10426             if (res) {
10427                ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
10428                   chan->name, strerror(errno));
10429             }
10430             len = 0;
10431             memset(exten, 0, sizeof(exten));
10432             timeout = firstdigittimeout;
10433          } else if (!strcmp(exten, "*0")) {
10434             struct ast_channel *nbridge =
10435                p->subs[SUB_THREEWAY].owner;
10436             struct dahdi_pvt *pbridge = NULL;
10437             /* set up the private struct of the bridged one, if any */
10438             if (nbridge && ast_bridged_channel(nbridge))
10439                pbridge = ast_bridged_channel(nbridge)->tech_pvt;
10440             if (nbridge && pbridge &&
10441                (nbridge->tech == &dahdi_tech) &&
10442                (ast_bridged_channel(nbridge)->tech == &dahdi_tech) &&
10443                ISTRUNK(pbridge)) {
10444                int func = DAHDI_FLASH;
10445                /* Clear out the dial buffer */
10446                p->dop.dialstr[0] = '\0';
10447                /* flash hookswitch */
10448                if ((ioctl(pbridge->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
10449                   ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
10450                      nbridge->name, strerror(errno));
10451                }
10452                swap_subs(p, SUB_REAL, SUB_THREEWAY);
10453                unalloc_sub(p, SUB_THREEWAY);
10454                p->owner = p->subs[SUB_REAL].owner;
10455                if (ast_bridged_channel(p->subs[SUB_REAL].owner))
10456                   ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
10457                ast_hangup(chan);
10458                goto quit;
10459             } else {
10460                tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10461                dahdi_wait_event(p->subs[idx].dfd);
10462                tone_zone_play_tone(p->subs[idx].dfd, -1);
10463                swap_subs(p, SUB_REAL, SUB_THREEWAY);
10464                unalloc_sub(p, SUB_THREEWAY);
10465                p->owner = p->subs[SUB_REAL].owner;
10466                ast_hangup(chan);
10467                goto quit;
10468             }
10469          } else if (!ast_canmatch_extension(chan, chan->context, exten, 1,
10470             S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))
10471             && !canmatch_featurecode(exten)) {
10472             ast_debug(1, "Can't match %s from '%s' in context %s\n", exten,
10473                S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, "<Unknown Caller>"),
10474                chan->context);
10475             break;
10476          }
10477          if (!timeout)
10478             timeout = gendigittimeout;
10479          if (len && !ast_ignore_pattern(chan->context, exten))
10480             tone_zone_play_tone(p->subs[idx].dfd, -1);
10481       }
10482       break;
10483    case SIG_FXSLS:
10484    case SIG_FXSGS:
10485    case SIG_FXSKS:
10486       /* check for SMDI messages */
10487       if (p->use_smdi && p->smdi_iface) {
10488          smdi_msg = ast_smdi_md_message_wait(p->smdi_iface, SMDI_MD_WAIT_TIMEOUT);
10489 
10490          if (smdi_msg != NULL) {
10491             ast_copy_string(chan->exten, smdi_msg->fwd_st, sizeof(chan->exten));
10492 
10493             if (smdi_msg->type == 'B')
10494                pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "b");
10495             else if (smdi_msg->type == 'N')
10496                pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "u");
10497 
10498             ast_debug(1, "Received SMDI message on %s\n", chan->name);
10499          } else {
10500             ast_log(LOG_WARNING, "SMDI enabled but no SMDI message present\n");
10501          }
10502       }
10503 
10504       if (p->use_callerid && (p->cid_signalling == CID_SIG_SMDI && smdi_msg)) {
10505          number = smdi_msg->calling_st;
10506 
10507       /* If we want caller id, we're in a prering state due to a polarity reversal
10508        * and we're set to use a polarity reversal to trigger the start of caller id,
10509        * grab the caller id and wait for ringing to start... */
10510       } else if (p->use_callerid && (chan->_state == AST_STATE_PRERING &&
10511                    (p->cid_start == CID_START_POLARITY || p->cid_start == CID_START_POLARITY_IN || p->cid_start == CID_START_DTMF_NOALERT))) {
10512          /* If set to use DTMF CID signalling, listen for DTMF */
10513          if (p->cid_signalling == CID_SIG_DTMF) {
10514             int k = 0;
10515             cs = NULL;
10516             ast_debug(1, "Receiving DTMF cid on channel %s\n", chan->name);
10517             dahdi_setlinear(p->subs[idx].dfd, 0);
10518             /*
10519              * We are the only party interested in the Rx stream since
10520              * we have not answered yet.  We don't need or even want DTMF
10521              * emulation.  The DTMF digits can come so fast that emulation
10522              * can drop some of them.
10523              */
10524             ast_set_flag(chan, AST_FLAG_END_DTMF_ONLY);
10525             res = 4000;/* This is a typical OFF time between rings. */
10526             for (;;) {
10527                struct ast_frame *f;
10528                res = ast_waitfor(chan, res);
10529                if (res <= 0) {
10530                   /*
10531                    * We do not need to restore the dahdi_setlinear()
10532                    * or AST_FLAG_END_DTMF_ONLY flag settings since we
10533                    * are hanging up the channel.
10534                    */
10535                   ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
10536                      "Exiting simple switch\n");
10537                   ast_hangup(chan);
10538                   goto quit;
10539                }
10540                f = ast_read(chan);
10541                if (!f)
10542                   break;
10543                if (f->frametype == AST_FRAME_DTMF) {
10544                   if (k < ARRAY_LEN(dtmfbuf) - 1) {
10545                      dtmfbuf[k++] = f->subclass.integer;
10546                   }
10547                   ast_debug(1, "CID got digit '%c'\n", f->subclass.integer);
10548                   res = 4000;/* This is a typical OFF time between rings. */
10549                }
10550                ast_frfree(f);
10551                if (chan->_state == AST_STATE_RING ||
10552                   chan->_state == AST_STATE_RINGING)
10553                   break; /* Got ring */
10554             }
10555             ast_clear_flag(chan, AST_FLAG_END_DTMF_ONLY);
10556             dtmfbuf[k] = '\0';
10557             dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10558             /* Got cid and ring. */
10559             ast_debug(1, "CID got string '%s'\n", dtmfbuf);
10560             callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
10561             ast_debug(1, "CID is '%s', flags %d\n", dtmfcid, flags);
10562             /* If first byte is NULL, we have no cid */
10563             if (!ast_strlen_zero(dtmfcid))
10564                number = dtmfcid;
10565             else
10566                number = NULL;
10567          /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */
10568          } else if ((p->cid_signalling == CID_SIG_V23) || (p->cid_signalling == CID_SIG_V23_JP)) {
10569             cs = callerid_new(p->cid_signalling);
10570             if (cs) {
10571                samples = 0;
10572 #if 1
10573                bump_gains(p);
10574 #endif
10575                /* Take out of linear mode for Caller*ID processing */
10576                dahdi_setlinear(p->subs[idx].dfd, 0);
10577 
10578                /* First we wait and listen for the Caller*ID */
10579                for (;;) {
10580                   i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10581                   if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10582                      ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10583                      callerid_free(cs);
10584                      ast_hangup(chan);
10585                      goto quit;
10586                   }
10587                   if (i & DAHDI_IOMUX_SIGEVENT) {
10588                      res = dahdi_get_event(p->subs[idx].dfd);
10589                      ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10590                      if (res == DAHDI_EVENT_NOALARM) {
10591                         p->inalarm = 0;
10592                      }
10593 
10594                      if (p->cid_signalling == CID_SIG_V23_JP) {
10595                         if (res == DAHDI_EVENT_RINGBEGIN) {
10596                            res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
10597                            usleep(1);
10598                         }
10599                      } else {
10600                         res = 0;
10601                         break;
10602                      }
10603                   } else if (i & DAHDI_IOMUX_READ) {
10604                      res = read(p->subs[idx].dfd, buf, sizeof(buf));
10605                      if (res < 0) {
10606                         if (errno != ELAST) {
10607                            ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10608                            callerid_free(cs);
10609                            ast_hangup(chan);
10610                            goto quit;
10611                         }
10612                         break;
10613                      }
10614                      samples += res;
10615 
10616                      if (p->cid_signalling == CID_SIG_V23_JP) {
10617                         res = callerid_feed_jp(cs, buf, res, AST_LAW(p));
10618                      } else {
10619                         res = callerid_feed(cs, buf, res, AST_LAW(p));
10620                      }
10621                      if (res < 0) {
10622                         /*
10623                          * The previous diagnostic message output likely
10624                          * explains why it failed.
10625                          */
10626                         ast_log(LOG_WARNING,
10627                            "Failed to decode CallerID on channel '%s'\n",
10628                            chan->name);
10629                         break;
10630                      } else if (res)
10631                         break;
10632                      else if (samples > (8000 * 10))
10633                         break;
10634                   }
10635                }
10636                if (res == 1) {
10637                   callerid_get(cs, &name, &number, &flags);
10638                   ast_log(LOG_NOTICE, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
10639                }
10640 
10641                if (p->cid_signalling == CID_SIG_V23_JP) {
10642                   res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
10643                   usleep(1);
10644                }
10645 
10646                /* Finished with Caller*ID, now wait for a ring to make sure there really is a call coming */
10647                res = 4000;/* This is a typical OFF time between rings. */
10648                for (;;) {
10649                   struct ast_frame *f;
10650                   res = ast_waitfor(chan, res);
10651                   if (res <= 0) {
10652                      ast_log(LOG_WARNING, "CID timed out waiting for ring. "
10653                         "Exiting simple switch\n");
10654                      ast_hangup(chan);
10655                      goto quit;
10656                   }
10657                   if (!(f = ast_read(chan))) {
10658                      ast_log(LOG_WARNING, "Hangup received waiting for ring. Exiting simple switch\n");
10659                      ast_hangup(chan);
10660                      goto quit;
10661                   }
10662                   ast_frfree(f);
10663                   if (chan->_state == AST_STATE_RING ||
10664                      chan->_state == AST_STATE_RINGING)
10665                      break; /* Got ring */
10666                }
10667 
10668                /* We must have a ring by now, so, if configured, lets try to listen for
10669                 * distinctive ringing */
10670                if (p->usedistinctiveringdetection) {
10671                   len = 0;
10672                   distMatches = 0;
10673                   /* Clear the current ring data array so we don't have old data in it. */
10674                   for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
10675                      curRingData[receivedRingT] = 0;
10676                   receivedRingT = 0;
10677                   counter = 0;
10678                   counter1 = 0;
10679                   /* Check to see if context is what it should be, if not set to be. */
10680                   if (strcmp(p->context,p->defcontext) != 0) {
10681                      ast_copy_string(p->context, p->defcontext, sizeof(p->context));
10682                      ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
10683                   }
10684 
10685                   for (;;) {
10686                      i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10687                      if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10688                         ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10689                         callerid_free(cs);
10690                         ast_hangup(chan);
10691                         goto quit;
10692                      }
10693                      if (i & DAHDI_IOMUX_SIGEVENT) {
10694                         res = dahdi_get_event(p->subs[idx].dfd);
10695                         ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10696                         if (res == DAHDI_EVENT_NOALARM) {
10697                            p->inalarm = 0;
10698                         }
10699                         res = 0;
10700                         /* Let us detect distinctive ring */
10701 
10702                         curRingData[receivedRingT] = p->ringt;
10703 
10704                         if (p->ringt < p->ringt_base/2)
10705                            break;
10706                         /* Increment the ringT counter so we can match it against
10707                            values in chan_dahdi.conf for distinctive ring */
10708                         if (++receivedRingT == ARRAY_LEN(curRingData))
10709                            break;
10710                      } else if (i & DAHDI_IOMUX_READ) {
10711                         res = read(p->subs[idx].dfd, buf, sizeof(buf));
10712                         if (res < 0) {
10713                            if (errno != ELAST) {
10714                               ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10715                               callerid_free(cs);
10716                               ast_hangup(chan);
10717                               goto quit;
10718                            }
10719                            break;
10720                         }
10721                         if (p->ringt > 0) {
10722                            if (!(--p->ringt)) {
10723                               res = -1;
10724                               break;
10725                            }
10726                         }
10727                      }
10728                   }
10729                      /* this only shows up if you have n of the dring patterns filled in */
10730                   ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
10731                   for (counter = 0; counter < 3; counter++) {
10732                      /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this
10733                      channel */
10734                      distMatches = 0;
10735                      for (counter1 = 0; counter1 < 3; counter1++) {
10736                         ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
10737                         if (p->drings.ringnum[counter].ring[counter1] == -1) {
10738                            ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
10739                            curRingData[counter1]);
10740                            distMatches++;
10741                         } else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
10742                               curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
10743                            ast_verb(3, "Ring pattern matched in range: %d to %d\n",
10744                            (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
10745                            (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
10746                            distMatches++;
10747                         }
10748                      }
10749 
10750                      if (distMatches == 3) {
10751                         /* The ring matches, set the context to whatever is for distinctive ring.. */
10752                         ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context));
10753                         ast_copy_string(chan->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(chan->context));
10754                         ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
10755                         break;
10756                      }
10757                   }
10758                }
10759                /* Restore linear mode (if appropriate) for Caller*ID processing */
10760                dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10761 #if 1
10762                restore_gains(p);
10763 #endif
10764             } else
10765                ast_log(LOG_WARNING, "Unable to get caller ID space\n");
10766          } else {
10767             ast_log(LOG_WARNING, "Channel %s in prering "
10768                "state, but I have nothing to do. "
10769                "Terminating simple switch, should be "
10770                "restarted by the actual ring.\n",
10771                chan->name);
10772             ast_hangup(chan);
10773             goto quit;
10774          }
10775       } else if (p->use_callerid && p->cid_start == CID_START_RING) {
10776          if (p->cid_signalling == CID_SIG_DTMF) {
10777             int k = 0;
10778             cs = NULL;
10779             dahdi_setlinear(p->subs[idx].dfd, 0);
10780             res = 2000;
10781             for (;;) {
10782                struct ast_frame *f;
10783                res = ast_waitfor(chan, res);
10784                if (res <= 0) {
10785                   ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
10786                      "Exiting simple switch\n");
10787                   ast_hangup(chan);
10788                   goto quit;
10789                }
10790                f = ast_read(chan);
10791                if (!f) {
10792                   /* Hangup received waiting for DTMFCID. Exiting simple switch. */
10793                   ast_hangup(chan);
10794                   goto quit;
10795                }
10796                if (f->frametype == AST_FRAME_DTMF) {
10797                   dtmfbuf[k++] = f->subclass.integer;
10798                   ast_log(LOG_DEBUG, "CID got digit '%c'\n", f->subclass.integer);
10799                   res = 2000;
10800                }
10801                ast_frfree(f);
10802 
10803                if (p->ringt_base == p->ringt)
10804                   break;
10805             }
10806             dtmfbuf[k] = '\0';
10807             dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10808             /* Got cid and ring. */
10809             callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
10810             ast_log(LOG_DEBUG, "CID is '%s', flags %d\n",
10811                dtmfcid, flags);
10812             /* If first byte is NULL, we have no cid */
10813             if (!ast_strlen_zero(dtmfcid))
10814                number = dtmfcid;
10815             else
10816                number = NULL;
10817             /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */
10818          } else {
10819             /* FSK Bell202 callerID */
10820             cs = callerid_new(p->cid_signalling);
10821             if (cs) {
10822 #if 1
10823                bump_gains(p);
10824 #endif
10825                samples = 0;
10826                len = 0;
10827                distMatches = 0;
10828                /* Clear the current ring data array so we don't have old data in it. */
10829                for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
10830                   curRingData[receivedRingT] = 0;
10831                receivedRingT = 0;
10832                counter = 0;
10833                counter1 = 0;
10834                /* Check to see if context is what it should be, if not set to be. */
10835                if (strcmp(p->context,p->defcontext) != 0) {
10836                   ast_copy_string(p->context, p->defcontext, sizeof(p->context));
10837                   ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
10838                }
10839 
10840                /* Take out of linear mode for Caller*ID processing */
10841                dahdi_setlinear(p->subs[idx].dfd, 0);
10842                for (;;) {
10843                   i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10844                   if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10845                      ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10846                      callerid_free(cs);
10847                      ast_hangup(chan);
10848                      goto quit;
10849                   }
10850                   if (i & DAHDI_IOMUX_SIGEVENT) {
10851                      res = dahdi_get_event(p->subs[idx].dfd);
10852                      ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10853                      if (res == DAHDI_EVENT_NOALARM) {
10854                         p->inalarm = 0;
10855                      }
10856                      /* If we get a PR event, they hung up while processing calerid */
10857                      if ( res == DAHDI_EVENT_POLARITY && p->hanguponpolarityswitch && p->polarity == POLARITY_REV) {
10858                         ast_log(LOG_DEBUG, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p->channel);
10859                         p->polarity = POLARITY_IDLE;
10860                         callerid_free(cs);
10861                         ast_hangup(chan);
10862                         goto quit;
10863                      }
10864                      res = 0;
10865                      /* Let us detect callerid when the telco uses distinctive ring */
10866 
10867                      curRingData[receivedRingT] = p->ringt;
10868 
10869                      if (p->ringt < p->ringt_base/2)
10870                         break;
10871                      /* Increment the ringT counter so we can match it against
10872                         values in chan_dahdi.conf for distinctive ring */
10873                      if (++receivedRingT == ARRAY_LEN(curRingData))
10874                         break;
10875                   } else if (i & DAHDI_IOMUX_READ) {
10876                      res = read(p->subs[idx].dfd, buf, sizeof(buf));
10877                      if (res < 0) {
10878                         if (errno != ELAST) {
10879                            ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10880                            callerid_free(cs);
10881                            ast_hangup(chan);
10882                            goto quit;
10883                         }
10884                         break;
10885                      }
10886                      if (p->ringt > 0) {
10887                         if (!(--p->ringt)) {
10888                            res = -1;
10889                            break;
10890                         }
10891                      }
10892                      samples += res;
10893                      res = callerid_feed(cs, buf, res, AST_LAW(p));
10894                      if (res < 0) {
10895                         /*
10896                          * The previous diagnostic message output likely
10897                          * explains why it failed.
10898                          */
10899                         ast_log(LOG_WARNING,
10900                            "Failed to decode CallerID on channel '%s'\n",
10901                            chan->name);
10902                         break;
10903                      } else if (res)
10904                         break;
10905                      else if (samples > (8000 * 10))
10906                         break;
10907                   }
10908                }
10909                if (res == 1) {
10910                   callerid_get(cs, &name, &number, &flags);
10911                   ast_debug(1, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
10912                }
10913                if (distinctiveringaftercid == 1) {
10914                   /* Clear the current ring data array so we don't have old data in it. */
10915                   for (receivedRingT = 0; receivedRingT < 3; receivedRingT++) {
10916                      curRingData[receivedRingT] = 0;
10917                   }
10918                   receivedRingT = 0;
10919                   ast_verb(3, "Detecting post-CID distinctive ring\n");
10920                   for (;;) {
10921                      i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10922                      if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10923                         ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10924                         callerid_free(cs);
10925                         ast_hangup(chan);
10926                         goto quit;
10927                      }
10928                      if (i & DAHDI_IOMUX_SIGEVENT) {
10929                         res = dahdi_get_event(p->subs[idx].dfd);
10930                         ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10931                         if (res == DAHDI_EVENT_NOALARM) {
10932                            p->inalarm = 0;
10933                         }
10934                         res = 0;
10935                         /* Let us detect callerid when the telco uses distinctive ring */
10936 
10937                         curRingData[receivedRingT] = p->ringt;
10938 
10939                         if (p->ringt < p->ringt_base/2)
10940                            break;
10941                         /* Increment the ringT counter so we can match it against
10942                            values in chan_dahdi.conf for distinctive ring */
10943                         if (++receivedRingT == ARRAY_LEN(curRingData))
10944                            break;
10945                      } else if (i & DAHDI_IOMUX_READ) {
10946                         res = read(p->subs[idx].dfd, buf, sizeof(buf));
10947                         if (res < 0) {
10948                            if (errno != ELAST) {
10949                               ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10950                               callerid_free(cs);
10951                               ast_hangup(chan);
10952                               goto quit;
10953                            }
10954                            break;
10955                         }
10956                         if (p->ringt > 0) {
10957                            if (!(--p->ringt)) {
10958                               res = -1;
10959                               break;
10960                            }
10961                         }
10962                      }
10963                   }
10964                }
10965                if (p->usedistinctiveringdetection) {
10966                   /* this only shows up if you have n of the dring patterns filled in */
10967                   ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
10968 
10969                   for (counter = 0; counter < 3; counter++) {
10970                      /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this
10971                      channel */
10972                      /* this only shows up if you have n of the dring patterns filled in */
10973                      ast_verb(3, "Checking %d,%d,%d\n",
10974                            p->drings.ringnum[counter].ring[0],
10975                            p->drings.ringnum[counter].ring[1],
10976                            p->drings.ringnum[counter].ring[2]);
10977                      distMatches = 0;
10978                      for (counter1 = 0; counter1 < 3; counter1++) {
10979                         ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
10980                         if (p->drings.ringnum[counter].ring[counter1] == -1) {
10981                            ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
10982                            curRingData[counter1]);
10983                            distMatches++;
10984                         }
10985                         else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
10986                            curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
10987                            ast_verb(3, "Ring pattern matched in range: %d to %d\n",
10988                            (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
10989                            (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
10990                            distMatches++;
10991                         }
10992                      }
10993                      if (distMatches == 3) {
10994                         /* The ring matches, set the context to whatever is for distinctive ring.. */
10995                         ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context));
10996                         ast_copy_string(chan->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(chan->context));
10997                         ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
10998                         break;
10999                      }
11000                   }
11001                }
11002                /* Restore linear mode (if appropriate) for Caller*ID processing */
11003                dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
11004 #if 1
11005                restore_gains(p);
11006 #endif
11007                if (res < 0) {
11008                   ast_log(LOG_WARNING, "CallerID returned with error on channel '%s'\n", chan->name);
11009                }
11010             } else
11011                ast_log(LOG_WARNING, "Unable to get caller ID space\n");
11012          }
11013       } else
11014          cs = NULL;
11015 
11016       if (number)
11017          ast_shrink_phone_number(number);
11018       ast_set_callerid(chan, number, name, number);
11019 
11020       if (smdi_msg)
11021          ASTOBJ_UNREF(smdi_msg, ast_smdi_md_message_destroy);
11022 
11023       if (cs)
11024          callerid_free(cs);
11025 
11026       my_handle_notify_message(chan, p, flags, -1);
11027 
11028       ast_setstate(chan, AST_STATE_RING);
11029       chan->rings = 1;
11030       p->ringt = p->ringt_base;
11031       res = ast_pbx_run(chan);
11032       if (res) {
11033          ast_hangup(chan);
11034          ast_log(LOG_WARNING, "PBX exited non-zero\n");
11035       }
11036       goto quit;
11037    default:
11038       ast_log(LOG_WARNING, "Don't know how to handle simple switch with signalling %s on channel %d\n", sig2str(p->sig), p->channel);
11039       res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
11040       if (res < 0)
11041             ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
11042    }
11043    res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
11044    if (res < 0)
11045          ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
11046    ast_hangup(chan);
11047 quit:
11048    ast_mutex_lock(&ss_thread_lock);
11049    ss_thread_count--;
11050    ast_cond_signal(&ss_thread_complete);
11051    ast_mutex_unlock(&ss_thread_lock);
11052    return NULL;
11053 }
11054 
11055 struct mwi_thread_data {
11056    struct dahdi_pvt *pvt;
11057    unsigned char buf[READ_SIZE];
11058    size_t len;
11059 };
11060 
11061 static int calc_energy(const unsigned char *buf, int len, format_t law)
11062 {
11063    int x;
11064    int sum = 0;
11065 
11066    if (!len)
11067       return 0;
11068 
11069    for (x = 0; x < len; x++)
11070       sum += abs(law == AST_FORMAT_ULAW ? AST_MULAW(buf[x]) : AST_ALAW(buf[x]));
11071 
11072    return sum / len;
11073 }
11074 
11075 static void *mwi_thread(void *data)
11076 {
11077    struct mwi_thread_data *mtd = data;
11078    struct callerid_state *cs;
11079    pthread_t threadid;
11080    int samples = 0;
11081    char *name, *number;
11082    int flags;
11083    int i, res;
11084    unsigned int spill_done = 0;
11085    int spill_result = -1;
11086 
11087    if (!(cs = callerid_new(mtd->pvt->cid_signalling))) {
11088       goto quit_no_clean;
11089    }
11090 
11091    callerid_feed(cs, mtd->buf, mtd->len, AST_LAW(mtd->pvt));
11092 
11093    bump_gains(mtd->pvt);
11094 
11095    for (;;) {
11096       i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
11097       if ((res = ioctl(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_IOMUX, &i))) {
11098          ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
11099          goto quit;
11100       }
11101 
11102       if (i & DAHDI_IOMUX_SIGEVENT) {
11103          struct ast_channel *chan;
11104 
11105          /* If we get an event, screen out events that we do not act on.
11106           * Otherwise, cancel and go to the simple switch to let it deal with it.
11107           */
11108          res = dahdi_get_event(mtd->pvt->subs[SUB_REAL].dfd);
11109 
11110          switch (res) {
11111          case DAHDI_EVENT_NEONMWI_ACTIVE:
11112          case DAHDI_EVENT_NEONMWI_INACTIVE:
11113          case DAHDI_EVENT_NONE:
11114          case DAHDI_EVENT_BITSCHANGED:
11115             break;
11116          case DAHDI_EVENT_NOALARM:
11117             if (analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) {
11118                struct analog_pvt *analog_p = mtd->pvt->sig_pvt;
11119 
11120                analog_p->inalarm = 0;
11121             }
11122             mtd->pvt->inalarm = 0;
11123             handle_clear_alarms(mtd->pvt);
11124             break;
11125          case DAHDI_EVENT_ALARM:
11126             if (analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) {
11127                struct analog_pvt *analog_p = mtd->pvt->sig_pvt;
11128 
11129                analog_p->inalarm = 1;
11130             }
11131             mtd->pvt->inalarm = 1;
11132             res = get_alarms(mtd->pvt);
11133             handle_alarms(mtd->pvt, res);
11134             break; /* What to do on channel alarm ???? -- fall thru intentionally?? */
11135          default:
11136             ast_log(LOG_NOTICE, "Got event %d (%s)...  Passing along to analog_ss_thread\n", res, event2str(res));
11137             callerid_free(cs);
11138 
11139             restore_gains(mtd->pvt);
11140             mtd->pvt->ringt = mtd->pvt->ringt_base;
11141 
11142             if ((chan = dahdi_new(mtd->pvt, AST_STATE_RING, 0, SUB_REAL, 0, NULL))) {
11143                int result;
11144 
11145                if (analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) {
11146                   result = analog_ss_thread_start(mtd->pvt->sig_pvt, chan);
11147                } else {
11148                   result = ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan);
11149                }
11150                if (result) {
11151                   ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", mtd->pvt->channel);
11152                   res = tone_zone_play_tone(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11153                   if (res < 0)
11154                      ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", mtd->pvt->channel);
11155                   ast_hangup(chan);
11156                }
11157             } else {
11158                ast_log(LOG_WARNING, "Could not create channel to handle call\n");
11159             }
11160             goto quit_no_clean;
11161          }
11162       } else if (i & DAHDI_IOMUX_READ) {
11163          if ((res = read(mtd->pvt->subs[SUB_REAL].dfd, mtd->buf, sizeof(mtd->buf))) < 0) {
11164             if (errno != ELAST) {
11165                ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
11166                goto quit;
11167             }
11168             break;
11169          }
11170          samples += res;
11171          if (!spill_done) {
11172             if ((spill_result = callerid_feed(cs, mtd->buf, res, AST_LAW(mtd->pvt))) < 0) {
11173                /*
11174                 * The previous diagnostic message output likely
11175                 * explains why it failed.
11176                 */
11177                ast_log(LOG_WARNING, "Failed to decode CallerID\n");
11178                break;
11179             } else if (spill_result) {
11180                spill_done = 1;
11181             }
11182          } else {
11183             /* keep reading data until the energy level drops below the threshold
11184                so we don't get another 'trigger' on the remaining carrier signal
11185             */
11186             if (calc_energy(mtd->buf, res, AST_LAW(mtd->pvt)) <= mwilevel)
11187                break;
11188          }
11189          if (samples > (8000 * 4)) /*Termination case - time to give up*/
11190             break;
11191       }
11192    }
11193 
11194    if (spill_result == 1) {
11195       callerid_get(cs, &name, &number, &flags);
11196       if (flags & CID_MSGWAITING) {
11197          ast_log(LOG_NOTICE, "mwi: Have Messages on channel %d\n", mtd->pvt->channel);
11198          notify_message(mtd->pvt->mailbox, 1);
11199       } else if (flags & CID_NOMSGWAITING) {
11200          ast_log(LOG_NOTICE, "mwi: No Messages on channel %d\n", mtd->pvt->channel);
11201          notify_message(mtd->pvt->mailbox, 0);
11202       } else {
11203          ast_log(LOG_NOTICE, "mwi: Status unknown on channel %d\n", mtd->pvt->channel);
11204       }
11205    }
11206 
11207 
11208 quit:
11209    callerid_free(cs);
11210 
11211    restore_gains(mtd->pvt);
11212 
11213 quit_no_clean:
11214    mtd->pvt->mwimonitoractive = 0;
11215    ast_free(mtd);
11216 
11217    return NULL;
11218 }
11219 
11220 /*
11221 * The following three functions (mwi_send_init, mwi_send_process_buffer,
11222 * mwi_send_process_event) work with the do_monitor thread to generate mwi spills
11223 * that are sent out via FXS port on voicemail state change.  The execution of
11224 * the mwi send is state driven and can either generate a ring pulse prior to
11225 * sending the fsk spill or simply send an fsk spill.
11226 */
11227 static int mwi_send_init(struct dahdi_pvt * pvt)
11228 {
11229    int x;
11230 
11231 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11232    /* Determine how this spill is to be sent */
11233    if (pvt->mwisend_rpas) {
11234       pvt->mwisend_data.mwisend_current = MWI_SEND_SA;
11235       pvt->mwisendactive = 1;
11236    } else if (pvt->mwisend_fsk) {
11237       pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
11238       pvt->mwisendactive = 1;
11239    } else {
11240       pvt->mwisendactive = 0;
11241       return 0;
11242    }
11243 #else
11244    if (mwisend_rpas) {
11245       pvt->mwisend_data.mwisend_current = MWI_SEND_SA;
11246    } else {
11247       pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
11248    }
11249    pvt->mwisendactive = 1;
11250 #endif
11251 
11252    if (pvt->cidspill) {
11253       ast_log(LOG_WARNING, "cidspill already exists when trying to send FSK MWI\n");
11254       ast_free(pvt->cidspill);
11255       pvt->cidspill = NULL;
11256       pvt->cidpos = 0;
11257       pvt->cidlen = 0;
11258    }
11259    pvt->cidspill = ast_calloc(1, MAX_CALLERID_SIZE);
11260    if (!pvt->cidspill) {
11261       pvt->mwisendactive = 0;
11262       return -1;
11263    }
11264    x = DAHDI_FLUSH_BOTH;
11265    ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
11266    x = 3000;
11267    ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_ONHOOKTRANSFER, &x);
11268 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11269    if (pvt->mwisend_fsk) {
11270 #endif
11271       pvt->cidlen = ast_callerid_vmwi_generate(pvt->cidspill, has_voicemail(pvt), CID_MWI_TYPE_MDMF_FULL,
11272                       AST_LAW(pvt), pvt->cid_name, pvt->cid_num, 0);
11273       pvt->cidpos = 0;
11274 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11275    }
11276 #endif
11277    return 0;
11278 }
11279 
11280 static int mwi_send_process_buffer(struct dahdi_pvt * pvt, int num_read)
11281 {
11282    struct timeval    now;
11283    int         res;
11284 
11285    /* sanity check to catch if this had been interrupted previously
11286    *  i.e. state says there is more to do but there is no spill allocated
11287    */
11288    if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current && !pvt->cidspill) {
11289       pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11290    } else if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current) {
11291       /* Normal processing -- Perform mwi send action */
11292       switch ( pvt->mwisend_data.mwisend_current) {
11293       case MWI_SEND_SA:
11294          /* Send the Ring Pulse Signal Alert */
11295          res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &AS_RP_cadence);
11296          if (res) {
11297             ast_log(LOG_WARNING, "Unable to set RP-AS ring cadence: %s\n", strerror(errno));
11298             goto quit;
11299          }
11300          res = dahdi_set_hook(pvt->subs[SUB_REAL].dfd, DAHDI_RING);
11301          pvt->mwisend_data.mwisend_current = MWI_SEND_SA_WAIT;
11302          break;
11303       case MWI_SEND_SA_WAIT:  /* do nothing until I get RINGEROFF event */
11304          break;
11305       case MWI_SEND_PAUSE:  /* Wait between alert and spill - min of 500 mS*/
11306 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11307          if (pvt->mwisend_fsk) {
11308 #endif
11309             gettimeofday(&now, NULL);
11310             if ((int)(now.tv_sec - pvt->mwisend_data.pause.tv_sec) * 1000000 + (int)now.tv_usec - (int)pvt->mwisend_data.pause.tv_usec > 500000) {
11311                pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
11312             }
11313 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11314          } else { /* support for mwisendtype=nofsk */
11315             pvt->mwisend_data.mwisend_current = MWI_SEND_CLEANUP;
11316          }
11317 #endif
11318          break;
11319       case MWI_SEND_SPILL:
11320          /* We read some number of bytes.  Write an equal amount of data */
11321          if(0 < num_read) {
11322             if (num_read > pvt->cidlen - pvt->cidpos)
11323                num_read = pvt->cidlen - pvt->cidpos;
11324             res = write(pvt->subs[SUB_REAL].dfd, pvt->cidspill + pvt->cidpos, num_read);
11325             if (res > 0) {
11326                pvt->cidpos += res;
11327                if (pvt->cidpos >= pvt->cidlen) {
11328                   pvt->mwisend_data.mwisend_current = MWI_SEND_CLEANUP;
11329                }
11330             } else {
11331                ast_log(LOG_WARNING, "MWI FSK Send Write failed: %s\n", strerror(errno));
11332                goto quit;
11333             }
11334          }
11335          break;
11336       case MWI_SEND_CLEANUP:
11337          /* For now, do nothing */
11338          pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11339          break;
11340       default:
11341          /* Should not get here, punt*/
11342          goto quit;
11343       }
11344    }
11345 
11346    if (MWI_SEND_DONE == pvt->mwisend_data.mwisend_current) {
11347       if (pvt->cidspill) {
11348          ast_free(pvt->cidspill);
11349          pvt->cidspill = NULL;
11350          pvt->cidpos = 0;
11351          pvt->cidlen = 0;
11352       }
11353       pvt->mwisendactive = 0;
11354    }
11355    return 0;
11356 quit:
11357    if (pvt->cidspill) {
11358       ast_free(pvt->cidspill);
11359       pvt->cidspill = NULL;
11360       pvt->cidpos = 0;
11361       pvt->cidlen = 0;
11362    }
11363    pvt->mwisendactive = 0;
11364    return -1;
11365 }
11366 
11367 static int mwi_send_process_event(struct dahdi_pvt * pvt, int event)
11368 {
11369    int handled = 0;
11370 
11371    if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current) {
11372       switch (event) {
11373       case DAHDI_EVENT_RINGEROFF:
11374          if(pvt->mwisend_data.mwisend_current == MWI_SEND_SA_WAIT) {
11375             handled = 1;
11376 
11377             if (dahdi_set_hook(pvt->subs[SUB_REAL].dfd, DAHDI_RINGOFF) ) {
11378                ast_log(LOG_WARNING, "Unable to finish RP-AS: %s mwi send aborted\n", strerror(errno));
11379                ast_free(pvt->cidspill);
11380                pvt->cidspill = NULL;
11381                pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11382                pvt->mwisendactive = 0;
11383             } else {
11384                pvt->mwisend_data.mwisend_current = MWI_SEND_PAUSE;
11385                gettimeofday(&pvt->mwisend_data.pause, NULL);
11386             }
11387          }
11388          break;
11389       /* Going off hook, I need to punt this spill */
11390       case DAHDI_EVENT_RINGOFFHOOK:
11391          if (pvt->cidspill) {
11392             ast_free(pvt->cidspill);
11393             pvt->cidspill = NULL;
11394             pvt->cidpos = 0;
11395             pvt->cidlen = 0;
11396          }
11397          pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11398          pvt->mwisendactive = 0;
11399          break;
11400       case DAHDI_EVENT_RINGERON:
11401       case DAHDI_EVENT_HOOKCOMPLETE:
11402          break;
11403       default:
11404          break;
11405       }
11406    }
11407    return handled;
11408 }
11409 
11410 /* destroy a DAHDI channel, identified by its number */
11411 static int dahdi_destroy_channel_bynum(int channel)
11412 {
11413    struct dahdi_pvt *cur;
11414 
11415    ast_mutex_lock(&iflock);
11416    for (cur = iflist; cur; cur = cur->next) {
11417       if (cur->channel == channel) {
11418          int x = DAHDI_FLASH;
11419 
11420          /* important to create an event for dahdi_wait_event to register so that all analog_ss_threads terminate */
11421          ioctl(cur->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
11422 
11423          destroy_channel(cur, 1);
11424          ast_mutex_unlock(&iflock);
11425          ast_module_unref(ast_module_info->self);
11426          return RESULT_SUCCESS;
11427       }
11428    }
11429    ast_mutex_unlock(&iflock);
11430    return RESULT_FAILURE;
11431 }
11432 
11433 static struct dahdi_pvt *handle_init_event(struct dahdi_pvt *i, int event)
11434 {
11435    int res;
11436    pthread_t threadid;
11437    struct ast_channel *chan;
11438 
11439    /* Handle an event on a given channel for the monitor thread. */
11440 
11441    switch (event) {
11442    case DAHDI_EVENT_NONE:
11443    case DAHDI_EVENT_BITSCHANGED:
11444       break;
11445    case DAHDI_EVENT_WINKFLASH:
11446    case DAHDI_EVENT_RINGOFFHOOK:
11447       if (i->inalarm) break;
11448       if (i->radio) break;
11449       /* Got a ring/answer.  What kind of channel are we? */
11450       switch (i->sig) {
11451       case SIG_FXOLS:
11452       case SIG_FXOGS:
11453       case SIG_FXOKS:
11454          res = dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
11455          if (res && (errno == EBUSY))
11456             break;
11457 
11458          /* Cancel VMWI spill */
11459          ast_free(i->cidspill);
11460          i->cidspill = NULL;
11461          restore_conference(i);
11462 
11463          if (i->immediate) {
11464             dahdi_enable_ec(i);
11465             /* The channel is immediately up.  Start right away */
11466             res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
11467             chan = dahdi_new(i, AST_STATE_RING, 1, SUB_REAL, 0, NULL);
11468             if (!chan) {
11469                ast_log(LOG_WARNING, "Unable to start PBX on channel %d\n", i->channel);
11470                res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11471                if (res < 0)
11472                   ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11473             }
11474          } else {
11475             /* Check for callerid, digits, etc */
11476             chan = dahdi_new(i, AST_STATE_RESERVED, 0, SUB_REAL, 0, NULL);
11477             if (chan) {
11478                if (has_voicemail(i))
11479                   res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
11480                else
11481                   res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
11482                if (res < 0)
11483                   ast_log(LOG_WARNING, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i->channel);
11484                if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
11485                   ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11486                   res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11487                   if (res < 0)
11488                      ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11489                   ast_hangup(chan);
11490                }
11491             } else
11492                ast_log(LOG_WARNING, "Unable to create channel\n");
11493          }
11494          break;
11495       case SIG_FXSLS:
11496       case SIG_FXSGS:
11497       case SIG_FXSKS:
11498             i->ringt = i->ringt_base;
11499             /* Fall through */
11500       case SIG_EMWINK:
11501       case SIG_FEATD:
11502       case SIG_FEATDMF:
11503       case SIG_FEATDMF_TA:
11504       case SIG_E911:
11505       case SIG_FGC_CAMA:
11506       case SIG_FGC_CAMAMF:
11507       case SIG_FEATB:
11508       case SIG_EM:
11509       case SIG_EM_E1:
11510       case SIG_SFWINK:
11511       case SIG_SF_FEATD:
11512       case SIG_SF_FEATDMF:
11513       case SIG_SF_FEATB:
11514       case SIG_SF:
11515          /* Check for callerid, digits, etc */
11516          if (i->cid_start == CID_START_POLARITY_IN) {
11517             chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL);
11518          } else {
11519             chan = dahdi_new(i, AST_STATE_RING, 0, SUB_REAL, 0, NULL);
11520          }
11521 
11522          if (!chan) {
11523             ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
11524          } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
11525             ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11526             res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11527             if (res < 0) {
11528                ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11529             }
11530             ast_hangup(chan);
11531          }
11532          break;
11533       default:
11534          ast_log(LOG_WARNING, "Don't know how to handle ring/answer with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
11535          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11536          if (res < 0)
11537             ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11538          return NULL;
11539       }
11540       break;
11541    case DAHDI_EVENT_NOALARM:
11542       switch (i->sig) {
11543 #if defined(HAVE_PRI)
11544       case SIG_PRI_LIB_HANDLE_CASES:
11545          ast_mutex_lock(&i->lock);
11546          sig_pri_chan_alarm_notify(i->sig_pvt, 1);
11547          ast_mutex_unlock(&i->lock);
11548          break;
11549 #endif   /* defined(HAVE_PRI) */
11550 #if defined(HAVE_SS7)
11551       case SIG_SS7:
11552          sig_ss7_set_alarm(i->sig_pvt, 0);
11553          break;
11554 #endif   /* defined(HAVE_SS7) */
11555       default:
11556          i->inalarm = 0;
11557          break;
11558       }
11559       handle_clear_alarms(i);
11560       break;
11561    case DAHDI_EVENT_ALARM:
11562       switch (i->sig) {
11563 #if defined(HAVE_PRI)
11564       case SIG_PRI_LIB_HANDLE_CASES:
11565          ast_mutex_lock(&i->lock);
11566          sig_pri_chan_alarm_notify(i->sig_pvt, 0);
11567          ast_mutex_unlock(&i->lock);
11568          break;
11569 #endif   /* defined(HAVE_PRI) */
11570 #if defined(HAVE_SS7)
11571       case SIG_SS7:
11572          sig_ss7_set_alarm(i->sig_pvt, 1);
11573          break;
11574 #endif   /* defined(HAVE_SS7) */
11575       default:
11576          i->inalarm = 1;
11577          break;
11578       }
11579       res = get_alarms(i);
11580       handle_alarms(i, res);
11581       /* fall thru intentionally */
11582    case DAHDI_EVENT_ONHOOK:
11583       if (i->radio)
11584          break;
11585       /* Back on hook.  Hang up. */
11586       switch (i->sig) {
11587       case SIG_FXOLS:
11588       case SIG_FXOGS:
11589       case SIG_FEATD:
11590       case SIG_FEATDMF:
11591       case SIG_FEATDMF_TA:
11592       case SIG_E911:
11593       case SIG_FGC_CAMA:
11594       case SIG_FGC_CAMAMF:
11595       case SIG_FEATB:
11596       case SIG_EM:
11597       case SIG_EM_E1:
11598       case SIG_EMWINK:
11599       case SIG_SF_FEATD:
11600       case SIG_SF_FEATDMF:
11601       case SIG_SF_FEATB:
11602       case SIG_SF:
11603       case SIG_SFWINK:
11604       case SIG_FXSLS:
11605       case SIG_FXSGS:
11606       case SIG_FXSKS:
11607       case SIG_FXOKS:
11608          dahdi_disable_ec(i);
11609          /* Diddle the battery for the zhone */
11610 #ifdef ZHONE_HACK
11611          dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
11612          usleep(1);
11613 #endif
11614          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
11615          dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
11616          break;
11617       case SIG_SS7:
11618       case SIG_PRI_LIB_HANDLE_CASES:
11619          dahdi_disable_ec(i);
11620          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
11621          break;
11622       default:
11623          ast_log(LOG_WARNING, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
11624          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
11625          return NULL;
11626       }
11627       break;
11628    case DAHDI_EVENT_POLARITY:
11629       switch (i->sig) {
11630       case SIG_FXSLS:
11631       case SIG_FXSKS:
11632       case SIG_FXSGS:
11633          /* We have already got a PR before the channel was
11634             created, but it wasn't handled. We need polarity
11635             to be REV for remote hangup detection to work.
11636             At least in Spain */
11637          if (i->hanguponpolarityswitch)
11638             i->polarity = POLARITY_REV;
11639          if (i->cid_start == CID_START_POLARITY || i->cid_start == CID_START_POLARITY_IN) {
11640             i->polarity = POLARITY_REV;
11641             ast_verb(2, "Starting post polarity "
11642                "CID detection on channel %d\n",
11643                i->channel);
11644             chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL);
11645             if (!chan) {
11646                ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
11647             } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
11648                ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11649                ast_hangup(chan);
11650             }
11651          }
11652          break;
11653       default:
11654          ast_log(LOG_WARNING, "handle_init_event detected "
11655             "polarity reversal on non-FXO (SIG_FXS) "
11656             "interface %d\n", i->channel);
11657       }
11658       break;
11659    case DAHDI_EVENT_REMOVED: /* destroy channel, will actually do so in do_monitor */
11660       ast_log(LOG_NOTICE,
11661             "Got DAHDI_EVENT_REMOVED. Destroying channel %d\n",
11662             i->channel);
11663       return i;
11664    case DAHDI_EVENT_NEONMWI_ACTIVE:
11665       if (i->mwimonitor_neon) {
11666          notify_message(i->mailbox, 1);
11667          ast_log(LOG_NOTICE, "NEON MWI set for channel %d, mailbox %s \n", i->channel, i->mailbox);
11668       }
11669       break;
11670    case DAHDI_EVENT_NEONMWI_INACTIVE:
11671       if (i->mwimonitor_neon) {
11672          notify_message(i->mailbox, 0);
11673          ast_log(LOG_NOTICE, "NEON MWI cleared for channel %d, mailbox %s\n", i->channel, i->mailbox);
11674       }
11675       break;
11676    }
11677    return NULL;
11678 }
11679 
11680 static void *do_monitor(void *data)
11681 {
11682    int count, res, res2, spoint, pollres=0;
11683    struct dahdi_pvt *i;
11684    struct dahdi_pvt *last = NULL;
11685    struct dahdi_pvt *doomed;
11686    time_t thispass = 0, lastpass = 0;
11687    int found;
11688    char buf[1024];
11689    struct pollfd *pfds=NULL;
11690    int lastalloc = -1;
11691    /* This thread monitors all the frame relay interfaces which are not yet in use
11692       (and thus do not have a separate thread) indefinitely */
11693    /* From here on out, we die whenever asked */
11694 #if 0
11695    if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) {
11696       ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n");
11697       return NULL;
11698    }
11699    ast_debug(1, "Monitor starting...\n");
11700 #endif
11701    pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
11702 
11703    for (;;) {
11704       /* Lock the interface list */
11705       ast_mutex_lock(&iflock);
11706       if (!pfds || (lastalloc != ifcount)) {
11707          if (pfds) {
11708             ast_free(pfds);
11709             pfds = NULL;
11710          }
11711          if (ifcount) {
11712             if (!(pfds = ast_calloc(1, ifcount * sizeof(*pfds)))) {
11713                ast_mutex_unlock(&iflock);
11714                return NULL;
11715             }
11716          }
11717          lastalloc = ifcount;
11718       }
11719       /* Build the stuff we're going to poll on, that is the socket of every
11720          dahdi_pvt that does not have an associated owner channel */
11721       count = 0;
11722       for (i = iflist; i; i = i->next) {
11723          ast_mutex_lock(&i->lock);
11724          if (pfds && (i->subs[SUB_REAL].dfd > -1) && i->sig && (!i->radio) && !(i->sig & SIG_MFCR2)) {
11725             if (analog_lib_handles(i->sig, i->radio, i->oprmode)) {
11726                struct analog_pvt *p = i->sig_pvt;
11727 
11728                if (!p) {
11729                   ast_log(LOG_ERROR, "No sig_pvt?\n");
11730                } else if (!p->owner && !p->subs[SUB_REAL].owner) {
11731                   /* This needs to be watched, as it lacks an owner */
11732                   pfds[count].fd = i->subs[SUB_REAL].dfd;
11733                   pfds[count].events = POLLPRI;
11734                   pfds[count].revents = 0;
11735                   /* Message waiting or r2 channels also get watched for reading */
11736                   if (i->cidspill || i->mwisendactive || i->mwimonitor_fsk || 
11737                      (i->cid_start == CID_START_DTMF_NOALERT && (i->sig == SIG_FXSLS || i->sig == SIG_FXSGS || i->sig == SIG_FXSKS))) {
11738                      pfds[count].events |= POLLIN;
11739                   }
11740                   count++;
11741                }
11742             } else {
11743                if (!i->owner && !i->subs[SUB_REAL].owner && !i->mwimonitoractive ) {
11744                   /* This needs to be watched, as it lacks an owner */
11745                   pfds[count].fd = i->subs[SUB_REAL].dfd;
11746                   pfds[count].events = POLLPRI;
11747                   pfds[count].revents = 0;
11748                   /* If we are monitoring for VMWI or sending CID, we need to
11749                      read from the channel as well */
11750                   if (i->cidspill || i->mwisendactive || i->mwimonitor_fsk ||
11751                      (i->cid_start == CID_START_DTMF_NOALERT && (i->sig == SIG_FXSLS || i->sig == SIG_FXSGS || i->sig == SIG_FXSKS))) {
11752                      pfds[count].events |= POLLIN;
11753                   }
11754                   count++;
11755                }
11756             }
11757          }
11758          ast_mutex_unlock(&i->lock);
11759       }
11760       /* Okay, now that we know what to do, release the interface lock */
11761       ast_mutex_unlock(&iflock);
11762 
11763       pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
11764       pthread_testcancel();
11765       /* Wait at least a second for something to happen */
11766       res = poll(pfds, count, 1000);
11767       pthread_testcancel();
11768       pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
11769 
11770       /* Okay, poll has finished.  Let's see what happened.  */
11771       if (res < 0) {
11772          if ((errno != EAGAIN) && (errno != EINTR))
11773             ast_log(LOG_WARNING, "poll return %d: %s\n", res, strerror(errno));
11774          continue;
11775       }
11776       /* Alright, lock the interface list again, and let's look and see what has
11777          happened */
11778       ast_mutex_lock(&iflock);
11779       found = 0;
11780       spoint = 0;
11781       lastpass = thispass;
11782       thispass = time(NULL);
11783       doomed = NULL;
11784       for (i = iflist;; i = i->next) {
11785          if (doomed) {
11786             int res;
11787             res = dahdi_destroy_channel_bynum(doomed->channel);
11788             if (res != RESULT_SUCCESS) {
11789                ast_log(LOG_WARNING, "Couldn't find channel to destroy, hopefully another destroy operation just happened.\n");
11790             }
11791             doomed = NULL;
11792          }
11793          if (!i) {
11794             break;
11795          }
11796 
11797          if (thispass != lastpass) {
11798             if (!found && ((i == last) || ((i == iflist) && !last))) {
11799                last = i;
11800                if (last) {
11801                   struct analog_pvt *analog_p = last->sig_pvt;
11802                   /* Only allow MWI to be initiated on a quiescent fxs port */
11803                   if (analog_p
11804                      && !last->mwisendactive
11805                      && (last->sig & __DAHDI_SIG_FXO)
11806                      && !analog_p->fxsoffhookstate
11807                      && !last->owner
11808                      && !ast_strlen_zero(last->mailbox)
11809                      && (thispass - analog_p->onhooktime > 3)) {
11810                      res = has_voicemail(last);
11811                      if (analog_p->msgstate != res) {
11812                         /* Set driver resources for signalling VMWI */
11813                         res2 = ioctl(last->subs[SUB_REAL].dfd, DAHDI_VMWI, &res);
11814                         if (res2) {
11815                            /* TODO: This message will ALWAYS be generated on some cards; any way to restrict it to those cards where it is interesting? */
11816                            ast_debug(3, "Unable to control message waiting led on channel %d: %s\n", last->channel, strerror(errno));
11817                         }
11818                         /* If enabled for FSK spill then initiate it */
11819                         if (mwi_send_init(last)) {
11820                            ast_log(LOG_WARNING, "Unable to initiate mwi send sequence on channel %d\n", last->channel);
11821                         }
11822                         analog_p->msgstate = res;
11823                         found ++;
11824                      }
11825                   }
11826                   last = last->next;
11827                }
11828             }
11829          }
11830          if ((i->subs[SUB_REAL].dfd > -1) && i->sig) {
11831             if (i->radio && !i->owner)
11832             {
11833                res = dahdi_get_event(i->subs[SUB_REAL].dfd);
11834                if (res)
11835                {
11836                   ast_debug(1, "Monitor doohicky got event %s on radio channel %d\n", event2str(res), i->channel);
11837                   /* Don't hold iflock while handling init events */
11838                   ast_mutex_unlock(&iflock);
11839                   if (analog_lib_handles(i->sig, i->radio, i->oprmode))
11840                      doomed = (struct dahdi_pvt *) analog_handle_init_event(i->sig_pvt, dahdievent_to_analogevent(res));
11841                   else
11842                      doomed = handle_init_event(i, res);
11843                   ast_mutex_lock(&iflock);
11844                }
11845                continue;
11846             }
11847             pollres = ast_fdisset(pfds, i->subs[SUB_REAL].dfd, count, &spoint);
11848             if (pollres & POLLIN) {
11849                if (i->owner || i->subs[SUB_REAL].owner) {
11850 #ifdef HAVE_PRI
11851                   if (!i->pri)
11852 #endif
11853                      ast_log(LOG_WARNING, "Whoa....  I'm owned but found (%d) in read...\n", i->subs[SUB_REAL].dfd);
11854                   continue;
11855                }
11856                if (!i->mwimonitor_fsk && !i->mwisendactive  && i->cid_start != CID_START_DTMF_NOALERT) {
11857                   ast_log(LOG_WARNING, "Whoa....  I'm not looking for MWI or sending MWI but am reading (%d)...\n", i->subs[SUB_REAL].dfd);
11858                   continue;
11859                }
11860                res = read(i->subs[SUB_REAL].dfd, buf, sizeof(buf));
11861                if (res > 0) {
11862                   if (i->mwimonitor_fsk) {
11863                      if (calc_energy((unsigned char *) buf, res, AST_LAW(i)) > mwilevel) {
11864                         pthread_attr_t attr;
11865                         pthread_t threadid;
11866                         struct mwi_thread_data *mtd;
11867 
11868                         pthread_attr_init(&attr);
11869                         pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
11870 
11871                         ast_log(LOG_DEBUG, "Maybe some MWI on port %d!\n", i->channel);
11872                         if ((mtd = ast_calloc(1, sizeof(*mtd)))) {
11873                            mtd->pvt = i;
11874                            memcpy(mtd->buf, buf, res);
11875                            mtd->len = res;
11876                            i->mwimonitoractive = 1;
11877                            if (ast_pthread_create_background(&threadid, &attr, mwi_thread, mtd)) {
11878                               ast_log(LOG_WARNING, "Unable to start mwi thread on channel %d\n", i->channel);
11879                               i->mwimonitoractive = 0;
11880                               ast_free(mtd);
11881                            }
11882                         }
11883                      }
11884                   /* If configured to check for a DTMF CID spill that comes without alert (e.g no polarity reversal) */
11885                   } else if (i->cid_start == CID_START_DTMF_NOALERT) {
11886                      int energy;
11887                      struct timeval now;
11888                      /* State machine dtmfcid_holdoff_state allows for the line to settle
11889                       * before checking agin for dtmf energy.  Presently waits for 500 mS before checking again 
11890                      */
11891                      if (1 == i->dtmfcid_holdoff_state) {
11892                         gettimeofday(&i->dtmfcid_delay, NULL);
11893                         i->dtmfcid_holdoff_state = 2;
11894                      } else if (2 == i->dtmfcid_holdoff_state) {
11895                         gettimeofday(&now, NULL);
11896                         if ((int)(now.tv_sec - i->dtmfcid_delay.tv_sec) * 1000000 + (int)now.tv_usec - (int)i->dtmfcid_delay.tv_usec > 500000) {
11897                            i->dtmfcid_holdoff_state = 0;
11898                         }
11899                      } else {
11900                         energy = calc_energy((unsigned char *) buf, res, AST_LAW(i));
11901                         if (!i->mwisendactive && energy > dtmfcid_level) {
11902                            pthread_t threadid;
11903                            struct ast_channel *chan;
11904                            ast_mutex_unlock(&iflock);
11905                            if (analog_lib_handles(i->sig, i->radio, i->oprmode)) {
11906                               /* just in case this event changes or somehow destroys a channel, set doomed here too */
11907                               doomed = analog_handle_init_event(i->sig_pvt, ANALOG_EVENT_DTMFCID);  
11908                               i->dtmfcid_holdoff_state = 1;
11909                            } else {
11910                               chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL);
11911                               if (!chan) {
11912                                  ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
11913                               } else {
11914                                  res = ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan);
11915                                  if (res) {
11916                                     ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11917                                     ast_hangup(chan);
11918                                  } else {
11919                                     i->dtmfcid_holdoff_state = 1;
11920                                  }
11921                               }
11922                            }
11923                            ast_mutex_lock(&iflock);
11924                         }
11925                      }
11926                   }
11927                   if (i->mwisendactive) {
11928                      mwi_send_process_buffer(i, res);
11929                   }
11930                } else {
11931                   ast_log(LOG_WARNING, "Read failed with %d: %s\n", res, strerror(errno));
11932                }
11933             }
11934             if (pollres & POLLPRI) {
11935                if (i->owner || i->subs[SUB_REAL].owner) {
11936 #ifdef HAVE_PRI
11937                   if (!i->pri)
11938 #endif
11939                      ast_log(LOG_WARNING, "Whoa....  I'm owned but found (%d)...\n", i->subs[SUB_REAL].dfd);
11940                   continue;
11941                }
11942                res = dahdi_get_event(i->subs[SUB_REAL].dfd);
11943                ast_debug(1, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel);
11944                /* Don't hold iflock while handling init events */
11945                ast_mutex_unlock(&iflock);
11946                if (0 == i->mwisendactive || 0 == mwi_send_process_event(i, res)) {
11947                   if (analog_lib_handles(i->sig, i->radio, i->oprmode))
11948                      doomed = (struct dahdi_pvt *) analog_handle_init_event(i->sig_pvt, dahdievent_to_analogevent(res));
11949                   else
11950                      doomed = handle_init_event(i, res);
11951                }
11952                ast_mutex_lock(&iflock);
11953             }
11954          }
11955       }
11956       ast_mutex_unlock(&iflock);
11957    }
11958    /* Never reached */
11959    return NULL;
11960 
11961 }
11962 
11963 static int restart_monitor(void)
11964 {
11965    /* If we're supposed to be stopped -- stay stopped */
11966    if (monitor_thread == AST_PTHREADT_STOP)
11967       return 0;
11968    ast_mutex_lock(&monlock);
11969    if (monitor_thread == pthread_self()) {
11970       ast_mutex_unlock(&monlock);
11971       ast_log(LOG_WARNING, "Cannot kill myself\n");
11972       return -1;
11973    }
11974    if (monitor_thread != AST_PTHREADT_NULL) {
11975       /* Wake up the thread */
11976       pthread_kill(monitor_thread, SIGURG);
11977    } else {
11978       /* Start a new monitor */
11979       if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) {
11980          ast_mutex_unlock(&monlock);
11981          ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
11982          return -1;
11983       }
11984    }
11985    ast_mutex_unlock(&monlock);
11986    return 0;
11987 }
11988 
11989 #if defined(HAVE_PRI)
11990 static int pri_resolve_span(int *span, int channel, int offset, struct dahdi_spaninfo *si)
11991 {
11992    int x;
11993    int trunkgroup;
11994    /* Get appropriate trunk group if there is one */
11995    trunkgroup = pris[*span].mastertrunkgroup;
11996    if (trunkgroup) {
11997       /* Select a specific trunk group */
11998       for (x = 0; x < NUM_SPANS; x++) {
11999          if (pris[x].pri.trunkgroup == trunkgroup) {
12000             *span = x;
12001             return 0;
12002          }
12003       }
12004       ast_log(LOG_WARNING, "Channel %d on span %d configured to use nonexistent trunk group %d\n", channel, *span, trunkgroup);
12005       *span = -1;
12006    } else {
12007       if (pris[*span].pri.trunkgroup) {
12008          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);
12009          *span = -1;
12010       } else if (pris[*span].mastertrunkgroup) {
12011          ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is already part of trunk group %d\n", *span, pris[*span].mastertrunkgroup);
12012          *span = -1;
12013       } else {
12014          if (si->totalchans == 31) {
12015             /* E1 */
12016             pris[*span].dchannels[0] = 16 + offset;
12017          } else if (si->totalchans == 24) {
12018             /* T1 or J1 */
12019             pris[*span].dchannels[0] = 24 + offset;
12020          } else if (si->totalchans == 3) {
12021             /* BRI */
12022             pris[*span].dchannels[0] = 3 + offset;
12023          } else {
12024             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);
12025             *span = -1;
12026             return 0;
12027          }
12028          pris[*span].pri.span = *span + 1;
12029       }
12030    }
12031    return 0;
12032 }
12033 #endif   /* defined(HAVE_PRI) */
12034 
12035 #if defined(HAVE_PRI)
12036 static int pri_create_trunkgroup(int trunkgroup, int *channels)
12037 {
12038    struct dahdi_spaninfo si;
12039    struct dahdi_params p;
12040    int fd;
12041    int span;
12042    int ospan=0;
12043    int x,y;
12044    for (x = 0; x < NUM_SPANS; x++) {
12045       if (pris[x].pri.trunkgroup == trunkgroup) {
12046          ast_log(LOG_WARNING, "Trunk group %d already exists on span %d, Primary d-channel %d\n", trunkgroup, x + 1, pris[x].dchannels[0]);
12047          return -1;
12048       }
12049    }
12050    for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
12051       if (!channels[y])
12052          break;
12053       memset(&si, 0, sizeof(si));
12054       memset(&p, 0, sizeof(p));
12055       fd = open("/dev/dahdi/channel", O_RDWR);
12056       if (fd < 0) {
12057          ast_log(LOG_WARNING, "Failed to open channel: %s\n", strerror(errno));
12058          return -1;
12059       }
12060       x = channels[y];
12061       if (ioctl(fd, DAHDI_SPECIFY, &x)) {
12062          ast_log(LOG_WARNING, "Failed to specify channel %d: %s\n", channels[y], strerror(errno));
12063          close(fd);
12064          return -1;
12065       }
12066       if (ioctl(fd, DAHDI_GET_PARAMS, &p)) {
12067          ast_log(LOG_WARNING, "Failed to get channel parameters for channel %d: %s\n", channels[y], strerror(errno));
12068          return -1;
12069       }
12070       if (ioctl(fd, DAHDI_SPANSTAT, &si)) {
12071          ast_log(LOG_WARNING, "Failed go get span information on channel %d (span %d): %s\n", channels[y], p.spanno, strerror(errno));
12072          close(fd);
12073          return -1;
12074       }
12075       span = p.spanno - 1;
12076       if (pris[span].pri.trunkgroup) {
12077          ast_log(LOG_WARNING, "Span %d is already provisioned for trunk group %d\n", span + 1, pris[span].pri.trunkgroup);
12078          close(fd);
12079          return -1;
12080       }
12081       if (pris[span].pri.pvts[0]) {
12082          ast_log(LOG_WARNING, "Span %d is already provisioned with channels (implicit PRI maybe?)\n", span + 1);
12083          close(fd);
12084          return -1;
12085       }
12086       if (!y) {
12087          pris[span].pri.trunkgroup = trunkgroup;
12088          ospan = span;
12089       }
12090       pris[ospan].dchannels[y] = channels[y];
12091       pris[span].pri.span = span + 1;
12092       close(fd);
12093    }
12094    return 0;
12095 }
12096 #endif   /* defined(HAVE_PRI) */
12097 
12098 #if defined(HAVE_PRI)
12099 static int pri_create_spanmap(int span, int trunkgroup, int logicalspan)
12100 {
12101    if (pris[span].mastertrunkgroup) {
12102       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);
12103       return -1;
12104    }
12105    pris[span].mastertrunkgroup = trunkgroup;
12106    pris[span].prilogicalspan = logicalspan;
12107    return 0;
12108 }
12109 #endif   /* defined(HAVE_PRI) */
12110 
12111 #if defined(HAVE_SS7)
12112 static unsigned int parse_pointcode(const char *pcstring)
12113 {
12114    unsigned int code1, code2, code3;
12115    int numvals;
12116 
12117    numvals = sscanf(pcstring, "%30d-%30d-%30d", &code1, &code2, &code3);
12118    if (numvals == 1)
12119       return code1;
12120    if (numvals == 3)
12121       return (code1 << 16) | (code2 << 8) | code3;
12122 
12123    return 0;
12124 }
12125 #endif   /* defined(HAVE_SS7) */
12126 
12127 #if defined(HAVE_SS7)
12128 static struct dahdi_ss7 * ss7_resolve_linkset(int linkset)
12129 {
12130    if ((linkset < 0) || (linkset >= NUM_SPANS))
12131       return NULL;
12132    else
12133       return &linksets[linkset - 1];
12134 }
12135 #endif   /* defined(HAVE_SS7) */
12136 
12137 #ifdef HAVE_OPENR2
12138 static void dahdi_r2_destroy_links(void)
12139 {
12140    int i = 0;
12141    if (!r2links) {
12142       return;
12143    }
12144    for (; i < r2links_count; i++) {
12145       if (r2links[i]->r2master != AST_PTHREADT_NULL) {
12146          pthread_cancel(r2links[i]->r2master);
12147          pthread_join(r2links[i]->r2master, NULL);
12148          openr2_context_delete(r2links[i]->protocol_context);
12149       }
12150       ast_free(r2links[i]);
12151    }
12152    ast_free(r2links);
12153    r2links = NULL;
12154    r2links_count = 0;
12155 }
12156 
12157 #define R2_LINK_CAPACITY 10
12158 static struct dahdi_mfcr2 *dahdi_r2_get_link(void)
12159 {
12160    struct dahdi_mfcr2 *new_r2link = NULL;
12161    struct dahdi_mfcr2 **new_r2links = NULL;
12162    /* this function is called just when starting up and no monitor threads have been launched,
12163       no need to lock monitored_count member */
12164    if (!r2links_count || (r2links[r2links_count - 1]->monitored_count == R2_LINK_CAPACITY)) {
12165       new_r2link = ast_calloc(1, sizeof(**r2links));
12166       if (!new_r2link) {
12167          ast_log(LOG_ERROR, "Cannot allocate R2 link!\n");
12168          return NULL;
12169       }
12170       new_r2links = ast_realloc(r2links, ((r2links_count + 1) * sizeof(*r2links)));
12171       if (!new_r2links) {
12172          ast_log(LOG_ERROR, "Cannot allocate R2 link!\n");
12173          ast_free(new_r2link);
12174          return NULL;
12175       }
12176       r2links = new_r2links;
12177       new_r2link->r2master = AST_PTHREADT_NULL;
12178       r2links[r2links_count] = new_r2link;
12179       r2links_count++;
12180       ast_log(LOG_DEBUG, "Created new R2 link!\n");
12181    }
12182    return r2links[r2links_count - 1];
12183 }
12184 
12185 static int dahdi_r2_set_context(struct dahdi_mfcr2 *r2_link, const struct dahdi_chan_conf *conf)
12186 {
12187    char tmplogdir[] = "/tmp";
12188    char logdir[OR2_MAX_PATH];
12189    int threshold = 0;
12190    int snres = 0;
12191    r2_link->protocol_context = openr2_context_new(NULL, &dahdi_r2_event_iface,
12192          &dahdi_r2_transcode_iface, conf->mfcr2.variant, conf->mfcr2.max_ani,
12193          conf->mfcr2.max_dnis);
12194    if (!r2_link->protocol_context) {
12195       return -1;
12196    }
12197    openr2_context_set_log_level(r2_link->protocol_context, conf->mfcr2.loglevel);
12198    openr2_context_set_ani_first(r2_link->protocol_context, conf->mfcr2.get_ani_first);
12199 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
12200    openr2_context_set_skip_category_request(r2_link->protocol_context, conf->mfcr2.skip_category_request);
12201 #endif
12202    openr2_context_set_mf_threshold(r2_link->protocol_context, threshold);
12203    openr2_context_set_mf_back_timeout(r2_link->protocol_context, conf->mfcr2.mfback_timeout);
12204    openr2_context_set_metering_pulse_timeout(r2_link->protocol_context, conf->mfcr2.metering_pulse_timeout);
12205    openr2_context_set_double_answer(r2_link->protocol_context, conf->mfcr2.double_answer);
12206    openr2_context_set_immediate_accept(r2_link->protocol_context, conf->mfcr2.immediate_accept);
12207    if (ast_strlen_zero(conf->mfcr2.logdir)) {
12208       if (openr2_context_set_log_directory(r2_link->protocol_context, tmplogdir)) {
12209          ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir);
12210       }
12211    } else {
12212       snres = snprintf(logdir, sizeof(logdir), "%s/%s/%s", ast_config_AST_LOG_DIR, "mfcr2", conf->mfcr2.logdir);
12213       if (snres >= sizeof(logdir)) {
12214          ast_log(LOG_ERROR, "MFC/R2 logging directory truncated, using %s\n", tmplogdir);
12215          if (openr2_context_set_log_directory(r2_link->protocol_context, tmplogdir)) {
12216             ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir);
12217          }
12218       } else {
12219          if (openr2_context_set_log_directory(r2_link->protocol_context, logdir)) {
12220             ast_log(LOG_ERROR, "Failed setting MFC/R2 log directory %s\n", logdir);
12221          }
12222       }
12223    }
12224    if (!ast_strlen_zero(conf->mfcr2.r2proto_file)) {
12225       if (openr2_context_configure_from_advanced_file(r2_link->protocol_context, conf->mfcr2.r2proto_file)) {
12226          ast_log(LOG_ERROR, "Failed to configure r2context from advanced configuration file %s\n", conf->mfcr2.r2proto_file);
12227       }
12228    }
12229    r2_link->monitored_count = 0;
12230    return 0;
12231 }
12232 #endif
12233 
12234 /* converts a DAHDI sigtype to signalling as can be configured from
12235  * chan_dahdi.conf.
12236  * While both have basically the same values, this will later be the
12237  * place to add filters and sanity checks
12238  */
12239 static int sigtype_to_signalling(int sigtype)
12240 {
12241    return sigtype;
12242 }
12243 
12244 /*!
12245  * \internal
12246  * \brief Get file name and channel number from (subdir,number)
12247  *
12248  * \param subdir name of the subdirectory under /dev/dahdi/
12249  * \param channel name of device file under /dev/dahdi/<subdir>/
12250  * \param path buffer to put file name in
12251  * \param pathlen maximal length of path
12252  *
12253  * \retval minor number of dahdi channel.
12254  * \retval -errno on error.
12255  */
12256 static int device2chan(const char *subdir, int channel, char *path, int pathlen)
12257 {
12258    struct stat stbuf;
12259    int      num;
12260 
12261    snprintf(path, pathlen, "/dev/dahdi/%s/%d", subdir, channel);
12262    if (stat(path, &stbuf) < 0) {
12263       ast_log(LOG_ERROR, "stat(%s) failed: %s\n", path, strerror(errno));
12264       return -errno;
12265    }
12266    if (!S_ISCHR(stbuf.st_mode)) {
12267       ast_log(LOG_ERROR, "%s: Not a character device file\n", path);
12268       return -EINVAL;
12269    }
12270    num = minor(stbuf.st_rdev);
12271    ast_log(LOG_DEBUG, "%s -> %d\n", path, num);
12272    return num;
12273 
12274 }
12275 
12276 /*!
12277  * \internal
12278  * \brief Initialize/create a channel interface.
12279  *
12280  * \param channel Channel interface number to initialize/create.
12281  * \param conf Configuration parameters to initialize interface with.
12282  * \param reloading What we are doing now:
12283  * 0 - initial module load,
12284  * 1 - module reload,
12285  * 2 - module restart
12286  *
12287  * \retval Interface-pointer initialized/created
12288  * \retval NULL if error
12289  */
12290 static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf, int reloading)
12291 {
12292    /* Make a dahdi_pvt structure for this interface */
12293    struct dahdi_pvt *tmp;/*!< Current channel structure initializing */
12294    char fn[80];
12295    struct dahdi_bufferinfo bi;
12296 
12297    int res;
12298 #if defined(HAVE_PRI)
12299    int span = 0;
12300 #endif   /* defined(HAVE_PRI) */
12301    int here = 0;/*!< TRUE if the channel interface already exists. */
12302    int x;
12303    struct analog_pvt *analog_p = NULL;
12304    struct dahdi_params p;
12305 #if defined(HAVE_PRI)
12306    struct dahdi_spaninfo si;
12307    struct sig_pri_chan *pri_chan = NULL;
12308 #endif   /* defined(HAVE_PRI) */
12309 #if defined(HAVE_SS7)
12310    struct sig_ss7_chan *ss7_chan = NULL;
12311 #endif   /* defined(HAVE_SS7) */
12312 
12313    /* Search channel interface list to see if it already exists. */
12314    for (tmp = iflist; tmp; tmp = tmp->next) {
12315       if (!tmp->destroy) {
12316          if (tmp->channel == channel) {
12317             /* The channel interface already exists. */
12318             here = 1;
12319             break;
12320          }
12321          if (tmp->channel > channel) {
12322             /* No way it can be in the sorted list. */
12323             tmp = NULL;
12324             break;
12325          }
12326       }
12327    }
12328 
12329    if (!here && reloading != 1) {
12330       tmp = ast_calloc(1, sizeof(*tmp));
12331       if (!tmp) {
12332          return NULL;
12333       }
12334       tmp->cc_params = ast_cc_config_params_init();
12335       if (!tmp->cc_params) {
12336          ast_free(tmp);
12337          return NULL;
12338       }
12339       ast_mutex_init(&tmp->lock);
12340       ifcount++;
12341       for (x = 0; x < 3; x++)
12342          tmp->subs[x].dfd = -1;
12343       tmp->channel = channel;
12344       tmp->priindication_oob = conf->chan.priindication_oob;
12345    }
12346 
12347    if (tmp) {
12348       int chan_sig = conf->chan.sig;
12349 
12350       /* If there are variables in tmp before it is updated to match the new config, clear them */
12351       if (reloading && tmp->vars) {
12352          ast_variables_destroy(tmp->vars);
12353          tmp->vars = NULL;
12354       }
12355 
12356 
12357       if (!here) {
12358          /* Can only get here if this is a new channel interface being created. */
12359          if ((channel != CHAN_PSEUDO)) {
12360             int count = 0;
12361 
12362             snprintf(fn, sizeof(fn), "%d", channel);
12363             /* Open non-blocking */
12364             tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
12365             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 */
12366                usleep(1);
12367                tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
12368                count++;
12369             }
12370             /* Allocate a DAHDI structure */
12371             if (tmp->subs[SUB_REAL].dfd < 0) {
12372                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);
12373                destroy_dahdi_pvt(tmp);
12374                return NULL;
12375             }
12376             memset(&p, 0, sizeof(p));
12377             res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
12378             if (res < 0) {
12379                ast_log(LOG_ERROR, "Unable to get parameters: %s\n", strerror(errno));
12380                destroy_dahdi_pvt(tmp);
12381                return NULL;
12382             }
12383             if (conf->is_sig_auto)
12384                chan_sig = sigtype_to_signalling(p.sigtype);
12385             if (p.sigtype != (chan_sig & 0x3ffff)) {
12386                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));
12387                destroy_dahdi_pvt(tmp);
12388                return NULL;
12389             }
12390             tmp->law_default = p.curlaw;
12391             tmp->law = p.curlaw;
12392             tmp->span = p.spanno;
12393 #if defined(HAVE_PRI)
12394             span = p.spanno - 1;
12395 #endif   /* defined(HAVE_PRI) */
12396          } else {
12397             chan_sig = 0;
12398          }
12399          tmp->sig = chan_sig;
12400          tmp->outsigmod = conf->chan.outsigmod;
12401 
12402          if (analog_lib_handles(chan_sig, tmp->radio, tmp->oprmode)) {
12403             analog_p = analog_new(dahdisig_to_analogsig(chan_sig), &dahdi_analog_callbacks, tmp);
12404             if (!analog_p) {
12405                destroy_dahdi_pvt(tmp);
12406                return NULL;
12407             }
12408             tmp->sig_pvt = analog_p;
12409          }
12410 #if defined(HAVE_SS7)
12411          if (chan_sig == SIG_SS7) {
12412             struct dahdi_ss7 *ss7;
12413             int clear = 0;
12414 
12415             if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &clear)) {
12416                ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
12417                destroy_dahdi_pvt(tmp);
12418                return NULL;
12419             }
12420 
12421             ss7 = ss7_resolve_linkset(cur_linkset);
12422             if (!ss7) {
12423                ast_log(LOG_ERROR, "Unable to find linkset %d\n", cur_linkset);
12424                destroy_dahdi_pvt(tmp);
12425                return NULL;
12426             }
12427             ss7->ss7.span = cur_linkset;
12428             if (cur_cicbeginswith < 0) {
12429                ast_log(LOG_ERROR, "Need to set cicbeginswith for the channels!\n");
12430                destroy_dahdi_pvt(tmp);
12431                return NULL;
12432             }
12433             ss7_chan = sig_ss7_chan_new(tmp, &dahdi_ss7_callbacks, &ss7->ss7);
12434             if (!ss7_chan) {
12435                destroy_dahdi_pvt(tmp);
12436                return NULL;
12437             }
12438             tmp->sig_pvt = ss7_chan;
12439             tmp->ss7 = &ss7->ss7;
12440 
12441             ss7_chan->channel = tmp->channel;
12442             ss7_chan->cic = cur_cicbeginswith++;
12443 
12444             /* DB: Add CIC's DPC information */
12445             ss7_chan->dpc = cur_defaultdpc;
12446 
12447             ss7->ss7.pvts[ss7->ss7.numchans++] = ss7_chan;
12448 
12449             ast_copy_string(ss7->ss7.internationalprefix, conf->ss7.ss7.internationalprefix, sizeof(ss7->ss7.internationalprefix));
12450             ast_copy_string(ss7->ss7.nationalprefix, conf->ss7.ss7.nationalprefix, sizeof(ss7->ss7.nationalprefix));
12451             ast_copy_string(ss7->ss7.subscriberprefix, conf->ss7.ss7.subscriberprefix, sizeof(ss7->ss7.subscriberprefix));
12452             ast_copy_string(ss7->ss7.unknownprefix, conf->ss7.ss7.unknownprefix, sizeof(ss7->ss7.unknownprefix));
12453 
12454             ss7->ss7.called_nai = conf->ss7.ss7.called_nai;
12455             ss7->ss7.calling_nai = conf->ss7.ss7.calling_nai;
12456          }
12457 #endif   /* defined(HAVE_SS7) */
12458 #ifdef HAVE_OPENR2
12459          if (chan_sig == SIG_MFCR2) {
12460             struct dahdi_mfcr2 *r2_link;
12461             r2_link = dahdi_r2_get_link();
12462             if (!r2_link) {
12463                ast_log(LOG_WARNING, "Cannot get another R2 DAHDI context!\n");
12464                destroy_dahdi_pvt(tmp);
12465                return NULL;
12466             }
12467             if (!r2_link->protocol_context && dahdi_r2_set_context(r2_link, conf)) {
12468                ast_log(LOG_ERROR, "Cannot create OpenR2 protocol context.\n");
12469                destroy_dahdi_pvt(tmp);
12470                return NULL;
12471             }
12472             if (r2_link->numchans == ARRAY_LEN(r2_link->pvts)) {
12473                ast_log(LOG_ERROR, "Cannot add more channels to this link!\n");
12474                destroy_dahdi_pvt(tmp);
12475                return NULL;
12476             }
12477             r2_link->pvts[r2_link->numchans++] = tmp;
12478             tmp->r2chan = openr2_chan_new_from_fd(r2_link->protocol_context,
12479                                         tmp->subs[SUB_REAL].dfd,
12480                                         NULL, NULL);
12481             if (!tmp->r2chan) {
12482                openr2_liberr_t err = openr2_context_get_last_error(r2_link->protocol_context);
12483                ast_log(LOG_ERROR, "Cannot create OpenR2 channel: %s\n", openr2_context_error_string(err));
12484                destroy_dahdi_pvt(tmp);
12485                return NULL;
12486             }
12487             tmp->mfcr2 = r2_link;
12488             if (conf->mfcr2.call_files) {
12489                openr2_chan_enable_call_files(tmp->r2chan);
12490             }
12491             openr2_chan_set_client_data(tmp->r2chan, tmp);
12492             /* cast seems to be needed to get rid of the annoying warning regarding format attribute  */
12493             openr2_chan_set_logging_func(tmp->r2chan, (openr2_logging_func_t)dahdi_r2_on_chan_log);
12494             openr2_chan_set_log_level(tmp->r2chan, conf->mfcr2.loglevel);
12495             tmp->mfcr2_category = conf->mfcr2.category;
12496             tmp->mfcr2_charge_calls = conf->mfcr2.charge_calls;
12497             tmp->mfcr2_allow_collect_calls = conf->mfcr2.allow_collect_calls;
12498             tmp->mfcr2_forced_release = conf->mfcr2.forced_release;
12499             tmp->mfcr2_accept_on_offer = conf->mfcr2.accept_on_offer;
12500             tmp->mfcr2call = 0;
12501             tmp->mfcr2_dnis_index = 0;
12502             tmp->mfcr2_ani_index = 0;
12503             r2_link->monitored_count++;
12504          }
12505 #endif
12506 #ifdef HAVE_PRI
12507          if (dahdi_sig_pri_lib_handles(chan_sig)) {
12508             int offset;
12509             int matchesdchan;
12510             int x,y;
12511             int myswitchtype = 0;
12512 
12513             offset = 0;
12514             if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &offset)) {
12515                ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
12516                destroy_dahdi_pvt(tmp);
12517                return NULL;
12518             }
12519             if (span >= NUM_SPANS) {
12520                ast_log(LOG_ERROR, "Channel %d does not lie on a span I know of (%d)\n", channel, span);
12521                destroy_dahdi_pvt(tmp);
12522                return NULL;
12523             } else {
12524                si.spanno = 0;
12525                if (ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SPANSTAT,&si) == -1) {
12526                   ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno));
12527                   destroy_dahdi_pvt(tmp);
12528                   return NULL;
12529                }
12530                /* Store the logical span first based upon the real span */
12531                tmp->logicalspan = pris[span].prilogicalspan;
12532                pri_resolve_span(&span, channel, (channel - p.chanpos), &si);
12533                if (span < 0) {
12534                   ast_log(LOG_WARNING, "Channel %d: Unable to find locate channel/trunk group!\n", channel);
12535                   destroy_dahdi_pvt(tmp);
12536                   return NULL;
12537                }
12538                myswitchtype = conf->pri.pri.switchtype;
12539                /* Make sure this isn't a d-channel */
12540                matchesdchan=0;
12541                for (x = 0; x < NUM_SPANS; x++) {
12542                   for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
12543                      if (pris[x].dchannels[y] == tmp->channel) {
12544                         matchesdchan = 1;
12545                         break;
12546                      }
12547                   }
12548                }
12549                if (!matchesdchan) {
12550                   if (pris[span].pri.nodetype && (pris[span].pri.nodetype != conf->pri.pri.nodetype)) {
12551                      ast_log(LOG_ERROR, "Span %d is already a %s node\n", span + 1, pri_node2str(pris[span].pri.nodetype));
12552                      destroy_dahdi_pvt(tmp);
12553                      return NULL;
12554                   }
12555                   if (pris[span].pri.switchtype && (pris[span].pri.switchtype != myswitchtype)) {
12556                      ast_log(LOG_ERROR, "Span %d is already a %s switch\n", span + 1, pri_switch2str(pris[span].pri.switchtype));
12557                      destroy_dahdi_pvt(tmp);
12558                      return NULL;
12559                   }
12560                   if ((pris[span].pri.dialplan) && (pris[span].pri.dialplan != conf->pri.pri.dialplan)) {
12561                      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));
12562                      destroy_dahdi_pvt(tmp);
12563                      return NULL;
12564                   }
12565                   if (!ast_strlen_zero(pris[span].pri.idledial) && strcmp(pris[span].pri.idledial, conf->pri.pri.idledial)) {
12566                      ast_log(LOG_ERROR, "Span %d already has idledial '%s'.\n", span + 1, conf->pri.pri.idledial);
12567                      destroy_dahdi_pvt(tmp);
12568                      return NULL;
12569                   }
12570                   if (!ast_strlen_zero(pris[span].pri.idleext) && strcmp(pris[span].pri.idleext, conf->pri.pri.idleext)) {
12571                      ast_log(LOG_ERROR, "Span %d already has idleext '%s'.\n", span + 1, conf->pri.pri.idleext);
12572                      destroy_dahdi_pvt(tmp);
12573                      return NULL;
12574                   }
12575                   if (pris[span].pri.minunused && (pris[span].pri.minunused != conf->pri.pri.minunused)) {
12576                      ast_log(LOG_ERROR, "Span %d already has minunused of %d.\n", span + 1, conf->pri.pri.minunused);
12577                      destroy_dahdi_pvt(tmp);
12578                      return NULL;
12579                   }
12580                   if (pris[span].pri.minidle && (pris[span].pri.minidle != conf->pri.pri.minidle)) {
12581                      ast_log(LOG_ERROR, "Span %d already has minidle of %d.\n", span + 1, conf->pri.pri.minidle);
12582                      destroy_dahdi_pvt(tmp);
12583                      return NULL;
12584                   }
12585                   if (pris[span].pri.numchans >= ARRAY_LEN(pris[span].pri.pvts)) {
12586                      ast_log(LOG_ERROR, "Unable to add channel %d: Too many channels in trunk group %d!\n", channel,
12587                         pris[span].pri.trunkgroup);
12588                      destroy_dahdi_pvt(tmp);
12589                      return NULL;
12590                   }
12591 
12592                   ast_debug(4, "Adding callbacks %p to chan %d\n", &dahdi_pri_callbacks, tmp->channel);
12593                   pri_chan = sig_pri_chan_new(tmp, &dahdi_pri_callbacks, &pris[span].pri, tmp->logicalspan, p.chanpos, pris[span].mastertrunkgroup);
12594                   if (!pri_chan) {
12595                      destroy_dahdi_pvt(tmp);
12596                      return NULL;
12597                   }
12598                   tmp->sig_pvt = pri_chan;
12599                   tmp->pri = &pris[span].pri;
12600 
12601                   tmp->priexclusive = conf->chan.priexclusive;
12602 
12603                   if (!tmp->pri->cc_params) {
12604                      tmp->pri->cc_params = ast_cc_config_params_init();
12605                      if (!tmp->pri->cc_params) {
12606                         destroy_dahdi_pvt(tmp);
12607                         return NULL;
12608                      }
12609                   }
12610                   ast_cc_copy_config_params(tmp->pri->cc_params,
12611                      conf->chan.cc_params);
12612 
12613                   pris[span].pri.sig = chan_sig;
12614                   pris[span].pri.nodetype = conf->pri.pri.nodetype;
12615                   pris[span].pri.switchtype = myswitchtype;
12616                   pris[span].pri.nsf = conf->pri.pri.nsf;
12617                   pris[span].pri.dialplan = conf->pri.pri.dialplan;
12618                   pris[span].pri.localdialplan = conf->pri.pri.localdialplan;
12619                   pris[span].pri.pvts[pris[span].pri.numchans++] = tmp->sig_pvt;
12620                   pris[span].pri.minunused = conf->pri.pri.minunused;
12621                   pris[span].pri.minidle = conf->pri.pri.minidle;
12622                   pris[span].pri.overlapdial = conf->pri.pri.overlapdial;
12623                   pris[span].pri.qsigchannelmapping = conf->pri.pri.qsigchannelmapping;
12624                   pris[span].pri.discardremoteholdretrieval = conf->pri.pri.discardremoteholdretrieval;
12625 #if defined(HAVE_PRI_SERVICE_MESSAGES)
12626                   pris[span].pri.enable_service_message_support = conf->pri.pri.enable_service_message_support;
12627 #endif   /* defined(HAVE_PRI_SERVICE_MESSAGES) */
12628 #ifdef HAVE_PRI_INBANDDISCONNECT
12629                   pris[span].pri.inbanddisconnect = conf->pri.pri.inbanddisconnect;
12630 #endif
12631 #if defined(HAVE_PRI_CALL_HOLD)
12632                   pris[span].pri.hold_disconnect_transfer =
12633                      conf->pri.pri.hold_disconnect_transfer;
12634 #endif   /* defined(HAVE_PRI_CALL_HOLD) */
12635 #if defined(HAVE_PRI_CCSS)
12636                   pris[span].pri.cc_ptmp_recall_mode =
12637                      conf->pri.pri.cc_ptmp_recall_mode;
12638                   pris[span].pri.cc_qsig_signaling_link_req =
12639                      conf->pri.pri.cc_qsig_signaling_link_req;
12640                   pris[span].pri.cc_qsig_signaling_link_rsp =
12641                      conf->pri.pri.cc_qsig_signaling_link_rsp;
12642 #endif   /* defined(HAVE_PRI_CCSS) */
12643 #if defined(HAVE_PRI_CALL_WAITING)
12644                   pris[span].pri.max_call_waiting_calls =
12645                      conf->pri.pri.max_call_waiting_calls;
12646                   pris[span].pri.allow_call_waiting_calls =
12647                      conf->pri.pri.allow_call_waiting_calls;
12648 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
12649                   pris[span].pri.transfer = conf->chan.transfer;
12650                   pris[span].pri.facilityenable = conf->pri.pri.facilityenable;
12651 #if defined(HAVE_PRI_L2_PERSISTENCE)
12652                   pris[span].pri.l2_persistence = conf->pri.pri.l2_persistence;
12653 #endif   /* defined(HAVE_PRI_L2_PERSISTENCE) */
12654 #if defined(HAVE_PRI_AOC_EVENTS)
12655                   pris[span].pri.aoc_passthrough_flag = conf->pri.pri.aoc_passthrough_flag;
12656                   pris[span].pri.aoce_delayhangup = conf->pri.pri.aoce_delayhangup;
12657 #endif   /* defined(HAVE_PRI_AOC_EVENTS) */
12658                   if (chan_sig == SIG_BRI_PTMP) {
12659                      pris[span].pri.layer1_ignored = conf->pri.pri.layer1_ignored;
12660                   } else {
12661                      /* Option does not apply to this line type. */
12662                      pris[span].pri.layer1_ignored = 0;
12663                   }
12664                   pris[span].pri.append_msn_to_user_tag = conf->pri.pri.append_msn_to_user_tag;
12665                   ast_copy_string(pris[span].pri.initial_user_tag, conf->chan.cid_tag, sizeof(pris[span].pri.initial_user_tag));
12666                   ast_copy_string(pris[span].pri.msn_list, conf->pri.pri.msn_list, sizeof(pris[span].pri.msn_list));
12667 #if defined(HAVE_PRI_MWI)
12668                   ast_copy_string(pris[span].pri.mwi_mailboxes,
12669                      conf->pri.pri.mwi_mailboxes,
12670                      sizeof(pris[span].pri.mwi_mailboxes));
12671 #endif   /* defined(HAVE_PRI_MWI) */
12672                   ast_copy_string(pris[span].pri.idledial, conf->pri.pri.idledial, sizeof(pris[span].pri.idledial));
12673                   ast_copy_string(pris[span].pri.idleext, conf->pri.pri.idleext, sizeof(pris[span].pri.idleext));
12674                   ast_copy_string(pris[span].pri.internationalprefix, conf->pri.pri.internationalprefix, sizeof(pris[span].pri.internationalprefix));
12675                   ast_copy_string(pris[span].pri.nationalprefix, conf->pri.pri.nationalprefix, sizeof(pris[span].pri.nationalprefix));
12676                   ast_copy_string(pris[span].pri.localprefix, conf->pri.pri.localprefix, sizeof(pris[span].pri.localprefix));
12677                   ast_copy_string(pris[span].pri.privateprefix, conf->pri.pri.privateprefix, sizeof(pris[span].pri.privateprefix));
12678                   ast_copy_string(pris[span].pri.unknownprefix, conf->pri.pri.unknownprefix, sizeof(pris[span].pri.unknownprefix));
12679                   pris[span].pri.resetinterval = conf->pri.pri.resetinterval;
12680 
12681                   for (x = 0; x < PRI_MAX_TIMERS; x++) {
12682                      pris[span].pri.pritimers[x] = conf->pri.pri.pritimers[x];
12683                   }
12684 
12685 #if defined(HAVE_PRI_CALL_WAITING)
12686                   /* Channel initial config parameters. */
12687                   pris[span].pri.ch_cfg.stripmsd = conf->chan.stripmsd;
12688                   pris[span].pri.ch_cfg.hidecallerid = conf->chan.hidecallerid;
12689                   pris[span].pri.ch_cfg.hidecalleridname = conf->chan.hidecalleridname;
12690                   pris[span].pri.ch_cfg.immediate = conf->chan.immediate;
12691                   pris[span].pri.ch_cfg.priexclusive = conf->chan.priexclusive;
12692                   pris[span].pri.ch_cfg.priindication_oob = conf->chan.priindication_oob;
12693                   pris[span].pri.ch_cfg.use_callerid = conf->chan.use_callerid;
12694                   pris[span].pri.ch_cfg.use_callingpres = conf->chan.use_callingpres;
12695                   ast_copy_string(pris[span].pri.ch_cfg.context, conf->chan.context, sizeof(pris[span].pri.ch_cfg.context));
12696                   ast_copy_string(pris[span].pri.ch_cfg.mohinterpret, conf->chan.mohinterpret, sizeof(pris[span].pri.ch_cfg.mohinterpret));
12697 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
12698                } else {
12699                   ast_log(LOG_ERROR, "Channel %d is reserved for D-channel.\n", p.chanpos);
12700                   destroy_dahdi_pvt(tmp);
12701                   return NULL;
12702                }
12703             }
12704          }
12705 #endif
12706       } else {
12707          /* already exists in interface list */
12708          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));
12709          chan_sig = tmp->sig;
12710          if (tmp->subs[SUB_REAL].dfd > -1) {
12711             memset(&p, 0, sizeof(p));
12712             res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
12713          }
12714       }
12715       /* Adjust starttime on loopstart and kewlstart trunks to reasonable values */
12716       switch (chan_sig) {
12717       case SIG_FXSKS:
12718       case SIG_FXSLS:
12719       case SIG_EM:
12720       case SIG_EM_E1:
12721       case SIG_EMWINK:
12722       case SIG_FEATD:
12723       case SIG_FEATDMF:
12724       case SIG_FEATDMF_TA:
12725       case SIG_FEATB:
12726       case SIG_E911:
12727       case SIG_SF:
12728       case SIG_SFWINK:
12729       case SIG_FGC_CAMA:
12730       case SIG_FGC_CAMAMF:
12731       case SIG_SF_FEATD:
12732       case SIG_SF_FEATDMF:
12733       case SIG_SF_FEATB:
12734          p.starttime = 250;
12735          break;
12736       }
12737 
12738       if (tmp->radio) {
12739          /* XXX Waiting to hear back from Jim if these should be adjustable XXX */
12740          p.channo = channel;
12741          p.rxwinktime = 1;
12742          p.rxflashtime = 1;
12743          p.starttime = 1;
12744          p.debouncetime = 5;
12745       } else {
12746          p.channo = channel;
12747          /* Override timing settings based on config file */
12748          if (conf->timing.prewinktime >= 0)
12749             p.prewinktime = conf->timing.prewinktime;
12750          if (conf->timing.preflashtime >= 0)
12751             p.preflashtime = conf->timing.preflashtime;
12752          if (conf->timing.winktime >= 0)
12753             p.winktime = conf->timing.winktime;
12754          if (conf->timing.flashtime >= 0)
12755             p.flashtime = conf->timing.flashtime;
12756          if (conf->timing.starttime >= 0)
12757             p.starttime = conf->timing.starttime;
12758          if (conf->timing.rxwinktime >= 0)
12759             p.rxwinktime = conf->timing.rxwinktime;
12760          if (conf->timing.rxflashtime >= 0)
12761             p.rxflashtime = conf->timing.rxflashtime;
12762          if (conf->timing.debouncetime >= 0)
12763             p.debouncetime = conf->timing.debouncetime;
12764       }
12765 
12766       /* don't set parms on a pseudo-channel */
12767       if (tmp->subs[SUB_REAL].dfd >= 0)
12768       {
12769          res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_PARAMS, &p);
12770          if (res < 0) {
12771             ast_log(LOG_ERROR, "Unable to set parameters: %s\n", strerror(errno));
12772             destroy_dahdi_pvt(tmp);
12773             return NULL;
12774          }
12775       }
12776 #if 1
12777       if (!here && (tmp->subs[SUB_REAL].dfd > -1)) {
12778          memset(&bi, 0, sizeof(bi));
12779          res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
12780          if (!res) {
12781             bi.txbufpolicy = conf->chan.buf_policy;
12782             bi.rxbufpolicy = conf->chan.buf_policy;
12783             bi.numbufs = conf->chan.buf_no;
12784             res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
12785             if (res < 0) {
12786                ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", channel, strerror(errno));
12787             }
12788          } else {
12789             ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", channel, strerror(errno));
12790          }
12791          tmp->buf_policy = conf->chan.buf_policy;
12792          tmp->buf_no = conf->chan.buf_no;
12793          tmp->usefaxbuffers = conf->chan.usefaxbuffers;
12794          tmp->faxbuf_policy = conf->chan.faxbuf_policy;
12795          tmp->faxbuf_no = conf->chan.faxbuf_no;
12796          /* This is not as gnarly as it may first appear.  If the ioctl above failed, we'd be setting
12797           * tmp->bufsize to zero which would cause subsequent faxbuffer-related ioctl calls to fail.
12798           * The reason the ioctl call above failed should to be determined before worrying about the
12799           * faxbuffer-related ioctl calls */
12800          tmp->bufsize = bi.bufsize;
12801       }
12802 #endif
12803       tmp->immediate = conf->chan.immediate;
12804       tmp->transfertobusy = conf->chan.transfertobusy;
12805       if (chan_sig & __DAHDI_SIG_FXS) {
12806          tmp->mwimonitor_fsk = conf->chan.mwimonitor_fsk;
12807          tmp->mwimonitor_neon = conf->chan.mwimonitor_neon;
12808          tmp->mwimonitor_rpas = conf->chan.mwimonitor_rpas;
12809       }
12810       tmp->ringt_base = ringt_base;
12811       tmp->firstradio = 0;
12812       if ((chan_sig == SIG_FXOKS) || (chan_sig == SIG_FXOLS) || (chan_sig == SIG_FXOGS))
12813          tmp->permcallwaiting = conf->chan.callwaiting;
12814       else
12815          tmp->permcallwaiting = 0;
12816       /* Flag to destroy the channel must be cleared on new mkif.  Part of changes for reload to work */
12817       tmp->destroy = 0;
12818       tmp->drings = conf->chan.drings;
12819 
12820       /* 10 is a nice default. */
12821       if (tmp->drings.ringnum[0].range == 0)
12822          tmp->drings.ringnum[0].range = 10;
12823       if (tmp->drings.ringnum[1].range == 0)
12824          tmp->drings.ringnum[1].range = 10;
12825       if (tmp->drings.ringnum[2].range == 0)
12826          tmp->drings.ringnum[2].range = 10;
12827 
12828       tmp->usedistinctiveringdetection = usedistinctiveringdetection;
12829       tmp->callwaitingcallerid = conf->chan.callwaitingcallerid;
12830       tmp->threewaycalling = conf->chan.threewaycalling;
12831       tmp->adsi = conf->chan.adsi;
12832       tmp->use_smdi = conf->chan.use_smdi;
12833       tmp->permhidecallerid = conf->chan.hidecallerid;
12834       tmp->hidecalleridname = conf->chan.hidecalleridname;
12835       tmp->callreturn = conf->chan.callreturn;
12836       tmp->echocancel = conf->chan.echocancel;
12837       tmp->echotraining = conf->chan.echotraining;
12838       tmp->pulse = conf->chan.pulse;
12839       if (tmp->echocancel.head.tap_length) {
12840          tmp->echocanbridged = conf->chan.echocanbridged;
12841       } else {
12842          if (conf->chan.echocanbridged)
12843             ast_log(LOG_NOTICE, "echocancelwhenbridged requires echocancel to be enabled; ignoring\n");
12844          tmp->echocanbridged = 0;
12845       }
12846       tmp->busydetect = conf->chan.busydetect;
12847       tmp->busycount = conf->chan.busycount;
12848       tmp->busycompare = conf->chan.busycompare;
12849       tmp->busytonelength = conf->chan.busytonelength;
12850       tmp->busyquietlength = conf->chan.busyquietlength;
12851       tmp->busyfuzziness = conf->chan.busyfuzziness;
12852       tmp->silencethreshold = conf->chan.silencethreshold;
12853       tmp->callprogress = conf->chan.callprogress;
12854       tmp->waitfordialtone = conf->chan.waitfordialtone;
12855       tmp->cancallforward = conf->chan.cancallforward;
12856       tmp->dtmfrelax = conf->chan.dtmfrelax;
12857       tmp->callwaiting = tmp->permcallwaiting;
12858       tmp->hidecallerid = tmp->permhidecallerid;
12859       tmp->channel = channel;
12860       tmp->stripmsd = conf->chan.stripmsd;
12861       tmp->use_callerid = conf->chan.use_callerid;
12862       tmp->cid_signalling = conf->chan.cid_signalling;
12863       tmp->cid_start = conf->chan.cid_start;
12864       tmp->dahditrcallerid = conf->chan.dahditrcallerid;
12865       tmp->restrictcid = conf->chan.restrictcid;
12866       tmp->use_callingpres = conf->chan.use_callingpres;
12867       if (tmp->usedistinctiveringdetection) {
12868          if (!tmp->use_callerid) {
12869             ast_log(LOG_NOTICE, "Distinctive Ring detect requires 'usecallerid' be on\n");
12870             tmp->use_callerid = 1;
12871          }
12872       }
12873 
12874       if (tmp->cid_signalling == CID_SIG_SMDI) {
12875          if (!tmp->use_smdi) {
12876             ast_log(LOG_WARNING, "SMDI callerid requires SMDI to be enabled, enabling...\n");
12877             tmp->use_smdi = 1;
12878          }
12879       }
12880       if (tmp->use_smdi) {
12881          tmp->smdi_iface = ast_smdi_interface_find(conf->smdi_port);
12882          if (!(tmp->smdi_iface)) {
12883             ast_log(LOG_ERROR, "Invalid SMDI port specfied, disabling SMDI support\n");
12884             tmp->use_smdi = 0;
12885          }
12886       }
12887 
12888       ast_copy_string(tmp->accountcode, conf->chan.accountcode, sizeof(tmp->accountcode));
12889       tmp->amaflags = conf->chan.amaflags;
12890       if (!here) {
12891          tmp->confno = -1;
12892          tmp->propconfno = -1;
12893       }
12894       tmp->canpark = conf->chan.canpark;
12895       tmp->transfer = conf->chan.transfer;
12896       ast_copy_string(tmp->defcontext,conf->chan.context,sizeof(tmp->defcontext));
12897       ast_copy_string(tmp->language, conf->chan.language, sizeof(tmp->language));
12898       ast_copy_string(tmp->mohinterpret, conf->chan.mohinterpret, sizeof(tmp->mohinterpret));
12899       ast_copy_string(tmp->mohsuggest, conf->chan.mohsuggest, sizeof(tmp->mohsuggest));
12900       ast_copy_string(tmp->context, conf->chan.context, sizeof(tmp->context));
12901       ast_copy_string(tmp->parkinglot, conf->chan.parkinglot, sizeof(tmp->parkinglot));
12902       tmp->cid_ton = 0;
12903       if (analog_lib_handles(tmp->sig, tmp->radio, tmp->oprmode)) {
12904          ast_copy_string(tmp->cid_num, conf->chan.cid_num, sizeof(tmp->cid_num));
12905          ast_copy_string(tmp->cid_name, conf->chan.cid_name, sizeof(tmp->cid_name));
12906       } else {
12907          tmp->cid_num[0] = '\0';
12908          tmp->cid_name[0] = '\0';
12909       }
12910 #if defined(HAVE_PRI)
12911       if (dahdi_sig_pri_lib_handles(tmp->sig)) {
12912          tmp->cid_tag[0] = '\0';
12913       } else
12914 #endif   /* defined(HAVE_PRI) */
12915       {
12916          ast_copy_string(tmp->cid_tag, conf->chan.cid_tag, sizeof(tmp->cid_tag));
12917       }
12918       tmp->cid_subaddr[0] = '\0';
12919       ast_copy_string(tmp->mailbox, conf->chan.mailbox, sizeof(tmp->mailbox));
12920       if (channel != CHAN_PSEUDO && !ast_strlen_zero(tmp->mailbox)) {
12921          char *mailbox, *context;
12922          mailbox = context = ast_strdupa(tmp->mailbox);
12923          strsep(&context, "@");
12924          if (ast_strlen_zero(context))
12925             context = "default";
12926          tmp->mwi_event_sub = ast_event_subscribe(AST_EVENT_MWI, mwi_event_cb, "Dahdi MWI subscription", NULL,
12927             AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
12928             AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
12929             AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS,
12930             AST_EVENT_IE_END);
12931       }
12932 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
12933       tmp->mwisend_setting = conf->chan.mwisend_setting;
12934       tmp->mwisend_fsk  = conf->chan.mwisend_fsk;
12935       tmp->mwisend_rpas = conf->chan.mwisend_rpas;
12936 #endif
12937 
12938       tmp->group = conf->chan.group;
12939       tmp->callgroup = conf->chan.callgroup;
12940       tmp->pickupgroup= conf->chan.pickupgroup;
12941       if (conf->chan.vars) {
12942          struct ast_variable *v, *tmpvar;
12943                    for (v = conf->chan.vars ; v ; v = v->next) {
12944                          if ((tmpvar = ast_variable_new(v->name, v->value, v->file))) {
12945                                   tmpvar->next = tmp->vars;
12946                                    tmp->vars = tmpvar;
12947                            }
12948                   }
12949       }
12950       tmp->cid_rxgain = conf->chan.cid_rxgain;
12951       tmp->rxgain = conf->chan.rxgain;
12952       tmp->txgain = conf->chan.txgain;
12953       tmp->txdrc = conf->chan.txdrc;
12954       tmp->rxdrc = conf->chan.rxdrc;
12955       tmp->tonezone = conf->chan.tonezone;
12956       if (tmp->subs[SUB_REAL].dfd > -1) {
12957          set_actual_gain(tmp->subs[SUB_REAL].dfd, tmp->rxgain, tmp->txgain, tmp->rxdrc, tmp->txdrc, tmp->law);
12958          if (tmp->dsp)
12959             ast_dsp_set_digitmode(tmp->dsp, DSP_DIGITMODE_DTMF | tmp->dtmfrelax);
12960          update_conf(tmp);
12961          if (!here) {
12962             switch (chan_sig) {
12963             case SIG_PRI_LIB_HANDLE_CASES:
12964             case SIG_SS7:
12965             case SIG_MFCR2:
12966                break;
12967             default:
12968                /* Hang it up to be sure it's good */
12969                dahdi_set_hook(tmp->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
12970                break;
12971             }
12972          }
12973          ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SETTONEZONE,&tmp->tonezone);
12974          if ((res = get_alarms(tmp)) != DAHDI_ALARM_NONE) {
12975             /* the dchannel is down so put the channel in alarm */
12976             switch (tmp->sig) {
12977 #ifdef HAVE_PRI
12978             case SIG_PRI_LIB_HANDLE_CASES:
12979                sig_pri_set_alarm(tmp->sig_pvt, 1);
12980                break;
12981 #endif
12982 #if defined(HAVE_SS7)
12983             case SIG_SS7:
12984                sig_ss7_set_alarm(tmp->sig_pvt, 1);
12985                break;
12986 #endif   /* defined(HAVE_SS7) */
12987             default:
12988                /* The only sig submodule left should be sig_analog. */
12989                analog_p = tmp->sig_pvt;
12990                if (analog_p) {
12991                   analog_p->inalarm = 1;
12992                }
12993                tmp->inalarm = 1;
12994                break;
12995             }
12996             handle_alarms(tmp, res);
12997          }
12998       }
12999 
13000       tmp->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
13001       tmp->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
13002       tmp->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
13003       tmp->sendcalleridafter = conf->chan.sendcalleridafter;
13004       ast_cc_copy_config_params(tmp->cc_params, conf->chan.cc_params);
13005 
13006       if (!here) {
13007          tmp->locallyblocked = 0;
13008          tmp->remotelyblocked = 0;
13009          switch (tmp->sig) {
13010 #if defined(HAVE_PRI)
13011          case SIG_PRI_LIB_HANDLE_CASES:
13012             tmp->inservice = 1;/* Inservice until actually implemented. */
13013 #if defined(HAVE_PRI_SERVICE_MESSAGES)
13014             ((struct sig_pri_chan *) tmp->sig_pvt)->service_status = 0;
13015             if (chan_sig == SIG_PRI) {
13016                char db_chan_name[20];
13017                char db_answer[5];
13018 
13019                /*
13020                 * Initialize the active out-of-service status
13021                 * and delete any record if the feature is not enabled.
13022                 */
13023                snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, tmp->span, tmp->channel);
13024                if (!ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) {
13025                   unsigned *why;
13026 
13027                   why = &((struct sig_pri_chan *) tmp->sig_pvt)->service_status;
13028                   if (tmp->pri->enable_service_message_support) {
13029                      char state;
13030 
13031                      sscanf(db_answer, "%1c:%30u", &state, why);
13032 
13033                      /* Ensure that only the implemented bits could be set.*/
13034                      *why &= (SRVST_NEAREND | SRVST_FAREND);
13035                   }
13036                   if (!*why) {
13037                      ast_db_del(db_chan_name, SRVST_DBKEY);
13038                   }
13039                }
13040             }
13041 #endif   /* defined(HAVE_PRI_SERVICE_MESSAGES) */
13042             break;
13043 #endif   /* defined(HAVE_PRI) */
13044 #if defined(HAVE_SS7)
13045          case SIG_SS7:
13046             tmp->inservice = 0;
13047             break;
13048 #endif   /* defined(HAVE_SS7) */
13049          default:
13050              /* We default to in service on protocols that don't have a reset */
13051             tmp->inservice = 1;
13052             break;
13053          }
13054       }
13055 
13056       switch (tmp->sig) {
13057 #if defined(HAVE_PRI)
13058       case SIG_PRI_LIB_HANDLE_CASES:
13059          if (pri_chan) {
13060             pri_chan->channel = tmp->channel;
13061             pri_chan->hidecallerid = tmp->hidecallerid;
13062             pri_chan->hidecalleridname = tmp->hidecalleridname;
13063             pri_chan->immediate = tmp->immediate;
13064             pri_chan->inalarm = tmp->inalarm;
13065             pri_chan->priexclusive = tmp->priexclusive;
13066             pri_chan->priindication_oob = tmp->priindication_oob;
13067             pri_chan->use_callerid = tmp->use_callerid;
13068             pri_chan->use_callingpres = tmp->use_callingpres;
13069             ast_copy_string(pri_chan->context, tmp->context,
13070                sizeof(pri_chan->context));
13071             ast_copy_string(pri_chan->mohinterpret, tmp->mohinterpret,
13072                sizeof(pri_chan->mohinterpret));
13073             pri_chan->stripmsd = tmp->stripmsd;
13074          }
13075          break;
13076 #endif   /* defined(HAVE_PRI) */
13077 #if defined(HAVE_SS7)
13078       case SIG_SS7:
13079          if (ss7_chan) {
13080             ss7_chan->inalarm = tmp->inalarm;
13081 
13082             ss7_chan->stripmsd = tmp->stripmsd;
13083             ss7_chan->hidecallerid = tmp->hidecallerid;
13084             ss7_chan->use_callerid = tmp->use_callerid;
13085             ss7_chan->use_callingpres = tmp->use_callingpres;
13086             ss7_chan->immediate = tmp->immediate;
13087             ss7_chan->locallyblocked = tmp->locallyblocked;
13088             ss7_chan->remotelyblocked = tmp->remotelyblocked;
13089             ast_copy_string(ss7_chan->context, tmp->context,
13090                sizeof(ss7_chan->context));
13091             ast_copy_string(ss7_chan->mohinterpret, tmp->mohinterpret,
13092                sizeof(ss7_chan->mohinterpret));
13093          }
13094          break;
13095 #endif   /* defined(HAVE_SS7) */
13096       default:
13097          /* The only sig submodule left should be sig_analog. */
13098          analog_p = tmp->sig_pvt;
13099          if (analog_p) {
13100             analog_p->channel = tmp->channel;
13101             analog_p->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
13102             analog_p->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
13103             analog_p->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
13104             analog_p->permcallwaiting = conf->chan.callwaiting; /* permcallwaiting possibly modified in analog_config_complete */
13105             analog_p->callreturn = conf->chan.callreturn;
13106             analog_p->cancallforward = conf->chan.cancallforward;
13107             analog_p->canpark = conf->chan.canpark;
13108             analog_p->dahditrcallerid = conf->chan.dahditrcallerid;
13109             analog_p->immediate = conf->chan.immediate;
13110             analog_p->permhidecallerid = conf->chan.permhidecallerid;
13111             analog_p->pulse = conf->chan.pulse;
13112             analog_p->threewaycalling = conf->chan.threewaycalling;
13113             analog_p->transfer = conf->chan.transfer;
13114             analog_p->transfertobusy = conf->chan.transfertobusy;
13115             analog_p->use_callerid = tmp->use_callerid;
13116             analog_p->use_smdi = tmp->use_smdi;
13117             analog_p->smdi_iface = tmp->smdi_iface;
13118             analog_p->outsigmod = ANALOG_SIG_NONE;
13119             analog_p->echotraining = conf->chan.echotraining;
13120             analog_p->cid_signalling = conf->chan.cid_signalling;
13121             analog_p->stripmsd = conf->chan.stripmsd;
13122             switch (conf->chan.cid_start) {
13123             case CID_START_POLARITY:
13124                analog_p->cid_start = ANALOG_CID_START_POLARITY;
13125                break;
13126             case CID_START_POLARITY_IN:
13127                analog_p->cid_start = ANALOG_CID_START_POLARITY_IN;
13128                break;
13129             case CID_START_DTMF_NOALERT:
13130                analog_p->cid_start = ANALOG_CID_START_DTMF_NOALERT;
13131                break;
13132             default:
13133                analog_p->cid_start = ANALOG_CID_START_RING;
13134                break;
13135             }
13136             analog_p->callwaitingcallerid = conf->chan.callwaitingcallerid;
13137             analog_p->ringt = conf->chan.ringt;
13138             analog_p->ringt_base = ringt_base;
13139             analog_p->chan_tech = &dahdi_tech;
13140             analog_p->onhooktime = time(NULL);
13141             if (chan_sig & __DAHDI_SIG_FXO) {
13142                memset(&p, 0, sizeof(p));
13143                res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
13144                if (!res) {
13145                   analog_p->fxsoffhookstate = p.rxisoffhook;
13146                }
13147 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
13148                res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_VMWI_CONFIG, &tmp->mwisend_setting);
13149 #endif
13150             }
13151             analog_p->msgstate = -1;
13152 
13153             ast_copy_string(analog_p->mohsuggest, conf->chan.mohsuggest, sizeof(analog_p->mohsuggest));
13154             ast_copy_string(analog_p->cid_num, conf->chan.cid_num, sizeof(analog_p->cid_num));
13155             ast_copy_string(analog_p->cid_name, conf->chan.cid_name, sizeof(analog_p->cid_name));
13156 
13157             analog_config_complete(analog_p);
13158          }
13159          break;
13160       }
13161 #if defined(HAVE_PRI)
13162       if (tmp->channel == CHAN_PSEUDO) {
13163          /*
13164           * Save off pseudo channel buffer policy values for dynamic creation of
13165           * no B channel interfaces.
13166           */
13167          dahdi_pseudo_parms.buf_no = tmp->buf_no;
13168          dahdi_pseudo_parms.buf_policy = tmp->buf_policy;
13169          dahdi_pseudo_parms.faxbuf_no = tmp->faxbuf_no;
13170          dahdi_pseudo_parms.faxbuf_policy = tmp->faxbuf_policy;
13171       }
13172 #endif   /* defined(HAVE_PRI) */
13173    }
13174    if (tmp && !here) {
13175       /* Add the new channel interface to the sorted channel interface list. */
13176       dahdi_iflist_insert(tmp);
13177    }
13178    return tmp;
13179 }
13180 
13181 static int is_group_or_channel_match(struct dahdi_pvt *p, int span, ast_group_t groupmatch, int *groupmatched, int channelmatch, int *channelmatched)
13182 {
13183 #if defined(HAVE_PRI)
13184    if (0 < span) {
13185       /* The channel must be on the specified PRI span. */
13186       if (!p->pri || p->pri->span != span) {
13187          return 0;
13188       }
13189       if (!groupmatch && channelmatch == -1) {
13190          /* Match any group since it only needs to be on the PRI span. */
13191          *groupmatched = 1;
13192          return 1;
13193       }
13194    }
13195 #endif   /* defined(HAVE_PRI) */
13196    /* check group matching */
13197    if (groupmatch) {
13198       if ((p->group & groupmatch) != groupmatch)
13199          /* Doesn't match the specified group, try the next one */
13200          return 0;
13201       *groupmatched = 1;
13202    }
13203    /* Check to see if we have a channel match */
13204    if (channelmatch != -1) {
13205       if (p->channel != channelmatch)
13206          /* Doesn't match the specified channel, try the next one */
13207          return 0;
13208       *channelmatched = 1;
13209    }
13210 
13211    return 1;
13212 }
13213 
13214 static int available(struct dahdi_pvt **pvt, int is_specific_channel)
13215 {
13216    struct dahdi_pvt *p = *pvt;
13217 
13218    if (p->inalarm)
13219       return 0;
13220 
13221    if (analog_lib_handles(p->sig, p->radio, p->oprmode))
13222       return analog_available(p->sig_pvt);
13223 
13224    switch (p->sig) {
13225 #if defined(HAVE_PRI)
13226    case SIG_PRI_LIB_HANDLE_CASES:
13227       {
13228          struct sig_pri_chan *pvt_chan;
13229          int res;
13230 
13231          pvt_chan = p->sig_pvt;
13232          res = sig_pri_available(&pvt_chan, is_specific_channel);
13233          *pvt = pvt_chan->chan_pvt;
13234          return res;
13235       }
13236 #endif   /* defined(HAVE_PRI) */
13237 #if defined(HAVE_SS7)
13238    case SIG_SS7:
13239       return sig_ss7_available(p->sig_pvt);
13240 #endif   /* defined(HAVE_SS7) */
13241    default:
13242       break;
13243    }
13244 
13245    if (p->locallyblocked || p->remotelyblocked) {
13246       return 0;
13247    }
13248 
13249    /* If no owner definitely available */
13250    if (!p->owner) {
13251 #ifdef HAVE_OPENR2
13252       /* Trust MFC/R2 */
13253       if (p->mfcr2) {
13254          if (p->mfcr2call) {
13255             return 0;
13256          } else {
13257             return 1;
13258          }
13259       }
13260 #endif
13261       return 1;
13262    }
13263 
13264    return 0;
13265 }
13266 
13267 #if defined(HAVE_PRI)
13268 #if defined(HAVE_PRI_CALL_WAITING)
13269 /*!
13270  * \internal
13271  * \brief Init the private channel configuration using the span controller.
13272  * \since 1.8
13273  *
13274  * \param priv Channel to init the configuration.
13275  * \param pri sig_pri PRI control structure.
13276  *
13277  * \note Assumes the pri->lock is already obtained.
13278  *
13279  * \return Nothing
13280  */
13281 static void my_pri_init_config(void *priv, struct sig_pri_span *pri)
13282 {
13283    struct dahdi_pvt *pvt = priv;
13284 
13285    pvt->stripmsd = pri->ch_cfg.stripmsd;
13286    pvt->hidecallerid = pri->ch_cfg.hidecallerid;
13287    pvt->hidecalleridname = pri->ch_cfg.hidecalleridname;
13288    pvt->immediate = pri->ch_cfg.immediate;
13289    pvt->priexclusive = pri->ch_cfg.priexclusive;
13290    pvt->priindication_oob = pri->ch_cfg.priindication_oob;
13291    pvt->use_callerid = pri->ch_cfg.use_callerid;
13292    pvt->use_callingpres = pri->ch_cfg.use_callingpres;
13293    ast_copy_string(pvt->context, pri->ch_cfg.context, sizeof(pvt->context));
13294    ast_copy_string(pvt->mohinterpret, pri->ch_cfg.mohinterpret, sizeof(pvt->mohinterpret));
13295 }
13296 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
13297 #endif   /* defined(HAVE_PRI) */
13298 
13299 #if defined(HAVE_PRI)
13300 /*!
13301  * \internal
13302  * \brief Create a no B channel interface.
13303  * \since 1.8
13304  *
13305  * \param pri sig_pri span controller to add interface.
13306  *
13307  * \note Assumes the pri->lock is already obtained.
13308  *
13309  * \retval array-index into private pointer array on success.
13310  * \retval -1 on error.
13311  */
13312 static int dahdi_new_pri_nobch_channel(struct sig_pri_span *pri)
13313 {
13314    int pvt_idx;
13315    int res;
13316    unsigned idx;
13317    struct dahdi_pvt *pvt;
13318    struct sig_pri_chan *chan;
13319    struct dahdi_bufferinfo bi;
13320 
13321    static int nobch_channel = CHAN_PSEUDO;
13322 
13323    /* Find spot in the private pointer array for new interface. */
13324    for (pvt_idx = 0; pvt_idx < pri->numchans; ++pvt_idx) {
13325       if (!pri->pvts[pvt_idx]) {
13326          break;
13327       }
13328    }
13329    if (pri->numchans == pvt_idx) {
13330       if (ARRAY_LEN(pri->pvts) <= pvt_idx) {
13331          ast_log(LOG_ERROR, "Unable to add a no-B-channel interface!\n");
13332          return -1;
13333       }
13334 
13335       /* Add new spot to the private pointer array. */
13336       pri->pvts[pvt_idx] = NULL;
13337       ++pri->numchans;
13338    }
13339 
13340    pvt = ast_calloc(1, sizeof(*pvt));
13341    if (!pvt) {
13342       return -1;
13343    }
13344    pvt->cc_params = ast_cc_config_params_init();
13345    if (!pvt->cc_params) {
13346       ast_free(pvt);
13347       return -1;
13348    }
13349    ast_mutex_init(&pvt->lock);
13350    for (idx = 0; idx < ARRAY_LEN(pvt->subs); ++idx) {
13351       pvt->subs[idx].dfd = -1;
13352    }
13353    pvt->buf_no = dahdi_pseudo_parms.buf_no;
13354    pvt->buf_policy = dahdi_pseudo_parms.buf_policy;
13355    pvt->faxbuf_no = dahdi_pseudo_parms.faxbuf_no;
13356    pvt->faxbuf_policy = dahdi_pseudo_parms.faxbuf_policy;
13357 
13358    chan = sig_pri_chan_new(pvt, &dahdi_pri_callbacks, pri, 0, 0, 0);
13359    if (!chan) {
13360       destroy_dahdi_pvt(pvt);
13361       return -1;
13362    }
13363    chan->no_b_channel = 1;
13364 
13365    /*
13366     * Pseudo channel companding law.
13367     * Needed for outgoing call waiting calls.
13368     * XXX May need to make this determined by switchtype or user option.
13369     */
13370    pvt->law_default = DAHDI_LAW_ALAW;
13371 
13372    pvt->sig = pri->sig;
13373    pvt->outsigmod = -1;
13374    pvt->pri = pri;
13375    pvt->sig_pvt = chan;
13376    pri->pvts[pvt_idx] = chan;
13377 
13378    pvt->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo");
13379    if (pvt->subs[SUB_REAL].dfd < 0) {
13380       ast_log(LOG_ERROR, "Unable to open no B channel interface pseudo channel: %s\n",
13381          strerror(errno));
13382       destroy_dahdi_pvt(pvt);
13383       return -1;
13384    }
13385    memset(&bi, 0, sizeof(bi));
13386    res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
13387    if (!res) {
13388       pvt->bufsize = bi.bufsize;
13389       bi.txbufpolicy = pvt->buf_policy;
13390       bi.rxbufpolicy = pvt->buf_policy;
13391       bi.numbufs = pvt->buf_no;
13392       res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
13393       if (res < 0) {
13394          ast_log(LOG_WARNING,
13395             "Unable to set buffer policy on no B channel interface: %s\n",
13396             strerror(errno));
13397       }
13398    } else
13399       ast_log(LOG_WARNING,
13400          "Unable to check buffer policy on no B channel interface: %s\n",
13401          strerror(errno));
13402 
13403    --nobch_channel;
13404    if (CHAN_PSEUDO < nobch_channel) {
13405       nobch_channel = CHAN_PSEUDO - 1;
13406    }
13407    pvt->channel = nobch_channel;
13408    pvt->span = pri->span;
13409    chan->channel = pvt->channel;
13410 
13411    dahdi_nobch_insert(pri, pvt);
13412 
13413    return pvt_idx;
13414 }
13415 #endif   /* defined(HAVE_PRI) */
13416 
13417 /* This function can *ONLY* be used for copying pseudo (CHAN_PSEUDO) private
13418    structures; it makes no attempt to safely copy regular channel private
13419    structures that might contain reference-counted object pointers and other
13420    scary bits
13421 */
13422 static struct dahdi_pvt *duplicate_pseudo(struct dahdi_pvt *src)
13423 {
13424    struct dahdi_pvt *p;
13425    struct dahdi_bufferinfo bi;
13426    int res;
13427 
13428    p = ast_malloc(sizeof(*p));
13429    if (!p) {
13430       return NULL;
13431    }
13432    *p = *src;
13433 
13434    /* Must deep copy the cc_params. */
13435    p->cc_params = ast_cc_config_params_init();
13436    if (!p->cc_params) {
13437       ast_free(p);
13438       return NULL;
13439    }
13440    ast_cc_copy_config_params(p->cc_params, src->cc_params);
13441 
13442    p->which_iflist = DAHDI_IFLIST_NONE;
13443    p->next = NULL;
13444    p->prev = NULL;
13445    ast_mutex_init(&p->lock);
13446    p->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo");
13447    if (p->subs[SUB_REAL].dfd < 0) {
13448       ast_log(LOG_ERROR, "Unable to dup channel: %s\n", strerror(errno));
13449       destroy_dahdi_pvt(p);
13450       return NULL;
13451    }
13452    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
13453    if (!res) {
13454       bi.txbufpolicy = src->buf_policy;
13455       bi.rxbufpolicy = src->buf_policy;
13456       bi.numbufs = src->buf_no;
13457       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
13458       if (res < 0) {
13459          ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel: %s\n", strerror(errno));
13460       }
13461    } else
13462       ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel: %s\n", strerror(errno));
13463    p->destroy = 1;
13464    dahdi_iflist_insert(p);
13465    return p;
13466 }
13467 
13468 struct dahdi_starting_point {
13469    /*! Group matching mask.  Zero if not specified. */
13470    ast_group_t groupmatch;
13471    /*! DAHDI channel to match with.  -1 if not specified. */
13472    int channelmatch;
13473    /*! Round robin saved search location index. (Valid if roundrobin TRUE) */
13474    int rr_starting_point;
13475    /*! ISDN span where channels can be picked (Zero if not specified) */
13476    int span;
13477    /*! Analog channel distinctive ring cadance index. */
13478    int cadance;
13479    /*! Dialing option. c/r/d if present and valid. */
13480    char opt;
13481    /*! TRUE if to search the channel list backwards. */
13482    char backwards;
13483    /*! TRUE if search is done with round robin sequence. */
13484    char roundrobin;
13485 };
13486 static struct dahdi_pvt *determine_starting_point(const char *data, struct dahdi_starting_point *param)
13487 {
13488    char *dest;
13489    char *s;
13490    int x;
13491    int res = 0;
13492    struct dahdi_pvt *p;
13493    char *subdir = NULL;
13494    AST_DECLARE_APP_ARGS(args,
13495       AST_APP_ARG(group);  /* channel/group token */
13496       //AST_APP_ARG(ext);  /* extension token */
13497       //AST_APP_ARG(opts); /* options token */
13498       AST_APP_ARG(other);  /* Any remining unused arguments */
13499    );
13500 
13501    /*
13502     * data is ---v
13503     * Dial(DAHDI/pseudo[/extension[/options]])
13504     * Dial(DAHDI/<channel#>[c|r<cadance#>|d][/extension[/options]])
13505     * Dial(DAHDI/<subdir>!<channel#>[c|r<cadance#>|d][/extension[/options]])
13506     * Dial(DAHDI/i<span>[/extension[/options]])
13507     * Dial(DAHDI/[i<span>-](g|G|r|R)<group#(0-63)>[c|r<cadance#>|d][/extension[/options]])
13508     *
13509     * i - ISDN span channel restriction.
13510     *     Used by CC to ensure that the CC recall goes out the same span.
13511     *     Also to make ISDN channel names dialable when the sequence number
13512     *     is stripped off.  (Used by DTMF attended transfer feature.)
13513     *
13514     * g - channel group allocation search forward
13515     * G - channel group allocation search backward
13516     * r - channel group allocation round robin search forward
13517     * R - channel group allocation round robin search backward
13518     *
13519     * c - Wait for DTMF digit to confirm answer
13520     * r<cadance#> - Set distintive ring cadance number
13521     * d - Force bearer capability for ISDN/SS7 call to digital.
13522     */
13523 
13524    if (data) {
13525       dest = ast_strdupa(data);
13526    } else {
13527       ast_log(LOG_WARNING, "Channel requested with no data\n");
13528       return NULL;
13529    }
13530    AST_NONSTANDARD_APP_ARGS(args, dest, '/');
13531    if (!args.argc || ast_strlen_zero(args.group)) {
13532       ast_log(LOG_WARNING, "No channel/group specified\n");
13533       return NULL;
13534    }
13535 
13536    /* Initialize the output parameters */
13537    memset(param, 0, sizeof(*param));
13538    param->channelmatch = -1;
13539 
13540    if (strchr(args.group, '!') != NULL) {
13541       char *prev = args.group;
13542       while ((s = strchr(prev, '!')) != NULL) {
13543          *s++ = '/';
13544          prev = s;
13545       }
13546       *(prev - 1) = '\0';
13547       subdir = args.group;
13548       args.group = prev;
13549    } else if (args.group[0] == 'i') {
13550       /* Extract the ISDN span channel restriction specifier. */
13551       res = sscanf(args.group + 1, "%30d", &x);
13552       if (res < 1) {
13553          ast_log(LOG_WARNING, "Unable to determine ISDN span for data %s\n", data);
13554          return NULL;
13555       }
13556       param->span = x;
13557 
13558       /* Remove the ISDN span channel restriction specifier. */
13559       s = strchr(args.group, '-');
13560       if (!s) {
13561          /* Search all groups since we are ISDN span restricted. */
13562          return iflist;
13563       }
13564       args.group = s + 1;
13565       res = 0;
13566    }
13567    if (toupper(args.group[0]) == 'G' || toupper(args.group[0])=='R') {
13568       /* Retrieve the group number */
13569       s = args.group + 1;
13570       res = sscanf(s, "%30d%1c%30d", &x, &param->opt, &param->cadance);
13571       if (res < 1) {
13572          ast_log(LOG_WARNING, "Unable to determine group for data %s\n", data);
13573          return NULL;
13574       }
13575       param->groupmatch = ((ast_group_t) 1 << x);
13576 
13577       if (toupper(args.group[0]) == 'G') {
13578          if (args.group[0] == 'G') {
13579             param->backwards = 1;
13580             p = ifend;
13581          } else
13582             p = iflist;
13583       } else {
13584          if (ARRAY_LEN(round_robin) <= x) {
13585             ast_log(LOG_WARNING, "Round robin index %d out of range for data %s\n",
13586                x, data);
13587             return NULL;
13588          }
13589          if (args.group[0] == 'R') {
13590             param->backwards = 1;
13591             p = round_robin[x] ? round_robin[x]->prev : ifend;
13592             if (!p)
13593                p = ifend;
13594          } else {
13595             p = round_robin[x] ? round_robin[x]->next : iflist;
13596             if (!p)
13597                p = iflist;
13598          }
13599          param->roundrobin = 1;
13600          param->rr_starting_point = x;
13601       }
13602    } else {
13603       s = args.group;
13604       if (!strcasecmp(s, "pseudo")) {
13605          /* Special case for pseudo */
13606          x = CHAN_PSEUDO;
13607          param->channelmatch = x;
13608       } else {
13609          res = sscanf(s, "%30d%1c%30d", &x, &param->opt, &param->cadance);
13610          if (res < 1) {
13611             ast_log(LOG_WARNING, "Unable to determine channel for data %s\n", data);
13612             return NULL;
13613          } else {
13614             param->channelmatch = x;
13615          }
13616       }
13617       if (subdir) {
13618          char path[PATH_MAX];
13619          struct stat stbuf;
13620 
13621          snprintf(path, sizeof(path), "/dev/dahdi/%s/%d",
13622                subdir, param->channelmatch);
13623          if (stat(path, &stbuf) < 0) {
13624             ast_log(LOG_WARNING, "stat(%s) failed: %s\n",
13625                   path, strerror(errno));
13626             return NULL;
13627          }
13628          if (!S_ISCHR(stbuf.st_mode)) {
13629             ast_log(LOG_ERROR, "%s: Not a character device file\n",
13630                   path);
13631             return NULL;
13632          }
13633          param->channelmatch = minor(stbuf.st_rdev);
13634       }
13635 
13636       p = iflist;
13637    }
13638 
13639    if (param->opt == 'r' && res < 3) {
13640       ast_log(LOG_WARNING, "Distinctive ring missing identifier in '%s'\n", data);
13641       param->opt = '\0';
13642    }
13643 
13644    return p;
13645 }
13646 
13647 static struct ast_channel *dahdi_request(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause)
13648 {
13649    int callwait = 0;
13650    struct dahdi_pvt *p;
13651    struct ast_channel *tmp = NULL;
13652    struct dahdi_pvt *exitpvt;
13653    int channelmatched = 0;
13654    int groupmatched = 0;
13655 #if defined(HAVE_PRI) || defined(HAVE_SS7)
13656    int transcapdigital = 0;
13657 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
13658    struct dahdi_starting_point start;
13659 
13660    ast_mutex_lock(&iflock);
13661    p = determine_starting_point(data, &start);
13662    if (!p) {
13663       /* We couldn't determine a starting point, which likely means badly-formatted channel name. Abort! */
13664       ast_mutex_unlock(&iflock);
13665       return NULL;
13666    }
13667 
13668    /* Search for an unowned channel */
13669    exitpvt = p;
13670    while (p && !tmp) {
13671       if (start.roundrobin)
13672          round_robin[start.rr_starting_point] = p;
13673 
13674       if (is_group_or_channel_match(p, start.span, start.groupmatch, &groupmatched, start.channelmatch, &channelmatched)
13675          && available(&p, channelmatched)) {
13676          ast_debug(1, "Using channel %d\n", p->channel);
13677 
13678          callwait = (p->owner != NULL);
13679 #ifdef HAVE_OPENR2
13680          if (p->mfcr2) {
13681             ast_mutex_lock(&p->lock);
13682             if (p->mfcr2call) {
13683                ast_mutex_unlock(&p->lock);
13684                ast_log(LOG_DEBUG, "Yay!, someone just beat us in the race for channel %d.\n", p->channel);
13685                goto next;
13686             }
13687             p->mfcr2call = 1;
13688             ast_mutex_unlock(&p->lock);
13689          }
13690 #endif
13691          if (p->channel == CHAN_PSEUDO) {
13692             p = duplicate_pseudo(p);
13693             if (!p) {
13694                break;
13695             }
13696          }
13697 
13698          p->distinctivering = 0;
13699          /* Make special notes */
13700          switch (start.opt) {
13701          case '\0':
13702             /* No option present. */
13703             break;
13704          case 'c':
13705             /* Confirm answer */
13706             p->confirmanswer = 1;
13707             break;
13708          case 'r':
13709             /* Distinctive ring */
13710             p->distinctivering = start.cadance;
13711             break;
13712          case 'd':
13713 #if defined(HAVE_PRI) || defined(HAVE_SS7)
13714             /* If this is an ISDN call, make it digital */
13715             transcapdigital = AST_TRANS_CAP_DIGITAL;
13716 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
13717             break;
13718          default:
13719             ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", start.opt, (char *)data);
13720             break;
13721          }
13722 
13723          p->outgoing = 1;
13724          if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
13725             tmp = analog_request(p->sig_pvt, &callwait, requestor);
13726 #ifdef HAVE_PRI
13727          } else if (dahdi_sig_pri_lib_handles(p->sig)) {
13728             /*
13729              * We already have the B channel reserved for this call.  We
13730              * just need to make sure that dahdi_hangup() has completed
13731              * cleaning up before continuing.
13732              */
13733             ast_mutex_lock(&p->lock);
13734             ast_mutex_unlock(&p->lock);
13735 
13736             sig_pri_extract_called_num_subaddr(p->sig_pvt, data, p->dnid,
13737                sizeof(p->dnid));
13738             tmp = sig_pri_request(p->sig_pvt, SIG_PRI_DEFLAW, requestor, transcapdigital);
13739 #endif
13740 #if defined(HAVE_SS7)
13741          } else if (p->sig == SIG_SS7) {
13742             tmp = sig_ss7_request(p->sig_pvt, SIG_SS7_DEFLAW, requestor, transcapdigital);
13743 #endif   /* defined(HAVE_SS7) */
13744          } else {
13745             tmp = dahdi_new(p, AST_STATE_RESERVED, 0, p->owner ? SUB_CALLWAIT : SUB_REAL, 0, requestor ? requestor->linkedid : "");
13746          }
13747          if (!tmp) {
13748             p->outgoing = 0;
13749 #if defined(HAVE_PRI)
13750             switch (p->sig) {
13751             case SIG_PRI_LIB_HANDLE_CASES:
13752 #if defined(HAVE_PRI_CALL_WAITING)
13753                if (((struct sig_pri_chan *) p->sig_pvt)->is_call_waiting) {
13754                   ((struct sig_pri_chan *) p->sig_pvt)->is_call_waiting = 0;
13755                   ast_atomic_fetchadd_int(&p->pri->num_call_waiting_calls, -1);
13756                }
13757 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
13758                /*
13759                 * This should be the last thing to clear when we are done with
13760                 * the channel.
13761                 */
13762                ((struct sig_pri_chan *) p->sig_pvt)->allocated = 0;
13763                break;
13764             default:
13765                break;
13766             }
13767 #endif   /* defined(HAVE_PRI) */
13768          } else {
13769             snprintf(p->dialstring, sizeof(p->dialstring), "DAHDI/%s", (char *) data);
13770          }
13771          break;
13772       }
13773 #ifdef HAVE_OPENR2
13774 next:
13775 #endif
13776       if (start.backwards) {
13777          p = p->prev;
13778          if (!p)
13779             p = ifend;
13780       } else {
13781          p = p->next;
13782          if (!p)
13783             p = iflist;
13784       }
13785       /* stop when you roll to the one that we started from */
13786       if (p == exitpvt)
13787          break;
13788    }
13789    ast_mutex_unlock(&iflock);
13790    restart_monitor();
13791    if (cause && !tmp) {
13792       if (callwait || channelmatched) {
13793          *cause = AST_CAUSE_BUSY;
13794       } else if (groupmatched) {
13795          *cause = AST_CAUSE_CONGESTION;
13796       } else {
13797          /*
13798           * We did not match any channel requested.
13799           * Dialplan error requesting non-existant channel?
13800           */
13801       }
13802    }
13803 
13804    return tmp;
13805 }
13806 
13807 /*!
13808  * \internal
13809  * \brief Determine the device state for a given DAHDI device if we can.
13810  * \since 1.8
13811  *
13812  * \param data DAHDI device name after "DAHDI/".
13813  *
13814  * \retval device_state enum ast_device_state value.
13815  * \retval AST_DEVICE_UNKNOWN if we could not determine the device's state.
13816  */
13817 static int dahdi_devicestate(void *data)
13818 {
13819 #if defined(HAVE_PRI)
13820    char *device;
13821    unsigned span;
13822    int res;
13823 
13824    device = data;
13825 
13826    if (*device != 'I') {
13827       /* The request is not for an ISDN span device. */
13828       return AST_DEVICE_UNKNOWN;
13829    }
13830    res = sscanf(device, "I%30u", &span);
13831    if (res != 1 || !span || NUM_SPANS < span) {
13832       /* Bad format for ISDN span device name. */
13833       return AST_DEVICE_UNKNOWN;
13834    }
13835    device = strchr(device, '/');
13836    if (!device) {
13837       /* Bad format for ISDN span device name. */
13838       return AST_DEVICE_UNKNOWN;
13839    }
13840 
13841    /*
13842     * Since there are currently no other span devstate's defined,
13843     * it must be congestion.
13844     */
13845 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
13846    ++device;
13847    if (!strcmp(device, "congestion"))
13848 #endif   /* defined(THRESHOLD_DEVSTATE_PLACEHOLDER) */
13849    {
13850       return pris[span - 1].pri.congestion_devstate;
13851    }
13852 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
13853    else if (!strcmp(device, "threshold")) {
13854       return pris[span - 1].pri.threshold_devstate;
13855    }
13856    return AST_DEVICE_UNKNOWN;
13857 #endif   /* defined(THRESHOLD_DEVSTATE_PLACEHOLDER) */
13858 #else
13859    return AST_DEVICE_UNKNOWN;
13860 #endif   /* defined(HAVE_PRI) */
13861 }
13862 
13863 /*!
13864  * \brief Callback made when dial failed to get a channel out of dahdi_request().
13865  * \since 1.8
13866  *
13867  * \param inbound Incoming asterisk channel.
13868  * \param dest Same dial string passed to dahdi_request().
13869  * \param callback Callback into CC core to announce a busy channel available for CC.
13870  *
13871  * \details
13872  * This callback acts like a forked dial with all prongs of the fork busy.
13873  * Essentially, for each channel that could have taken the call, indicate that
13874  * it is busy.
13875  *
13876  * \retval 0 on success.
13877  * \retval -1 on error.
13878  */
13879 static int dahdi_cc_callback(struct ast_channel *inbound, const char *dest, ast_cc_callback_fn callback)
13880 {
13881    struct dahdi_pvt *p;
13882    struct dahdi_pvt *exitpvt;
13883    struct dahdi_starting_point start;
13884    int groupmatched = 0;
13885    int channelmatched = 0;
13886 
13887    ast_mutex_lock(&iflock);
13888    p = determine_starting_point(dest, &start);
13889    if (!p) {
13890       ast_mutex_unlock(&iflock);
13891       return -1;
13892    }
13893    exitpvt = p;
13894    for (;;) {
13895       if (is_group_or_channel_match(p, start.span, start.groupmatch, &groupmatched, start.channelmatch, &channelmatched)) {
13896          /* We found a potential match. call the callback */
13897          struct ast_str *device_name;
13898          char *dash;
13899          const char *monitor_type;
13900          char dialstring[AST_CHANNEL_NAME];
13901          char full_device_name[AST_CHANNEL_NAME];
13902 
13903          switch (ast_get_cc_monitor_policy(p->cc_params)) {
13904          case AST_CC_MONITOR_NEVER:
13905             break;
13906          case AST_CC_MONITOR_NATIVE:
13907          case AST_CC_MONITOR_ALWAYS:
13908          case AST_CC_MONITOR_GENERIC:
13909 #if defined(HAVE_PRI)
13910             if (dahdi_sig_pri_lib_handles(p->sig)) {
13911                /*
13912                 * ISDN is in a trunk busy condition so we need to monitor
13913                 * the span congestion device state.
13914                 */
13915                snprintf(full_device_name, sizeof(full_device_name),
13916                   "DAHDI/I%d/congestion", p->pri->span);
13917             } else
13918 #endif   /* defined(HAVE_PRI) */
13919             {
13920 #if defined(HAVE_PRI)
13921                device_name = create_channel_name(p, 1, "");
13922 #else
13923                device_name = create_channel_name(p);
13924 #endif   /* defined(HAVE_PRI) */
13925                snprintf(full_device_name, sizeof(full_device_name), "DAHDI/%s",
13926                   device_name ? ast_str_buffer(device_name) : "");
13927                ast_free(device_name);
13928                /*
13929                 * The portion after the '-' in the channel name is either a random
13930                 * number, a sequence number, or a subchannel number. None are
13931                 * necessary so strip them off.
13932                 */
13933                dash = strrchr(full_device_name, '-');
13934                if (dash) {
13935                   *dash = '\0';
13936                }
13937             }
13938             snprintf(dialstring, sizeof(dialstring), "DAHDI/%s", dest);
13939 
13940             /*
13941              * Analog can only do generic monitoring.
13942              * ISDN is in a trunk busy condition and any "device" is going
13943              * to be busy until a B channel becomes available.  The generic
13944              * monitor can do this task.
13945              */
13946             monitor_type = AST_CC_GENERIC_MONITOR_TYPE;
13947             callback(inbound,
13948 #if defined(HAVE_PRI)
13949                p->pri ? p->pri->cc_params : p->cc_params,
13950 #else
13951                p->cc_params,
13952 #endif   /* defined(HAVE_PRI) */
13953                monitor_type, full_device_name, dialstring, NULL);
13954             break;
13955          }
13956       }
13957       p = start.backwards ? p->prev : p->next;
13958       if (!p) {
13959          p = start.backwards ? ifend : iflist;
13960       }
13961       if (p == exitpvt) {
13962          break;
13963       }
13964    }
13965    ast_mutex_unlock(&iflock);
13966    return 0;
13967 }
13968 
13969 #if defined(HAVE_SS7)
13970 static void dahdi_ss7_message(struct ss7 *ss7, char *s)
13971 {
13972    int i;
13973 
13974    if (ss7) {
13975       for (i = 0; i < NUM_SPANS; i++) {
13976          if (linksets[i].ss7.ss7 == ss7) {
13977             ast_verbose("[%d] %s", i + 1, s);
13978             return;
13979          }
13980       }
13981    }
13982    ast_verbose("%s", s);
13983 }
13984 #endif   /* defined(HAVE_SS7) */
13985 
13986 #if defined(HAVE_SS7)
13987 static void dahdi_ss7_error(struct ss7 *ss7, char *s)
13988 {
13989    int i;
13990 
13991    if (ss7) {
13992       for (i = 0; i < NUM_SPANS; i++) {
13993          if (linksets[i].ss7.ss7 == ss7) {
13994             ast_log(LOG_ERROR, "[%d] %s", i + 1, s);
13995             return;
13996          }
13997       }
13998    }
13999    ast_log(LOG_ERROR, "%s", s);
14000 }
14001 #endif   /* defined(HAVE_SS7) */
14002 
14003 #if defined(HAVE_OPENR2)
14004 static void *mfcr2_monitor(void *data)
14005 {
14006    struct dahdi_mfcr2 *mfcr2 = data;
14007    /* we should be using pthread_key_create
14008       and allocate pollers dynamically.
14009       I think do_monitor() could be leaking, since it
14010       could be cancelled at any time and is not
14011       using thread keys, why?, */
14012    struct pollfd pollers[ARRAY_LEN(mfcr2->pvts)];
14013    int res = 0;
14014    int i = 0;
14015    int oldstate = 0;
14016    int quit_loop = 0;
14017    int maxsleep = 20;
14018    int was_idle = 0;
14019    int pollsize = 0;
14020    /* now that we're ready to get calls, unblock our side and
14021       get current line state */
14022    for (i = 0; i < mfcr2->numchans; i++) {
14023       openr2_chan_set_idle(mfcr2->pvts[i]->r2chan);
14024       openr2_chan_handle_cas(mfcr2->pvts[i]->r2chan);
14025    }
14026    while (1) {
14027       /* we trust here that the mfcr2 channel list will not ever change once
14028          the module is loaded */
14029       pollsize = 0;
14030       for (i = 0; i < mfcr2->numchans; i++) {
14031          pollers[i].revents = 0;
14032          pollers[i].events = 0;
14033          if (mfcr2->pvts[i]->owner) {
14034             continue;
14035          }
14036          if (!mfcr2->pvts[i]->r2chan) {
14037             ast_log(LOG_DEBUG, "Wow, no r2chan on channel %d\n", mfcr2->pvts[i]->channel);
14038             quit_loop = 1;
14039             break;
14040          }
14041          openr2_chan_enable_read(mfcr2->pvts[i]->r2chan);
14042          pollers[i].events = POLLIN | POLLPRI;
14043          pollers[i].fd = mfcr2->pvts[i]->subs[SUB_REAL].dfd;
14044          pollsize++;
14045       }
14046       if (quit_loop) {
14047          break;
14048       }
14049       if (pollsize == 0) {
14050          if (!was_idle) {
14051             ast_log(LOG_DEBUG, "Monitor thread going idle since everybody has an owner\n");
14052             was_idle = 1;
14053          }
14054          poll(NULL, 0, maxsleep);
14055          continue;
14056       }
14057       was_idle = 0;
14058       /* probably poll() is a valid cancel point, lets just be on the safe side
14059          by calling pthread_testcancel */
14060       pthread_testcancel();
14061       res = poll(pollers, mfcr2->numchans, maxsleep);
14062       pthread_testcancel();
14063       if ((res < 0) && (errno != EINTR)) {
14064          ast_log(LOG_ERROR, "going out, poll failed: %s\n", strerror(errno));
14065          break;
14066       }
14067       /* do we want to allow to cancel while processing events? */
14068       pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate);
14069       for (i = 0; i < mfcr2->numchans; i++) {
14070          if (pollers[i].revents & POLLPRI || pollers[i].revents & POLLIN) {
14071             openr2_chan_process_event(mfcr2->pvts[i]->r2chan);
14072          }
14073       }
14074       pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
14075    }
14076    ast_log(LOG_NOTICE, "Quitting MFC/R2 monitor thread\n");
14077    return 0;
14078 }
14079 #endif /* HAVE_OPENR2 */
14080 
14081 #if defined(HAVE_PRI)
14082 #ifndef PRI_RESTART
14083 #error "Upgrade your libpri"
14084 #endif
14085 static void dahdi_pri_message(struct pri *pri, char *s)
14086 {
14087    int x;
14088    int y;
14089    int dchan = -1;
14090    int span = -1;
14091    int dchancount = 0;
14092 
14093    if (pri) {
14094       for (x = 0; x < NUM_SPANS; x++) {
14095          for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
14096             if (pris[x].pri.dchans[y]) {
14097                dchancount++;
14098             }
14099 
14100             if (pris[x].pri.dchans[y] == pri) {
14101                dchan = y;
14102             }
14103          }
14104          if (dchan >= 0) {
14105             span = x;
14106             break;
14107          }
14108          dchancount = 0;
14109       }
14110       if (-1 < span) {
14111          if (1 < dchancount) {
14112             ast_verbose("[PRI Span: %d D-Channel: %d] %s", span + 1, dchan, s);
14113          } else {
14114             ast_verbose("PRI Span: %d %s", span + 1, s);
14115          }
14116       } else {
14117          ast_verbose("PRI Span: ? %s", s);
14118       }
14119    } else {
14120       ast_verbose("PRI Span: ? %s", s);
14121    }
14122 
14123    ast_mutex_lock(&pridebugfdlock);
14124 
14125    if (pridebugfd >= 0) {
14126       if (write(pridebugfd, s, strlen(s)) < 0) {
14127          ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
14128       }
14129    }
14130 
14131    ast_mutex_unlock(&pridebugfdlock);
14132 }
14133 #endif   /* defined(HAVE_PRI) */
14134 
14135 #if defined(HAVE_PRI)
14136 static void dahdi_pri_error(struct pri *pri, char *s)
14137 {
14138    int x;
14139    int y;
14140    int dchan = -1;
14141    int span = -1;
14142    int dchancount = 0;
14143 
14144    if (pri) {
14145       for (x = 0; x < NUM_SPANS; x++) {
14146          for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
14147             if (pris[x].pri.dchans[y]) {
14148                dchancount++;
14149             }
14150 
14151             if (pris[x].pri.dchans[y] == pri) {
14152                dchan = y;
14153             }
14154          }
14155          if (dchan >= 0) {
14156             span = x;
14157             break;
14158          }
14159          dchancount = 0;
14160       }
14161       if (-1 < span) {
14162          if (1 < dchancount) {
14163             ast_log(LOG_ERROR, "[PRI Span: %d D-Channel: %d] %s", span + 1, dchan, s);
14164          } else {
14165             ast_log(LOG_ERROR, "PRI Span: %d %s", span + 1, s);
14166          }
14167       } else {
14168          ast_log(LOG_ERROR, "PRI Span: ? %s", s);
14169       }
14170    } else {
14171       ast_log(LOG_ERROR, "PRI Span: ? %s", s);
14172    }
14173 
14174    ast_mutex_lock(&pridebugfdlock);
14175 
14176    if (pridebugfd >= 0) {
14177       if (write(pridebugfd, s, strlen(s)) < 0) {
14178          ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
14179       }
14180    }
14181 
14182    ast_mutex_unlock(&pridebugfdlock);
14183 }
14184 #endif   /* defined(HAVE_PRI) */
14185 
14186 #if defined(HAVE_PRI)
14187 static int prepare_pri(struct dahdi_pri *pri)
14188 {
14189    int i, res, x;
14190    struct dahdi_params p;
14191    struct dahdi_bufferinfo bi;
14192    struct dahdi_spaninfo si;
14193 
14194    pri->pri.calls = &dahdi_pri_callbacks;
14195 
14196    for (i = 0; i < SIG_PRI_NUM_DCHANS; i++) {
14197       if (!pri->dchannels[i])
14198          break;
14199       pri->pri.fds[i] = open("/dev/dahdi/channel", O_RDWR);
14200       x = pri->dchannels[i];
14201       if ((pri->pri.fds[i] < 0) || (ioctl(pri->pri.fds[i],DAHDI_SPECIFY,&x) == -1)) {
14202          ast_log(LOG_ERROR, "Unable to open D-channel %d (%s)\n", x, strerror(errno));
14203          return -1;
14204       }
14205       memset(&p, 0, sizeof(p));
14206       res = ioctl(pri->pri.fds[i], DAHDI_GET_PARAMS, &p);
14207       if (res) {
14208          dahdi_close_pri_fd(pri, i);
14209          ast_log(LOG_ERROR, "Unable to get parameters for D-channel %d (%s)\n", x, strerror(errno));
14210          return -1;
14211       }
14212       if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC)) {
14213          dahdi_close_pri_fd(pri, i);
14214          ast_log(LOG_ERROR, "D-channel %d is not in HDLC/FCS mode.\n", x);
14215          return -1;
14216       }
14217       memset(&si, 0, sizeof(si));
14218       res = ioctl(pri->pri.fds[i], DAHDI_SPANSTAT, &si);
14219       if (res) {
14220          dahdi_close_pri_fd(pri, i);
14221          ast_log(LOG_ERROR, "Unable to get span state for D-channel %d (%s)\n", x, strerror(errno));
14222       }
14223       if (!si.alarms) {
14224          pri_event_noalarm(&pri->pri, i, 1);
14225       } else {
14226          pri_event_alarm(&pri->pri, i, 1);
14227       }
14228       memset(&bi, 0, sizeof(bi));
14229       bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
14230       bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
14231       bi.numbufs = 32;
14232       bi.bufsize = 1024;
14233       if (ioctl(pri->pri.fds[i], DAHDI_SET_BUFINFO, &bi)) {
14234          ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", x, strerror(errno));
14235          dahdi_close_pri_fd(pri, i);
14236          return -1;
14237       }
14238       pri->pri.dchan_logical_span[i] = pris[p.spanno - 1].prilogicalspan;
14239    }
14240    return 0;
14241 }
14242 #endif   /* defined(HAVE_PRI) */
14243 
14244 #if defined(HAVE_PRI)
14245 static char *complete_span_helper(const char *line, const char *word, int pos, int state, int rpos)
14246 {
14247    int which, span;
14248    char *ret = NULL;
14249 
14250    if (pos != rpos)
14251       return ret;
14252 
14253    for (which = span = 0; span < NUM_SPANS; span++) {
14254       if (pris[span].pri.pri && ++which > state) {
14255          if (asprintf(&ret, "%d", span + 1) < 0) { /* user indexes start from 1 */
14256             ast_log(LOG_WARNING, "asprintf() failed: %s\n", strerror(errno));
14257          }
14258          break;
14259       }
14260    }
14261    return ret;
14262 }
14263 #endif   /* defined(HAVE_PRI) */
14264 
14265 #if defined(HAVE_PRI)
14266 static char *complete_span_4(const char *line, const char *word, int pos, int state)
14267 {
14268    return complete_span_helper(line,word,pos,state,3);
14269 }
14270 #endif   /* defined(HAVE_PRI) */
14271 
14272 #if defined(HAVE_PRI)
14273 static char *handle_pri_set_debug_file(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14274 {
14275    int myfd;
14276    switch (cmd) {
14277    case CLI_INIT:
14278       e->command = "pri set debug file";
14279       e->usage = "Usage: pri set debug file [output-file]\n"
14280          "       Sends PRI debug output to the specified output file\n";
14281       return NULL;
14282    case CLI_GENERATE:
14283       return NULL;
14284    }
14285    if (a->argc < 5)
14286       return CLI_SHOWUSAGE;
14287 
14288    if (ast_strlen_zero(a->argv[4]))
14289       return CLI_SHOWUSAGE;
14290 
14291    myfd = open(a->argv[4], O_CREAT|O_WRONLY, AST_FILE_MODE);
14292    if (myfd < 0) {
14293       ast_cli(a->fd, "Unable to open '%s' for writing\n", a->argv[4]);
14294       return CLI_SUCCESS;
14295    }
14296 
14297    ast_mutex_lock(&pridebugfdlock);
14298 
14299    if (pridebugfd >= 0)
14300       close(pridebugfd);
14301 
14302    pridebugfd = myfd;
14303    ast_copy_string(pridebugfilename,a->argv[4],sizeof(pridebugfilename));
14304    ast_mutex_unlock(&pridebugfdlock);
14305    ast_cli(a->fd, "PRI debug output will be sent to '%s'\n", a->argv[4]);
14306    return CLI_SUCCESS;
14307 }
14308 #endif   /* defined(HAVE_PRI) */
14309 
14310 #if defined(HAVE_PRI)
14311 static char *handle_pri_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14312 {
14313    int span;
14314    int x;
14315    int level = 0;
14316    switch (cmd) {
14317    case CLI_INIT:
14318       e->command = "pri set debug {on|off|0|1|2} span";
14319       e->usage =
14320          "Usage: pri set debug {<level>|on|off} span <span>\n"
14321          "       Enables debugging on a given PRI span\n";
14322       return NULL;
14323    case CLI_GENERATE:
14324       return complete_span_4(a->line, a->word, a->pos, a->n);
14325    }
14326    if (a->argc < 6) {
14327       return CLI_SHOWUSAGE;
14328    }
14329 
14330    if (!strcasecmp(a->argv[3], "on")) {
14331       level = 1;
14332    } else if (!strcasecmp(a->argv[3], "off")) {
14333       level = 0;
14334    } else {
14335       level = atoi(a->argv[3]);
14336    }
14337    span = atoi(a->argv[5]);
14338    if ((span < 1) || (span > NUM_SPANS)) {
14339       ast_cli(a->fd, "Invalid span %s.  Should be a number %d to %d\n", a->argv[5], 1, NUM_SPANS);
14340       return CLI_SUCCESS;
14341    }
14342    if (!pris[span-1].pri.pri) {
14343       ast_cli(a->fd, "No PRI running on span %d\n", span);
14344       return CLI_SUCCESS;
14345    }
14346 
14347    /* Set debug level in libpri */
14348    for (x = 0; x < SIG_PRI_NUM_DCHANS; x++) {
14349       if (pris[span - 1].pri.dchans[x]) {
14350          switch (level) {
14351          case 0:
14352             pri_set_debug(pris[span - 1].pri.dchans[x], 0);
14353             break;
14354          case 1:
14355             pri_set_debug(pris[span - 1].pri.dchans[x], SIG_PRI_DEBUG_NORMAL);
14356             break;
14357          default:
14358             pri_set_debug(pris[span - 1].pri.dchans[x], SIG_PRI_DEBUG_INTENSE);
14359             break;
14360          }
14361       }
14362    }
14363    if (level == 0) {
14364       /* Close the debugging file if it's set */
14365       ast_mutex_lock(&pridebugfdlock);
14366       if (0 <= pridebugfd) {
14367          close(pridebugfd);
14368          pridebugfd = -1;
14369          ast_cli(a->fd, "Disabled PRI debug output to file '%s'\n",
14370             pridebugfilename);
14371       }
14372       ast_mutex_unlock(&pridebugfdlock);
14373    }
14374    pris[span - 1].pri.debug = (level) ? 1 : 0;
14375    ast_cli(a->fd, "%s debugging on span %d\n", (level) ? "Enabled" : "Disabled", span);
14376    return CLI_SUCCESS;
14377 }
14378 #endif   /* defined(HAVE_PRI) */
14379 
14380 #if defined(HAVE_PRI)
14381 #if defined(HAVE_PRI_SERVICE_MESSAGES)
14382 static char *handle_pri_service_generic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a, int changestatus)
14383 {
14384    unsigned *why;
14385    int channel;
14386    int trunkgroup;
14387    int x, y, fd = a->fd;
14388    int interfaceid = 0;
14389    char db_chan_name[20], db_answer[5];
14390    struct dahdi_pvt *tmp;
14391    struct dahdi_pri *pri;
14392 
14393    if (a->argc < 5 || a->argc > 6)
14394       return CLI_SHOWUSAGE;
14395    if (strchr(a->argv[4], ':')) {
14396       if (sscanf(a->argv[4], "%30d:%30d", &trunkgroup, &channel) != 2)
14397          return CLI_SHOWUSAGE;
14398       if ((trunkgroup < 1) || (channel < 1))
14399          return CLI_SHOWUSAGE;
14400       pri = NULL;
14401       for (x=0;x<NUM_SPANS;x++) {
14402          if (pris[x].pri.trunkgroup == trunkgroup) {
14403             pri = pris + x;
14404             break;
14405          }
14406       }
14407       if (!pri) {
14408          ast_cli(fd, "No such trunk group %d\n", trunkgroup);
14409          return CLI_FAILURE;
14410       }
14411    } else
14412       channel = atoi(a->argv[4]);
14413 
14414    if (a->argc == 6)
14415       interfaceid = atoi(a->argv[5]);
14416 
14417    /* either servicing a D-Channel */
14418    for (x = 0; x < NUM_SPANS; x++) {
14419       for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
14420          if (pris[x].dchannels[y] == channel) {
14421             pri = pris + x;
14422             if (pri->pri.enable_service_message_support) {
14423                ast_mutex_lock(&pri->pri.lock);
14424                pri_maintenance_service(pri->pri.pri, interfaceid, -1, changestatus);
14425                ast_mutex_unlock(&pri->pri.lock);
14426             } else {
14427                ast_cli(fd,
14428                   "\n\tThis operation has not been enabled in chan_dahdi.conf, set 'service_message_support=yes' to use this operation.\n"
14429                   "\tNote only 4ESS, 5ESS, and NI2 switch types are supported.\n\n");
14430             }
14431             return CLI_SUCCESS;
14432          }
14433       }
14434    }
14435 
14436    /* or servicing a B-Channel */
14437    ast_mutex_lock(&iflock);
14438    for (tmp = iflist; tmp; tmp = tmp->next) {
14439       if (tmp->pri && tmp->channel == channel) {
14440          ast_mutex_unlock(&iflock);
14441          ast_mutex_lock(&tmp->pri->lock);
14442          if (!tmp->pri->enable_service_message_support) {
14443             ast_mutex_unlock(&tmp->pri->lock);
14444             ast_cli(fd,
14445                "\n\tThis operation has not been enabled in chan_dahdi.conf, set 'service_message_support=yes' to use this operation.\n"
14446                "\tNote only 4ESS, 5ESS, and NI2 switch types are supported.\n\n");
14447             return CLI_SUCCESS;
14448          }
14449          snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, tmp->span, channel);
14450          why = &((struct sig_pri_chan *) tmp->sig_pvt)->service_status;
14451          switch(changestatus) {
14452          case 0: /* enable */
14453             /* Near end wants to be in service now. */
14454             ast_db_del(db_chan_name, SRVST_DBKEY);
14455             *why &= ~SRVST_NEAREND;
14456             if (*why) {
14457                snprintf(db_answer, sizeof(db_answer), "%s:%u", SRVST_TYPE_OOS, *why);
14458                ast_db_put(db_chan_name, SRVST_DBKEY, db_answer);
14459             } else {
14460                dahdi_pri_update_span_devstate(tmp->pri);
14461             }
14462             break;
14463          /* case 1:  -- loop */
14464          case 2: /* disable */
14465             /* Near end wants to be out-of-service now. */
14466             ast_db_del(db_chan_name, SRVST_DBKEY);
14467             *why |= SRVST_NEAREND;
14468             snprintf(db_answer, sizeof(db_answer), "%s:%u", SRVST_TYPE_OOS, *why);
14469             ast_db_put(db_chan_name, SRVST_DBKEY, db_answer);
14470             dahdi_pri_update_span_devstate(tmp->pri);
14471             break;
14472          /* case 3:  -- continuity */
14473          /* case 4:  -- shutdown */
14474          default:
14475             ast_log(LOG_WARNING, "Unsupported changestatus: '%d'\n", changestatus);
14476             break;
14477          }
14478          pri_maintenance_bservice(tmp->pri->pri, tmp->sig_pvt, changestatus);
14479          ast_mutex_unlock(&tmp->pri->lock);
14480          return CLI_SUCCESS;
14481       }
14482    }
14483    ast_mutex_unlock(&iflock);
14484 
14485    ast_cli(fd, "Unable to find given channel %d, possibly not a PRI\n", channel);
14486    return CLI_FAILURE;
14487 }
14488 
14489 static char *handle_pri_service_enable_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14490 {
14491    switch (cmd) {
14492    case CLI_INIT:
14493       e->command = "pri service enable channel";
14494       e->usage =
14495          "Usage: pri service enable channel <channel> [<interface id>]\n"
14496          "       Send an AT&T / NFAS / CCS ANSI T1.607 maintenance message\n"
14497          "  to restore a channel to service, with optional interface id\n"
14498          "  as agreed upon with remote switch operator\n";
14499       return NULL;
14500    case CLI_GENERATE:
14501       return NULL;
14502    }
14503    return handle_pri_service_generic(e, cmd, a, 0);
14504 }
14505 
14506 static char *handle_pri_service_disable_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14507 {
14508    switch (cmd) {
14509    case CLI_INIT:
14510       e->command = "pri service disable channel";
14511       e->usage =
14512          "Usage: pri service disable channel <chan num> [<interface id>]\n"
14513          "  Send an AT&T / NFAS / CCS ANSI T1.607 maintenance message\n"
14514          "  to remove a channel from service, with optional interface id\n"
14515          "  as agreed upon with remote switch operator\n";
14516       return NULL;
14517    case CLI_GENERATE:
14518       return NULL;
14519    }
14520    return handle_pri_service_generic(e, cmd, a, 2);
14521 }
14522 #endif   /* defined(HAVE_PRI_SERVICE_MESSAGES) */
14523 #endif   /* defined(HAVE_PRI) */
14524 
14525 #if defined(HAVE_PRI)
14526 static char *handle_pri_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14527 {
14528    int span;
14529 
14530    switch (cmd) {
14531    case CLI_INIT:
14532       e->command = "pri show channels";
14533       e->usage =
14534          "Usage: pri show channels\n"
14535          "       Displays PRI channel information such as the current mapping\n"
14536          "       of DAHDI B channels to Asterisk channel names and which calls\n"
14537          "       are on hold or call-waiting.  Calls on hold or call-waiting\n"
14538          "       are not associated with any B channel.\n";
14539       return NULL;
14540    case CLI_GENERATE:
14541       return NULL;
14542    }
14543 
14544    if (a->argc != 3)
14545       return CLI_SHOWUSAGE;
14546 
14547    sig_pri_cli_show_channels_header(a->fd);
14548    for (span = 0; span < NUM_SPANS; ++span) {
14549       if (pris[span].pri.pri) {
14550          sig_pri_cli_show_channels(a->fd, &pris[span].pri);
14551       }
14552    }
14553    return CLI_SUCCESS;
14554 }
14555 #endif   /* defined(HAVE_PRI) */
14556 
14557 #if defined(HAVE_PRI)
14558 static char *handle_pri_show_spans(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14559 {
14560    int span;
14561 
14562    switch (cmd) {
14563    case CLI_INIT:
14564       e->command = "pri show spans";
14565       e->usage =
14566          "Usage: pri show spans\n"
14567          "       Displays PRI span information\n";
14568       return NULL;
14569    case CLI_GENERATE:
14570       return NULL;
14571    }
14572 
14573    if (a->argc != 3)
14574       return CLI_SHOWUSAGE;
14575 
14576    for (span = 0; span < NUM_SPANS; span++) {
14577       if (pris[span].pri.pri) {
14578          sig_pri_cli_show_spans(a->fd, span + 1, &pris[span].pri);
14579       }
14580    }
14581    return CLI_SUCCESS;
14582 }
14583 #endif   /* defined(HAVE_PRI) */
14584 
14585 #if defined(HAVE_PRI)
14586 static char *handle_pri_show_span(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14587 {
14588    int span;
14589 
14590    switch (cmd) {
14591    case CLI_INIT:
14592       e->command = "pri show span";
14593       e->usage =
14594          "Usage: pri show span <span>\n"
14595          "       Displays PRI Information on a given PRI span\n";
14596       return NULL;
14597    case CLI_GENERATE:
14598       return complete_span_4(a->line, a->word, a->pos, a->n);
14599    }
14600 
14601    if (a->argc < 4)
14602       return CLI_SHOWUSAGE;
14603    span = atoi(a->argv[3]);
14604    if ((span < 1) || (span > NUM_SPANS)) {
14605       ast_cli(a->fd, "Invalid span '%s'.  Should be a number from %d to %d\n", a->argv[3], 1, NUM_SPANS);
14606       return CLI_SUCCESS;
14607    }
14608    if (!pris[span-1].pri.pri) {
14609       ast_cli(a->fd, "No PRI running on span %d\n", span);
14610       return CLI_SUCCESS;
14611    }
14612 
14613    sig_pri_cli_show_span(a->fd, pris[span-1].dchannels, &pris[span-1].pri);
14614 
14615    return CLI_SUCCESS;
14616 }
14617 #endif   /* defined(HAVE_PRI) */
14618 
14619 #if defined(HAVE_PRI)
14620 static char *handle_pri_show_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14621 {
14622    int x;
14623    int span;
14624    int count=0;
14625    int debug;
14626 
14627    switch (cmd) {
14628    case CLI_INIT:
14629       e->command = "pri show debug";
14630       e->usage =
14631          "Usage: pri show debug\n"
14632          "  Show the debug state of pri spans\n";
14633       return NULL;
14634    case CLI_GENERATE:
14635       return NULL;
14636    }
14637 
14638    for (span = 0; span < NUM_SPANS; span++) {
14639       if (pris[span].pri.pri) {
14640          for (x = 0; x < SIG_PRI_NUM_DCHANS; x++) {
14641             if (pris[span].pri.dchans[x]) {
14642                debug = pri_get_debug(pris[span].pri.dchans[x]);
14643                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" );
14644                count++;
14645             }
14646          }
14647       }
14648 
14649    }
14650    ast_mutex_lock(&pridebugfdlock);
14651    if (pridebugfd >= 0)
14652       ast_cli(a->fd, "Logging PRI debug to file %s\n", pridebugfilename);
14653    ast_mutex_unlock(&pridebugfdlock);
14654 
14655    if (!count)
14656       ast_cli(a->fd, "No PRI running\n");
14657    return CLI_SUCCESS;
14658 }
14659 #endif   /* defined(HAVE_PRI) */
14660 
14661 #if defined(HAVE_PRI)
14662 static char *handle_pri_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14663 {
14664    switch (cmd) {
14665    case CLI_INIT:
14666       e->command = "pri show version";
14667       e->usage =
14668          "Usage: pri show version\n"
14669          "Show libpri version information\n";
14670       return NULL;
14671    case CLI_GENERATE:
14672       return NULL;
14673    }
14674 
14675    ast_cli(a->fd, "libpri version: %s\n", pri_get_version());
14676 
14677    return CLI_SUCCESS;
14678 }
14679 #endif   /* defined(HAVE_PRI) */
14680 
14681 #if defined(HAVE_PRI)
14682 static struct ast_cli_entry dahdi_pri_cli[] = {
14683    AST_CLI_DEFINE(handle_pri_debug, "Enables PRI debugging on a span"),
14684 #if defined(HAVE_PRI_SERVICE_MESSAGES)
14685    AST_CLI_DEFINE(handle_pri_service_enable_channel, "Return a channel to service"),
14686    AST_CLI_DEFINE(handle_pri_service_disable_channel, "Remove a channel from service"),
14687 #endif   /* defined(HAVE_PRI_SERVICE_MESSAGES) */
14688    AST_CLI_DEFINE(handle_pri_show_channels, "Displays PRI channel information"),
14689    AST_CLI_DEFINE(handle_pri_show_spans, "Displays PRI span information"),
14690    AST_CLI_DEFINE(handle_pri_show_span, "Displays PRI span information"),
14691    AST_CLI_DEFINE(handle_pri_show_debug, "Displays current PRI debug settings"),
14692    AST_CLI_DEFINE(handle_pri_set_debug_file, "Sends PRI debug output to the specified file"),
14693    AST_CLI_DEFINE(handle_pri_version, "Displays libpri version"),
14694 };
14695 #endif   /* defined(HAVE_PRI) */
14696 
14697 #ifdef HAVE_OPENR2
14698 
14699 static char *handle_mfcr2_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14700 {
14701    switch (cmd) {
14702    case CLI_INIT:
14703       e->command = "mfcr2 show version";
14704       e->usage =
14705          "Usage: mfcr2 show version\n"
14706          "       Shows the version of the OpenR2 library being used.\n";
14707       return NULL;
14708    case CLI_GENERATE:
14709       return NULL;
14710    }
14711    ast_cli(a->fd, "OpenR2 version: %s, revision: %s\n", openr2_get_version(), openr2_get_revision());
14712    return CLI_SUCCESS;
14713 }
14714 
14715 static char *handle_mfcr2_show_variants(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14716 {
14717 #define FORMAT "%4s %40s\n"
14718    int i = 0;
14719    int numvariants = 0;
14720    const openr2_variant_entry_t *variants;
14721    switch (cmd) {
14722    case CLI_INIT:
14723       e->command = "mfcr2 show variants";
14724       e->usage =
14725          "Usage: mfcr2 show variants\n"
14726          "       Shows the list of MFC/R2 variants supported.\n";
14727       return NULL;
14728    case CLI_GENERATE:
14729       return NULL;
14730    }
14731    if (!(variants = openr2_proto_get_variant_list(&numvariants))) {
14732       ast_cli(a->fd, "Failed to get list of variants.\n");
14733       return CLI_FAILURE;
14734    }
14735    ast_cli(a->fd, FORMAT, "Variant Code", "Country");
14736    for (i = 0; i < numvariants; i++) {
14737       ast_cli(a->fd, FORMAT, variants[i].name, variants[i].country);
14738    }
14739    return CLI_SUCCESS;
14740 #undef FORMAT
14741 }
14742 
14743 static char *handle_mfcr2_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14744 {
14745 #define FORMAT "%4s %-7.7s %-7.7s %-8.8s %-9.9s %-16.16s %-8.8s %-8.8s\n"
14746    int filtertype = 0;
14747    int targetnum = 0;
14748    char channo[5];
14749    char anino[5];
14750    char dnisno[5];
14751    struct dahdi_pvt *p;
14752    openr2_context_t *r2context;
14753    openr2_variant_t r2variant;
14754    switch (cmd) {
14755    case CLI_INIT:
14756       e->command = "mfcr2 show channels [group|context]";
14757       e->usage =
14758          "Usage: mfcr2 show channels [group <group> | context <context>]\n"
14759          "       Shows the DAHDI channels configured with MFC/R2 signaling.\n";
14760       return NULL;
14761    case CLI_GENERATE:
14762       return NULL;
14763    }
14764    if (!((a->argc == 3) || (a->argc == 5))) {
14765       return CLI_SHOWUSAGE;
14766    }
14767    if (a->argc == 5) {
14768       if (!strcasecmp(a->argv[3], "group")) {
14769          targetnum = atoi(a->argv[4]);
14770          if ((targetnum < 0) || (targetnum > 63))
14771             return CLI_SHOWUSAGE;
14772          targetnum = 1 << targetnum;
14773          filtertype = 1;
14774       } else if (!strcasecmp(a->argv[3], "context")) {
14775          filtertype = 2;
14776       } else {
14777          return CLI_SHOWUSAGE;
14778       }
14779    }
14780    ast_cli(a->fd, FORMAT, "Chan", "Variant", "Max ANI", "Max DNIS", "ANI First", "Immediate Accept", "Tx CAS", "Rx CAS");
14781    ast_mutex_lock(&iflock);
14782    for (p = iflist; p; p = p->next) {
14783       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14784          continue;
14785       }
14786       if (filtertype) {
14787          switch(filtertype) {
14788          case 1: /* mfcr2 show channels group <group> */
14789             if (p->group != targetnum) {
14790                continue;
14791             }
14792             break;
14793          case 2: /* mfcr2 show channels context <context> */
14794             if (strcasecmp(p->context, a->argv[4])) {
14795                continue;
14796             }
14797             break;
14798          default:
14799             ;
14800          }
14801       }
14802       r2context = openr2_chan_get_context(p->r2chan);
14803       r2variant = openr2_context_get_variant(r2context);
14804       snprintf(channo, sizeof(channo), "%d", p->channel);
14805       snprintf(anino, sizeof(anino), "%d", openr2_context_get_max_ani(r2context));
14806       snprintf(dnisno, sizeof(dnisno), "%d", openr2_context_get_max_dnis(r2context));
14807       ast_cli(a->fd, FORMAT, channo, openr2_proto_get_variant_string(r2variant),
14808             anino, dnisno, openr2_context_get_ani_first(r2context) ? "Yes" : "No",
14809             openr2_context_get_immediate_accept(r2context) ? "Yes" : "No",
14810             openr2_chan_get_tx_cas_string(p->r2chan), openr2_chan_get_rx_cas_string(p->r2chan));
14811    }
14812    ast_mutex_unlock(&iflock);
14813    return CLI_SUCCESS;
14814 #undef FORMAT
14815 }
14816 
14817 static char *handle_mfcr2_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14818 {
14819    struct dahdi_pvt *p = NULL;
14820    int channo = 0;
14821    char *toklevel = NULL;
14822    char *saveptr = NULL;
14823    char *logval = NULL;
14824    openr2_log_level_t loglevel = OR2_LOG_NOTHING;
14825    openr2_log_level_t tmplevel = OR2_LOG_NOTHING;
14826    switch (cmd) {
14827    case CLI_INIT:
14828       e->command = "mfcr2 set debug";
14829       e->usage =
14830          "Usage: mfcr2 set debug <loglevel> <channel>\n"
14831          "       Set a new logging level for the specified channel.\n"
14832          "       If no channel is specified the logging level will be applied to all channels.\n";
14833       return NULL;
14834    case CLI_GENERATE:
14835       return NULL;
14836    }
14837    if (a->argc < 4) {
14838       return CLI_SHOWUSAGE;
14839    }
14840    channo = (a->argc == 5) ? atoi(a->argv[4]) : -1;
14841    logval = ast_strdupa(a->argv[3]);
14842    toklevel = strtok_r(logval, ",", &saveptr);
14843    if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
14844       ast_cli(a->fd, "Invalid MFC/R2 logging level '%s'.\n", a->argv[3]);
14845       return CLI_FAILURE;
14846    } else if (OR2_LOG_NOTHING == tmplevel) {
14847       loglevel = tmplevel;
14848    } else {
14849       loglevel |= tmplevel;
14850       while ((toklevel = strtok_r(NULL, ",", &saveptr))) {
14851          if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
14852             ast_cli(a->fd, "Ignoring invalid logging level: '%s'.\n", toklevel);
14853             continue;
14854          }
14855          loglevel |= tmplevel;
14856       }
14857    }
14858    ast_mutex_lock(&iflock);
14859    for (p = iflist; p; p = p->next) {
14860       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14861          continue;
14862       }
14863       if ((channo != -1) && (p->channel != channo )) {
14864          continue;
14865       }
14866       openr2_chan_set_log_level(p->r2chan, loglevel);
14867       if (channo != -1) {
14868          ast_cli(a->fd, "MFC/R2 debugging set to '%s' for channel %d.\n", a->argv[3], p->channel);
14869          break;
14870       }
14871    }
14872    if ((channo != -1) && !p) {
14873       ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
14874    }
14875    if (channo == -1) {
14876       ast_cli(a->fd, "MFC/R2 debugging set to '%s' for all channels.\n", a->argv[3]);
14877    }
14878    ast_mutex_unlock(&iflock);
14879    return CLI_SUCCESS;
14880 }
14881 
14882 static char *handle_mfcr2_call_files(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14883 {
14884    struct dahdi_pvt *p = NULL;
14885    int channo = 0;
14886    switch (cmd) {
14887    case CLI_INIT:
14888       e->command = "mfcr2 call files [on|off]";
14889       e->usage =
14890          "Usage: mfcr2 call files [on|off] <channel>\n"
14891          "       Enable call files creation on the specified channel.\n"
14892          "       If no channel is specified call files creation policy will be applied to all channels.\n";
14893       return NULL;
14894    case CLI_GENERATE:
14895       return NULL;
14896    }
14897    if (a->argc < 4) {
14898       return CLI_SHOWUSAGE;
14899    }
14900    channo = (a->argc == 5) ? atoi(a->argv[4]) : -1;
14901    ast_mutex_lock(&iflock);
14902    for (p = iflist; p; p = p->next) {
14903       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14904          continue;
14905       }
14906       if ((channo != -1) && (p->channel != channo )) {
14907          continue;
14908       }
14909       if (ast_true(a->argv[3])) {
14910          openr2_chan_enable_call_files(p->r2chan);
14911       } else {
14912          openr2_chan_disable_call_files(p->r2chan);
14913       }
14914       if (channo != -1) {
14915          if (ast_true(a->argv[3])) {
14916             ast_cli(a->fd, "MFC/R2 call files enabled for channel %d.\n", p->channel);
14917          } else {
14918             ast_cli(a->fd, "MFC/R2 call files disabled for channel %d.\n", p->channel);
14919          }
14920          break;
14921       }
14922    }
14923    if ((channo != -1) && !p) {
14924       ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
14925    }
14926    if (channo == -1) {
14927       if (ast_true(a->argv[3])) {
14928          ast_cli(a->fd, "MFC/R2 Call files enabled for all channels.\n");
14929       } else {
14930          ast_cli(a->fd, "MFC/R2 Call files disabled for all channels.\n");
14931       }
14932    }
14933    ast_mutex_unlock(&iflock);
14934    return CLI_SUCCESS;
14935 }
14936 
14937 static char *handle_mfcr2_set_idle(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14938 {
14939    struct dahdi_pvt *p = NULL;
14940    int channo = 0;
14941    switch (cmd) {
14942    case CLI_INIT:
14943       e->command = "mfcr2 set idle";
14944       e->usage =
14945          "Usage: mfcr2 set idle <channel>\n"
14946          "       DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n"
14947          "       Force the given channel into IDLE state.\n"
14948          "       If no channel is specified, all channels will be set to IDLE.\n";
14949       return NULL;
14950    case CLI_GENERATE:
14951       return NULL;
14952    }
14953    channo = (a->argc == 4) ? atoi(a->argv[3]) : -1;
14954    ast_mutex_lock(&iflock);
14955    for (p = iflist; p; p = p->next) {
14956       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14957          continue;
14958       }
14959       if ((channo != -1) && (p->channel != channo )) {
14960          continue;
14961       }
14962       openr2_chan_set_idle(p->r2chan);
14963       ast_mutex_lock(&p->lock);
14964       p->locallyblocked = 0;
14965       p->mfcr2call = 0;
14966       ast_mutex_unlock(&p->lock);
14967       if (channo != -1) {
14968          break;
14969       }
14970    }
14971    if ((channo != -1) && !p) {
14972       ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
14973    }
14974    ast_mutex_unlock(&iflock);
14975    return CLI_SUCCESS;
14976 }
14977 
14978 static char *handle_mfcr2_set_blocked(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14979 {
14980    struct dahdi_pvt *p = NULL;
14981    int channo = 0;
14982    switch (cmd) {
14983    case CLI_INIT:
14984       e->command = "mfcr2 set blocked";
14985       e->usage =
14986          "Usage: mfcr2 set blocked <channel>\n"
14987          "       DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n"
14988          "       Force the given channel into BLOCKED state.\n"
14989          "       If no channel is specified, all channels will be set to BLOCKED.\n";
14990       return NULL;
14991    case CLI_GENERATE:
14992       return NULL;
14993    }
14994    channo = (a->argc == 4) ? atoi(a->argv[3]) : -1;
14995    ast_mutex_lock(&iflock);
14996    for (p = iflist; p; p = p->next) {
14997       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14998          continue;
14999       }
15000       if ((channo != -1) && (p->channel != channo )) {
15001          continue;
15002       }
15003       openr2_chan_set_blocked(p->r2chan);
15004       ast_mutex_lock(&p->lock);
15005       p->locallyblocked = 1;
15006       ast_mutex_unlock(&p->lock);
15007       if (channo != -1) {
15008          break;
15009       }
15010    }
15011    if ((channo != -1) && !p) {
15012       ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
15013    }
15014    ast_mutex_unlock(&iflock);
15015    return CLI_SUCCESS;
15016 }
15017 
15018 static struct ast_cli_entry dahdi_mfcr2_cli[] = {
15019    AST_CLI_DEFINE(handle_mfcr2_version, "Show OpenR2 library version"),
15020    AST_CLI_DEFINE(handle_mfcr2_show_variants, "Show supported MFC/R2 variants"),
15021    AST_CLI_DEFINE(handle_mfcr2_show_channels, "Show MFC/R2 channels"),
15022    AST_CLI_DEFINE(handle_mfcr2_set_debug, "Set MFC/R2 channel logging level"),
15023    AST_CLI_DEFINE(handle_mfcr2_call_files, "Enable/Disable MFC/R2 call files"),
15024    AST_CLI_DEFINE(handle_mfcr2_set_idle, "Reset MFC/R2 channel forcing it to IDLE"),
15025    AST_CLI_DEFINE(handle_mfcr2_set_blocked, "Reset MFC/R2 channel forcing it to BLOCKED"),
15026 };
15027 
15028 #endif /* HAVE_OPENR2 */
15029 
15030 static char *dahdi_destroy_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15031 {
15032    int channel;
15033    int ret;
15034    switch (cmd) {
15035    case CLI_INIT:
15036       e->command = "dahdi destroy channel";
15037       e->usage =
15038          "Usage: dahdi destroy channel <chan num>\n"
15039          "  DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.  Immediately removes a given channel, whether it is in use or not\n";
15040       return NULL;
15041    case CLI_GENERATE:
15042       return NULL;
15043    }
15044    if (a->argc != 4)
15045       return CLI_SHOWUSAGE;
15046 
15047    channel = atoi(a->argv[3]);
15048    ret = dahdi_destroy_channel_bynum(channel);
15049    return ( RESULT_SUCCESS == ret ) ? CLI_SUCCESS : CLI_FAILURE;
15050 }
15051 
15052 static void dahdi_softhangup_all(void)
15053 {
15054    struct dahdi_pvt *p;
15055 retry:
15056    ast_mutex_lock(&iflock);
15057    for (p = iflist; p; p = p->next) {
15058       ast_mutex_lock(&p->lock);
15059       if (p->owner && !p->restartpending) {
15060          if (ast_channel_trylock(p->owner)) {
15061             if (option_debug > 2)
15062                ast_verbose("Avoiding deadlock\n");
15063             /* Avoid deadlock since you're not supposed to lock iflock or pvt before a channel */
15064             ast_mutex_unlock(&p->lock);
15065             ast_mutex_unlock(&iflock);
15066             goto retry;
15067          }
15068          if (option_debug > 2)
15069             ast_verbose("Softhanging up on %s\n", p->owner->name);
15070          ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_EXPLICIT);
15071          p->restartpending = 1;
15072          num_restart_pending++;
15073          ast_channel_unlock(p->owner);
15074       }
15075       ast_mutex_unlock(&p->lock);
15076    }
15077    ast_mutex_unlock(&iflock);
15078 }
15079 
15080 static int setup_dahdi(int reload);
15081 static int dahdi_restart(void)
15082 {
15083 #if defined(HAVE_PRI) || defined(HAVE_SS7)
15084    int i, j;
15085 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
15086    int cancel_code;
15087    struct dahdi_pvt *p;
15088 
15089    ast_mutex_lock(&restart_lock);
15090    ast_verb(1, "Destroying channels and reloading DAHDI configuration.\n");
15091    dahdi_softhangup_all();
15092    ast_verb(4, "Initial softhangup of all DAHDI channels complete.\n");
15093 #ifdef HAVE_OPENR2
15094    dahdi_r2_destroy_links();
15095 #endif
15096 
15097 #if defined(HAVE_PRI)
15098    for (i = 0; i < NUM_SPANS; i++) {
15099       if (pris[i].pri.master && (pris[i].pri.master != AST_PTHREADT_NULL)) {
15100          cancel_code = pthread_cancel(pris[i].pri.master);
15101          pthread_kill(pris[i].pri.master, SIGURG);
15102          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);
15103          pthread_join(pris[i].pri.master, NULL);
15104          ast_debug(4, "Joined thread of span %d\n", i);
15105       }
15106    }
15107 #endif
15108 
15109 #if defined(HAVE_SS7)
15110    for (i = 0; i < NUM_SPANS; i++) {
15111       if (linksets[i].ss7.master && (linksets[i].ss7.master != AST_PTHREADT_NULL)) {
15112          cancel_code = pthread_cancel(linksets[i].ss7.master);
15113          pthread_kill(linksets[i].ss7.master, SIGURG);
15114          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);
15115          pthread_join(linksets[i].ss7.master, NULL);
15116          ast_debug(4, "Joined thread of span %d\n", i);
15117       }
15118    }
15119 #endif   /* defined(HAVE_SS7) */
15120 
15121    ast_mutex_lock(&monlock);
15122    if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
15123       cancel_code = pthread_cancel(monitor_thread);
15124       pthread_kill(monitor_thread, SIGURG);
15125       ast_debug(4, "Waiting to join monitor thread with pid=%p, cancel_code=%d\n", (void *) monitor_thread, cancel_code);
15126       pthread_join(monitor_thread, NULL);
15127       ast_debug(4, "Joined monitor thread\n");
15128    }
15129    monitor_thread = AST_PTHREADT_NULL; /* prepare to restart thread in setup_dahdi once channels are reconfigured */
15130 
15131    ast_mutex_lock(&ss_thread_lock);
15132    while (ss_thread_count > 0) { /* let ss_threads finish and run dahdi_hangup before dahvi_pvts are destroyed */
15133       int x = DAHDI_FLASH;
15134       ast_debug(3, "Waiting on %d analog_ss_thread(s) to finish\n", ss_thread_count);
15135 
15136       ast_mutex_lock(&iflock);
15137       for (p = iflist; p; p = p->next) {
15138          if (p->owner) {
15139             /* important to create an event for dahdi_wait_event to register so that all analog_ss_threads terminate */
15140             ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
15141          }
15142       }
15143       ast_mutex_unlock(&iflock);
15144       ast_cond_wait(&ss_thread_complete, &ss_thread_lock);
15145    }
15146 
15147    /* ensure any created channels before monitor threads were stopped are hungup */
15148    dahdi_softhangup_all();
15149    ast_verb(4, "Final softhangup of all DAHDI channels complete.\n");
15150    destroy_all_channels();
15151    ast_debug(1, "Channels destroyed. Now re-reading config. %d active channels remaining.\n", ast_active_channels());
15152 
15153    ast_mutex_unlock(&monlock);
15154 
15155 #ifdef HAVE_PRI
15156    for (i = 0; i < NUM_SPANS; i++) {
15157       for (j = 0; j < SIG_PRI_NUM_DCHANS; j++)
15158          dahdi_close_pri_fd(&(pris[i]), j);
15159    }
15160 
15161    memset(pris, 0, sizeof(pris));
15162    for (i = 0; i < NUM_SPANS; i++) {
15163       sig_pri_init_pri(&pris[i].pri);
15164    }
15165    pri_set_error(dahdi_pri_error);
15166    pri_set_message(dahdi_pri_message);
15167 #endif
15168 #if defined(HAVE_SS7)
15169    for (i = 0; i < NUM_SPANS; i++) {
15170       for (j = 0; j < SIG_SS7_NUM_DCHANS; j++)
15171          dahdi_close_ss7_fd(&(linksets[i]), j);
15172    }
15173 
15174    memset(linksets, 0, sizeof(linksets));
15175    for (i = 0; i < NUM_SPANS; i++) {
15176       sig_ss7_init_linkset(&linksets[i].ss7);
15177    }
15178    ss7_set_error(dahdi_ss7_error);
15179    ss7_set_message(dahdi_ss7_message);
15180 #endif   /* defined(HAVE_SS7) */
15181 
15182    if (setup_dahdi(2) != 0) {
15183       ast_log(LOG_WARNING, "Reload channels from dahdi config failed!\n");
15184       ast_mutex_unlock(&ss_thread_lock);
15185       return 1;
15186    }
15187    ast_mutex_unlock(&ss_thread_lock);
15188    ast_mutex_unlock(&restart_lock);
15189    return 0;
15190 }
15191 
15192 static char *dahdi_restart_cmd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15193 {
15194    switch (cmd) {
15195    case CLI_INIT:
15196       e->command = "dahdi restart";
15197       e->usage =
15198          "Usage: dahdi restart\n"
15199          "  Restarts the DAHDI channels: destroys them all and then\n"
15200          "  re-reads them from chan_dahdi.conf.\n"
15201          "  Note that this will STOP any running CALL on DAHDI channels.\n"
15202          "";
15203       return NULL;
15204    case CLI_GENERATE:
15205       return NULL;
15206    }
15207    if (a->argc != 2)
15208       return CLI_SHOWUSAGE;
15209 
15210    if (dahdi_restart() != 0)
15211       return CLI_FAILURE;
15212    return CLI_SUCCESS;
15213 }
15214 
15215 static int action_dahdirestart(struct mansession *s, const struct message *m)
15216 {
15217    if (dahdi_restart() != 0) {
15218       astman_send_error(s, m, "Failed rereading DAHDI configuration");
15219       return 1;
15220    }
15221    astman_send_ack(s, m, "DAHDIRestart: Success");
15222    return 0;
15223 }
15224 
15225 static char *dahdi_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15226 {
15227 #define FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
15228 #define FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
15229    unsigned int targetnum = 0;
15230    int filtertype = 0;
15231    struct dahdi_pvt *tmp = NULL;
15232    char tmps[20] = "";
15233    char statestr[20] = "";
15234    char blockstr[20] = "";
15235 
15236    switch (cmd) {
15237    case CLI_INIT:
15238       e->command = "dahdi show channels [group|context]";
15239       e->usage =
15240          "Usage: dahdi show channels [ group <group> | context <context> ]\n"
15241          "  Shows a list of available channels with optional filtering\n"
15242          "  <group> must be a number between 0 and 63\n";
15243       return NULL;
15244    case CLI_GENERATE:
15245       return NULL;
15246    }
15247 
15248    /* syntax: dahdi show channels [ group <group> | context <context> ] */
15249 
15250    if (!((a->argc == 3) || (a->argc == 5)))
15251       return CLI_SHOWUSAGE;
15252 
15253    if (a->argc == 5) {
15254       if (!strcasecmp(a->argv[3], "group")) {
15255          targetnum = atoi(a->argv[4]);
15256          if ((targetnum < 0) || (targetnum > 63))
15257             return CLI_SHOWUSAGE;
15258          targetnum = 1 << targetnum;
15259          filtertype = 1;
15260       } else if (!strcasecmp(a->argv[3], "context")) {
15261          filtertype = 2;
15262       }
15263    }
15264 
15265    ast_cli(a->fd, FORMAT2, "Chan", "Extension", "Context", "Language", "MOH Interpret", "Blocked", "State");
15266    ast_mutex_lock(&iflock);
15267    for (tmp = iflist; tmp; tmp = tmp->next) {
15268       if (filtertype) {
15269          switch(filtertype) {
15270          case 1: /* dahdi show channels group <group> */
15271             if (!(tmp->group & targetnum)) {
15272                continue;
15273             }
15274             break;
15275          case 2: /* dahdi show channels context <context> */
15276             if (strcasecmp(tmp->context, a->argv[4])) {
15277                continue;
15278             }
15279             break;
15280          default:
15281             break;
15282          }
15283       }
15284       if (tmp->channel > 0) {
15285          snprintf(tmps, sizeof(tmps), "%d", tmp->channel);
15286       } else
15287          ast_copy_string(tmps, "pseudo", sizeof(tmps));
15288 
15289       if (tmp->locallyblocked)
15290          blockstr[0] = 'L';
15291       else
15292          blockstr[0] = ' ';
15293 
15294       if (tmp->remotelyblocked)
15295          blockstr[1] = 'R';
15296       else
15297          blockstr[1] = ' ';
15298 
15299       blockstr[2] = '\0';
15300 
15301       snprintf(statestr, sizeof(statestr), "%s", "In Service");
15302 
15303       ast_cli(a->fd, FORMAT, tmps, tmp->exten, tmp->context, tmp->language, tmp->mohinterpret, blockstr, statestr);
15304    }
15305    ast_mutex_unlock(&iflock);
15306    return CLI_SUCCESS;
15307 #undef FORMAT
15308 #undef FORMAT2
15309 }
15310 
15311 static char *dahdi_show_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15312 {
15313    int channel;
15314    struct dahdi_pvt *tmp = NULL;
15315    struct dahdi_confinfo ci;
15316    struct dahdi_params ps;
15317    int x;
15318 
15319    switch (cmd) {
15320    case CLI_INIT:
15321       e->command = "dahdi show channel";
15322       e->usage =
15323          "Usage: dahdi show channel <chan num>\n"
15324          "  Detailed information about a given channel\n";
15325       return NULL;
15326    case CLI_GENERATE:
15327       return NULL;
15328    }
15329 
15330    if (a->argc != 4)
15331       return CLI_SHOWUSAGE;
15332 
15333    channel = atoi(a->argv[3]);
15334 
15335    ast_mutex_lock(&iflock);
15336    for (tmp = iflist; tmp; tmp = tmp->next) {
15337       if (tmp->channel == channel) {
15338          ast_cli(a->fd, "Channel: %d\n", tmp->channel);
15339          ast_cli(a->fd, "File Descriptor: %d\n", tmp->subs[SUB_REAL].dfd);
15340          ast_cli(a->fd, "Span: %d\n", tmp->span);
15341          ast_cli(a->fd, "Extension: %s\n", tmp->exten);
15342          ast_cli(a->fd, "Dialing: %s\n", tmp->dialing ? "yes" : "no");
15343          ast_cli(a->fd, "Context: %s\n", tmp->context);
15344          ast_cli(a->fd, "Caller ID: %s\n", tmp->cid_num);
15345          ast_cli(a->fd, "Calling TON: %d\n", tmp->cid_ton);
15346 #if defined(HAVE_PRI)
15347 #if defined(HAVE_PRI_SUBADDR)
15348          ast_cli(a->fd, "Caller ID subaddress: %s\n", tmp->cid_subaddr);
15349 #endif   /* defined(HAVE_PRI_SUBADDR) */
15350 #endif   /* defined(HAVE_PRI) */
15351          ast_cli(a->fd, "Caller ID name: %s\n", tmp->cid_name);
15352          ast_cli(a->fd, "Mailbox: %s\n", S_OR(tmp->mailbox, "none"));
15353          if (tmp->vars) {
15354             struct ast_variable *v;
15355             ast_cli(a->fd, "Variables:\n");
15356             for (v = tmp->vars ; v ; v = v->next)
15357                ast_cli(a->fd, "       %s = %s\n", v->name, v->value);
15358          }
15359          ast_cli(a->fd, "Destroy: %d\n", tmp->destroy);
15360          ast_cli(a->fd, "InAlarm: %d\n", tmp->inalarm);
15361          ast_cli(a->fd, "Signalling Type: %s\n", sig2str(tmp->sig));
15362          ast_cli(a->fd, "Radio: %d\n", tmp->radio);
15363          ast_cli(a->fd, "Owner: %s\n", tmp->owner ? tmp->owner->name : "<None>");
15364          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)" : "");
15365          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)" : "");
15366          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)" : "");
15367          ast_cli(a->fd, "Confno: %d\n", tmp->confno);
15368          ast_cli(a->fd, "Propagated Conference: %d\n", tmp->propconfno);
15369          ast_cli(a->fd, "Real in conference: %d\n", tmp->inconference);
15370          ast_cli(a->fd, "DSP: %s\n", tmp->dsp ? "yes" : "no");
15371          ast_cli(a->fd, "Busy Detection: %s\n", tmp->busydetect ? "yes" : "no");
15372          if (tmp->busydetect) {
15373 #if defined(BUSYDETECT_TONEONLY)
15374             ast_cli(a->fd, "    Busy Detector Helper: BUSYDETECT_TONEONLY\n");
15375 #elif defined(BUSYDETECT_COMPARE_TONE_AND_SILENCE)
15376             ast_cli(a->fd, "    Busy Detector Helper: BUSYDETECT_COMPARE_TONE_AND_SILENCE\n");
15377 #endif
15378 #ifdef BUSYDETECT_DEBUG
15379             ast_cli(a->fd, "    Busy Detector Debug: Enabled\n");
15380 #endif
15381             ast_cli(a->fd, "    Busy Count: %d\n", tmp->busycount);
15382             ast_cli(a->fd, "    Busy Pattern: %d,%d\n", tmp->busytonelength, tmp->busyquietlength);
15383          }
15384          ast_cli(a->fd, "TDD: %s\n", tmp->tdd ? "yes" : "no");
15385          ast_cli(a->fd, "Relax DTMF: %s\n", tmp->dtmfrelax ? "yes" : "no");
15386          ast_cli(a->fd, "Dialing/CallwaitCAS: %d/%d\n", tmp->dialing, tmp->callwaitcas);
15387          ast_cli(a->fd, "Default law: %s\n", tmp->law_default == DAHDI_LAW_MULAW ? "ulaw" : tmp->law_default == DAHDI_LAW_ALAW ? "alaw" : "unknown");
15388          ast_cli(a->fd, "Fax Handled: %s\n", tmp->faxhandled ? "yes" : "no");
15389          ast_cli(a->fd, "Pulse phone: %s\n", tmp->pulsedial ? "yes" : "no");
15390          ast_cli(a->fd, "Gains (RX/TX): %.2f/%.2f\n", tmp->rxgain, tmp->txgain);
15391          ast_cli(a->fd, "Dynamic Range Compression (RX/TX): %.2f/%.2f\n", tmp->rxdrc, tmp->txdrc);
15392          ast_cli(a->fd, "DND: %s\n", dahdi_dnd(tmp, -1) ? "yes" : "no");
15393          ast_cli(a->fd, "Echo Cancellation:\n");
15394 
15395          if (tmp->echocancel.head.tap_length) {
15396             ast_cli(a->fd, "\t%d taps\n", tmp->echocancel.head.tap_length);
15397             for (x = 0; x < tmp->echocancel.head.param_count; x++) {
15398                ast_cli(a->fd, "\t\t%s: %ud\n", tmp->echocancel.params[x].name, tmp->echocancel.params[x].value);
15399             }
15400             ast_cli(a->fd, "\t%scurrently %s\n", tmp->echocanbridged ? "" : "(unless TDM bridged) ", tmp->echocanon ? "ON" : "OFF");
15401          } else {
15402             ast_cli(a->fd, "\tnone\n");
15403          }
15404          ast_cli(a->fd, "Wait for dialtone: %dms\n", tmp->waitfordialtone);
15405          if (tmp->master)
15406             ast_cli(a->fd, "Master Channel: %d\n", tmp->master->channel);
15407          for (x = 0; x < MAX_SLAVES; x++) {
15408             if (tmp->slaves[x])
15409                ast_cli(a->fd, "Slave Channel: %d\n", tmp->slaves[x]->channel);
15410          }
15411 #ifdef HAVE_OPENR2
15412          if (tmp->mfcr2) {
15413             char calldir[OR2_MAX_PATH];
15414             openr2_context_t *r2context = openr2_chan_get_context(tmp->r2chan);
15415             openr2_variant_t r2variant = openr2_context_get_variant(r2context);
15416             ast_cli(a->fd, "MFC/R2 MF State: %s\n", openr2_chan_get_mf_state_string(tmp->r2chan));
15417             ast_cli(a->fd, "MFC/R2 MF Group: %s\n", openr2_chan_get_mf_group_string(tmp->r2chan));
15418             ast_cli(a->fd, "MFC/R2 State: %s\n", openr2_chan_get_r2_state_string(tmp->r2chan));
15419             ast_cli(a->fd, "MFC/R2 Call State: %s\n", openr2_chan_get_call_state_string(tmp->r2chan));
15420             ast_cli(a->fd, "MFC/R2 Call Files Enabled: %s\n", openr2_chan_get_call_files_enabled(tmp->r2chan) ? "Yes" : "No");
15421             ast_cli(a->fd, "MFC/R2 Variant: %s\n", openr2_proto_get_variant_string(r2variant));
15422             ast_cli(a->fd, "MFC/R2 Max ANI: %d\n", openr2_context_get_max_ani(r2context));
15423             ast_cli(a->fd, "MFC/R2 Max DNIS: %d\n", openr2_context_get_max_dnis(r2context));
15424             ast_cli(a->fd, "MFC/R2 Get ANI First: %s\n", openr2_context_get_ani_first(r2context) ? "Yes" : "No");
15425 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
15426             ast_cli(a->fd, "MFC/R2 Skip Category Request: %s\n", openr2_context_get_skip_category_request(r2context) ? "Yes" : "No");
15427 #endif
15428             ast_cli(a->fd, "MFC/R2 Immediate Accept: %s\n", openr2_context_get_immediate_accept(r2context) ? "Yes" : "No");
15429             ast_cli(a->fd, "MFC/R2 Accept on Offer: %s\n", tmp->mfcr2_accept_on_offer ? "Yes" : "No");
15430             ast_cli(a->fd, "MFC/R2 Charge Calls: %s\n", tmp->mfcr2_charge_calls ? "Yes" : "No");
15431             ast_cli(a->fd, "MFC/R2 Allow Collect Calls: %s\n", tmp->mfcr2_allow_collect_calls ? "Yes" : "No");
15432             ast_cli(a->fd, "MFC/R2 Forced Release: %s\n", tmp->mfcr2_forced_release ? "Yes" : "No");
15433             ast_cli(a->fd, "MFC/R2 MF Back Timeout: %dms\n", openr2_context_get_mf_back_timeout(r2context));
15434             ast_cli(a->fd, "MFC/R2 R2 Metering Pulse Timeout: %dms\n", openr2_context_get_metering_pulse_timeout(r2context));
15435             ast_cli(a->fd, "MFC/R2 Rx CAS: %s\n", openr2_chan_get_rx_cas_string(tmp->r2chan));
15436             ast_cli(a->fd, "MFC/R2 Tx CAS: %s\n", openr2_chan_get_tx_cas_string(tmp->r2chan));
15437             ast_cli(a->fd, "MFC/R2 MF Tx Signal: %d\n", openr2_chan_get_tx_mf_signal(tmp->r2chan));
15438             ast_cli(a->fd, "MFC/R2 MF Rx Signal: %d\n", openr2_chan_get_rx_mf_signal(tmp->r2chan));
15439             ast_cli(a->fd, "MFC/R2 Call Files Directory: %s\n", openr2_context_get_log_directory(r2context, calldir, sizeof(calldir)));
15440          }
15441 #endif
15442 #if defined(HAVE_SS7)
15443          if (tmp->ss7) {
15444             struct sig_ss7_chan *chan = tmp->sig_pvt;
15445 
15446             ast_cli(a->fd, "CIC: %d\n", chan->cic);
15447          }
15448 #endif   /* defined(HAVE_SS7) */
15449 #ifdef HAVE_PRI
15450          if (tmp->pri) {
15451             struct sig_pri_chan *chan = tmp->sig_pvt;
15452 
15453             ast_cli(a->fd, "PRI Flags: ");
15454             if (chan->resetting != SIG_PRI_RESET_IDLE) {
15455                ast_cli(a->fd, "Resetting=%d ", chan->resetting);
15456             }
15457             if (chan->call)
15458                ast_cli(a->fd, "Call ");
15459             if (chan->allocated) {
15460                ast_cli(a->fd, "Allocated ");
15461             }
15462             ast_cli(a->fd, "\n");
15463             if (tmp->logicalspan)
15464                ast_cli(a->fd, "PRI Logical Span: %d\n", tmp->logicalspan);
15465             else
15466                ast_cli(a->fd, "PRI Logical Span: Implicit\n");
15467          }
15468 #endif
15469          memset(&ci, 0, sizeof(ci));
15470          ps.channo = tmp->channel;
15471          if (tmp->subs[SUB_REAL].dfd > -1) {
15472             memset(&ci, 0, sizeof(ci));
15473             if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
15474                ast_cli(a->fd, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci.confno, ci.confmode);
15475             }
15476             if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONFMUTE, &x)) {
15477                ast_cli(a->fd, "Actual Confmute: %s\n", x ? "Yes" : "No");
15478             }
15479             memset(&ps, 0, sizeof(ps));
15480             if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
15481                ast_log(LOG_WARNING, "Failed to get parameters on channel %d: %s\n", tmp->channel, strerror(errno));
15482             } else {
15483                ast_cli(a->fd, "Hookstate (FXS only): %s\n", ps.rxisoffhook ? "Offhook" : "Onhook");
15484             }
15485          }
15486          if (ISTRUNK(tmp)) {
15487             ast_cli(a->fd, "Call Progress: %s\n", tmp->callprogress ? "yes" : "no");  
15488             if (!ast_strlen_zero(progzone))
15489                ast_cli(a->fd, "Progress Zone: %s\n", progzone);
15490             ast_cli(a->fd, "Busy Detect: %s\n", tmp->busydetect ? "yes" : "no");  
15491             if(tmp->busydetect) {
15492                ast_cli(a->fd, "Busy Count: %d\n", tmp->busycount);
15493                if(tmp->busytonelength > 0) {
15494                   ast_cli(a->fd, "Busy Pattern:\n");
15495                   ast_cli(a->fd, " -- Tone Length: %6d ms\n", tmp->busytonelength);
15496                   if (tmp->busyquietlength > 0) 
15497                      ast_cli(a->fd, " -- Quiet Length: %6d ms\n", tmp->busyquietlength);
15498                   else 
15499                      ast_cli(a->fd, " -- Detect Tone Only\n");
15500                   if(tmp->busyfuzziness > 0)
15501                      ast_cli(a->fd, "Busy Pattern Fuziness: %d\n", tmp->busyfuzziness);
15502                }
15503             }
15504          }
15505          ast_mutex_unlock(&iflock);
15506          return CLI_SUCCESS;
15507       }
15508    }
15509    ast_mutex_unlock(&iflock);
15510 
15511    ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15512    return CLI_FAILURE;
15513 }
15514 
15515 static char *handle_dahdi_show_cadences(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15516 {
15517    int i, j;
15518    switch (cmd) {
15519    case CLI_INIT:
15520       e->command = "dahdi show cadences";
15521       e->usage =
15522          "Usage: dahdi show cadences\n"
15523          "       Shows all cadences currently defined\n";
15524       return NULL;
15525    case CLI_GENERATE:
15526       return NULL;
15527    }
15528    for (i = 0; i < num_cadence; i++) {
15529       char output[1024];
15530       char tmp[16], tmp2[64];
15531       snprintf(tmp, sizeof(tmp), "r%d: ", i + 1);
15532       term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output));
15533 
15534       for (j = 0; j < 16; j++) {
15535          if (cadences[i].ringcadence[j] == 0)
15536             break;
15537          snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]);
15538          if (cidrings[i] * 2 - 1 == j)
15539             term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1);
15540          else
15541             term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1);
15542          if (j != 0)
15543             strncat(output, ",", sizeof(output) - strlen(output) - 1);
15544          strncat(output, tmp2, sizeof(output) - strlen(output) - 1);
15545       }
15546       ast_cli(a->fd,"%s\n",output);
15547    }
15548    return CLI_SUCCESS;
15549 }
15550 
15551 /* Based on irqmiss.c */
15552 static char *dahdi_show_status(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15553 {
15554    #define FORMAT "%-40.40s %-7.7s %-6d %-6d %-6d %-3.3s %-4.4s %-8.8s %s\n"
15555    #define FORMAT2 "%-40.40s %-7.7s %-6.6s %-6.6s %-6.6s %-3.3s %-4.4s %-8.8s %s\n"
15556    int span;
15557    int res;
15558    char alarmstr[50];
15559 
15560    int ctl;
15561    struct dahdi_spaninfo s;
15562 
15563    switch (cmd) {
15564    case CLI_INIT:
15565       e->command = "dahdi show status";
15566       e->usage =
15567          "Usage: dahdi show status\n"
15568          "       Shows a list of DAHDI cards with status\n";
15569       return NULL;
15570    case CLI_GENERATE:
15571       return NULL;
15572    }
15573    ctl = open("/dev/dahdi/ctl", O_RDWR);
15574    if (ctl < 0) {
15575       ast_cli(a->fd, "No DAHDI found. Unable to open /dev/dahdi/ctl: %s\n", strerror(errno));
15576       return CLI_FAILURE;
15577    }
15578    ast_cli(a->fd, FORMAT2, "Description", "Alarms", "IRQ", "bpviol", "CRC", "Framing", "Coding", "Options", "LBO");
15579 
15580    for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
15581       s.spanno = span;
15582       res = ioctl(ctl, DAHDI_SPANSTAT, &s);
15583       if (res) {
15584          continue;
15585       }
15586       alarmstr[0] = '\0';
15587       if (s.alarms > 0) {
15588          if (s.alarms & DAHDI_ALARM_BLUE)
15589             strcat(alarmstr, "BLU/");
15590          if (s.alarms & DAHDI_ALARM_YELLOW)
15591             strcat(alarmstr, "YEL/");
15592          if (s.alarms & DAHDI_ALARM_RED)
15593             strcat(alarmstr, "RED/");
15594          if (s.alarms & DAHDI_ALARM_LOOPBACK)
15595             strcat(alarmstr, "LB/");
15596          if (s.alarms & DAHDI_ALARM_RECOVER)
15597             strcat(alarmstr, "REC/");
15598          if (s.alarms & DAHDI_ALARM_NOTOPEN)
15599             strcat(alarmstr, "NOP/");
15600          if (!strlen(alarmstr))
15601             strcat(alarmstr, "UUU/");
15602          if (strlen(alarmstr)) {
15603             /* Strip trailing / */
15604             alarmstr[strlen(alarmstr) - 1] = '\0';
15605          }
15606       } else {
15607          if (s.numchans)
15608             strcpy(alarmstr, "OK");
15609          else
15610             strcpy(alarmstr, "UNCONFIGURED");
15611       }
15612 
15613       ast_cli(a->fd, FORMAT, s.desc, alarmstr, s.irqmisses, s.bpvcount, s.crc4count,
15614          s.lineconfig & DAHDI_CONFIG_D4 ? "D4" :
15615          s.lineconfig & DAHDI_CONFIG_ESF ? "ESF" :
15616          s.lineconfig & DAHDI_CONFIG_CCS ? "CCS" :
15617          "CAS",
15618          s.lineconfig & DAHDI_CONFIG_B8ZS ? "B8ZS" :
15619          s.lineconfig & DAHDI_CONFIG_HDB3 ? "HDB3" :
15620          s.lineconfig & DAHDI_CONFIG_AMI ? "AMI" :
15621          "Unk",
15622          s.lineconfig & DAHDI_CONFIG_CRC4 ?
15623             s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" :
15624             s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "YEL" : "",
15625          lbostr[s.lbo]
15626          );
15627    }
15628    close(ctl);
15629 
15630    return CLI_SUCCESS;
15631 #undef FORMAT
15632 #undef FORMAT2
15633 }
15634 
15635 static char *dahdi_show_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15636 {
15637    int pseudo_fd = -1;
15638    struct dahdi_versioninfo vi;
15639 
15640    switch (cmd) {
15641    case CLI_INIT:
15642       e->command = "dahdi show version";
15643       e->usage =
15644          "Usage: dahdi show version\n"
15645          "       Shows the DAHDI version in use\n";
15646       return NULL;
15647    case CLI_GENERATE:
15648       return NULL;
15649    }
15650    if ((pseudo_fd = open("/dev/dahdi/ctl", O_RDONLY)) < 0) {
15651       ast_cli(a->fd, "Failed to open control file to get version.\n");
15652       return CLI_SUCCESS;
15653    }
15654 
15655    strcpy(vi.version, "Unknown");
15656    strcpy(vi.echo_canceller, "Unknown");
15657 
15658    if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi))
15659       ast_cli(a->fd, "Failed to get DAHDI version: %s\n", strerror(errno));
15660    else
15661       ast_cli(a->fd, "DAHDI Version: %s Echo Canceller: %s\n", vi.version, vi.echo_canceller);
15662 
15663    close(pseudo_fd);
15664 
15665    return CLI_SUCCESS;
15666 }
15667 
15668 static char *dahdi_set_hwgain(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15669 {
15670    int channel;
15671    int gain;
15672    int tx;
15673    struct dahdi_hwgain hwgain;
15674    struct dahdi_pvt *tmp = NULL;
15675 
15676    switch (cmd) {
15677    case CLI_INIT:
15678       e->command = "dahdi set hwgain";
15679       e->usage =
15680          "Usage: dahdi set hwgain <rx|tx> <chan#> <gain>\n"
15681          "  Sets the hardware gain on a a given channel, overriding the\n"
15682          "   value provided at module loadtime, whether the channel is in\n"
15683          "   use or not.  Changes take effect immediately.\n"
15684          "   <rx|tx> which direction do you want to change (relative to our module)\n"
15685          "   <chan num> is the channel number relative to the device\n"
15686          "   <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
15687       return NULL;
15688    case CLI_GENERATE:
15689       return NULL;
15690    }
15691 
15692    if (a->argc != 6)
15693       return CLI_SHOWUSAGE;
15694 
15695    if (!strcasecmp("rx", a->argv[3]))
15696       tx = 0; /* rx */
15697    else if (!strcasecmp("tx", a->argv[3]))
15698       tx = 1; /* tx */
15699    else
15700       return CLI_SHOWUSAGE;
15701 
15702    channel = atoi(a->argv[4]);
15703    gain = atof(a->argv[5])*10.0;
15704 
15705    ast_mutex_lock(&iflock);
15706 
15707    for (tmp = iflist; tmp; tmp = tmp->next) {
15708 
15709       if (tmp->channel != channel)
15710          continue;
15711 
15712       if (tmp->subs[SUB_REAL].dfd == -1)
15713          break;
15714 
15715       hwgain.newgain = gain;
15716       hwgain.tx = tx;
15717       if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_HWGAIN, &hwgain) < 0) {
15718          ast_cli(a->fd, "Unable to set the hardware gain for channel %d: %s\n", channel, strerror(errno));
15719          ast_mutex_unlock(&iflock);
15720          return CLI_FAILURE;
15721       }
15722       ast_cli(a->fd, "hardware %s gain set to %d (%.1f dB) on channel %d\n",
15723          tx ? "tx" : "rx", gain, (float)gain/10.0, channel);
15724       break;
15725    }
15726 
15727    ast_mutex_unlock(&iflock);
15728 
15729    if (tmp)
15730       return CLI_SUCCESS;
15731 
15732    ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15733    return CLI_FAILURE;
15734 
15735 }
15736 
15737 static char *dahdi_set_swgain(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15738 {
15739    int channel;
15740    float gain;
15741    int tx;
15742    int res;
15743    struct dahdi_pvt *tmp = NULL;
15744 
15745    switch (cmd) {
15746    case CLI_INIT:
15747       e->command = "dahdi set swgain";
15748       e->usage =
15749          "Usage: dahdi set swgain <rx|tx> <chan#> <gain>\n"
15750          "  Sets the software gain on a a given channel, overriding the\n"
15751          "   value provided at module loadtime, whether the channel is in\n"
15752          "   use or not.  Changes take effect immediately.\n"
15753          "   <rx|tx> which direction do you want to change (relative to our module)\n"
15754          "   <chan num> is the channel number relative to the device\n"
15755          "   <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
15756       return NULL;
15757    case CLI_GENERATE:
15758       return NULL;
15759    }
15760 
15761    if (a->argc != 6)
15762       return CLI_SHOWUSAGE;
15763 
15764    if (!strcasecmp("rx", a->argv[3]))
15765       tx = 0; /* rx */
15766    else if (!strcasecmp("tx", a->argv[3]))
15767       tx = 1; /* tx */
15768    else
15769       return CLI_SHOWUSAGE;
15770 
15771    channel = atoi(a->argv[4]);
15772    gain = atof(a->argv[5]);
15773 
15774    ast_mutex_lock(&iflock);
15775    for (tmp = iflist; tmp; tmp = tmp->next) {
15776 
15777       if (tmp->channel != channel)
15778          continue;
15779 
15780       if (tmp->subs[SUB_REAL].dfd == -1)
15781          break;
15782 
15783       if (tx)
15784          res = set_actual_txgain(tmp->subs[SUB_REAL].dfd, gain, tmp->txdrc, tmp->law);
15785       else
15786          res = set_actual_rxgain(tmp->subs[SUB_REAL].dfd, gain, tmp->rxdrc, tmp->law);
15787 
15788       if (res) {
15789          ast_cli(a->fd, "Unable to set the software gain for channel %d\n", channel);
15790          ast_mutex_unlock(&iflock);
15791          return CLI_FAILURE;
15792       }
15793 
15794       ast_cli(a->fd, "software %s gain set to %.1f on channel %d\n",
15795          tx ? "tx" : "rx", gain, channel);
15796       break;
15797    }
15798    ast_mutex_unlock(&iflock);
15799 
15800    if (tmp)
15801       return CLI_SUCCESS;
15802 
15803    ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15804    return CLI_FAILURE;
15805 
15806 }
15807 
15808 static char *dahdi_set_dnd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15809 {
15810    int channel;
15811    int on;
15812    struct dahdi_pvt *dahdi_chan = NULL;
15813 
15814    switch (cmd) {
15815    case CLI_INIT:
15816       e->command = "dahdi set dnd";
15817       e->usage =
15818          "Usage: dahdi set dnd <chan#> <on|off>\n"
15819          "  Sets/resets DND (Do Not Disturb) mode on a channel.\n"
15820          "  Changes take effect immediately.\n"
15821          "  <chan num> is the channel number\n"
15822          "  <on|off> Enable or disable DND mode?\n"
15823          ;
15824       return NULL;
15825    case CLI_GENERATE:
15826       return NULL;
15827    }
15828 
15829    if (a->argc != 5)
15830       return CLI_SHOWUSAGE;
15831 
15832    if ((channel = atoi(a->argv[3])) <= 0) {
15833       ast_cli(a->fd, "Expected channel number, got '%s'\n", a->argv[3]);
15834       return CLI_SHOWUSAGE;
15835    }
15836 
15837    if (ast_true(a->argv[4]))
15838       on = 1;
15839    else if (ast_false(a->argv[4]))
15840       on = 0;
15841    else {
15842       ast_cli(a->fd, "Expected 'on' or 'off', got '%s'\n", a->argv[4]);
15843       return CLI_SHOWUSAGE;
15844    }
15845 
15846    ast_mutex_lock(&iflock);
15847    for (dahdi_chan = iflist; dahdi_chan; dahdi_chan = dahdi_chan->next) {
15848       if (dahdi_chan->channel != channel)
15849          continue;
15850 
15851       /* Found the channel. Actually set it */
15852       dahdi_dnd(dahdi_chan, on);
15853       break;
15854    }
15855    ast_mutex_unlock(&iflock);
15856 
15857    if (!dahdi_chan) {
15858       ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15859       return CLI_FAILURE;
15860    }
15861 
15862    return CLI_SUCCESS;
15863 }
15864 
15865 static struct ast_cli_entry dahdi_cli[] = {
15866    AST_CLI_DEFINE(handle_dahdi_show_cadences, "List cadences"),
15867    AST_CLI_DEFINE(dahdi_show_channels, "Show active DAHDI channels"),
15868    AST_CLI_DEFINE(dahdi_show_channel, "Show information on a channel"),
15869    AST_CLI_DEFINE(dahdi_destroy_channel, "Destroy a channel"),
15870    AST_CLI_DEFINE(dahdi_restart_cmd, "Fully restart DAHDI channels"),
15871    AST_CLI_DEFINE(dahdi_show_status, "Show all DAHDI cards status"),
15872    AST_CLI_DEFINE(dahdi_show_version, "Show the DAHDI version in use"),
15873    AST_CLI_DEFINE(dahdi_set_hwgain, "Set hardware gain on a channel"),
15874    AST_CLI_DEFINE(dahdi_set_swgain, "Set software gain on a channel"),
15875    AST_CLI_DEFINE(dahdi_set_dnd, "Sets/resets DND (Do Not Disturb) mode on a channel"),
15876 };
15877 
15878 #define TRANSFER  0
15879 #define HANGUP    1
15880 
15881 static int dahdi_fake_event(struct dahdi_pvt *p, int mode)
15882 {
15883    if (p) {
15884       switch (mode) {
15885       case TRANSFER:
15886          p->fake_event = DAHDI_EVENT_WINKFLASH;
15887          break;
15888       case HANGUP:
15889          p->fake_event = DAHDI_EVENT_ONHOOK;
15890          break;
15891       default:
15892          ast_log(LOG_WARNING, "I don't know how to handle transfer event with this: %d on channel %s\n",mode, p->owner->name);
15893       }
15894    }
15895    return 0;
15896 }
15897 static struct dahdi_pvt *find_channel(int channel)
15898 {
15899    struct dahdi_pvt *p;
15900 
15901    ast_mutex_lock(&iflock);
15902    for (p = iflist; p; p = p->next) {
15903       if (p->channel == channel) {
15904          break;
15905       }
15906    }
15907    ast_mutex_unlock(&iflock);
15908    return p;
15909 }
15910 
15911 /*!
15912  * \internal
15913  * \brief Get private struct using given numeric channel string.
15914  *
15915  * \param channel Numeric channel number string get private struct.
15916  *
15917  * \retval pvt on success.
15918  * \retval NULL on error.
15919  */
15920 static struct dahdi_pvt *find_channel_from_str(const char *channel)
15921 {
15922    int chan_num;
15923 
15924    if (sscanf(channel, "%30d", &chan_num) != 1) {
15925       /* Not numeric string. */
15926       return NULL;
15927    }
15928 
15929    return find_channel(chan_num);
15930 }
15931 
15932 static int action_dahdidndon(struct mansession *s, const struct message *m)
15933 {
15934    struct dahdi_pvt *p;
15935    const char *channel = astman_get_header(m, "DAHDIChannel");
15936 
15937    if (ast_strlen_zero(channel)) {
15938       astman_send_error(s, m, "No channel specified");
15939       return 0;
15940    }
15941    p = find_channel_from_str(channel);
15942    if (!p) {
15943       astman_send_error(s, m, "No such channel");
15944       return 0;
15945    }
15946    dahdi_dnd(p, 1);
15947    astman_send_ack(s, m, "DND Enabled");
15948    return 0;
15949 }
15950 
15951 static int action_dahdidndoff(struct mansession *s, const struct message *m)
15952 {
15953    struct dahdi_pvt *p;
15954    const char *channel = astman_get_header(m, "DAHDIChannel");
15955 
15956    if (ast_strlen_zero(channel)) {
15957       astman_send_error(s, m, "No channel specified");
15958       return 0;
15959    }
15960    p = find_channel_from_str(channel);
15961    if (!p) {
15962       astman_send_error(s, m, "No such channel");
15963       return 0;
15964    }
15965    dahdi_dnd(p, 0);
15966    astman_send_ack(s, m, "DND Disabled");
15967    return 0;
15968 }
15969 
15970 static int action_transfer(struct mansession *s, const struct message *m)
15971 {
15972    struct dahdi_pvt *p;
15973    const char *channel = astman_get_header(m, "DAHDIChannel");
15974 
15975    if (ast_strlen_zero(channel)) {
15976       astman_send_error(s, m, "No channel specified");
15977       return 0;
15978    }
15979    p = find_channel_from_str(channel);
15980    if (!p) {
15981       astman_send_error(s, m, "No such channel");
15982       return 0;
15983    }
15984    if (!analog_lib_handles(p->sig, 0, 0)) {
15985       astman_send_error(s, m, "Channel signaling is not analog");
15986       return 0;
15987    }
15988    dahdi_fake_event(p,TRANSFER);
15989    astman_send_ack(s, m, "DAHDITransfer");
15990    return 0;
15991 }
15992 
15993 static int action_transferhangup(struct mansession *s, const struct message *m)
15994 {
15995    struct dahdi_pvt *p;
15996    const char *channel = astman_get_header(m, "DAHDIChannel");
15997 
15998    if (ast_strlen_zero(channel)) {
15999       astman_send_error(s, m, "No channel specified");
16000       return 0;
16001    }
16002    p = find_channel_from_str(channel);
16003    if (!p) {
16004       astman_send_error(s, m, "No such channel");
16005       return 0;
16006    }
16007    if (!analog_lib_handles(p->sig, 0, 0)) {
16008       astman_send_error(s, m, "Channel signaling is not analog");
16009       return 0;
16010    }
16011    dahdi_fake_event(p,HANGUP);
16012    astman_send_ack(s, m, "DAHDIHangup");
16013    return 0;
16014 }
16015 
16016 static int action_dahdidialoffhook(struct mansession *s, const struct message *m)
16017 {
16018    struct dahdi_pvt *p;
16019    const char *channel = astman_get_header(m, "DAHDIChannel");
16020    const char *number = astman_get_header(m, "Number");
16021    int i;
16022 
16023    if (ast_strlen_zero(channel)) {
16024       astman_send_error(s, m, "No channel specified");
16025       return 0;
16026    }
16027    if (ast_strlen_zero(number)) {
16028       astman_send_error(s, m, "No number specified");
16029       return 0;
16030    }
16031    p = find_channel_from_str(channel);
16032    if (!p) {
16033       astman_send_error(s, m, "No such channel");
16034       return 0;
16035    }
16036    if (!p->owner) {
16037       astman_send_error(s, m, "Channel does not have it's owner");
16038       return 0;
16039    }
16040    for (i = 0; i < strlen(number); i++) {
16041       struct ast_frame f = { AST_FRAME_DTMF, .subclass.integer = number[i] };
16042       dahdi_queue_frame(p, &f);
16043    }
16044    astman_send_ack(s, m, "DAHDIDialOffhook");
16045    return 0;
16046 }
16047 
16048 static int action_dahdishowchannels(struct mansession *s, const struct message *m)
16049 {
16050    struct dahdi_pvt *tmp = NULL;
16051    const char *id = astman_get_header(m, "ActionID");
16052    const char *dahdichannel = astman_get_header(m, "DAHDIChannel");
16053    char idText[256] = "";
16054    int channels = 0;
16055    int dahdichanquery;
16056 
16057    if (!dahdichannel || sscanf(dahdichannel, "%30d", &dahdichanquery) != 1) {
16058       /* Not numeric string. */
16059       dahdichanquery = -1;
16060    }
16061 
16062    astman_send_ack(s, m, "DAHDI channel status will follow");
16063    if (!ast_strlen_zero(id))
16064       snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
16065 
16066    ast_mutex_lock(&iflock);
16067 
16068    for (tmp = iflist; tmp; tmp = tmp->next) {
16069       if (tmp->channel > 0) {
16070          int alm;
16071 
16072          /* If a specific channel is queried for, only deliver status for that channel */
16073          if (dahdichanquery > 0 && tmp->channel != dahdichanquery)
16074             continue;
16075 
16076          alm = get_alarms(tmp);
16077          channels++;
16078          if (tmp->owner) {
16079             /* Add data if we have a current call */
16080             astman_append(s,
16081                "Event: DAHDIShowChannels\r\n"
16082                "DAHDIChannel: %d\r\n"
16083                "Channel: %s\r\n"
16084                "Uniqueid: %s\r\n"
16085                "AccountCode: %s\r\n"
16086                "Signalling: %s\r\n"
16087                "SignallingCode: %d\r\n"
16088                "Context: %s\r\n"
16089                "DND: %s\r\n"
16090                "Alarm: %s\r\n"
16091                "%s"
16092                "\r\n",
16093                tmp->channel,
16094                tmp->owner->name,
16095                tmp->owner->uniqueid,
16096                tmp->owner->accountcode,
16097                sig2str(tmp->sig),
16098                tmp->sig,
16099                tmp->context,
16100                dahdi_dnd(tmp, -1) ? "Enabled" : "Disabled",
16101                alarm2str(alm), idText);
16102          } else {
16103             astman_append(s,
16104                "Event: DAHDIShowChannels\r\n"
16105                "DAHDIChannel: %d\r\n"
16106                "Signalling: %s\r\n"
16107                "SignallingCode: %d\r\n"
16108                "Context: %s\r\n"
16109                "DND: %s\r\n"
16110                "Alarm: %s\r\n"
16111                "%s"
16112                "\r\n",
16113                tmp->channel, sig2str(tmp->sig), tmp->sig,
16114                tmp->context,
16115                dahdi_dnd(tmp, -1) ? "Enabled" : "Disabled",
16116                alarm2str(alm), idText);
16117          }
16118       }
16119    }
16120 
16121    ast_mutex_unlock(&iflock);
16122 
16123    astman_append(s,
16124       "Event: DAHDIShowChannelsComplete\r\n"
16125       "%s"
16126       "Items: %d\r\n"
16127       "\r\n",
16128       idText,
16129       channels);
16130    return 0;
16131 }
16132 
16133 #if defined(HAVE_SS7)
16134 static int linkset_addsigchan(int sigchan)
16135 {
16136    struct dahdi_ss7 *link;
16137    int res;
16138    int curfd;
16139    struct dahdi_params params;
16140    struct dahdi_bufferinfo bi;
16141    struct dahdi_spaninfo si;
16142 
16143    if (sigchan < 0) {
16144       ast_log(LOG_ERROR, "Invalid sigchan!\n");
16145       return -1;
16146    }
16147    if (cur_ss7type < 0) {
16148       ast_log(LOG_ERROR, "Unspecified or invalid ss7type\n");
16149       return -1;
16150    }
16151    if (cur_pointcode < 0) {
16152       ast_log(LOG_ERROR, "Unspecified pointcode!\n");
16153       return -1;
16154    }
16155    if (cur_adjpointcode < 0) {
16156       ast_log(LOG_ERROR, "Unspecified adjpointcode!\n");
16157       return -1;
16158    }
16159    if (cur_defaultdpc < 0) {
16160       ast_log(LOG_ERROR, "Unspecified defaultdpc!\n");
16161       return -1;
16162    }
16163    if (cur_networkindicator < 0) {
16164       ast_log(LOG_ERROR, "Invalid networkindicator!\n");
16165       return -1;
16166    }
16167    link = ss7_resolve_linkset(cur_linkset);
16168    if (!link) {
16169       ast_log(LOG_ERROR, "Invalid linkset number.  Must be between 1 and %d\n", NUM_SPANS + 1);
16170       return -1;
16171    }
16172    if (link->ss7.numsigchans >= SIG_SS7_NUM_DCHANS) {
16173       ast_log(LOG_ERROR, "Too many sigchans on linkset %d\n", cur_linkset);
16174       return -1;
16175    }
16176 
16177    curfd = link->ss7.numsigchans;
16178 
16179    /* Open signaling channel */
16180    link->ss7.fds[curfd] = open("/dev/dahdi/channel", O_RDWR, 0600);
16181    if (link->ss7.fds[curfd] < 0) {
16182       ast_log(LOG_ERROR, "Unable to open SS7 sigchan %d (%s)\n", sigchan,
16183          strerror(errno));
16184       return -1;
16185    }
16186    if (ioctl(link->ss7.fds[curfd], DAHDI_SPECIFY, &sigchan) == -1) {
16187       dahdi_close_ss7_fd(link, curfd);
16188       ast_log(LOG_ERROR, "Unable to specify SS7 sigchan %d (%s)\n", sigchan,
16189          strerror(errno));
16190       return -1;
16191    }
16192 
16193    /* Get signaling channel parameters */
16194    memset(&params, 0, sizeof(params));
16195    res = ioctl(link->ss7.fds[curfd], DAHDI_GET_PARAMS, &params);
16196    if (res) {
16197       dahdi_close_ss7_fd(link, curfd);
16198       ast_log(LOG_ERROR, "Unable to get parameters for sigchan %d (%s)\n", sigchan,
16199          strerror(errno));
16200       return -1;
16201    }
16202    if (params.sigtype != DAHDI_SIG_HDLCFCS
16203       && params.sigtype != DAHDI_SIG_HARDHDLC
16204       && params.sigtype != DAHDI_SIG_MTP2) {
16205       dahdi_close_ss7_fd(link, curfd);
16206       ast_log(LOG_ERROR, "sigchan %d is not in HDLC/FCS mode.\n", sigchan);
16207       return -1;
16208    }
16209 
16210    /* Set signaling channel buffer policy. */
16211    memset(&bi, 0, sizeof(bi));
16212    bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
16213    bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
16214    bi.numbufs = 32;
16215    bi.bufsize = 512;
16216    if (ioctl(link->ss7.fds[curfd], DAHDI_SET_BUFINFO, &bi)) {
16217       ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n",
16218          sigchan, strerror(errno));
16219       dahdi_close_ss7_fd(link, curfd);
16220       return -1;
16221    }
16222 
16223    /* Get current signaling channel alarm status. */
16224    memset(&si, 0, sizeof(si));
16225    res = ioctl(link->ss7.fds[curfd], DAHDI_SPANSTAT, &si);
16226    if (res) {
16227       dahdi_close_ss7_fd(link, curfd);
16228       ast_log(LOG_ERROR, "Unable to get span state for sigchan %d (%s)\n", sigchan,
16229          strerror(errno));
16230    }
16231 
16232    res = sig_ss7_add_sigchan(&link->ss7, curfd, cur_ss7type,
16233       (params.sigtype == DAHDI_SIG_MTP2)
16234          ? SS7_TRANSPORT_DAHDIMTP2
16235          : SS7_TRANSPORT_DAHDIDCHAN,
16236       si.alarms, cur_networkindicator, cur_pointcode, cur_adjpointcode);
16237    if (res) {
16238       dahdi_close_ss7_fd(link, curfd);
16239       return -1;
16240    }
16241 
16242    ++link->ss7.numsigchans;
16243 
16244    return 0;
16245 }
16246 #endif   /* defined(HAVE_SS7) */
16247 
16248 #if defined(HAVE_SS7)
16249 static char *handle_ss7_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16250 {
16251    int span;
16252    switch (cmd) {
16253    case CLI_INIT:
16254       e->command = "ss7 set debug {on|off} linkset";
16255       e->usage =
16256          "Usage: ss7 set debug {on|off} linkset <linkset>\n"
16257          "       Enables debugging on a given SS7 linkset\n";
16258       return NULL;
16259    case CLI_GENERATE:
16260       return NULL;
16261    }
16262    if (a->argc < 6)
16263       return CLI_SHOWUSAGE;
16264    span = atoi(a->argv[5]);
16265    if ((span < 1) || (span > NUM_SPANS)) {
16266       ast_cli(a->fd, "Invalid linkset %s.  Should be a number from %d to %d\n", a->argv[5], 1, NUM_SPANS);
16267       return CLI_SUCCESS;
16268    }
16269    if (!linksets[span-1].ss7.ss7) {
16270       ast_cli(a->fd, "No SS7 running on linkset %d\n", span);
16271    } else {
16272       if (!strcasecmp(a->argv[3], "on")) {
16273          linksets[span - 1].ss7.debug = 1;
16274          ss7_set_debug(linksets[span-1].ss7.ss7, SIG_SS7_DEBUG);
16275          ast_cli(a->fd, "Enabled debugging on linkset %d\n", span);
16276       } else {
16277          linksets[span - 1].ss7.debug = 0;
16278          ss7_set_debug(linksets[span-1].ss7.ss7, 0);
16279          ast_cli(a->fd, "Disabled debugging on linkset %d\n", span);
16280       }
16281    }
16282 
16283    return CLI_SUCCESS;
16284 }
16285 #endif   /* defined(HAVE_SS7) */
16286 
16287 #if defined(HAVE_SS7)
16288 static char *handle_ss7_block_cic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16289 {
16290    int linkset, cic;
16291    int blocked = -1, i;
16292    switch (cmd) {
16293    case CLI_INIT:
16294       e->command = "ss7 block cic";
16295       e->usage =
16296          "Usage: ss7 block cic <linkset> <CIC>\n"
16297          "       Sends a remote blocking request for the given CIC on the specified linkset\n";
16298       return NULL;
16299    case CLI_GENERATE:
16300       return NULL;
16301    }
16302    if (a->argc == 5)
16303       linkset = atoi(a->argv[3]);
16304    else
16305       return CLI_SHOWUSAGE;
16306 
16307    if ((linkset < 1) || (linkset > NUM_SPANS)) {
16308       ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16309       return CLI_SUCCESS;
16310    }
16311 
16312    if (!linksets[linkset-1].ss7.ss7) {
16313       ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16314       return CLI_SUCCESS;
16315    }
16316 
16317    cic = atoi(a->argv[4]);
16318 
16319    if (cic < 1) {
16320       ast_cli(a->fd, "Invalid CIC specified!\n");
16321       return CLI_SUCCESS;
16322    }
16323 
16324    for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
16325       if (linksets[linkset-1].ss7.pvts[i]->cic == cic) {
16326          blocked = linksets[linkset-1].ss7.pvts[i]->locallyblocked;
16327          if (!blocked) {
16328             ast_mutex_lock(&linksets[linkset-1].ss7.lock);
16329             isup_blo(linksets[linkset-1].ss7.ss7, cic, linksets[linkset-1].ss7.pvts[i]->dpc);
16330             ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
16331          }
16332       }
16333    }
16334 
16335    if (blocked < 0) {
16336       ast_cli(a->fd, "Invalid CIC specified!\n");
16337       return CLI_SUCCESS;
16338    }
16339 
16340    if (!blocked)
16341       ast_cli(a->fd, "Sent blocking request for linkset %d on CIC %d\n", linkset, cic);
16342    else
16343       ast_cli(a->fd, "CIC %d already locally blocked\n", cic);
16344 
16345    /* Break poll on the linkset so it sends our messages */
16346    pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
16347 
16348    return CLI_SUCCESS;
16349 }
16350 #endif   /* defined(HAVE_SS7) */
16351 
16352 #if defined(HAVE_SS7)
16353 static char *handle_ss7_block_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16354 {
16355    int linkset;
16356    int i;
16357    switch (cmd) {
16358    case CLI_INIT:
16359       e->command = "ss7 block linkset";
16360       e->usage =
16361          "Usage: ss7 block linkset <linkset number>\n"
16362          "       Sends a remote blocking request for all CICs on the given linkset\n";
16363       return NULL;
16364    case CLI_GENERATE:
16365       return NULL;
16366    }
16367    if (a->argc == 4)
16368       linkset = atoi(a->argv[3]);
16369    else
16370       return CLI_SHOWUSAGE;
16371 
16372    if ((linkset < 1) || (linkset > NUM_SPANS)) {
16373       ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16374       return CLI_SUCCESS;
16375    }
16376 
16377    if (!linksets[linkset-1].ss7.ss7) {
16378       ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16379       return CLI_SUCCESS;
16380    }
16381 
16382    for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
16383       ast_cli(a->fd, "Sending remote blocking request on CIC %d\n", linksets[linkset-1].ss7.pvts[i]->cic);
16384       ast_mutex_lock(&linksets[linkset-1].ss7.lock);
16385       isup_blo(linksets[linkset-1].ss7.ss7, linksets[linkset-1].ss7.pvts[i]->cic, linksets[linkset-1].ss7.pvts[i]->dpc);
16386       ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
16387    }
16388 
16389    /* Break poll on the linkset so it sends our messages */
16390    pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
16391 
16392    return CLI_SUCCESS;
16393 }
16394 #endif   /* defined(HAVE_SS7) */
16395 
16396 #if defined(HAVE_SS7)
16397 static char *handle_ss7_unblock_cic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16398 {
16399    int linkset, cic;
16400    int i, blocked = -1;
16401    switch (cmd) {
16402    case CLI_INIT:
16403       e->command = "ss7 unblock cic";
16404       e->usage =
16405          "Usage: ss7 unblock cic <linkset> <CIC>\n"
16406          "       Sends a remote unblocking request for the given CIC on the specified linkset\n";
16407       return NULL;
16408    case CLI_GENERATE:
16409       return NULL;
16410    }
16411 
16412    if (a->argc == 5)
16413       linkset = atoi(a->argv[3]);
16414    else
16415       return CLI_SHOWUSAGE;
16416 
16417    if ((linkset < 1) || (linkset > NUM_SPANS)) {
16418       ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16419       return CLI_SUCCESS;
16420    }
16421 
16422    if (!linksets[linkset-1].ss7.ss7) {
16423       ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16424       return CLI_SUCCESS;
16425    }
16426 
16427    cic = atoi(a->argv[4]);
16428 
16429    if (cic < 1) {
16430       ast_cli(a->fd, "Invalid CIC specified!\n");
16431       return CLI_SUCCESS;
16432    }
16433 
16434    for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
16435       if (linksets[linkset-1].ss7.pvts[i]->cic == cic) {
16436          blocked = linksets[linkset-1].ss7.pvts[i]->locallyblocked;
16437          if (blocked) {
16438             ast_mutex_lock(&linksets[linkset-1].ss7.lock);
16439             isup_ubl(linksets[linkset-1].ss7.ss7, cic, linksets[linkset-1].ss7.pvts[i]->dpc);
16440             ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
16441          }
16442       }
16443    }
16444 
16445    if (blocked > 0)
16446       ast_cli(a->fd, "Sent unblocking request for linkset %d on CIC %d\n", linkset, cic);
16447 
16448    /* Break poll on the linkset so it sends our messages */
16449    pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
16450 
16451    return CLI_SUCCESS;
16452 }
16453 #endif   /* defined(HAVE_SS7) */
16454 
16455 #if defined(HAVE_SS7)
16456 static char *handle_ss7_unblock_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16457 {
16458    int linkset;
16459    int i;
16460    switch (cmd) {
16461    case CLI_INIT:
16462       e->command = "ss7 unblock linkset";
16463       e->usage =
16464          "Usage: ss7 unblock linkset <linkset number>\n"
16465          "       Sends a remote unblocking request for all CICs on the specified linkset\n";
16466       return NULL;
16467    case CLI_GENERATE:
16468       return NULL;
16469    }
16470 
16471    if (a->argc == 4)
16472       linkset = atoi(a->argv[3]);
16473    else
16474       return CLI_SHOWUSAGE;
16475 
16476    if ((linkset < 1) || (linkset > NUM_SPANS)) {
16477       ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16478       return CLI_SUCCESS;
16479    }
16480 
16481    if (!linksets[linkset-1].ss7.ss7) {
16482       ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16483       return CLI_SUCCESS;
16484    }
16485 
16486    for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
16487       ast_cli(a->fd, "Sending remote unblock request on CIC %d\n", linksets[linkset-1].ss7.pvts[i]->cic);
16488       ast_mutex_lock(&linksets[linkset-1].ss7.lock);
16489       isup_ubl(linksets[linkset-1].ss7.ss7, linksets[linkset-1].ss7.pvts[i]->cic, linksets[linkset-1].ss7.pvts[i]->dpc);
16490       ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
16491    }
16492 
16493    /* Break poll on the linkset so it sends our messages */
16494    pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
16495 
16496    return CLI_SUCCESS;
16497 }
16498 #endif   /* defined(HAVE_SS7) */
16499 
16500 #if defined(HAVE_SS7)
16501 static char *handle_ss7_show_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16502 {
16503    int linkset;
16504    struct sig_ss7_linkset *ss7;
16505    switch (cmd) {
16506    case CLI_INIT:
16507       e->command = "ss7 show linkset";
16508       e->usage =
16509          "Usage: ss7 show linkset <span>\n"
16510          "       Shows the status of an SS7 linkset.\n";
16511       return NULL;
16512    case CLI_GENERATE:
16513       return NULL;
16514    }
16515 
16516    if (a->argc < 4)
16517       return CLI_SHOWUSAGE;
16518    linkset = atoi(a->argv[3]);
16519    if ((linkset < 1) || (linkset > NUM_SPANS)) {
16520       ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16521       return CLI_SUCCESS;
16522    }
16523    ss7 = &linksets[linkset - 1].ss7;
16524    if (!ss7->ss7) {
16525       ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16526       return CLI_SUCCESS;
16527    }
16528 
16529    ast_cli(a->fd, "SS7 linkset %d status: %s\n", linkset, (ss7->state == LINKSET_STATE_UP) ? "Up" : "Down");
16530 
16531    return CLI_SUCCESS;
16532 }
16533 #endif   /* defined(HAVE_SS7) */
16534 
16535 #if defined(HAVE_SS7)
16536 static char *handle_ss7_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16537 {
16538    int linkset;
16539 
16540    switch (cmd) {
16541    case CLI_INIT:
16542       e->command = "ss7 show channels";
16543       e->usage =
16544          "Usage: ss7 show channels\n"
16545          "       Displays SS7 channel information at a glance.\n";
16546       return NULL;
16547    case CLI_GENERATE:
16548       return NULL;
16549    }
16550 
16551    if (a->argc != 3)
16552       return CLI_SHOWUSAGE;
16553 
16554    sig_ss7_cli_show_channels_header(a->fd);
16555    for (linkset = 0; linkset < NUM_SPANS; ++linkset) {
16556       if (linksets[linkset].ss7.ss7) {
16557          sig_ss7_cli_show_channels(a->fd, &linksets[linkset].ss7);
16558       }
16559    }
16560    return CLI_SUCCESS;
16561 }
16562 #endif   /* defined(HAVE_SS7) */
16563 
16564 #if defined(HAVE_SS7)
16565 static char *handle_ss7_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16566 {
16567    switch (cmd) {
16568    case CLI_INIT:
16569       e->command = "ss7 show version";
16570       e->usage =
16571          "Usage: ss7 show version\n"
16572          "  Show the libss7 version\n";
16573       return NULL;
16574    case CLI_GENERATE:
16575       return NULL;
16576    }
16577 
16578    ast_cli(a->fd, "libss7 version: %s\n", ss7_get_version());
16579 
16580    return CLI_SUCCESS;
16581 }
16582 #endif   /* defined(HAVE_SS7) */
16583 
16584 #if defined(HAVE_SS7)
16585 static struct ast_cli_entry dahdi_ss7_cli[] = {
16586    AST_CLI_DEFINE(handle_ss7_debug, "Enables SS7 debugging on a linkset"),
16587    AST_CLI_DEFINE(handle_ss7_block_cic, "Blocks the given CIC"),
16588    AST_CLI_DEFINE(handle_ss7_unblock_cic, "Unblocks the given CIC"),
16589    AST_CLI_DEFINE(handle_ss7_block_linkset, "Blocks all CICs on a linkset"),
16590    AST_CLI_DEFINE(handle_ss7_unblock_linkset, "Unblocks all CICs on a linkset"),
16591    AST_CLI_DEFINE(handle_ss7_show_linkset, "Shows the status of a linkset"),
16592    AST_CLI_DEFINE(handle_ss7_show_channels, "Displays SS7 channel information"),
16593    AST_CLI_DEFINE(handle_ss7_version, "Displays libss7 version"),
16594 };
16595 #endif   /* defined(HAVE_SS7) */
16596 
16597 #if defined(HAVE_PRI)
16598 #if defined(HAVE_PRI_CCSS)
16599 /*!
16600  * \internal
16601  * \brief CC agent initialization.
16602  * \since 1.8
16603  *
16604  * \param agent CC core agent control.
16605  * \param chan Original channel the agent will attempt to recall.
16606  *
16607  * \details
16608  * This callback is called when the CC core is initialized.  Agents should allocate
16609  * any private data necessary for the call and assign it to the private_data
16610  * on the agent.  Additionally, if any ast_cc_agent_flags are pertinent to the
16611  * specific agent type, they should be set in this function as well.
16612  *
16613  * \retval 0 on success.
16614  * \retval -1 on error.
16615  */
16616 static int dahdi_pri_cc_agent_init(struct ast_cc_agent *agent, struct ast_channel *chan)
16617 {
16618    struct dahdi_pvt *pvt;
16619    struct sig_pri_chan *pvt_chan;
16620    int res;
16621 
16622    ast_assert(!strcmp(chan->tech->type, "DAHDI"));
16623 
16624    pvt = chan->tech_pvt;
16625    if (dahdi_sig_pri_lib_handles(pvt->sig)) {
16626       pvt_chan = pvt->sig_pvt;
16627    } else {
16628       pvt_chan = NULL;
16629    }
16630    if (!pvt_chan) {
16631       return -1;
16632    }
16633 
16634    ast_module_ref(ast_module_info->self);
16635 
16636    res = sig_pri_cc_agent_init(agent, pvt_chan);
16637    if (res) {
16638       ast_module_unref(ast_module_info->self);
16639    }
16640    return res;
16641 }
16642 #endif   /* defined(HAVE_PRI_CCSS) */
16643 #endif   /* defined(HAVE_PRI) */
16644 
16645 #if defined(HAVE_PRI)
16646 #if defined(HAVE_PRI_CCSS)
16647 /*!
16648  * \internal
16649  * \brief Destroy private data on the agent.
16650  * \since 1.8
16651  *
16652  * \param agent CC core agent control.
16653  *
16654  * \details
16655  * The core will call this function upon completion
16656  * or failure of CC.
16657  *
16658  * \return Nothing
16659  */
16660 static void dahdi_pri_cc_agent_destructor(struct ast_cc_agent *agent)
16661 {
16662    sig_pri_cc_agent_destructor(agent);
16663 
16664    ast_module_unref(ast_module_info->self);
16665 }
16666 #endif   /* defined(HAVE_PRI_CCSS) */
16667 #endif   /* defined(HAVE_PRI) */
16668 
16669 #if defined(HAVE_PRI)
16670 #if defined(HAVE_PRI_CCSS)
16671 static struct ast_cc_agent_callbacks dahdi_pri_cc_agent_callbacks = {
16672    .type = dahdi_pri_cc_type,
16673    .init = dahdi_pri_cc_agent_init,
16674    .start_offer_timer = sig_pri_cc_agent_start_offer_timer,
16675    .stop_offer_timer = sig_pri_cc_agent_stop_offer_timer,
16676    .respond = sig_pri_cc_agent_req_rsp,
16677    .status_request = sig_pri_cc_agent_status_req,
16678    .stop_ringing = sig_pri_cc_agent_stop_ringing,
16679    .party_b_free = sig_pri_cc_agent_party_b_free,
16680    .start_monitoring = sig_pri_cc_agent_start_monitoring,
16681    .callee_available = sig_pri_cc_agent_callee_available,
16682    .destructor = dahdi_pri_cc_agent_destructor,
16683 };
16684 #endif   /* defined(HAVE_PRI_CCSS) */
16685 #endif   /* defined(HAVE_PRI) */
16686 
16687 #if defined(HAVE_PRI)
16688 #if defined(HAVE_PRI_CCSS)
16689 static struct ast_cc_monitor_callbacks dahdi_pri_cc_monitor_callbacks = {
16690    .type = dahdi_pri_cc_type,
16691    .request_cc = sig_pri_cc_monitor_req_cc,
16692    .suspend = sig_pri_cc_monitor_suspend,
16693    .unsuspend = sig_pri_cc_monitor_unsuspend,
16694    .status_response = sig_pri_cc_monitor_status_rsp,
16695    .cancel_available_timer = sig_pri_cc_monitor_cancel_available_timer,
16696    .destructor = sig_pri_cc_monitor_destructor,
16697 };
16698 #endif   /* defined(HAVE_PRI_CCSS) */
16699 #endif   /* defined(HAVE_PRI) */
16700 
16701 static int __unload_module(void)
16702 {
16703    struct dahdi_pvt *p;
16704 #if defined(HAVE_PRI) || defined(HAVE_SS7)
16705    int i, j;
16706 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
16707 
16708 #ifdef HAVE_PRI
16709    for (i = 0; i < NUM_SPANS; i++) {
16710       if (pris[i].pri.master != AST_PTHREADT_NULL)
16711          pthread_cancel(pris[i].pri.master);
16712    }
16713    ast_cli_unregister_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
16714    ast_unregister_application(dahdi_send_keypad_facility_app);
16715 #ifdef HAVE_PRI_PROG_W_CAUSE
16716    ast_unregister_application(dahdi_send_callrerouting_facility_app);
16717 #endif
16718 #endif
16719 #if defined(HAVE_SS7)
16720    for (i = 0; i < NUM_SPANS; i++) {
16721       if (linksets[i].ss7.master != AST_PTHREADT_NULL)
16722          pthread_cancel(linksets[i].ss7.master);
16723       }
16724    ast_cli_unregister_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
16725 #endif   /* defined(HAVE_SS7) */
16726 #if defined(HAVE_OPENR2)
16727    dahdi_r2_destroy_links();
16728    ast_cli_unregister_multiple(dahdi_mfcr2_cli, ARRAY_LEN(dahdi_mfcr2_cli));
16729    ast_unregister_application(dahdi_accept_r2_call_app);
16730 #endif
16731 
16732    ast_cli_unregister_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli));
16733    ast_manager_unregister("DAHDIDialOffhook");
16734    ast_manager_unregister("DAHDIHangup");
16735    ast_manager_unregister("DAHDITransfer");
16736    ast_manager_unregister("DAHDIDNDoff");
16737    ast_manager_unregister("DAHDIDNDon");
16738    ast_manager_unregister("DAHDIShowChannels");
16739    ast_manager_unregister("DAHDIRestart");
16740    ast_data_unregister(NULL);
16741    ast_channel_unregister(&dahdi_tech);
16742 
16743    /* Hangup all interfaces if they have an owner */
16744    ast_mutex_lock(&iflock);
16745    for (p = iflist; p; p = p->next) {
16746       if (p->owner)
16747          ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
16748    }
16749    ast_mutex_unlock(&iflock);
16750 
16751    ast_mutex_lock(&monlock);
16752    if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
16753       pthread_cancel(monitor_thread);
16754       pthread_kill(monitor_thread, SIGURG);
16755       pthread_join(monitor_thread, NULL);
16756    }
16757    monitor_thread = AST_PTHREADT_STOP;
16758    ast_mutex_unlock(&monlock);
16759 
16760    destroy_all_channels();
16761 
16762 #if defined(HAVE_PRI)
16763    for (i = 0; i < NUM_SPANS; i++) {
16764       if (pris[i].pri.master && (pris[i].pri.master != AST_PTHREADT_NULL))
16765          pthread_join(pris[i].pri.master, NULL);
16766       for (j = 0; j < SIG_PRI_NUM_DCHANS; j++) {
16767          dahdi_close_pri_fd(&(pris[i]), j);
16768       }
16769       sig_pri_stop_pri(&pris[i].pri);
16770    }
16771 #if defined(HAVE_PRI_CCSS)
16772    ast_cc_agent_unregister(&dahdi_pri_cc_agent_callbacks);
16773    ast_cc_monitor_unregister(&dahdi_pri_cc_monitor_callbacks);
16774 #endif   /* defined(HAVE_PRI_CCSS) */
16775    sig_pri_unload();
16776 #endif
16777 
16778 #if defined(HAVE_SS7)
16779    for (i = 0; i < NUM_SPANS; i++) {
16780       if (linksets[i].ss7.master && (linksets[i].ss7.master != AST_PTHREADT_NULL))
16781          pthread_join(linksets[i].ss7.master, NULL);
16782       for (j = 0; j < SIG_SS7_NUM_DCHANS; j++) {
16783          dahdi_close_ss7_fd(&(linksets[i]), j);
16784       }
16785    }
16786 #endif   /* defined(HAVE_SS7) */
16787    ast_cond_destroy(&ss_thread_complete);
16788    return 0;
16789 }
16790 
16791 static int unload_module(void)
16792 {
16793 #if defined(HAVE_PRI) || defined(HAVE_SS7)
16794    int y;
16795 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
16796 #ifdef HAVE_PRI
16797    for (y = 0; y < NUM_SPANS; y++)
16798       ast_mutex_destroy(&pris[y].pri.lock);
16799 #endif
16800 #if defined(HAVE_SS7)
16801    for (y = 0; y < NUM_SPANS; y++)
16802       ast_mutex_destroy(&linksets[y].ss7.lock);
16803 #endif   /* defined(HAVE_SS7) */
16804    return __unload_module();
16805 }
16806 
16807 static void string_replace(char *str, int char1, int char2)
16808 {
16809    for (; *str; str++) {
16810       if (*str == char1) {
16811          *str = char2;
16812       }
16813    }
16814 }
16815 
16816 static char *parse_spanchan(char *chanstr, char **subdir)
16817 {
16818    char *p;
16819 
16820    if ((p = strrchr(chanstr, '!')) == NULL) {
16821       *subdir = NULL;
16822       return chanstr;
16823    }
16824    *p++ = '\0';
16825    string_replace(chanstr, '!', '/');
16826    *subdir = chanstr;
16827    return p;
16828 }
16829 
16830 static int build_channels(struct dahdi_chan_conf *conf, const char *value, int reload, int lineno, int *found_pseudo)
16831 {
16832    char *c, *chan;
16833    char *subdir;
16834    int x, start, finish;
16835    struct dahdi_pvt *tmp;
16836 
16837    if ((reload == 0) && (conf->chan.sig < 0) && !conf->is_sig_auto) {
16838       ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n");
16839       return -1;
16840    }
16841 
16842    c = ast_strdupa(value);
16843    c = parse_spanchan(c, &subdir);
16844 
16845    while ((chan = strsep(&c, ","))) {
16846       if (sscanf(chan, "%30d-%30d", &start, &finish) == 2) {
16847          /* Range */
16848       } else if (sscanf(chan, "%30d", &start)) {
16849          /* Just one */
16850          finish = start;
16851       } else if (!strcasecmp(chan, "pseudo")) {
16852          finish = start = CHAN_PSEUDO;
16853          if (found_pseudo)
16854             *found_pseudo = 1;
16855       } else {
16856          ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan);
16857          return -1;
16858       }
16859       if (finish < start) {
16860          ast_log(LOG_WARNING, "Sillyness: %d < %d\n", start, finish);
16861          x = finish;
16862          finish = start;
16863          start = x;
16864       }
16865 
16866       for (x = start; x <= finish; x++) {
16867          char fn[PATH_MAX];
16868          int real_channel = x;
16869 
16870          if (!ast_strlen_zero(subdir)) {
16871             real_channel = device2chan(subdir, x, fn, sizeof(fn));
16872             if (real_channel < 0) {
16873                if (conf->ignore_failed_channels) {
16874                   ast_log(LOG_WARNING, "Failed configuring %s!%d, (got %d). But moving on to others.\n",
16875                         subdir, x, real_channel);
16876                   continue;
16877                } else {
16878                   ast_log(LOG_ERROR, "Failed configuring %s!%d, (got %d).\n",
16879                         subdir, x, real_channel);
16880                   return -1;
16881                }
16882             }
16883          }
16884          tmp = mkintf(real_channel, conf, reload);
16885 
16886          if (tmp) {
16887             ast_verb(3, "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", real_channel, sig2str(tmp->sig));
16888          } else {
16889             ast_log(LOG_ERROR, "Unable to %s channel '%s'\n",
16890                   (reload == 1) ? "reconfigure" : "register", value);
16891             return -1;
16892          }
16893       }
16894    }
16895 
16896    return 0;
16897 }
16898 
16899 /** The length of the parameters list of 'dahdichan'.
16900  * \todo Move definition of MAX_CHANLIST_LEN to a proper place. */
16901 #define MAX_CHANLIST_LEN 80
16902 
16903 static void process_echocancel(struct dahdi_chan_conf *confp, const char *data, unsigned int line)
16904 {
16905    char *parse = ast_strdupa(data);
16906    char *params[DAHDI_MAX_ECHOCANPARAMS + 1];
16907    unsigned int param_count;
16908    unsigned int x;
16909 
16910    if (!(param_count = ast_app_separate_args(parse, ',', params, ARRAY_LEN(params))))
16911       return;
16912 
16913    memset(&confp->chan.echocancel, 0, sizeof(confp->chan.echocancel));
16914 
16915    /* first parameter is tap length, process it here */
16916 
16917    x = ast_strlen_zero(params[0]) ? 0 : atoi(params[0]);
16918 
16919    if ((x == 32) || (x == 64) || (x == 128) || (x == 256) || (x == 512) || (x == 1024))
16920       confp->chan.echocancel.head.tap_length = x;
16921    else if ((confp->chan.echocancel.head.tap_length = ast_true(params[0])))
16922       confp->chan.echocancel.head.tap_length = 128;
16923 
16924    /* now process any remaining parameters */
16925 
16926    for (x = 1; x < param_count; x++) {
16927       struct {
16928          char *name;
16929          char *value;
16930       } param;
16931 
16932       if (ast_app_separate_args(params[x], '=', (char **) &param, 2) < 1) {
16933          ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, params[x]);
16934          continue;
16935       }
16936 
16937       if (ast_strlen_zero(param.name) || (strlen(param.name) > sizeof(confp->chan.echocancel.params[0].name)-1)) {
16938          ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, param.name);
16939          continue;
16940       }
16941 
16942       strcpy(confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].name, param.name);
16943 
16944       if (param.value) {
16945          if (sscanf(param.value, "%30d", &confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].value) != 1) {
16946             ast_log(LOG_WARNING, "Invalid echocancel parameter value supplied at line %d: '%s'\n", line, param.value);
16947             continue;
16948          }
16949       }
16950       confp->chan.echocancel.head.param_count++;
16951    }
16952 }
16953 
16954 /*! process_dahdi() - ignore keyword 'channel' and similar */
16955 #define PROC_DAHDI_OPT_NOCHAN  (1 << 0)
16956 /*! process_dahdi() - No warnings on non-existing cofiguration keywords */
16957 #define PROC_DAHDI_OPT_NOWARN  (1 << 1)
16958 
16959 static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct ast_variable *v, int reload, int options)
16960 {
16961    struct dahdi_pvt *tmp;
16962    int y;
16963    int found_pseudo = 0;
16964    struct ast_variable *dahdichan = NULL;
16965 
16966    for (; v; v = v->next) {
16967       if (!ast_jb_read_conf(&global_jbconf, v->name, v->value))
16968          continue;
16969 
16970       /* Create the interface list */
16971       if (!strcasecmp(v->name, "channel") || !strcasecmp(v->name, "channels")) {
16972          if (options & PROC_DAHDI_OPT_NOCHAN) {
16973             ast_log(LOG_WARNING, "Channel '%s' ignored.\n", v->value);
16974             continue;
16975          }
16976          if (build_channels(confp, v->value, reload, v->lineno, &found_pseudo)) {
16977             if (confp->ignore_failed_channels) {
16978                ast_log(LOG_WARNING, "Channel '%s' failure ignored: ignore_failed_channels.\n", v->value);
16979                continue;
16980             } else {
16981                return -1;
16982             }
16983          }
16984          ast_log(LOG_DEBUG, "Channel '%s' configured.\n", v->value);
16985       } else if (!strcasecmp(v->name, "ignore_failed_channels")) {
16986          confp->ignore_failed_channels = ast_true(v->value);
16987       } else if (!strcasecmp(v->name, "buffers")) {
16988          if (parse_buffers_policy(v->value, &confp->chan.buf_no, &confp->chan.buf_policy)) {
16989             ast_log(LOG_WARNING, "Using default buffer policy.\n");
16990             confp->chan.buf_no = numbufs;
16991             confp->chan.buf_policy = DAHDI_POLICY_IMMEDIATE;
16992          }
16993       } else if (!strcasecmp(v->name, "faxbuffers")) {
16994          if (!parse_buffers_policy(v->value, &confp->chan.faxbuf_no, &confp->chan.faxbuf_policy)) {
16995             confp->chan.usefaxbuffers = 1;
16996          }
16997       } else if (!strcasecmp(v->name, "dahdichan")) {
16998          /* Only process the last dahdichan value. */
16999          dahdichan = v;
17000       } else if (!strcasecmp(v->name, "usedistinctiveringdetection")) {
17001          usedistinctiveringdetection = ast_true(v->value);
17002       } else if (!strcasecmp(v->name, "distinctiveringaftercid")) {
17003          distinctiveringaftercid = ast_true(v->value);
17004       } else if (!strcasecmp(v->name, "dring1context")) {
17005          ast_copy_string(confp->chan.drings.ringContext[0].contextData,v->value,sizeof(confp->chan.drings.ringContext[0].contextData));
17006       } else if (!strcasecmp(v->name, "dring2context")) {
17007          ast_copy_string(confp->chan.drings.ringContext[1].contextData,v->value,sizeof(confp->chan.drings.ringContext[1].contextData));
17008       } else if (!strcasecmp(v->name, "dring3context")) {
17009          ast_copy_string(confp->chan.drings.ringContext[2].contextData,v->value,sizeof(confp->chan.drings.ringContext[2].contextData));
17010       } else if (!strcasecmp(v->name, "dring1range")) {
17011          confp->chan.drings.ringnum[0].range = atoi(v->value);
17012       } else if (!strcasecmp(v->name, "dring2range")) {
17013          confp->chan.drings.ringnum[1].range = atoi(v->value);
17014       } else if (!strcasecmp(v->name, "dring3range")) {
17015          confp->chan.drings.ringnum[2].range = atoi(v->value);
17016       } else if (!strcasecmp(v->name, "dring1")) {
17017          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]);
17018       } else if (!strcasecmp(v->name, "dring2")) {
17019          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]);
17020       } else if (!strcasecmp(v->name, "dring3")) {
17021          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]);
17022       } else if (!strcasecmp(v->name, "usecallerid")) {
17023          confp->chan.use_callerid = ast_true(v->value);
17024       } else if (!strcasecmp(v->name, "cidsignalling")) {
17025          if (!strcasecmp(v->value, "bell"))
17026             confp->chan.cid_signalling = CID_SIG_BELL;
17027          else if (!strcasecmp(v->value, "v23"))
17028             confp->chan.cid_signalling = CID_SIG_V23;
17029          else if (!strcasecmp(v->value, "dtmf"))
17030             confp->chan.cid_signalling = CID_SIG_DTMF;
17031          else if (!strcasecmp(v->value, "smdi"))
17032             confp->chan.cid_signalling = CID_SIG_SMDI;
17033          else if (!strcasecmp(v->value, "v23_jp"))
17034             confp->chan.cid_signalling = CID_SIG_V23_JP;
17035          else if (ast_true(v->value))
17036             confp->chan.cid_signalling = CID_SIG_BELL;
17037       } else if (!strcasecmp(v->name, "cidstart")) {
17038          if (!strcasecmp(v->value, "ring"))
17039             confp->chan.cid_start = CID_START_RING;
17040          else if (!strcasecmp(v->value, "polarity_in"))
17041             confp->chan.cid_start = CID_START_POLARITY_IN;
17042          else if (!strcasecmp(v->value, "polarity"))
17043             confp->chan.cid_start = CID_START_POLARITY;
17044          else if (!strcasecmp(v->value, "dtmf"))
17045             confp->chan.cid_start = CID_START_DTMF_NOALERT;
17046          else if (ast_true(v->value))
17047             confp->chan.cid_start = CID_START_RING;
17048       } else if (!strcasecmp(v->name, "threewaycalling")) {
17049          confp->chan.threewaycalling = ast_true(v->value);
17050       } else if (!strcasecmp(v->name, "cancallforward")) {
17051          confp->chan.cancallforward = ast_true(v->value);
17052       } else if (!strcasecmp(v->name, "relaxdtmf")) {
17053          if (ast_true(v->value))
17054             confp->chan.dtmfrelax = DSP_DIGITMODE_RELAXDTMF;
17055          else
17056             confp->chan.dtmfrelax = 0;
17057       } else if (!strcasecmp(v->name, "mailbox")) {
17058          ast_copy_string(confp->chan.mailbox, v->value, sizeof(confp->chan.mailbox));
17059       } else if (!strcasecmp(v->name, "hasvoicemail")) {
17060          if (ast_true(v->value) && ast_strlen_zero(confp->chan.mailbox)) {
17061             ast_copy_string(confp->chan.mailbox, cat, sizeof(confp->chan.mailbox));
17062          }
17063       } else if (!strcasecmp(v->name, "adsi")) {
17064          confp->chan.adsi = ast_true(v->value);
17065       } else if (!strcasecmp(v->name, "usesmdi")) {
17066          confp->chan.use_smdi = ast_true(v->value);
17067       } else if (!strcasecmp(v->name, "smdiport")) {
17068          ast_copy_string(confp->smdi_port, v->value, sizeof(confp->smdi_port));
17069       } else if (!strcasecmp(v->name, "transfer")) {
17070          confp->chan.transfer = ast_true(v->value);
17071       } else if (!strcasecmp(v->name, "canpark")) {
17072          confp->chan.canpark = ast_true(v->value);
17073       } else if (!strcasecmp(v->name, "echocancelwhenbridged")) {
17074          confp->chan.echocanbridged = ast_true(v->value);
17075       } else if (!strcasecmp(v->name, "busydetect")) {
17076          confp->chan.busydetect = ast_true(v->value);
17077       } else if (!strcasecmp(v->name, "busycount")) {
17078          confp->chan.busycount = atoi(v->value);
17079       } else if (!strcasecmp(v->name, "silencethreshold")) {
17080          confp->chan.silencethreshold = atoi(v->value);
17081       } else if (!strcasecmp(v->name, "busycompare")) {
17082          confp->chan.busycompare = ast_true(v->value);
17083       } else if (!strcasecmp(v->name, "busypattern")) {
17084          if (sscanf(v->value, "%30d,%30d", &confp->chan.busytonelength, &confp->chan.busyquietlength) != 2) {
17085             ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength,quietlength at line %d.\n", v->lineno);
17086          }
17087          int count = sscanf(v->value, "%d,%d", &confp->chan.busytonelength, &confp->chan.busyquietlength);
17088          if (count == 1)
17089             confp->chan.busyquietlength = 0;
17090          else if (count < 1)
17091             ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength[,quietlength] at line %d.\n", v->lineno);
17092       } else if (!strcasecmp(v->name, "busyfuzziness")) {
17093          confp->chan.busyfuzziness = atoi(v->value);
17094       } else if (!strcasecmp(v->name, "callprogress")) {
17095          confp->chan.callprogress &= ~CALLPROGRESS_PROGRESS;
17096          if (ast_true(v->value))
17097             confp->chan.callprogress |= CALLPROGRESS_PROGRESS;
17098       } else if (!strcasecmp(v->name, "waitfordialtone")) {
17099          confp->chan.waitfordialtone = atoi(v->value);
17100       } else if (!strcasecmp(v->name, "faxdetect")) {
17101          confp->chan.callprogress &= ~CALLPROGRESS_FAX;
17102          if (!strcasecmp(v->value, "incoming")) {
17103             confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING;
17104          } else if (!strcasecmp(v->value, "outgoing")) {
17105             confp->chan.callprogress |= CALLPROGRESS_FAX_OUTGOING;
17106          } else if (!strcasecmp(v->value, "both") || ast_true(v->value))
17107             confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING;
17108       } else if (!strcasecmp(v->name, "echocancel")) {
17109          process_echocancel(confp, v->value, v->lineno);
17110       } else if (!strcasecmp(v->name, "echotraining")) {
17111          if (sscanf(v->value, "%30d", &y) == 1) {
17112             if ((y < 10) || (y > 4000)) {
17113                ast_log(LOG_WARNING, "Echo training time must be within the range of 10 to 4000 ms at line %d.\n", v->lineno);
17114             } else {
17115                confp->chan.echotraining = y;
17116             }
17117          } else if (ast_true(v->value)) {
17118             confp->chan.echotraining = 400;
17119          } else
17120             confp->chan.echotraining = 0;
17121       } else if (!strcasecmp(v->name, "hidecallerid")) {
17122          confp->chan.hidecallerid = ast_true(v->value);
17123       } else if (!strcasecmp(v->name, "hidecalleridname")) {
17124          confp->chan.hidecalleridname = ast_true(v->value);
17125       } else if (!strcasecmp(v->name, "pulsedial")) {
17126          confp->chan.pulse = ast_true(v->value);
17127       } else if (!strcasecmp(v->name, "callreturn")) {
17128          confp->chan.callreturn = ast_true(v->value);
17129       } else if (!strcasecmp(v->name, "callwaiting")) {
17130          confp->chan.callwaiting = ast_true(v->value);
17131       } else if (!strcasecmp(v->name, "callwaitingcallerid")) {
17132          confp->chan.callwaitingcallerid = ast_true(v->value);
17133       } else if (!strcasecmp(v->name, "context")) {
17134          ast_copy_string(confp->chan.context, v->value, sizeof(confp->chan.context));
17135       } else if (!strcasecmp(v->name, "language")) {
17136          ast_copy_string(confp->chan.language, v->value, sizeof(confp->chan.language));
17137       } else if (!strcasecmp(v->name, "progzone")) {
17138          ast_copy_string(progzone, v->value, sizeof(progzone));
17139       } else if (!strcasecmp(v->name, "mohinterpret")
17140          ||!strcasecmp(v->name, "musiconhold") || !strcasecmp(v->name, "musicclass")) {
17141          ast_copy_string(confp->chan.mohinterpret, v->value, sizeof(confp->chan.mohinterpret));
17142       } else if (!strcasecmp(v->name, "mohsuggest")) {
17143          ast_copy_string(confp->chan.mohsuggest, v->value, sizeof(confp->chan.mohsuggest));
17144       } else if (!strcasecmp(v->name, "parkinglot")) {
17145          ast_copy_string(confp->chan.parkinglot, v->value, sizeof(confp->chan.parkinglot));
17146       } else if (!strcasecmp(v->name, "stripmsd")) {
17147          ast_log(LOG_NOTICE, "Configuration option \"%s\" has been deprecated. Please use dialplan instead\n", v->name);
17148          confp->chan.stripmsd = atoi(v->value);
17149       } else if (!strcasecmp(v->name, "jitterbuffers")) {
17150          numbufs = atoi(v->value);
17151       } else if (!strcasecmp(v->name, "group")) {
17152          confp->chan.group = ast_get_group(v->value);
17153       } else if (!strcasecmp(v->name, "callgroup")) {
17154          if (!strcasecmp(v->value, "none"))
17155             confp->chan.callgroup = 0;
17156          else
17157             confp->chan.callgroup = ast_get_group(v->value);
17158       } else if (!strcasecmp(v->name, "pickupgroup")) {
17159          if (!strcasecmp(v->value, "none"))
17160             confp->chan.pickupgroup = 0;
17161          else
17162             confp->chan.pickupgroup = ast_get_group(v->value);
17163       } else if (!strcasecmp(v->name, "setvar")) {
17164          char *varname = ast_strdupa(v->value), *varval = NULL;
17165          struct ast_variable *tmpvar;
17166          if (varname && (varval = strchr(varname, '='))) {
17167             *varval++ = '\0';
17168             if ((tmpvar = ast_variable_new(varname, varval, ""))) {
17169                tmpvar->next = confp->chan.vars;
17170                confp->chan.vars = tmpvar;
17171             }
17172          }
17173       } else if (!strcasecmp(v->name, "immediate")) {
17174          confp->chan.immediate = ast_true(v->value);
17175       } else if (!strcasecmp(v->name, "transfertobusy")) {
17176          confp->chan.transfertobusy = ast_true(v->value);
17177       } else if (!strcasecmp(v->name, "mwimonitor")) {
17178          confp->chan.mwimonitor_neon = 0;
17179          confp->chan.mwimonitor_fsk = 0;
17180          confp->chan.mwimonitor_rpas = 0;
17181          if (strcasestr(v->value, "fsk")) {
17182             confp->chan.mwimonitor_fsk = 1;
17183          }
17184          if (strcasestr(v->value, "rpas")) {
17185             confp->chan.mwimonitor_rpas = 1;
17186          }
17187          if (strcasestr(v->value, "neon")) {
17188             confp->chan.mwimonitor_neon = 1;
17189          }
17190          /* If set to true or yes, assume that simple fsk is desired */
17191          if (ast_true(v->value)) {
17192             confp->chan.mwimonitor_fsk = 1;
17193          }
17194       } else if (!strcasecmp(v->name, "cid_rxgain")) {
17195          if (sscanf(v->value, "%30f", &confp->chan.cid_rxgain) != 1) {
17196             ast_log(LOG_WARNING, "Invalid cid_rxgain: %s at line %d.\n", v->value, v->lineno);
17197          }
17198       } else if (!strcasecmp(v->name, "rxgain")) {
17199          if (sscanf(v->value, "%30f", &confp->chan.rxgain) != 1) {
17200             ast_log(LOG_WARNING, "Invalid rxgain: %s at line %d.\n", v->value, v->lineno);
17201          }
17202       } else if (!strcasecmp(v->name, "txgain")) {
17203          if (sscanf(v->value, "%30f", &confp->chan.txgain) != 1) {
17204             ast_log(LOG_WARNING, "Invalid txgain: %s at line %d.\n", v->value, v->lineno);
17205          }
17206       } else if (!strcasecmp(v->name, "txdrc")) {
17207          if (sscanf(v->value, "%f", &confp->chan.txdrc) != 1) {
17208             ast_log(LOG_WARNING, "Invalid txdrc: %s\n", v->value);
17209          }
17210       } else if (!strcasecmp(v->name, "rxdrc")) {
17211          if (sscanf(v->value, "%f", &confp->chan.rxdrc) != 1) {
17212             ast_log(LOG_WARNING, "Invalid rxdrc: %s\n", v->value);
17213          }
17214       } else if (!strcasecmp(v->name, "tonezone")) {
17215          if (sscanf(v->value, "%30d", &confp->chan.tonezone) != 1) {
17216             ast_log(LOG_WARNING, "Invalid tonezone: %s at line %d.\n", v->value, v->lineno);
17217          }
17218       } else if (!strcasecmp(v->name, "callerid")) {
17219          if (!strcasecmp(v->value, "asreceived")) {
17220             confp->chan.cid_num[0] = '\0';
17221             confp->chan.cid_name[0] = '\0';
17222          } else {
17223             ast_callerid_split(v->value, confp->chan.cid_name, sizeof(confp->chan.cid_name), confp->chan.cid_num, sizeof(confp->chan.cid_num));
17224          }
17225       } else if (!strcasecmp(v->name, "fullname")) {
17226          ast_copy_string(confp->chan.cid_name, v->value, sizeof(confp->chan.cid_name));
17227       } else if (!strcasecmp(v->name, "cid_number")) {
17228          ast_copy_string(confp->chan.cid_num, v->value, sizeof(confp->chan.cid_num));
17229       } else if (!strcasecmp(v->name, "cid_tag")) {
17230          ast_copy_string(confp->chan.cid_tag, v->value, sizeof(confp->chan.cid_tag));
17231       } else if (!strcasecmp(v->name, "useincomingcalleridondahditransfer")) {
17232          confp->chan.dahditrcallerid = ast_true(v->value);
17233       } else if (!strcasecmp(v->name, "restrictcid")) {
17234          confp->chan.restrictcid = ast_true(v->value);
17235       } else if (!strcasecmp(v->name, "usecallingpres")) {
17236          confp->chan.use_callingpres = ast_true(v->value);
17237       } else if (!strcasecmp(v->name, "accountcode")) {
17238          ast_copy_string(confp->chan.accountcode, v->value, sizeof(confp->chan.accountcode));
17239       } else if (!strcasecmp(v->name, "amaflags")) {
17240          y = ast_cdr_amaflags2int(v->value);
17241          if (y < 0)
17242             ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d.\n", v->value, v->lineno);
17243          else
17244             confp->chan.amaflags = y;
17245       } else if (!strcasecmp(v->name, "polarityonanswerdelay")) {
17246          confp->chan.polarityonanswerdelay = atoi(v->value);
17247       } else if (!strcasecmp(v->name, "answeronpolarityswitch")) {
17248          confp->chan.answeronpolarityswitch = ast_true(v->value);
17249       } else if (!strcasecmp(v->name, "hanguponpolarityswitch")) {
17250          confp->chan.hanguponpolarityswitch = ast_true(v->value);
17251       } else if (!strcasecmp(v->name, "sendcalleridafter")) {
17252          confp->chan.sendcalleridafter = atoi(v->value);
17253       } else if (!strcasecmp(v->name, "mwimonitornotify")) {
17254          ast_copy_string(mwimonitornotify, v->value, sizeof(mwimonitornotify));
17255       } else if (ast_cc_is_config_param(v->name)) {
17256          ast_cc_set_param(confp->chan.cc_params, v->name, v->value);
17257       } else if (!strcasecmp(v->name, "mwisendtype")) {
17258 #ifndef HAVE_DAHDI_LINEREVERSE_VMWI  /* backward compatibility for older dahdi VMWI implementation */
17259          if (!strcasecmp(v->value, "rpas")) { /* Ring Pulse Alert Signal */
17260             mwisend_rpas = 1;
17261          } else {
17262             mwisend_rpas = 0;
17263          }
17264 #else
17265          /* Default is fsk, to turn it off you must specify nofsk */
17266          memset(&confp->chan.mwisend_setting, 0, sizeof(confp->chan.mwisend_setting));
17267          if (strcasestr(v->value, "nofsk")) {      /* NoFSK */
17268             confp->chan.mwisend_fsk = 0;
17269          } else {             /* Default FSK */
17270             confp->chan.mwisend_fsk = 1;
17271          }
17272          if (strcasestr(v->value, "rpas")) {       /* Ring Pulse Alert Signal, normally followed by FSK */
17273             confp->chan.mwisend_rpas = 1;
17274          } else {
17275             confp->chan.mwisend_rpas = 0;
17276          }
17277          if (strcasestr(v->value, "lrev")) {       /* Line Reversal */
17278             confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_LREV;
17279          }
17280          if (strcasestr(v->value, "hvdc")) {       /* HV 90VDC */
17281             confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_HVDC;
17282          }
17283          if ( (strcasestr(v->value, "neon")) || (strcasestr(v->value, "hvac")) ){   /* 90V DC pulses */
17284             confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_HVAC;
17285          }
17286 #endif
17287       } else if (reload != 1) {
17288           if (!strcasecmp(v->name, "signalling") || !strcasecmp(v->name, "signaling")) {
17289             int orig_radio = confp->chan.radio;
17290             int orig_outsigmod = confp->chan.outsigmod;
17291             int orig_auto = confp->is_sig_auto;
17292 
17293             confp->chan.radio = 0;
17294             confp->chan.outsigmod = -1;
17295             confp->is_sig_auto = 0;
17296             if (!strcasecmp(v->value, "em")) {
17297                confp->chan.sig = SIG_EM;
17298             } else if (!strcasecmp(v->value, "em_e1")) {
17299                confp->chan.sig = SIG_EM_E1;
17300             } else if (!strcasecmp(v->value, "em_w")) {
17301                confp->chan.sig = SIG_EMWINK;
17302             } else if (!strcasecmp(v->value, "fxs_ls")) {
17303                confp->chan.sig = SIG_FXSLS;
17304             } else if (!strcasecmp(v->value, "fxs_gs")) {
17305                confp->chan.sig = SIG_FXSGS;
17306             } else if (!strcasecmp(v->value, "fxs_ks")) {
17307                confp->chan.sig = SIG_FXSKS;
17308             } else if (!strcasecmp(v->value, "fxo_ls")) {
17309                confp->chan.sig = SIG_FXOLS;
17310             } else if (!strcasecmp(v->value, "fxo_gs")) {
17311                confp->chan.sig = SIG_FXOGS;
17312             } else if (!strcasecmp(v->value, "fxo_ks")) {
17313                confp->chan.sig = SIG_FXOKS;
17314             } else if (!strcasecmp(v->value, "fxs_rx")) {
17315                confp->chan.sig = SIG_FXSKS;
17316                confp->chan.radio = 1;
17317             } else if (!strcasecmp(v->value, "fxo_rx")) {
17318                confp->chan.sig = SIG_FXOLS;
17319                confp->chan.radio = 1;
17320             } else if (!strcasecmp(v->value, "fxs_tx")) {
17321                confp->chan.sig = SIG_FXSLS;
17322                confp->chan.radio = 1;
17323             } else if (!strcasecmp(v->value, "fxo_tx")) {
17324                confp->chan.sig = SIG_FXOGS;
17325                confp->chan.radio = 1;
17326             } else if (!strcasecmp(v->value, "em_rx")) {
17327                confp->chan.sig = SIG_EM;
17328                confp->chan.radio = 1;
17329             } else if (!strcasecmp(v->value, "em_tx")) {
17330                confp->chan.sig = SIG_EM;
17331                confp->chan.radio = 1;
17332             } else if (!strcasecmp(v->value, "em_rxtx")) {
17333                confp->chan.sig = SIG_EM;
17334                confp->chan.radio = 2;
17335             } else if (!strcasecmp(v->value, "em_txrx")) {
17336                confp->chan.sig = SIG_EM;
17337                confp->chan.radio = 2;
17338             } else if (!strcasecmp(v->value, "sf")) {
17339                confp->chan.sig = SIG_SF;
17340             } else if (!strcasecmp(v->value, "sf_w")) {
17341                confp->chan.sig = SIG_SFWINK;
17342             } else if (!strcasecmp(v->value, "sf_featd")) {
17343                confp->chan.sig = SIG_FEATD;
17344             } else if (!strcasecmp(v->value, "sf_featdmf")) {
17345                confp->chan.sig = SIG_FEATDMF;
17346             } else if (!strcasecmp(v->value, "sf_featb")) {
17347                confp->chan.sig = SIG_SF_FEATB;
17348             } else if (!strcasecmp(v->value, "sf")) {
17349                confp->chan.sig = SIG_SF;
17350             } else if (!strcasecmp(v->value, "sf_rx")) {
17351                confp->chan.sig = SIG_SF;
17352                confp->chan.radio = 1;
17353             } else if (!strcasecmp(v->value, "sf_tx")) {
17354                confp->chan.sig = SIG_SF;
17355                confp->chan.radio = 1;
17356             } else if (!strcasecmp(v->value, "sf_rxtx")) {
17357                confp->chan.sig = SIG_SF;
17358                confp->chan.radio = 2;
17359             } else if (!strcasecmp(v->value, "sf_txrx")) {
17360                confp->chan.sig = SIG_SF;
17361                confp->chan.radio = 2;
17362             } else if (!strcasecmp(v->value, "featd")) {
17363                confp->chan.sig = SIG_FEATD;
17364             } else if (!strcasecmp(v->value, "featdmf")) {
17365                confp->chan.sig = SIG_FEATDMF;
17366             } else if (!strcasecmp(v->value, "featdmf_ta")) {
17367                confp->chan.sig = SIG_FEATDMF_TA;
17368             } else if (!strcasecmp(v->value, "e911")) {
17369                confp->chan.sig = SIG_E911;
17370             } else if (!strcasecmp(v->value, "fgccama")) {
17371                confp->chan.sig = SIG_FGC_CAMA;
17372             } else if (!strcasecmp(v->value, "fgccamamf")) {
17373                confp->chan.sig = SIG_FGC_CAMAMF;
17374             } else if (!strcasecmp(v->value, "featb")) {
17375                confp->chan.sig = SIG_FEATB;
17376 #ifdef HAVE_PRI
17377             } else if (!strcasecmp(v->value, "pri_net")) {
17378                confp->chan.sig = SIG_PRI;
17379                confp->pri.pri.nodetype = PRI_NETWORK;
17380             } else if (!strcasecmp(v->value, "pri_cpe")) {
17381                confp->chan.sig = SIG_PRI;
17382                confp->pri.pri.nodetype = PRI_CPE;
17383             } else if (!strcasecmp(v->value, "bri_cpe")) {
17384                confp->chan.sig = SIG_BRI;
17385                confp->pri.pri.nodetype = PRI_CPE;
17386             } else if (!strcasecmp(v->value, "bri_net")) {
17387                confp->chan.sig = SIG_BRI;
17388                confp->pri.pri.nodetype = PRI_NETWORK;
17389             } else if (!strcasecmp(v->value, "bri_cpe_ptmp")) {
17390                confp->chan.sig = SIG_BRI_PTMP;
17391                confp->pri.pri.nodetype = PRI_CPE;
17392             } else if (!strcasecmp(v->value, "bri_net_ptmp")) {
17393 #if defined(HAVE_PRI_CALL_HOLD)
17394                confp->chan.sig = SIG_BRI_PTMP;
17395                confp->pri.pri.nodetype = PRI_NETWORK;
17396 #else
17397                ast_log(LOG_WARNING, "How cool would it be if someone implemented this mode!  For now, sucks for you. (line %d)\n", v->lineno);
17398 #endif   /* !defined(HAVE_PRI_CALL_HOLD) */
17399 #endif
17400 #if defined(HAVE_SS7)
17401             } else if (!strcasecmp(v->value, "ss7")) {
17402                confp->chan.sig = SIG_SS7;
17403 #endif   /* defined(HAVE_SS7) */
17404 #ifdef HAVE_OPENR2
17405             } else if (!strcasecmp(v->value, "mfcr2")) {
17406                confp->chan.sig = SIG_MFCR2;
17407 #endif
17408             } else if (!strcasecmp(v->value, "auto")) {
17409                confp->is_sig_auto = 1;
17410             } else {
17411                confp->chan.outsigmod = orig_outsigmod;
17412                confp->chan.radio = orig_radio;
17413                confp->is_sig_auto = orig_auto;
17414                ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
17415             }
17416           } else if (!strcasecmp(v->name, "outsignalling") || !strcasecmp(v->name, "outsignaling")) {
17417             if (!strcasecmp(v->value, "em")) {
17418                confp->chan.outsigmod = SIG_EM;
17419             } else if (!strcasecmp(v->value, "em_e1")) {
17420                confp->chan.outsigmod = SIG_EM_E1;
17421             } else if (!strcasecmp(v->value, "em_w")) {
17422                confp->chan.outsigmod = SIG_EMWINK;
17423             } else if (!strcasecmp(v->value, "sf")) {
17424                confp->chan.outsigmod = SIG_SF;
17425             } else if (!strcasecmp(v->value, "sf_w")) {
17426                confp->chan.outsigmod = SIG_SFWINK;
17427             } else if (!strcasecmp(v->value, "sf_featd")) {
17428                confp->chan.outsigmod = SIG_FEATD;
17429             } else if (!strcasecmp(v->value, "sf_featdmf")) {
17430                confp->chan.outsigmod = SIG_FEATDMF;
17431             } else if (!strcasecmp(v->value, "sf_featb")) {
17432                confp->chan.outsigmod = SIG_SF_FEATB;
17433             } else if (!strcasecmp(v->value, "sf")) {
17434                confp->chan.outsigmod = SIG_SF;
17435             } else if (!strcasecmp(v->value, "featd")) {
17436                confp->chan.outsigmod = SIG_FEATD;
17437             } else if (!strcasecmp(v->value, "featdmf")) {
17438                confp->chan.outsigmod = SIG_FEATDMF;
17439             } else if (!strcasecmp(v->value, "featdmf_ta")) {
17440                confp->chan.outsigmod = SIG_FEATDMF_TA;
17441             } else if (!strcasecmp(v->value, "e911")) {
17442                confp->chan.outsigmod = SIG_E911;
17443             } else if (!strcasecmp(v->value, "fgccama")) {
17444                confp->chan.outsigmod = SIG_FGC_CAMA;
17445             } else if (!strcasecmp(v->value, "fgccamamf")) {
17446                confp->chan.outsigmod = SIG_FGC_CAMAMF;
17447             } else if (!strcasecmp(v->value, "featb")) {
17448                confp->chan.outsigmod = SIG_FEATB;
17449             } else {
17450                ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
17451             }
17452 #ifdef HAVE_PRI
17453          } else if (!strcasecmp(v->name, "pridialplan")) {
17454             if (!strcasecmp(v->value, "national")) {
17455                confp->pri.pri.dialplan = PRI_NATIONAL_ISDN + 1;
17456             } else if (!strcasecmp(v->value, "unknown")) {
17457                confp->pri.pri.dialplan = PRI_UNKNOWN + 1;
17458             } else if (!strcasecmp(v->value, "private")) {
17459                confp->pri.pri.dialplan = PRI_PRIVATE + 1;
17460             } else if (!strcasecmp(v->value, "international")) {
17461                confp->pri.pri.dialplan = PRI_INTERNATIONAL_ISDN + 1;
17462             } else if (!strcasecmp(v->value, "local")) {
17463                confp->pri.pri.dialplan = PRI_LOCAL_ISDN + 1;
17464             } else if (!strcasecmp(v->value, "dynamic")) {
17465                confp->pri.pri.dialplan = -1;
17466             } else if (!strcasecmp(v->value, "redundant")) {
17467                confp->pri.pri.dialplan = -2;
17468             } else {
17469                ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno);
17470             }
17471          } else if (!strcasecmp(v->name, "prilocaldialplan")) {
17472             if (!strcasecmp(v->value, "national")) {
17473                confp->pri.pri.localdialplan = PRI_NATIONAL_ISDN + 1;
17474             } else if (!strcasecmp(v->value, "unknown")) {
17475                confp->pri.pri.localdialplan = PRI_UNKNOWN + 1;
17476             } else if (!strcasecmp(v->value, "private")) {
17477                confp->pri.pri.localdialplan = PRI_PRIVATE + 1;
17478             } else if (!strcasecmp(v->value, "international")) {
17479                confp->pri.pri.localdialplan = PRI_INTERNATIONAL_ISDN + 1;
17480             } else if (!strcasecmp(v->value, "local")) {
17481                confp->pri.pri.localdialplan = PRI_LOCAL_ISDN + 1;
17482             } else if (!strcasecmp(v->value, "dynamic")) {
17483                confp->pri.pri.localdialplan = -1;
17484             } else if (!strcasecmp(v->value, "redundant")) {
17485                confp->pri.pri.localdialplan = -2;
17486             } else {
17487                ast_log(LOG_WARNING, "Unknown PRI localdialplan '%s' at line %d.\n", v->value, v->lineno);
17488             }
17489          } else if (!strcasecmp(v->name, "switchtype")) {
17490             if (!strcasecmp(v->value, "national"))
17491                confp->pri.pri.switchtype = PRI_SWITCH_NI2;
17492             else if (!strcasecmp(v->value, "ni1"))
17493                confp->pri.pri.switchtype = PRI_SWITCH_NI1;
17494             else if (!strcasecmp(v->value, "dms100"))
17495                confp->pri.pri.switchtype = PRI_SWITCH_DMS100;
17496             else if (!strcasecmp(v->value, "4ess"))
17497                confp->pri.pri.switchtype = PRI_SWITCH_ATT4ESS;
17498             else if (!strcasecmp(v->value, "5ess"))
17499                confp->pri.pri.switchtype = PRI_SWITCH_LUCENT5E;
17500             else if (!strcasecmp(v->value, "euroisdn"))
17501                confp->pri.pri.switchtype = PRI_SWITCH_EUROISDN_E1;
17502             else if (!strcasecmp(v->value, "qsig"))
17503                confp->pri.pri.switchtype = PRI_SWITCH_QSIG;
17504             else {
17505                ast_log(LOG_ERROR, "Unknown switchtype '%s' at line %d.\n", v->value, v->lineno);
17506                return -1;
17507             }
17508          } else if (!strcasecmp(v->name, "msn")) {
17509             ast_copy_string(confp->pri.pri.msn_list, v->value,
17510                sizeof(confp->pri.pri.msn_list));
17511          } else if (!strcasecmp(v->name, "nsf")) {
17512             if (!strcasecmp(v->value, "sdn"))
17513                confp->pri.pri.nsf = PRI_NSF_SDN;
17514             else if (!strcasecmp(v->value, "megacom"))
17515                confp->pri.pri.nsf = PRI_NSF_MEGACOM;
17516             else if (!strcasecmp(v->value, "tollfreemegacom"))
17517                confp->pri.pri.nsf = PRI_NSF_TOLL_FREE_MEGACOM;
17518             else if (!strcasecmp(v->value, "accunet"))
17519                confp->pri.pri.nsf = PRI_NSF_ACCUNET;
17520             else if (!strcasecmp(v->value, "none"))
17521                confp->pri.pri.nsf = PRI_NSF_NONE;
17522             else {
17523                ast_log(LOG_WARNING, "Unknown network-specific facility '%s' at line %d.\n", v->value, v->lineno);
17524                confp->pri.pri.nsf = PRI_NSF_NONE;
17525             }
17526          } else if (!strcasecmp(v->name, "priindication")) {
17527             if (!strcasecmp(v->value, "outofband"))
17528                confp->chan.priindication_oob = 1;
17529             else if (!strcasecmp(v->value, "inband"))
17530                confp->chan.priindication_oob = 0;
17531             else
17532                ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d.\n",
17533                   v->value, v->lineno);
17534          } else if (!strcasecmp(v->name, "priexclusive")) {
17535             confp->chan.priexclusive = ast_true(v->value);
17536          } else if (!strcasecmp(v->name, "internationalprefix")) {
17537             ast_copy_string(confp->pri.pri.internationalprefix, v->value, sizeof(confp->pri.pri.internationalprefix));
17538          } else if (!strcasecmp(v->name, "nationalprefix")) {
17539             ast_copy_string(confp->pri.pri.nationalprefix, v->value, sizeof(confp->pri.pri.nationalprefix));
17540          } else if (!strcasecmp(v->name, "localprefix")) {
17541             ast_copy_string(confp->pri.pri.localprefix, v->value, sizeof(confp->pri.pri.localprefix));
17542          } else if (!strcasecmp(v->name, "privateprefix")) {
17543             ast_copy_string(confp->pri.pri.privateprefix, v->value, sizeof(confp->pri.pri.privateprefix));
17544          } else if (!strcasecmp(v->name, "unknownprefix")) {
17545             ast_copy_string(confp->pri.pri.unknownprefix, v->value, sizeof(confp->pri.pri.unknownprefix));
17546          } else if (!strcasecmp(v->name, "resetinterval")) {
17547             if (!strcasecmp(v->value, "never"))
17548                confp->pri.pri.resetinterval = -1;
17549             else if (atoi(v->value) >= 60)
17550                confp->pri.pri.resetinterval = atoi(v->value);
17551             else
17552                ast_log(LOG_WARNING, "'%s' is not a valid reset interval, should be >= 60 seconds or 'never' at line %d.\n",
17553                   v->value, v->lineno);
17554          } else if (!strcasecmp(v->name, "minunused")) {
17555             confp->pri.pri.minunused = atoi(v->value);
17556          } else if (!strcasecmp(v->name, "minidle")) {
17557             confp->pri.pri.minidle = atoi(v->value);
17558          } else if (!strcasecmp(v->name, "idleext")) {
17559             ast_copy_string(confp->pri.pri.idleext, v->value, sizeof(confp->pri.pri.idleext));
17560          } else if (!strcasecmp(v->name, "idledial")) {
17561             ast_copy_string(confp->pri.pri.idledial, v->value, sizeof(confp->pri.pri.idledial));
17562          } else if (!strcasecmp(v->name, "overlapdial")) {
17563             if (ast_true(v->value)) {
17564                confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
17565             } else if (!strcasecmp(v->value, "incoming")) {
17566                confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_INCOMING;
17567             } else if (!strcasecmp(v->value, "outgoing")) {
17568                confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_OUTGOING;
17569             } else if (!strcasecmp(v->value, "both") || ast_true(v->value)) {
17570                confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
17571             } else {
17572                confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_NONE;
17573             }
17574 #ifdef HAVE_PRI_PROG_W_CAUSE
17575          } else if (!strcasecmp(v->name, "qsigchannelmapping")) {
17576             if (!strcasecmp(v->value, "logical")) {
17577                confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_LOGICAL;
17578             } else if (!strcasecmp(v->value, "physical")) {
17579                confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL;
17580             } else {
17581                confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL;
17582             }
17583 #endif
17584          } else if (!strcasecmp(v->name, "discardremoteholdretrieval")) {
17585             confp->pri.pri.discardremoteholdretrieval = ast_true(v->value);
17586 #if defined(HAVE_PRI_SERVICE_MESSAGES)
17587          } else if (!strcasecmp(v->name, "service_message_support")) {
17588             /* assuming switchtype for this channel group has been configured already */
17589             if ((confp->pri.pri.switchtype == PRI_SWITCH_ATT4ESS 
17590                || confp->pri.pri.switchtype == PRI_SWITCH_LUCENT5E
17591                || confp->pri.pri.switchtype == PRI_SWITCH_NI2) && ast_true(v->value)) {
17592                confp->pri.pri.enable_service_message_support = 1;
17593             } else {
17594                confp->pri.pri.enable_service_message_support = 0;
17595             }
17596 #endif   /* defined(HAVE_PRI_SERVICE_MESSAGES) */
17597 #ifdef HAVE_PRI_INBANDDISCONNECT
17598          } else if (!strcasecmp(v->name, "inbanddisconnect")) {
17599             confp->pri.pri.inbanddisconnect = ast_true(v->value);
17600 #endif
17601          } else if (!strcasecmp(v->name, "pritimer")) {
17602 #ifdef PRI_GETSET_TIMERS
17603             char tmp[20];
17604             char *timerc;
17605             char *c;
17606             int timer;
17607             int timeridx;
17608 
17609             ast_copy_string(tmp, v->value, sizeof(tmp));
17610             c = tmp;
17611             timerc = strsep(&c, ",");
17612             if (!ast_strlen_zero(timerc) && !ast_strlen_zero(c)) {
17613                timeridx = pri_timer2idx(timerc);
17614                timer = atoi(c);
17615                if (timeridx < 0 || PRI_MAX_TIMERS <= timeridx) {
17616                   ast_log(LOG_WARNING,
17617                      "'%s' is not a valid ISDN timer at line %d.\n", timerc,
17618                      v->lineno);
17619                } else if (!timer) {
17620                   ast_log(LOG_WARNING,
17621                      "'%s' is not a valid value for ISDN timer '%s' at line %d.\n",
17622                      c, timerc, v->lineno);
17623                } else {
17624                   confp->pri.pri.pritimers[timeridx] = timer;
17625                }
17626             } else {
17627                ast_log(LOG_WARNING,
17628                   "'%s' is not a valid ISDN timer configuration string at line %d.\n",
17629                   v->value, v->lineno);
17630             }
17631 #endif /* PRI_GETSET_TIMERS */
17632          } else if (!strcasecmp(v->name, "facilityenable")) {
17633             confp->pri.pri.facilityenable = ast_true(v->value);
17634 #if defined(HAVE_PRI_AOC_EVENTS)
17635          } else if (!strcasecmp(v->name, "aoc_enable")) {
17636             confp->pri.pri.aoc_passthrough_flag = 0;
17637             if (strchr(v->value, 's') || strchr(v->value, 'S')) {
17638                confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_S;
17639             }
17640             if (strchr(v->value, 'd') || strchr(v->value, 'D')) {
17641                confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_D;
17642             }
17643             if (strchr(v->value, 'e') || strchr(v->value, 'E')) {
17644                confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_E;
17645             }
17646          } else if (!strcasecmp(v->name, "aoce_delayhangup")) {
17647             confp->pri.pri.aoce_delayhangup = ast_true(v->value);
17648 #endif   /* defined(HAVE_PRI_AOC_EVENTS) */
17649 #if defined(HAVE_PRI_CALL_HOLD)
17650          } else if (!strcasecmp(v->name, "hold_disconnect_transfer")) {
17651             confp->pri.pri.hold_disconnect_transfer = ast_true(v->value);
17652 #endif   /* defined(HAVE_PRI_CALL_HOLD) */
17653 #if defined(HAVE_PRI_CCSS)
17654          } else if (!strcasecmp(v->name, "cc_ptmp_recall_mode")) {
17655             if (!strcasecmp(v->value, "global")) {
17656                confp->pri.pri.cc_ptmp_recall_mode = 0;/* globalRecall */
17657             } else if (!strcasecmp(v->value, "specific")) {
17658                confp->pri.pri.cc_ptmp_recall_mode = 1;/* specificRecall */
17659             } else {
17660                confp->pri.pri.cc_ptmp_recall_mode = 1;/* specificRecall */
17661             }
17662          } else if (!strcasecmp(v->name, "cc_qsig_signaling_link_req")) {
17663             if (!strcasecmp(v->value, "release")) {
17664                confp->pri.pri.cc_qsig_signaling_link_req = 0;/* release */
17665             } else if (!strcasecmp(v->value, "retain")) {
17666                confp->pri.pri.cc_qsig_signaling_link_req = 1;/* retain */
17667             } else if (!strcasecmp(v->value, "do_not_care")) {
17668                confp->pri.pri.cc_qsig_signaling_link_req = 2;/* do-not-care */
17669             } else {
17670                confp->pri.pri.cc_qsig_signaling_link_req = 1;/* retain */
17671             }
17672          } else if (!strcasecmp(v->name, "cc_qsig_signaling_link_rsp")) {
17673             if (!strcasecmp(v->value, "release")) {
17674                confp->pri.pri.cc_qsig_signaling_link_rsp = 0;/* release */
17675             } else if (!strcasecmp(v->value, "retain")) {
17676                confp->pri.pri.cc_qsig_signaling_link_rsp = 1;/* retain */
17677             } else {
17678                confp->pri.pri.cc_qsig_signaling_link_rsp = 1;/* retain */
17679             }
17680 #endif   /* defined(HAVE_PRI_CCSS) */
17681 #if defined(HAVE_PRI_CALL_WAITING)
17682          } else if (!strcasecmp(v->name, "max_call_waiting_calls")) {
17683             confp->pri.pri.max_call_waiting_calls = atoi(v->value);
17684             if (confp->pri.pri.max_call_waiting_calls < 0) {
17685                /* Negative values are not allowed. */
17686                confp->pri.pri.max_call_waiting_calls = 0;
17687             }
17688          } else if (!strcasecmp(v->name, "allow_call_waiting_calls")) {
17689             confp->pri.pri.allow_call_waiting_calls = ast_true(v->value);
17690 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
17691 #if defined(HAVE_PRI_MWI)
17692          } else if (!strcasecmp(v->name, "mwi_mailboxes")) {
17693             ast_copy_string(confp->pri.pri.mwi_mailboxes, v->value,
17694                sizeof(confp->pri.pri.mwi_mailboxes));
17695 #endif   /* defined(HAVE_PRI_MWI) */
17696          } else if (!strcasecmp(v->name, "append_msn_to_cid_tag")) {
17697             confp->pri.pri.append_msn_to_user_tag = ast_true(v->value);
17698          } else if (!strcasecmp(v->name, "layer1_presence")) {
17699             if (!strcasecmp(v->value, "required")) {
17700                confp->pri.pri.layer1_ignored = 0;
17701             } else if (!strcasecmp(v->value, "ignore")) {
17702                confp->pri.pri.layer1_ignored = 1;
17703             } else {
17704                /* Default */
17705                confp->pri.pri.layer1_ignored = 0;
17706             }
17707 #if defined(HAVE_PRI_L2_PERSISTENCE)
17708          } else if (!strcasecmp(v->name, "layer2_persistence")) {
17709             if (!strcasecmp(v->value, "keep_up")) {
17710                confp->pri.pri.l2_persistence = PRI_L2_PERSISTENCE_KEEP_UP;
17711             } else if (!strcasecmp(v->value, "leave_down")) {
17712                confp->pri.pri.l2_persistence = PRI_L2_PERSISTENCE_LEAVE_DOWN;
17713             } else {
17714                confp->pri.pri.l2_persistence = PRI_L2_PERSISTENCE_DEFAULT;
17715             }
17716 #endif   /* defined(HAVE_PRI_L2_PERSISTENCE) */
17717 #endif /* HAVE_PRI */
17718 #if defined(HAVE_SS7)
17719          } else if (!strcasecmp(v->name, "ss7type")) {
17720             if (!strcasecmp(v->value, "itu")) {
17721                cur_ss7type = SS7_ITU;
17722             } else if (!strcasecmp(v->value, "ansi")) {
17723                cur_ss7type = SS7_ANSI;
17724             } else
17725                ast_log(LOG_WARNING, "'%s' is an unknown ss7 switch type at line %d.!\n", v->value, v->lineno);
17726          } else if (!strcasecmp(v->name, "linkset")) {
17727             cur_linkset = atoi(v->value);
17728          } else if (!strcasecmp(v->name, "pointcode")) {
17729             cur_pointcode = parse_pointcode(v->value);
17730          } else if (!strcasecmp(v->name, "adjpointcode")) {
17731             cur_adjpointcode = parse_pointcode(v->value);
17732          } else if (!strcasecmp(v->name, "defaultdpc")) {
17733             cur_defaultdpc = parse_pointcode(v->value);
17734          } else if (!strcasecmp(v->name, "cicbeginswith")) {
17735             cur_cicbeginswith = atoi(v->value);
17736          } else if (!strcasecmp(v->name, "networkindicator")) {
17737             if (!strcasecmp(v->value, "national"))
17738                cur_networkindicator = SS7_NI_NAT;
17739             else if (!strcasecmp(v->value, "national_spare"))
17740                cur_networkindicator = SS7_NI_NAT_SPARE;
17741             else if (!strcasecmp(v->value, "international"))
17742                cur_networkindicator = SS7_NI_INT;
17743             else if (!strcasecmp(v->value, "international_spare"))
17744                cur_networkindicator = SS7_NI_INT_SPARE;
17745             else
17746                cur_networkindicator = -1;
17747          } else if (!strcasecmp(v->name, "ss7_internationalprefix")) {
17748             ast_copy_string(confp->ss7.ss7.internationalprefix, v->value, sizeof(confp->ss7.ss7.internationalprefix));
17749          } else if (!strcasecmp(v->name, "ss7_nationalprefix")) {
17750             ast_copy_string(confp->ss7.ss7.nationalprefix, v->value, sizeof(confp->ss7.ss7.nationalprefix));
17751          } else if (!strcasecmp(v->name, "ss7_subscriberprefix")) {
17752             ast_copy_string(confp->ss7.ss7.subscriberprefix, v->value, sizeof(confp->ss7.ss7.subscriberprefix));
17753          } else if (!strcasecmp(v->name, "ss7_unknownprefix")) {
17754             ast_copy_string(confp->ss7.ss7.unknownprefix, v->value, sizeof(confp->ss7.ss7.unknownprefix));
17755          } else if (!strcasecmp(v->name, "ss7_called_nai")) {
17756             if (!strcasecmp(v->value, "national")) {
17757                confp->ss7.ss7.called_nai = SS7_NAI_NATIONAL;
17758             } else if (!strcasecmp(v->value, "international")) {
17759                confp->ss7.ss7.called_nai = SS7_NAI_INTERNATIONAL;
17760             } else if (!strcasecmp(v->value, "subscriber")) {
17761                confp->ss7.ss7.called_nai = SS7_NAI_SUBSCRIBER;
17762             } else if (!strcasecmp(v->value, "unknown")) {
17763                confp->ss7.ss7.called_nai = SS7_NAI_UNKNOWN;
17764             } else if (!strcasecmp(v->value, "dynamic")) {
17765                confp->ss7.ss7.called_nai = SS7_NAI_DYNAMIC;
17766             } else {
17767                ast_log(LOG_WARNING, "Unknown SS7 called_nai '%s' at line %d.\n", v->value, v->lineno);
17768             }
17769          } else if (!strcasecmp(v->name, "ss7_calling_nai")) {
17770             if (!strcasecmp(v->value, "national")) {
17771                confp->ss7.ss7.calling_nai = SS7_NAI_NATIONAL;
17772             } else if (!strcasecmp(v->value, "international")) {
17773                confp->ss7.ss7.calling_nai = SS7_NAI_INTERNATIONAL;
17774             } else if (!strcasecmp(v->value, "subscriber")) {
17775                confp->ss7.ss7.calling_nai = SS7_NAI_SUBSCRIBER;
17776             } else if (!strcasecmp(v->value, "unknown")) {
17777                confp->ss7.ss7.calling_nai = SS7_NAI_UNKNOWN;
17778             } else if (!strcasecmp(v->value, "dynamic")) {
17779                confp->ss7.ss7.calling_nai = SS7_NAI_DYNAMIC;
17780             } else {
17781                ast_log(LOG_WARNING, "Unknown SS7 calling_nai '%s' at line %d.\n", v->value, v->lineno);
17782             }
17783          } else if (!strcasecmp(v->name, "sigchan")) {
17784             int sigchan, res;
17785             sigchan = atoi(v->value);
17786             res = linkset_addsigchan(sigchan);
17787             if (res < 0)
17788                return -1;
17789 
17790          } else if (!strcasecmp(v->name, "ss7_explicitacm")) {
17791             struct dahdi_ss7 *link;
17792             link = ss7_resolve_linkset(cur_linkset);
17793             if (!link) {
17794                ast_log(LOG_ERROR, "Invalid linkset number.  Must be between 1 and %d\n", NUM_SPANS + 1);
17795                return -1;
17796             }
17797             if (ast_true(v->value))
17798                link->ss7.flags |= LINKSET_FLAG_EXPLICITACM;
17799 #endif   /* defined(HAVE_SS7) */
17800 #ifdef HAVE_OPENR2
17801          } else if (!strcasecmp(v->name, "mfcr2_advanced_protocol_file")) {
17802             ast_copy_string(confp->mfcr2.r2proto_file, v->value, sizeof(confp->mfcr2.r2proto_file));
17803             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);
17804          } else if (!strcasecmp(v->name, "mfcr2_logdir")) {
17805             ast_copy_string(confp->mfcr2.logdir, v->value, sizeof(confp->mfcr2.logdir));
17806          } else if (!strcasecmp(v->name, "mfcr2_variant")) {
17807             confp->mfcr2.variant = openr2_proto_get_variant(v->value);
17808             if (OR2_VAR_UNKNOWN == confp->mfcr2.variant) {
17809                ast_log(LOG_WARNING, "Unknown MFC/R2 variant '%s' at line %d, defaulting to ITU.\n", v->value, v->lineno);
17810                confp->mfcr2.variant = OR2_VAR_ITU;
17811             }
17812          } else if (!strcasecmp(v->name, "mfcr2_mfback_timeout")) {
17813             confp->mfcr2.mfback_timeout = atoi(v->value);
17814             if (!confp->mfcr2.mfback_timeout) {
17815                ast_log(LOG_WARNING, "MF timeout of 0? hum, I will protect you from your ignorance. Setting default.\n");
17816                confp->mfcr2.mfback_timeout = -1;
17817             } else if (confp->mfcr2.mfback_timeout > 0 && confp->mfcr2.mfback_timeout < 500) {
17818                ast_log(LOG_WARNING, "MF timeout less than 500ms is not recommended, you have been warned!\n");
17819             }
17820          } else if (!strcasecmp(v->name, "mfcr2_metering_pulse_timeout")) {
17821             confp->mfcr2.metering_pulse_timeout = atoi(v->value);
17822             if (confp->mfcr2.metering_pulse_timeout > 500) {
17823                ast_log(LOG_WARNING, "Metering pulse timeout greater than 500ms is not recommended, you have been warned!\n");
17824             }
17825          } else if (!strcasecmp(v->name, "mfcr2_get_ani_first")) {
17826             confp->mfcr2.get_ani_first = ast_true(v->value) ? 1 : 0;
17827          } else if (!strcasecmp(v->name, "mfcr2_double_answer")) {
17828             confp->mfcr2.double_answer = ast_true(v->value) ? 1 : 0;
17829          } else if (!strcasecmp(v->name, "mfcr2_charge_calls")) {
17830             confp->mfcr2.charge_calls = ast_true(v->value) ? 1 : 0;
17831          } else if (!strcasecmp(v->name, "mfcr2_accept_on_offer")) {
17832             confp->mfcr2.accept_on_offer = ast_true(v->value) ? 1 : 0;
17833          } else if (!strcasecmp(v->name, "mfcr2_allow_collect_calls")) {
17834             confp->mfcr2.allow_collect_calls = ast_true(v->value) ? 1 : 0;
17835          } else if (!strcasecmp(v->name, "mfcr2_forced_release")) {
17836             confp->mfcr2.forced_release = ast_true(v->value) ? 1 : 0;
17837          } else if (!strcasecmp(v->name, "mfcr2_immediate_accept")) {
17838             confp->mfcr2.immediate_accept = ast_true(v->value) ? 1 : 0;
17839 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
17840          } else if (!strcasecmp(v->name, "mfcr2_skip_category")) {
17841             confp->mfcr2.skip_category_request = ast_true(v->value) ? 1 : 0;
17842 #endif
17843          } else if (!strcasecmp(v->name, "mfcr2_call_files")) {
17844             confp->mfcr2.call_files = ast_true(v->value) ? 1 : 0;
17845          } else if (!strcasecmp(v->name, "mfcr2_max_ani")) {
17846             confp->mfcr2.max_ani = atoi(v->value);
17847             if (confp->mfcr2.max_ani >= AST_MAX_EXTENSION){
17848                confp->mfcr2.max_ani = AST_MAX_EXTENSION - 1;
17849             }
17850          } else if (!strcasecmp(v->name, "mfcr2_max_dnis")) {
17851             confp->mfcr2.max_dnis = atoi(v->value);
17852             if (confp->mfcr2.max_dnis >= AST_MAX_EXTENSION){
17853                confp->mfcr2.max_dnis = AST_MAX_EXTENSION - 1;
17854             }
17855          } else if (!strcasecmp(v->name, "mfcr2_category")) {
17856             confp->mfcr2.category = openr2_proto_get_category(v->value);
17857             if (OR2_CALLING_PARTY_CATEGORY_UNKNOWN == confp->mfcr2.category) {
17858                confp->mfcr2.category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER;
17859                ast_log(LOG_WARNING, "Invalid MFC/R2 caller category '%s' at line %d. Using national subscriber as default.\n",
17860                      v->value, v->lineno);
17861             }
17862          } else if (!strcasecmp(v->name, "mfcr2_logging")) {
17863             openr2_log_level_t tmplevel;
17864             char *clevel;
17865             char *logval = ast_strdupa(v->value);
17866             while (logval) {
17867                clevel = strsep(&logval,",");
17868                if (-1 == (tmplevel = openr2_log_get_level(clevel))) {
17869                   ast_log(LOG_WARNING, "Ignoring invalid logging level: '%s' at line %d.\n", clevel, v->lineno);
17870                   continue;
17871                }
17872                confp->mfcr2.loglevel |= tmplevel;
17873             }
17874 #endif /* HAVE_OPENR2 */
17875          } else if (!strcasecmp(v->name, "cadence")) {
17876             /* setup to scan our argument */
17877             int element_count, c[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
17878             int i;
17879             struct dahdi_ring_cadence new_cadence;
17880             int cid_location = -1;
17881             int firstcadencepos = 0;
17882             char original_args[80];
17883             int cadence_is_ok = 1;
17884 
17885             ast_copy_string(original_args, v->value, sizeof(original_args));
17886             /* 16 cadences allowed (8 pairs) */
17887             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]);
17888 
17889             /* Cadence must be even (on/off) */
17890             if (element_count % 2 == 1) {
17891                ast_log(LOG_ERROR, "Must be a silence duration for each ring duration: %s at line %d.\n", original_args, v->lineno);
17892                cadence_is_ok = 0;
17893             }
17894 
17895             /* Ring cadences cannot be negative */
17896             for (i = 0; i < element_count; i++) {
17897                if (c[i] == 0) {
17898                   ast_log(LOG_ERROR, "Ring or silence duration cannot be zero: %s at line %d.\n", original_args, v->lineno);
17899                   cadence_is_ok = 0;
17900                   break;
17901                } else if (c[i] < 0) {
17902                   if (i % 2 == 1) {
17903                      /* Silence duration, negative possibly okay */
17904                      if (cid_location == -1) {
17905                         cid_location = i;
17906                         c[i] *= -1;
17907                      } else {
17908                         ast_log(LOG_ERROR, "CID location specified twice: %s at line %d.\n", original_args, v->lineno);
17909                         cadence_is_ok = 0;
17910                         break;
17911                      }
17912                   } else {
17913                      if (firstcadencepos == 0) {
17914                         firstcadencepos = i; /* only recorded to avoid duplicate specification */
17915                                  /* duration will be passed negative to the DAHDI driver */
17916                      } else {
17917                          ast_log(LOG_ERROR, "First cadence position specified twice: %s at line %d.\n", original_args, v->lineno);
17918                         cadence_is_ok = 0;
17919                         break;
17920                      }
17921                   }
17922                }
17923             }
17924 
17925             /* Substitute our scanned cadence */
17926             for (i = 0; i < 16; i++) {
17927                new_cadence.ringcadence[i] = c[i];
17928             }
17929 
17930             if (cadence_is_ok) {
17931                /* ---we scanned it without getting annoyed; now some sanity checks--- */
17932                if (element_count < 2) {
17933                   ast_log(LOG_ERROR, "Minimum cadence is ring,pause: %s at line %d.\n", original_args, v->lineno);
17934                } else {
17935                   if (cid_location == -1) {
17936                      /* user didn't say; default to first pause */
17937                      cid_location = 1;
17938                   } else {
17939                      /* convert element_index to cidrings value */
17940                      cid_location = (cid_location + 1) / 2;
17941                   }
17942                   /* ---we like their cadence; try to install it--- */
17943                   if (!user_has_defined_cadences++)
17944                      /* this is the first user-defined cadence; clear the default user cadences */
17945                      num_cadence = 0;
17946                   if ((num_cadence+1) >= NUM_CADENCE_MAX)
17947                      ast_log(LOG_ERROR, "Already %d cadences; can't add another: %s at line %d.\n", NUM_CADENCE_MAX, original_args, v->lineno);
17948                   else {
17949                      cadences[num_cadence] = new_cadence;
17950                      cidrings[num_cadence++] = cid_location;
17951                      ast_verb(3, "cadence 'r%d' added: %s\n",num_cadence,original_args);
17952                   }
17953                }
17954             }
17955          } else if (!strcasecmp(v->name, "ringtimeout")) {
17956             ringt_base = (atoi(v->value) * 8) / READ_SIZE;
17957          } else if (!strcasecmp(v->name, "prewink")) {
17958             confp->timing.prewinktime = atoi(v->value);
17959          } else if (!strcasecmp(v->name, "preflash")) {
17960             confp->timing.preflashtime = atoi(v->value);
17961          } else if (!strcasecmp(v->name, "wink")) {
17962             confp->timing.winktime = atoi(v->value);
17963          } else if (!strcasecmp(v->name, "flash")) {
17964             confp->timing.flashtime = atoi(v->value);
17965          } else if (!strcasecmp(v->name, "start")) {
17966             confp->timing.starttime = atoi(v->value);
17967          } else if (!strcasecmp(v->name, "rxwink")) {
17968             confp->timing.rxwinktime = atoi(v->value);
17969          } else if (!strcasecmp(v->name, "rxflash")) {
17970             confp->timing.rxflashtime = atoi(v->value);
17971          } else if (!strcasecmp(v->name, "debounce")) {
17972             confp->timing.debouncetime = atoi(v->value);
17973          } else if (!strcasecmp(v->name, "toneduration")) {
17974             int toneduration;
17975             int ctlfd;
17976             int res;
17977             struct dahdi_dialparams dps;
17978 
17979             ctlfd = open("/dev/dahdi/ctl", O_RDWR);
17980             if (ctlfd == -1) {
17981                ast_log(LOG_ERROR, "Unable to open /dev/dahdi/ctl to set toneduration at line %d.\n", v->lineno);
17982                return -1;
17983             }
17984 
17985             toneduration = atoi(v->value);
17986             if (toneduration > -1) {
17987                memset(&dps, 0, sizeof(dps));
17988 
17989                dps.dtmf_tonelen = dps.mfv1_tonelen = toneduration;
17990                res = ioctl(ctlfd, DAHDI_SET_DIALPARAMS, &dps);
17991                if (res < 0) {
17992                   ast_log(LOG_ERROR, "Invalid tone duration: %d ms at line %d: %s\n", toneduration, v->lineno, strerror(errno));
17993                   close(ctlfd);
17994                   return -1;
17995                }
17996             }
17997             close(ctlfd);
17998          } else if (!strcasecmp(v->name, "defaultcic")) {
17999             ast_copy_string(defaultcic, v->value, sizeof(defaultcic));
18000          } else if (!strcasecmp(v->name, "defaultozz")) {
18001             ast_copy_string(defaultozz, v->value, sizeof(defaultozz));
18002          } else if (!strcasecmp(v->name, "mwilevel")) {
18003             mwilevel = atoi(v->value);
18004          } else if (!strcasecmp(v->name, "dtmfcidlevel")) {
18005             dtmfcid_level = atoi(v->value);
18006          } else if (!strcasecmp(v->name, "reportalarms")) {
18007             if (!strcasecmp(v->value, "all"))
18008                report_alarms = REPORT_CHANNEL_ALARMS | REPORT_SPAN_ALARMS;
18009             if (!strcasecmp(v->value, "none"))
18010                report_alarms = 0;
18011             else if (!strcasecmp(v->value, "channels"))
18012                report_alarms = REPORT_CHANNEL_ALARMS;
18013             else if (!strcasecmp(v->value, "spans"))
18014                report_alarms = REPORT_SPAN_ALARMS;
18015           }
18016       } else if (!(options & PROC_DAHDI_OPT_NOWARN) )
18017          ast_log(LOG_WARNING, "Ignoring any changes to '%s' (on reload) at line %d.\n", v->name, v->lineno);
18018    }
18019 
18020    /* Since confp has already filled invidual dahdi_pvt objects with channels at this point, clear the variables in confp's pvt. */
18021    if (confp->chan.vars) {
18022       ast_variables_destroy(confp->chan.vars);
18023       confp->chan.vars = NULL;
18024    }
18025 
18026    if (dahdichan) {
18027       /* Process the deferred dahdichan value. */
18028       if (build_channels(confp, dahdichan->value, reload, dahdichan->lineno,
18029          &found_pseudo)) {
18030          if (confp->ignore_failed_channels) {
18031             ast_log(LOG_WARNING,
18032                "Dahdichan '%s' failure ignored: ignore_failed_channels.\n",
18033                dahdichan->value);
18034          } else {
18035             return -1;
18036          }
18037       }
18038    }
18039 
18040    /* mark the first channels of each DAHDI span to watch for their span alarms */
18041    for (tmp = iflist, y=-1; tmp; tmp = tmp->next) {
18042       if (!tmp->destroy && tmp->span != y) {
18043          tmp->manages_span_alarms = 1;
18044          y = tmp->span; 
18045       } else {
18046          tmp->manages_span_alarms = 0;
18047       }
18048    }
18049 
18050    /*< \todo why check for the pseudo in the per-channel section.
18051     * Any actual use for manual setup of the pseudo channel? */
18052    if (!found_pseudo && reload != 1 && !(options & PROC_DAHDI_OPT_NOCHAN)) {
18053       /* use the default configuration for a channel, so
18054          that any settings from real configured channels
18055          don't "leak" into the pseudo channel config
18056       */
18057       struct dahdi_chan_conf conf = dahdi_chan_conf_default();
18058 
18059       if (conf.chan.cc_params) {
18060          tmp = mkintf(CHAN_PSEUDO, &conf, reload);
18061       } else {
18062          tmp = NULL;
18063       }
18064       if (tmp) {
18065          ast_verb(3, "Automatically generated pseudo channel\n");
18066       } else {
18067          ast_log(LOG_WARNING, "Unable to register pseudo channel!\n");
18068       }
18069       ast_cc_config_params_destroy(conf.chan.cc_params);
18070    }
18071    return 0;
18072 }
18073 
18074 /*!
18075  * \internal
18076  * \brief Deep copy struct dahdi_chan_conf.
18077  * \since 1.8
18078  *
18079  * \param dest Destination.
18080  * \param src Source.
18081  *
18082  * \return Nothing
18083  */
18084 static void deep_copy_dahdi_chan_conf(struct dahdi_chan_conf *dest, const struct dahdi_chan_conf *src)
18085 {
18086    struct ast_cc_config_params *cc_params;
18087 
18088    cc_params = dest->chan.cc_params;
18089    *dest = *src;
18090    dest->chan.cc_params = cc_params;
18091    ast_cc_copy_config_params(dest->chan.cc_params, src->chan.cc_params);
18092 }
18093 
18094 /*!
18095  * \internal
18096  * \brief Setup DAHDI channel driver.
18097  *
18098  * \param reload enum: load_module(0), reload(1), restart(2).
18099  * \param default_conf Default config parameters.  So cc_params can be properly destroyed.
18100  * \param base_conf Default config parameters per section.  So cc_params can be properly destroyed.
18101  * \param conf Local config parameters.  So cc_params can be properly destroyed.
18102  *
18103  * \retval 0 on success.
18104  * \retval -1 on error.
18105  */
18106 static int setup_dahdi_int(int reload, struct dahdi_chan_conf *default_conf, struct dahdi_chan_conf *base_conf, struct dahdi_chan_conf *conf)
18107 {
18108    struct ast_config *cfg;
18109    struct ast_config *ucfg;
18110    struct ast_variable *v;
18111    struct ast_flags config_flags = { reload == 1 ? CONFIG_FLAG_FILEUNCHANGED : 0 };
18112    const char *chans;
18113    const char *cat;
18114    int res;
18115 
18116 #ifdef HAVE_PRI
18117    char *c;
18118    int spanno;
18119    int i;
18120    int logicalspan;
18121    int trunkgroup;
18122    int dchannels[SIG_PRI_NUM_DCHANS];
18123 #endif
18124    int have_cfg_now;
18125    static int had_cfg_before = 1;/* So initial load will complain if we don't have cfg. */
18126 
18127    cfg = ast_config_load(config, config_flags);
18128    have_cfg_now = !!cfg;
18129    if (!cfg) {
18130       /* Error if we have no config file */
18131       if (had_cfg_before) {
18132          ast_log(LOG_ERROR, "Unable to load config %s\n", config);
18133          ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
18134       }
18135       cfg = ast_config_new();/* Dummy config */
18136       if (!cfg) {
18137          return 0;
18138       }
18139       ucfg = ast_config_load("users.conf", config_flags);
18140       if (ucfg == CONFIG_STATUS_FILEUNCHANGED) {
18141          ast_config_destroy(cfg);
18142          return 0;
18143       }
18144       if (ucfg == CONFIG_STATUS_FILEINVALID) {
18145          ast_log(LOG_ERROR, "File users.conf cannot be parsed.  Aborting.\n");
18146          ast_config_destroy(cfg);
18147          return 0;
18148       }
18149    } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
18150       ucfg = ast_config_load("users.conf", config_flags);
18151       if (ucfg == CONFIG_STATUS_FILEUNCHANGED) {
18152          return 0;
18153       }
18154       if (ucfg == CONFIG_STATUS_FILEINVALID) {
18155          ast_log(LOG_ERROR, "File users.conf cannot be parsed.  Aborting.\n");
18156          return 0;
18157       }
18158       ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
18159       cfg = ast_config_load(config, config_flags);
18160       have_cfg_now = !!cfg;
18161       if (!cfg) {
18162          if (had_cfg_before) {
18163             /* We should have been able to load the config. */
18164             ast_log(LOG_ERROR, "Bad. Unable to load config %s\n", config);
18165             ast_config_destroy(ucfg);
18166             return 0;
18167          }
18168          cfg = ast_config_new();/* Dummy config */
18169          if (!cfg) {
18170             ast_config_destroy(ucfg);
18171             return 0;
18172          }
18173       } else if (cfg == CONFIG_STATUS_FILEINVALID) {
18174          ast_log(LOG_ERROR, "File %s cannot be parsed.  Aborting.\n", config);
18175          ast_config_destroy(ucfg);
18176          return 0;
18177       }
18178    } else if (cfg == CONFIG_STATUS_FILEINVALID) {
18179       ast_log(LOG_ERROR, "File %s cannot be parsed.  Aborting.\n", config);
18180       return 0;
18181    } else {
18182       ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
18183       ucfg = ast_config_load("users.conf", config_flags);
18184       if (ucfg == CONFIG_STATUS_FILEINVALID) {
18185          ast_log(LOG_ERROR, "File users.conf cannot be parsed.  Aborting.\n");
18186          ast_config_destroy(cfg);
18187          return 0;
18188       }
18189    }
18190    had_cfg_before = have_cfg_now;
18191 
18192    /* It's a little silly to lock it, but we might as well just to be sure */
18193    ast_mutex_lock(&iflock);
18194 #ifdef HAVE_PRI
18195    if (reload != 1) {
18196       /* Process trunkgroups first */
18197       v = ast_variable_browse(cfg, "trunkgroups");
18198       while (v) {
18199          if (!strcasecmp(v->name, "trunkgroup")) {
18200             trunkgroup = atoi(v->value);
18201             if (trunkgroup > 0) {
18202                if ((c = strchr(v->value, ','))) {
18203                   i = 0;
18204                   memset(dchannels, 0, sizeof(dchannels));
18205                   while (c && (i < SIG_PRI_NUM_DCHANS)) {
18206                      dchannels[i] = atoi(c + 1);
18207                      if (dchannels[i] < 0) {
18208                         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);
18209                      } else
18210                         i++;
18211                      c = strchr(c + 1, ',');
18212                   }
18213                   if (i) {
18214                      if (pri_create_trunkgroup(trunkgroup, dchannels)) {
18215                         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);
18216                   } else
18217                         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");
18218                   } else
18219                      ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
18220                } else
18221                   ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
18222             } else
18223                ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of chan_dahdi.conf\n", v->lineno);
18224          } else if (!strcasecmp(v->name, "spanmap")) {
18225             spanno = atoi(v->value);
18226             if (spanno > 0) {
18227                if ((c = strchr(v->value, ','))) {
18228                   trunkgroup = atoi(c + 1);
18229                   if (trunkgroup > 0) {
18230                      if ((c = strchr(c + 1, ',')))
18231                         logicalspan = atoi(c + 1);
18232                      else
18233                         logicalspan = 0;
18234                      if (logicalspan >= 0) {
18235                         if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) {
18236                            ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
18237                      } else
18238                            ast_verb(2, "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
18239                      } else
18240                         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);
18241                   } else
18242                      ast_log(LOG_WARNING, "Trunk group must be a postive number at line %d of chan_dahdi.conf\n", v->lineno);
18243                } else
18244                   ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of chan_dahdi.conf\n", v->lineno);
18245             } else
18246                ast_log(LOG_WARNING, "Span number must be a postive integer at line %d of chan_dahdi.conf\n", v->lineno);
18247          } else {
18248             ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name);
18249          }
18250          v = v->next;
18251       }
18252    }
18253 #endif
18254 
18255    /* Copy the default jb config over global_jbconf */
18256    memcpy(&global_jbconf, &default_jbconf, sizeof(global_jbconf));
18257 
18258    mwimonitornotify[0] = '\0';
18259 
18260    v = ast_variable_browse(cfg, "channels");
18261    if ((res = process_dahdi(base_conf,
18262       "" /* Must be empty for the channels category.  Silly voicemail mailbox. */,
18263       v, reload, 0))) {
18264       ast_mutex_unlock(&iflock);
18265       ast_config_destroy(cfg);
18266       if (ucfg) {
18267          ast_config_destroy(ucfg);
18268       }
18269       return res;
18270    }
18271 
18272    /* Now get configuration from all normal sections in chan_dahdi.conf: */
18273    for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) {
18274       /* [channels] and [trunkgroups] are used. Let's also reserve
18275        * [globals] and [general] for future use
18276        */
18277       if (!strcasecmp(cat, "general") ||
18278          !strcasecmp(cat, "trunkgroups") ||
18279          !strcasecmp(cat, "globals") ||
18280          !strcasecmp(cat, "channels")) {
18281          continue;
18282       }
18283 
18284       chans = ast_variable_retrieve(cfg, cat, "dahdichan");
18285       if (ast_strlen_zero(chans)) {
18286          /* Section is useless without a dahdichan value present. */
18287          continue;
18288       }
18289 
18290       /* Copy base_conf to conf. */
18291       deep_copy_dahdi_chan_conf(conf, base_conf);
18292 
18293       if ((res = process_dahdi(conf, cat, ast_variable_browse(cfg, cat), reload, PROC_DAHDI_OPT_NOCHAN))) {
18294          ast_mutex_unlock(&iflock);
18295          ast_config_destroy(cfg);
18296          if (ucfg) {
18297             ast_config_destroy(ucfg);
18298          }
18299          return res;
18300       }
18301    }
18302 
18303    ast_config_destroy(cfg);
18304 
18305    if (ucfg) {
18306       /* Reset base_conf, so things don't leak from chan_dahdi.conf */
18307       deep_copy_dahdi_chan_conf(base_conf, default_conf);
18308       process_dahdi(base_conf,
18309          "" /* Must be empty for the general category.  Silly voicemail mailbox. */,
18310          ast_variable_browse(ucfg, "general"), 1, 0);
18311 
18312       for (cat = ast_category_browse(ucfg, NULL); cat ; cat = ast_category_browse(ucfg, cat)) {
18313          if (!strcasecmp(cat, "general")) {
18314             continue;
18315          }
18316 
18317          chans = ast_variable_retrieve(ucfg, cat, "dahdichan");
18318          if (ast_strlen_zero(chans)) {
18319             /* Section is useless without a dahdichan value present. */
18320             continue;
18321          }
18322 
18323          /* Copy base_conf to conf. */
18324          deep_copy_dahdi_chan_conf(conf, base_conf);
18325 
18326          if ((res = process_dahdi(conf, cat, ast_variable_browse(ucfg, cat), reload, PROC_DAHDI_OPT_NOCHAN | PROC_DAHDI_OPT_NOWARN))) {
18327             ast_config_destroy(ucfg);
18328             ast_mutex_unlock(&iflock);
18329             return res;
18330          }
18331       }
18332       ast_config_destroy(ucfg);
18333    }
18334    ast_mutex_unlock(&iflock);
18335 
18336 #ifdef HAVE_PRI
18337    if (reload != 1) {
18338       int x;
18339       for (x = 0; x < NUM_SPANS; x++) {
18340          if (pris[x].pri.pvts[0]) {
18341             prepare_pri(pris + x);
18342             if (sig_pri_start_pri(&pris[x].pri)) {
18343                ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1);
18344                return -1;
18345             } else
18346                ast_verb(2, "Starting D-Channel on span %d\n", x + 1);
18347          }
18348       }
18349    }
18350 #endif
18351 #if defined(HAVE_SS7)
18352    if (reload != 1) {
18353       int x;
18354       for (x = 0; x < NUM_SPANS; x++) {
18355          if (linksets[x].ss7.ss7) {
18356             linksets[x].ss7.calls = &dahdi_ss7_callbacks;
18357             if (ast_pthread_create(&linksets[x].ss7.master, NULL, ss7_linkset, &linksets[x].ss7)) {
18358                ast_log(LOG_ERROR, "Unable to start SS7 linkset on span %d\n", x + 1);
18359                return -1;
18360             } else
18361                ast_verb(2, "Starting SS7 linkset on span %d\n", x + 1);
18362          }
18363       }
18364    }
18365 #endif   /* defined(HAVE_SS7) */
18366 #ifdef HAVE_OPENR2
18367    if (reload != 1) {
18368       int x;
18369       for (x = 0; x < r2links_count; x++) {
18370          if (ast_pthread_create(&r2links[x]->r2master, NULL, mfcr2_monitor, r2links[x])) {
18371             ast_log(LOG_ERROR, "Unable to start R2 monitor on channel group %d\n", x + 1);
18372             return -1;
18373          } else {
18374             ast_verb(2, "Starting R2 monitor on channel group %d\n", x + 1);
18375          }
18376       }
18377    }
18378 #endif
18379    /* And start the monitor for the first time */
18380    restart_monitor();
18381    return 0;
18382 }
18383 
18384 /*!
18385  * \internal
18386  * \brief Setup DAHDI channel driver.
18387  *
18388  * \param reload enum: load_module(0), reload(1), restart(2).
18389  *
18390  * \retval 0 on success.
18391  * \retval -1 on error.
18392  */
18393 static int setup_dahdi(int reload)
18394 {
18395    int res;
18396    struct dahdi_chan_conf default_conf = dahdi_chan_conf_default();
18397    struct dahdi_chan_conf base_conf = dahdi_chan_conf_default();
18398    struct dahdi_chan_conf conf = dahdi_chan_conf_default();
18399 
18400    if (default_conf.chan.cc_params && base_conf.chan.cc_params && conf.chan.cc_params) {
18401       res = setup_dahdi_int(reload, &default_conf, &base_conf, &conf);
18402    } else {
18403       res = -1;
18404    }
18405    ast_cc_config_params_destroy(default_conf.chan.cc_params);
18406    ast_cc_config_params_destroy(base_conf.chan.cc_params);
18407    ast_cc_config_params_destroy(conf.chan.cc_params);
18408 
18409    return res;
18410 }
18411 
18412 /*!
18413  * \internal
18414  * \brief Callback used to generate the dahdi status tree.
18415  * \param[in] search The search pattern tree.
18416  * \retval NULL on error.
18417  * \retval non-NULL The generated tree.
18418  */
18419 static int dahdi_status_data_provider_get(const struct ast_data_search *search,
18420       struct ast_data *data_root)
18421 {
18422    int ctl, res, span;
18423    struct ast_data *data_span, *data_alarms;
18424    struct dahdi_spaninfo s;
18425 
18426    ctl = open("/dev/dahdi/ctl", O_RDWR);
18427    if (ctl < 0) {
18428       ast_log(LOG_ERROR, "No DAHDI found. Unable to open /dev/dahdi/ctl: %s\n", strerror(errno));
18429       return -1;
18430    }
18431    for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
18432       s.spanno = span;
18433       res = ioctl(ctl, DAHDI_SPANSTAT, &s);
18434       if (res) {
18435          continue;
18436       }
18437 
18438       data_span = ast_data_add_node(data_root, "span");
18439       if (!data_span) {
18440          continue;
18441       }
18442       ast_data_add_str(data_span, "description", s.desc);
18443 
18444       /* insert the alarms status */
18445       data_alarms = ast_data_add_node(data_span, "alarms");
18446       if (!data_alarms) {
18447          continue;
18448       }
18449 
18450       ast_data_add_bool(data_alarms, "BLUE", s.alarms & DAHDI_ALARM_BLUE);
18451       ast_data_add_bool(data_alarms, "YELLOW", s.alarms & DAHDI_ALARM_YELLOW);
18452       ast_data_add_bool(data_alarms, "RED", s.alarms & DAHDI_ALARM_RED);
18453       ast_data_add_bool(data_alarms, "LOOPBACK", s.alarms & DAHDI_ALARM_LOOPBACK);
18454       ast_data_add_bool(data_alarms, "RECOVER", s.alarms & DAHDI_ALARM_RECOVER);
18455       ast_data_add_bool(data_alarms, "NOTOPEN", s.alarms & DAHDI_ALARM_NOTOPEN);
18456 
18457       ast_data_add_int(data_span, "irqmisses", s.irqmisses);
18458       ast_data_add_int(data_span, "bpviol", s.bpvcount);
18459       ast_data_add_int(data_span, "crc4", s.crc4count);
18460       ast_data_add_str(data_span, "framing", s.lineconfig & DAHDI_CONFIG_D4 ? "D4" :
18461                      s.lineconfig & DAHDI_CONFIG_ESF ? "ESF" :
18462                      s.lineconfig & DAHDI_CONFIG_CCS ? "CCS" :
18463                      "CAS");
18464       ast_data_add_str(data_span, "coding",  s.lineconfig & DAHDI_CONFIG_B8ZS ? "B8ZS" :
18465                      s.lineconfig & DAHDI_CONFIG_HDB3 ? "HDB3" :
18466                      s.lineconfig & DAHDI_CONFIG_AMI ? "AMI" :
18467                      "Unknown");
18468       ast_data_add_str(data_span, "options", s.lineconfig & DAHDI_CONFIG_CRC4 ?
18469                      s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" :
18470                      s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "YEL" : "");
18471       ast_data_add_str(data_span, "lbo", lbostr[s.lbo]);
18472 
18473       /* if this span doesn't match remove it. */
18474       if (!ast_data_search_match(search, data_span)) {
18475          ast_data_remove_node(data_root, data_span);
18476       }
18477    }
18478    close(ctl);
18479 
18480    return 0;
18481 }
18482 
18483 /*!
18484  * \internal
18485  * \brief Callback used to generate the dahdi channels tree.
18486  * \param[in] search The search pattern tree.
18487  * \retval NULL on error.
18488  * \retval non-NULL The generated tree.
18489  */
18490 static int dahdi_channels_data_provider_get(const struct ast_data_search *search,
18491       struct ast_data *data_root)
18492 {
18493    struct dahdi_pvt *tmp;
18494    struct ast_data *data_channel;
18495 
18496    ast_mutex_lock(&iflock);
18497    for (tmp = iflist; tmp; tmp = tmp->next) {
18498       data_channel = ast_data_add_node(data_root, "channel");
18499       if (!data_channel) {
18500          continue;
18501       }
18502 
18503       ast_data_add_structure(dahdi_pvt, data_channel, tmp);
18504 
18505       /* if this channel doesn't match remove it. */
18506       if (!ast_data_search_match(search, data_channel)) {
18507          ast_data_remove_node(data_root, data_channel);
18508       }
18509    }
18510    ast_mutex_unlock(&iflock);
18511 
18512    return 0;
18513 }
18514 
18515 /*!
18516  * \internal
18517  * \brief Callback used to generate the dahdi channels tree.
18518  * \param[in] search The search pattern tree.
18519  * \retval NULL on error.
18520  * \retval non-NULL The generated tree.
18521  */
18522 static int dahdi_version_data_provider_get(const struct ast_data_search *search,
18523       struct ast_data *data_root)
18524 {
18525    int pseudo_fd = -1;
18526    struct dahdi_versioninfo vi = {
18527       .version = "Unknown",
18528       .echo_canceller = "Unknown"
18529    };
18530 
18531    if ((pseudo_fd = open("/dev/dahdi/ctl", O_RDONLY)) < 0) {
18532       ast_log(LOG_ERROR, "Failed to open control file to get version.\n");
18533       return -1;
18534    }
18535 
18536    if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi)) {
18537       ast_log(LOG_ERROR, "Failed to get DAHDI version: %s\n", strerror(errno));
18538    }
18539 
18540    close(pseudo_fd);
18541 
18542    ast_data_add_str(data_root, "value", vi.version);
18543    ast_data_add_str(data_root, "echocanceller", vi.echo_canceller);
18544 
18545    return 0;
18546 }
18547 
18548 static const struct ast_data_handler dahdi_status_data_provider = {
18549    .version = AST_DATA_HANDLER_VERSION,
18550    .get = dahdi_status_data_provider_get
18551 };
18552 
18553 static const struct ast_data_handler dahdi_channels_data_provider = {
18554    .version = AST_DATA_HANDLER_VERSION,
18555    .get = dahdi_channels_data_provider_get
18556 };
18557 
18558 static const struct ast_data_handler dahdi_version_data_provider = {
18559    .version = AST_DATA_HANDLER_VERSION,
18560    .get = dahdi_version_data_provider_get
18561 };
18562 
18563 static const struct ast_data_entry dahdi_data_providers[] = {
18564    AST_DATA_ENTRY("asterisk/channel/dahdi/status", &dahdi_status_data_provider),
18565    AST_DATA_ENTRY("asterisk/channel/dahdi/channels", &dahdi_channels_data_provider),
18566    AST_DATA_ENTRY("asterisk/channel/dahdi/version", &dahdi_version_data_provider)
18567 };
18568 
18569 static int load_module(void)
18570 {
18571    int res;
18572 #if defined(HAVE_PRI) || defined(HAVE_SS7)
18573    int y;
18574 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
18575 
18576 #ifdef HAVE_PRI
18577    memset(pris, 0, sizeof(pris));
18578    for (y = 0; y < NUM_SPANS; y++) {
18579       sig_pri_init_pri(&pris[y].pri);
18580    }
18581    pri_set_error(dahdi_pri_error);
18582    pri_set_message(dahdi_pri_message);
18583    ast_register_application_xml(dahdi_send_keypad_facility_app, dahdi_send_keypad_facility_exec);
18584 #ifdef HAVE_PRI_PROG_W_CAUSE
18585    ast_register_application_xml(dahdi_send_callrerouting_facility_app, dahdi_send_callrerouting_facility_exec);
18586 #endif
18587 #if defined(HAVE_PRI_CCSS)
18588    if (ast_cc_agent_register(&dahdi_pri_cc_agent_callbacks)
18589       || ast_cc_monitor_register(&dahdi_pri_cc_monitor_callbacks)) {
18590       __unload_module();
18591       return AST_MODULE_LOAD_FAILURE;
18592    }
18593 #endif   /* defined(HAVE_PRI_CCSS) */
18594    if (sig_pri_load(
18595 #if defined(HAVE_PRI_CCSS)
18596       dahdi_pri_cc_type
18597 #else
18598       NULL
18599 #endif   /* defined(HAVE_PRI_CCSS) */
18600       )) {
18601       __unload_module();
18602       return AST_MODULE_LOAD_FAILURE;
18603    }
18604 #endif
18605 #if defined(HAVE_SS7)
18606    memset(linksets, 0, sizeof(linksets));
18607    for (y = 0; y < NUM_SPANS; y++) {
18608       sig_ss7_init_linkset(&linksets[y].ss7);
18609    }
18610    ss7_set_error(dahdi_ss7_error);
18611    ss7_set_message(dahdi_ss7_message);
18612 #endif   /* defined(HAVE_SS7) */
18613    res = setup_dahdi(0);
18614    /* Make sure we can register our DAHDI channel type */
18615    if (res)
18616       return AST_MODULE_LOAD_DECLINE;
18617    if (ast_channel_register(&dahdi_tech)) {
18618       ast_log(LOG_ERROR, "Unable to register channel class 'DAHDI'\n");
18619       __unload_module();
18620       return AST_MODULE_LOAD_FAILURE;
18621    }
18622 #ifdef HAVE_PRI
18623    ast_cli_register_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
18624 #endif
18625 #if defined(HAVE_SS7)
18626    ast_cli_register_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
18627 #endif   /* defined(HAVE_SS7) */
18628 #ifdef HAVE_OPENR2
18629    ast_cli_register_multiple(dahdi_mfcr2_cli, ARRAY_LEN(dahdi_mfcr2_cli));
18630    ast_register_application_xml(dahdi_accept_r2_call_app, dahdi_accept_r2_call_exec);
18631 #endif
18632 
18633    ast_cli_register_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli));
18634    /* register all the data providers */
18635    ast_data_register_multiple(dahdi_data_providers, ARRAY_LEN(dahdi_data_providers));
18636    memset(round_robin, 0, sizeof(round_robin));
18637    ast_manager_register_xml("DAHDITransfer", 0, action_transfer);
18638    ast_manager_register_xml("DAHDIHangup", 0, action_transferhangup);
18639    ast_manager_register_xml("DAHDIDialOffhook", 0, action_dahdidialoffhook);
18640    ast_manager_register_xml("DAHDIDNDon", 0, action_dahdidndon);
18641    ast_manager_register_xml("DAHDIDNDoff", 0, action_dahdidndoff);
18642    ast_manager_register_xml("DAHDIShowChannels", 0, action_dahdishowchannels);
18643    ast_manager_register_xml("DAHDIRestart", 0, action_dahdirestart);
18644 
18645    ast_cond_init(&ss_thread_complete, NULL);
18646 
18647    return res;
18648 }
18649 
18650 static int dahdi_sendtext(struct ast_channel *c, const char *text)
18651 {
18652 #define  END_SILENCE_LEN 400
18653 #define  HEADER_MS 50
18654 #define  TRAILER_MS 5
18655 #define  HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8)
18656 #define  ASCII_BYTES_PER_CHAR 80
18657 
18658    unsigned char *buf,*mybuf;
18659    struct dahdi_pvt *p = c->tech_pvt;
18660    struct pollfd fds[1];
18661    int size,res,fd,len,x;
18662    int bytes=0;
18663    /* Initial carrier (imaginary) */
18664    float cr = 1.0;
18665    float ci = 0.0;
18666    float scont = 0.0;
18667    int idx;
18668 
18669    idx = dahdi_get_index(c, p, 0);
18670    if (idx < 0) {
18671       ast_log(LOG_WARNING, "Huh?  I don't exist?\n");
18672       return -1;
18673    }
18674    if (!text[0]) return(0); /* if nothing to send, don't */
18675    if ((!p->tdd) && (!p->mate)) return(0);  /* if not in TDD mode, just return */
18676    if (p->mate)
18677       buf = ast_malloc(((strlen(text) + 1) * ASCII_BYTES_PER_CHAR) + END_SILENCE_LEN + HEADER_LEN);
18678    else
18679       buf = ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN);
18680    if (!buf)
18681       return -1;
18682    mybuf = buf;
18683    if (p->mate) {
18684       int codec = AST_LAW(p);
18685       for (x = 0; x < HEADER_MS; x++) {   /* 50 ms of Mark */
18686          PUT_CLID_MARKMS;
18687       }
18688       /* Put actual message */
18689       for (x = 0; text[x]; x++) {
18690          PUT_CLID(text[x]);
18691       }
18692       for (x = 0; x < TRAILER_MS; x++) {  /* 5 ms of Mark */
18693          PUT_CLID_MARKMS;
18694       }
18695       len = bytes;
18696       buf = mybuf;
18697    } else {
18698       len = tdd_generate(p->tdd, buf, text);
18699       if (len < 1) {
18700          ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text));
18701          ast_free(mybuf);
18702          return -1;
18703       }
18704    }
18705    memset(buf + len, 0x7f, END_SILENCE_LEN);
18706    len += END_SILENCE_LEN;
18707    fd = p->subs[idx].dfd;
18708    while (len) {
18709       if (ast_check_hangup(c)) {
18710          ast_free(mybuf);
18711          return -1;
18712       }
18713       size = len;
18714       if (size > READ_SIZE)
18715          size = READ_SIZE;
18716       fds[0].fd = fd;
18717       fds[0].events = POLLOUT | POLLPRI;
18718       fds[0].revents = 0;
18719       res = poll(fds, 1, -1);
18720       if (!res) {
18721          ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
18722          continue;
18723       }
18724       /* if got exception */
18725       if (fds[0].revents & POLLPRI) {
18726          ast_free(mybuf);
18727          return -1;
18728       }
18729       if (!(fds[0].revents & POLLOUT)) {
18730          ast_debug(1, "write fd not ready on channel %d\n", p->channel);
18731          continue;
18732       }
18733       res = write(fd, buf, size);
18734       if (res != size) {
18735          if (res == -1) {
18736             ast_free(mybuf);
18737             return -1;
18738          }
18739          ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
18740          break;
18741       }
18742       len -= size;
18743       buf += size;
18744    }
18745    ast_free(mybuf);
18746    return(0);
18747 }
18748 
18749 
18750 static int reload(void)
18751 {
18752    int res = 0;
18753 
18754    res = setup_dahdi(1);
18755    if (res) {
18756       ast_log(LOG_WARNING, "Reload of chan_dahdi.so is unsuccessful!\n");
18757       return -1;
18758    }
18759    return 0;
18760 }
18761 
18762 /* This is a workaround so that menuselect displays a proper description
18763  * AST_MODULE_INFO(, , "DAHDI Telephony"
18764  */
18765 
18766 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, tdesc,
18767    .load = load_module,
18768    .unload = unload_module,
18769    .reload = reload,
18770    .load_pri = AST_MODPRI_CHANNEL_DRIVER,
18771       .nonoptreq = "res_smdi",
18772    );

Generated on Mon Oct 8 12:38:59 2012 for Asterisk - The Open Source Telephony Project by  doxygen 1.4.7