Mon Jun 18 2012 03:55:24

Asterisk developer's documentation


chan_dahdi.c
Go to the documentation of this file.
00001 /*
00002  * Asterisk -- An open source telephony toolkit.
00003  *
00004  * Copyright (C) 1999 - 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: 358377 $")
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 Length of "busy" tone on time.
01127     * \note Set from the "busypattern" value read in from chan_dahdi.conf
01128     */
01129    int busy_tonelength;
01130    /*!
01131     * \brief Length of "busy" tone off time.
01132     * \note Set from the "busypattern" value read in from chan_dahdi.conf
01133     */
01134    int busy_quietlength;
01135    /*!
01136     * \brief Bitmapped call progress detection flags. CALLPROGRESS_xxx values.
01137     * \note Bits set from the "callprogress" and "faxdetect" values read in from chan_dahdi.conf
01138     */
01139    int callprogress;
01140    /*!
01141     * \brief Number of milliseconds to wait for dialtone.
01142     * \note Set from the "waitfordialtone" value read in from chan_dahdi.conf
01143     */
01144    int waitfordialtone;
01145    struct timeval waitingfordt;        /*!< Time we started waiting for dialtone */
01146    struct timeval flashtime;        /*!< Last flash-hook time */
01147    /*! \brief Opaque DSP configuration structure. */
01148    struct ast_dsp *dsp;
01149    /*! \brief DAHDI dial operation command struct for ioctl() call. */
01150    struct dahdi_dialoperation dop;
01151    int whichwink;             /*!< SIG_FEATDMF_TA Which wink are we on? */
01152    /*! \brief Second part of SIG_FEATDMF_TA wink operation. */
01153    char finaldial[64];
01154    char accountcode[AST_MAX_ACCOUNT_CODE];      /*!< Account code */
01155    int amaflags;              /*!< AMA Flags */
01156    struct tdd_state *tdd;           /*!< TDD flag */
01157    /*! \brief Accumulated call forwarding number. */
01158    char call_forward[AST_MAX_EXTENSION];
01159    /*!
01160     * \brief Voice mailbox location.
01161     * \note Set from the "mailbox" string read in from chan_dahdi.conf
01162     */
01163    char mailbox[AST_MAX_EXTENSION];
01164    /*! \brief Opaque event subscription parameters for message waiting indication support. */
01165    struct ast_event_sub *mwi_event_sub;
01166    /*! \brief Delayed dialing for E911.  Overlap digits for ISDN. */
01167    char dialdest[256];
01168 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
01169    struct dahdi_vmwi_info mwisend_setting;            /*!< Which VMWI methods to use */
01170    unsigned int mwisend_fsk: 1;     /*! Variable for enabling FSK MWI handling in chan_dahdi */
01171    unsigned int mwisend_rpas:1;     /*! Variable for enabling Ring Pulse Alert before MWI FSK Spill */
01172 #endif
01173    int distinctivering;          /*!< Which distinctivering to use */
01174    int dtmfrelax;             /*!< whether to run in relaxed DTMF mode */
01175    /*! \brief Holding place for event injected from outside normal operation. */
01176    int fake_event;
01177    /*!
01178     * \brief Minimal time period (ms) between the answer polarity
01179     * switch and hangup polarity switch.
01180     */
01181    int polarityonanswerdelay;
01182    /*! \brief Start delay time if polarityonanswerdelay is nonzero. */
01183    struct timeval polaritydelaytv;
01184    /*!
01185     * \brief Send caller ID on FXS after this many rings. Set to 1 for US.
01186     * \note Set from the "sendcalleridafter" value read in from chan_dahdi.conf
01187     */
01188    int sendcalleridafter;
01189    /*! \brief Current line interface polarity. POLARITY_IDLE, POLARITY_REV */
01190    int polarity;
01191    /*! \brief DSP feature flags: DSP_FEATURE_xxx */
01192    int dsp_features;
01193 #if defined(HAVE_SS7)
01194    /*! \brief SS7 control parameters */
01195    struct sig_ss7_linkset *ss7;
01196 #endif   /* defined(HAVE_SS7) */
01197 #ifdef HAVE_OPENR2
01198    struct dahdi_mfcr2 *mfcr2;
01199    openr2_chan_t *r2chan;
01200    openr2_calling_party_category_t mfcr2_recvd_category;
01201    openr2_calling_party_category_t mfcr2_category;
01202    int mfcr2_dnis_index;
01203    int mfcr2_ani_index;
01204    int mfcr2call:1;
01205    int mfcr2_answer_pending:1;
01206    int mfcr2_charge_calls:1;
01207    int mfcr2_allow_collect_calls:1;
01208    int mfcr2_forced_release:1;
01209    int mfcr2_dnis_matched:1;
01210    int mfcr2_call_accepted:1;
01211    int mfcr2_progress:1;
01212    int mfcr2_accept_on_offer:1;
01213 #endif
01214    /*! \brief DTMF digit in progress.  0 when no digit in progress. */
01215    char begindigit;
01216    /*! \brief TRUE if confrence is muted. */
01217    int muting;
01218    void *sig_pvt;
01219    struct ast_cc_config_params *cc_params;
01220    /* DAHDI channel names may differ greatly from the
01221     * string that was provided to an app such as Dial. We
01222     * need to save the original string passed to dahdi_request
01223     * for call completion purposes. This way, we can replicate
01224     * the original dialed string later.
01225     */
01226    char dialstring[AST_CHANNEL_NAME];
01227 };
01228 
01229 #define DATA_EXPORT_DAHDI_PVT(MEMBER)              \
01230    MEMBER(dahdi_pvt, cid_rxgain, AST_DATA_DOUBLE)        \
01231    MEMBER(dahdi_pvt, rxgain, AST_DATA_DOUBLE)         \
01232    MEMBER(dahdi_pvt, txgain, AST_DATA_DOUBLE)         \
01233    MEMBER(dahdi_pvt, txdrc, AST_DATA_DOUBLE)       \
01234    MEMBER(dahdi_pvt, rxdrc, AST_DATA_DOUBLE)       \
01235    MEMBER(dahdi_pvt, adsi, AST_DATA_BOOLEAN)       \
01236    MEMBER(dahdi_pvt, answeronpolarityswitch, AST_DATA_BOOLEAN) \
01237    MEMBER(dahdi_pvt, busydetect, AST_DATA_BOOLEAN)       \
01238    MEMBER(dahdi_pvt, callreturn, AST_DATA_BOOLEAN)       \
01239    MEMBER(dahdi_pvt, callwaiting, AST_DATA_BOOLEAN)      \
01240    MEMBER(dahdi_pvt, callwaitingcallerid, AST_DATA_BOOLEAN) \
01241    MEMBER(dahdi_pvt, cancallforward, AST_DATA_BOOLEAN)      \
01242    MEMBER(dahdi_pvt, canpark, AST_DATA_BOOLEAN)       \
01243    MEMBER(dahdi_pvt, confirmanswer, AST_DATA_BOOLEAN)    \
01244    MEMBER(dahdi_pvt, destroy, AST_DATA_BOOLEAN)       \
01245    MEMBER(dahdi_pvt, didtdd, AST_DATA_BOOLEAN)        \
01246    MEMBER(dahdi_pvt, dialednone, AST_DATA_BOOLEAN)       \
01247    MEMBER(dahdi_pvt, dialing, AST_DATA_BOOLEAN)       \
01248    MEMBER(dahdi_pvt, digital, AST_DATA_BOOLEAN)       \
01249    MEMBER(dahdi_pvt, dnd, AST_DATA_BOOLEAN)        \
01250    MEMBER(dahdi_pvt, echobreak, AST_DATA_BOOLEAN)        \
01251    MEMBER(dahdi_pvt, echocanbridged, AST_DATA_BOOLEAN)      \
01252    MEMBER(dahdi_pvt, echocanon, AST_DATA_BOOLEAN)        \
01253    MEMBER(dahdi_pvt, faxhandled, AST_DATA_BOOLEAN)       \
01254    MEMBER(dahdi_pvt, usefaxbuffers, AST_DATA_BOOLEAN)    \
01255    MEMBER(dahdi_pvt, bufferoverrideinuse, AST_DATA_BOOLEAN) \
01256    MEMBER(dahdi_pvt, firstradio, AST_DATA_BOOLEAN)       \
01257    MEMBER(dahdi_pvt, hanguponpolarityswitch, AST_DATA_BOOLEAN) \
01258    MEMBER(dahdi_pvt, hardwaredtmf, AST_DATA_BOOLEAN)     \
01259    MEMBER(dahdi_pvt, hidecallerid, AST_DATA_BOOLEAN)     \
01260    MEMBER(dahdi_pvt, hidecalleridname, AST_DATA_BOOLEAN)    \
01261    MEMBER(dahdi_pvt, ignoredtmf, AST_DATA_BOOLEAN)       \
01262    MEMBER(dahdi_pvt, immediate, AST_DATA_BOOLEAN)        \
01263    MEMBER(dahdi_pvt, inalarm, AST_DATA_BOOLEAN)       \
01264    MEMBER(dahdi_pvt, mate, AST_DATA_BOOLEAN)       \
01265    MEMBER(dahdi_pvt, outgoing, AST_DATA_BOOLEAN)         \
01266    MEMBER(dahdi_pvt, permcallwaiting, AST_DATA_BOOLEAN)     \
01267    MEMBER(dahdi_pvt, priindication_oob, AST_DATA_BOOLEAN)      \
01268    MEMBER(dahdi_pvt, priexclusive, AST_DATA_BOOLEAN)     \
01269    MEMBER(dahdi_pvt, pulse, AST_DATA_BOOLEAN)         \
01270    MEMBER(dahdi_pvt, pulsedial, AST_DATA_BOOLEAN)        \
01271    MEMBER(dahdi_pvt, restartpending, AST_DATA_BOOLEAN)      \
01272    MEMBER(dahdi_pvt, restrictcid, AST_DATA_BOOLEAN)      \
01273    MEMBER(dahdi_pvt, threewaycalling, AST_DATA_BOOLEAN)     \
01274    MEMBER(dahdi_pvt, transfer, AST_DATA_BOOLEAN)         \
01275    MEMBER(dahdi_pvt, use_callerid, AST_DATA_BOOLEAN)     \
01276    MEMBER(dahdi_pvt, use_callingpres, AST_DATA_BOOLEAN)     \
01277    MEMBER(dahdi_pvt, usedistinctiveringdetection, AST_DATA_BOOLEAN)  \
01278    MEMBER(dahdi_pvt, dahditrcallerid, AST_DATA_BOOLEAN)        \
01279    MEMBER(dahdi_pvt, transfertobusy, AST_DATA_BOOLEAN)         \
01280    MEMBER(dahdi_pvt, mwimonitor_neon, AST_DATA_BOOLEAN)        \
01281    MEMBER(dahdi_pvt, mwimonitor_fsk, AST_DATA_BOOLEAN)         \
01282    MEMBER(dahdi_pvt, mwimonitor_rpas, AST_DATA_BOOLEAN)        \
01283    MEMBER(dahdi_pvt, mwimonitoractive, AST_DATA_BOOLEAN)       \
01284    MEMBER(dahdi_pvt, mwisendactive, AST_DATA_BOOLEAN)       \
01285    MEMBER(dahdi_pvt, inservice, AST_DATA_BOOLEAN)           \
01286    MEMBER(dahdi_pvt, locallyblocked, AST_DATA_BOOLEAN)         \
01287    MEMBER(dahdi_pvt, remotelyblocked, AST_DATA_BOOLEAN)        \
01288    MEMBER(dahdi_pvt, manages_span_alarms, AST_DATA_BOOLEAN)    \
01289    MEMBER(dahdi_pvt, use_smdi, AST_DATA_BOOLEAN)            \
01290    MEMBER(dahdi_pvt, context, AST_DATA_STRING)           \
01291    MEMBER(dahdi_pvt, defcontext, AST_DATA_STRING)           \
01292    MEMBER(dahdi_pvt, exten, AST_DATA_STRING)          \
01293    MEMBER(dahdi_pvt, language, AST_DATA_STRING)          \
01294    MEMBER(dahdi_pvt, mohinterpret, AST_DATA_STRING)         \
01295    MEMBER(dahdi_pvt, mohsuggest, AST_DATA_STRING)           \
01296    MEMBER(dahdi_pvt, parkinglot, AST_DATA_STRING)
01297 
01298 AST_DATA_STRUCTURE(dahdi_pvt, DATA_EXPORT_DAHDI_PVT);
01299 
01300 static struct dahdi_pvt *iflist = NULL;   /*!< Main interface list start */
01301 static struct dahdi_pvt *ifend = NULL; /*!< Main interface list end */
01302 
01303 #if defined(HAVE_PRI)
01304 static struct dahdi_parms_pseudo {
01305    int buf_no;             /*!< Number of buffers */
01306    int buf_policy;            /*!< Buffer policy */
01307    int faxbuf_no;              /*!< Number of Fax buffers */
01308    int faxbuf_policy;          /*!< Fax buffer policy */
01309 } dahdi_pseudo_parms;
01310 #endif   /* defined(HAVE_PRI) */
01311 
01312 /*! \brief Channel configuration from chan_dahdi.conf .
01313  * This struct is used for parsing the [channels] section of chan_dahdi.conf.
01314  * Generally there is a field here for every possible configuration item.
01315  *
01316  * The state of fields is saved along the parsing and whenever a 'channel'
01317  * statement is reached, the current dahdi_chan_conf is used to configure the
01318  * channel (struct dahdi_pvt)
01319  *
01320  * \see dahdi_chan_init for the default values.
01321  */
01322 struct dahdi_chan_conf {
01323    struct dahdi_pvt chan;
01324 #ifdef HAVE_PRI
01325    struct dahdi_pri pri;
01326 #endif
01327 
01328 #if defined(HAVE_SS7)
01329    struct dahdi_ss7 ss7;
01330 #endif   /* defined(HAVE_SS7) */
01331 
01332 #ifdef HAVE_OPENR2
01333    struct dahdi_mfcr2_conf mfcr2;
01334 #endif
01335    struct dahdi_params timing;
01336    int is_sig_auto; /*!< Use channel signalling from DAHDI? */
01337    /*! Continue configuration even if a channel is not there. */
01338    int ignore_failed_channels;
01339 
01340    /*!
01341     * \brief The serial port to listen for SMDI data on
01342     * \note Set from the "smdiport" string read in from chan_dahdi.conf
01343     */
01344    char smdi_port[SMDI_MAX_FILENAME_LEN];
01345 };
01346 
01347 /*! returns a new dahdi_chan_conf with default values (by-value) */
01348 static struct dahdi_chan_conf dahdi_chan_conf_default(void)
01349 {
01350    /* recall that if a field is not included here it is initialized
01351     * to 0 or equivalent
01352     */
01353    struct dahdi_chan_conf conf = {
01354 #ifdef HAVE_PRI
01355       .pri.pri = {
01356          .nsf = PRI_NSF_NONE,
01357          .switchtype = PRI_SWITCH_NI2,
01358          .dialplan = PRI_UNKNOWN + 1,
01359          .localdialplan = PRI_NATIONAL_ISDN + 1,
01360          .nodetype = PRI_CPE,
01361          .qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL,
01362 
01363 #if defined(HAVE_PRI_CCSS)
01364          .cc_ptmp_recall_mode = 1,/* specificRecall */
01365          .cc_qsig_signaling_link_req = 1,/* retain */
01366          .cc_qsig_signaling_link_rsp = 1,/* retain */
01367 #endif   /* defined(HAVE_PRI_CCSS) */
01368 
01369          .minunused = 2,
01370          .idleext = "",
01371          .idledial = "",
01372          .internationalprefix = "",
01373          .nationalprefix = "",
01374          .localprefix = "",
01375          .privateprefix = "",
01376          .unknownprefix = "",
01377          .resetinterval = -1,
01378       },
01379 #endif
01380 #if defined(HAVE_SS7)
01381       .ss7.ss7 = {
01382          .called_nai = SS7_NAI_NATIONAL,
01383          .calling_nai = SS7_NAI_NATIONAL,
01384          .internationalprefix = "",
01385          .nationalprefix = "",
01386          .subscriberprefix = "",
01387          .unknownprefix = ""
01388       },
01389 #endif   /* defined(HAVE_SS7) */
01390 #ifdef HAVE_OPENR2
01391       .mfcr2 = {
01392          .variant = OR2_VAR_ITU,
01393          .mfback_timeout = -1,
01394          .metering_pulse_timeout = -1,
01395          .max_ani = 10,
01396          .max_dnis = 4,
01397          .get_ani_first = -1,
01398 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
01399          .skip_category_request = -1,
01400 #endif
01401          .call_files = 0,
01402          .allow_collect_calls = 0,
01403          .charge_calls = 1,
01404          .accept_on_offer = 1,
01405          .forced_release = 0,
01406          .double_answer = 0,
01407          .immediate_accept = -1,
01408          .logdir = "",
01409          .r2proto_file = "",
01410          .loglevel = OR2_LOG_ERROR | OR2_LOG_WARNING,
01411          .category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER
01412       },
01413 #endif
01414       .chan = {
01415          .context = "default",
01416          .cid_num = "",
01417          .cid_name = "",
01418          .cid_tag = "",
01419          .mohinterpret = "default",
01420          .mohsuggest = "",
01421          .parkinglot = "",
01422          .transfertobusy = 1,
01423 
01424          .cid_signalling = CID_SIG_BELL,
01425          .cid_start = CID_START_RING,
01426          .dahditrcallerid = 0,
01427          .use_callerid = 1,
01428          .sig = -1,
01429          .outsigmod = -1,
01430 
01431          .cid_rxgain = +5.0,
01432 
01433          .tonezone = -1,
01434 
01435          .echocancel.head.tap_length = 1,
01436 
01437          .busycount = 3,
01438 
01439          .accountcode = "",
01440 
01441          .mailbox = "",
01442 
01443 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
01444          .mwisend_fsk = 1,
01445 #endif
01446          .polarityonanswerdelay = 600,
01447 
01448          .sendcalleridafter = DEFAULT_CIDRINGS,
01449 
01450          .buf_policy = DAHDI_POLICY_IMMEDIATE,
01451          .buf_no = numbufs,
01452          .usefaxbuffers = 0,
01453          .cc_params = ast_cc_config_params_init(),
01454       },
01455       .timing = {
01456          .prewinktime = -1,
01457          .preflashtime = -1,
01458          .winktime = -1,
01459          .flashtime = -1,
01460          .starttime = -1,
01461          .rxwinktime = -1,
01462          .rxflashtime = -1,
01463          .debouncetime = -1
01464       },
01465       .is_sig_auto = 1,
01466       .smdi_port = "/dev/ttyS0",
01467    };
01468 
01469    return conf;
01470 }
01471 
01472 
01473 static struct ast_channel *dahdi_request(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause);
01474 static int dahdi_digit_begin(struct ast_channel *ast, char digit);
01475 static int dahdi_digit_end(struct ast_channel *ast, char digit, unsigned int duration);
01476 static int dahdi_sendtext(struct ast_channel *c, const char *text);
01477 static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout);
01478 static int dahdi_hangup(struct ast_channel *ast);
01479 static int dahdi_answer(struct ast_channel *ast);
01480 static struct ast_frame *dahdi_read(struct ast_channel *ast);
01481 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame);
01482 static struct ast_frame *dahdi_exception(struct ast_channel *ast);
01483 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen);
01484 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
01485 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen);
01486 static int dahdi_queryoption(struct ast_channel *chan, int option, void *data, int *datalen);
01487 static int dahdi_func_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len);
01488 static int dahdi_func_write(struct ast_channel *chan, const char *function, char *data, const char *value);
01489 static int dahdi_devicestate(void *data);
01490 static int dahdi_cc_callback(struct ast_channel *inbound, const char *dest, ast_cc_callback_fn callback);
01491 
01492 static const struct ast_channel_tech dahdi_tech = {
01493    .type = "DAHDI",
01494    .description = tdesc,
01495    .capabilities = AST_FORMAT_SLINEAR | AST_FORMAT_ULAW | AST_FORMAT_ALAW,
01496    .requester = dahdi_request,
01497    .send_digit_begin = dahdi_digit_begin,
01498    .send_digit_end = dahdi_digit_end,
01499    .send_text = dahdi_sendtext,
01500    .call = dahdi_call,
01501    .hangup = dahdi_hangup,
01502    .answer = dahdi_answer,
01503    .read = dahdi_read,
01504    .write = dahdi_write,
01505    .bridge = dahdi_bridge,
01506    .exception = dahdi_exception,
01507    .indicate = dahdi_indicate,
01508    .fixup = dahdi_fixup,
01509    .setoption = dahdi_setoption,
01510    .queryoption = dahdi_queryoption,
01511    .func_channel_read = dahdi_func_read,
01512    .func_channel_write = dahdi_func_write,
01513    .devicestate = dahdi_devicestate,
01514    .cc_callback = dahdi_cc_callback,
01515 };
01516 
01517 #define GET_CHANNEL(p) ((p)->channel)
01518 
01519 #define SIG_PRI_LIB_HANDLE_CASES \
01520    SIG_PRI:                \
01521    case SIG_BRI:              \
01522    case SIG_BRI_PTMP
01523 
01524 /*!
01525  * \internal
01526  * \brief Determine if sig_pri handles the signaling.
01527  * \since 1.8
01528  *
01529  * \param signaling Signaling to determine if is for sig_pri.
01530  *
01531  * \return TRUE if the signaling is for sig_pri.
01532  */
01533 static inline int dahdi_sig_pri_lib_handles(int signaling)
01534 {
01535    int handles;
01536 
01537    switch (signaling) {
01538    case SIG_PRI_LIB_HANDLE_CASES:
01539       handles = 1;
01540       break;
01541    default:
01542       handles = 0;
01543       break;
01544    }
01545 
01546    return handles;
01547 }
01548 
01549 static enum analog_sigtype dahdisig_to_analogsig(int sig)
01550 {
01551    switch (sig) {
01552    case SIG_FXOLS:
01553       return ANALOG_SIG_FXOLS;
01554    case SIG_FXOGS:
01555       return ANALOG_SIG_FXOGS;
01556    case SIG_FXOKS:
01557       return ANALOG_SIG_FXOKS;
01558    case SIG_FXSLS:
01559       return ANALOG_SIG_FXSLS;
01560    case SIG_FXSGS:
01561       return ANALOG_SIG_FXSGS;
01562    case SIG_FXSKS:
01563       return ANALOG_SIG_FXSKS;
01564    case SIG_EMWINK:
01565       return ANALOG_SIG_EMWINK;
01566    case SIG_EM:
01567       return ANALOG_SIG_EM;
01568    case SIG_EM_E1:
01569       return ANALOG_SIG_EM_E1;
01570    case SIG_FEATD:
01571       return ANALOG_SIG_FEATD;
01572    case SIG_FEATDMF:
01573       return ANALOG_SIG_FEATDMF;
01574    case SIG_E911:
01575       return SIG_E911;
01576    case SIG_FGC_CAMA:
01577       return ANALOG_SIG_FGC_CAMA;
01578    case SIG_FGC_CAMAMF:
01579       return ANALOG_SIG_FGC_CAMAMF;
01580    case SIG_FEATB:
01581       return ANALOG_SIG_FEATB;
01582    case SIG_SFWINK:
01583       return ANALOG_SIG_SFWINK;
01584    case SIG_SF:
01585       return ANALOG_SIG_SF;
01586    case SIG_SF_FEATD:
01587       return ANALOG_SIG_SF_FEATD;
01588    case SIG_SF_FEATDMF:
01589       return ANALOG_SIG_SF_FEATDMF;
01590    case SIG_FEATDMF_TA:
01591       return ANALOG_SIG_FEATDMF_TA;
01592    case SIG_SF_FEATB:
01593       return ANALOG_SIG_FEATB;
01594    default:
01595       return -1;
01596    }
01597 }
01598 
01599 
01600 static int analog_tone_to_dahditone(enum analog_tone tone)
01601 {
01602    switch (tone) {
01603    case ANALOG_TONE_RINGTONE:
01604       return DAHDI_TONE_RINGTONE;
01605    case ANALOG_TONE_STUTTER:
01606       return DAHDI_TONE_STUTTER;
01607    case ANALOG_TONE_CONGESTION:
01608       return DAHDI_TONE_CONGESTION;
01609    case ANALOG_TONE_DIALTONE:
01610       return DAHDI_TONE_DIALTONE;
01611    case ANALOG_TONE_DIALRECALL:
01612       return DAHDI_TONE_DIALRECALL;
01613    case ANALOG_TONE_INFO:
01614       return DAHDI_TONE_INFO;
01615    default:
01616       return -1;
01617    }
01618 }
01619 
01620 static int analogsub_to_dahdisub(enum analog_sub analogsub)
01621 {
01622    int index;
01623 
01624    switch (analogsub) {
01625    case ANALOG_SUB_REAL:
01626       index = SUB_REAL;
01627       break;
01628    case ANALOG_SUB_CALLWAIT:
01629       index = SUB_CALLWAIT;
01630       break;
01631    case ANALOG_SUB_THREEWAY:
01632       index = SUB_THREEWAY;
01633       break;
01634    default:
01635       ast_log(LOG_ERROR, "Unidentified sub!\n");
01636       index = SUB_REAL;
01637    }
01638 
01639    return index;
01640 }
01641 
01642 static enum analog_event dahdievent_to_analogevent(int event);
01643 static int bump_gains(struct dahdi_pvt *p);
01644 static int dahdi_setlinear(int dfd, int linear);
01645 
01646 static int my_start_cid_detect(void *pvt, int cid_signalling)
01647 {
01648    struct dahdi_pvt *p = pvt;
01649    int index = SUB_REAL;
01650    p->cs = callerid_new(cid_signalling);
01651    if (!p->cs) {
01652       ast_log(LOG_ERROR, "Unable to alloc callerid\n");
01653       return -1;
01654    }
01655    bump_gains(p);
01656    dahdi_setlinear(p->subs[index].dfd, 0);
01657 
01658    return 0;
01659 }
01660 
01661 static int my_stop_cid_detect(void *pvt)
01662 {
01663    struct dahdi_pvt *p = pvt;
01664    int index = SUB_REAL;
01665    if (p->cs)
01666       callerid_free(p->cs);
01667    dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
01668    return 0;
01669 }
01670 
01671 static int my_get_callerid(void *pvt, char *namebuf, char *numbuf, enum analog_event *ev, size_t timeout)
01672 {
01673    struct dahdi_pvt *p = pvt;
01674    struct analog_pvt *analog_p = p->sig_pvt;
01675    struct pollfd poller;
01676    char *name, *num;
01677    int index = SUB_REAL;
01678    int res;
01679    unsigned char buf[256];
01680    int flags;
01681 
01682    poller.fd = p->subs[SUB_REAL].dfd;
01683    poller.events = POLLPRI | POLLIN;
01684    poller.revents = 0;
01685 
01686    res = poll(&poller, 1, timeout);
01687 
01688    if (poller.revents & POLLPRI) {
01689       *ev = dahdievent_to_analogevent(dahdi_get_event(p->subs[SUB_REAL].dfd));
01690       return 1;
01691    }
01692 
01693    if (poller.revents & POLLIN) {
01694       /*** NOTES ***/
01695       /* Change API: remove cid_signalling from get_callerid, add a new start_cid_detect and stop_cid_detect function
01696        * to enable slin mode and allocate cid detector. get_callerid should be able to be called any number of times until
01697        * either a timeout occurs or CID is detected (returns 0). returning 1 should be event received, and -1 should be
01698        * a failure and die, and returning 2 means no event was received. */
01699       res = read(p->subs[index].dfd, buf, sizeof(buf));
01700       if (res < 0) {
01701          if (errno != ELAST) {
01702             ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
01703             callerid_free(p->cs);
01704             return -1;
01705          }
01706       }
01707 
01708       if (analog_p->ringt > 0) {
01709          if (!(--analog_p->ringt)) {
01710             /* only return if we timeout from a ring event */
01711             return -1;
01712          }
01713       }
01714 
01715       if (p->cid_signalling == CID_SIG_V23_JP) {
01716          res = callerid_feed_jp(p->cs, buf, res, AST_LAW(p));
01717       } else {
01718          res = callerid_feed(p->cs, buf, res, AST_LAW(p));
01719       }
01720       if (res < 0) {
01721          /*
01722           * The previous diagnostic message output likely
01723           * explains why it failed.
01724           */
01725          ast_log(LOG_WARNING, "Failed to decode CallerID\n");
01726          return -1;
01727       }
01728 
01729       if (res == 1) {
01730          callerid_get(p->cs, &name, &num, &flags);
01731          if (name)
01732             ast_copy_string(namebuf, name, ANALOG_MAX_CID);
01733          if (num)
01734             ast_copy_string(numbuf, num, ANALOG_MAX_CID);
01735 
01736          ast_debug(1, "CallerID number: %s, name: %s, flags=%d\n", num, name, flags);
01737          return 0;
01738       }
01739    }
01740 
01741    *ev = ANALOG_EVENT_NONE;
01742    return 2;
01743 }
01744 
01745 static const char *event2str(int event);
01746 static int restore_gains(struct dahdi_pvt *p);
01747 
01748 static int my_distinctive_ring(struct ast_channel *chan, void *pvt, int idx, int *ringdata)
01749 {
01750    unsigned char buf[256];
01751    int distMatches;
01752    int curRingData[RING_PATTERNS];
01753    int receivedRingT;
01754    int counter1;
01755    int counter;
01756    int i;
01757    int res;
01758    int checkaftercid = 0;
01759 
01760    struct dahdi_pvt *p = pvt;
01761    struct analog_pvt *analog_p = p->sig_pvt;
01762 
01763    if (ringdata == NULL) {
01764       ringdata = curRingData;
01765    } else {
01766       checkaftercid = 1;
01767    }
01768 
01769    /* We must have a ring by now, so, if configured, lets try to listen for
01770     * distinctive ringing */
01771    if ((checkaftercid && distinctiveringaftercid) || !checkaftercid) {
01772       /* Clear the current ring data array so we don't have old data in it. */
01773       for (receivedRingT = 0; receivedRingT < RING_PATTERNS; receivedRingT++)
01774          ringdata[receivedRingT] = 0;
01775       receivedRingT = 0;
01776       if (checkaftercid && distinctiveringaftercid)
01777          ast_verb(3, "Detecting post-CID distinctive ring\n");
01778       /* Check to see if context is what it should be, if not set to be. */
01779       else if (strcmp(p->context,p->defcontext) != 0) {
01780          ast_copy_string(p->context, p->defcontext, sizeof(p->context));
01781          ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
01782       }
01783 
01784       for (;;) {
01785          i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
01786          if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
01787             ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
01788             ast_hangup(chan);
01789             return 1;
01790          }
01791          if (i & DAHDI_IOMUX_SIGEVENT) {
01792             res = dahdi_get_event(p->subs[idx].dfd);
01793             if (res == DAHDI_EVENT_NOALARM) {
01794                p->inalarm = 0;
01795                analog_p->inalarm = 0;
01796             }
01797             ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
01798             res = 0;
01799             /* Let us detect distinctive ring */
01800 
01801             ringdata[receivedRingT] = analog_p->ringt;
01802 
01803             if (analog_p->ringt < analog_p->ringt_base/2)
01804                break;
01805             /* Increment the ringT counter so we can match it against
01806                values in chan_dahdi.conf for distinctive ring */
01807             if (++receivedRingT == RING_PATTERNS)
01808                break;
01809          } else if (i & DAHDI_IOMUX_READ) {
01810             res = read(p->subs[idx].dfd, buf, sizeof(buf));
01811             if (res < 0) {
01812                if (errno != ELAST) {
01813                   ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
01814                   ast_hangup(chan);
01815                   return 1;
01816                }
01817                break;
01818             }
01819             if (analog_p->ringt > 0) {
01820                if (!(--analog_p->ringt)) {
01821                   res = -1;
01822                   break;
01823                }
01824             }
01825          }
01826       }
01827    }
01828    if ((checkaftercid && usedistinctiveringdetection) || !checkaftercid) {
01829       /* this only shows up if you have n of the dring patterns filled in */
01830       ast_verb(3, "Detected ring pattern: %d,%d,%d\n",ringdata[0],ringdata[1],ringdata[2]);
01831       for (counter = 0; counter < 3; counter++) {
01832       /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this channel */
01833          distMatches = 0;
01834          /* this only shows up if you have n of the dring patterns filled in */
01835          ast_verb(3, "Checking %d,%d,%d\n",
01836                p->drings.ringnum[counter].ring[0],
01837                p->drings.ringnum[counter].ring[1],
01838                p->drings.ringnum[counter].ring[2]);
01839          for (counter1 = 0; counter1 < 3; counter1++) {
01840             ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
01841             if (p->drings.ringnum[counter].ring[counter1] == -1) {
01842                ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
01843                ringdata[counter1]);
01844                distMatches++;
01845             } else if (ringdata[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
01846                               ringdata[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
01847                ast_verb(3, "Ring pattern matched in range: %d to %d\n",
01848                (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
01849                (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
01850                distMatches++;
01851             }
01852          }
01853 
01854          if (distMatches == 3) {
01855             /* The ring matches, set the context to whatever is for distinctive ring.. */
01856             ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context));
01857             ast_copy_string(chan->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(chan->context));
01858             ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
01859             break;
01860          }
01861       }
01862    }
01863    /* Restore linear mode (if appropriate) for Caller*ID processing */
01864    dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
01865    restore_gains(p);
01866 
01867    return 0;
01868 }
01869 
01870 static int my_stop_callwait(void *pvt)
01871 {
01872    struct dahdi_pvt *p = pvt;
01873    p->callwaitingrepeat = 0;
01874    p->cidcwexpire = 0;
01875    p->cid_suppress_expire = 0;
01876 
01877    return 0;
01878 }
01879 
01880 static int send_callerid(struct dahdi_pvt *p);
01881 static int save_conference(struct dahdi_pvt *p);
01882 static int restore_conference(struct dahdi_pvt *p);
01883 
01884 static int my_callwait(void *pvt)
01885 {
01886    struct dahdi_pvt *p = pvt;
01887    p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
01888    if (p->cidspill) {
01889       ast_log(LOG_WARNING, "Spill already exists?!?\n");
01890       ast_free(p->cidspill);
01891    }
01892 
01893    /*
01894     * SAS: Subscriber Alert Signal, 440Hz for 300ms
01895     * CAS: CPE Alert Signal, 2130Hz * 2750Hz sine waves
01896     */
01897    if (!(p->cidspill = ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE * 4)))
01898       return -1;
01899    save_conference(p);
01900    /* Silence */
01901    memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
01902    if (!p->callwaitrings && p->callwaitingcallerid) {
01903       ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
01904       p->callwaitcas = 1;
01905       p->cidlen = 2400 + 680 + READ_SIZE * 4;
01906    } else {
01907       ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
01908       p->callwaitcas = 0;
01909       p->cidlen = 2400 + READ_SIZE * 4;
01910    }
01911    p->cidpos = 0;
01912    send_callerid(p);
01913 
01914    return 0;
01915 }
01916 
01917 static int my_send_callerid(void *pvt, int cwcid, struct ast_party_caller *caller)
01918 {
01919    struct dahdi_pvt *p = pvt;
01920 
01921    ast_debug(2, "Starting cid spill\n");
01922 
01923    if (p->cidspill) {
01924       ast_log(LOG_WARNING, "cidspill already exists??\n");
01925       ast_free(p->cidspill);
01926    }
01927 
01928    if ((p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) {
01929       if (cwcid == 0) {
01930          p->cidlen = ast_callerid_generate(p->cidspill,
01931             caller->id.name.str,
01932             caller->id.number.str,
01933             AST_LAW(p));
01934       } else {
01935          ast_verb(3, "CPE supports Call Waiting Caller*ID.  Sending '%s/%s'\n",
01936             caller->id.name.str, caller->id.number.str);
01937          p->callwaitcas = 0;
01938          p->cidcwexpire = 0;
01939          p->cidlen = ast_callerid_callwaiting_generate(p->cidspill,
01940             caller->id.name.str,
01941             caller->id.number.str,
01942             AST_LAW(p));
01943          p->cidlen += READ_SIZE * 4;
01944       }
01945       p->cidpos = 0;
01946       p->cid_suppress_expire = 0;
01947       send_callerid(p);
01948    }
01949    return 0;
01950 }
01951 
01952 static int my_dsp_reset_and_flush_digits(void *pvt)
01953 {
01954    struct dahdi_pvt *p = pvt;
01955    if (p->dsp)
01956       ast_dsp_digitreset(p->dsp);
01957 
01958    return 0;
01959 }
01960 
01961 static int my_dsp_set_digitmode(void *pvt, enum analog_dsp_digitmode mode)
01962 {
01963    struct dahdi_pvt *p = pvt;
01964 
01965    if (p->channel == CHAN_PSEUDO)
01966       ast_log(LOG_ERROR, "You have assumed incorrectly sir!\n");
01967 
01968    if (mode == ANALOG_DIGITMODE_DTMF) {
01969       /* If we do hardware dtmf, no need for a DSP */
01970       if (p->hardwaredtmf) {
01971          if (p->dsp) {
01972             ast_dsp_free(p->dsp);
01973             p->dsp = NULL;
01974          }
01975          return 0;
01976       }
01977 
01978       if (!p->dsp) {
01979          p->dsp = ast_dsp_new();
01980          if (!p->dsp) {
01981             ast_log(LOG_ERROR, "Unable to allocate DSP\n");
01982             return -1;
01983          }
01984       }
01985 
01986       ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
01987    } else if (mode == ANALOG_DIGITMODE_MF) {
01988       if (!p->dsp) {
01989          p->dsp = ast_dsp_new();
01990          if (!p->dsp) {
01991             ast_log(LOG_ERROR, "Unable to allocate DSP\n");
01992             return -1;
01993          }
01994       }
01995       ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
01996    }
01997    return 0;
01998 }
01999 
02000 static int dahdi_wink(struct dahdi_pvt *p, int index);
02001 
02002 static int my_wink(void *pvt, enum analog_sub sub)
02003 {
02004    struct dahdi_pvt *p = pvt;
02005    int index = analogsub_to_dahdisub(sub);
02006    if (index != SUB_REAL) {
02007       ast_log(LOG_ERROR, "We used a sub other than SUB_REAL (incorrect assumption sir)\n");
02008    }
02009    return dahdi_wink(p, index);
02010 }
02011 
02012 static void wakeup_sub(struct dahdi_pvt *p, int a);
02013 
02014 static int reset_conf(struct dahdi_pvt *p);
02015 
02016 static inline int dahdi_confmute(struct dahdi_pvt *p, int muted);
02017 
02018 static void my_handle_dtmf(void *pvt, struct ast_channel *ast, enum analog_sub analog_index, struct ast_frame **dest)
02019 {
02020    struct ast_frame *f = *dest;
02021    struct dahdi_pvt *p = pvt;
02022    int idx = analogsub_to_dahdisub(analog_index);
02023 
02024    ast_debug(1, "%s DTMF digit: 0x%02X '%c' on %s\n",
02025       f->frametype == AST_FRAME_DTMF_BEGIN ? "Begin" : "End",
02026       f->subclass.integer, f->subclass.integer, ast->name);
02027 
02028    if (f->subclass.integer == 'f') {
02029       if (f->frametype == AST_FRAME_DTMF_END) {
02030          /* Fax tone -- Handle and return NULL */
02031          if ((p->callprogress & CALLPROGRESS_FAX) && !p->faxhandled) {
02032             /* If faxbuffers are configured, use them for the fax transmission */
02033             if (p->usefaxbuffers && !p->bufferoverrideinuse) {
02034                struct dahdi_bufferinfo bi = {
02035                   .txbufpolicy = p->faxbuf_policy,
02036                   .bufsize = p->bufsize,
02037                   .numbufs = p->faxbuf_no
02038                };
02039                int res;
02040 
02041                if ((res = ioctl(p->subs[idx].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
02042                   ast_log(LOG_WARNING, "Channel '%s' unable to set buffer policy, reason: %s\n", ast->name, strerror(errno));
02043                } else {
02044                   p->bufferoverrideinuse = 1;
02045                }
02046             }
02047             p->faxhandled = 1;
02048             if (p->dsp) {
02049                p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
02050                ast_dsp_set_features(p->dsp, p->dsp_features);
02051                ast_debug(1, "Disabling FAX tone detection on %s after tone received\n", ast->name);
02052             }
02053             if (strcmp(ast->exten, "fax")) {
02054                const char *target_context = S_OR(ast->macrocontext, ast->context);
02055 
02056                /* We need to unlock 'ast' here because ast_exists_extension has the
02057                 * potential to start autoservice on the channel. Such action is prone
02058                 * to deadlock.
02059                 */
02060                ast_mutex_unlock(&p->lock);
02061                ast_channel_unlock(ast);
02062                if (ast_exists_extension(ast, target_context, "fax", 1,
02063                   S_COR(ast->caller.id.number.valid, ast->caller.id.number.str, NULL))) {
02064                   ast_channel_lock(ast);
02065                   ast_mutex_lock(&p->lock);
02066                   ast_verb(3, "Redirecting %s to fax extension\n", ast->name);
02067                   /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
02068                   pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten);
02069                   if (ast_async_goto(ast, target_context, "fax", 1))
02070                      ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context);
02071                } else {
02072                   ast_channel_lock(ast);
02073                   ast_mutex_lock(&p->lock);
02074                   ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
02075                }
02076             } else {
02077                ast_debug(1, "Already in a fax extension, not redirecting\n");
02078             }
02079          } else {
02080             ast_debug(1, "Fax already handled\n");
02081          }
02082          dahdi_confmute(p, 0);
02083       }
02084       p->subs[idx].f.frametype = AST_FRAME_NULL;
02085       p->subs[idx].f.subclass.integer = 0;
02086       *dest = &p->subs[idx].f;
02087    }
02088 }
02089 
02090 static void my_lock_private(void *pvt)
02091 {
02092    struct dahdi_pvt *p = pvt;
02093    ast_mutex_lock(&p->lock);
02094 }
02095 
02096 static void my_unlock_private(void *pvt)
02097 {
02098    struct dahdi_pvt *p = pvt;
02099    ast_mutex_unlock(&p->lock);
02100 }
02101 
02102 static void my_deadlock_avoidance_private(void *pvt)
02103 {
02104    struct dahdi_pvt *p = pvt;
02105 
02106    DEADLOCK_AVOIDANCE(&p->lock);
02107 }
02108 
02109 /*!
02110  * \internal
02111  * \brief Post an AMI DAHDI channel association event.
02112  * \since 1.8
02113  *
02114  * \param p DAHDI private pointer
02115  * \param chan Channel associated with the private pointer
02116  *
02117  * \return Nothing
02118  */
02119 static void dahdi_ami_channel_event(struct dahdi_pvt *p, struct ast_channel *chan)
02120 {
02121    char ch_name[20];
02122 
02123    if (p->channel < CHAN_PSEUDO) {
02124       /* No B channel */
02125       snprintf(ch_name, sizeof(ch_name), "no-media (%d)", p->channel);
02126    } else if (p->channel == CHAN_PSEUDO) {
02127       /* Pseudo channel */
02128       strcpy(ch_name, "pseudo");
02129    } else {
02130       /* Real channel */
02131       snprintf(ch_name, sizeof(ch_name), "%d", p->channel);
02132    }
02133    ast_manager_event(chan, EVENT_FLAG_CALL, "DAHDIChannel",
02134       "Channel: %s\r\n"
02135       "Uniqueid: %s\r\n"
02136       "DAHDISpan: %d\r\n"
02137       "DAHDIChannel: %s\r\n",
02138       chan->name,
02139       chan->uniqueid,
02140       p->span,
02141       ch_name);
02142 }
02143 
02144 #ifdef HAVE_PRI
02145 /*!
02146  * \internal
02147  * \brief Post an AMI DAHDI channel association event.
02148  * \since 1.8
02149  *
02150  * \param pvt DAHDI private pointer
02151  * \param chan Channel associated with the private pointer
02152  *
02153  * \return Nothing
02154  */
02155 static void my_ami_channel_event(void *pvt, struct ast_channel *chan)
02156 {
02157    struct dahdi_pvt *p = pvt;
02158 
02159    dahdi_ami_channel_event(p, chan);
02160 }
02161 #endif
02162 
02163 /* linear_mode = 0 - turn linear mode off, >0 - turn linear mode on
02164 *  returns the last value of the linear setting 
02165 */ 
02166 static int my_set_linear_mode(void *pvt, enum analog_sub sub, int linear_mode)
02167 {
02168    struct dahdi_pvt *p = pvt;
02169    int oldval;
02170    int idx = analogsub_to_dahdisub(sub);
02171    
02172    dahdi_setlinear(p->subs[idx].dfd, linear_mode);
02173    oldval = p->subs[idx].linear;
02174    p->subs[idx].linear = linear_mode ? 1 : 0;
02175    return oldval;
02176 }
02177 
02178 static void my_set_inthreeway(void *pvt, enum analog_sub sub, int inthreeway)
02179 {
02180    struct dahdi_pvt *p = pvt;
02181    int idx = analogsub_to_dahdisub(sub);
02182 
02183    p->subs[idx].inthreeway = inthreeway;
02184 }
02185 
02186 static int get_alarms(struct dahdi_pvt *p);
02187 static void handle_alarms(struct dahdi_pvt *p, int alms);
02188 static void my_get_and_handle_alarms(void *pvt)
02189 {
02190    int res;
02191    struct dahdi_pvt *p = pvt;
02192 
02193    res = get_alarms(p);
02194    handle_alarms(p, res);
02195 }
02196 
02197 static void *my_get_sigpvt_bridged_channel(struct ast_channel *chan)
02198 {
02199    struct dahdi_pvt *p = ast_bridged_channel(chan)->tech_pvt;
02200    if (p)
02201       return p->sig_pvt;
02202    else
02203       return NULL;
02204 }
02205 
02206 static int my_get_sub_fd(void *pvt, enum analog_sub sub)
02207 {
02208    struct dahdi_pvt *p = pvt;
02209    int dahdi_sub = analogsub_to_dahdisub(sub);
02210    return p->subs[dahdi_sub].dfd;
02211 }
02212 
02213 static void my_set_cadence(void *pvt, int *cid_rings, struct ast_channel *ast)
02214 {
02215    struct dahdi_pvt *p = pvt;
02216 
02217    /* Choose proper cadence */
02218    if ((p->distinctivering > 0) && (p->distinctivering <= num_cadence)) {
02219       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &cadences[p->distinctivering - 1]))
02220          ast_log(LOG_WARNING, "Unable to set distinctive ring cadence %d on '%s': %s\n", p->distinctivering, ast->name, strerror(errno));
02221       *cid_rings = cidrings[p->distinctivering - 1];
02222    } else {
02223       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, NULL))
02224          ast_log(LOG_WARNING, "Unable to reset default ring on '%s': %s\n", ast->name, strerror(errno));
02225       *cid_rings = p->sendcalleridafter;
02226    }
02227 }
02228 
02229 static void my_set_alarm(void *pvt, int in_alarm)
02230 {
02231    struct dahdi_pvt *p = pvt;
02232 
02233    p->inalarm = in_alarm;
02234 }
02235 
02236 static void my_set_dialing(void *pvt, int is_dialing)
02237 {
02238    struct dahdi_pvt *p = pvt;
02239 
02240    p->dialing = is_dialing;
02241 }
02242 
02243 static void my_set_outgoing(void *pvt, int is_outgoing)
02244 {
02245    struct dahdi_pvt *p = pvt;
02246 
02247    p->outgoing = is_outgoing;
02248 }
02249 
02250 #if defined(HAVE_PRI) || defined(HAVE_SS7)
02251 static void my_set_digital(void *pvt, int is_digital)
02252 {
02253    struct dahdi_pvt *p = pvt;
02254 
02255    p->digital = is_digital;
02256 }
02257 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
02258 
02259 #if defined(HAVE_SS7)
02260 static void my_set_inservice(void *pvt, int is_inservice)
02261 {
02262    struct dahdi_pvt *p = pvt;
02263 
02264    p->inservice = is_inservice;
02265 }
02266 #endif   /* defined(HAVE_SS7) */
02267 
02268 #if defined(HAVE_SS7)
02269 static void my_set_locallyblocked(void *pvt, int is_blocked)
02270 {
02271    struct dahdi_pvt *p = pvt;
02272 
02273    p->locallyblocked = is_blocked;
02274 }
02275 #endif   /* defined(HAVE_SS7) */
02276 
02277 #if defined(HAVE_SS7)
02278 static void my_set_remotelyblocked(void *pvt, int is_blocked)
02279 {
02280    struct dahdi_pvt *p = pvt;
02281 
02282    p->remotelyblocked = is_blocked;
02283 }
02284 #endif   /* defined(HAVE_SS7) */
02285 
02286 static void my_set_ringtimeout(void *pvt, int ringt)
02287 {
02288    struct dahdi_pvt *p = pvt;
02289    p->ringt = ringt;
02290 }
02291 
02292 static void my_set_waitingfordt(void *pvt, struct ast_channel *ast)
02293 {
02294    struct dahdi_pvt *p = pvt;
02295 
02296    if (p->waitfordialtone && CANPROGRESSDETECT(p) && p->dsp) {
02297       ast_log(LOG_DEBUG, "Defer dialing for %dms or dialtone\n", p->waitfordialtone);
02298       gettimeofday(&p->waitingfordt, NULL);
02299       ast_setstate(ast, AST_STATE_OFFHOOK);
02300    }
02301 }
02302 
02303 static int my_check_waitingfordt(void *pvt)
02304 {
02305    struct dahdi_pvt *p = pvt;
02306 
02307    if (p->waitingfordt.tv_usec) {
02308       return 1;
02309    }
02310 
02311    return 0;
02312 }
02313 
02314 static void my_set_confirmanswer(void *pvt, int flag)
02315 {
02316    struct dahdi_pvt *p = pvt;
02317    p->confirmanswer = flag;
02318 }
02319 
02320 static int my_check_confirmanswer(void *pvt)
02321 {
02322    struct dahdi_pvt *p = pvt;
02323    if (p->confirmanswer) {
02324       return 1;
02325    }
02326 
02327    return 0;
02328 }
02329 
02330 static void my_set_callwaiting(void *pvt, int callwaiting_enable)
02331 {
02332    struct dahdi_pvt *p = pvt;
02333 
02334    p->callwaiting = callwaiting_enable;
02335 }
02336 
02337 static void my_cancel_cidspill(void *pvt)
02338 {
02339    struct dahdi_pvt *p = pvt;
02340 
02341    ast_free(p->cidspill);
02342    p->cidspill = NULL;
02343    restore_conference(p);
02344 }
02345 
02346 static int my_confmute(void *pvt, int mute)
02347 {
02348    struct dahdi_pvt *p = pvt;
02349    return dahdi_confmute(p, mute);
02350 }
02351 
02352 static void my_set_pulsedial(void *pvt, int flag)
02353 {
02354    struct dahdi_pvt *p = pvt;
02355    p->pulsedial = flag;
02356 }
02357 
02358 static void my_set_new_owner(void *pvt, struct ast_channel *new_owner)
02359 {
02360    struct dahdi_pvt *p = pvt;
02361 
02362    p->owner = new_owner;
02363 }
02364 
02365 static const char *my_get_orig_dialstring(void *pvt)
02366 {
02367    struct dahdi_pvt *p = pvt;
02368 
02369    return p->dialstring;
02370 }
02371 
02372 static void my_increase_ss_count(void)
02373 {
02374    ast_mutex_lock(&ss_thread_lock);
02375    ss_thread_count++;
02376    ast_mutex_unlock(&ss_thread_lock);
02377 }
02378 
02379 static void my_decrease_ss_count(void)
02380 {
02381    ast_mutex_lock(&ss_thread_lock);
02382    ss_thread_count--;
02383    ast_cond_signal(&ss_thread_complete);
02384    ast_mutex_unlock(&ss_thread_lock);
02385 }
02386 
02387 static void my_all_subchannels_hungup(void *pvt)
02388 {
02389    struct dahdi_pvt *p = pvt;
02390    int res, law;
02391 
02392    p->faxhandled = 0;
02393    p->didtdd = 0;
02394 
02395    if (p->dsp) {
02396       ast_dsp_free(p->dsp);
02397       p->dsp = NULL;
02398    }
02399 
02400    p->law = p->law_default;
02401    law = p->law_default;
02402    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
02403    if (res < 0)
02404       ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
02405 
02406    dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
02407 
02408 #if 1
02409    {
02410    int i;
02411    p->owner = NULL;
02412    /* Cleanup owners here */
02413    for (i = 0; i < 3; i++) {
02414       p->subs[i].owner = NULL;
02415    }
02416    }
02417 #endif
02418 
02419    reset_conf(p);
02420    if (num_restart_pending == 0) {
02421       restart_monitor();
02422    }
02423 }
02424 
02425 static int conf_del(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index);
02426 
02427 static int my_conf_del(void *pvt, enum analog_sub sub)
02428 {
02429    struct dahdi_pvt *p = pvt;
02430    int x = analogsub_to_dahdisub(sub);
02431 
02432    return conf_del(p, &p->subs[x], x);
02433 }
02434 
02435 static int conf_add(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index, int slavechannel);
02436 
02437 static int my_conf_add(void *pvt, enum analog_sub sub)
02438 {
02439    struct dahdi_pvt *p = pvt;
02440    int x = analogsub_to_dahdisub(sub);
02441 
02442    return conf_add(p, &p->subs[x], x, 0);
02443 }
02444 
02445 static int isslavenative(struct dahdi_pvt *p, struct dahdi_pvt **out);
02446 
02447 static int my_complete_conference_update(void *pvt, int needconference)
02448 {
02449    struct dahdi_pvt *p = pvt;
02450    int needconf = needconference;
02451    int x;
02452    int useslavenative;
02453    struct dahdi_pvt *slave = NULL;
02454 
02455    useslavenative = isslavenative(p, &slave);
02456 
02457    /* If we have a slave, add him to our conference now. or DAX
02458       if this is slave native */
02459    for (x = 0; x < MAX_SLAVES; x++) {
02460       if (p->slaves[x]) {
02461          if (useslavenative)
02462             conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
02463          else {
02464             conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
02465             needconf++;
02466          }
02467       }
02468    }
02469    /* If we're supposed to be in there, do so now */
02470    if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
02471       if (useslavenative)
02472          conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
02473       else {
02474          conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
02475          needconf++;
02476       }
02477    }
02478    /* If we have a master, add ourselves to his conference */
02479    if (p->master) {
02480       if (isslavenative(p->master, NULL)) {
02481          conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
02482       } else {
02483          conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
02484       }
02485    }
02486    if (!needconf) {
02487       /* Nobody is left (or should be left) in our conference.
02488          Kill it. */
02489       p->confno = -1;
02490    }
02491 
02492    return 0;
02493 }
02494 
02495 static int check_for_conference(struct dahdi_pvt *p);
02496 
02497 static int my_check_for_conference(void *pvt)
02498 {
02499    struct dahdi_pvt *p = pvt;
02500    return check_for_conference(p);
02501 }
02502 
02503 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)
02504 {
02505    struct dahdi_pvt *p = pvt;
02506    int da, db;
02507    int tchan;
02508    int tinthreeway;
02509 
02510    da = analogsub_to_dahdisub(a);
02511    db = analogsub_to_dahdisub(b);
02512 
02513    tchan = p->subs[da].chan;
02514    p->subs[da].chan = p->subs[db].chan;
02515    p->subs[db].chan = tchan;
02516 
02517    tinthreeway = p->subs[da].inthreeway;
02518    p->subs[da].inthreeway = p->subs[db].inthreeway;
02519    p->subs[db].inthreeway = tinthreeway;
02520 
02521    p->subs[da].owner = ast_a;
02522    p->subs[db].owner = ast_b;
02523 
02524    if (ast_a)
02525       ast_channel_set_fd(ast_a, 0, p->subs[da].dfd);
02526    if (ast_b)
02527       ast_channel_set_fd(ast_b, 0, p->subs[db].dfd);
02528 
02529    wakeup_sub(p, a);
02530    wakeup_sub(p, b);
02531 
02532    return;
02533 }
02534 
02535 static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpbx, int idx, int law, const char *linkedid);
02536 
02537 static struct ast_channel *my_new_analog_ast_channel(void *pvt, int state, int startpbx, enum analog_sub sub, const struct ast_channel *requestor)
02538 {
02539    struct dahdi_pvt *p = pvt;
02540    int dsub = analogsub_to_dahdisub(sub);
02541 
02542    return dahdi_new(p, state, startpbx, dsub, 0, requestor ? requestor->linkedid : "");
02543 }
02544 
02545 #if defined(HAVE_PRI) || defined(HAVE_SS7)
02546 static int dahdi_setlaw(int dfd, int law)
02547 {
02548    int res;
02549    res = ioctl(dfd, DAHDI_SETLAW, &law);
02550    if (res)
02551       return res;
02552    return 0;
02553 }
02554 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
02555 
02556 #if defined(HAVE_PRI)
02557 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)
02558 {
02559    struct dahdi_pvt *p = pvt;
02560    int audio;
02561    int newlaw = -1;
02562 
02563    switch (p->sig) {
02564    case SIG_PRI_LIB_HANDLE_CASES:
02565       if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
02566          /* PRI nobch pseudo channel.  Does not handle ioctl(DAHDI_AUDIOMODE) */
02567          break;
02568       }
02569       /* Fall through */
02570    default:
02571       /* Set to audio mode at this point */
02572       audio = 1;
02573       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &audio) == -1) {
02574          ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n",
02575             p->channel, audio, strerror(errno));
02576       }
02577       break;
02578    }
02579 
02580    if (law != SIG_PRI_DEFLAW) {
02581       dahdi_setlaw(p->subs[SUB_REAL].dfd, (law == SIG_PRI_ULAW) ? DAHDI_LAW_MULAW : DAHDI_LAW_ALAW);
02582    }
02583 
02584    ast_copy_string(p->exten, exten, sizeof(p->exten));
02585 
02586    switch (law) {
02587       case SIG_PRI_DEFLAW:
02588          newlaw = 0;
02589          break;
02590       case SIG_PRI_ALAW:
02591          newlaw = DAHDI_LAW_ALAW;
02592          break;
02593       case SIG_PRI_ULAW:
02594          newlaw = DAHDI_LAW_MULAW;
02595          break;
02596    }
02597    return dahdi_new(p, state, 0, SUB_REAL, newlaw, requestor ? requestor->linkedid : "");
02598 }
02599 #endif   /* defined(HAVE_PRI) */
02600 
02601 static int set_actual_gain(int fd, float rxgain, float txgain, float rxdrc, float txdrc, int law);
02602 
02603 #if defined(HAVE_PRI) || defined(HAVE_SS7)
02604 /*!
02605  * \internal
02606  * \brief Open the PRI/SS7 channel media path.
02607  * \since 1.8
02608  *
02609  * \param p Channel private control structure.
02610  *
02611  * \return Nothing
02612  */
02613 static void my_pri_ss7_open_media(void *p)
02614 {
02615    struct dahdi_pvt *pvt = p;
02616    int res;
02617    int dfd;
02618    int set_val;
02619 
02620    dfd = pvt->subs[SUB_REAL].dfd;
02621 
02622    /* Open the media path. */
02623    set_val = 1;
02624    res = ioctl(dfd, DAHDI_AUDIOMODE, &set_val);
02625    if (res < 0) {
02626       ast_log(LOG_WARNING, "Unable to enable audio mode on channel %d (%s)\n",
02627          pvt->channel, strerror(errno));
02628    }
02629 
02630    /* Set correct companding law for this call. */
02631    res = dahdi_setlaw(dfd, pvt->law);
02632    if (res < 0) {
02633       ast_log(LOG_WARNING, "Unable to set law on channel %d\n", pvt->channel);
02634    }
02635 
02636    /* Set correct gain for this call. */
02637    if (pvt->digital) {
02638       res = set_actual_gain(dfd, 0, 0, pvt->rxdrc, pvt->txdrc, pvt->law);
02639    } else {
02640       res = set_actual_gain(dfd, pvt->rxgain, pvt->txgain, pvt->rxdrc, pvt->txdrc,
02641          pvt->law);
02642    }
02643    if (res < 0) {
02644       ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", pvt->channel);
02645    }
02646 
02647    if (pvt->dsp_features && pvt->dsp) {
02648       ast_dsp_set_features(pvt->dsp, pvt->dsp_features);
02649       pvt->dsp_features = 0;
02650    }
02651 }
02652 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
02653 
02654 #if defined(HAVE_PRI)
02655 /*!
02656  * \internal
02657  * \brief Ask DAHDI to dial the given dial string.
02658  * \since 1.8.11
02659  *
02660  * \param p Channel private control structure.
02661  * \param dial_string String to pass to DAHDI to dial.
02662  *
02663  * \note The channel private lock needs to be held when calling.
02664  *
02665  * \return Nothing
02666  */
02667 static void my_pri_dial_digits(void *p, const char *dial_string)
02668 {
02669    struct dahdi_dialoperation zo = {
02670       .op = DAHDI_DIAL_OP_APPEND,
02671    };
02672    struct dahdi_pvt *pvt = p;
02673    int res;
02674 
02675    snprintf(zo.dialstr, sizeof(zo.dialstr), "T%s", dial_string);
02676    ast_debug(1, "Channel %d: Sending '%s' to DAHDI_DIAL.\n", pvt->channel, zo.dialstr);
02677    res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo);
02678    if (res) {
02679       ast_log(LOG_WARNING, "Channel %d: Couldn't dial '%s': %s\n",
02680          pvt->channel, dial_string, strerror(errno));
02681    } else {
02682       pvt->dialing = 1;
02683    }
02684 }
02685 #endif   /* defined(HAVE_PRI) */
02686 
02687 static int unalloc_sub(struct dahdi_pvt *p, int x);
02688 
02689 static int my_unallocate_sub(void *pvt, enum analog_sub analogsub)
02690 {
02691    struct dahdi_pvt *p = pvt;
02692 
02693    return unalloc_sub(p, analogsub_to_dahdisub(analogsub));
02694 }
02695 
02696 static int alloc_sub(struct dahdi_pvt *p, int x);
02697 
02698 static int my_allocate_sub(void *pvt, enum analog_sub analogsub)
02699 {
02700    struct dahdi_pvt *p = pvt;
02701 
02702    return alloc_sub(p, analogsub_to_dahdisub(analogsub));
02703 }
02704 
02705 static int has_voicemail(struct dahdi_pvt *p);
02706 
02707 static int my_has_voicemail(void *pvt)
02708 {
02709    struct dahdi_pvt *p = pvt;
02710 
02711    return has_voicemail(p);
02712 }
02713 
02714 static int my_play_tone(void *pvt, enum analog_sub sub, enum analog_tone tone)
02715 {
02716    struct dahdi_pvt *p = pvt;
02717    int index;
02718 
02719    index = analogsub_to_dahdisub(sub);
02720 
02721    return tone_zone_play_tone(p->subs[index].dfd, analog_tone_to_dahditone(tone));
02722 }
02723 
02724 static enum analog_event dahdievent_to_analogevent(int event)
02725 {
02726    enum analog_event res;
02727 
02728    switch (event) {
02729    case DAHDI_EVENT_ONHOOK:
02730       res = ANALOG_EVENT_ONHOOK;
02731       break;
02732    case DAHDI_EVENT_RINGOFFHOOK:
02733       res = ANALOG_EVENT_RINGOFFHOOK;
02734       break;
02735    case DAHDI_EVENT_WINKFLASH:
02736       res = ANALOG_EVENT_WINKFLASH;
02737       break;
02738    case DAHDI_EVENT_ALARM:
02739       res = ANALOG_EVENT_ALARM;
02740       break;
02741    case DAHDI_EVENT_NOALARM:
02742       res = ANALOG_EVENT_NOALARM;
02743       break;
02744    case DAHDI_EVENT_DIALCOMPLETE:
02745       res = ANALOG_EVENT_DIALCOMPLETE;
02746       break;
02747    case DAHDI_EVENT_RINGERON:
02748       res = ANALOG_EVENT_RINGERON;
02749       break;
02750    case DAHDI_EVENT_RINGEROFF:
02751       res = ANALOG_EVENT_RINGEROFF;
02752       break;
02753    case DAHDI_EVENT_HOOKCOMPLETE:
02754       res = ANALOG_EVENT_HOOKCOMPLETE;
02755       break;
02756    case DAHDI_EVENT_PULSE_START:
02757       res = ANALOG_EVENT_PULSE_START;
02758       break;
02759    case DAHDI_EVENT_POLARITY:
02760       res = ANALOG_EVENT_POLARITY;
02761       break;
02762    case DAHDI_EVENT_RINGBEGIN:
02763       res = ANALOG_EVENT_RINGBEGIN;
02764       break;
02765    case DAHDI_EVENT_EC_DISABLED:
02766       res = ANALOG_EVENT_EC_DISABLED;
02767       break;
02768    case DAHDI_EVENT_REMOVED:
02769       res = ANALOG_EVENT_REMOVED;
02770       break;
02771    case DAHDI_EVENT_NEONMWI_ACTIVE:
02772       res = ANALOG_EVENT_NEONMWI_ACTIVE;
02773       break;
02774    case DAHDI_EVENT_NEONMWI_INACTIVE:
02775       res = ANALOG_EVENT_NEONMWI_INACTIVE;
02776       break;
02777 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
02778    case DAHDI_EVENT_TX_CED_DETECTED:
02779       res = ANALOG_EVENT_TX_CED_DETECTED;
02780       break;
02781    case DAHDI_EVENT_RX_CED_DETECTED:
02782       res = ANALOG_EVENT_RX_CED_DETECTED;
02783       break;
02784    case DAHDI_EVENT_EC_NLP_DISABLED:
02785       res = ANALOG_EVENT_EC_NLP_DISABLED;
02786       break;
02787    case DAHDI_EVENT_EC_NLP_ENABLED:
02788       res = ANALOG_EVENT_EC_NLP_ENABLED;
02789       break;
02790 #endif
02791    case DAHDI_EVENT_PULSEDIGIT:
02792       res = ANALOG_EVENT_PULSEDIGIT;
02793       break;
02794    case DAHDI_EVENT_DTMFDOWN:
02795       res = ANALOG_EVENT_DTMFDOWN;
02796       break;
02797    case DAHDI_EVENT_DTMFUP:
02798       res = ANALOG_EVENT_DTMFUP;
02799       break;
02800    default:
02801       switch(event & 0xFFFF0000) {
02802       case DAHDI_EVENT_PULSEDIGIT:
02803       case DAHDI_EVENT_DTMFDOWN:
02804       case DAHDI_EVENT_DTMFUP:
02805          /* The event includes a digit number in the low word.
02806           * Converting it to a 'enum analog_event' would remove
02807           * that information. Thus it is returned as-is.
02808           */
02809          return event;
02810       }
02811 
02812       res = ANALOG_EVENT_ERROR;
02813       break;
02814    }
02815 
02816    return res;
02817 }
02818 
02819 static inline int dahdi_wait_event(int fd);
02820 
02821 static int my_wait_event(void *pvt)
02822 {
02823    struct dahdi_pvt *p = pvt;
02824 
02825    return dahdi_wait_event(p->subs[SUB_REAL].dfd);
02826 }
02827 
02828 static int my_get_event(void *pvt)
02829 {
02830    struct dahdi_pvt *p = pvt;
02831    int res;
02832 
02833    if (p->fake_event) {
02834       res = p->fake_event;
02835       p->fake_event = 0;
02836    } else
02837       res = dahdi_get_event(p->subs[SUB_REAL].dfd);
02838 
02839    return dahdievent_to_analogevent(res);
02840 }
02841 
02842 static int my_is_off_hook(void *pvt)
02843 {
02844    struct dahdi_pvt *p = pvt;
02845    int res;
02846    struct dahdi_params par;
02847 
02848    memset(&par, 0, sizeof(par));
02849 
02850    if (p->subs[SUB_REAL].dfd > -1)
02851       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
02852    else {
02853       /* Assume not off hook on CVRS */
02854       res = 0;
02855       par.rxisoffhook = 0;
02856    }
02857    if (res) {
02858       ast_log(LOG_WARNING, "Unable to check hook state on channel %d: %s\n", p->channel, strerror(errno));
02859    }
02860 
02861    if ((p->sig == SIG_FXSKS) || (p->sig == SIG_FXSGS)) {
02862       /* When "onhook" that means no battery on the line, and thus
02863       it is out of service..., if it's on a TDM card... If it's a channel
02864       bank, there is no telling... */
02865       return (par.rxbits > -1) || par.rxisoffhook;
02866    }
02867 
02868    return par.rxisoffhook;
02869 }
02870 
02871 static void dahdi_enable_ec(struct dahdi_pvt *p);
02872 static void dahdi_disable_ec(struct dahdi_pvt *p);
02873 
02874 static int my_set_echocanceller(void *pvt, int enable)
02875 {
02876    struct dahdi_pvt *p = pvt;
02877 
02878    if (enable)
02879       dahdi_enable_ec(p);
02880    else
02881       dahdi_disable_ec(p);
02882 
02883    return 0;
02884 }
02885 
02886 static int dahdi_ring_phone(struct dahdi_pvt *p);
02887 
02888 static int my_ring(void *pvt)
02889 {
02890    struct dahdi_pvt *p = pvt;
02891 
02892    return dahdi_ring_phone(p);
02893 }
02894 
02895 static int my_flash(void *pvt)
02896 {
02897    struct dahdi_pvt *p = pvt;
02898    int func = DAHDI_FLASH;
02899    return ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &func);
02900 }
02901 
02902 static inline int dahdi_set_hook(int fd, int hs);
02903 
02904 static int my_off_hook(void *pvt)
02905 {
02906    struct dahdi_pvt *p = pvt;
02907    return dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
02908 }
02909 
02910 static void my_set_needringing(void *pvt, int value)
02911 {
02912    struct dahdi_pvt *p = pvt;
02913    p->subs[SUB_REAL].needringing = value;
02914 }
02915 
02916 static void my_set_polarity(void *pvt, int value)
02917 {
02918    struct dahdi_pvt *p = pvt;
02919 
02920    if (p->channel == CHAN_PSEUDO) {
02921       return;
02922    }
02923    p->polarity = value;
02924    ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETPOLARITY, &value);
02925 }
02926 
02927 static void my_start_polarityswitch(void *pvt)
02928 {
02929    struct dahdi_pvt *p = pvt;
02930 
02931    if (p->answeronpolarityswitch || p->hanguponpolarityswitch) {
02932       my_set_polarity(pvt, 0);
02933    }
02934 }
02935 
02936 static void my_answer_polarityswitch(void *pvt)
02937 {
02938    struct dahdi_pvt *p = pvt;
02939 
02940    if (!p->answeronpolarityswitch) {
02941       return;
02942    }
02943 
02944    my_set_polarity(pvt, 1);
02945 }
02946 
02947 static void my_hangup_polarityswitch(void *pvt)
02948 {
02949    struct dahdi_pvt *p = pvt;
02950 
02951    if (!p->hanguponpolarityswitch) {
02952       return;
02953    }
02954 
02955    if (p->answeronpolarityswitch) {
02956       my_set_polarity(pvt, 0);
02957    } else {
02958       my_set_polarity(pvt, 1);
02959    }
02960 }
02961 
02962 static int my_start(void *pvt)
02963 {
02964    struct dahdi_pvt *p = pvt;
02965    int x = DAHDI_START;
02966 
02967    return ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
02968 }
02969 
02970 static int my_dial_digits(void *pvt, enum analog_sub sub, struct analog_dialoperation *dop)
02971 {
02972    int index = analogsub_to_dahdisub(sub);
02973    int res;
02974    struct dahdi_pvt *p = pvt;
02975    struct dahdi_dialoperation ddop;
02976 
02977    if (dop->op != ANALOG_DIAL_OP_REPLACE) {
02978       ast_log(LOG_ERROR, "Fix the dial_digits callback!\n");
02979       return -1;
02980    }
02981 
02982    if (sub != ANALOG_SUB_REAL) {
02983       ast_log(LOG_ERROR, "Trying to dial_digits '%s' on channel %d subchannel %d\n",
02984          dop->dialstr, p->channel, sub);
02985       return -1;
02986    }
02987 
02988    ddop.op = DAHDI_DIAL_OP_REPLACE;
02989    ast_copy_string(ddop.dialstr, dop->dialstr, sizeof(ddop.dialstr));
02990 
02991    ast_debug(1, "Channel %d: Sending '%s' to DAHDI_DIAL.\n", p->channel, ddop.dialstr);
02992 
02993    res = ioctl(p->subs[index].dfd, DAHDI_DIAL, &ddop);
02994    if (res == -1) {
02995       ast_debug(1, "DAHDI_DIAL ioctl failed on %s: %s\n", p->owner->name, strerror(errno));
02996    }
02997 
02998    return res;
02999 }
03000 
03001 static void dahdi_train_ec(struct dahdi_pvt *p);
03002 
03003 static int my_train_echocanceller(void *pvt)
03004 {
03005    struct dahdi_pvt *p = pvt;
03006 
03007    dahdi_train_ec(p);
03008 
03009    return 0;
03010 }
03011 
03012 static int my_is_dialing(void *pvt, enum analog_sub sub)
03013 {
03014    struct dahdi_pvt *p = pvt;
03015    int index;
03016    int x;
03017 
03018    index = analogsub_to_dahdisub(sub);
03019 
03020    if (ioctl(p->subs[index].dfd, DAHDI_DIALING, &x)) {
03021       ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed!\n");
03022       return -1;
03023    }
03024 
03025    return x;
03026 }
03027 
03028 static int my_on_hook(void *pvt)
03029 {
03030    struct dahdi_pvt *p = pvt;
03031    return dahdi_set_hook(p->subs[ANALOG_SUB_REAL].dfd, DAHDI_ONHOOK);
03032 }
03033 
03034 #if defined(HAVE_PRI)
03035 static void my_pri_fixup_chans(void *chan_old, void *chan_new)
03036 {
03037    struct dahdi_pvt *old_chan = chan_old;
03038    struct dahdi_pvt *new_chan = chan_new;
03039 
03040    new_chan->owner = old_chan->owner;
03041    old_chan->owner = NULL;
03042    if (new_chan->owner) {
03043       new_chan->owner->tech_pvt = new_chan;
03044       new_chan->owner->fds[0] = new_chan->subs[SUB_REAL].dfd;
03045       new_chan->subs[SUB_REAL].owner = old_chan->subs[SUB_REAL].owner;
03046       old_chan->subs[SUB_REAL].owner = NULL;
03047    }
03048    /* Copy any DSP that may be present */
03049    new_chan->dsp = old_chan->dsp;
03050    new_chan->dsp_features = old_chan->dsp_features;
03051    old_chan->dsp = NULL;
03052    old_chan->dsp_features = 0;
03053 
03054    /* Transfer flags from the old channel. */
03055    new_chan->dialing = old_chan->dialing;
03056    new_chan->digital = old_chan->digital;
03057    new_chan->outgoing = old_chan->outgoing;
03058    old_chan->dialing = 0;
03059    old_chan->digital = 0;
03060    old_chan->outgoing = 0;
03061 
03062    /* More stuff to transfer to the new channel. */
03063    new_chan->law = old_chan->law;
03064    strcpy(new_chan->dialstring, old_chan->dialstring);
03065 }
03066 #endif   /* defined(HAVE_PRI) */
03067 
03068 #if defined(HAVE_PRI)
03069 static int sig_pri_tone_to_dahditone(enum sig_pri_tone tone)
03070 {
03071    switch (tone) {
03072    case SIG_PRI_TONE_RINGTONE:
03073       return DAHDI_TONE_RINGTONE;
03074    case SIG_PRI_TONE_STUTTER:
03075       return DAHDI_TONE_STUTTER;
03076    case SIG_PRI_TONE_CONGESTION:
03077       return DAHDI_TONE_CONGESTION;
03078    case SIG_PRI_TONE_DIALTONE:
03079       return DAHDI_TONE_DIALTONE;
03080    case SIG_PRI_TONE_DIALRECALL:
03081       return DAHDI_TONE_DIALRECALL;
03082    case SIG_PRI_TONE_INFO:
03083       return DAHDI_TONE_INFO;
03084    case SIG_PRI_TONE_BUSY:
03085       return DAHDI_TONE_BUSY;
03086    default:
03087       return -1;
03088    }
03089 }
03090 #endif   /* defined(HAVE_PRI) */
03091 
03092 #if defined(HAVE_PRI)
03093 static void my_handle_dchan_exception(struct sig_pri_span *pri, int index)
03094 {
03095    int x;
03096 
03097    ioctl(pri->fds[index], DAHDI_GETEVENT, &x);
03098    if (x) {
03099       ast_log(LOG_NOTICE, "PRI got event: %s (%d) on D-channel of span %d\n", event2str(x), x, pri->span);
03100    }
03101    /* Keep track of alarm state */
03102    switch (x) {
03103    case DAHDI_EVENT_ALARM:
03104       pri_event_alarm(pri, index, 0);
03105       break;
03106    case DAHDI_EVENT_NOALARM:
03107       pri_event_noalarm(pri, index, 0);
03108       break;
03109    default:
03110       break;
03111    }
03112 }
03113 #endif   /* defined(HAVE_PRI) */
03114 
03115 #if defined(HAVE_PRI)
03116 static int my_pri_play_tone(void *pvt, enum sig_pri_tone tone)
03117 {
03118    struct dahdi_pvt *p = pvt;
03119 
03120    return tone_zone_play_tone(p->subs[SUB_REAL].dfd, sig_pri_tone_to_dahditone(tone));
03121 }
03122 #endif   /* defined(HAVE_PRI) */
03123 
03124 #if defined(HAVE_PRI) || defined(HAVE_SS7)
03125 /*!
03126  * \internal
03127  * \brief Set the caller id information.
03128  * \since 1.8
03129  *
03130  * \param pvt DAHDI private structure
03131  * \param caller Caller-id information to set.
03132  *
03133  * \return Nothing
03134  */
03135 static void my_set_callerid(void *pvt, const struct ast_party_caller *caller)
03136 {
03137    struct dahdi_pvt *p = pvt;
03138 
03139    ast_copy_string(p->cid_num,
03140       S_COR(caller->id.number.valid, caller->id.number.str, ""),
03141       sizeof(p->cid_num));
03142    ast_copy_string(p->cid_name,
03143       S_COR(caller->id.name.valid, caller->id.name.str, ""),
03144       sizeof(p->cid_name));
03145    ast_copy_string(p->cid_subaddr,
03146       S_COR(caller->id.subaddress.valid, caller->id.subaddress.str, ""),
03147       sizeof(p->cid_subaddr));
03148    p->cid_ton = caller->id.number.plan;
03149    p->callingpres = ast_party_id_presentation(&caller->id);
03150    if (caller->id.tag) {
03151       ast_copy_string(p->cid_tag, caller->id.tag, sizeof(p->cid_tag));
03152    }
03153    ast_copy_string(p->cid_ani,
03154       S_COR(caller->ani.number.valid, caller->ani.number.str, ""),
03155       sizeof(p->cid_ani));
03156    p->cid_ani2 = caller->ani2;
03157 }
03158 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
03159 
03160 #if defined(HAVE_PRI) || defined(HAVE_SS7)
03161 /*!
03162  * \internal
03163  * \brief Set the Dialed Number Identifier.
03164  * \since 1.8
03165  *
03166  * \param pvt DAHDI private structure
03167  * \param dnid Dialed Number Identifier string.
03168  *
03169  * \return Nothing
03170  */
03171 static void my_set_dnid(void *pvt, const char *dnid)
03172 {
03173    struct dahdi_pvt *p = pvt;
03174 
03175    ast_copy_string(p->dnid, dnid, sizeof(p->dnid));
03176 }
03177 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
03178 
03179 #if defined(HAVE_PRI)
03180 /*!
03181  * \internal
03182  * \brief Set the Redirecting Directory Number Information Service (RDNIS).
03183  * \since 1.8
03184  *
03185  * \param pvt DAHDI private structure
03186  * \param rdnis Redirecting Directory Number Information Service (RDNIS) string.
03187  *
03188  * \return Nothing
03189  */
03190 static void my_set_rdnis(void *pvt, const char *rdnis)
03191 {
03192    struct dahdi_pvt *p = pvt;
03193 
03194    ast_copy_string(p->rdnis, rdnis, sizeof(p->rdnis));
03195 }
03196 #endif   /* defined(HAVE_PRI) */
03197 
03198 #if defined(HAVE_PRI)
03199 /*!
03200  * \internal
03201  * \brief Make a dialstring for native ISDN CC to recall properly.
03202  * \since 1.8
03203  *
03204  * \param priv Channel private control structure.
03205  * \param buf Where to put the modified dialstring.
03206  * \param buf_size Size of modified dialstring buffer.
03207  *
03208  * \details
03209  * original dialstring:
03210  * DAHDI/[i<span>-](g|G|r|R)<group#(0-63)>[c|r<cadance#>|d][/extension[/options]]
03211  *
03212  * The modified dialstring will have prefixed the channel-group section
03213  * with the ISDN channel restriction.
03214  *
03215  * buf:
03216  * DAHDI/i<span>-(g|G|r|R)<group#(0-63)>[c|r<cadance#>|d][/extension[/options]]
03217  *
03218  * The routine will check to see if the ISDN channel restriction is already
03219  * in the original dialstring.
03220  *
03221  * \return Nothing
03222  */
03223 static void my_pri_make_cc_dialstring(void *priv, char *buf, size_t buf_size)
03224 {
03225    char *dial;
03226    struct dahdi_pvt *pvt;
03227    AST_DECLARE_APP_ARGS(args,
03228       AST_APP_ARG(tech);   /* channel technology token */
03229       AST_APP_ARG(group);  /* channel/group token */
03230       //AST_APP_ARG(ext);  /* extension token */
03231       //AST_APP_ARG(opts); /* options token */
03232       //AST_APP_ARG(other);   /* Any remining unused arguments */
03233    );
03234 
03235    pvt = priv;
03236    dial = ast_strdupa(pvt->dialstring);
03237    AST_NONSTANDARD_APP_ARGS(args, dial, '/');
03238    if (!args.tech) {
03239       ast_copy_string(buf, pvt->dialstring, buf_size);
03240       return;
03241    }
03242    if (!args.group) {
03243       /* Append the ISDN span channel restriction to the dialstring. */
03244       snprintf(buf, buf_size, "%s/i%d-", args.tech, pvt->pri->span);
03245       return;
03246    }
03247    if (isdigit(args.group[0]) || args.group[0] == 'i' || strchr(args.group, '!')) {
03248       /* The ISDN span channel restriction is not needed or already
03249        * in the dialstring. */
03250       ast_copy_string(buf, pvt->dialstring, buf_size);
03251       return;
03252    }
03253    /* Insert the ISDN span channel restriction into the dialstring. */
03254    snprintf(buf, buf_size, "%s/i%d-%s", args.tech, pvt->pri->span, args.group);
03255 }
03256 #endif   /* defined(HAVE_PRI) */
03257 
03258 #if defined(HAVE_PRI)
03259 /*!
03260  * \internal
03261  * \brief Reevaluate the PRI span device state.
03262  * \since 1.8
03263  *
03264  * \param pri Asterisk D channel control structure.
03265  *
03266  * \return Nothing
03267  *
03268  * \note Assumes the pri->lock is already obtained.
03269  */
03270 static void dahdi_pri_update_span_devstate(struct sig_pri_span *pri)
03271 {
03272    unsigned idx;
03273    unsigned num_b_chans;   /* Number of B channels provisioned on the span. */
03274    unsigned in_use;     /* Number of B channels in use on the span. */
03275    unsigned in_alarm;      /* TRUE if the span is in alarm condition. */
03276    enum ast_device_state new_state;
03277 
03278    /* Count the number of B channels and the number of B channels in use. */
03279    num_b_chans = 0;
03280    in_use = 0;
03281    in_alarm = 1;
03282    for (idx = pri->numchans; idx--;) {
03283       if (pri->pvts[idx] && !pri->pvts[idx]->no_b_channel) {
03284          /* This is a B channel interface. */
03285          ++num_b_chans;
03286          if (!sig_pri_is_chan_available(pri->pvts[idx])) {
03287             ++in_use;
03288          }
03289          if (!pri->pvts[idx]->inalarm) {
03290             /* There is a channel that is not in alarm. */
03291             in_alarm = 0;
03292          }
03293       }
03294    }
03295 
03296    /* Update the span congestion device state and report any change. */
03297    if (in_alarm) {
03298       new_state = AST_DEVICE_UNAVAILABLE;
03299    } else {
03300       new_state = num_b_chans == in_use ? AST_DEVICE_BUSY : AST_DEVICE_NOT_INUSE;
03301    }
03302    if (pri->congestion_devstate != new_state) {
03303       pri->congestion_devstate = new_state;
03304       ast_devstate_changed(AST_DEVICE_UNKNOWN, "DAHDI/I%d/congestion", pri->span);
03305    }
03306 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
03307    /* Update the span threshold device state and report any change. */
03308    if (in_alarm) {
03309       new_state = AST_DEVICE_UNAVAILABLE;
03310    } else if (!in_use) {
03311       new_state = AST_DEVICE_NOT_INUSE;
03312    } else if (!pri->user_busy_threshold) {
03313       new_state = in_use < num_b_chans ? AST_DEVICE_INUSE : AST_DEVICE_BUSY;
03314    } else {
03315       new_state = in_use < pri->user_busy_threshold ? AST_DEVICE_INUSE
03316          : AST_DEVICE_BUSY;
03317    }
03318    if (pri->threshold_devstate != new_state) {
03319       pri->threshold_devstate = new_state;
03320       ast_devstate_changed(AST_DEVICE_UNKNOWN, "DAHDI/I%d/threshold", pri->span);
03321    }
03322 #endif   /* defined(THRESHOLD_DEVSTATE_PLACEHOLDER) */
03323 }
03324 #endif   /* defined(HAVE_PRI) */
03325 
03326 #if defined(HAVE_PRI)
03327 /*!
03328  * \internal
03329  * \brief Reference this module.
03330  * \since 1.8
03331  *
03332  * \return Nothing
03333  */
03334 static void my_module_ref(void)
03335 {
03336    ast_module_ref(ast_module_info->self);
03337 }
03338 #endif   /* defined(HAVE_PRI) */
03339 
03340 #if defined(HAVE_PRI)
03341 /*!
03342  * \internal
03343  * \brief Unreference this module.
03344  * \since 1.8
03345  *
03346  * \return Nothing
03347  */
03348 static void my_module_unref(void)
03349 {
03350    ast_module_unref(ast_module_info->self);
03351 }
03352 #endif   /* defined(HAVE_PRI) */
03353 
03354 #if defined(HAVE_PRI)
03355 #if defined(HAVE_PRI_CALL_WAITING)
03356 static void my_pri_init_config(void *priv, struct sig_pri_span *pri);
03357 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
03358 static int dahdi_new_pri_nobch_channel(struct sig_pri_span *pri);
03359 
03360 static struct sig_pri_callback dahdi_pri_callbacks =
03361 {
03362    .handle_dchan_exception = my_handle_dchan_exception,
03363    .play_tone = my_pri_play_tone,
03364    .set_echocanceller = my_set_echocanceller,
03365    .dsp_reset_and_flush_digits = my_dsp_reset_and_flush_digits,
03366    .lock_private = my_lock_private,
03367    .unlock_private = my_unlock_private,
03368    .new_ast_channel = my_new_pri_ast_channel,
03369    .fixup_chans = my_pri_fixup_chans,
03370    .set_alarm = my_set_alarm,
03371    .set_dialing = my_set_dialing,
03372    .set_outgoing = my_set_outgoing,
03373    .set_digital = my_set_digital,
03374    .set_callerid = my_set_callerid,
03375    .set_dnid = my_set_dnid,
03376    .set_rdnis = my_set_rdnis,
03377    .new_nobch_intf = dahdi_new_pri_nobch_channel,
03378 #if defined(HAVE_PRI_CALL_WAITING)
03379    .init_config = my_pri_init_config,
03380 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
03381    .get_orig_dialstring = my_get_orig_dialstring,
03382    .make_cc_dialstring = my_pri_make_cc_dialstring,
03383    .update_span_devstate = dahdi_pri_update_span_devstate,
03384    .module_ref = my_module_ref,
03385    .module_unref = my_module_unref,
03386    .dial_digits = my_pri_dial_digits,
03387    .open_media = my_pri_ss7_open_media,
03388    .ami_channel_event = my_ami_channel_event,
03389 };
03390 #endif   /* defined(HAVE_PRI) */
03391 
03392 #if defined(HAVE_SS7)
03393 /*!
03394  * \internal
03395  * \brief Handle the SS7 link exception.
03396  * \since 1.8
03397  *
03398  * \param linkset Controlling linkset for the channel.
03399  * \param which Link index of the signaling channel.
03400  *
03401  * \return Nothing
03402  */
03403 static void my_handle_link_exception(struct sig_ss7_linkset *linkset, int which)
03404 {
03405    int event;
03406 
03407    if (ioctl(linkset->fds[which], DAHDI_GETEVENT, &event)) {
03408       ast_log(LOG_ERROR, "SS7: Error in exception retrieval on span %d/%d!\n",
03409          linkset->span, which);
03410       return;
03411    }
03412    switch (event) {
03413    case DAHDI_EVENT_NONE:
03414       break;
03415    case DAHDI_EVENT_ALARM:
03416       ast_log(LOG_ERROR, "SS7 got event: %s(%d) on span %d/%d\n",
03417          event2str(event), event, linkset->span, which);
03418       sig_ss7_link_alarm(linkset, which);
03419       break;
03420    case DAHDI_EVENT_NOALARM:
03421       ast_log(LOG_ERROR, "SS7 got event: %s(%d) on span %d/%d\n",
03422          event2str(event), event, linkset->span, which);
03423       sig_ss7_link_noalarm(linkset, which);
03424       break;
03425    default:
03426       ast_log(LOG_NOTICE, "SS7 got event: %s(%d) on span %d/%d\n",
03427          event2str(event), event, linkset->span, which);
03428       break;
03429    }
03430 }
03431 #endif   /* defined(HAVE_SS7) */
03432 
03433 #if defined(HAVE_SS7)
03434 static void my_ss7_set_loopback(void *pvt, int enable)
03435 {
03436    struct dahdi_pvt *p = pvt;
03437 
03438    if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_LOOPBACK, &enable)) {
03439       ast_log(LOG_WARNING, "Unable to set loopback on channel %d: %s\n", p->channel,
03440          strerror(errno));
03441    }
03442 }
03443 #endif   /* defined(HAVE_SS7) */
03444 
03445 #if defined(HAVE_SS7)
03446 /*!
03447  * \internal
03448  * \brief Create a new asterisk channel structure for SS7.
03449  * \since 1.8
03450  *
03451  * \param pvt Private channel structure.
03452  * \param state Initial state of new channel.
03453  * \param law Combanding law to use.
03454  * \param exten Dialplan extension for incoming call.
03455  * \param requestor Channel requesting this new channel.
03456  *
03457  * \retval ast_channel on success.
03458  * \retval NULL on error.
03459  */
03460 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)
03461 {
03462    struct dahdi_pvt *p = pvt;
03463    int audio;
03464    int newlaw;
03465 
03466    /* Set to audio mode at this point */
03467    audio = 1;
03468    if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &audio) == -1)
03469       ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n",
03470          p->channel, audio, strerror(errno));
03471 
03472    if (law != SIG_SS7_DEFLAW) {
03473       dahdi_setlaw(p->subs[SUB_REAL].dfd,
03474          (law == SIG_SS7_ULAW) ? DAHDI_LAW_MULAW : DAHDI_LAW_ALAW);
03475    }
03476 
03477    ast_copy_string(p->exten, exten, sizeof(p->exten));
03478 
03479    newlaw = -1;
03480    switch (law) {
03481    case SIG_SS7_DEFLAW:
03482       newlaw = 0;
03483       break;
03484    case SIG_SS7_ALAW:
03485       newlaw = DAHDI_LAW_ALAW;
03486       break;
03487    case SIG_SS7_ULAW:
03488       newlaw = DAHDI_LAW_MULAW;
03489       break;
03490    }
03491    return dahdi_new(p, state, 0, SUB_REAL, newlaw, requestor ? requestor->linkedid : "");
03492 }
03493 #endif   /* defined(HAVE_SS7) */
03494 
03495 #if defined(HAVE_SS7)
03496 static int sig_ss7_tone_to_dahditone(enum sig_ss7_tone tone)
03497 {
03498    switch (tone) {
03499    case SIG_SS7_TONE_RINGTONE:
03500       return DAHDI_TONE_RINGTONE;
03501    case SIG_SS7_TONE_STUTTER:
03502       return DAHDI_TONE_STUTTER;
03503    case SIG_SS7_TONE_CONGESTION:
03504       return DAHDI_TONE_CONGESTION;
03505    case SIG_SS7_TONE_DIALTONE:
03506       return DAHDI_TONE_DIALTONE;
03507    case SIG_SS7_TONE_DIALRECALL:
03508       return DAHDI_TONE_DIALRECALL;
03509    case SIG_SS7_TONE_INFO:
03510       return DAHDI_TONE_INFO;
03511    case SIG_SS7_TONE_BUSY:
03512       return DAHDI_TONE_BUSY;
03513    default:
03514       return -1;
03515    }
03516 }
03517 #endif   /* defined(HAVE_SS7) */
03518 
03519 #if defined(HAVE_SS7)
03520 static int my_ss7_play_tone(void *pvt, enum sig_ss7_tone tone)
03521 {
03522    struct dahdi_pvt *p = pvt;
03523 
03524    return tone_zone_play_tone(p->subs[SUB_REAL].dfd, sig_ss7_tone_to_dahditone(tone));
03525 }
03526 #endif   /* defined(HAVE_SS7) */
03527 
03528 #if defined(HAVE_SS7)
03529 static struct sig_ss7_callback dahdi_ss7_callbacks =
03530 {
03531    .lock_private = my_lock_private,
03532    .unlock_private = my_unlock_private,
03533 
03534    .set_echocanceller = my_set_echocanceller,
03535    .set_loopback = my_ss7_set_loopback,
03536 
03537    .new_ast_channel = my_new_ss7_ast_channel,
03538    .play_tone = my_ss7_play_tone,
03539 
03540    .handle_link_exception = my_handle_link_exception,
03541    .set_alarm = my_set_alarm,
03542    .set_dialing = my_set_dialing,
03543    .set_outgoing = my_set_outgoing,
03544    .set_digital = my_set_digital,
03545    .set_inservice = my_set_inservice,
03546    .set_locallyblocked = my_set_locallyblocked,
03547    .set_remotelyblocked = my_set_remotelyblocked,
03548    .set_callerid = my_set_callerid,
03549    .set_dnid = my_set_dnid,
03550    .open_media = my_pri_ss7_open_media,
03551 };
03552 #endif   /* defined(HAVE_SS7) */
03553 
03554 /*!
03555  * \brief Send MWI state change
03556  *
03557  * \arg mailbox_full This is the mailbox associated with the FXO line that the
03558  *      MWI state has changed on.
03559  * \arg thereornot This argument should simply be set to 1 or 0, to indicate
03560  *      whether there are messages waiting or not.
03561  *
03562  *  \return nothing
03563  *
03564  * This function does two things:
03565  *
03566  * 1) It generates an internal Asterisk event notifying any other module that
03567  *    cares about MWI that the state of a mailbox has changed.
03568  *
03569  * 2) It runs the script specified by the mwimonitornotify option to allow
03570  *    some custom handling of the state change.
03571  */
03572 static void notify_message(char *mailbox_full, int thereornot)
03573 {
03574    char s[sizeof(mwimonitornotify) + 80];
03575    struct ast_event *event;
03576    char *mailbox, *context;
03577 
03578    /* Strip off @default */
03579    context = mailbox = ast_strdupa(mailbox_full);
03580    strsep(&context, "@");
03581    if (ast_strlen_zero(context))
03582       context = "default";
03583 
03584    if (!(event = ast_event_new(AST_EVENT_MWI,
03585          AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
03586          AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
03587          AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot,
03588          AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot,
03589          AST_EVENT_IE_END))) {
03590       return;
03591    }
03592 
03593    ast_event_queue_and_cache(event);
03594 
03595    if (!ast_strlen_zero(mailbox) && !ast_strlen_zero(mwimonitornotify)) {
03596       snprintf(s, sizeof(s), "%s %s %d", mwimonitornotify, mailbox, thereornot);
03597       ast_safe_system(s);
03598    }
03599 }
03600 
03601 static void my_handle_notify_message(struct ast_channel *chan, void *pvt, int cid_flags, int neon_mwievent)
03602 {
03603    struct dahdi_pvt *p = pvt;
03604 
03605    if (neon_mwievent > -1 && !p->mwimonitor_neon)
03606       return;
03607 
03608    if (neon_mwievent == ANALOG_EVENT_NEONMWI_ACTIVE || cid_flags & CID_MSGWAITING) {
03609       ast_log(LOG_NOTICE, "MWI: Channel %d message waiting, mailbox %s\n", p->channel, p->mailbox);
03610       notify_message(p->mailbox, 1);
03611    } else if (neon_mwievent == ANALOG_EVENT_NEONMWI_INACTIVE || cid_flags & CID_NOMSGWAITING) {
03612       ast_log(LOG_NOTICE, "MWI: Channel %d no message waiting, mailbox %s\n", p->channel, p->mailbox);
03613       notify_message(p->mailbox, 0);
03614    }
03615    /* If the CID had Message waiting payload, assume that this for MWI only and hangup the call */
03616    /* If generated using Ring Pulse Alert, then ring has been answered as a call and needs to be hungup */
03617    if (neon_mwievent == -1 && p->mwimonitor_rpas) {
03618       ast_hangup(chan);
03619       return;
03620    }
03621 }
03622 
03623 static int my_have_progressdetect(void *pvt)
03624 {
03625    struct dahdi_pvt *p = pvt;
03626 
03627    if ((p->callprogress & CALLPROGRESS_PROGRESS)
03628       && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
03629       return 1;
03630    } else {
03631       /* Don't have progress detection. */
03632       return 0;
03633    }
03634 }
03635 
03636 static struct analog_callback dahdi_analog_callbacks =
03637 {
03638    .play_tone = my_play_tone,
03639    .get_event = my_get_event,
03640    .wait_event = my_wait_event,
03641    .is_off_hook = my_is_off_hook,
03642    .set_echocanceller = my_set_echocanceller,
03643    .ring = my_ring,
03644    .flash = my_flash,
03645    .off_hook = my_off_hook,
03646    .dial_digits = my_dial_digits,
03647    .train_echocanceller = my_train_echocanceller,
03648    .on_hook = my_on_hook,
03649    .is_dialing = my_is_dialing,
03650    .allocate_sub = my_allocate_sub,
03651    .unallocate_sub = my_unallocate_sub,
03652    .swap_subs = my_swap_subchannels,
03653    .has_voicemail = my_has_voicemail,
03654    .check_for_conference = my_check_for_conference,
03655    .conf_add = my_conf_add,
03656    .conf_del = my_conf_del,
03657    .complete_conference_update = my_complete_conference_update,
03658    .start = my_start,
03659    .all_subchannels_hungup = my_all_subchannels_hungup,
03660    .lock_private = my_lock_private,
03661    .unlock_private = my_unlock_private,
03662    .deadlock_avoidance_private = my_deadlock_avoidance_private,
03663    .handle_dtmf = my_handle_dtmf,
03664    .wink = my_wink,
03665    .new_ast_channel = my_new_analog_ast_channel,
03666    .dsp_set_digitmode = my_dsp_set_digitmode,
03667    .dsp_reset_and_flush_digits = my_dsp_reset_and_flush_digits,
03668    .send_callerid = my_send_callerid,
03669    .callwait = my_callwait,
03670    .stop_callwait = my_stop_callwait,
03671    .get_callerid = my_get_callerid,
03672    .start_cid_detect = my_start_cid_detect,
03673    .stop_cid_detect = my_stop_cid_detect,
03674    .handle_notify_message = my_handle_notify_message,
03675    .increase_ss_count = my_increase_ss_count,
03676    .decrease_ss_count = my_decrease_ss_count,
03677    .distinctive_ring = my_distinctive_ring,
03678    .set_linear_mode = my_set_linear_mode,
03679    .set_inthreeway = my_set_inthreeway,
03680    .get_and_handle_alarms = my_get_and_handle_alarms,
03681    .get_sigpvt_bridged_channel = my_get_sigpvt_bridged_channel,
03682    .get_sub_fd = my_get_sub_fd,
03683    .set_cadence = my_set_cadence,
03684    .set_alarm = my_set_alarm,
03685    .set_dialing = my_set_dialing,
03686    .set_outgoing = my_set_outgoing,
03687    .set_ringtimeout = my_set_ringtimeout,
03688    .set_waitingfordt = my_set_waitingfordt,
03689    .check_waitingfordt = my_check_waitingfordt,
03690    .set_confirmanswer = my_set_confirmanswer,
03691    .check_confirmanswer = my_check_confirmanswer,
03692    .set_callwaiting = my_set_callwaiting,
03693    .cancel_cidspill = my_cancel_cidspill,
03694    .confmute = my_confmute,
03695    .set_pulsedial = my_set_pulsedial,
03696    .set_new_owner = my_set_new_owner,
03697    .get_orig_dialstring = my_get_orig_dialstring,
03698    .set_needringing = my_set_needringing,
03699    .set_polarity = my_set_polarity,
03700    .start_polarityswitch = my_start_polarityswitch,
03701    .answer_polarityswitch = my_answer_polarityswitch,
03702    .hangup_polarityswitch = my_hangup_polarityswitch,
03703    .have_progressdetect = my_have_progressdetect,
03704 };
03705 
03706 /*! Round robin search locations. */
03707 static struct dahdi_pvt *round_robin[32];
03708 
03709 #define dahdi_get_index(ast, p, nullok)   _dahdi_get_index(ast, p, nullok, __PRETTY_FUNCTION__, __LINE__)
03710 static int _dahdi_get_index(struct ast_channel *ast, struct dahdi_pvt *p, int nullok, const char *fname, unsigned long line)
03711 {
03712    int res;
03713    if (p->subs[SUB_REAL].owner == ast)
03714       res = 0;
03715    else if (p->subs[SUB_CALLWAIT].owner == ast)
03716       res = 1;
03717    else if (p->subs[SUB_THREEWAY].owner == ast)
03718       res = 2;
03719    else {
03720       res = -1;
03721       if (!nullok)
03722          ast_log(LOG_WARNING,
03723             "Unable to get index for '%s' on channel %d (%s(), line %lu)\n",
03724             ast ? ast->name : "", p->channel, fname, line);
03725    }
03726    return res;
03727 }
03728 
03729 /*!
03730  * \internal
03731  * \brief Obtain the specified subchannel owner lock if the owner exists.
03732  *
03733  * \param pvt Channel private struct.
03734  * \param sub_idx Subchannel owner to lock.
03735  *
03736  * \note Assumes the pvt->lock is already obtained.
03737  *
03738  * \note
03739  * Because deadlock avoidance may have been necessary, you need to confirm
03740  * the state of things before continuing.
03741  *
03742  * \return Nothing
03743  */
03744 static void dahdi_lock_sub_owner(struct dahdi_pvt *pvt, int sub_idx)
03745 {
03746    for (;;) {
03747       if (!pvt->subs[sub_idx].owner) {
03748          /* No subchannel owner pointer */
03749          break;
03750       }
03751       if (!ast_channel_trylock(pvt->subs[sub_idx].owner)) {
03752          /* Got subchannel owner lock */
03753          break;
03754       }
03755       /* We must unlock the private to avoid the possibility of a deadlock */
03756       DEADLOCK_AVOIDANCE(&pvt->lock);
03757    }
03758 }
03759 
03760 static void wakeup_sub(struct dahdi_pvt *p, int a)
03761 {
03762    dahdi_lock_sub_owner(p, a);
03763    if (p->subs[a].owner) {
03764       ast_queue_frame(p->subs[a].owner, &ast_null_frame);
03765       ast_channel_unlock(p->subs[a].owner);
03766    }
03767 }
03768 
03769 static void dahdi_queue_frame(struct dahdi_pvt *p, struct ast_frame *f)
03770 {
03771    for (;;) {
03772       if (p->owner) {
03773          if (ast_channel_trylock(p->owner)) {
03774             DEADLOCK_AVOIDANCE(&p->lock);
03775          } else {
03776             ast_queue_frame(p->owner, f);
03777             ast_channel_unlock(p->owner);
03778             break;
03779          }
03780       } else
03781          break;
03782    }
03783 }
03784 
03785 static void handle_clear_alarms(struct dahdi_pvt *p)
03786 {
03787    if (report_alarms & REPORT_CHANNEL_ALARMS) {
03788       ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel);
03789       manager_event(EVENT_FLAG_SYSTEM, "AlarmClear", "Channel: %d\r\n", p->channel);
03790    }
03791    if (report_alarms & REPORT_SPAN_ALARMS && p->manages_span_alarms) {
03792       ast_log(LOG_NOTICE, "Alarm cleared on span %d\n", p->span);
03793       manager_event(EVENT_FLAG_SYSTEM, "SpanAlarmClear", "Span: %d\r\n", p->span);
03794    }
03795 }
03796 
03797 #ifdef HAVE_OPENR2
03798 
03799 static int dahdi_r2_answer(struct dahdi_pvt *p)
03800 {
03801    int res = 0;
03802    /* openr2 1.1.0 and older does not even define OR2_LIB_INTERFACE
03803    * and does not has support for openr2_chan_answer_call_with_mode
03804    *  */
03805 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
03806    const char *double_answer = pbx_builtin_getvar_helper(p->owner, "MFCR2_DOUBLE_ANSWER");
03807    int wants_double_answer = ast_true(double_answer) ? 1 : 0;
03808    if (!double_answer) {
03809       /* this still can result in double answer if the channel context
03810       * was configured that way */
03811       res = openr2_chan_answer_call(p->r2chan);
03812    } else if (wants_double_answer) {
03813       res = openr2_chan_answer_call_with_mode(p->r2chan, OR2_ANSWER_DOUBLE);
03814    } else {
03815       res = openr2_chan_answer_call_with_mode(p->r2chan, OR2_ANSWER_SIMPLE);
03816    }
03817 #else
03818    res = openr2_chan_answer_call(p->r2chan);
03819 #endif
03820    return res;
03821 }
03822 
03823 
03824 
03825 /* should be called with the ast_channel locked */
03826 static openr2_calling_party_category_t dahdi_r2_get_channel_category(struct ast_channel *c)
03827 {
03828    openr2_calling_party_category_t cat;
03829    const char *catstr = pbx_builtin_getvar_helper(c, "MFCR2_CATEGORY");
03830    struct dahdi_pvt *p = c->tech_pvt;
03831    if (ast_strlen_zero(catstr)) {
03832       ast_debug(1, "No MFC/R2 category specified for chan %s, using default %s\n",
03833             c->name, openr2_proto_get_category_string(p->mfcr2_category));
03834       return p->mfcr2_category;
03835    }
03836    if ((cat = openr2_proto_get_category(catstr)) == OR2_CALLING_PARTY_CATEGORY_UNKNOWN) {
03837       ast_log(LOG_WARNING, "Invalid category specified '%s' for chan %s, using default %s\n",
03838             catstr, c->name, openr2_proto_get_category_string(p->mfcr2_category));
03839       return p->mfcr2_category;
03840    }
03841    ast_debug(1, "Using category %s\n", catstr);
03842    return cat;
03843 }
03844 
03845 static void dahdi_r2_on_call_init(openr2_chan_t *r2chan)
03846 {
03847    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
03848    ast_mutex_lock(&p->lock);
03849    if (p->mfcr2call) {
03850       ast_mutex_unlock(&p->lock);
03851       /* TODO: This can happen when some other thread just finished dahdi_request requesting this very same
03852          interface but has not yet seized the line (dahdi_call), and the far end wins and seize the line,
03853          can we avoid this somehow?, at this point when dahdi_call send the seize, it is likely that since
03854          the other end will see our seize as a forced release and drop the call, we will see an invalid
03855          pattern that will be seen and treated as protocol error. */
03856       ast_log(LOG_ERROR, "Collision of calls on chan %d detected!.\n", openr2_chan_get_number(r2chan));
03857       return;
03858    }
03859    p->mfcr2call = 1;
03860    /* better safe than sorry ... */
03861    p->cid_name[0] = '\0';
03862    p->cid_num[0] = '\0';
03863    p->cid_subaddr[0] = '\0';
03864    p->rdnis[0] = '\0';
03865    p->exten[0] = '\0';
03866    p->mfcr2_ani_index = '\0';
03867    p->mfcr2_dnis_index = '\0';
03868    p->mfcr2_dnis_matched = 0;
03869    p->mfcr2_answer_pending = 0;
03870    p->mfcr2_call_accepted = 0;
03871    ast_mutex_unlock(&p->lock);
03872    ast_verbose("New MFC/R2 call detected on chan %d.\n", openr2_chan_get_number(r2chan));
03873 }
03874 
03875 static void dahdi_r2_on_hardware_alarm(openr2_chan_t *r2chan, int alarm)
03876 {
03877    int res;
03878    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
03879    ast_mutex_lock(&p->lock);
03880    p->inalarm = alarm ? 1 : 0;
03881    if (p->inalarm) {
03882       res = get_alarms(p);
03883       handle_alarms(p, res);
03884    } else {
03885       handle_clear_alarms(p);
03886    }
03887    ast_mutex_unlock(&p->lock);
03888 }
03889 
03890 static void dahdi_r2_on_os_error(openr2_chan_t *r2chan, int errorcode)
03891 {
03892    ast_log(LOG_ERROR, "OS error on chan %d: %s\n", openr2_chan_get_number(r2chan), strerror(errorcode));
03893 }
03894 
03895 static void dahdi_r2_on_protocol_error(openr2_chan_t *r2chan, openr2_protocol_error_t reason)
03896 {
03897    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
03898    ast_log(LOG_ERROR, "MFC/R2 protocol error on chan %d: %s\n", openr2_chan_get_number(r2chan), openr2_proto_get_error(reason));
03899    if (p->owner) {
03900       p->owner->hangupcause = AST_CAUSE_PROTOCOL_ERROR;
03901       p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
03902    }
03903    ast_mutex_lock(&p->lock);
03904    p->mfcr2call = 0;
03905    ast_mutex_unlock(&p->lock);
03906 }
03907 
03908 static void dahdi_r2_disconnect_call(struct dahdi_pvt *p, openr2_call_disconnect_cause_t cause)
03909 {
03910    if (openr2_chan_disconnect_call(p->r2chan, cause)) {
03911       ast_log(LOG_NOTICE, "Bad! failed to disconnect call on channel %d with reason %s, hope for the best!\n",
03912          p->channel, openr2_proto_get_disconnect_string(cause));
03913       /* force the chan to idle and release the call flag now since we will not see a clean on_call_end */
03914       openr2_chan_set_idle(p->r2chan);
03915       ast_mutex_lock(&p->lock);
03916       p->mfcr2call = 0;
03917       ast_mutex_unlock(&p->lock);
03918    }
03919 }
03920 
03921 static void dahdi_r2_on_call_offered(openr2_chan_t *r2chan, const char *ani, const char *dnis, openr2_calling_party_category_t category)
03922 {
03923    struct dahdi_pvt *p;
03924    struct ast_channel *c;
03925    ast_verbose("MFC/R2 call offered on chan %d. ANI = %s, DNIS = %s, Category = %s\n",
03926          openr2_chan_get_number(r2chan), ani ? ani : "(restricted)", dnis,
03927          openr2_proto_get_category_string(category));
03928    p = openr2_chan_get_client_data(r2chan);
03929    /* if collect calls are not allowed and this is a collect call, reject it! */
03930    if (!p->mfcr2_allow_collect_calls && category == OR2_CALLING_PARTY_CATEGORY_COLLECT_CALL) {
03931       ast_log(LOG_NOTICE, "Rejecting MFC/R2 collect call\n");
03932       dahdi_r2_disconnect_call(p, OR2_CAUSE_COLLECT_CALL_REJECTED);
03933       return;
03934    }
03935    ast_mutex_lock(&p->lock);
03936    p->mfcr2_recvd_category = category;
03937    /* if we're not supposed to use CID, clear whatever we have */
03938    if (!p->use_callerid) {
03939       ast_log(LOG_DEBUG, "No CID allowed in configuration, CID is being cleared!\n");
03940       p->cid_num[0] = 0;
03941       p->cid_name[0] = 0;
03942    }
03943    /* if we're supposed to answer immediately, clear DNIS and set 's' exten */
03944    if (p->immediate || !openr2_context_get_max_dnis(openr2_chan_get_context(r2chan))) {
03945       ast_log(LOG_DEBUG, "Setting exten => s because of immediate or 0 DNIS configured\n");
03946       p->exten[0] = 's';
03947       p->exten[1] = 0;
03948    }
03949    ast_mutex_unlock(&p->lock);
03950    if (!ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
03951       ast_log(LOG_NOTICE, "MFC/R2 call on channel %d requested non-existent extension '%s' in context '%s'. Rejecting call.\n",
03952             p->channel, p->exten, p->context);
03953       dahdi_r2_disconnect_call(p, OR2_CAUSE_UNALLOCATED_NUMBER);
03954       return;
03955    }
03956    if (!p->mfcr2_accept_on_offer) {
03957       /* The user wants us to start the PBX thread right away without accepting the call first */
03958       c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, NULL);
03959       if (c) {
03960          /* Done here, don't disable reading now since we still need to generate MF tones to accept
03961             the call or reject it and detect the tone off condition of the other end, all of this
03962             will be done in the PBX thread now */
03963          return;
03964       }
03965       ast_log(LOG_WARNING, "Unable to create PBX channel in DAHDI channel %d\n", p->channel);
03966       dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER);
03967    } else if (p->mfcr2_charge_calls) {
03968       ast_log(LOG_DEBUG, "Accepting MFC/R2 call with charge on chan %d\n", p->channel);
03969       openr2_chan_accept_call(r2chan, OR2_CALL_WITH_CHARGE);
03970    } else {
03971       ast_log(LOG_DEBUG, "Accepting MFC/R2 call with no charge on chan %d\n", p->channel);
03972       openr2_chan_accept_call(r2chan, OR2_CALL_NO_CHARGE);
03973    }
03974 }
03975 
03976 static void dahdi_r2_on_call_end(openr2_chan_t *r2chan)
03977 {
03978    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
03979    ast_verbose("MFC/R2 call end on channel %d\n", p->channel);
03980    ast_mutex_lock(&p->lock);
03981    p->mfcr2call = 0;
03982    ast_mutex_unlock(&p->lock);
03983 }
03984 
03985 static void dahdi_enable_ec(struct dahdi_pvt *p);
03986 static void dahdi_r2_on_call_accepted(openr2_chan_t *r2chan, openr2_call_mode_t mode)
03987 {
03988    struct dahdi_pvt *p = NULL;
03989    struct ast_channel *c = NULL;
03990    p = openr2_chan_get_client_data(r2chan);
03991    dahdi_enable_ec(p);
03992    p->mfcr2_call_accepted = 1;
03993    /* if it's an incoming call ... */
03994    if (OR2_DIR_BACKWARD == openr2_chan_get_direction(r2chan)) {
03995       ast_verbose("MFC/R2 call has been accepted on backward channel %d\n", openr2_chan_get_number(r2chan));
03996       /* If accept on offer is not set, it means at this point the PBX thread is already
03997          launched (was launched in the 'on call offered' handler) and therefore this callback
03998          is being executed already in the PBX thread rather than the monitor thread, don't launch
03999          any other thread, just disable the openr2 reading and answer the call if needed */
04000       if (!p->mfcr2_accept_on_offer) {
04001          openr2_chan_disable_read(r2chan);
04002          if (p->mfcr2_answer_pending) {
04003             ast_log(LOG_DEBUG, "Answering MFC/R2 call after accepting it on chan %d\n", openr2_chan_get_number(r2chan));
04004             dahdi_r2_answer(p);
04005          }
04006          return;
04007       }
04008       c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, NULL);
04009       if (c) {
04010          /* chan_dahdi will take care of reading from now on in the PBX thread, tell the
04011             library to forget about it */
04012          openr2_chan_disable_read(r2chan);
04013          return;
04014       }
04015       ast_log(LOG_WARNING, "Unable to create PBX channel in DAHDI channel %d\n", p->channel);
04016       /* failed to create the channel, bail out and report it as an out of order line */
04017       dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER);
04018       return;
04019    }
04020    /* this is an outgoing call, no need to launch the PBX thread, most likely we're in one already */
04021    ast_verbose("MFC/R2 call has been accepted on forward channel %d\n", p->channel);
04022    p->subs[SUB_REAL].needringing = 1;
04023    p->dialing = 0;
04024    /* chan_dahdi will take care of reading from now on in the PBX thread, tell the library to forget about it */
04025    openr2_chan_disable_read(r2chan);
04026 }
04027 
04028 static void dahdi_r2_on_call_answered(openr2_chan_t *r2chan)
04029 {
04030    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04031    ast_verbose("MFC/R2 call has been answered on channel %d\n", openr2_chan_get_number(r2chan));
04032    p->subs[SUB_REAL].needanswer = 1;
04033 }
04034 
04035 static void dahdi_r2_on_call_read(openr2_chan_t *r2chan, const unsigned char *buf, int buflen)
04036 {
04037    /*ast_log(LOG_DEBUG, "Read data from dahdi channel %d\n", openr2_chan_get_number(r2chan));*/
04038 }
04039 
04040 static int dahdi_r2_cause_to_ast_cause(openr2_call_disconnect_cause_t cause)
04041 {
04042    switch (cause) {
04043    case OR2_CAUSE_BUSY_NUMBER:
04044       return AST_CAUSE_BUSY;
04045    case OR2_CAUSE_NETWORK_CONGESTION:
04046       return AST_CAUSE_CONGESTION;
04047    case OR2_CAUSE_OUT_OF_ORDER:
04048       return AST_CAUSE_DESTINATION_OUT_OF_ORDER;
04049    case OR2_CAUSE_UNALLOCATED_NUMBER:
04050       return AST_CAUSE_UNREGISTERED;
04051    case OR2_CAUSE_NO_ANSWER:
04052       return AST_CAUSE_NO_ANSWER;
04053    case OR2_CAUSE_NORMAL_CLEARING:
04054       return AST_CAUSE_NORMAL_CLEARING;
04055    case OR2_CAUSE_UNSPECIFIED:
04056    default:
04057       return AST_CAUSE_NOTDEFINED;
04058    }
04059 }
04060 
04061 static void dahdi_r2_on_call_disconnect(openr2_chan_t *r2chan, openr2_call_disconnect_cause_t cause)
04062 {
04063    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04064    ast_verbose("MFC/R2 call disconnected on channel %d\n", openr2_chan_get_number(r2chan));
04065    ast_mutex_lock(&p->lock);
04066    if (!p->owner) {
04067       ast_mutex_unlock(&p->lock);
04068       /* no owner, therefore we can't use dahdi_hangup to disconnect, do it right now */
04069       dahdi_r2_disconnect_call(p, OR2_CAUSE_NORMAL_CLEARING);
04070       return;
04071    }
04072    /* when we have an owner we don't call dahdi_r2_disconnect_call here, that will
04073       be done in dahdi_hangup */
04074    if (p->owner->_state == AST_STATE_UP) {
04075       p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
04076       ast_mutex_unlock(&p->lock);
04077    } else if (openr2_chan_get_direction(r2chan) == OR2_DIR_FORWARD) {
04078       /* being the forward side we must report what happened to the call to whoever requested it */
04079       switch (cause) {
04080       case OR2_CAUSE_BUSY_NUMBER:
04081          p->subs[SUB_REAL].needbusy = 1;
04082          break;
04083       case OR2_CAUSE_NETWORK_CONGESTION:
04084       case OR2_CAUSE_OUT_OF_ORDER:
04085       case OR2_CAUSE_UNALLOCATED_NUMBER:
04086       case OR2_CAUSE_NO_ANSWER:
04087       case OR2_CAUSE_UNSPECIFIED:
04088       case OR2_CAUSE_NORMAL_CLEARING:
04089          p->subs[SUB_REAL].needcongestion = 1;
04090          break;
04091       default:
04092          p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
04093       }
04094       ast_mutex_unlock(&p->lock);
04095    } else {
04096       ast_mutex_unlock(&p->lock);
04097       /* being the backward side and not UP yet, we only need to request hangup */
04098       /* TODO: what about doing this same thing when were AST_STATE_UP? */
04099       ast_queue_hangup_with_cause(p->owner, dahdi_r2_cause_to_ast_cause(cause));
04100    }
04101 }
04102 
04103 static void dahdi_r2_write_log(openr2_log_level_t level, char *logmessage)
04104 {
04105    switch (level) {
04106    case OR2_LOG_NOTICE:
04107       ast_verbose("%s", logmessage);
04108       break;
04109    case OR2_LOG_WARNING:
04110       ast_log(LOG_WARNING, "%s", logmessage);
04111       break;
04112    case OR2_LOG_ERROR:
04113       ast_log(LOG_ERROR, "%s", logmessage);
04114       break;
04115    case OR2_LOG_STACK_TRACE:
04116    case OR2_LOG_MF_TRACE:
04117    case OR2_LOG_CAS_TRACE:
04118    case OR2_LOG_DEBUG:
04119    case OR2_LOG_EX_DEBUG:
04120       ast_log(LOG_DEBUG, "%s", logmessage);
04121       break;
04122    default:
04123       ast_log(LOG_WARNING, "We should handle logging level %d here.\n", level);
04124       ast_log(LOG_DEBUG, "%s", logmessage);
04125       break;
04126    }
04127 }
04128 
04129 static void dahdi_r2_on_line_blocked(openr2_chan_t *r2chan)
04130 {
04131    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04132    ast_mutex_lock(&p->lock);
04133    p->remotelyblocked = 1;
04134    ast_mutex_unlock(&p->lock);
04135    ast_log(LOG_NOTICE, "Far end blocked on chan %d\n", openr2_chan_get_number(r2chan));
04136 }
04137 
04138 static void dahdi_r2_on_line_idle(openr2_chan_t *r2chan)
04139 {
04140    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04141    ast_mutex_lock(&p->lock);
04142    p->remotelyblocked = 0;
04143    ast_mutex_unlock(&p->lock);
04144    ast_log(LOG_NOTICE, "Far end unblocked on chan %d\n", openr2_chan_get_number(r2chan));
04145 }
04146 
04147 static void dahdi_r2_on_context_log(openr2_context_t *r2context, openr2_log_level_t level, const char *fmt, va_list ap)
04148    __attribute__((format (printf, 3, 0)));
04149 static void dahdi_r2_on_context_log(openr2_context_t *r2context, openr2_log_level_t level, const char *fmt, va_list ap)
04150 {
04151 #define CONTEXT_TAG "Context - "
04152    char logmsg[256];
04153    char completemsg[sizeof(logmsg) + sizeof(CONTEXT_TAG) - 1];
04154    vsnprintf(logmsg, sizeof(logmsg), fmt, ap);
04155    snprintf(completemsg, sizeof(completemsg), CONTEXT_TAG "%s", logmsg);
04156    dahdi_r2_write_log(level, completemsg);
04157 #undef CONTEXT_TAG
04158 }
04159 
04160 static void dahdi_r2_on_chan_log(openr2_chan_t *r2chan, openr2_log_level_t level, const char *fmt, va_list ap)
04161    __attribute__((format (printf, 3, 0)));
04162 static void dahdi_r2_on_chan_log(openr2_chan_t *r2chan, openr2_log_level_t level, const char *fmt, va_list ap)
04163 {
04164 #define CHAN_TAG "Chan "
04165    char logmsg[256];
04166    char completemsg[sizeof(logmsg) + sizeof(CHAN_TAG) - 1];
04167    vsnprintf(logmsg, sizeof(logmsg), fmt, ap);
04168    snprintf(completemsg, sizeof(completemsg), CHAN_TAG "%d - %s", openr2_chan_get_number(r2chan), logmsg);
04169    dahdi_r2_write_log(level, completemsg);
04170 }
04171 
04172 static int dahdi_r2_on_dnis_digit_received(openr2_chan_t *r2chan, char digit)
04173 {
04174    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04175    /* if 'immediate' is set, let's stop requesting DNIS */
04176    if (p->immediate) {
04177       return 0;
04178    }
04179    p->exten[p->mfcr2_dnis_index] = digit;
04180    p->rdnis[p->mfcr2_dnis_index] = digit;
04181    p->mfcr2_dnis_index++;
04182    p->exten[p->mfcr2_dnis_index] = 0;
04183    p->rdnis[p->mfcr2_dnis_index] = 0;
04184    /* if the DNIS is a match and cannot match more, stop requesting DNIS */
04185    if ((p->mfcr2_dnis_matched ||
04186        (ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num) && (p->mfcr2_dnis_matched = 1))) &&
04187        !ast_matchmore_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
04188       return 0;
04189    }
04190    /* otherwise keep going */
04191    return 1;
04192 }
04193 
04194 static void dahdi_r2_on_ani_digit_received(openr2_chan_t *r2chan, char digit)
04195 {
04196    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04197    p->cid_num[p->mfcr2_ani_index] = digit;
04198    p->cid_name[p->mfcr2_ani_index] = digit;
04199    p->mfcr2_ani_index++;
04200    p->cid_num[p->mfcr2_ani_index] = 0;
04201    p->cid_name[p->mfcr2_ani_index] = 0;
04202 }
04203 
04204 static void dahdi_r2_on_billing_pulse_received(openr2_chan_t *r2chan)
04205 {
04206    ast_verbose("MFC/R2 billing pulse received on channel %d\n", openr2_chan_get_number(r2chan));
04207 }
04208 
04209 static openr2_event_interface_t dahdi_r2_event_iface = {
04210    .on_call_init = dahdi_r2_on_call_init,
04211    .on_call_offered = dahdi_r2_on_call_offered,
04212    .on_call_accepted = dahdi_r2_on_call_accepted,
04213    .on_call_answered = dahdi_r2_on_call_answered,
04214    .on_call_disconnect = dahdi_r2_on_call_disconnect,
04215    .on_call_end = dahdi_r2_on_call_end,
04216    .on_call_read = dahdi_r2_on_call_read,
04217    .on_hardware_alarm = dahdi_r2_on_hardware_alarm,
04218    .on_os_error = dahdi_r2_on_os_error,
04219    .on_protocol_error = dahdi_r2_on_protocol_error,
04220    .on_line_blocked = dahdi_r2_on_line_blocked,
04221    .on_line_idle = dahdi_r2_on_line_idle,
04222    /* cast seems to be needed to get rid of the annoying warning regarding format attribute  */
04223    .on_context_log = (openr2_handle_context_logging_func)dahdi_r2_on_context_log,
04224    .on_dnis_digit_received = dahdi_r2_on_dnis_digit_received,
04225    .on_ani_digit_received = dahdi_r2_on_ani_digit_received,
04226    /* so far we do nothing with billing pulses */
04227    .on_billing_pulse_received = dahdi_r2_on_billing_pulse_received
04228 };
04229 
04230 static inline int16_t dahdi_r2_alaw_to_linear(uint8_t sample)
04231 {
04232    return AST_ALAW(sample);
04233 }
04234 
04235 static inline uint8_t dahdi_r2_linear_to_alaw(int sample)
04236 {
04237    return AST_LIN2A(sample);
04238 }
04239 
04240 static openr2_transcoder_interface_t dahdi_r2_transcode_iface = {
04241    dahdi_r2_alaw_to_linear,
04242    dahdi_r2_linear_to_alaw
04243 };
04244 
04245 #endif /* HAVE_OPENR2 */
04246 
04247 static void swap_subs(struct dahdi_pvt *p, int a, int b)
04248 {
04249    int tchan;
04250    int tinthreeway;
04251    struct ast_channel *towner;
04252 
04253    ast_debug(1, "Swapping %d and %d\n", a, b);
04254 
04255    tchan = p->subs[a].chan;
04256    towner = p->subs[a].owner;
04257    tinthreeway = p->subs[a].inthreeway;
04258 
04259    p->subs[a].chan = p->subs[b].chan;
04260    p->subs[a].owner = p->subs[b].owner;
04261    p->subs[a].inthreeway = p->subs[b].inthreeway;
04262 
04263    p->subs[b].chan = tchan;
04264    p->subs[b].owner = towner;
04265    p->subs[b].inthreeway = tinthreeway;
04266 
04267    if (p->subs[a].owner)
04268       ast_channel_set_fd(p->subs[a].owner, 0, p->subs[a].dfd);
04269    if (p->subs[b].owner)
04270       ast_channel_set_fd(p->subs[b].owner, 0, p->subs[b].dfd);
04271    wakeup_sub(p, a);
04272    wakeup_sub(p, b);
04273 }
04274 
04275 static int dahdi_open(char *fn)
04276 {
04277    int fd;
04278    int isnum;
04279    int chan = 0;
04280    int bs;
04281    int x;
04282    isnum = 1;
04283    for (x = 0; x < strlen(fn); x++) {
04284       if (!isdigit(fn[x])) {
04285          isnum = 0;
04286          break;
04287       }
04288    }
04289    if (isnum) {
04290       chan = atoi(fn);
04291       if (chan < 1) {
04292          ast_log(LOG_WARNING, "Invalid channel number '%s'\n", fn);
04293          return -1;
04294       }
04295       fn = "/dev/dahdi/channel";
04296    }
04297    fd = open(fn, O_RDWR | O_NONBLOCK);
04298    if (fd < 0) {
04299       ast_log(LOG_WARNING, "Unable to open '%s': %s\n", fn, strerror(errno));
04300       return -1;
04301    }
04302    if (chan) {
04303       if (ioctl(fd, DAHDI_SPECIFY, &chan)) {
04304          x = errno;
04305          close(fd);
04306          errno = x;
04307          ast_log(LOG_WARNING, "Unable to specify channel %d: %s\n", chan, strerror(errno));
04308          return -1;
04309       }
04310    }
04311    bs = READ_SIZE;
04312    if (ioctl(fd, DAHDI_SET_BLOCKSIZE, &bs) == -1) {
04313       ast_log(LOG_WARNING, "Unable to set blocksize '%d': %s\n", bs,  strerror(errno));
04314       x = errno;
04315       close(fd);
04316       errno = x;
04317       return -1;
04318    }
04319    return fd;
04320 }
04321 
04322 static void dahdi_close(int fd)
04323 {
04324    if (fd > 0)
04325       close(fd);
04326 }
04327 
04328 static void dahdi_close_sub(struct dahdi_pvt *chan_pvt, int sub_num)
04329 {
04330    dahdi_close(chan_pvt->subs[sub_num].dfd);
04331    chan_pvt->subs[sub_num].dfd = -1;
04332 }
04333 
04334 #if defined(HAVE_PRI)
04335 static void dahdi_close_pri_fd(struct dahdi_pri *pri, int fd_num)
04336 {
04337    dahdi_close(pri->pri.fds[fd_num]);
04338    pri->pri.fds[fd_num] = -1;
04339 }
04340 #endif   /* defined(HAVE_PRI) */
04341 
04342 #if defined(HAVE_SS7)
04343 static void dahdi_close_ss7_fd(struct dahdi_ss7 *ss7, int fd_num)
04344 {
04345    dahdi_close(ss7->ss7.fds[fd_num]);
04346    ss7->ss7.fds[fd_num] = -1;
04347 }
04348 #endif   /* defined(HAVE_SS7) */
04349 
04350 static int dahdi_setlinear(int dfd, int linear)
04351 {
04352    return ioctl(dfd, DAHDI_SETLINEAR, &linear);
04353 }
04354 
04355 
04356 static int alloc_sub(struct dahdi_pvt *p, int x)
04357 {
04358    struct dahdi_bufferinfo bi;
04359    int res;
04360    if (p->subs[x].dfd >= 0) {
04361       ast_log(LOG_WARNING, "%s subchannel of %d already in use\n", subnames[x], p->channel);
04362       return -1;
04363    }
04364 
04365    p->subs[x].dfd = dahdi_open("/dev/dahdi/pseudo");
04366    if (p->subs[x].dfd <= -1) {
04367       ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno));
04368       return -1;
04369    }
04370 
04371    res = ioctl(p->subs[x].dfd, DAHDI_GET_BUFINFO, &bi);
04372    if (!res) {
04373       bi.txbufpolicy = p->buf_policy;
04374       bi.rxbufpolicy = p->buf_policy;
04375       bi.numbufs = p->buf_no;
04376       res = ioctl(p->subs[x].dfd, DAHDI_SET_BUFINFO, &bi);
04377       if (res < 0) {
04378          ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", x, strerror(errno));
04379       }
04380    } else
04381       ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", x, strerror(errno));
04382 
04383    if (ioctl(p->subs[x].dfd, DAHDI_CHANNO, &p->subs[x].chan) == 1) {
04384       ast_log(LOG_WARNING, "Unable to get channel number for pseudo channel on FD %d: %s\n", p->subs[x].dfd, strerror(errno));
04385       dahdi_close_sub(p, x);
04386       p->subs[x].dfd = -1;
04387       return -1;
04388    }
04389    ast_debug(1, "Allocated %s subchannel on FD %d channel %d\n", subnames[x], p->subs[x].dfd, p->subs[x].chan);
04390    return 0;
04391 }
04392 
04393 static int unalloc_sub(struct dahdi_pvt *p, int x)
04394 {
04395    if (!x) {
04396       ast_log(LOG_WARNING, "Trying to unalloc the real channel %d?!?\n", p->channel);
04397       return -1;
04398    }
04399    ast_debug(1, "Released sub %d of channel %d\n", x, p->channel);
04400    dahdi_close_sub(p, x);
04401    p->subs[x].linear = 0;
04402    p->subs[x].chan = 0;
04403    p->subs[x].owner = NULL;
04404    p->subs[x].inthreeway = 0;
04405    p->polarity = POLARITY_IDLE;
04406    memset(&p->subs[x].curconf, 0, sizeof(p->subs[x].curconf));
04407    return 0;
04408 }
04409 
04410 static int digit_to_dtmfindex(char digit)
04411 {
04412    if (isdigit(digit))
04413       return DAHDI_TONE_DTMF_BASE + (digit - '0');
04414    else if (digit >= 'A' && digit <= 'D')
04415       return DAHDI_TONE_DTMF_A + (digit - 'A');
04416    else if (digit >= 'a' && digit <= 'd')
04417       return DAHDI_TONE_DTMF_A + (digit - 'a');
04418    else if (digit == '*')
04419       return DAHDI_TONE_DTMF_s;
04420    else if (digit == '#')
04421       return DAHDI_TONE_DTMF_p;
04422    else
04423       return -1;
04424 }
04425 
04426 static int dahdi_digit_begin(struct ast_channel *chan, char digit)
04427 {
04428    struct dahdi_pvt *pvt;
04429    int idx;
04430    int dtmf = -1;
04431    int res;
04432 
04433    pvt = chan->tech_pvt;
04434 
04435    ast_mutex_lock(&pvt->lock);
04436 
04437    idx = dahdi_get_index(chan, pvt, 0);
04438 
04439    if ((idx != SUB_REAL) || !pvt->owner)
04440       goto out;
04441 
04442 #ifdef HAVE_PRI
04443    switch (pvt->sig) {
04444    case SIG_PRI_LIB_HANDLE_CASES:
04445       res = sig_pri_digit_begin(pvt->sig_pvt, chan, digit);
04446       if (!res)
04447          goto out;
04448       break;
04449    default:
04450       break;
04451    }
04452 #endif
04453    if ((dtmf = digit_to_dtmfindex(digit)) == -1)
04454       goto out;
04455 
04456    if (pvt->pulse || ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &dtmf)) {
04457       struct dahdi_dialoperation zo = {
04458          .op = DAHDI_DIAL_OP_APPEND,
04459       };
04460 
04461       zo.dialstr[0] = 'T';
04462       zo.dialstr[1] = digit;
04463       zo.dialstr[2] = '\0';
04464       if ((res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo)))
04465          ast_log(LOG_WARNING, "Channel %s couldn't dial digit %c: %s\n",
04466             chan->name, digit, strerror(errno));
04467       else
04468          pvt->dialing = 1;
04469    } else {
04470       ast_debug(1, "Channel %s started VLDTMF digit '%c'\n",
04471          chan->name, digit);
04472       pvt->dialing = 1;
04473       pvt->begindigit = digit;
04474    }
04475 
04476 out:
04477    ast_mutex_unlock(&pvt->lock);
04478 
04479    return 0;
04480 }
04481 
04482 static int dahdi_digit_end(struct ast_channel *chan, char digit, unsigned int duration)
04483 {
04484    struct dahdi_pvt *pvt;
04485    int res = 0;
04486    int idx;
04487    int x;
04488 
04489    pvt = chan->tech_pvt;
04490 
04491    ast_mutex_lock(&pvt->lock);
04492 
04493    idx = dahdi_get_index(chan, pvt, 0);
04494 
04495    if ((idx != SUB_REAL) || !pvt->owner || pvt->pulse)
04496       goto out;
04497 
04498 #ifdef HAVE_PRI
04499    /* This means that the digit was already sent via PRI signalling */
04500    if (dahdi_sig_pri_lib_handles(pvt->sig) && !pvt->begindigit) {
04501       goto out;
04502    }
04503 #endif
04504 
04505    if (pvt->begindigit) {
04506       x = -1;
04507       ast_debug(1, "Channel %s ending VLDTMF digit '%c'\n",
04508          chan->name, digit);
04509       res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &x);
04510       pvt->dialing = 0;
04511       pvt->begindigit = 0;
04512    }
04513 
04514 out:
04515    ast_mutex_unlock(&pvt->lock);
04516 
04517    return res;
04518 }
04519 
04520 static const char * const events[] = {
04521    "No event",
04522    "On hook",
04523    "Ring/Answered",
04524    "Wink/Flash",
04525    "Alarm",
04526    "No more alarm",
04527    "HDLC Abort",
04528    "HDLC Overrun",
04529    "HDLC Bad FCS",
04530    "Dial Complete",
04531    "Ringer On",
04532    "Ringer Off",
04533    "Hook Transition Complete",
04534    "Bits Changed",
04535    "Pulse Start",
04536    "Timer Expired",
04537    "Timer Ping",
04538    "Polarity Reversal",
04539    "Ring Begin",
04540 };
04541 
04542 static struct {
04543    int alarm;
04544    char *name;
04545 } alarms[] = {
04546    { DAHDI_ALARM_RED, "Red Alarm" },
04547    { DAHDI_ALARM_YELLOW, "Yellow Alarm" },
04548    { DAHDI_ALARM_BLUE, "Blue Alarm" },
04549    { DAHDI_ALARM_RECOVER, "Recovering" },
04550    { DAHDI_ALARM_LOOPBACK, "Loopback" },
04551    { DAHDI_ALARM_NOTOPEN, "Not Open" },
04552    { DAHDI_ALARM_NONE, "None" },
04553 };
04554 
04555 static char *alarm2str(int alm)
04556 {
04557    int x;
04558    for (x = 0; x < ARRAY_LEN(alarms); x++) {
04559       if (alarms[x].alarm & alm)
04560          return alarms[x].name;
04561    }
04562    return alm ? "Unknown Alarm" : "No Alarm";
04563 }
04564 
04565 static const char *event2str(int event)
04566 {
04567    static char buf[256];
04568    if ((event < (ARRAY_LEN(events))) && (event > -1))
04569       return events[event];
04570    sprintf(buf, "Event %d", event); /* safe */
04571    return buf;
04572 }
04573 
04574 static char *dahdi_sig2str(int sig)
04575 {
04576    static char buf[256];
04577    switch (sig) {
04578    case SIG_EM:
04579       return "E & M Immediate";
04580    case SIG_EMWINK:
04581       return "E & M Wink";
04582    case SIG_EM_E1:
04583       return "E & M E1";
04584    case SIG_FEATD:
04585       return "Feature Group D (DTMF)";
04586    case SIG_FEATDMF:
04587       return "Feature Group D (MF)";
04588    case SIG_FEATDMF_TA:
04589       return "Feature Groud D (MF) Tandem Access";
04590    case SIG_FEATB:
04591       return "Feature Group B (MF)";
04592    case SIG_E911:
04593       return "E911 (MF)";
04594    case SIG_FGC_CAMA:
04595       return "FGC/CAMA (Dialpulse)";
04596    case SIG_FGC_CAMAMF:
04597       return "FGC/CAMA (MF)";
04598    case SIG_FXSLS:
04599       return "FXS Loopstart";
04600    case SIG_FXSGS:
04601       return "FXS Groundstart";
04602    case SIG_FXSKS:
04603       return "FXS Kewlstart";
04604    case SIG_FXOLS:
04605       return "FXO Loopstart";
04606    case SIG_FXOGS:
04607       return "FXO Groundstart";
04608    case SIG_FXOKS:
04609       return "FXO Kewlstart";
04610    case SIG_PRI:
04611       return "ISDN PRI";
04612    case SIG_BRI:
04613       return "ISDN BRI Point to Point";
04614    case SIG_BRI_PTMP:
04615       return "ISDN BRI Point to MultiPoint";
04616    case SIG_SS7:
04617       return "SS7";
04618    case SIG_MFCR2:
04619       return "MFC/R2";
04620    case SIG_SF:
04621       return "SF (Tone) Immediate";
04622    case SIG_SFWINK:
04623       return "SF (Tone) Wink";
04624    case SIG_SF_FEATD:
04625       return "SF (Tone) with Feature Group D (DTMF)";
04626    case SIG_SF_FEATDMF:
04627       return "SF (Tone) with Feature Group D (MF)";
04628    case SIG_SF_FEATB:
04629       return "SF (Tone) with Feature Group B (MF)";
04630    case 0:
04631       return "Pseudo";
04632    default:
04633       snprintf(buf, sizeof(buf), "Unknown signalling %d", sig);
04634       return buf;
04635    }
04636 }
04637 
04638 #define sig2str dahdi_sig2str
04639 
04640 static int analog_lib_handles(int signalling, int radio, int oprmode)
04641 {
04642    switch (signalling) {
04643    case SIG_FXOLS:
04644    case SIG_FXOGS:
04645    case SIG_FXOKS:
04646    case SIG_FXSLS:
04647    case SIG_FXSGS:
04648    case SIG_FXSKS:
04649    case SIG_EMWINK:
04650    case SIG_EM:
04651    case SIG_EM_E1:
04652    case SIG_FEATD:
04653    case SIG_FEATDMF:
04654    case SIG_E911:
04655    case SIG_FGC_CAMA:
04656    case SIG_FGC_CAMAMF:
04657    case SIG_FEATB:
04658    case SIG_SFWINK:
04659    case SIG_SF:
04660    case SIG_SF_FEATD:
04661    case SIG_SF_FEATDMF:
04662    case SIG_FEATDMF_TA:
04663    case SIG_SF_FEATB:
04664       break;
04665    default:
04666       /* The rest of the function should cover the remainder of signalling types */
04667       return 0;
04668    }
04669 
04670    if (radio)
04671       return 0;
04672 
04673    if (oprmode)
04674       return 0;
04675 
04676    return 1;
04677 }
04678 
04679 static int conf_add(struct dahdi_pvt *p, struct dahdi_subchannel *c, int idx, int slavechannel)
04680 {
04681    /* If the conference already exists, and we're already in it
04682       don't bother doing anything */
04683    struct dahdi_confinfo zi;
04684 
04685    memset(&zi, 0, sizeof(zi));
04686    zi.chan = 0;
04687 
04688    if (slavechannel > 0) {
04689       /* If we have only one slave, do a digital mon */
04690       zi.confmode = DAHDI_CONF_DIGITALMON;
04691       zi.confno = slavechannel;
04692    } else {
04693       if (!idx) {
04694          /* Real-side and pseudo-side both participate in conference */
04695          zi.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER |
04696             DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER;
04697       } else
04698          zi.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER;
04699       zi.confno = p->confno;
04700    }
04701    if ((zi.confno == c->curconf.confno) && (zi.confmode == c->curconf.confmode))
04702       return 0;
04703    if (c->dfd < 0)
04704       return 0;
04705    if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
04706       ast_log(LOG_WARNING, "Failed to add %d to conference %d/%d: %s\n", c->dfd, zi.confmode, zi.confno, strerror(errno));
04707       return -1;
04708    }
04709    if (slavechannel < 1) {
04710       p->confno = zi.confno;
04711    }
04712    c->curconf = zi;
04713    ast_debug(1, "Added %d to conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
04714    return 0;
04715 }
04716 
04717 static int isourconf(struct dahdi_pvt *p, struct dahdi_subchannel *c)
04718 {
04719    /* If they're listening to our channel, they're ours */
04720    if ((p->channel == c->curconf.confno) && (c->curconf.confmode == DAHDI_CONF_DIGITALMON))
04721       return 1;
04722    /* If they're a talker on our (allocated) conference, they're ours */
04723    if ((p->confno > 0) && (p->confno == c->curconf.confno) && (c->curconf.confmode & DAHDI_CONF_TALKER))
04724       return 1;
04725    return 0;
04726 }
04727 
04728 static int conf_del(struct dahdi_pvt *p, struct dahdi_subchannel *c, int idx)
04729 {
04730    struct dahdi_confinfo zi;
04731    if (/* Can't delete if there's no dfd */
04732       (c->dfd < 0) ||
04733       /* Don't delete from the conference if it's not our conference */
04734       !isourconf(p, c)
04735       /* Don't delete if we don't think it's conferenced at all (implied) */
04736       ) return 0;
04737    memset(&zi, 0, sizeof(zi));
04738    if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
04739       ast_log(LOG_WARNING, "Failed to drop %d from conference %d/%d: %s\n", c->dfd, c->curconf.confmode, c->curconf.confno, strerror(errno));
04740       return -1;
04741    }
04742    ast_debug(1, "Removed %d from conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
04743    memcpy(&c->curconf, &zi, sizeof(c->curconf));
04744    return 0;
04745 }
04746 
04747 static int isslavenative(struct dahdi_pvt *p, struct dahdi_pvt **out)
04748 {
04749    int x;
04750    int useslavenative;
04751    struct dahdi_pvt *slave = NULL;
04752    /* Start out optimistic */
04753    useslavenative = 1;
04754    /* Update conference state in a stateless fashion */
04755    for (x = 0; x < 3; x++) {
04756       /* Any three-way calling makes slave native mode *definitely* out
04757          of the question */
04758       if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway)
04759          useslavenative = 0;
04760    }
04761    /* If we don't have any 3-way calls, check to see if we have
04762       precisely one slave */
04763    if (useslavenative) {
04764       for (x = 0; x < MAX_SLAVES; x++) {
04765          if (p->slaves[x]) {
04766             if (slave) {
04767                /* Whoops already have a slave!  No
04768                   slave native and stop right away */
04769                slave = NULL;
04770                useslavenative = 0;
04771                break;
04772             } else {
04773                /* We have one slave so far */
04774                slave = p->slaves[x];
04775             }
04776          }
04777       }
04778    }
04779    /* If no slave, slave native definitely out */
04780    if (!slave)
04781       useslavenative = 0;
04782    else if (slave->law != p->law) {
04783       useslavenative = 0;
04784       slave = NULL;
04785    }
04786    if (out)
04787       *out = slave;
04788    return useslavenative;
04789 }
04790 
04791 static int reset_conf(struct dahdi_pvt *p)
04792 {
04793    p->confno = -1;
04794    memset(&p->subs[SUB_REAL].curconf, 0, sizeof(p->subs[SUB_REAL].curconf));
04795    if (p->subs[SUB_REAL].dfd > -1) {
04796       struct dahdi_confinfo zi;
04797 
04798       memset(&zi, 0, sizeof(zi));
04799       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &zi))
04800          ast_log(LOG_WARNING, "Failed to reset conferencing on channel %d: %s\n", p->channel, strerror(errno));
04801    }
04802    return 0;
04803 }
04804 
04805 static int update_conf(struct dahdi_pvt *p)
04806 {
04807    int needconf = 0;
04808    int x;
04809    int useslavenative;
04810    struct dahdi_pvt *slave = NULL;
04811 
04812    useslavenative = isslavenative(p, &slave);
04813    /* Start with the obvious, general stuff */
04814    for (x = 0; x < 3; x++) {
04815       /* Look for three way calls */
04816       if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) {
04817          conf_add(p, &p->subs[x], x, 0);
04818          needconf++;
04819       } else {
04820          conf_del(p, &p->subs[x], x);
04821       }
04822    }
04823    /* If we have a slave, add him to our conference now. or DAX
04824       if this is slave native */
04825    for (x = 0; x < MAX_SLAVES; x++) {
04826       if (p->slaves[x]) {
04827          if (useslavenative)
04828             conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
04829          else {
04830             conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
04831             needconf++;
04832          }
04833       }
04834    }
04835    /* If we're supposed to be in there, do so now */
04836    if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
04837       if (useslavenative)
04838          conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
04839       else {
04840          conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
04841          needconf++;
04842       }
04843    }
04844    /* If we have a master, add ourselves to his conference */
04845    if (p->master) {
04846       if (isslavenative(p->master, NULL)) {
04847          conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
04848       } else {
04849          conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
04850       }
04851    }
04852    if (!needconf) {
04853       /* Nobody is left (or should be left) in our conference.
04854          Kill it. */
04855       p->confno = -1;
04856    }
04857    ast_debug(1, "Updated conferencing on %d, with %d conference users\n", p->channel, needconf);
04858    return 0;
04859 }
04860 
04861 static void dahdi_enable_ec(struct dahdi_pvt *p)
04862 {
04863    int res;
04864    if (!p)
04865       return;
04866    if (p->echocanon) {
04867       ast_debug(1, "Echo cancellation already on\n");
04868       return;
04869    }
04870    if (p->digital) {
04871       ast_debug(1, "Echo cancellation isn't required on digital connection\n");
04872       return;
04873    }
04874    if (p->echocancel.head.tap_length) {
04875 #if defined(HAVE_PRI) || defined(HAVE_SS7)
04876       switch (p->sig) {
04877 #if defined(HAVE_PRI)
04878       case SIG_PRI_LIB_HANDLE_CASES:
04879          if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
04880             /*
04881              * PRI nobch pseudo channel.  Does not need ec anyway.
04882              * Does not handle ioctl(DAHDI_AUDIOMODE)
04883              */
04884             return;
04885          }
04886          /* Fall through */
04887 #endif   /* defined(HAVE_PRI) */
04888 #if defined(HAVE_SS7)
04889       case SIG_SS7:
04890 #endif   /* defined(HAVE_SS7) */
04891          {
04892             int x = 1;
04893 
04894             res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x);
04895             if (res)
04896                ast_log(LOG_WARNING,
04897                   "Unable to enable audio mode on channel %d (%s)\n",
04898                   p->channel, strerror(errno));
04899          }
04900          break;
04901       default:
04902          break;
04903       }
04904 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
04905       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &p->echocancel);
04906       if (res) {
04907          ast_log(LOG_WARNING, "Unable to enable echo cancellation on channel %d (%s)\n", p->channel, strerror(errno));
04908       } else {
04909          p->echocanon = 1;
04910          ast_debug(1, "Enabled echo cancellation on channel %d\n", p->channel);
04911       }
04912    } else
04913       ast_debug(1, "No echo cancellation requested\n");
04914 }
04915 
04916 static void dahdi_train_ec(struct dahdi_pvt *p)
04917 {
04918    int x;
04919    int res;
04920 
04921    if (p && p->echocanon && p->echotraining) {
04922       x = p->echotraining;
04923       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOTRAIN, &x);
04924       if (res)
04925          ast_log(LOG_WARNING, "Unable to request echo training on channel %d: %s\n", p->channel, strerror(errno));
04926       else
04927          ast_debug(1, "Engaged echo training on channel %d\n", p->channel);
04928    } else {
04929       ast_debug(1, "No echo training requested\n");
04930    }
04931 }
04932 
04933 static void dahdi_disable_ec(struct dahdi_pvt *p)
04934 {
04935    int res;
04936 
04937    if (p->echocanon) {
04938       struct dahdi_echocanparams ecp = { .tap_length = 0 };
04939 
04940       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &ecp);
04941 
04942       if (res)
04943          ast_log(LOG_WARNING, "Unable to disable echo cancellation on channel %d: %s\n", p->channel, strerror(errno));
04944       else
04945          ast_debug(1, "Disabled echo cancellation on channel %d\n", p->channel);
04946    }
04947 
04948    p->echocanon = 0;
04949 }
04950 
04951 /* perform a dynamic range compression transform on the given sample */
04952 static int drc_sample(int sample, float drc)
04953 {
04954    float neg;
04955    float shallow, steep;
04956    float max = SHRT_MAX;
04957    
04958    neg = (sample < 0 ? -1 : 1);
04959    steep = drc*sample;
04960    shallow = neg*(max-max/drc)+(float)sample/drc;
04961    if (abs(steep) < abs(shallow)) {
04962       sample = steep;
04963    }
04964    else {
04965       sample = shallow;
04966    }
04967 
04968    return sample;
04969 }
04970 
04971 
04972 static void fill_txgain(struct dahdi_gains *g, float gain, float drc, int law)
04973 {
04974    int j;
04975    int k;
04976 
04977    float linear_gain = pow(10.0, gain / 20.0);
04978 
04979    switch (law) {
04980    case DAHDI_LAW_ALAW:
04981       for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
04982          if (gain || drc) {
04983             k = AST_ALAW(j);
04984             if (drc) {
04985                k = drc_sample(k, drc);
04986             }
04987             k = (float)k*linear_gain;
04988             if (k > 32767) k = 32767;
04989             if (k < -32767) k = -32767;
04990             g->txgain[j] = AST_LIN2A(k);
04991          } else {
04992             g->txgain[j] = j;
04993          }
04994       }
04995       break;
04996    case DAHDI_LAW_MULAW:
04997       for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
04998          if (gain || drc) {
04999             k = AST_MULAW(j);
05000             if (drc) {
05001                k = drc_sample(k, drc);
05002             }
05003             k = (float)k*linear_gain;
05004             if (k > 32767) k = 32767;
05005             if (k < -32767) k = -32767;
05006             g->txgain[j] = AST_LIN2MU(k);
05007 
05008          } else {
05009             g->txgain[j] = j;
05010          }
05011       }
05012       break;
05013    }
05014 }
05015 
05016 static void fill_rxgain(struct dahdi_gains *g, float gain, float drc, int law)
05017 {
05018    int j;
05019    int k;
05020    float linear_gain = pow(10.0, gain / 20.0);
05021 
05022    switch (law) {
05023    case DAHDI_LAW_ALAW:
05024       for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
05025          if (gain || drc) {
05026             k = AST_ALAW(j);
05027             if (drc) {
05028                k = drc_sample(k, drc);
05029             }
05030             k = (float)k*linear_gain;
05031             if (k > 32767) k = 32767;
05032             if (k < -32767) k = -32767;
05033             g->rxgain[j] = AST_LIN2A(k);
05034          } else {
05035             g->rxgain[j] = j;
05036          }
05037       }
05038       break;
05039    case DAHDI_LAW_MULAW:
05040       for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
05041          if (gain || drc) {
05042             k = AST_MULAW(j);
05043             if (drc) {
05044                k = drc_sample(k, drc);
05045             }
05046             k = (float)k*linear_gain;
05047             if (k > 32767) k = 32767;
05048             if (k < -32767) k = -32767;
05049             g->rxgain[j] = AST_LIN2MU(k);
05050          } else {
05051             g->rxgain[j] = j;
05052          }
05053       }
05054       break;
05055    }
05056 }
05057 
05058 static int set_actual_txgain(int fd, float gain, float drc, int law)
05059 {
05060    struct dahdi_gains g;
05061    int res;
05062 
05063    memset(&g, 0, sizeof(g));
05064    res = ioctl(fd, DAHDI_GETGAINS, &g);
05065    if (res) {
05066       ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
05067       return res;
05068    }
05069 
05070    fill_txgain(&g, gain, drc, law);
05071 
05072    return ioctl(fd, DAHDI_SETGAINS, &g);
05073 }
05074 
05075 static int set_actual_rxgain(int fd, float gain, float drc, int law)
05076 {
05077    struct dahdi_gains g;
05078    int res;
05079 
05080    memset(&g, 0, sizeof(g));
05081    res = ioctl(fd, DAHDI_GETGAINS, &g);
05082    if (res) {
05083       ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
05084       return res;
05085    }
05086 
05087    fill_rxgain(&g, gain, drc, law);
05088 
05089    return ioctl(fd, DAHDI_SETGAINS, &g);
05090 }
05091 
05092 static int set_actual_gain(int fd, float rxgain, float txgain, float rxdrc, float txdrc, int law)
05093 {
05094    return set_actual_txgain(fd, txgain, txdrc, law) | set_actual_rxgain(fd, rxgain, rxdrc, law);
05095 }
05096 
05097 static int bump_gains(struct dahdi_pvt *p)
05098 {
05099    int res;
05100 
05101    /* Bump receive gain by value stored in cid_rxgain */
05102    res = set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain + p->cid_rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
05103    if (res) {
05104       ast_log(LOG_WARNING, "Unable to bump gain: %s\n", strerror(errno));
05105       return -1;
05106    }
05107 
05108    return 0;
05109 }
05110 
05111 static int restore_gains(struct dahdi_pvt *p)
05112 {
05113    int res;
05114 
05115    res = set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
05116    if (res) {
05117       ast_log(LOG_WARNING, "Unable to restore gains: %s\n", strerror(errno));
05118       return -1;
05119    }
05120 
05121    return 0;
05122 }
05123 
05124 static inline int dahdi_set_hook(int fd, int hs)
05125 {
05126    int x, res;
05127 
05128    x = hs;
05129    res = ioctl(fd, DAHDI_HOOK, &x);
05130 
05131    if (res < 0) {
05132       if (errno == EINPROGRESS)
05133          return 0;
05134       ast_log(LOG_WARNING, "DAHDI hook failed returned %d (trying %d): %s\n", res, hs, strerror(errno));
05135       /* will expectedly fail if phone is off hook during operation, such as during a restart */
05136    }
05137 
05138    return res;
05139 }
05140 
05141 static inline int dahdi_confmute(struct dahdi_pvt *p, int muted)
05142 {
05143    int x, res;
05144 
05145    x = muted;
05146 #if defined(HAVE_PRI) || defined(HAVE_SS7)
05147    switch (p->sig) {
05148 #if defined(HAVE_PRI)
05149    case SIG_PRI_LIB_HANDLE_CASES:
05150       if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
05151          /* PRI nobch pseudo channel.  Does not handle ioctl(DAHDI_AUDIOMODE) */
05152          break;
05153       }
05154       /* Fall through */
05155 #endif   /* defined(HAVE_PRI) */
05156 #if defined(HAVE_SS7)
05157    case SIG_SS7:
05158 #endif   /* defined(HAVE_SS7) */
05159       {
05160          int y = 1;
05161 
05162          res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &y);
05163          if (res)
05164             ast_log(LOG_WARNING, "Unable to set audio mode on %d: %s\n",
05165                p->channel, strerror(errno));
05166       }
05167       break;
05168    default:
05169       break;
05170    }
05171 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
05172    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_CONFMUTE, &x);
05173    if (res < 0)
05174       ast_log(LOG_WARNING, "DAHDI confmute(%d) failed on channel %d: %s\n", muted, p->channel, strerror(errno));
05175    return res;
05176 }
05177 
05178 static int save_conference(struct dahdi_pvt *p)
05179 {
05180    struct dahdi_confinfo c;
05181    int res;
05182    if (p->saveconf.confmode) {
05183       ast_log(LOG_WARNING, "Can't save conference -- already in use\n");
05184       return -1;
05185    }
05186    p->saveconf.chan = 0;
05187    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &p->saveconf);
05188    if (res) {
05189       ast_log(LOG_WARNING, "Unable to get conference info: %s\n", strerror(errno));
05190       p->saveconf.confmode = 0;
05191       return -1;
05192    }
05193    memset(&c, 0, sizeof(c));
05194    c.confmode = DAHDI_CONF_NORMAL;
05195    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &c);
05196    if (res) {
05197       ast_log(LOG_WARNING, "Unable to set conference info: %s\n", strerror(errno));
05198       return -1;
05199    }
05200    ast_debug(1, "Disabled conferencing\n");
05201    return 0;
05202 }
05203 
05204 static int restore_conference(struct dahdi_pvt *p)
05205 {
05206    int res;
05207    if (p->saveconf.confmode) {
05208       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &p->saveconf);
05209       p->saveconf.confmode = 0;
05210       if (res) {
05211          ast_log(LOG_WARNING, "Unable to restore conference info: %s\n", strerror(errno));
05212          return -1;
05213       }
05214       ast_debug(1, "Restored conferencing\n");
05215    }
05216    return 0;
05217 }
05218 
05219 static int send_cwcidspill(struct dahdi_pvt *p)
05220 {
05221    p->callwaitcas = 0;
05222    p->cidcwexpire = 0;
05223    p->cid_suppress_expire = 0;
05224    if (!(p->cidspill = ast_malloc(MAX_CALLERID_SIZE)))
05225       return -1;
05226    p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, p->callwait_name, p->callwait_num, AST_LAW(p));
05227    /* Make sure we account for the end */
05228    p->cidlen += READ_SIZE * 4;
05229    p->cidpos = 0;
05230    send_callerid(p);
05231    ast_verb(3, "CPE supports Call Waiting Caller*ID.  Sending '%s/%s'\n", p->callwait_name, p->callwait_num);
05232    return 0;
05233 }
05234 
05235 static int has_voicemail(struct dahdi_pvt *p)
05236 {
05237    int new_msgs;
05238    struct ast_event *event;
05239    char *mailbox, *context;
05240 
05241    mailbox = context = ast_strdupa(p->mailbox);
05242    strsep(&context, "@");
05243    if (ast_strlen_zero(context))
05244       context = "default";
05245 
05246    event = ast_event_get_cached(AST_EVENT_MWI,
05247       AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
05248       AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
05249       AST_EVENT_IE_END);
05250 
05251    if (event) {
05252       new_msgs = ast_event_get_ie_uint(event, AST_EVENT_IE_NEWMSGS);
05253       ast_event_destroy(event);
05254    } else
05255       new_msgs = ast_app_has_voicemail(p->mailbox, NULL);
05256 
05257    return new_msgs;
05258 }
05259 
05260 
05261 
05262 static int send_callerid(struct dahdi_pvt *p)
05263 {
05264    /* Assumes spill in p->cidspill, p->cidlen in length and we're p->cidpos into it */
05265    int res;
05266    /* Take out of linear mode if necessary */
05267    if (p->subs[SUB_REAL].linear) {
05268       p->subs[SUB_REAL].linear = 0;
05269       dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
05270    }
05271    while (p->cidpos < p->cidlen) {
05272       res = write(p->subs[SUB_REAL].dfd, p->cidspill + p->cidpos, p->cidlen - p->cidpos);
05273       ast_debug(4, "writing callerid at pos %d of %d, res = %d\n", p->cidpos, p->cidlen, res);
05274       if (res < 0) {
05275          if (errno == EAGAIN)
05276             return 0;
05277          else {
05278             ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
05279             return -1;
05280          }
05281       }
05282       if (!res)
05283          return 0;
05284       p->cidpos += res;
05285    }
05286    p->cid_suppress_expire = CALLWAITING_SUPPRESS_SAMPLES;
05287    ast_free(p->cidspill);
05288    p->cidspill = NULL;
05289    if (p->callwaitcas) {
05290       /* Wait for CID/CW to expire */
05291       p->cidcwexpire = CIDCW_EXPIRE_SAMPLES;
05292       p->cid_suppress_expire = p->cidcwexpire;
05293    } else
05294       restore_conference(p);
05295    return 0;
05296 }
05297 
05298 static int dahdi_callwait(struct ast_channel *ast)
05299 {
05300    struct dahdi_pvt *p = ast->tech_pvt;
05301    p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
05302    if (p->cidspill) {
05303       ast_log(LOG_WARNING, "Spill already exists?!?\n");
05304       ast_free(p->cidspill);
05305    }
05306 
05307    /*
05308     * SAS: Subscriber Alert Signal, 440Hz for 300ms
05309     * CAS: CPE Alert Signal, 2130Hz * 2750Hz sine waves
05310     */
05311    if (!(p->cidspill = ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE * 4)))
05312       return -1;
05313    save_conference(p);
05314    /* Silence */
05315    memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
05316    if (!p->callwaitrings && p->callwaitingcallerid) {
05317       ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
05318       p->callwaitcas = 1;
05319       p->cidlen = 2400 + 680 + READ_SIZE * 4;
05320    } else {
05321       ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
05322       p->callwaitcas = 0;
05323       p->cidlen = 2400 + READ_SIZE * 4;
05324    }
05325    p->cidpos = 0;
05326    send_callerid(p);
05327 
05328    return 0;
05329 }
05330 
05331 static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout)
05332 {
05333    struct dahdi_pvt *p = ast->tech_pvt;
05334    int x, res, mysig;
05335    char dest[256]; /* must be same length as p->dialdest */
05336 
05337    ast_mutex_lock(&p->lock);
05338    ast_copy_string(dest, rdest, sizeof(dest));
05339    ast_copy_string(p->dialdest, rdest, sizeof(p->dialdest));
05340    if ((ast->_state == AST_STATE_BUSY)) {
05341       p->subs[SUB_REAL].needbusy = 1;
05342       ast_mutex_unlock(&p->lock);
05343       return 0;
05344    }
05345    if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
05346       ast_log(LOG_WARNING, "dahdi_call called on %s, neither down nor reserved\n", ast->name);
05347       ast_mutex_unlock(&p->lock);
05348       return -1;
05349    }
05350    p->waitingfordt.tv_sec = 0;
05351    p->dialednone = 0;
05352    if ((p->radio || (p->oprmode < 0)))  /* if a radio channel, up immediately */
05353    {
05354       /* Special pseudo -- automatically up */
05355       ast_setstate(ast, AST_STATE_UP);
05356       ast_mutex_unlock(&p->lock);
05357       return 0;
05358    }
05359    x = DAHDI_FLUSH_READ | DAHDI_FLUSH_WRITE;
05360    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
05361    if (res)
05362       ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", p->channel, strerror(errno));
05363    p->outgoing = 1;
05364 
05365    if (IS_DIGITAL(ast->transfercapability)){
05366       set_actual_gain(p->subs[SUB_REAL].dfd, 0, 0, p->rxdrc, p->txdrc, p->law);
05367    } else {
05368       set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
05369    }  
05370 
05371 #ifdef HAVE_PRI
05372    if (dahdi_sig_pri_lib_handles(p->sig)) {
05373       res = sig_pri_call(p->sig_pvt, ast, rdest, timeout,
05374          (p->law == DAHDI_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW);
05375       ast_mutex_unlock(&p->lock);
05376       return res;
05377    }
05378 #endif
05379 
05380 #if defined(HAVE_SS7)
05381    if (p->sig == SIG_SS7) {
05382       res = sig_ss7_call(p->sig_pvt, ast, rdest);
05383       ast_mutex_unlock(&p->lock);
05384       return res;
05385    }
05386 #endif   /* defined(HAVE_SS7) */
05387 
05388    /* If this is analog signalling we can exit here */
05389    if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
05390       p->callwaitrings = 0;
05391       res = analog_call(p->sig_pvt, ast, rdest, timeout);
05392       ast_mutex_unlock(&p->lock);
05393       return res;
05394    }
05395 
05396    mysig = p->outsigmod > -1 ? p->outsigmod : p->sig;
05397    switch (mysig) {
05398    case 0:
05399       /* Special pseudo -- automatically up*/
05400       ast_setstate(ast, AST_STATE_UP);
05401       break;
05402    case SIG_MFCR2:
05403       break;
05404    default:
05405       ast_debug(1, "not yet implemented\n");
05406       ast_mutex_unlock(&p->lock);
05407       return -1;
05408    }
05409 
05410 #ifdef HAVE_OPENR2
05411    if (p->mfcr2) {
05412       openr2_calling_party_category_t chancat;
05413       int callres = 0;
05414       char *c, *l;
05415 
05416       /* We'll get it in a moment -- but use dialdest to store pre-setup_ack digits */
05417       p->dialdest[0] = '\0';
05418 
05419       c = strchr(dest, '/');
05420       if (c) {
05421          c++;
05422       } else {
05423          c = "";
05424       }
05425       if (!p->hidecallerid) {
05426          l = ast->connected.id.number.valid ? ast->connected.id.number.str : NULL;
05427       } else {
05428          l = NULL;
05429       }
05430       if (strlen(c) < p->stripmsd) {
05431          ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
05432          ast_mutex_unlock(&p->lock);
05433          return -1;
05434       }
05435       p->dialing = 1;
05436       chancat = dahdi_r2_get_channel_category(ast);
05437       callres = openr2_chan_make_call(p->r2chan, l, (c + p->stripmsd), chancat);
05438       if (-1 == callres) {
05439          ast_mutex_unlock(&p->lock);
05440          ast_log(LOG_ERROR, "unable to make new MFC/R2 call!\n");
05441          return -1;
05442       }
05443       p->mfcr2_call_accepted = 0;
05444       p->mfcr2_progress = 0;
05445       ast_setstate(ast, AST_STATE_DIALING);
05446    }
05447 #endif /* HAVE_OPENR2 */
05448    ast_mutex_unlock(&p->lock);
05449    return 0;
05450 }
05451 
05452 /*!
05453  * \internal
05454  * \brief Insert the given chan_dahdi interface structure into the interface list.
05455  * \since 1.8
05456  *
05457  * \param pvt chan_dahdi private interface structure to insert.
05458  *
05459  * \details
05460  * The interface list is a doubly linked list sorted by the chan_dahdi channel number.
05461  * Any duplicates are inserted after the existing entries.
05462  *
05463  * \note The new interface must not already be in the list.
05464  *
05465  * \return Nothing
05466  */
05467 static void dahdi_iflist_insert(struct dahdi_pvt *pvt)
05468 {
05469    struct dahdi_pvt *cur;
05470 
05471    pvt->which_iflist = DAHDI_IFLIST_MAIN;
05472 
05473    /* Find place in middle of list for the new interface. */
05474    for (cur = iflist; cur; cur = cur->next) {
05475       if (pvt->channel < cur->channel) {
05476          /* New interface goes before the current interface. */
05477          pvt->prev = cur->prev;
05478          pvt->next = cur;
05479          if (cur->prev) {
05480             /* Insert into the middle of the list. */
05481             cur->prev->next = pvt;
05482          } else {
05483             /* Insert at head of list. */
05484             iflist = pvt;
05485          }
05486          cur->prev = pvt;
05487          return;
05488       }
05489    }
05490 
05491    /* New interface goes onto the end of the list */
05492    pvt->prev = ifend;
05493    pvt->next = NULL;
05494    if (ifend) {
05495       ifend->next = pvt;
05496    }
05497    ifend = pvt;
05498    if (!iflist) {
05499       /* List was empty */
05500       iflist = pvt;
05501    }
05502 }
05503 
05504 /*!
05505  * \internal
05506  * \brief Extract the given chan_dahdi interface structure from the interface list.
05507  * \since 1.8
05508  *
05509  * \param pvt chan_dahdi private interface structure to extract.
05510  *
05511  * \note
05512  * The given interface structure can be either in the interface list or a stand alone
05513  * structure that has not been put in the list if the next and prev pointers are NULL.
05514  *
05515  * \return Nothing
05516  */
05517 static void dahdi_iflist_extract(struct dahdi_pvt *pvt)
05518 {
05519    /* Extract from the forward chain. */
05520    if (pvt->prev) {
05521       pvt->prev->next = pvt->next;
05522    } else if (iflist == pvt) {
05523       /* Node is at the head of the list. */
05524       iflist = pvt->next;
05525    }
05526 
05527    /* Extract from the reverse chain. */
05528    if (pvt->next) {
05529       pvt->next->prev = pvt->prev;
05530    } else if (ifend == pvt) {
05531       /* Node is at the end of the list. */
05532       ifend = pvt->prev;
05533    }
05534 
05535    /* Node is no longer in the list. */
05536    pvt->which_iflist = DAHDI_IFLIST_NONE;
05537    pvt->prev = NULL;
05538    pvt->next = NULL;
05539 }
05540 
05541 #if defined(HAVE_PRI)
05542 /*!
05543  * \internal
05544  * \brief Insert the given chan_dahdi interface structure into the no B channel list.
05545  * \since 1.8
05546  *
05547  * \param pri sig_pri span control structure holding no B channel list.
05548  * \param pvt chan_dahdi private interface structure to insert.
05549  *
05550  * \details
05551  * The interface list is a doubly linked list sorted by the chan_dahdi channel number.
05552  * Any duplicates are inserted after the existing entries.
05553  *
05554  * \note The new interface must not already be in the list.
05555  *
05556  * \return Nothing
05557  */
05558 static void dahdi_nobch_insert(struct sig_pri_span *pri, struct dahdi_pvt *pvt)
05559 {
05560    struct dahdi_pvt *cur;
05561 
05562    pvt->which_iflist = DAHDI_IFLIST_NO_B_CHAN;
05563 
05564    /* Find place in middle of list for the new interface. */
05565    for (cur = pri->no_b_chan_iflist; cur; cur = cur->next) {
05566       if (pvt->channel < cur->channel) {
05567          /* New interface goes before the current interface. */
05568          pvt->prev = cur->prev;
05569          pvt->next = cur;
05570          if (cur->prev) {
05571             /* Insert into the middle of the list. */
05572             cur->prev->next = pvt;
05573          } else {
05574             /* Insert at head of list. */
05575             pri->no_b_chan_iflist = pvt;
05576          }
05577          cur->prev = pvt;
05578          return;
05579       }
05580    }
05581 
05582    /* New interface goes onto the end of the list */
05583    pvt->prev = pri->no_b_chan_end;
05584    pvt->next = NULL;
05585    if (pri->no_b_chan_end) {
05586       ((struct dahdi_pvt *) pri->no_b_chan_end)->next = pvt;
05587    }
05588    pri->no_b_chan_end = pvt;
05589    if (!pri->no_b_chan_iflist) {
05590       /* List was empty */
05591       pri->no_b_chan_iflist = pvt;
05592    }
05593 }
05594 #endif   /* defined(HAVE_PRI) */
05595 
05596 #if defined(HAVE_PRI)
05597 /*!
05598  * \internal
05599  * \brief Extract the given chan_dahdi interface structure from the no B channel list.
05600  * \since 1.8
05601  *
05602  * \param pri sig_pri span control structure holding no B channel list.
05603  * \param pvt chan_dahdi private interface structure to extract.
05604  *
05605  * \note
05606  * The given interface structure can be either in the interface list or a stand alone
05607  * structure that has not been put in the list if the next and prev pointers are NULL.
05608  *
05609  * \return Nothing
05610  */
05611 static void dahdi_nobch_extract(struct sig_pri_span *pri, struct dahdi_pvt *pvt)
05612 {
05613    /* Extract from the forward chain. */
05614    if (pvt->prev) {
05615       pvt->prev->next = pvt->next;
05616    } else if (pri->no_b_chan_iflist == pvt) {
05617       /* Node is at the head of the list. */
05618       pri->no_b_chan_iflist = pvt->next;
05619    }
05620 
05621    /* Extract from the reverse chain. */
05622    if (pvt->next) {
05623       pvt->next->prev = pvt->prev;
05624    } else if (pri->no_b_chan_end == pvt) {
05625       /* Node is at the end of the list. */
05626       pri->no_b_chan_end = pvt->prev;
05627    }
05628 
05629    /* Node is no longer in the list. */
05630    pvt->which_iflist = DAHDI_IFLIST_NONE;
05631    pvt->prev = NULL;
05632    pvt->next = NULL;
05633 }
05634 #endif   /* defined(HAVE_PRI) */
05635 
05636 #if defined(HAVE_PRI)
05637 /*!
05638  * \internal
05639  * \brief Unlink the channel interface from the PRI private pointer array.
05640  * \since 1.8
05641  *
05642  * \param pvt chan_dahdi private interface structure to unlink.
05643  *
05644  * \return Nothing
05645  */
05646 static void dahdi_unlink_pri_pvt(struct dahdi_pvt *pvt)
05647 {
05648    unsigned idx;
05649    struct sig_pri_span *pri;
05650 
05651    pri = pvt->pri;
05652    if (!pri) {
05653       /* Not PRI signaling so cannot be in a PRI private pointer array. */
05654       return;
05655    }
05656    ast_mutex_lock(&pri->lock);
05657    for (idx = 0; idx < pri->numchans; ++idx) {
05658       if (pri->pvts[idx] == pvt->sig_pvt) {
05659          pri->pvts[idx] = NULL;
05660          ast_mutex_unlock(&pri->lock);
05661          return;
05662       }
05663    }
05664    ast_mutex_unlock(&pri->lock);
05665 }
05666 #endif   /* defined(HAVE_PRI) */
05667 
05668 #if defined(HAVE_SS7)
05669 /*!
05670  * \internal
05671  * \brief Unlink the channel interface from the SS7 private pointer array.
05672  * \since 1.8
05673  *
05674  * \param pvt chan_dahdi private interface structure to unlink.
05675  *
05676  * \return Nothing
05677  */
05678 static void dahdi_unlink_ss7_pvt(struct dahdi_pvt *pvt)
05679 {
05680    unsigned idx;
05681    struct sig_ss7_linkset *ss7;
05682 
05683    ss7 = pvt->ss7;
05684    if (!ss7) {
05685       /* Not SS7 signaling so cannot be in a SS7 private pointer array. */
05686       return;
05687    }
05688    ast_mutex_lock(&ss7->lock);
05689    for (idx = 0; idx < ss7->numchans; ++idx) {
05690       if (ss7->pvts[idx] == pvt->sig_pvt) {
05691          ss7->pvts[idx] = NULL;
05692          ast_mutex_unlock(&ss7->lock);
05693          return;
05694       }
05695    }
05696    ast_mutex_unlock(&ss7->lock);
05697 }
05698 #endif   /* defined(HAVE_SS7) */
05699 
05700 static struct dahdi_pvt *find_next_iface_in_span(struct dahdi_pvt *cur)
05701 {
05702    if (cur->next && cur->next->span == cur->span) {
05703       return cur->next;
05704    } else if (cur->prev && cur->prev->span == cur->span) {
05705       return cur->prev;
05706    }
05707 
05708    return NULL;
05709 }
05710 
05711 static void destroy_dahdi_pvt(struct dahdi_pvt *pvt)
05712 {
05713    struct dahdi_pvt *p = pvt;
05714 
05715    if (p->manages_span_alarms) {
05716       struct dahdi_pvt *next = find_next_iface_in_span(p);
05717       if (next) {
05718          next->manages_span_alarms = 1;
05719       }
05720    }
05721 
05722    /* Remove channel from the list */
05723 #if defined(HAVE_PRI)
05724    dahdi_unlink_pri_pvt(p);
05725 #endif   /* defined(HAVE_PRI) */
05726 #if defined(HAVE_SS7)
05727    dahdi_unlink_ss7_pvt(p);
05728 #endif   /* defined(HAVE_SS7) */
05729    switch (pvt->which_iflist) {
05730    case DAHDI_IFLIST_NONE:
05731       break;
05732    case DAHDI_IFLIST_MAIN:
05733       dahdi_iflist_extract(p);
05734       break;
05735 #if defined(HAVE_PRI)
05736    case DAHDI_IFLIST_NO_B_CHAN:
05737       if (p->pri) {
05738          dahdi_nobch_extract(p->pri, p);
05739       }
05740       break;
05741 #endif   /* defined(HAVE_PRI) */
05742    }
05743 
05744    if (p->sig_pvt) {
05745       if (analog_lib_handles(p->sig, 0, 0)) {
05746          analog_delete(p->sig_pvt);
05747       }
05748       switch (p->sig) {
05749 #if defined(HAVE_PRI)
05750       case SIG_PRI_LIB_HANDLE_CASES:
05751          sig_pri_chan_delete(p->sig_pvt);
05752          break;
05753 #endif   /* defined(HAVE_PRI) */
05754 #if defined(HAVE_SS7)
05755       case SIG_SS7:
05756          sig_ss7_chan_delete(p->sig_pvt);
05757          break;
05758 #endif   /* defined(HAVE_SS7) */
05759       default:
05760          break;
05761       }
05762    }
05763    ast_free(p->cidspill);
05764    if (p->use_smdi)
05765       ast_smdi_interface_unref(p->smdi_iface);
05766    if (p->mwi_event_sub)
05767       ast_event_unsubscribe(p->mwi_event_sub);
05768    if (p->vars) {
05769       ast_variables_destroy(p->vars);
05770    }
05771    if (p->cc_params) {
05772       ast_cc_config_params_destroy(p->cc_params);
05773    }
05774    ast_mutex_destroy(&p->lock);
05775    dahdi_close_sub(p, SUB_REAL);
05776    if (p->owner)
05777       p->owner->tech_pvt = NULL;
05778    ast_free(p);
05779 }
05780 
05781 static void destroy_channel(struct dahdi_pvt *cur, int now)
05782 {
05783    int i;
05784 
05785    if (!now) {
05786       /* Do not destroy the channel now if it is owned by someone. */
05787       if (cur->owner) {
05788          return;
05789       }
05790       for (i = 0; i < 3; i++) {
05791          if (cur->subs[i].owner) {
05792             return;
05793          }
05794       }
05795    }
05796    destroy_dahdi_pvt(cur);
05797 }
05798 
05799 static void destroy_all_channels(void)
05800 {
05801    int chan;
05802 #if defined(HAVE_PRI)
05803    unsigned span;
05804    struct sig_pri_span *pri;
05805 #endif   /* defined(HAVE_PRI) */
05806    struct dahdi_pvt *p;
05807 
05808    while (num_restart_pending) {
05809       usleep(1);
05810    }
05811 
05812    ast_mutex_lock(&iflock);
05813    /* Destroy all the interfaces and free their memory */
05814    while (iflist) {
05815       p = iflist;
05816 
05817       chan = p->channel;
05818 #if defined(HAVE_PRI_SERVICE_MESSAGES)
05819       {
05820          char db_chan_name[20];
05821          char db_answer[5];
05822          char state;
05823          int why = -1;
05824 
05825          snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, p->span, chan);
05826          if (!ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) {
05827             sscanf(db_answer, "%1c:%30d", &state, &why);
05828          }
05829          if (!why) {
05830             /* SRVST persistence is not required */
05831             ast_db_del(db_chan_name, SRVST_DBKEY);
05832          }
05833       }
05834 #endif   /* defined(HAVE_PRI_SERVICE_MESSAGES) */
05835       /* Free associated memory */
05836       destroy_dahdi_pvt(p);
05837       ast_verb(3, "Unregistered channel %d\n", chan);
05838    }
05839    ifcount = 0;
05840    ast_mutex_unlock(&iflock);
05841 
05842 #if defined(HAVE_PRI)
05843    /* Destroy all of the no B channel interface lists */
05844    for (span = 0; span < NUM_SPANS; ++span) {
05845       if (!pris[span].dchannels[0]) {
05846          break;
05847       }
05848       pri = &pris[span].pri;
05849       ast_mutex_lock(&pri->lock);
05850       while (pri->no_b_chan_iflist) {
05851          p = pri->no_b_chan_iflist;
05852 
05853          /* Free associated memory */
05854          destroy_dahdi_pvt(p);
05855       }
05856       ast_mutex_unlock(&pri->lock);
05857    }
05858 #endif   /* defined(HAVE_PRI) */
05859 }
05860 
05861 #if defined(HAVE_PRI)
05862 static char *dahdi_send_keypad_facility_app = "DAHDISendKeypadFacility";
05863 
05864 static int dahdi_send_keypad_facility_exec(struct ast_channel *chan, const char *digits)
05865 {
05866    /* Data will be our digit string */
05867    struct dahdi_pvt *p;
05868 
05869    if (ast_strlen_zero(digits)) {
05870       ast_debug(1, "No digit string sent to application!\n");
05871       return -1;
05872    }
05873 
05874    p = (struct dahdi_pvt *)chan->tech_pvt;
05875 
05876    if (!p) {
05877       ast_debug(1, "Unable to find technology private\n");
05878       return -1;
05879    }
05880 
05881    pri_send_keypad_facility_exec(p->sig_pvt, digits);
05882 
05883    return 0;
05884 }
05885 #endif   /* defined(HAVE_PRI) */
05886 
05887 #if defined(HAVE_PRI)
05888 #if defined(HAVE_PRI_PROG_W_CAUSE)
05889 static char *dahdi_send_callrerouting_facility_app = "DAHDISendCallreroutingFacility";
05890 
05891 static int dahdi_send_callrerouting_facility_exec(struct ast_channel *chan, const char *data)
05892 {
05893    /* Data will be our digit string */
05894    struct dahdi_pvt *pvt;
05895    char *parse;
05896    int res = -1;
05897    AST_DECLARE_APP_ARGS(args,
05898       AST_APP_ARG(destination);
05899       AST_APP_ARG(original);
05900       AST_APP_ARG(reason);
05901    );
05902 
05903    if (ast_strlen_zero(data)) {
05904       ast_log(LOG_DEBUG, "No data sent to application!\n");
05905       return -1;
05906    }
05907    if (chan->tech != &dahdi_tech) {
05908       ast_log(LOG_DEBUG, "Only DAHDI technology accepted!\n");
05909       return -1;
05910    }
05911    pvt = (struct dahdi_pvt *) chan->tech_pvt;
05912    if (!pvt) {
05913       ast_log(LOG_DEBUG, "Unable to find technology private\n");
05914       return -1;
05915    }
05916    switch (pvt->sig) {
05917    case SIG_PRI_LIB_HANDLE_CASES:
05918       break;
05919    default:
05920       ast_log(LOG_DEBUG, "callrerouting attempted on non-ISDN channel %s\n",
05921          chan->name);
05922       return -1;
05923    }
05924 
05925    parse = ast_strdupa(data);
05926    AST_STANDARD_APP_ARGS(args, parse);
05927 
05928    if (ast_strlen_zero(args.destination)) {
05929       ast_log(LOG_WARNING, "callrerouting facility requires at least destination number argument\n");
05930       return -1;
05931    }
05932 
05933    if (ast_strlen_zero(args.original)) {
05934       ast_log(LOG_WARNING, "Callrerouting Facility without original called number argument\n");
05935       args.original = NULL;
05936    }
05937 
05938    if (ast_strlen_zero(args.reason)) {
05939       ast_log(LOG_NOTICE, "Callrerouting Facility without diversion reason argument, defaulting to unknown\n");
05940       args.reason = NULL;
05941    }
05942 
05943    pri_send_callrerouting_facility_exec(pvt->sig_pvt, chan->_state, args.destination,
05944       args.original, args.reason);
05945 
05946    return res;
05947 }
05948 #endif   /* defined(HAVE_PRI_PROG_W_CAUSE) */
05949 #endif   /* defined(HAVE_PRI) */
05950 
05951 #if defined(HAVE_OPENR2)
05952 static const char * const dahdi_accept_r2_call_app = "DAHDIAcceptR2Call";
05953 
05954 static int dahdi_accept_r2_call_exec(struct ast_channel *chan, const char *data)
05955 {
05956    /* data is whether to accept with charge or no charge */
05957    openr2_call_mode_t accept_mode;
05958    int res, timeout, maxloops;
05959    struct ast_frame *f;
05960    struct dahdi_pvt *p;
05961    char *parse;
05962    AST_DECLARE_APP_ARGS(args,
05963          AST_APP_ARG(charge);
05964    );
05965 
05966    if (ast_strlen_zero(data)) {
05967       ast_log(LOG_DEBUG, "No data sent to application!\n");
05968       return -1;
05969    }
05970 
05971    if (chan->tech != &dahdi_tech) {
05972       ast_log(LOG_DEBUG, "Only DAHDI technology accepted!\n");
05973       return -1;
05974    }
05975 
05976    p = (struct dahdi_pvt *)chan->tech_pvt;
05977    if (!p) {
05978       ast_log(LOG_DEBUG, "Unable to find technology private!\n");
05979       return -1;
05980    }
05981 
05982    parse = ast_strdupa(data);
05983    AST_STANDARD_APP_ARGS(args, parse);
05984 
05985    if (ast_strlen_zero(args.charge)) {
05986       ast_log(LOG_WARNING, "DAHDIAcceptR2Call requires 'yes' or 'no' for the charge parameter\n");
05987       return -1;
05988    }
05989 
05990    ast_mutex_lock(&p->lock);
05991    if (!p->mfcr2 || !p->mfcr2call) {
05992       ast_mutex_unlock(&p->lock);
05993       ast_log(LOG_DEBUG, "Channel %s does not seems to be an R2 active channel!\n", chan->name);
05994       return -1;
05995    }
05996 
05997    if (p->mfcr2_call_accepted) {
05998       ast_mutex_unlock(&p->lock);
05999       ast_log(LOG_DEBUG, "MFC/R2 call already accepted on channel %s!\n", chan->name);
06000       return 0;
06001    }
06002    accept_mode = ast_true(args.charge) ? OR2_CALL_WITH_CHARGE : OR2_CALL_NO_CHARGE;
06003    if (openr2_chan_accept_call(p->r2chan, accept_mode)) {
06004       ast_mutex_unlock(&p->lock);
06005       ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n");
06006       return -1;
06007    }
06008    ast_mutex_unlock(&p->lock);
06009 
06010    res = 0;
06011    timeout = 100;
06012    maxloops = 50; /* wait up to 5 seconds */
06013    /* we need to read() until the call is accepted */
06014    while (maxloops > 0) {
06015       maxloops--;
06016       if (ast_check_hangup(chan)) {
06017          break;
06018       }
06019       res = ast_waitfor(chan, timeout);
06020       if (res < 0) {
06021          ast_log(LOG_DEBUG, "ast_waitfor failed on channel %s, going out ...\n", chan->name);
06022          res = -1;
06023          break;
06024       }
06025       if (res == 0) {
06026          continue;
06027       }
06028       f = ast_read(chan);
06029       if (!f) {
06030          ast_log(LOG_DEBUG, "No frame read on channel %s, going out ...\n", chan->name);
06031          res = -1;
06032          break;
06033       }
06034       if (f->frametype == AST_FRAME_CONTROL && f->subclass.integer == AST_CONTROL_HANGUP) {
06035          ast_log(LOG_DEBUG, "Got HANGUP frame on channel %s, going out ...\n", chan->name);
06036          ast_frfree(f);
06037          res = -1;
06038          break;
06039       }
06040       ast_frfree(f);
06041       ast_mutex_lock(&p->lock);
06042       if (p->mfcr2_call_accepted) {
06043          ast_mutex_unlock(&p->lock);
06044          ast_log(LOG_DEBUG, "Accepted MFC/R2 call!\n");
06045          break;
06046       }
06047       ast_mutex_unlock(&p->lock);
06048    }
06049    if (res == -1) {
06050       ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n");
06051    }
06052    return res;
06053 }
06054 
06055 static openr2_call_disconnect_cause_t dahdi_ast_cause_to_r2_cause(int cause)
06056 {
06057    openr2_call_disconnect_cause_t r2cause = OR2_CAUSE_NORMAL_CLEARING;
06058    switch (cause) {
06059    case AST_CAUSE_USER_BUSY:
06060    case AST_CAUSE_CALL_REJECTED:
06061    case AST_CAUSE_INTERWORKING: /* I don't know wtf is this but is used sometimes when ekiga rejects a call */
06062       r2cause = OR2_CAUSE_BUSY_NUMBER;
06063       break;
06064 
06065    case AST_CAUSE_NORMAL_CIRCUIT_CONGESTION:
06066    case AST_CAUSE_SWITCH_CONGESTION:
06067       r2cause = OR2_CAUSE_NETWORK_CONGESTION;
06068       break;
06069 
06070    case AST_CAUSE_UNALLOCATED:
06071       r2cause = OR2_CAUSE_UNALLOCATED_NUMBER;
06072       break;
06073 
06074    case AST_CAUSE_NETWORK_OUT_OF_ORDER:
06075    case AST_CAUSE_DESTINATION_OUT_OF_ORDER:
06076       r2cause = OR2_CAUSE_OUT_OF_ORDER;
06077       break;
06078 
06079    case AST_CAUSE_NO_ANSWER:
06080    case AST_CAUSE_NO_USER_RESPONSE:
06081       r2cause = OR2_CAUSE_NO_ANSWER;
06082       break;
06083 
06084    default:
06085       r2cause = OR2_CAUSE_NORMAL_CLEARING;
06086       break;
06087    }
06088    ast_log(LOG_DEBUG, "ast cause %d resulted in openr2 cause %d/%s\n",
06089          cause, r2cause, openr2_proto_get_disconnect_string(r2cause));
06090    return r2cause;
06091 }
06092 #endif
06093 
06094 static int revert_fax_buffers(struct dahdi_pvt *p, struct ast_channel *ast)
06095 {
06096    if (p->bufferoverrideinuse) {
06097       /* faxbuffers are in use, revert them */
06098       struct dahdi_bufferinfo bi = {
06099          .txbufpolicy = p->buf_policy,
06100          .rxbufpolicy = p->buf_policy,
06101          .bufsize = p->bufsize,
06102          .numbufs = p->buf_no
06103       };
06104       int bpres;
06105 
06106       if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
06107          ast_log(LOG_WARNING, "Channel '%s' unable to revert buffer policy: %s\n", ast->name, strerror(errno));
06108       }
06109       p->bufferoverrideinuse = 0;
06110       return bpres;
06111    }
06112 
06113    return -1;
06114 }
06115 
06116 static int dahdi_hangup(struct ast_channel *ast)
06117 {
06118    int res = 0;
06119    int idx,x;
06120    int law;
06121    /*static int restore_gains(struct dahdi_pvt *p);*/
06122    struct dahdi_pvt *p = ast->tech_pvt;
06123    struct dahdi_params par;
06124 
06125    ast_debug(1, "dahdi_hangup(%s)\n", ast->name);
06126    if (!ast->tech_pvt) {
06127       ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
06128       return 0;
06129    }
06130 
06131    ast_mutex_lock(&p->lock);
06132    p->exten[0] = '\0';
06133    if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
06134       dahdi_confmute(p, 0);
06135       restore_gains(p);
06136       p->ignoredtmf = 0;
06137       p->waitingfordt.tv_sec = 0;
06138 
06139       res = analog_hangup(p->sig_pvt, ast);
06140       revert_fax_buffers(p, ast);
06141 
06142       goto hangup_out;
06143    } else {
06144       p->cid_num[0] = '\0';
06145       p->cid_name[0] = '\0';
06146       p->cid_subaddr[0] = '\0';
06147    }
06148 
06149 #if defined(HAVE_PRI)
06150    if (dahdi_sig_pri_lib_handles(p->sig)) {
06151       x = 1;
06152       ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
06153 
06154       dahdi_confmute(p, 0);
06155       p->muting = 0;
06156       restore_gains(p);
06157       if (p->dsp) {
06158          ast_dsp_free(p->dsp);
06159          p->dsp = NULL;
06160       }
06161       p->ignoredtmf = 0;
06162 
06163       /* Real channel, do some fixup */
06164       p->subs[SUB_REAL].owner = NULL;
06165       p->subs[SUB_REAL].needbusy = 0;
06166       dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
06167 
06168       p->owner = NULL;
06169       p->cid_tag[0] = '\0';
06170       p->ringt = 0;/* Probably not used in this mode.  Reset anyway. */
06171       p->distinctivering = 0;/* Probably not used in this mode. Reset anyway. */
06172       p->confirmanswer = 0;/* Probably not used in this mode. Reset anyway. */
06173       p->outgoing = 0;
06174       p->digital = 0;
06175       p->faxhandled = 0;
06176       p->pulsedial = 0;/* Probably not used in this mode. Reset anyway. */
06177 
06178       revert_fax_buffers(p, ast);
06179 
06180       p->law = p->law_default;
06181       law = p->law_default;
06182       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
06183       if (res < 0) {
06184          ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n",
06185             p->channel, strerror(errno));
06186       }
06187 
06188       sig_pri_hangup(p->sig_pvt, ast);
06189 
06190       tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06191       dahdi_disable_ec(p);
06192 
06193       x = 0;
06194       ast_channel_setoption(ast, AST_OPTION_TDD, &x, sizeof(char), 0);
06195       p->didtdd = 0;/* Probably not used in this mode. Reset anyway. */
06196 
06197       p->rdnis[0] = '\0';
06198       update_conf(p);
06199       reset_conf(p);
06200 
06201       /* Restore data mode */
06202       x = 0;
06203       ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
06204 
06205       if (num_restart_pending == 0) {
06206          restart_monitor();
06207       }
06208       goto hangup_out;
06209    }
06210 #endif   /* defined(HAVE_PRI) */
06211 
06212 #if defined(HAVE_SS7)
06213    if (p->sig == SIG_SS7) {
06214       x = 1;
06215       ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
06216 
06217       dahdi_confmute(p, 0);
06218       p->muting = 0;
06219       restore_gains(p);
06220       if (p->dsp) {
06221          ast_dsp_free(p->dsp);
06222          p->dsp = NULL;
06223       }
06224       p->ignoredtmf = 0;
06225 
06226       /* Real channel, do some fixup */
06227       p->subs[SUB_REAL].owner = NULL;
06228       p->subs[SUB_REAL].needbusy = 0;
06229       dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
06230 
06231       p->owner = NULL;
06232       p->ringt = 0;/* Probably not used in this mode.  Reset anyway. */
06233       p->distinctivering = 0;/* Probably not used in this mode. Reset anyway. */
06234       p->confirmanswer = 0;/* Probably not used in this mode. Reset anyway. */
06235       p->outgoing = 0;
06236       p->digital = 0;
06237       p->faxhandled = 0;
06238       p->pulsedial = 0;/* Probably not used in this mode. Reset anyway. */
06239 
06240       revert_fax_buffers(p, ast);
06241 
06242       p->law = p->law_default;
06243       law = p->law_default;
06244       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
06245       if (res < 0) {
06246          ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n",
06247             p->channel, strerror(errno));
06248       }
06249 
06250       sig_ss7_hangup(p->sig_pvt, ast);
06251 
06252       tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06253       dahdi_disable_ec(p);
06254 
06255       x = 0;
06256       ast_channel_setoption(ast, AST_OPTION_TDD, &x, sizeof(char), 0);
06257       p->didtdd = 0;/* Probably not used in this mode. Reset anyway. */
06258 
06259       update_conf(p);
06260       reset_conf(p);
06261 
06262       /* Restore data mode */
06263       x = 0;
06264       ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
06265 
06266       if (num_restart_pending == 0) {
06267          restart_monitor();
06268       }
06269       goto hangup_out;
06270    }
06271 #endif   /* defined(HAVE_SS7) */
06272 
06273    idx = dahdi_get_index(ast, p, 1);
06274 
06275    dahdi_confmute(p, 0);
06276    p->muting = 0;
06277    restore_gains(p);
06278    if (p->origcid_num) {
06279       ast_copy_string(p->cid_num, p->origcid_num, sizeof(p->cid_num));
06280       ast_free(p->origcid_num);
06281       p->origcid_num = NULL;
06282    }
06283    if (p->origcid_name) {
06284       ast_copy_string(p->cid_name, p->origcid_name, sizeof(p->cid_name));
06285       ast_free(p->origcid_name);
06286       p->origcid_name = NULL;
06287    }
06288    if (p->dsp)
06289       ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
06290 
06291    ast_debug(1, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n",
06292       p->channel, idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
06293    p->ignoredtmf = 0;
06294 
06295    if (idx > -1) {
06296       /* Real channel, do some fixup */
06297       p->subs[idx].owner = NULL;
06298       p->subs[idx].needanswer = 0;
06299       p->subs[idx].needflash = 0;
06300       p->subs[idx].needringing = 0;
06301       p->subs[idx].needbusy = 0;
06302       p->subs[idx].needcongestion = 0;
06303       p->subs[idx].linear = 0;
06304       p->polarity = POLARITY_IDLE;
06305       dahdi_setlinear(p->subs[idx].dfd, 0);
06306       if (idx == SUB_REAL) {
06307          if ((p->subs[SUB_CALLWAIT].dfd > -1) && (p->subs[SUB_THREEWAY].dfd > -1)) {
06308             ast_debug(1, "Normal call hung up with both three way call and a call waiting call in place?\n");
06309             if (p->subs[SUB_CALLWAIT].inthreeway) {
06310                /* We had flipped over to answer a callwait and now it's gone */
06311                ast_debug(1, "We were flipped over to the callwait, moving back and unowning.\n");
06312                /* Move to the call-wait, but un-own us until they flip back. */
06313                swap_subs(p, SUB_CALLWAIT, SUB_REAL);
06314                unalloc_sub(p, SUB_CALLWAIT);
06315                p->owner = NULL;
06316             } else {
06317                /* The three way hung up, but we still have a call wait */
06318                ast_debug(1, "We were in the threeway and have a callwait still.  Ditching the threeway.\n");
06319                swap_subs(p, SUB_THREEWAY, SUB_REAL);
06320                unalloc_sub(p, SUB_THREEWAY);
06321                if (p->subs[SUB_REAL].inthreeway) {
06322                   /* This was part of a three way call.  Immediately make way for
06323                      another call */
06324                   ast_debug(1, "Call was complete, setting owner to former third call\n");
06325                   p->owner = p->subs[SUB_REAL].owner;
06326                } else {
06327                   /* This call hasn't been completed yet...  Set owner to NULL */
06328                   ast_debug(1, "Call was incomplete, setting owner to NULL\n");
06329                   p->owner = NULL;
06330                }
06331                p->subs[SUB_REAL].inthreeway = 0;
06332             }
06333          } else if (p->subs[SUB_CALLWAIT].dfd > -1) {
06334             /* Move to the call-wait and switch back to them. */
06335             swap_subs(p, SUB_CALLWAIT, SUB_REAL);
06336             unalloc_sub(p, SUB_CALLWAIT);
06337             p->owner = p->subs[SUB_REAL].owner;
06338             if (p->owner->_state != AST_STATE_UP)
06339                p->subs[SUB_REAL].needanswer = 1;
06340             if (ast_bridged_channel(p->subs[SUB_REAL].owner))
06341                ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
06342          } else if (p->subs[SUB_THREEWAY].dfd > -1) {
06343             swap_subs(p, SUB_THREEWAY, SUB_REAL);
06344             unalloc_sub(p, SUB_THREEWAY);
06345             if (p->subs[SUB_REAL].inthreeway) {
06346                /* This was part of a three way call.  Immediately make way for
06347                   another call */
06348                ast_debug(1, "Call was complete, setting owner to former third call\n");
06349                p->owner = p->subs[SUB_REAL].owner;
06350             } else {
06351                /* This call hasn't been completed yet...  Set owner to NULL */
06352                ast_debug(1, "Call was incomplete, setting owner to NULL\n");
06353                p->owner = NULL;
06354             }
06355             p->subs[SUB_REAL].inthreeway = 0;
06356          }
06357       } else if (idx == SUB_CALLWAIT) {
06358          /* Ditch the holding callwait call, and immediately make it availabe */
06359          if (p->subs[SUB_CALLWAIT].inthreeway) {
06360             /* This is actually part of a three way, placed on hold.  Place the third part
06361                on music on hold now */
06362             if (p->subs[SUB_THREEWAY].owner && ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
06363                ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
06364                   S_OR(p->mohsuggest, NULL),
06365                   !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
06366             }
06367             p->subs[SUB_THREEWAY].inthreeway = 0;
06368             /* Make it the call wait now */
06369             swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
06370             unalloc_sub(p, SUB_THREEWAY);
06371          } else
06372             unalloc_sub(p, SUB_CALLWAIT);
06373       } else if (idx == SUB_THREEWAY) {
06374          if (p->subs[SUB_CALLWAIT].inthreeway) {
06375             /* The other party of the three way call is currently in a call-wait state.
06376                Start music on hold for them, and take the main guy out of the third call */
06377             if (p->subs[SUB_CALLWAIT].owner && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
06378                ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
06379                   S_OR(p->mohsuggest, NULL),
06380                   !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
06381             }
06382             p->subs[SUB_CALLWAIT].inthreeway = 0;
06383          }
06384          p->subs[SUB_REAL].inthreeway = 0;
06385          /* If this was part of a three way call index, let us make
06386             another three way call */
06387          unalloc_sub(p, SUB_THREEWAY);
06388       } else {
06389          /* This wasn't any sort of call, but how are we an index? */
06390          ast_log(LOG_WARNING, "Index found but not any type of call?\n");
06391       }
06392    }
06393 
06394    if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) {
06395       p->owner = NULL;
06396       p->ringt = 0;
06397       p->distinctivering = 0;
06398       p->confirmanswer = 0;
06399       p->outgoing = 0;
06400       p->digital = 0;
06401       p->faxhandled = 0;
06402       p->pulsedial = 0;
06403       if (p->dsp) {
06404          ast_dsp_free(p->dsp);
06405          p->dsp = NULL;
06406       }
06407 
06408       revert_fax_buffers(p, ast);
06409 
06410       p->law = p->law_default;
06411       law = p->law_default;
06412       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
06413       if (res < 0)
06414          ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
06415       /* Perform low level hangup if no owner left */
06416 #ifdef HAVE_OPENR2
06417       if (p->mfcr2 && p->mfcr2call && openr2_chan_get_direction(p->r2chan) != OR2_DIR_STOPPED) {
06418          ast_log(LOG_DEBUG, "disconnecting MFC/R2 call on chan %d\n", p->channel);
06419          /* If it's an incoming call, check the mfcr2_forced_release setting */
06420          if (openr2_chan_get_direction(p->r2chan) == OR2_DIR_BACKWARD && p->mfcr2_forced_release) {
06421             dahdi_r2_disconnect_call(p, OR2_CAUSE_FORCED_RELEASE);
06422          } else {
06423             const char *r2causestr = pbx_builtin_getvar_helper(ast, "MFCR2_CAUSE");
06424             int r2cause_user = r2causestr ? atoi(r2causestr) : 0;
06425             openr2_call_disconnect_cause_t r2cause = r2cause_user ? dahdi_ast_cause_to_r2_cause(r2cause_user)
06426                                                              : dahdi_ast_cause_to_r2_cause(ast->hangupcause);
06427             dahdi_r2_disconnect_call(p, r2cause);
06428          }
06429       } else if (p->mfcr2call) {
06430          ast_log(LOG_DEBUG, "Clearing call request on channel %d\n", p->channel);
06431          /* since ast_request() was called but not ast_call() we have not yet dialed
06432          and the openr2 stack will not call on_call_end callback, we need to unset
06433          the mfcr2call flag and bump the monitor count so the monitor thread can take
06434          care of this channel events from now on */
06435          p->mfcr2call = 0;
06436       }
06437 #endif
06438       switch (p->sig) {
06439       case SIG_SS7:
06440       case SIG_MFCR2:
06441       case SIG_PRI_LIB_HANDLE_CASES:
06442       case 0:
06443          break;
06444       default:
06445          res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
06446          break;
06447       }
06448       if (res < 0) {
06449          ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast->name);
06450       }
06451       switch (p->sig) {
06452       case SIG_FXOGS:
06453       case SIG_FXOLS:
06454       case SIG_FXOKS:
06455          memset(&par, 0, sizeof(par));
06456          res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
06457          if (!res) {
06458             struct analog_pvt *analog_p = p->sig_pvt;
06459 #if 0
06460             ast_debug(1, "Hanging up channel %d, offhook = %d\n", p->channel, par.rxisoffhook);
06461 #endif
06462             /* If they're off hook, try playing congestion */
06463             if ((par.rxisoffhook) && (!(p->radio || (p->oprmode < 0))))
06464                tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
06465             else
06466                tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06467             analog_p->fxsoffhookstate = par.rxisoffhook;
06468          }
06469          break;
06470       case SIG_FXSGS:
06471       case SIG_FXSLS:
06472       case SIG_FXSKS:
06473          /* Make sure we're not made available for at least two seconds assuming
06474          we were actually used for an inbound or outbound call. */
06475          if (ast->_state != AST_STATE_RESERVED) {
06476             time(&p->guardtime);
06477             p->guardtime += 2;
06478          }
06479          break;
06480       default:
06481          tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06482          break;
06483       }
06484       if (p->sig)
06485          dahdi_disable_ec(p);
06486       x = 0;
06487       ast_channel_setoption(ast,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0);
06488       ast_channel_setoption(ast,AST_OPTION_TDD,&x,sizeof(char),0);
06489       p->didtdd = 0;
06490       p->callwaitcas = 0;
06491       p->callwaiting = p->permcallwaiting;
06492       p->hidecallerid = p->permhidecallerid;
06493       p->waitingfordt.tv_sec = 0;
06494       p->dialing = 0;
06495       p->rdnis[0] = '\0';
06496       update_conf(p);
06497       reset_conf(p);
06498       /* Restore data mode */
06499       switch (p->sig) {
06500       case SIG_PRI_LIB_HANDLE_CASES:
06501       case SIG_SS7:
06502          x = 0;
06503          ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
06504          break;
06505       default:
06506          break;
06507       }
06508       if (num_restart_pending == 0)
06509          restart_monitor();
06510    }
06511 
06512    p->callwaitingrepeat = 0;
06513    p->cidcwexpire = 0;
06514    p->cid_suppress_expire = 0;
06515    p->oprmode = 0;
06516 hangup_out:
06517    ast->tech_pvt = NULL;
06518    ast_free(p->cidspill);
06519    p->cidspill = NULL;
06520 
06521    ast_mutex_unlock(&p->lock);
06522    ast_verb(3, "Hungup '%s'\n", ast->name);
06523 
06524    ast_mutex_lock(&iflock);
06525    if (p->restartpending) {
06526       num_restart_pending--;
06527    }
06528 
06529    if (p->destroy) {
06530       destroy_channel(p, 0);
06531    }
06532    ast_mutex_unlock(&iflock);
06533 
06534    ast_module_unref(ast_module_info->self);
06535    return 0;
06536 }
06537 
06538 static int dahdi_answer(struct ast_channel *ast)
06539 {
06540    struct dahdi_pvt *p = ast->tech_pvt;
06541    int res = 0;
06542    int idx;
06543    ast_setstate(ast, AST_STATE_UP);/*! \todo XXX this is redundantly set by the analog and PRI submodules! */
06544    ast_mutex_lock(&p->lock);
06545    idx = dahdi_get_index(ast, p, 0);
06546    if (idx < 0)
06547       idx = SUB_REAL;
06548    /* nothing to do if a radio channel */
06549    if ((p->radio || (p->oprmode < 0))) {
06550       ast_mutex_unlock(&p->lock);
06551       return 0;
06552    }
06553 
06554    if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
06555       res = analog_answer(p->sig_pvt, ast);
06556       ast_mutex_unlock(&p->lock);
06557       return res;
06558    }
06559 
06560    switch (p->sig) {
06561 #if defined(HAVE_PRI)
06562    case SIG_PRI_LIB_HANDLE_CASES:
06563       res = sig_pri_answer(p->sig_pvt, ast);
06564       break;
06565 #endif   /* defined(HAVE_PRI) */
06566 #if defined(HAVE_SS7)
06567    case SIG_SS7:
06568       res = sig_ss7_answer(p->sig_pvt, ast);
06569       break;
06570 #endif   /* defined(HAVE_SS7) */
06571 #ifdef HAVE_OPENR2
06572    case SIG_MFCR2:
06573       if (!p->mfcr2_call_accepted) {
06574          /* The call was not accepted on offer nor the user, so it must be accepted now before answering,
06575             openr2_chan_answer_call will be called when the callback on_call_accepted is executed */
06576          p->mfcr2_answer_pending = 1;
06577          if (p->mfcr2_charge_calls) {
06578             ast_log(LOG_DEBUG, "Accepting MFC/R2 call with charge before answering on chan %d\n", p->channel);
06579             openr2_chan_accept_call(p->r2chan, OR2_CALL_WITH_CHARGE);
06580          } else {
06581             ast_log(LOG_DEBUG, "Accepting MFC/R2 call with no charge before answering on chan %d\n", p->channel);
06582             openr2_chan_accept_call(p->r2chan, OR2_CALL_NO_CHARGE);
06583          }
06584       } else {
06585          ast_log(LOG_DEBUG, "Answering MFC/R2 call on chan %d\n", p->channel);
06586          dahdi_r2_answer(p);
06587       }
06588       break;
06589 #endif
06590    case 0:
06591       ast_mutex_unlock(&p->lock);
06592       return 0;
06593    default:
06594       ast_log(LOG_WARNING, "Don't know how to answer signalling %d (channel %d)\n", p->sig, p->channel);
06595       res = -1;
06596       break;
06597    }
06598    ast_mutex_unlock(&p->lock);
06599    return res;
06600 }
06601 
06602 static void disable_dtmf_detect(struct dahdi_pvt *p)
06603 {
06604    int val = 0;
06605 
06606    p->ignoredtmf = 1;
06607 
06608    ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
06609 
06610    if (!p->hardwaredtmf && p->dsp) {
06611       p->dsp_features &= ~DSP_FEATURE_DIGIT_DETECT;
06612       ast_dsp_set_features(p->dsp, p->dsp_features);
06613    }
06614 }
06615 
06616 static void enable_dtmf_detect(struct dahdi_pvt *p)
06617 {
06618    int val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
06619 
06620    if (p->channel == CHAN_PSEUDO)
06621       return;
06622 
06623    p->ignoredtmf = 0;
06624 
06625    ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
06626 
06627    if (!p->hardwaredtmf && p->dsp) {
06628       p->dsp_features |= DSP_FEATURE_DIGIT_DETECT;
06629       ast_dsp_set_features(p->dsp, p->dsp_features);
06630    }
06631 }
06632 
06633 static int dahdi_queryoption(struct ast_channel *chan, int option, void *data, int *datalen)
06634 {
06635    char *cp;
06636    struct dahdi_pvt *p = chan->tech_pvt;
06637 
06638    /* all supported options require data */
06639    if (!p || !data || (*datalen < 1)) {
06640       errno = EINVAL;
06641       return -1;
06642    }
06643 
06644    switch (option) {
06645    case AST_OPTION_DIGIT_DETECT:
06646       cp = (char *) data;
06647       *cp = p->ignoredtmf ? 0 : 1;
06648       ast_debug(1, "Reporting digit detection %sabled on %s\n", *cp ? "en" : "dis", chan->name);
06649       break;
06650    case AST_OPTION_FAX_DETECT:
06651       cp = (char *) data;
06652       *cp = (p->dsp_features & DSP_FEATURE_FAX_DETECT) ? 0 : 1;
06653       ast_debug(1, "Reporting fax tone detection %sabled on %s\n", *cp ? "en" : "dis", chan->name);
06654       break;
06655    case AST_OPTION_CC_AGENT_TYPE:
06656 #if defined(HAVE_PRI)
06657 #if defined(HAVE_PRI_CCSS)
06658       if (dahdi_sig_pri_lib_handles(p->sig)) {
06659          ast_copy_string((char *) data, dahdi_pri_cc_type, *datalen);
06660          break;
06661       }
06662 #endif   /* defined(HAVE_PRI_CCSS) */
06663 #endif   /* defined(HAVE_PRI) */
06664       return -1;
06665    default:
06666       return -1;
06667    }
06668 
06669    errno = 0;
06670 
06671    return 0;
06672 }
06673 
06674 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen)
06675 {
06676    char *cp;
06677    signed char *scp;
06678    int x;
06679    int idx;
06680    struct dahdi_pvt *p = chan->tech_pvt, *pp;
06681    struct oprmode *oprmode;
06682 
06683 
06684    /* all supported options require data */
06685    if (!p || !data || (datalen < 1)) {
06686       errno = EINVAL;
06687       return -1;
06688    }
06689 
06690    switch (option) {
06691    case AST_OPTION_TXGAIN:
06692       scp = (signed char *) data;
06693       idx = dahdi_get_index(chan, p, 0);
06694       if (idx < 0) {
06695          ast_log(LOG_WARNING, "No index in TXGAIN?\n");
06696          return -1;
06697       }
06698       ast_debug(1, "Setting actual tx gain on %s to %f\n", chan->name, p->txgain + (float) *scp);
06699       return set_actual_txgain(p->subs[idx].dfd, p->txgain + (float) *scp, p->txdrc, p->law);
06700    case AST_OPTION_RXGAIN:
06701       scp = (signed char *) data;
06702       idx = dahdi_get_index(chan, p, 0);
06703       if (idx < 0) {
06704          ast_log(LOG_WARNING, "No index in RXGAIN?\n");
06705          return -1;
06706       }
06707       ast_debug(1, "Setting actual rx gain on %s to %f\n", chan->name, p->rxgain + (float) *scp);
06708       return set_actual_rxgain(p->subs[idx].dfd, p->rxgain + (float) *scp, p->rxdrc, p->law);
06709    case AST_OPTION_TONE_VERIFY:
06710       if (!p->dsp)
06711          break;
06712       cp = (char *) data;
06713       switch (*cp) {
06714       case 1:
06715          ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",chan->name);
06716          ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | p->dtmfrelax);  /* set mute mode if desired */
06717          break;
06718       case 2:
06719          ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",chan->name);
06720          ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX | p->dtmfrelax);  /* set mute mode if desired */
06721          break;
06722       default:
06723          ast_debug(1, "Set option TONE VERIFY, mode: OFF(0) on %s\n",chan->name);
06724          ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);  /* set mute mode if desired */
06725          break;
06726       }
06727       break;
06728    case AST_OPTION_TDD:
06729       /* turn on or off TDD */
06730       cp = (char *) data;
06731       p->mate = 0;
06732       if (!*cp) { /* turn it off */
06733          ast_debug(1, "Set option TDD MODE, value: OFF(0) on %s\n",chan->name);
06734          if (p->tdd)
06735             tdd_free(p->tdd);
06736          p->tdd = 0;
06737          break;
06738       }
06739       ast_debug(1, "Set option TDD MODE, value: %s(%d) on %s\n",
06740          (*cp == 2) ? "MATE" : "ON", (int) *cp, chan->name);
06741       dahdi_disable_ec(p);
06742       /* otherwise, turn it on */
06743       if (!p->didtdd) { /* if havent done it yet */
06744          unsigned char mybuf[41000];/*! \todo XXX This is an abuse of the stack!! */
06745          unsigned char *buf;
06746          int size, res, fd, len;
06747          struct pollfd fds[1];
06748 
06749          buf = mybuf;
06750          memset(buf, 0x7f, sizeof(mybuf)); /* set to silence */
06751          ast_tdd_gen_ecdisa(buf + 16000, 16000);  /* put in tone */
06752          len = 40000;
06753          idx = dahdi_get_index(chan, p, 0);
06754          if (idx < 0) {
06755             ast_log(LOG_WARNING, "No index in TDD?\n");
06756             return -1;
06757          }
06758          fd = p->subs[idx].dfd;
06759          while (len) {
06760             if (ast_check_hangup(chan))
06761                return -1;
06762             size = len;
06763             if (size > READ_SIZE)
06764                size = READ_SIZE;
06765             fds[0].fd = fd;
06766             fds[0].events = POLLPRI | POLLOUT;
06767             fds[0].revents = 0;
06768             res = poll(fds, 1, -1);
06769             if (!res) {
06770                ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
06771                continue;
06772             }
06773             /* if got exception */
06774             if (fds[0].revents & POLLPRI)
06775                return -1;
06776             if (!(fds[0].revents & POLLOUT)) {
06777                ast_debug(1, "write fd not ready on channel %d\n", p->channel);
06778                continue;
06779             }
06780             res = write(fd, buf, size);
06781             if (res != size) {
06782                if (res == -1) return -1;
06783                ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
06784                break;
06785             }
06786             len -= size;
06787             buf += size;
06788          }
06789          p->didtdd = 1; /* set to have done it now */
06790       }
06791       if (*cp == 2) { /* Mate mode */
06792          if (p->tdd)
06793             tdd_free(p->tdd);
06794          p->tdd = 0;
06795          p->mate = 1;
06796          break;
06797       }
06798       if (!p->tdd) { /* if we don't have one yet */
06799          p->tdd = tdd_new(); /* allocate one */
06800       }
06801       break;
06802    case AST_OPTION_RELAXDTMF:  /* Relax DTMF decoding (or not) */
06803       if (!p->dsp)
06804          break;
06805       cp = (char *) data;
06806       ast_debug(1, "Set option RELAX DTMF, value: %s(%d) on %s\n",
06807          *cp ? "ON" : "OFF", (int) *cp, chan->name);
06808       ast_dsp_set_digitmode(p->dsp, ((*cp) ? DSP_DIGITMODE_RELAXDTMF : DSP_DIGITMODE_DTMF) | p->dtmfrelax);
06809       break;
06810    case AST_OPTION_AUDIO_MODE:  /* Set AUDIO mode (or not) */
06811 #if defined(HAVE_PRI)
06812       if (dahdi_sig_pri_lib_handles(p->sig)
06813          && ((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
06814          /* PRI nobch pseudo channel.  Does not handle ioctl(DAHDI_AUDIOMODE) */
06815          break;
06816       }
06817 #endif   /* defined(HAVE_PRI) */
06818 
06819       cp = (char *) data;
06820       if (!*cp) {
06821          ast_debug(1, "Set option AUDIO MODE, value: OFF(0) on %s\n", chan->name);
06822          x = 0;
06823          dahdi_disable_ec(p);
06824       } else {
06825          ast_debug(1, "Set option AUDIO MODE, value: ON(1) on %s\n", chan->name);
06826          x = 1;
06827       }
06828       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x) == -1)
06829          ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, x, strerror(errno));
06830       break;
06831    case AST_OPTION_OPRMODE:  /* Operator services mode */
06832       oprmode = (struct oprmode *) data;
06833       /* We don't support operator mode across technologies */
06834       if (strcasecmp(chan->tech->type, oprmode->peer->tech->type)) {
06835          ast_log(LOG_NOTICE, "Operator mode not supported on %s to %s calls.\n",
06836                chan->tech->type, oprmode->peer->tech->type);
06837          errno = EINVAL;
06838          return -1;
06839       }
06840       pp = oprmode->peer->tech_pvt;
06841       p->oprmode = pp->oprmode = 0;
06842       /* setup peers */
06843       p->oprpeer = pp;
06844       pp->oprpeer = p;
06845       /* setup modes, if any */
06846       if (oprmode->mode)
06847       {
06848          pp->oprmode = oprmode->mode;
06849          p->oprmode = -oprmode->mode;
06850       }
06851       ast_debug(1, "Set Operator Services mode, value: %d on %s/%s\n",
06852          oprmode->mode, chan->name,oprmode->peer->name);
06853       break;
06854    case AST_OPTION_ECHOCAN:
06855       cp = (char *) data;
06856       if (*cp) {
06857          ast_debug(1, "Enabling echo cancellation on %s\n", chan->name);
06858          dahdi_enable_ec(p);
06859       } else {
06860          ast_debug(1, "Disabling echo cancellation on %s\n", chan->name);
06861          dahdi_disable_ec(p);
06862       }
06863       break;
06864    case AST_OPTION_DIGIT_DETECT:
06865       cp = (char *) data;
06866       ast_debug(1, "%sabling digit detection on %s\n", *cp ? "En" : "Dis", chan->name);
06867       if (*cp) {
06868          enable_dtmf_detect(p);
06869       } else {
06870          disable_dtmf_detect(p);
06871       }
06872       break;
06873    case AST_OPTION_FAX_DETECT:
06874       cp = (char *) data;
06875       if (p->dsp) {
06876          ast_debug(1, "%sabling fax tone detection on %s\n", *cp ? "En" : "Dis", chan->name);
06877          if (*cp) {
06878             p->dsp_features |= DSP_FEATURE_FAX_DETECT;
06879          } else {
06880             p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
06881          }
06882          ast_dsp_set_features(p->dsp, p->dsp_features);
06883       }
06884       break;
06885    default:
06886       return -1;
06887    }
06888    errno = 0;
06889 
06890    return 0;
06891 }
06892 
06893 static int dahdi_func_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len)
06894 {
06895    struct dahdi_pvt *p = chan->tech_pvt;
06896    int res = 0;
06897 
06898    if (!p) {
06899       /* No private structure! */
06900       *buf = '\0';
06901       return -1;
06902    }
06903 
06904    if (!strcasecmp(data, "rxgain")) {
06905       ast_mutex_lock(&p->lock);
06906       snprintf(buf, len, "%f", p->rxgain);
06907       ast_mutex_unlock(&p->lock);
06908    } else if (!strcasecmp(data, "txgain")) {
06909       ast_mutex_lock(&p->lock);
06910       snprintf(buf, len, "%f", p->txgain);
06911       ast_mutex_unlock(&p->lock);
06912    } else if (!strcasecmp(data, "dahdi_channel")) {
06913       ast_mutex_lock(&p->lock);
06914       snprintf(buf, len, "%d", p->channel);
06915       ast_mutex_unlock(&p->lock);
06916    } else if (!strcasecmp(data, "dahdi_span")) {
06917       ast_mutex_lock(&p->lock);
06918       snprintf(buf, len, "%d", p->span);
06919       ast_mutex_unlock(&p->lock);
06920    } else if (!strcasecmp(data, "dahdi_type")) {
06921       ast_mutex_lock(&p->lock);
06922       switch (p->sig) {
06923 #if defined(HAVE_OPENR2)
06924       case SIG_MFCR2:
06925          ast_copy_string(buf, "mfc/r2", len);
06926          break;
06927 #endif   /* defined(HAVE_OPENR2) */
06928 #if defined(HAVE_PRI)
06929       case SIG_PRI_LIB_HANDLE_CASES:
06930          ast_copy_string(buf, "pri", len);
06931          break;
06932 #endif   /* defined(HAVE_PRI) */
06933       case 0:
06934          ast_copy_string(buf, "pseudo", len);
06935          break;
06936 #if defined(HAVE_SS7)
06937       case SIG_SS7:
06938          ast_copy_string(buf, "ss7", len);
06939          break;
06940 #endif   /* defined(HAVE_SS7) */
06941       default:
06942          /* The only thing left is analog ports. */
06943          ast_copy_string(buf, "analog", len);
06944          break;
06945       }
06946       ast_mutex_unlock(&p->lock);
06947 #if defined(HAVE_PRI)
06948 #if defined(HAVE_PRI_REVERSE_CHARGE)
06949    } else if (!strcasecmp(data, "reversecharge")) {
06950       ast_mutex_lock(&p->lock);
06951       switch (p->sig) {
06952       case SIG_PRI_LIB_HANDLE_CASES:
06953          snprintf(buf, len, "%d", ((struct sig_pri_chan *) p->sig_pvt)->reverse_charging_indication);
06954          break;
06955       default:
06956          *buf = '\0';
06957          res = -1;
06958          break;
06959       }
06960       ast_mutex_unlock(&p->lock);
06961 #endif
06962 #if defined(HAVE_PRI_SETUP_KEYPAD)
06963    } else if (!strcasecmp(data, "keypad_digits")) {
06964       ast_mutex_lock(&p->lock);
06965       switch (p->sig) {
06966       case SIG_PRI_LIB_HANDLE_CASES:
06967          ast_copy_string(buf, ((struct sig_pri_chan *) p->sig_pvt)->keypad_digits,
06968             len);
06969          break;
06970       default:
06971          *buf = '\0';
06972          res = -1;
06973          break;
06974       }
06975       ast_mutex_unlock(&p->lock);
06976 #endif   /* defined(HAVE_PRI_SETUP_KEYPAD) */
06977    } else if (!strcasecmp(data, "no_media_path")) {
06978       ast_mutex_lock(&p->lock);
06979       switch (p->sig) {
06980       case SIG_PRI_LIB_HANDLE_CASES:
06981          /*
06982           * TRUE if the call is on hold or is call waiting because
06983           * there is no media path available.
06984           */
06985          snprintf(buf, len, "%d", ((struct sig_pri_chan *) p->sig_pvt)->no_b_channel);
06986          break;
06987       default:
06988          *buf = '\0';
06989          res = -1;
06990          break;
06991       }
06992       ast_mutex_unlock(&p->lock);
06993 #endif   /* defined(HAVE_PRI) */
06994    } else {
06995       *buf = '\0';
06996       res = -1;
06997    }
06998 
06999    return res;
07000 }
07001 
07002 
07003 static int parse_buffers_policy(const char *parse, int *num_buffers, int *policy)
07004 {
07005    int res;
07006    char policy_str[21] = "";
07007 
07008    if ((res = sscanf(parse, "%30d,%20s", num_buffers, policy_str)) != 2) {
07009       ast_log(LOG_WARNING, "Parsing buffer string '%s' failed.\n", parse);
07010       return 1;
07011    }
07012    if (*num_buffers < 0) {
07013       ast_log(LOG_WARNING, "Invalid buffer count given '%d'.\n", *num_buffers);
07014       return -1;
07015    }
07016    if (!strcasecmp(policy_str, "full")) {
07017       *policy = DAHDI_POLICY_WHEN_FULL;
07018    } else if (!strcasecmp(policy_str, "immediate")) {
07019       *policy = DAHDI_POLICY_IMMEDIATE;
07020 #if defined(HAVE_DAHDI_HALF_FULL)
07021    } else if (!strcasecmp(policy_str, "half")) {
07022       *policy = DAHDI_POLICY_HALF_FULL;
07023 #endif
07024    } else {
07025       ast_log(LOG_WARNING, "Invalid policy name given '%s'.\n", policy_str);
07026       return -1;
07027    }
07028 
07029    return 0;
07030 }
07031 
07032 static int dahdi_func_write(struct ast_channel *chan, const char *function, char *data, const char *value)
07033 {
07034    struct dahdi_pvt *p = chan->tech_pvt;
07035    int res = 0;
07036 
07037    if (!p) {
07038       /* No private structure! */
07039       return -1;
07040    }
07041 
07042    if (!strcasecmp(data, "buffers")) {
07043       int num_bufs, policy;
07044 
07045       if (!(parse_buffers_policy(value, &num_bufs, &policy))) {
07046          struct dahdi_bufferinfo bi = {
07047             .txbufpolicy = policy,
07048             .rxbufpolicy = policy,
07049             .bufsize = p->bufsize,
07050             .numbufs = num_bufs,
07051          };
07052          int bpres;
07053 
07054          if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
07055             ast_log(LOG_WARNING, "Channel '%d' unable to override buffer policy: %s\n", p->channel, strerror(errno));
07056          } else {
07057             p->bufferoverrideinuse = 1;
07058          }
07059       } else {
07060          res = -1;
07061       }
07062    } else if (!strcasecmp(data, "echocan_mode")) {
07063       if (!strcasecmp(value, "on")) {
07064          ast_mutex_lock(&p->lock);
07065          dahdi_enable_ec(p);
07066          ast_mutex_unlock(&p->lock);
07067       } else if (!strcasecmp(value, "off")) {
07068          ast_mutex_lock(&p->lock);
07069          dahdi_disable_ec(p);
07070          ast_mutex_unlock(&p->lock);
07071 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
07072       } else if (!strcasecmp(value, "fax")) {
07073          int blah = 1;
07074 
07075          ast_mutex_lock(&p->lock);
07076          if (!p->echocanon) {
07077             dahdi_enable_ec(p);
07078          }
07079          if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_FAX_MODE, &blah)) {
07080             ast_log(LOG_WARNING, "Unable to place echocan into fax mode on channel %d: %s\n", p->channel, strerror(errno));
07081          }
07082          ast_mutex_unlock(&p->lock);
07083       } else if (!strcasecmp(value, "voice")) {
07084          int blah = 0;
07085 
07086          ast_mutex_lock(&p->lock);
07087          if (!p->echocanon) {
07088             dahdi_enable_ec(p);
07089          }
07090          if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_FAX_MODE, &blah)) {
07091             ast_log(LOG_WARNING, "Unable to place echocan into voice mode on channel %d: %s\n", p->channel, strerror(errno));
07092          }
07093          ast_mutex_unlock(&p->lock);
07094 #endif
07095       } else {
07096          ast_log(LOG_WARNING, "Unsupported value '%s' provided for '%s' item.\n", value, data);
07097          res = -1;
07098       }
07099    } else {
07100       res = -1;
07101    }
07102 
07103    return res;
07104 }
07105 
07106 static void dahdi_unlink(struct dahdi_pvt *slave, struct dahdi_pvt *master, int needlock)
07107 {
07108    /* Unlink a specific slave or all slaves/masters from a given master */
07109    int x;
07110    int hasslaves;
07111    if (!master)
07112       return;
07113    if (needlock) {
07114       ast_mutex_lock(&master->lock);
07115       if (slave) {
07116          while (ast_mutex_trylock(&slave->lock)) {
07117             DEADLOCK_AVOIDANCE(&master->lock);
07118          }
07119       }
07120    }
07121    hasslaves = 0;
07122    for (x = 0; x < MAX_SLAVES; x++) {
07123       if (master->slaves[x]) {
07124          if (!slave || (master->slaves[x] == slave)) {
07125             /* Take slave out of the conference */
07126             ast_debug(1, "Unlinking slave %d from %d\n", master->slaves[x]->channel, master->channel);
07127             conf_del(master, &master->slaves[x]->subs[SUB_REAL], SUB_REAL);
07128             conf_del(master->slaves[x], &master->subs[SUB_REAL], SUB_REAL);
07129             master->slaves[x]->master = NULL;
07130             master->slaves[x] = NULL;
07131          } else
07132             hasslaves = 1;
07133       }
07134       if (!hasslaves)
07135          master->inconference = 0;
07136    }
07137    if (!slave) {
07138       if (master->master) {
07139          /* Take master out of the conference */
07140          conf_del(master->master, &master->subs[SUB_REAL], SUB_REAL);
07141          conf_del(master, &master->master->subs[SUB_REAL], SUB_REAL);
07142          hasslaves = 0;
07143          for (x = 0; x < MAX_SLAVES; x++) {
07144             if (master->master->slaves[x] == master)
07145                master->master->slaves[x] = NULL;
07146             else if (master->master->slaves[x])
07147                hasslaves = 1;
07148          }
07149          if (!hasslaves)
07150             master->master->inconference = 0;
07151       }
07152       master->master = NULL;
07153    }
07154    update_conf(master);
07155    if (needlock) {
07156       if (slave)
07157          ast_mutex_unlock(&slave->lock);
07158       ast_mutex_unlock(&master->lock);
07159    }
07160 }
07161 
07162 static void dahdi_link(struct dahdi_pvt *slave, struct dahdi_pvt *master) {
07163    int x;
07164    if (!slave || !master) {
07165       ast_log(LOG_WARNING, "Tried to link to/from NULL??\n");
07166       return;
07167    }
07168    for (x = 0; x < MAX_SLAVES; x++) {
07169       if (!master->slaves[x]) {
07170          master->slaves[x] = slave;
07171          break;
07172       }
07173    }
07174    if (x >= MAX_SLAVES) {
07175       ast_log(LOG_WARNING, "Replacing slave %d with new slave, %d\n", master->slaves[MAX_SLAVES - 1]->channel, slave->channel);
07176       master->slaves[MAX_SLAVES - 1] = slave;
07177    }
07178    if (slave->master)
07179       ast_log(LOG_WARNING, "Replacing master %d with new master, %d\n", slave->master->channel, master->channel);
07180    slave->master = master;
07181 
07182    ast_debug(1, "Making %d slave to master %d at %d\n", slave->channel, master->channel, x);
07183 }
07184 
07185 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)
07186 {
07187    struct ast_channel *who;
07188    struct dahdi_pvt *p0, *p1, *op0, *op1;
07189    struct dahdi_pvt *master = NULL, *slave = NULL;
07190    struct ast_frame *f;
07191    int inconf = 0;
07192    int nothingok = 1;
07193    int ofd0, ofd1;
07194    int oi0, oi1, i0 = -1, i1 = -1, t0, t1;
07195    int os0 = -1, os1 = -1;
07196    int priority = 0;
07197    struct ast_channel *oc0, *oc1;
07198    enum ast_bridge_result res;
07199 #ifdef PRI_2BCT
07200    int triedtopribridge = 0;
07201    q931_call *q931c0;
07202    q931_call *q931c1;
07203 #endif
07204 
07205    /* For now, don't attempt to native bridge if either channel needs DTMF detection.
07206       There is code below to handle it properly until DTMF is actually seen,
07207       but due to currently unresolved issues it's ignored...
07208    */
07209 
07210    if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1))
07211       return AST_BRIDGE_FAILED_NOWARN;
07212 
07213    ast_channel_lock(c0);
07214    while (ast_channel_trylock(c1)) {
07215       CHANNEL_DEADLOCK_AVOIDANCE(c0);
07216    }
07217 
07218    p0 = c0->tech_pvt;
07219    p1 = c1->tech_pvt;
07220    /* cant do pseudo-channels here */
07221    if (!p0 || (!p0->sig) || !p1 || (!p1->sig)) {
07222       ast_channel_unlock(c0);
07223       ast_channel_unlock(c1);
07224       return AST_BRIDGE_FAILED_NOWARN;
07225    }
07226 
07227    oi0 = dahdi_get_index(c0, p0, 0);
07228    oi1 = dahdi_get_index(c1, p1, 0);
07229    if ((oi0 < 0) || (oi1 < 0)) {
07230       ast_channel_unlock(c0);
07231       ast_channel_unlock(c1);
07232       return AST_BRIDGE_FAILED;
07233    }
07234 
07235    op0 = p0 = c0->tech_pvt;
07236    op1 = p1 = c1->tech_pvt;
07237    ofd0 = c0->fds[0];
07238    ofd1 = c1->fds[0];
07239    oc0 = p0->owner;
07240    oc1 = p1->owner;
07241 
07242    if (ast_mutex_trylock(&p0->lock)) {
07243       /* Don't block, due to potential for deadlock */
07244       ast_channel_unlock(c0);
07245       ast_channel_unlock(c1);
07246       ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
07247       return AST_BRIDGE_RETRY;
07248    }
07249    if (ast_mutex_trylock(&p1->lock)) {
07250       /* Don't block, due to potential for deadlock */
07251       ast_mutex_unlock(&p0->lock);
07252       ast_channel_unlock(c0);
07253       ast_channel_unlock(c1);
07254       ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
07255       return AST_BRIDGE_RETRY;
07256    }
07257 
07258    if ((p0->callwaiting && p0->callwaitingcallerid)
07259       || (p1->callwaiting && p1->callwaitingcallerid)) {
07260       /*
07261        * Call Waiting Caller ID requires DTMF detection to know if it
07262        * can send the CID spill.
07263        *
07264        * For now, don't attempt to native bridge if either channel
07265        * needs DTMF detection.  There is code below to handle it
07266        * properly until DTMF is actually seen, but due to currently
07267        * unresolved issues it's ignored...
07268        */
07269       ast_mutex_unlock(&p0->lock);
07270       ast_mutex_unlock(&p1->lock);
07271       ast_channel_unlock(c0);
07272       ast_channel_unlock(c1);
07273       return AST_BRIDGE_FAILED_NOWARN;
07274    }
07275 
07276 #if defined(HAVE_PRI)
07277    if ((dahdi_sig_pri_lib_handles(p0->sig)
07278          && ((struct sig_pri_chan *) p0->sig_pvt)->no_b_channel)
07279       || (dahdi_sig_pri_lib_handles(p1->sig)
07280          && ((struct sig_pri_chan *) p1->sig_pvt)->no_b_channel)) {
07281       /*
07282        * PRI nobch channels (hold and call waiting) are equivalent to
07283        * pseudo channels and cannot be done here.
07284        */
07285       ast_mutex_unlock(&p0->lock);
07286       ast_mutex_unlock(&p1->lock);
07287       ast_channel_unlock(c0);
07288       ast_channel_unlock(c1);
07289       return AST_BRIDGE_FAILED_NOWARN;
07290    }
07291 #endif   /* defined(HAVE_PRI) */
07292 
07293    if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
07294       if (p0->owner && p1->owner) {
07295          /* If we don't have a call-wait in a 3-way, and we aren't in a 3-way, we can be master */
07296          if (!p0->subs[SUB_CALLWAIT].inthreeway && !p1->subs[SUB_REAL].inthreeway) {
07297             master = p0;
07298             slave = p1;
07299             inconf = 1;
07300          } else if (!p1->subs[SUB_CALLWAIT].inthreeway && !p0->subs[SUB_REAL].inthreeway) {
07301             master = p1;
07302             slave = p0;
07303             inconf = 1;
07304          } else {
07305             ast_log(LOG_WARNING, "Huh?  Both calls are callwaits or 3-ways?  That's clever...?\n");
07306             ast_log(LOG_WARNING, "p0: chan %d/%d/CW%d/3W%d, p1: chan %d/%d/CW%d/3W%d\n",
07307                p0->channel,
07308                oi0, (p0->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
07309                p0->subs[SUB_REAL].inthreeway, p0->channel,
07310                oi0, (p1->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
07311                p1->subs[SUB_REAL].inthreeway);
07312          }
07313          nothingok = 0;
07314       }
07315    } else if ((oi0 == SUB_REAL) && (oi1 == SUB_THREEWAY)) {
07316       if (p1->subs[SUB_THREEWAY].inthreeway) {
07317          master = p1;
07318          slave = p0;
07319          nothingok = 0;
07320       }
07321    } else if ((oi0 == SUB_THREEWAY) && (oi1 == SUB_REAL)) {
07322       if (p0->subs[SUB_THREEWAY].inthreeway) {
07323          master = p0;
07324          slave = p1;
07325          nothingok = 0;
07326       }
07327    } else if ((oi0 == SUB_REAL) && (oi1 == SUB_CALLWAIT)) {
07328       /* We have a real and a call wait.  If we're in a three way call, put us in it, otherwise,
07329          don't put us in anything */
07330       if (p1->subs[SUB_CALLWAIT].inthreeway) {
07331          master = p1;
07332          slave = p0;
07333          nothingok = 0;
07334       }
07335    } else if ((oi0 == SUB_CALLWAIT) && (oi1 == SUB_REAL)) {
07336       /* Same as previous */
07337       if (p0->subs[SUB_CALLWAIT].inthreeway) {
07338          master = p0;
07339          slave = p1;
07340          nothingok = 0;
07341       }
07342    }
07343    ast_debug(1, "master: %d, slave: %d, nothingok: %d\n",
07344       master ? master->channel : 0, slave ? slave->channel : 0, nothingok);
07345    if (master && slave) {
07346       /* Stop any tones, or play ringtone as appropriate.  If they're bridged
07347          in an active threeway call with a channel that is ringing, we should
07348          indicate ringing. */
07349       if ((oi1 == SUB_THREEWAY) &&
07350          p1->subs[SUB_THREEWAY].inthreeway &&
07351          p1->subs[SUB_REAL].owner &&
07352          p1->subs[SUB_REAL].inthreeway &&
07353          (p1->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
07354          ast_debug(1,
07355             "Playing ringback on %d/%d(%s) since %d/%d(%s) is in a ringing three-way\n",
07356             p0->channel, oi0, c0->name, p1->channel, oi1, c1->name);
07357          tone_zone_play_tone(p0->subs[oi0].dfd, DAHDI_TONE_RINGTONE);
07358          os1 = p1->subs[SUB_REAL].owner->_state;
07359       } else {
07360          ast_debug(1, "Stopping tones on %d/%d(%s) talking to %d/%d(%s)\n",
07361             p0->channel, oi0, c0->name, p1->channel, oi1, c1->name);
07362          tone_zone_play_tone(p0->subs[oi0].dfd, -1);
07363       }
07364       if ((oi0 == SUB_THREEWAY) &&
07365          p0->subs[SUB_THREEWAY].inthreeway &&
07366          p0->subs[SUB_REAL].owner &&
07367          p0->subs[SUB_REAL].inthreeway &&
07368          (p0->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
07369          ast_debug(1,
07370             "Playing ringback on %d/%d(%s) since %d/%d(%s) is in a ringing three-way\n",
07371             p1->channel, oi1, c1->name, p0->channel, oi0, c0->name);
07372          tone_zone_play_tone(p1->subs[oi1].dfd, DAHDI_TONE_RINGTONE);
07373          os0 = p0->subs[SUB_REAL].owner->_state;
07374       } else {
07375          ast_debug(1, "Stopping tones on %d/%d(%s) talking to %d/%d(%s)\n",
07376             p1->channel, oi1, c1->name, p0->channel, oi0, c0->name);
07377          tone_zone_play_tone(p1->subs[oi1].dfd, -1);
07378       }
07379       if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
07380          if (!p0->echocanbridged || !p1->echocanbridged) {
07381             /* Disable echo cancellation if appropriate */
07382             dahdi_disable_ec(p0);
07383             dahdi_disable_ec(p1);
07384          }
07385       }
07386       dahdi_link(slave, master);
07387       master->inconference = inconf;
07388    } else if (!nothingok)
07389       ast_log(LOG_WARNING, "Can't link %d/%s with %d/%s\n", p0->channel, subnames[oi0], p1->channel, subnames[oi1]);
07390 
07391    update_conf(p0);
07392    update_conf(p1);
07393    t0 = p0->subs[SUB_REAL].inthreeway;
07394    t1 = p1->subs[SUB_REAL].inthreeway;
07395 
07396    ast_mutex_unlock(&p0->lock);
07397    ast_mutex_unlock(&p1->lock);
07398 
07399    ast_channel_unlock(c0);
07400    ast_channel_unlock(c1);
07401 
07402    /* Native bridge failed */
07403    if ((!master || !slave) && !nothingok) {
07404       dahdi_enable_ec(p0);
07405       dahdi_enable_ec(p1);
07406       return AST_BRIDGE_FAILED;
07407    }
07408 
07409    ast_verb(3, "Native bridging %s and %s\n", c0->name, c1->name);
07410 
07411    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
07412       disable_dtmf_detect(op0);
07413 
07414    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
07415       disable_dtmf_detect(op1);
07416 
07417    for (;;) {
07418       struct ast_channel *c0_priority[2] = {c0, c1};
07419       struct ast_channel *c1_priority[2] = {c1, c0};
07420 
07421       /* Here's our main loop...  Start by locking things, looking for private parts,
07422          and then balking if anything is wrong */
07423 
07424       ast_channel_lock(c0);
07425       while (ast_channel_trylock(c1)) {
07426          CHANNEL_DEADLOCK_AVOIDANCE(c0);
07427       }
07428 
07429       p0 = c0->tech_pvt;
07430       p1 = c1->tech_pvt;
07431 
07432       if (op0 == p0)
07433          i0 = dahdi_get_index(c0, p0, 1);
07434       if (op1 == p1)
07435          i1 = dahdi_get_index(c1, p1, 1);
07436 
07437       ast_channel_unlock(c0);
07438       ast_channel_unlock(c1);
07439 
07440       if (!timeoutms ||
07441          (op0 != p0) ||
07442          (op1 != p1) ||
07443          (ofd0 != c0->fds[0]) ||
07444          (ofd1 != c1->fds[0]) ||
07445          (p0->subs[SUB_REAL].owner && (os0 > -1) && (os0 != p0->subs[SUB_REAL].owner->_state)) ||
07446          (p1->subs[SUB_REAL].owner && (os1 > -1) && (os1 != p1->subs[SUB_REAL].owner->_state)) ||
07447          (oc0 != p0->owner) ||
07448          (oc1 != p1->owner) ||
07449          (t0 != p0->subs[SUB_REAL].inthreeway) ||
07450          (t1 != p1->subs[SUB_REAL].inthreeway) ||
07451          (oi0 != i0) ||
07452          (oi1 != i1)) {
07453          ast_debug(1, "Something changed out on %d/%d to %d/%d, returning -3 to restart\n",
07454             op0->channel, oi0, op1->channel, oi1);
07455          res = AST_BRIDGE_RETRY;
07456          goto return_from_bridge;
07457       }
07458 
07459 #ifdef PRI_2BCT
07460       if (!triedtopribridge) {
07461          triedtopribridge = 1;
07462          if (p0->pri && p0->pri == p1->pri && p0->pri->transfer) {
07463             ast_mutex_lock(&p0->pri->lock);
07464             switch (p0->sig) {
07465             case SIG_PRI_LIB_HANDLE_CASES:
07466                q931c0 = ((struct sig_pri_chan *) (p0->sig_pvt))->call;
07467                break;
07468             default:
07469                q931c0 = NULL;
07470                break;
07471             }
07472             switch (p1->sig) {
07473             case SIG_PRI_LIB_HANDLE_CASES:
07474                q931c1 = ((struct sig_pri_chan *) (p1->sig_pvt))->call;
07475                break;
07476             default:
07477                q931c1 = NULL;
07478                break;
07479             }
07480             if (q931c0 && q931c1) {
07481                pri_channel_bridge(q931c0, q931c1);
07482             }
07483             ast_mutex_unlock(&p0->pri->lock);
07484          }
07485       }
07486 #endif
07487 
07488       who = ast_waitfor_n(priority ? c0_priority : c1_priority, 2, &timeoutms);
07489       if (!who) {
07490          ast_debug(1, "Ooh, empty read...\n");
07491          continue;
07492       }
07493       f = ast_read(who);
07494       if (!f || (f->frametype == AST_FRAME_CONTROL)) {
07495          *fo = f;
07496          *rc = who;
07497          res = AST_BRIDGE_COMPLETE;
07498          goto return_from_bridge;
07499       }
07500       if (f->frametype == AST_FRAME_DTMF) {
07501          if ((who == c0) && p0->pulsedial) {
07502             ast_write(c1, f);
07503          } else if ((who == c1) && p1->pulsedial) {
07504             ast_write(c0, f);
07505          } else {
07506             *fo = f;
07507             *rc = who;
07508             res = AST_BRIDGE_COMPLETE;
07509             goto return_from_bridge;
07510          }
07511       }
07512       ast_frfree(f);
07513 
07514       /* Swap who gets priority */
07515       priority = !priority;
07516    }
07517 
07518 return_from_bridge:
07519    if (op0 == p0)
07520       dahdi_enable_ec(p0);
07521 
07522    if (op1 == p1)
07523       dahdi_enable_ec(p1);
07524 
07525    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
07526       enable_dtmf_detect(op0);
07527 
07528    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
07529       enable_dtmf_detect(op1);
07530 
07531    dahdi_unlink(slave, master, 1);
07532 
07533    return res;
07534 }
07535 
07536 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
07537 {
07538    struct dahdi_pvt *p = newchan->tech_pvt;
07539    int x;
07540 
07541    ast_mutex_lock(&p->lock);
07542 
07543    ast_debug(1, "New owner for channel %d is %s\n", p->channel, newchan->name);
07544    if (p->owner == oldchan) {
07545       p->owner = newchan;
07546    }
07547    for (x = 0; x < 3; x++) {
07548       if (p->subs[x].owner == oldchan) {
07549          if (!x) {
07550             dahdi_unlink(NULL, p, 0);
07551          }
07552          p->subs[x].owner = newchan;
07553       }
07554    }
07555    if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
07556       analog_fixup(oldchan, newchan, p->sig_pvt);
07557 #if defined(HAVE_PRI)
07558    } else if (dahdi_sig_pri_lib_handles(p->sig)) {
07559       sig_pri_fixup(oldchan, newchan, p->sig_pvt);
07560 #endif   /* defined(HAVE_PRI) */
07561 #if defined(HAVE_SS7)
07562    } else if (p->sig == SIG_SS7) {
07563       sig_ss7_fixup(oldchan, newchan, p->sig_pvt);
07564 #endif   /* defined(HAVE_SS7) */
07565    }
07566    update_conf(p);
07567 
07568    ast_mutex_unlock(&p->lock);
07569 
07570    if (newchan->_state == AST_STATE_RINGING) {
07571       dahdi_indicate(newchan, AST_CONTROL_RINGING, NULL, 0);
07572    }
07573    return 0;
07574 }
07575 
07576 static int dahdi_ring_phone(struct dahdi_pvt *p)
07577 {
07578    int x;
07579    int res;
07580    /* Make sure our transmit state is on hook */
07581    x = 0;
07582    x = DAHDI_ONHOOK;
07583    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
07584    do {
07585       x = DAHDI_RING;
07586       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
07587       if (res) {
07588          switch (errno) {
07589          case EBUSY:
07590          case EINTR:
07591             /* Wait just in case */
07592             usleep(10000);
07593             continue;
07594          case EINPROGRESS:
07595             res = 0;
07596             break;
07597          default:
07598             ast_log(LOG_WARNING, "Couldn't ring the phone: %s\n", strerror(errno));
07599             res = 0;
07600          }
07601       }
07602    } while (res);
07603    return res;
07604 }
07605 
07606 static void *analog_ss_thread(void *data);
07607 
07608 static int attempt_transfer(struct dahdi_pvt *p)
07609 {
07610    /* In order to transfer, we need at least one of the channels to
07611       actually be in a call bridge.  We can't conference two applications
07612       together (but then, why would we want to?) */
07613    if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
07614       /* The three-way person we're about to transfer to could still be in MOH, so
07615          stop if now if appropriate */
07616       if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner))
07617          ast_queue_control(p->subs[SUB_THREEWAY].owner, AST_CONTROL_UNHOLD);
07618       if (p->subs[SUB_REAL].owner->_state == AST_STATE_RINGING) {
07619          ast_indicate(ast_bridged_channel(p->subs[SUB_REAL].owner), AST_CONTROL_RINGING);
07620       }
07621       if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RING) {
07622          tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE);
07623       }
07624        if (ast_channel_masquerade(p->subs[SUB_THREEWAY].owner, ast_bridged_channel(p->subs[SUB_REAL].owner))) {
07625          ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
07626                ast_bridged_channel(p->subs[SUB_REAL].owner)->name, p->subs[SUB_THREEWAY].owner->name);
07627          return -1;
07628       }
07629       /* Orphan the channel after releasing the lock */
07630       ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
07631       unalloc_sub(p, SUB_THREEWAY);
07632    } else if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
07633       ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
07634       if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RINGING) {
07635          ast_indicate(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), AST_CONTROL_RINGING);
07636       }
07637       if (p->subs[SUB_REAL].owner->_state == AST_STATE_RING) {
07638          tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
07639       }
07640       if (ast_channel_masquerade(p->subs[SUB_REAL].owner, ast_bridged_channel(p->subs[SUB_THREEWAY].owner))) {
07641          ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
07642                ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->name, p->subs[SUB_REAL].owner->name);
07643          return -1;
07644       }
07645       /* Three-way is now the REAL */
07646       swap_subs(p, SUB_THREEWAY, SUB_REAL);
07647       ast_channel_unlock(p->subs[SUB_REAL].owner);
07648       unalloc_sub(p, SUB_THREEWAY);
07649       /* Tell the caller not to hangup */
07650       return 1;
07651    } else {
07652       ast_debug(1, "Neither %s nor %s are in a bridge, nothing to transfer\n",
07653          p->subs[SUB_REAL].owner->name, p->subs[SUB_THREEWAY].owner->name);
07654       p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
07655       return -1;
07656    }
07657    return 0;
07658 }
07659 
07660 static int check_for_conference(struct dahdi_pvt *p)
07661 {
07662    struct dahdi_confinfo ci;
07663    /* Fine if we already have a master, etc */
07664    if (p->master || (p->confno > -1))
07665       return 0;
07666    memset(&ci, 0, sizeof(ci));
07667    if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
07668       ast_log(LOG_WARNING, "Failed to get conference info on channel %d: %s\n", p->channel, strerror(errno));
07669       return 0;
07670    }
07671    /* If we have no master and don't have a confno, then
07672       if we're in a conference, it's probably a MeetMe room or
07673       some such, so don't let us 3-way out! */
07674    if ((p->subs[SUB_REAL].curconf.confno != ci.confno) || (p->subs[SUB_REAL].curconf.confmode != ci.confmode)) {
07675       ast_verb(3, "Avoiding 3-way call when in an external conference\n");
07676       return 1;
07677    }
07678    return 0;
07679 }
07680 
07681 /*! Checks channel for alarms
07682  * \param p a channel to check for alarms.
07683  * \returns the alarms on the span to which the channel belongs, or alarms on
07684  *          the channel if no span alarms.
07685  */
07686 static int get_alarms(struct dahdi_pvt *p)
07687 {
07688    int res;
07689    struct dahdi_spaninfo zi;
07690    struct dahdi_params params;
07691 
07692    memset(&zi, 0, sizeof(zi));
07693    zi.spanno = p->span;
07694 
07695    if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SPANSTAT, &zi)) >= 0) {
07696       if (zi.alarms != DAHDI_ALARM_NONE)
07697          return zi.alarms;
07698    } else {
07699       ast_log(LOG_WARNING, "Unable to determine alarm on channel %d: %s\n", p->channel, strerror(errno));
07700       return 0;
07701    }
07702 
07703    /* No alarms on the span. Check for channel alarms. */
07704    memset(&params, 0, sizeof(params));
07705    if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &params)) >= 0)
07706       return params.chan_alarms;
07707 
07708    ast_log(LOG_WARNING, "Unable to determine alarm on channel %d\n", p->channel);
07709 
07710    return DAHDI_ALARM_NONE;
07711 }
07712 
07713 static void dahdi_handle_dtmf(struct ast_channel *ast, int idx, struct ast_frame **dest)
07714 {
07715    struct dahdi_pvt *p = ast->tech_pvt;
07716    struct ast_frame *f = *dest;
07717 
07718    ast_debug(1, "%s DTMF digit: 0x%02X '%c' on %s\n",
07719       f->frametype == AST_FRAME_DTMF_BEGIN ? "Begin" : "End",
07720       f->subclass.integer, f->subclass.integer, ast->name);
07721 
07722    if (p->confirmanswer) {
07723       if (f->frametype == AST_FRAME_DTMF_END) {
07724          ast_debug(1, "Confirm answer on %s!\n", ast->name);
07725          /* Upon receiving a DTMF digit, consider this an answer confirmation instead
07726             of a DTMF digit */
07727          p->subs[idx].f.frametype = AST_FRAME_CONTROL;
07728          p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
07729          /* Reset confirmanswer so DTMF's will behave properly for the duration of the call */
07730          p->confirmanswer = 0;
07731       } else {
07732          p->subs[idx].f.frametype = AST_FRAME_NULL;
07733          p->subs[idx].f.subclass.integer = 0;
07734       }
07735       *dest = &p->subs[idx].f;
07736    } else if (p->callwaitcas) {
07737       if (f->frametype == AST_FRAME_DTMF_END) {
07738          if ((f->subclass.integer == 'A') || (f->subclass.integer == 'D')) {
07739             ast_debug(1, "Got some DTMF, but it's for the CAS\n");
07740             ast_free(p->cidspill);
07741             p->cidspill = NULL;
07742             send_cwcidspill(p);
07743          }
07744          p->callwaitcas = 0;
07745       }
07746       p->subs[idx].f.frametype = AST_FRAME_NULL;
07747       p->subs[idx].f.subclass.integer = 0;
07748       *dest = &p->subs[idx].f;
07749    } else if (f->subclass.integer == 'f') {
07750       if (f->frametype == AST_FRAME_DTMF_END) {
07751          /* Fax tone -- Handle and return NULL */
07752          if ((p->callprogress & CALLPROGRESS_FAX) && !p->faxhandled) {
07753             /* If faxbuffers are configured, use them for the fax transmission */
07754             if (p->usefaxbuffers && !p->bufferoverrideinuse) {
07755                struct dahdi_bufferinfo bi = {
07756                   .txbufpolicy = p->faxbuf_policy,
07757                   .bufsize = p->bufsize,
07758                   .numbufs = p->faxbuf_no
07759                };
07760                int res;
07761 
07762                if ((res = ioctl(p->subs[idx].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
07763                   ast_log(LOG_WARNING, "Channel '%s' unable to set buffer policy, reason: %s\n", ast->name, strerror(errno));
07764                } else {
07765                   p->bufferoverrideinuse = 1;
07766                }
07767             }
07768             p->faxhandled = 1;
07769             if (p->dsp) {
07770                p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
07771                ast_dsp_set_features(p->dsp, p->dsp_features);
07772                ast_debug(1, "Disabling FAX tone detection on %s after tone received\n", ast->name);
07773             }
07774             if (strcmp(ast->exten, "fax")) {
07775                const char *target_context = S_OR(ast->macrocontext, ast->context);
07776 
07777                /* We need to unlock 'ast' here because ast_exists_extension has the
07778                 * potential to start autoservice on the channel. Such action is prone
07779                 * to deadlock.
07780                 */
07781                ast_mutex_unlock(&p->lock);
07782                ast_channel_unlock(ast);
07783                if (ast_exists_extension(ast, target_context, "fax", 1,
07784                   S_COR(ast->caller.id.number.valid, ast->caller.id.number.str, NULL))) {
07785                   ast_channel_lock(ast);
07786                   ast_mutex_lock(&p->lock);
07787                   ast_verb(3, "Redirecting %s to fax extension\n", ast->name);
07788                   /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
07789                   pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten);
07790                   if (ast_async_goto(ast, target_context, "fax", 1))
07791                      ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context);
07792                } else {
07793                   ast_channel_lock(ast);
07794                   ast_mutex_lock(&p->lock);
07795                   ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
07796                }
07797             } else {
07798                ast_debug(1, "Already in a fax extension, not redirecting\n");
07799             }
07800          } else {
07801             ast_debug(1, "Fax already handled\n");
07802          }
07803          dahdi_confmute(p, 0);
07804       }
07805       p->subs[idx].f.frametype = AST_FRAME_NULL;
07806       p->subs[idx].f.subclass.integer = 0;
07807       *dest = &p->subs[idx].f;
07808    }
07809 }
07810 
07811 static void handle_alarms(struct dahdi_pvt *p, int alms)
07812 {
07813    const char *alarm_str = alarm2str(alms);
07814 
07815    if (report_alarms & REPORT_CHANNEL_ALARMS) {
07816       ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", p->channel, alarm_str);
07817       manager_event(EVENT_FLAG_SYSTEM, "Alarm",
07818                  "Alarm: %s\r\n"
07819                  "Channel: %d\r\n",
07820                  alarm_str, p->channel);
07821    }
07822 
07823    if (report_alarms & REPORT_SPAN_ALARMS && p->manages_span_alarms) {
07824       ast_log(LOG_WARNING, "Detected alarm on span %d: %s\n", p->span, alarm_str);
07825       manager_event(EVENT_FLAG_SYSTEM, "SpanAlarm",
07826                  "Alarm: %s\r\n"
07827                  "Span: %d\r\n",
07828                  alarm_str, p->span);
07829    }
07830 }
07831 
07832 static struct ast_frame *dahdi_handle_event(struct ast_channel *ast)
07833 {
07834    int res, x;
07835    int idx, mysig;
07836    char *c;
07837    struct dahdi_pvt *p = ast->tech_pvt;
07838    pthread_t threadid;
07839    struct ast_channel *chan;
07840    struct ast_frame *f;
07841 
07842    idx = dahdi_get_index(ast, p, 0);
07843    mysig = p->sig;
07844    if (p->outsigmod > -1)
07845       mysig = p->outsigmod;
07846    p->subs[idx].f.frametype = AST_FRAME_NULL;
07847    p->subs[idx].f.subclass.integer = 0;
07848    p->subs[idx].f.datalen = 0;
07849    p->subs[idx].f.samples = 0;
07850    p->subs[idx].f.mallocd = 0;
07851    p->subs[idx].f.offset = 0;
07852    p->subs[idx].f.src = "dahdi_handle_event";
07853    p->subs[idx].f.data.ptr = NULL;
07854    f = &p->subs[idx].f;
07855 
07856    if (idx < 0)
07857       return &p->subs[idx].f;
07858    if (p->fake_event) {
07859       res = p->fake_event;
07860       p->fake_event = 0;
07861    } else
07862       res = dahdi_get_event(p->subs[idx].dfd);
07863 
07864    ast_debug(1, "Got event %s(%d) on channel %d (index %d)\n", event2str(res), res, p->channel, idx);
07865 
07866    if (res & (DAHDI_EVENT_PULSEDIGIT | DAHDI_EVENT_DTMFUP)) {
07867       p->pulsedial = (res & DAHDI_EVENT_PULSEDIGIT) ? 1 : 0;
07868       ast_debug(1, "Detected %sdigit '%c'\n", p->pulsedial ? "pulse ": "", res & 0xff);
07869 #if defined(HAVE_PRI)
07870       if (dahdi_sig_pri_lib_handles(p->sig)
07871          && ((struct sig_pri_chan *) p->sig_pvt)->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING
07872          && p->pri
07873          && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
07874          /* absorb event */
07875       } else
07876 #endif   /* defined(HAVE_PRI) */
07877       {
07878          /* Unmute conference */
07879          dahdi_confmute(p, 0);
07880          p->subs[idx].f.frametype = AST_FRAME_DTMF_END;
07881          p->subs[idx].f.subclass.integer = res & 0xff;
07882          dahdi_handle_dtmf(ast, idx, &f);
07883       }
07884       return f;
07885    }
07886 
07887    if (res & DAHDI_EVENT_DTMFDOWN) {
07888       ast_debug(1, "DTMF Down '%c'\n", res & 0xff);
07889 #if defined(HAVE_PRI)
07890       if (dahdi_sig_pri_lib_handles(p->sig)
07891          && ((struct sig_pri_chan *) p->sig_pvt)->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING
07892          && p->pri
07893          && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
07894          /* absorb event */
07895       } else
07896 #endif   /* defined(HAVE_PRI) */
07897       {
07898          /* Mute conference */
07899          dahdi_confmute(p, 1);
07900          p->subs[idx].f.frametype = AST_FRAME_DTMF_BEGIN;
07901          p->subs[idx].f.subclass.integer = res & 0xff;
07902          dahdi_handle_dtmf(ast, idx, &f);
07903       }
07904       return &p->subs[idx].f;
07905    }
07906 
07907    switch (res) {
07908    case DAHDI_EVENT_EC_DISABLED:
07909       ast_verb(3, "Channel %d echo canceler disabled.\n", p->channel);
07910       p->echocanon = 0;
07911       break;
07912 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
07913    case DAHDI_EVENT_TX_CED_DETECTED:
07914       ast_verb(3, "Channel %d detected a CED tone towards the network.\n", p->channel);
07915       break;
07916    case DAHDI_EVENT_RX_CED_DETECTED:
07917       ast_verb(3, "Channel %d detected a CED tone from the network.\n", p->channel);
07918       break;
07919    case DAHDI_EVENT_EC_NLP_DISABLED:
07920       ast_verb(3, "Channel %d echo canceler disabled its NLP.\n", p->channel);
07921       break;
07922    case DAHDI_EVENT_EC_NLP_ENABLED:
07923       ast_verb(3, "Channel %d echo canceler enabled its NLP.\n", p->channel);
07924       break;
07925 #endif
07926    case DAHDI_EVENT_BITSCHANGED:
07927 #ifdef HAVE_OPENR2
07928       if (p->sig != SIG_MFCR2) {
07929          ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig));
07930       } else {
07931          ast_log(LOG_DEBUG, "bits changed in chan %d\n", p->channel);
07932          openr2_chan_handle_cas(p->r2chan);
07933       }
07934 #else
07935       ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig));
07936 #endif
07937    case DAHDI_EVENT_PULSE_START:
07938       /* Stop tone if there's a pulse start and the PBX isn't started */
07939       if (!ast->pbx)
07940          tone_zone_play_tone(p->subs[idx].dfd, -1);
07941       break;
07942    case DAHDI_EVENT_DIALCOMPLETE:
07943       /* DAHDI has completed dialing all digits sent using DAHDI_DIAL. */
07944 #if defined(HAVE_PRI)
07945       if (dahdi_sig_pri_lib_handles(p->sig)) {
07946          if (p->inalarm) {
07947             break;
07948          }
07949          if (ioctl(p->subs[idx].dfd, DAHDI_DIALING, &x) == -1) {
07950             ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed on %s: %s\n", ast->name,
07951                strerror(errno));
07952             return NULL;
07953          }
07954          if (x) {
07955             /* Still dialing in DAHDI driver */
07956             break;
07957          }
07958          /*
07959           * The ast channel is locked and the private may be locked more
07960           * than once.
07961           */
07962          sig_pri_dial_complete(p->sig_pvt, ast);
07963          break;
07964       }
07965 #endif   /* defined(HAVE_PRI) */
07966 #ifdef HAVE_OPENR2
07967       if ((p->sig & SIG_MFCR2) && p->r2chan && ast->_state != AST_STATE_UP) {
07968          /* we don't need to do anything for this event for R2 signaling
07969             if the call is being setup */
07970          break;
07971       }
07972 #endif
07973       if (p->inalarm) break;
07974       if ((p->radio || (p->oprmode < 0))) break;
07975       if (ioctl(p->subs[idx].dfd,DAHDI_DIALING,&x) == -1) {
07976          ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed on %s: %s\n",ast->name, strerror(errno));
07977          return NULL;
07978       }
07979       if (!x) { /* if not still dialing in driver */
07980          dahdi_enable_ec(p);
07981          if (p->echobreak) {
07982             dahdi_train_ec(p);
07983             ast_copy_string(p->dop.dialstr, p->echorest, sizeof(p->dop.dialstr));
07984             p->dop.op = DAHDI_DIAL_OP_REPLACE;
07985             res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
07986             p->echobreak = 0;
07987          } else {
07988             p->dialing = 0;
07989             if ((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) {
07990                /* if thru with dialing after offhook */
07991                if (ast->_state == AST_STATE_DIALING_OFFHOOK) {
07992                   ast_setstate(ast, AST_STATE_UP);
07993                   p->subs[idx].f.frametype = AST_FRAME_CONTROL;
07994                   p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
07995                   break;
07996                } else { /* if to state wait for offhook to dial rest */
07997                   /* we now wait for off hook */
07998                   ast_setstate(ast,AST_STATE_DIALING_OFFHOOK);
07999                }
08000             }
08001             if (ast->_state == AST_STATE_DIALING) {
08002                if ((p->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
08003                   ast_debug(1, "Done dialing, but waiting for progress detection before doing more...\n");
08004                } else if (p->confirmanswer || (!p->dialednone
08005                   && ((mysig == SIG_EM) || (mysig == SIG_EM_E1)
08006                      || (mysig == SIG_EMWINK) || (mysig == SIG_FEATD)
08007                      || (mysig == SIG_FEATDMF_TA) || (mysig == SIG_FEATDMF)
08008                      || (mysig == SIG_E911) || (mysig == SIG_FGC_CAMA)
08009                      || (mysig == SIG_FGC_CAMAMF) || (mysig == SIG_FEATB)
08010                      || (mysig == SIG_SF) || (mysig == SIG_SFWINK)
08011                      || (mysig == SIG_SF_FEATD) || (mysig == SIG_SF_FEATDMF)
08012                      || (mysig == SIG_SF_FEATB)))) {
08013                   ast_setstate(ast, AST_STATE_RINGING);
08014                } else if (!p->answeronpolarityswitch) {
08015                   ast_setstate(ast, AST_STATE_UP);
08016                   p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08017                   p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
08018                   /* If aops=0 and hops=1, this is necessary */
08019                   p->polarity = POLARITY_REV;
08020                } else {
08021                   /* Start clean, so we can catch the change to REV polarity when party answers */
08022                   p->polarity = POLARITY_IDLE;
08023                }
08024             }
08025          }
08026       }
08027       break;
08028    case DAHDI_EVENT_ALARM:
08029       switch (p->sig) {
08030 #if defined(HAVE_PRI)
08031       case SIG_PRI_LIB_HANDLE_CASES:
08032          sig_pri_chan_alarm_notify(p->sig_pvt, 0);
08033          break;
08034 #endif   /* defined(HAVE_PRI) */
08035 #if defined(HAVE_SS7)
08036       case SIG_SS7:
08037          sig_ss7_set_alarm(p->sig_pvt, 1);
08038          break;
08039 #endif   /* defined(HAVE_SS7) */
08040       default:
08041          p->inalarm = 1;
08042          break;
08043       }
08044       res = get_alarms(p);
08045       handle_alarms(p, res);
08046 #ifdef HAVE_PRI
08047       if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
08048          /* fall through intentionally */
08049       } else {
08050          break;
08051       }
08052 #endif
08053 #if defined(HAVE_SS7)
08054       if (p->sig == SIG_SS7)
08055          break;
08056 #endif   /* defined(HAVE_SS7) */
08057 #ifdef HAVE_OPENR2
08058       if (p->sig == SIG_MFCR2)
08059          break;
08060 #endif
08061    case DAHDI_EVENT_ONHOOK:
08062       if (p->radio) {
08063          p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08064          p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_UNKEY;
08065          break;
08066       }
08067       if (p->oprmode < 0)
08068       {
08069          if (p->oprmode != -1) break;
08070          if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
08071          {
08072             /* Make sure it starts ringing */
08073             dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
08074             dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RING);
08075             save_conference(p->oprpeer);
08076             tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
08077          }
08078          break;
08079       }
08080       switch (p->sig) {
08081       case SIG_FXOLS:
08082       case SIG_FXOGS:
08083       case SIG_FXOKS:
08084          /* Check for some special conditions regarding call waiting */
08085          if (idx == SUB_REAL) {
08086             /* The normal line was hung up */
08087             if (p->subs[SUB_CALLWAIT].owner) {
08088                /* There's a call waiting call, so ring the phone, but make it unowned in the mean time */
08089                swap_subs(p, SUB_CALLWAIT, SUB_REAL);
08090                ast_verb(3, "Channel %d still has (callwait) call, ringing phone\n", p->channel);
08091                unalloc_sub(p, SUB_CALLWAIT);
08092 #if 0
08093                p->subs[idx].needanswer = 0;
08094                p->subs[idx].needringing = 0;
08095 #endif
08096                p->callwaitingrepeat = 0;
08097                p->cidcwexpire = 0;
08098                p->cid_suppress_expire = 0;
08099                p->owner = NULL;
08100                /* Don't start streaming audio yet if the incoming call isn't up yet */
08101                if (p->subs[SUB_REAL].owner->_state != AST_STATE_UP)
08102                   p->dialing = 1;
08103                dahdi_ring_phone(p);
08104             } else if (p->subs[SUB_THREEWAY].owner) {
08105                unsigned int mssinceflash;
08106                /* Here we have to retain the lock on both the main channel, the 3-way channel, and
08107                   the private structure -- not especially easy or clean */
08108                while (p->subs[SUB_THREEWAY].owner && ast_channel_trylock(p->subs[SUB_THREEWAY].owner)) {
08109                   /* Yuck, didn't get the lock on the 3-way, gotta release everything and re-grab! */
08110                   DLA_UNLOCK(&p->lock);
08111                   CHANNEL_DEADLOCK_AVOIDANCE(ast);
08112                   /* We can grab ast and p in that order, without worry.  We should make sure
08113                      nothing seriously bad has happened though like some sort of bizarre double
08114                      masquerade! */
08115                   DLA_LOCK(&p->lock);
08116                   if (p->owner != ast) {
08117                      ast_log(LOG_WARNING, "This isn't good...\n");
08118                      return NULL;
08119                   }
08120                }
08121                if (!p->subs[SUB_THREEWAY].owner) {
08122                   ast_log(LOG_NOTICE, "Whoa, threeway disappeared kinda randomly.\n");
08123                   return NULL;
08124                }
08125                mssinceflash = ast_tvdiff_ms(ast_tvnow(), p->flashtime);
08126                ast_debug(1, "Last flash was %d ms ago\n", mssinceflash);
08127                if (mssinceflash < MIN_MS_SINCE_FLASH) {
08128                   /* It hasn't been long enough since the last flashook.  This is probably a bounce on
08129                      hanging up.  Hangup both channels now */
08130                   if (p->subs[SUB_THREEWAY].owner)
08131                      ast_queue_hangup_with_cause(p->subs[SUB_THREEWAY].owner, AST_CAUSE_NO_ANSWER);
08132                   p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08133                   ast_debug(1, "Looks like a bounced flash, hanging up both calls on %d\n", p->channel);
08134                   ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08135                } else if ((ast->pbx) || (ast->_state == AST_STATE_UP)) {
08136                   if (p->transfer) {
08137                      /* In any case this isn't a threeway call anymore */
08138                      p->subs[SUB_REAL].inthreeway = 0;
08139                      p->subs[SUB_THREEWAY].inthreeway = 0;
08140                      /* Only attempt transfer if the phone is ringing; why transfer to busy tone eh? */
08141                      if (!p->transfertobusy && ast->_state == AST_STATE_BUSY) {
08142                         ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08143                         /* Swap subs and dis-own channel */
08144                         swap_subs(p, SUB_THREEWAY, SUB_REAL);
08145                         p->owner = NULL;
08146                         /* Ring the phone */
08147                         dahdi_ring_phone(p);
08148                      } else {
08149                         if ((res = attempt_transfer(p)) < 0) {
08150                            p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08151                            if (p->subs[SUB_THREEWAY].owner)
08152                               ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08153                         } else if (res) {
08154                            /* Don't actually hang up at this point */
08155                            if (p->subs[SUB_THREEWAY].owner)
08156                               ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08157                            break;
08158                         }
08159                      }
08160                   } else {
08161                      p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08162                      if (p->subs[SUB_THREEWAY].owner)
08163                         ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08164                   }
08165                } else {
08166                   ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08167                   /* Swap subs and dis-own channel */
08168                   swap_subs(p, SUB_THREEWAY, SUB_REAL);
08169                   p->owner = NULL;
08170                   /* Ring the phone */
08171                   dahdi_ring_phone(p);
08172                }
08173             }
08174          } else {
08175             ast_log(LOG_WARNING, "Got a hangup and my index is %d?\n", idx);
08176          }
08177          /* Fall through */
08178       default:
08179          dahdi_disable_ec(p);
08180          return NULL;
08181       }
08182       break;
08183    case DAHDI_EVENT_RINGOFFHOOK:
08184       if (p->inalarm) break;
08185       if (p->oprmode < 0)
08186       {
08187          if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
08188          {
08189             /* Make sure it stops ringing */
08190             dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
08191             tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, -1);
08192             restore_conference(p->oprpeer);
08193          }
08194          break;
08195       }
08196       if (p->radio)
08197       {
08198          p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08199          p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_KEY;
08200          break;
08201       }
08202       /* for E911, its supposed to wait for offhook then dial
08203          the second half of the dial string */
08204       if (((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) && (ast->_state == AST_STATE_DIALING_OFFHOOK)) {
08205          c = strchr(p->dialdest, '/');
08206          if (c)
08207             c++;
08208          else
08209             c = p->dialdest;
08210          if (*c) snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*0%s#", c);
08211          else ast_copy_string(p->dop.dialstr,"M*2#", sizeof(p->dop.dialstr));
08212          if (strlen(p->dop.dialstr) > 4) {
08213             memset(p->echorest, 'w', sizeof(p->echorest) - 1);
08214             strcpy(p->echorest + (p->echotraining / 401) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
08215             p->echorest[sizeof(p->echorest) - 1] = '\0';
08216             p->echobreak = 1;
08217             p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
08218          } else
08219             p->echobreak = 0;
08220          if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
08221             int saveerr = errno;
08222 
08223             x = DAHDI_ONHOOK;
08224             ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
08225             ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
08226             return NULL;
08227             }
08228          p->dialing = 1;
08229          return &p->subs[idx].f;
08230       }
08231       switch (p->sig) {
08232       case SIG_FXOLS:
08233       case SIG_FXOGS:
08234       case SIG_FXOKS:
08235          switch (ast->_state) {
08236          case AST_STATE_RINGING:
08237             dahdi_enable_ec(p);
08238             dahdi_train_ec(p);
08239             p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08240             p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
08241             /* Make sure it stops ringing */
08242             p->subs[SUB_REAL].needringing = 0;
08243             dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
08244             ast_debug(1, "channel %d answered\n", p->channel);
08245 
08246             /* Cancel any running CallerID spill */
08247             ast_free(p->cidspill);
08248             p->cidspill = NULL;
08249             restore_conference(p);
08250 
08251             p->dialing = 0;
08252             p->callwaitcas = 0;
08253             if (p->confirmanswer) {
08254                /* Ignore answer if "confirm answer" is enabled */
08255                p->subs[idx].f.frametype = AST_FRAME_NULL;
08256                p->subs[idx].f.subclass.integer = 0;
08257             } else if (!ast_strlen_zero(p->dop.dialstr)) {
08258                /* nick@dccinc.com 4/3/03 - fxo should be able to do deferred dialing */
08259                res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
08260                if (res < 0) {
08261                   ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
08262                   p->dop.dialstr[0] = '\0';
08263                   return NULL;
08264                } else {
08265                   ast_debug(1, "Sent FXO deferred digit string: %s\n", p->dop.dialstr);
08266                   p->subs[idx].f.frametype = AST_FRAME_NULL;
08267                   p->subs[idx].f.subclass.integer = 0;
08268                   p->dialing = 1;
08269                }
08270                p->dop.dialstr[0] = '\0';
08271                ast_setstate(ast, AST_STATE_DIALING);
08272             } else
08273                ast_setstate(ast, AST_STATE_UP);
08274             return &p->subs[idx].f;
08275          case AST_STATE_DOWN:
08276             ast_setstate(ast, AST_STATE_RING);
08277             ast->rings = 1;
08278             p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08279             p->subs[idx].f.subclass.integer = AST_CONTROL_OFFHOOK;
08280             ast_debug(1, "channel %d picked up\n", p->channel);
08281             return &p->subs[idx].f;
08282          case AST_STATE_UP:
08283             /* Make sure it stops ringing */
08284             dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
08285             /* Okay -- probably call waiting*/
08286             if (ast_bridged_channel(p->owner))
08287                ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
08288             p->subs[idx].needunhold = 1;
08289             break;
08290          case AST_STATE_RESERVED:
08291             /* Start up dialtone */
08292             if (has_voicemail(p))
08293                res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
08294             else
08295                res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
08296             break;
08297          default:
08298             ast_log(LOG_WARNING, "FXO phone off hook in weird state %d??\n", ast->_state);
08299          }
08300          break;
08301       case SIG_FXSLS:
08302       case SIG_FXSGS:
08303       case SIG_FXSKS:
08304          if (ast->_state == AST_STATE_RING) {
08305             p->ringt = p->ringt_base;
08306          }
08307 
08308          /* If we get a ring then we cannot be in
08309           * reversed polarity. So we reset to idle */
08310          ast_debug(1, "Setting IDLE polarity due "
08311             "to ring. Old polarity was %d\n",
08312             p->polarity);
08313          p->polarity = POLARITY_IDLE;
08314 
08315          /* Fall through */
08316       case SIG_EM:
08317       case SIG_EM_E1:
08318       case SIG_EMWINK:
08319       case SIG_FEATD:
08320       case SIG_FEATDMF:
08321       case SIG_FEATDMF_TA:
08322       case SIG_E911:
08323       case SIG_FGC_CAMA:
08324       case SIG_FGC_CAMAMF:
08325       case SIG_FEATB:
08326       case SIG_SF:
08327       case SIG_SFWINK:
08328       case SIG_SF_FEATD:
08329       case SIG_SF_FEATDMF:
08330       case SIG_SF_FEATB:
08331          if (ast->_state == AST_STATE_PRERING)
08332             ast_setstate(ast, AST_STATE_RING);
08333          if ((ast->_state == AST_STATE_DOWN) || (ast->_state == AST_STATE_RING)) {
08334             ast_debug(1, "Ring detected\n");
08335             p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08336             p->subs[idx].f.subclass.integer = AST_CONTROL_RING;
08337          } else if (p->outgoing && ((ast->_state == AST_STATE_RINGING) || (ast->_state == AST_STATE_DIALING))) {
08338             ast_debug(1, "Line answered\n");
08339             if (p->confirmanswer) {
08340                p->subs[idx].f.frametype = AST_FRAME_NULL;
08341                p->subs[idx].f.subclass.integer = 0;
08342             } else {
08343                p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08344                p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
08345                ast_setstate(ast, AST_STATE_UP);
08346             }
08347          } else if (ast->_state != AST_STATE_RING)
08348             ast_log(LOG_WARNING, "Ring/Off-hook in strange state %d on channel %d\n", ast->_state, p->channel);
08349          break;
08350       default:
08351          ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
08352       }
08353       break;
08354    case DAHDI_EVENT_RINGBEGIN:
08355       switch (p->sig) {
08356       case SIG_FXSLS:
08357       case SIG_FXSGS:
08358       case SIG_FXSKS:
08359          if (ast->_state == AST_STATE_RING) {
08360             p->ringt = p->ringt_base;
08361          }
08362          break;
08363       }
08364       break;
08365    case DAHDI_EVENT_RINGERON:
08366       break;
08367    case DAHDI_EVENT_NOALARM:
08368       switch (p->sig) {
08369 #if defined(HAVE_PRI)
08370       case SIG_PRI_LIB_HANDLE_CASES:
08371          sig_pri_chan_alarm_notify(p->sig_pvt, 1);
08372          break;
08373 #endif   /* defined(HAVE_PRI) */
08374 #if defined(HAVE_SS7)
08375       case SIG_SS7:
08376          sig_ss7_set_alarm(p->sig_pvt, 0);
08377          break;
08378 #endif   /* defined(HAVE_SS7) */
08379       default:
08380          p->inalarm = 0;
08381          break;
08382       }
08383       handle_clear_alarms(p);
08384       break;
08385    case DAHDI_EVENT_WINKFLASH:
08386       if (p->inalarm) break;
08387       if (p->radio) break;
08388       if (p->oprmode < 0) break;
08389       if (p->oprmode > 1)
08390       {
08391          struct dahdi_params par;
08392 
08393          memset(&par, 0, sizeof(par));
08394          if (ioctl(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par) != -1)
08395          {
08396             if (!par.rxisoffhook)
08397             {
08398                /* Make sure it stops ringing */
08399                dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
08400                dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RING);
08401                save_conference(p);
08402                tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
08403             }
08404          }
08405          break;
08406       }
08407       /* Remember last time we got a flash-hook */
08408       p->flashtime = ast_tvnow();
08409       switch (mysig) {
08410       case SIG_FXOLS:
08411       case SIG_FXOGS:
08412       case SIG_FXOKS:
08413          ast_debug(1, "Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n",
08414             idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
08415 
08416          /* Cancel any running CallerID spill */
08417          ast_free(p->cidspill);
08418          p->cidspill = NULL;
08419          restore_conference(p);
08420          p->callwaitcas = 0;
08421 
08422          if (idx != SUB_REAL) {
08423             ast_log(LOG_WARNING, "Got flash hook with index %d on channel %d?!?\n", idx, p->channel);
08424             goto winkflashdone;
08425          }
08426 
08427          if (p->subs[SUB_CALLWAIT].owner) {
08428             /* Swap to call-wait */
08429             swap_subs(p, SUB_REAL, SUB_CALLWAIT);
08430             tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
08431             p->owner = p->subs[SUB_REAL].owner;
08432             ast_debug(1, "Making %s the new owner\n", p->owner->name);
08433             if (p->owner->_state == AST_STATE_RINGING) {
08434                ast_setstate(p->owner, AST_STATE_UP);
08435                p->subs[SUB_REAL].needanswer = 1;
08436             }
08437             p->callwaitingrepeat = 0;
08438             p->cidcwexpire = 0;
08439             p->cid_suppress_expire = 0;
08440             /* Start music on hold if appropriate */
08441             if (!p->subs[SUB_CALLWAIT].inthreeway && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
08442                ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
08443                   S_OR(p->mohsuggest, NULL),
08444                   !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
08445             }
08446             p->subs[SUB_CALLWAIT].needhold = 1;
08447             if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
08448                ast_queue_control_data(p->subs[SUB_REAL].owner, AST_CONTROL_HOLD,
08449                   S_OR(p->mohsuggest, NULL),
08450                   !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
08451             }
08452             p->subs[SUB_REAL].needunhold = 1;
08453          } else if (!p->subs[SUB_THREEWAY].owner) {
08454             if (!p->threewaycalling) {
08455                /* Just send a flash if no 3-way calling */
08456                p->subs[SUB_REAL].needflash = 1;
08457                goto winkflashdone;
08458             } else if (!check_for_conference(p)) {
08459                char cid_num[256];
08460                char cid_name[256];
08461 
08462                cid_num[0] = 0;
08463                cid_name[0] = 0;
08464                if (p->dahditrcallerid && p->owner) {
08465                   if (p->owner->caller.id.number.valid
08466                      && p->owner->caller.id.number.str) {
08467                      ast_copy_string(cid_num, p->owner->caller.id.number.str,
08468                         sizeof(cid_num));
08469                   }
08470                   if (p->owner->caller.id.name.valid
08471                      && p->owner->caller.id.name.str) {
08472                      ast_copy_string(cid_name, p->owner->caller.id.name.str,
08473                         sizeof(cid_name));
08474                   }
08475                }
08476                /* XXX This section needs much more error checking!!! XXX */
08477                /* Start a 3-way call if feasible */
08478                if (!((ast->pbx) ||
08479                   (ast->_state == AST_STATE_UP) ||
08480                   (ast->_state == AST_STATE_RING))) {
08481                   ast_debug(1, "Flash when call not up or ringing\n");
08482                   goto winkflashdone;
08483                }
08484                if (alloc_sub(p, SUB_THREEWAY)) {
08485                   ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n");
08486                   goto winkflashdone;
08487                }
08488                /* Make new channel */
08489                chan = dahdi_new(p, AST_STATE_RESERVED, 0, SUB_THREEWAY, 0, NULL);
08490                if (p->dahditrcallerid) {
08491                   if (!p->origcid_num)
08492                      p->origcid_num = ast_strdup(p->cid_num);
08493                   if (!p->origcid_name)
08494                      p->origcid_name = ast_strdup(p->cid_name);
08495                   ast_copy_string(p->cid_num, cid_num, sizeof(p->cid_num));
08496                   ast_copy_string(p->cid_name, cid_name, sizeof(p->cid_name));
08497                }
08498                /* Swap things around between the three-way and real call */
08499                swap_subs(p, SUB_THREEWAY, SUB_REAL);
08500                /* Disable echo canceller for better dialing */
08501                dahdi_disable_ec(p);
08502                res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALRECALL);
08503                if (res)
08504                   ast_log(LOG_WARNING, "Unable to start dial recall tone on channel %d\n", p->channel);
08505                p->owner = chan;
08506                if (!chan) {
08507                   ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", p->channel);
08508                } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
08509                   ast_log(LOG_WARNING, "Unable to start simple switch on channel %d\n", p->channel);
08510                   res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
08511                   dahdi_enable_ec(p);
08512                   ast_hangup(chan);
08513                } else {
08514                   ast_verb(3, "Started three way call on channel %d\n", p->channel);
08515 
08516                   /* Start music on hold if appropriate */
08517                   if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
08518                      ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
08519                         S_OR(p->mohsuggest, NULL),
08520                         !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
08521                   }
08522                   p->subs[SUB_THREEWAY].needhold = 1;
08523                }
08524             }
08525          } else {
08526             /* Already have a 3 way call */
08527             if (p->subs[SUB_THREEWAY].inthreeway) {
08528                /* Call is already up, drop the last person */
08529                ast_debug(1, "Got flash with three way call up, dropping last call on %d\n", p->channel);
08530                /* If the primary call isn't answered yet, use it */
08531                if ((p->subs[SUB_REAL].owner->_state != AST_STATE_UP) && (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_UP)) {
08532                   /* Swap back -- we're dropping the real 3-way that isn't finished yet*/
08533                   swap_subs(p, SUB_THREEWAY, SUB_REAL);
08534                   p->owner = p->subs[SUB_REAL].owner;
08535                }
08536                /* Drop the last call and stop the conference */
08537                ast_verb(3, "Dropping three-way call on %s\n", p->subs[SUB_THREEWAY].owner->name);
08538                p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08539                p->subs[SUB_REAL].inthreeway = 0;
08540                p->subs[SUB_THREEWAY].inthreeway = 0;
08541             } else {
08542                /* Lets see what we're up to */
08543                if (((ast->pbx) || (ast->_state == AST_STATE_UP)) &&
08544                   (p->transfertobusy || (ast->_state != AST_STATE_BUSY))) {
08545                   int otherindex = SUB_THREEWAY;
08546 
08547                   ast_verb(3, "Building conference call with %s and %s\n",
08548                      p->subs[SUB_THREEWAY].owner->name,
08549                      p->subs[SUB_REAL].owner->name);
08550                   /* Put them in the threeway, and flip */
08551                   p->subs[SUB_THREEWAY].inthreeway = 1;
08552                   p->subs[SUB_REAL].inthreeway = 1;
08553                   if (ast->_state == AST_STATE_UP) {
08554                      swap_subs(p, SUB_THREEWAY, SUB_REAL);
08555                      otherindex = SUB_REAL;
08556                   }
08557                   if (p->subs[otherindex].owner && ast_bridged_channel(p->subs[otherindex].owner))
08558                      ast_queue_control(p->subs[otherindex].owner, AST_CONTROL_UNHOLD);
08559                   p->subs[otherindex].needunhold = 1;
08560                   p->owner = p->subs[SUB_REAL].owner;
08561                } else {
08562                   ast_verb(3, "Dumping incomplete call on on %s\n", p->subs[SUB_THREEWAY].owner->name);
08563                   swap_subs(p, SUB_THREEWAY, SUB_REAL);
08564                   p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08565                   p->owner = p->subs[SUB_REAL].owner;
08566                   if (p->subs[SUB_REAL].owner && ast_bridged_channel(p->subs[SUB_REAL].owner))
08567                      ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
08568                   p->subs[SUB_REAL].needunhold = 1;
08569                   dahdi_enable_ec(p);
08570                }
08571             }
08572          }
08573 winkflashdone:
08574          update_conf(p);
08575          break;
08576       case SIG_EM:
08577       case SIG_EM_E1:
08578       case SIG_FEATD:
08579       case SIG_SF:
08580       case SIG_SFWINK:
08581       case SIG_SF_FEATD:
08582       case SIG_FXSLS:
08583       case SIG_FXSGS:
08584          if (p->dialing)
08585             ast_debug(1, "Ignoring wink on channel %d\n", p->channel);
08586          else
08587             ast_debug(1, "Got wink in weird state %d on channel %d\n", ast->_state, p->channel);
08588          break;
08589       case SIG_FEATDMF_TA:
08590          switch (p->whichwink) {
08591          case 0:
08592             ast_debug(1, "ANI2 set to '%d' and ANI is '%s'\n", p->owner->caller.ani2,
08593                S_COR(p->owner->caller.ani.number.valid,
08594                   p->owner->caller.ani.number.str, ""));
08595             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%d%s#",
08596                p->owner->caller.ani2,
08597                S_COR(p->owner->caller.ani.number.valid,
08598                   p->owner->caller.ani.number.str, ""));
08599             break;
08600          case 1:
08601             ast_copy_string(p->dop.dialstr, p->finaldial, sizeof(p->dop.dialstr));
08602             break;
08603          case 2:
08604             ast_log(LOG_WARNING, "Received unexpected wink on channel of type SIG_FEATDMF_TA\n");
08605             return NULL;
08606          }
08607          p->whichwink++;
08608          /* Fall through */
08609       case SIG_FEATDMF:
08610       case SIG_E911:
08611       case SIG_FGC_CAMAMF:
08612       case SIG_FGC_CAMA:
08613       case SIG_FEATB:
08614       case SIG_SF_FEATDMF:
08615       case SIG_SF_FEATB:
08616       case SIG_EMWINK:
08617          /* FGD MF and EMWINK *Must* wait for wink */
08618          if (!ast_strlen_zero(p->dop.dialstr)) {
08619             res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
08620             if (res < 0) {
08621                ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
08622                p->dop.dialstr[0] = '\0';
08623                return NULL;
08624             } else
08625                ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
08626          }
08627          p->dop.dialstr[0] = '\0';
08628          break;
08629       default:
08630          ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
08631       }
08632       break;
08633    case DAHDI_EVENT_HOOKCOMPLETE:
08634       if (p->inalarm) break;
08635       if ((p->radio || (p->oprmode < 0))) break;
08636       if (p->waitingfordt.tv_sec) break;
08637       switch (mysig) {
08638       case SIG_FXSLS:  /* only interesting for FXS */
08639       case SIG_FXSGS:
08640       case SIG_FXSKS:
08641       case SIG_EM:
08642       case SIG_EM_E1:
08643       case SIG_EMWINK:
08644       case SIG_FEATD:
08645       case SIG_SF:
08646       case SIG_SFWINK:
08647       case SIG_SF_FEATD:
08648          if (!ast_strlen_zero(p->dop.dialstr)) {
08649             res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
08650             if (res < 0) {
08651                ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
08652                p->dop.dialstr[0] = '\0';
08653                return NULL;
08654             } else
08655                ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
08656          }
08657          p->dop.dialstr[0] = '\0';
08658          p->dop.op = DAHDI_DIAL_OP_REPLACE;
08659          break;
08660       case SIG_FEATDMF:
08661       case SIG_FEATDMF_TA:
08662       case SIG_E911:
08663       case SIG_FGC_CAMA:
08664       case SIG_FGC_CAMAMF:
08665       case SIG_FEATB:
08666       case SIG_SF_FEATDMF:
08667       case SIG_SF_FEATB:
08668          ast_debug(1, "Got hook complete in MF FGD, waiting for wink now on channel %d\n",p->channel);
08669          break;
08670       default:
08671          break;
08672       }
08673       break;
08674    case DAHDI_EVENT_POLARITY:
08675       /*
08676        * If we get a Polarity Switch event, check to see
08677        * if we should change the polarity state and
08678        * mark the channel as UP or if this is an indication
08679        * of remote end disconnect.
08680        */
08681       if (p->polarity == POLARITY_IDLE) {
08682          p->polarity = POLARITY_REV;
08683          if (p->answeronpolarityswitch &&
08684             ((ast->_state == AST_STATE_DIALING) ||
08685             (ast->_state == AST_STATE_RINGING))) {
08686             ast_debug(1, "Answering on polarity switch!\n");
08687             ast_setstate(p->owner, AST_STATE_UP);
08688             if (p->hanguponpolarityswitch) {
08689                p->polaritydelaytv = ast_tvnow();
08690             }
08691          } else
08692             ast_debug(1, "Ignore switch to REVERSED Polarity on channel %d, state %d\n", p->channel, ast->_state);
08693       }
08694       /* Removed else statement from here as it was preventing hangups from ever happening*/
08695       /* Added AST_STATE_RING in if statement below to deal with calling party hangups that take place when ringing */
08696       if (p->hanguponpolarityswitch &&
08697          (p->polarityonanswerdelay > 0) &&
08698          (p->polarity == POLARITY_REV) &&
08699          ((ast->_state == AST_STATE_UP) || (ast->_state == AST_STATE_RING)) ) {
08700          /* Added log_debug information below to provide a better indication of what is going on */
08701          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) );
08702 
08703          if (ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) > p->polarityonanswerdelay) {
08704             ast_debug(1, "Polarity Reversal detected and now Hanging up on channel %d\n", p->channel);
08705             ast_softhangup(p->owner, AST_SOFTHANGUP_EXPLICIT);
08706             p->polarity = POLARITY_IDLE;
08707          } else
08708             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);
08709 
08710       } else {
08711          p->polarity = POLARITY_IDLE;
08712          ast_debug(1, "Ignoring Polarity switch to IDLE on channel %d, state %d\n", p->channel, ast->_state);
08713       }
08714       /* Added more log_debug information below to provide a better indication of what is going on */
08715       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) );
08716       break;
08717    default:
08718       ast_debug(1, "Dunno what to do with event %d on channel %d\n", res, p->channel);
08719    }
08720    return &p->subs[idx].f;
08721 }
08722 
08723 static struct ast_frame *__dahdi_exception(struct ast_channel *ast)
08724 {
08725    int res;
08726    int idx;
08727    struct ast_frame *f;
08728    int usedindex = -1;
08729    struct dahdi_pvt *p = ast->tech_pvt;
08730 
08731    idx = dahdi_get_index(ast, p, 1);
08732 
08733    p->subs[idx].f.frametype = AST_FRAME_NULL;
08734    p->subs[idx].f.datalen = 0;
08735    p->subs[idx].f.samples = 0;
08736    p->subs[idx].f.mallocd = 0;
08737    p->subs[idx].f.offset = 0;
08738    p->subs[idx].f.subclass.integer = 0;
08739    p->subs[idx].f.delivery = ast_tv(0,0);
08740    p->subs[idx].f.src = "dahdi_exception";
08741    p->subs[idx].f.data.ptr = NULL;
08742 
08743 
08744    if ((!p->owner) && (!(p->radio || (p->oprmode < 0)))) {
08745       /* If nobody owns us, absorb the event appropriately, otherwise
08746          we loop indefinitely.  This occurs when, during call waiting, the
08747          other end hangs up our channel so that it no longer exists, but we
08748          have neither FLASH'd nor ONHOOK'd to signify our desire to
08749          change to the other channel. */
08750       if (p->fake_event) {
08751          res = p->fake_event;
08752          p->fake_event = 0;
08753       } else
08754          res = dahdi_get_event(p->subs[SUB_REAL].dfd);
08755       /* Switch to real if there is one and this isn't something really silly... */
08756       if ((res != DAHDI_EVENT_RINGEROFF) && (res != DAHDI_EVENT_RINGERON) &&
08757          (res != DAHDI_EVENT_HOOKCOMPLETE)) {
08758          ast_debug(1, "Restoring owner of channel %d on event %d\n", p->channel, res);
08759          p->owner = p->subs[SUB_REAL].owner;
08760          if (p->owner && ast_bridged_channel(p->owner))
08761             ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
08762          p->subs[SUB_REAL].needunhold = 1;
08763       }
08764       switch (res) {
08765       case DAHDI_EVENT_ONHOOK:
08766          dahdi_disable_ec(p);
08767          if (p->owner) {
08768             ast_verb(3, "Channel %s still has call, ringing phone\n", p->owner->name);
08769             dahdi_ring_phone(p);
08770             p->callwaitingrepeat = 0;
08771             p->cidcwexpire = 0;
08772             p->cid_suppress_expire = 0;
08773          } else
08774             ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
08775          update_conf(p);
08776          break;
08777       case DAHDI_EVENT_RINGOFFHOOK:
08778          dahdi_enable_ec(p);
08779          dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
08780          if (p->owner && (p->owner->_state == AST_STATE_RINGING)) {
08781             p->subs[SUB_REAL].needanswer = 1;
08782             p->dialing = 0;
08783          }
08784          break;
08785       case DAHDI_EVENT_HOOKCOMPLETE:
08786       case DAHDI_EVENT_RINGERON:
08787       case DAHDI_EVENT_RINGEROFF:
08788          /* Do nothing */
08789          break;
08790       case DAHDI_EVENT_WINKFLASH:
08791          p->flashtime = ast_tvnow();
08792          if (p->owner) {
08793             ast_verb(3, "Channel %d flashed to other channel %s\n", p->channel, p->owner->name);
08794             if (p->owner->_state != AST_STATE_UP) {
08795                /* Answer if necessary */
08796                usedindex = dahdi_get_index(p->owner, p, 0);
08797                if (usedindex > -1) {
08798                   p->subs[usedindex].needanswer = 1;
08799                }
08800                ast_setstate(p->owner, AST_STATE_UP);
08801             }
08802             p->callwaitingrepeat = 0;
08803             p->cidcwexpire = 0;
08804             p->cid_suppress_expire = 0;
08805             if (ast_bridged_channel(p->owner))
08806                ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
08807             p->subs[SUB_REAL].needunhold = 1;
08808          } else
08809             ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
08810          update_conf(p);
08811          break;
08812       default:
08813          ast_log(LOG_WARNING, "Don't know how to absorb event %s\n", event2str(res));
08814       }
08815       f = &p->subs[idx].f;
08816       return f;
08817    }
08818    if (!(p->radio || (p->oprmode < 0)))
08819       ast_debug(1, "Exception on %d, channel %d\n", ast->fds[0],p->channel);
08820    /* If it's not us, return NULL immediately */
08821    if (ast != p->owner) {
08822       ast_log(LOG_WARNING, "We're %s, not %s\n", ast->name, p->owner->name);
08823       f = &p->subs[idx].f;
08824       return f;
08825    }
08826    f = dahdi_handle_event(ast);
08827 
08828    /* tell the cdr this zap device hung up */
08829    if (f == NULL) {
08830       ast_set_hangupsource(ast, ast->name, 0);
08831    }
08832 
08833    return f;
08834 }
08835 
08836 static struct ast_frame *dahdi_exception(struct ast_channel *ast)
08837 {
08838    struct dahdi_pvt *p = ast->tech_pvt;
08839    struct ast_frame *f;
08840    ast_mutex_lock(&p->lock);
08841    if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
08842       struct analog_pvt *analog_p = p->sig_pvt;
08843       f = analog_exception(analog_p, ast);
08844    } else {
08845       f = __dahdi_exception(ast);
08846    }
08847    ast_mutex_unlock(&p->lock);
08848    return f;
08849 }
08850 
08851 static struct ast_frame *dahdi_read(struct ast_channel *ast)
08852 {
08853    struct dahdi_pvt *p;
08854    int res;
08855    int idx;
08856    void *readbuf;
08857    struct ast_frame *f;
08858 
08859    /*
08860     * For analog channels, we must do deadlock avoidance because
08861     * analog ports can have more than one Asterisk channel using
08862     * the same private structure.
08863     */
08864    p = ast->tech_pvt;
08865    while (ast_mutex_trylock(&p->lock)) {
08866       CHANNEL_DEADLOCK_AVOIDANCE(ast);
08867 
08868       /*
08869        * For PRI channels, we must refresh the private pointer because
08870        * the call could move to another B channel while the Asterisk
08871        * channel is unlocked.
08872        */
08873       p = ast->tech_pvt;
08874    }
08875 
08876    idx = dahdi_get_index(ast, p, 0);
08877 
08878    /* Hang up if we don't really exist */
08879    if (idx < 0)   {
08880       ast_log(LOG_WARNING, "We don't exist?\n");
08881       ast_mutex_unlock(&p->lock);
08882       return NULL;
08883    }
08884 
08885    if ((p->radio || (p->oprmode < 0)) && p->inalarm) {
08886       ast_mutex_unlock(&p->lock);
08887       return NULL;
08888    }
08889 
08890    p->subs[idx].f.frametype = AST_FRAME_NULL;
08891    p->subs[idx].f.datalen = 0;
08892    p->subs[idx].f.samples = 0;
08893    p->subs[idx].f.mallocd = 0;
08894    p->subs[idx].f.offset = 0;
08895    p->subs[idx].f.subclass.integer = 0;
08896    p->subs[idx].f.delivery = ast_tv(0,0);
08897    p->subs[idx].f.src = "dahdi_read";
08898    p->subs[idx].f.data.ptr = NULL;
08899 
08900    /* make sure it sends initial key state as first frame */
08901    if ((p->radio || (p->oprmode < 0)) && (!p->firstradio))
08902    {
08903       struct dahdi_params ps;
08904 
08905       memset(&ps, 0, sizeof(ps));
08906       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
08907          ast_mutex_unlock(&p->lock);
08908          return NULL;
08909       }
08910       p->firstradio = 1;
08911       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08912       if (ps.rxisoffhook)
08913       {
08914          p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_KEY;
08915       }
08916       else
08917       {
08918          p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_UNKEY;
08919       }
08920       ast_mutex_unlock(&p->lock);
08921       return &p->subs[idx].f;
08922    }
08923    if (p->ringt > 0) {
08924       if (!(--p->ringt)) {
08925          ast_mutex_unlock(&p->lock);
08926          return NULL;
08927       }
08928    }
08929 
08930 #ifdef HAVE_OPENR2
08931    if (p->mfcr2) {
08932       openr2_chan_process_event(p->r2chan);
08933       if (OR2_DIR_FORWARD == openr2_chan_get_direction(p->r2chan)) {
08934          struct ast_frame f = { AST_FRAME_CONTROL, { AST_CONTROL_PROGRESS }, };
08935          /* if the call is already accepted and we already delivered AST_CONTROL_RINGING
08936           * now enqueue a progress frame to bridge the media up */
08937          if (p->mfcr2_call_accepted &&
08938              !p->mfcr2_progress && 
08939              ast->_state == AST_STATE_RINGING) {
08940             ast_log(LOG_DEBUG, "Enqueuing progress frame after R2 accept in chan %d\n", p->channel);
08941             ast_queue_frame(p->owner, &f);
08942             p->mfcr2_progress = 1;
08943          }
08944       }
08945    }
08946 #endif
08947 
08948    if (p->subs[idx].needringing) {
08949       /* Send ringing frame if requested */
08950       p->subs[idx].needringing = 0;
08951       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08952       p->subs[idx].f.subclass.integer = AST_CONTROL_RINGING;
08953       ast_setstate(ast, AST_STATE_RINGING);
08954       ast_mutex_unlock(&p->lock);
08955       return &p->subs[idx].f;
08956    }
08957 
08958    if (p->subs[idx].needbusy) {
08959       /* Send busy frame if requested */
08960       p->subs[idx].needbusy = 0;
08961       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08962       p->subs[idx].f.subclass.integer = AST_CONTROL_BUSY;
08963       ast_mutex_unlock(&p->lock);
08964       return &p->subs[idx].f;
08965    }
08966 
08967    if (p->subs[idx].needcongestion) {
08968       /* Send congestion frame if requested */
08969       p->subs[idx].needcongestion = 0;
08970       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08971       p->subs[idx].f.subclass.integer = AST_CONTROL_CONGESTION;
08972       ast_mutex_unlock(&p->lock);
08973       return &p->subs[idx].f;
08974    }
08975 
08976    if (p->subs[idx].needanswer) {
08977       /* Send answer frame if requested */
08978       p->subs[idx].needanswer = 0;
08979       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08980       p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
08981       ast_mutex_unlock(&p->lock);
08982       return &p->subs[idx].f;
08983    }
08984 #ifdef HAVE_OPENR2
08985    if (p->mfcr2 && openr2_chan_get_read_enabled(p->r2chan)) {
08986       /* openr2 took care of reading and handling any event
08987         (needanswer, needbusy etc), if we continue we will read()
08988         twice, lets just return a null frame. This should only
08989         happen when openr2 is dialing out */
08990       ast_mutex_unlock(&p->lock);
08991       return &ast_null_frame;
08992    }
08993 #endif
08994 
08995    if (p->subs[idx].needflash) {
08996       /* Send answer frame if requested */
08997       p->subs[idx].needflash = 0;
08998       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08999       p->subs[idx].f.subclass.integer = AST_CONTROL_FLASH;
09000       ast_mutex_unlock(&p->lock);
09001       return &p->subs[idx].f;
09002    }
09003 
09004    if (p->subs[idx].needhold) {
09005       /* Send answer frame if requested */
09006       p->subs[idx].needhold = 0;
09007       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09008       p->subs[idx].f.subclass.integer = AST_CONTROL_HOLD;
09009       ast_mutex_unlock(&p->lock);
09010       ast_debug(1, "Sending hold on '%s'\n", ast->name);
09011       return &p->subs[idx].f;
09012    }
09013 
09014    if (p->subs[idx].needunhold) {
09015       /* Send answer frame if requested */
09016       p->subs[idx].needunhold = 0;
09017       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09018       p->subs[idx].f.subclass.integer = AST_CONTROL_UNHOLD;
09019       ast_mutex_unlock(&p->lock);
09020       ast_debug(1, "Sending unhold on '%s'\n", ast->name);
09021       return &p->subs[idx].f;
09022    }
09023 
09024    /*
09025     * If we have a fake_event, fake an exception to handle it only
09026     * if this channel owns the private.
09027     */
09028    if (p->fake_event && p->owner == ast) {
09029       if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
09030          struct analog_pvt *analog_p = p->sig_pvt;
09031 
09032          f = analog_exception(analog_p, ast);
09033       } else {
09034          f = __dahdi_exception(ast);
09035       }
09036       ast_mutex_unlock(&p->lock);
09037       return f;
09038    }
09039 
09040    if (ast->rawreadformat == AST_FORMAT_SLINEAR) {
09041       if (!p->subs[idx].linear) {
09042          p->subs[idx].linear = 1;
09043          res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09044          if (res)
09045             ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to linear mode.\n", p->channel, idx);
09046       }
09047    } else if ((ast->rawreadformat == AST_FORMAT_ULAW) ||
09048       (ast->rawreadformat == AST_FORMAT_ALAW)) {
09049       if (p->subs[idx].linear) {
09050          p->subs[idx].linear = 0;
09051          res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09052          if (res)
09053             ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to companded mode.\n", p->channel, idx);
09054       }
09055    } else {
09056       ast_log(LOG_WARNING, "Don't know how to read frames in format %s\n", ast_getformatname(ast->rawreadformat));
09057       ast_mutex_unlock(&p->lock);
09058       return NULL;
09059    }
09060    readbuf = ((unsigned char *)p->subs[idx].buffer) + AST_FRIENDLY_OFFSET;
09061    CHECK_BLOCKING(ast);
09062    res = read(p->subs[idx].dfd, readbuf, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
09063    ast_clear_flag(ast, AST_FLAG_BLOCKING);
09064    /* Check for hangup */
09065    if (res < 0) {
09066       f = NULL;
09067       if (res == -1) {
09068          if (errno == EAGAIN) {
09069             /* Return "NULL" frame if there is nobody there */
09070             ast_mutex_unlock(&p->lock);
09071             return &p->subs[idx].f;
09072          } else if (errno == ELAST) {
09073             if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
09074                struct analog_pvt *analog_p = p->sig_pvt;
09075                f = analog_exception(analog_p, ast);
09076             } else {
09077                f = __dahdi_exception(ast);
09078             }
09079          } else
09080             ast_log(LOG_WARNING, "dahdi_rec: %s\n", strerror(errno));
09081       }
09082       ast_mutex_unlock(&p->lock);
09083       return f;
09084    }
09085    if (res != (p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE)) {
09086       ast_debug(1, "Short read (%d/%d), must be an event...\n", res, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
09087       if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
09088          struct analog_pvt *analog_p = p->sig_pvt;
09089          f = analog_exception(analog_p, ast);
09090       } else {
09091          f = __dahdi_exception(ast);
09092       }
09093       ast_mutex_unlock(&p->lock);
09094       return f;
09095    }
09096    if (p->tdd) { /* if in TDD mode, see if we receive that */
09097       int c;
09098 
09099       c = tdd_feed(p->tdd,readbuf,READ_SIZE);
09100       if (c < 0) {
09101          ast_debug(1,"tdd_feed failed\n");
09102          ast_mutex_unlock(&p->lock);
09103          return NULL;
09104       }
09105       if (c) { /* if a char to return */
09106          p->subs[idx].f.subclass.integer = 0;
09107          p->subs[idx].f.frametype = AST_FRAME_TEXT;
09108          p->subs[idx].f.mallocd = 0;
09109          p->subs[idx].f.offset = AST_FRIENDLY_OFFSET;
09110          p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET;
09111          p->subs[idx].f.datalen = 1;
09112          *((char *) p->subs[idx].f.data.ptr) = c;
09113          ast_mutex_unlock(&p->lock);
09114          return &p->subs[idx].f;
09115       }
09116    }
09117    if (idx == SUB_REAL) {
09118       /* Ensure the CW timers decrement only on a single subchannel */
09119       if (p->cidcwexpire) {
09120          if (!--p->cidcwexpire) {
09121             /* Expired CID/CW */
09122             ast_verb(3, "CPE does not support Call Waiting Caller*ID.\n");
09123             restore_conference(p);
09124          }
09125       }
09126       if (p->cid_suppress_expire) {
09127          --p->cid_suppress_expire;
09128       }
09129       if (p->callwaitingrepeat) {
09130          if (!--p->callwaitingrepeat) {
09131             /* Expired, Repeat callwaiting tone */
09132             ++p->callwaitrings;
09133             dahdi_callwait(ast);
09134          }
09135       }
09136    }
09137    if (p->subs[idx].linear) {
09138       p->subs[idx].f.datalen = READ_SIZE * 2;
09139    } else
09140       p->subs[idx].f.datalen = READ_SIZE;
09141 
09142    /* Handle CallerID Transmission */
09143    if ((p->owner == ast) && p->cidspill) {
09144       send_callerid(p);
09145    }
09146 
09147    p->subs[idx].f.frametype = AST_FRAME_VOICE;
09148    p->subs[idx].f.subclass.codec = ast->rawreadformat;
09149    p->subs[idx].f.samples = READ_SIZE;
09150    p->subs[idx].f.mallocd = 0;
09151    p->subs[idx].f.offset = AST_FRIENDLY_OFFSET;
09152    p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET / sizeof(p->subs[idx].buffer[0]);
09153 #if 0
09154    ast_debug(1, "Read %d of voice on %s\n", p->subs[idx].f.datalen, ast->name);
09155 #endif
09156    if (p->dialing ||  p->radio || /* Transmitting something */
09157       (idx && (ast->_state != AST_STATE_UP)) || /* Three-way or callwait that isn't up */
09158       ((idx == SUB_CALLWAIT) && !p->subs[SUB_CALLWAIT].inthreeway) /* Inactive and non-confed call-wait */
09159       ) {
09160       /* Whoops, we're still dialing, or in a state where we shouldn't transmit....
09161          don't send anything */
09162       p->subs[idx].f.frametype = AST_FRAME_NULL;
09163       p->subs[idx].f.subclass.integer = 0;
09164       p->subs[idx].f.samples = 0;
09165       p->subs[idx].f.mallocd = 0;
09166       p->subs[idx].f.offset = 0;
09167       p->subs[idx].f.data.ptr = NULL;
09168       p->subs[idx].f.datalen= 0;
09169    }
09170    if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect || p->callprogress || p->waitingfordt.tv_sec) && !idx) {
09171       /* Perform busy detection etc on the dahdi line */
09172       int mute;
09173 
09174       f = ast_dsp_process(ast, p->dsp, &p->subs[idx].f);
09175 
09176       /* Check if DSP code thinks we should be muting this frame and mute the conference if so */
09177       mute = ast_dsp_was_muted(p->dsp);
09178       if (p->muting != mute) {
09179          p->muting = mute;
09180          dahdi_confmute(p, mute);
09181       }
09182 
09183       if (f) {
09184          if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass.integer == AST_CONTROL_BUSY)) {
09185             if ((ast->_state == AST_STATE_UP) && !p->outgoing) {
09186                /* Treat this as a "hangup" instead of a "busy" on the assumption that
09187                   a busy */
09188                f = NULL;
09189             }
09190          } else if (f->frametype == AST_FRAME_DTMF_BEGIN
09191             || f->frametype == AST_FRAME_DTMF_END) {
09192 #ifdef HAVE_PRI
09193             if (dahdi_sig_pri_lib_handles(p->sig)
09194                && ((struct sig_pri_chan *) p->sig_pvt)->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING
09195                && p->pri
09196                && ((!p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING))
09197                   || (p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)))) {
09198                /* Don't accept in-band DTMF when in overlap dial mode */
09199                ast_debug(1, "Absorbing inband %s DTMF digit: 0x%02X '%c' on %s\n",
09200                   f->frametype == AST_FRAME_DTMF_BEGIN ? "begin" : "end",
09201                   f->subclass.integer, f->subclass.integer, ast->name);
09202 
09203                f->frametype = AST_FRAME_NULL;
09204                f->subclass.integer = 0;
09205             }
09206 #endif
09207             /* DSP clears us of being pulse */
09208             p->pulsedial = 0;
09209          } else if (p->waitingfordt.tv_sec) {
09210             if (ast_tvdiff_ms(ast_tvnow(), p->waitingfordt) >= p->waitfordialtone ) {
09211                p->waitingfordt.tv_sec = 0;
09212                ast_log(LOG_WARNING, "Never saw dialtone on channel %d\n", p->channel);
09213                f=NULL;
09214             } else if (f->frametype == AST_FRAME_VOICE) {
09215                f->frametype = AST_FRAME_NULL;
09216                f->subclass.integer = 0;
09217                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) {
09218                   p->waitingfordt.tv_sec = 0;
09219                   p->dsp_features &= ~DSP_FEATURE_WAITDIALTONE;
09220                   ast_dsp_set_features(p->dsp, p->dsp_features);
09221                   ast_log(LOG_DEBUG, "Got 10 samples of dialtone!\n");
09222                   if (!ast_strlen_zero(p->dop.dialstr)) { /* Dial deferred digits */
09223                      res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
09224                      if (res < 0) {
09225                         ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d\n", p->channel);
09226                         p->dop.dialstr[0] = '\0';
09227                         ast_mutex_unlock(&p->lock);
09228                         return NULL;
09229                      } else {
09230                         ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", p->dop.dialstr);
09231                         p->dialing = 1;
09232                         p->dop.dialstr[0] = '\0';
09233                         p->dop.op = DAHDI_DIAL_OP_REPLACE;
09234                         ast_setstate(ast, AST_STATE_DIALING);
09235                      }
09236                   }
09237                }
09238             }
09239          }
09240       }
09241    } else
09242       f = &p->subs[idx].f;
09243 
09244    if (f) {
09245       switch (f->frametype) {
09246       case AST_FRAME_DTMF_BEGIN:
09247       case AST_FRAME_DTMF_END:
09248          if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
09249             analog_handle_dtmf(p->sig_pvt, ast, idx, &f);
09250          } else {
09251             dahdi_handle_dtmf(ast, idx, &f);
09252          }
09253          break;
09254       case AST_FRAME_VOICE:
09255          if (p->cidspill || p->cid_suppress_expire) {
09256             /* We are/were sending a caller id spill.  Suppress any echo. */
09257             p->subs[idx].f.frametype = AST_FRAME_NULL;
09258             p->subs[idx].f.subclass.integer = 0;
09259             p->subs[idx].f.samples = 0;
09260             p->subs[idx].f.mallocd = 0;
09261             p->subs[idx].f.offset = 0;
09262             p->subs[idx].f.data.ptr = NULL;
09263             p->subs[idx].f.datalen= 0;
09264          }
09265          break;
09266       default:
09267          break;
09268       }
09269    }
09270 
09271    ast_mutex_unlock(&p->lock);
09272    return f;
09273 }
09274 
09275 static int my_dahdi_write(struct dahdi_pvt *p, unsigned char *buf, int len, int idx, int linear)
09276 {
09277    int sent=0;
09278    int size;
09279    int res;
09280    int fd;
09281    fd = p->subs[idx].dfd;
09282    while (len) {
09283       size = len;
09284       if (size > (linear ? READ_SIZE * 2 : READ_SIZE))
09285          size = (linear ? READ_SIZE * 2 : READ_SIZE);
09286       res = write(fd, buf, size);
09287       if (res != size) {
09288          ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
09289          return sent;
09290       }
09291       len -= size;
09292       buf += size;
09293    }
09294    return sent;
09295 }
09296 
09297 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame)
09298 {
09299    struct dahdi_pvt *p = ast->tech_pvt;
09300    int res;
09301    int idx;
09302    idx = dahdi_get_index(ast, p, 0);
09303    if (idx < 0) {
09304       ast_log(LOG_WARNING, "%s doesn't really exist?\n", ast->name);
09305       return -1;
09306    }
09307 
09308    /* Write a frame of (presumably voice) data */
09309    if (frame->frametype != AST_FRAME_VOICE) {
09310       if (frame->frametype != AST_FRAME_IMAGE)
09311          ast_log(LOG_WARNING, "Don't know what to do with frame type '%d'\n", frame->frametype);
09312       return 0;
09313    }
09314    if ((frame->subclass.codec != AST_FORMAT_SLINEAR) &&
09315       (frame->subclass.codec != AST_FORMAT_ULAW) &&
09316       (frame->subclass.codec != AST_FORMAT_ALAW)) {
09317       ast_log(LOG_WARNING, "Cannot handle frames in %s format\n", ast_getformatname(frame->subclass.codec));
09318       return -1;
09319    }
09320    if (p->dialing) {
09321       ast_debug(1, "Dropping frame since I'm still dialing on %s...\n",ast->name);
09322       return 0;
09323    }
09324    if (!p->owner) {
09325       ast_debug(1, "Dropping frame since there is no active owner on %s...\n",ast->name);
09326       return 0;
09327    }
09328    if (p->cidspill) {
09329       ast_debug(1, "Dropping frame since I've still got a callerid spill on %s...\n",
09330          ast->name);
09331       return 0;
09332    }
09333    /* Return if it's not valid data */
09334    if (!frame->data.ptr || !frame->datalen)
09335       return 0;
09336 
09337    if (frame->subclass.codec == AST_FORMAT_SLINEAR) {
09338       if (!p->subs[idx].linear) {
09339          p->subs[idx].linear = 1;
09340          res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09341          if (res)
09342             ast_log(LOG_WARNING, "Unable to set linear mode on channel %d\n", p->channel);
09343       }
09344       res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 1);
09345    } else {
09346       /* x-law already */
09347       if (p->subs[idx].linear) {
09348          p->subs[idx].linear = 0;
09349          res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09350          if (res)
09351             ast_log(LOG_WARNING, "Unable to set companded mode on channel %d\n", p->channel);
09352       }
09353       res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 0);
09354    }
09355    if (res < 0) {
09356       ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
09357       return -1;
09358    }
09359    return 0;
09360 }
09361 
09362 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen)
09363 {
09364    struct dahdi_pvt *p = chan->tech_pvt;
09365    int res=-1;
09366    int idx;
09367    int func = DAHDI_FLASH;
09368 
09369    ast_mutex_lock(&p->lock);
09370    ast_debug(1, "Requested indication %d on channel %s\n", condition, chan->name);
09371    switch (p->sig) {
09372 #if defined(HAVE_PRI)
09373    case SIG_PRI_LIB_HANDLE_CASES:
09374       res = sig_pri_indicate(p->sig_pvt, chan, condition, data, datalen);
09375       ast_mutex_unlock(&p->lock);
09376       return res;
09377 #endif   /* defined(HAVE_PRI) */
09378 #if defined(HAVE_SS7)
09379    case SIG_SS7:
09380       res = sig_ss7_indicate(p->sig_pvt, chan, condition, data, datalen);
09381       ast_mutex_unlock(&p->lock);
09382       return res;
09383 #endif   /* defined(HAVE_SS7) */
09384    default:
09385       break;
09386    }
09387 #ifdef HAVE_OPENR2
09388    if (p->mfcr2 && !p->mfcr2_call_accepted) {
09389       ast_mutex_unlock(&p->lock);
09390       /* if this is an R2 call and the call is not yet accepted, we don't want the
09391          tone indications to mess up with the MF tones */
09392       return 0;
09393    }
09394 #endif
09395    idx = dahdi_get_index(chan, p, 0);
09396    if (idx == SUB_REAL) {
09397       switch (condition) {
09398       case AST_CONTROL_BUSY:
09399          res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_BUSY);
09400          break;
09401       case AST_CONTROL_RINGING:
09402          res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_RINGTONE);
09403 
09404          if (chan->_state != AST_STATE_UP) {
09405             if ((chan->_state != AST_STATE_RING) ||
09406                ((p->sig != SIG_FXSKS) &&
09407              (p->sig != SIG_FXSLS) &&
09408              (p->sig != SIG_FXSGS)))
09409             ast_setstate(chan, AST_STATE_RINGING);
09410          }
09411          break;
09412       case AST_CONTROL_INCOMPLETE:
09413          ast_debug(1, "Received AST_CONTROL_INCOMPLETE on %s\n", chan->name);
09414          /* act as a progress or proceeding, allowing the caller to enter additional numbers */
09415          res = 0;
09416          break;
09417       case AST_CONTROL_PROCEEDING:
09418          ast_debug(1, "Received AST_CONTROL_PROCEEDING on %s\n", chan->name);
09419          /* don't continue in ast_indicate */
09420          res = 0;
09421          break;
09422       case AST_CONTROL_PROGRESS:
09423          ast_debug(1, "Received AST_CONTROL_PROGRESS on %s\n", chan->name);
09424          /* don't continue in ast_indicate */
09425          res = 0;
09426          break;
09427       case AST_CONTROL_CONGESTION:
09428          /* There are many cause codes that generate an AST_CONTROL_CONGESTION. */
09429          switch (chan->hangupcause) {
09430          case AST_CAUSE_USER_BUSY:
09431          case AST_CAUSE_NORMAL_CLEARING:
09432          case 0:/* Cause has not been set. */
09433             /* Supply a more appropriate cause. */
09434             chan->hangupcause = AST_CAUSE_CONGESTION;
09435             break;
09436          default:
09437             break;
09438          }
09439          break;
09440       case AST_CONTROL_HOLD:
09441          ast_moh_start(chan, data, p->mohinterpret);
09442          break;
09443       case AST_CONTROL_UNHOLD:
09444          ast_moh_stop(chan);
09445          break;
09446       case AST_CONTROL_RADIO_KEY:
09447          if (p->radio)
09448             res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
09449          res = 0;
09450          break;
09451       case AST_CONTROL_RADIO_UNKEY:
09452          if (p->radio)
09453             res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_RINGOFF);
09454          res = 0;
09455          break;
09456       case AST_CONTROL_FLASH:
09457          /* flash hookswitch */
09458          if (ISTRUNK(p) && (p->sig != SIG_PRI)) {
09459             /* Clear out the dial buffer */
09460             p->dop.dialstr[0] = '\0';
09461             if ((ioctl(p->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
09462                ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
09463                   chan->name, strerror(errno));
09464             } else
09465                res = 0;
09466          } else
09467             res = 0;
09468          break;
09469       case AST_CONTROL_SRCUPDATE:
09470          res = 0;
09471          break;
09472       case -1:
09473          res = tone_zone_play_tone(p->subs[idx].dfd, -1);
09474          break;
09475       }
09476    } else {
09477       res = 0;
09478    }
09479    ast_mutex_unlock(&p->lock);
09480    return res;
09481 }
09482 
09483 #if defined(HAVE_PRI)
09484 static struct ast_str *create_channel_name(struct dahdi_pvt *i, int is_outgoing, char *address)
09485 #else
09486 static struct ast_str *create_channel_name(struct dahdi_pvt *i)
09487 #endif   /* defined(HAVE_PRI) */
09488 {
09489    struct ast_str *chan_name;
09490    int x, y;
09491 
09492    /* Create the new channel name tail. */
09493    if (!(chan_name = ast_str_create(32))) {
09494       return NULL;
09495    }
09496    if (i->channel == CHAN_PSEUDO) {
09497       ast_str_set(&chan_name, 0, "pseudo-%ld", ast_random());
09498 #if defined(HAVE_PRI)
09499    } else if (i->pri) {
09500       ast_mutex_lock(&i->pri->lock);
09501       y = ++i->pri->new_chan_seq;
09502       if (is_outgoing) {
09503          ast_str_set(&chan_name, 0, "i%d/%s-%x", i->pri->span, address, y);
09504          address[0] = '\0';
09505       } else if (ast_strlen_zero(i->cid_subaddr)) {
09506          /* Put in caller-id number only since there is no subaddress. */
09507          ast_str_set(&chan_name, 0, "i%d/%s-%x", i->pri->span, i->cid_num, y);
09508       } else {
09509          /* Put in caller-id number and subaddress. */
09510          ast_str_set(&chan_name, 0, "i%d/%s:%s-%x", i->pri->span, i->cid_num,
09511             i->cid_subaddr, y);
09512       }
09513       ast_mutex_unlock(&i->pri->lock);
09514 #endif   /* defined(HAVE_PRI) */
09515    } else {
09516       y = 1;
09517       do {
09518          ast_str_set(&chan_name, 0, "%d-%d", i->channel, y);
09519          for (x = 0; x < 3; ++x) {
09520             if (i->subs[x].owner && !strcasecmp(ast_str_buffer(chan_name),
09521                i->subs[x].owner->name + 6)) {
09522                break;
09523             }
09524          }
09525          ++y;
09526       } while (x < 3);
09527    }
09528    return chan_name;
09529 }
09530 
09531 static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpbx, int idx, int law, const char *linkedid)
09532 {
09533    struct ast_channel *tmp;
09534    format_t deflaw;
09535    int x;
09536    int features;
09537    struct ast_str *chan_name;
09538    struct ast_variable *v;
09539    char *dashptr;
09540    char device_name[AST_CHANNEL_NAME];
09541 
09542    if (i->subs[idx].owner) {
09543       ast_log(LOG_WARNING, "Channel %d already has a %s call\n", i->channel,subnames[idx]);
09544       return NULL;
09545    }
09546 
09547 #if defined(HAVE_PRI)
09548    /*
09549     * The dnid has been stuffed with the called-number[:subaddress]
09550     * by dahdi_request() for outgoing calls.
09551     */
09552    chan_name = create_channel_name(i, i->outgoing, i->dnid);
09553 #else
09554    chan_name = create_channel_name(i);
09555 #endif   /* defined(HAVE_PRI) */
09556    if (!chan_name) {
09557       return NULL;
09558    }
09559 
09560    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));
09561    ast_free(chan_name);
09562    if (!tmp)
09563       return NULL;
09564    tmp->tech = &dahdi_tech;
09565 #if defined(HAVE_PRI)
09566    if (i->pri) {
09567       ast_cc_copy_config_params(i->cc_params, i->pri->cc_params);
09568    }
09569 #endif   /* defined(HAVE_PRI) */
09570    ast_channel_cc_params_init(tmp, i->cc_params);
09571    if (law) {
09572       i->law = law;
09573       if (law == DAHDI_LAW_ALAW) {
09574          deflaw = AST_FORMAT_ALAW;
09575       } else {
09576          deflaw = AST_FORMAT_ULAW;
09577       }
09578    } else {
09579       switch (i->sig) {
09580       case SIG_PRI_LIB_HANDLE_CASES:
09581          /* Make sure companding law is known. */
09582          i->law = (i->law_default == DAHDI_LAW_ALAW)
09583             ? DAHDI_LAW_ALAW : DAHDI_LAW_MULAW;
09584          break;
09585       default:
09586          i->law = i->law_default;
09587          break;
09588       }
09589       if (i->law_default == DAHDI_LAW_ALAW) {
09590          deflaw = AST_FORMAT_ALAW;
09591       } else {
09592          deflaw = AST_FORMAT_ULAW;
09593       }
09594    }
09595    ast_channel_set_fd(tmp, 0, i->subs[idx].dfd);
09596    tmp->nativeformats = deflaw;
09597    /* Start out assuming ulaw since it's smaller :) */
09598    tmp->rawreadformat = deflaw;
09599    tmp->readformat = deflaw;
09600    tmp->rawwriteformat = deflaw;
09601    tmp->writeformat = deflaw;
09602    i->subs[idx].linear = 0;
09603    dahdi_setlinear(i->subs[idx].dfd, i->subs[idx].linear);
09604    features = 0;
09605    if (idx == SUB_REAL) {
09606       if (i->busydetect && CANBUSYDETECT(i))
09607          features |= DSP_FEATURE_BUSY_DETECT;
09608       if ((i->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(i))
09609          features |= DSP_FEATURE_CALL_PROGRESS;
09610       if ((i->waitfordialtone) && CANPROGRESSDETECT(i))
09611          features |= DSP_FEATURE_WAITDIALTONE;
09612       if ((!i->outgoing && (i->callprogress & CALLPROGRESS_FAX_INCOMING)) ||
09613          (i->outgoing && (i->callprogress & CALLPROGRESS_FAX_OUTGOING))) {
09614          features |= DSP_FEATURE_FAX_DETECT;
09615       }
09616       x = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
09617       if (ioctl(i->subs[idx].dfd, DAHDI_TONEDETECT, &x)) {
09618          i->hardwaredtmf = 0;
09619          features |= DSP_FEATURE_DIGIT_DETECT;
09620       } else if (NEED_MFDETECT(i)) {
09621          i->hardwaredtmf = 1;
09622          features |= DSP_FEATURE_DIGIT_DETECT;
09623       }
09624    }
09625    if (features) {
09626       if (i->dsp) {
09627          ast_debug(1, "Already have a dsp on %s?\n", tmp->name);
09628       } else {
09629          if (i->channel != CHAN_PSEUDO)
09630             i->dsp = ast_dsp_new();
09631          else
09632             i->dsp = NULL;
09633          if (i->dsp) {
09634             i->dsp_features = features;
09635 #if defined(HAVE_PRI) || defined(HAVE_SS7)
09636             /* We cannot do progress detection until receive PROGRESS message */
09637             if (i->outgoing && (dahdi_sig_pri_lib_handles(i->sig) || (i->sig == SIG_SS7))) {
09638                /* Remember requested DSP features, don't treat
09639                   talking as ANSWER */
09640                i->dsp_features = features & ~DSP_PROGRESS_TALK;
09641                features = 0;
09642             }
09643 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
09644             ast_dsp_set_features(i->dsp, features);
09645             ast_dsp_set_digitmode(i->dsp, DSP_DIGITMODE_DTMF | i->dtmfrelax);
09646             if (!ast_strlen_zero(progzone))
09647                ast_dsp_set_call_progress_zone(i->dsp, progzone);
09648             if (i->busydetect && CANBUSYDETECT(i)) {
09649                ast_dsp_set_busy_count(i->dsp, i->busycount);
09650                ast_dsp_set_busy_pattern(i->dsp, i->busy_tonelength, i->busy_quietlength);
09651             }
09652          }
09653       }
09654    }
09655 
09656    if (state == AST_STATE_RING)
09657       tmp->rings = 1;
09658    tmp->tech_pvt = i;
09659    if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) {
09660       /* Only FXO signalled stuff can be picked up */
09661       tmp->callgroup = i->callgroup;
09662       tmp->pickupgroup = i->pickupgroup;
09663    }
09664    if (!ast_strlen_zero(i->parkinglot))
09665       ast_string_field_set(tmp, parkinglot, i->parkinglot);
09666    if (!ast_strlen_zero(i->language))
09667       ast_string_field_set(tmp, language, i->language);
09668    if (!i->owner)
09669       i->owner = tmp;
09670    if (!ast_strlen_zero(i->accountcode))
09671       ast_string_field_set(tmp, accountcode, i->accountcode);
09672    if (i->amaflags)
09673       tmp->amaflags = i->amaflags;
09674    i->subs[idx].owner = tmp;
09675    ast_copy_string(tmp->context, i->context, sizeof(tmp->context));
09676    if (!analog_lib_handles(i->sig, i->radio, i->oprmode)) {
09677       ast_string_field_set(tmp, call_forward, i->call_forward);
09678    }
09679    /* If we've been told "no ADSI" then enforce it */
09680    if (!i->adsi)
09681       tmp->adsicpe = AST_ADSI_UNAVAILABLE;
09682    if (!ast_strlen_zero(i->exten))
09683       ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten));
09684    if (!ast_strlen_zero(i->rdnis)) {
09685       tmp->redirecting.from.number.valid = 1;
09686       tmp->redirecting.from.number.str = ast_strdup(i->rdnis);
09687    }
09688    if (!ast_strlen_zero(i->dnid)) {
09689       tmp->dialed.number.str = ast_strdup(i->dnid);
09690    }
09691 
09692    /* Don't use ast_set_callerid() here because it will
09693     * generate a needless NewCallerID event */
09694 #if defined(HAVE_PRI) || defined(HAVE_SS7)
09695    if (!ast_strlen_zero(i->cid_ani)) {
09696       tmp->caller.ani.number.valid = 1;
09697       tmp->caller.ani.number.str = ast_strdup(i->cid_ani);
09698    } else if (!ast_strlen_zero(i->cid_num)) {
09699       tmp->caller.ani.number.valid = 1;
09700       tmp->caller.ani.number.str = ast_strdup(i->cid_num);
09701    }
09702 #else
09703    if (!ast_strlen_zero(i->cid_num)) {
09704       tmp->caller.ani.number.valid = 1;
09705       tmp->caller.ani.number.str = ast_strdup(i->cid_num);
09706    }
09707 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
09708    tmp->caller.id.name.presentation = i->callingpres;
09709    tmp->caller.id.number.presentation = i->callingpres;
09710    tmp->caller.id.number.plan = i->cid_ton;
09711    tmp->caller.ani2 = i->cid_ani2;
09712    tmp->caller.id.tag = ast_strdup(i->cid_tag);
09713    /* clear the fake event in case we posted one before we had ast_channel */
09714    i->fake_event = 0;
09715    /* Assure there is no confmute on this channel */
09716    dahdi_confmute(i, 0);
09717    i->muting = 0;
09718    /* Configure the new channel jb */
09719    ast_jb_configure(tmp, &global_jbconf);
09720 
09721    /* Set initial device state */
09722    ast_copy_string(device_name, tmp->name, sizeof(device_name));
09723    dashptr = strrchr(device_name, '-');
09724    if (dashptr) {
09725       *dashptr = '\0';
09726    }
09727    ast_devstate_changed_literal(AST_DEVICE_UNKNOWN, device_name);
09728 
09729    for (v = i->vars ; v ; v = v->next)
09730       pbx_builtin_setvar_helper(tmp, v->name, v->value);
09731 
09732    ast_module_ref(ast_module_info->self);
09733 
09734    dahdi_ami_channel_event(i, tmp);
09735    if (startpbx) {
09736 #ifdef HAVE_OPENR2
09737       if (i->mfcr2call) {
09738          pbx_builtin_setvar_helper(tmp, "MFCR2_CATEGORY", openr2_proto_get_category_string(i->mfcr2_recvd_category));
09739       }
09740 #endif
09741       if (ast_pbx_start(tmp)) {
09742          ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
09743          ast_hangup(tmp);
09744          return NULL;
09745       }
09746    }
09747    return tmp;
09748 }
09749 
09750 
09751 static int my_getsigstr(struct ast_channel *chan, char *str, const char *term, int ms)
09752 {
09753    char c;
09754 
09755    *str = 0; /* start with empty output buffer */
09756    for (;;)
09757    {
09758       /* Wait for the first digit (up to specified ms). */
09759       c = ast_waitfordigit(chan, ms);
09760       /* if timeout, hangup or error, return as such */
09761       if (c < 1)
09762          return c;
09763       *str++ = c;
09764       *str = 0;
09765       if (strchr(term, c))
09766          return 1;
09767    }
09768 }
09769 
09770 static int dahdi_wink(struct dahdi_pvt *p, int idx)
09771 {
09772    int j;
09773    dahdi_set_hook(p->subs[idx].dfd, DAHDI_WINK);
09774    for (;;)
09775    {
09776       /* set bits of interest */
09777       j = DAHDI_IOMUX_SIGEVENT;
09778       /* wait for some happening */
09779       if (ioctl(p->subs[idx].dfd,DAHDI_IOMUX,&j) == -1) return(-1);
09780       /* exit loop if we have it */
09781       if (j & DAHDI_IOMUX_SIGEVENT) break;
09782    }
09783    /* get the event info */
09784    if (ioctl(p->subs[idx].dfd,DAHDI_GETEVENT,&j) == -1) return(-1);
09785    return 0;
09786 }
09787 
09788 /*! \brief enable or disable the chan_dahdi Do-Not-Disturb mode for a DAHDI channel
09789  * \param dahdichan "Physical" DAHDI channel (e.g: DAHDI/5)
09790  * \param flag on 1 to enable, 0 to disable, -1 return dnd value
09791  *
09792  * chan_dahdi has a DND (Do Not Disturb) mode for each dahdichan (physical
09793  * DAHDI channel). Use this to enable or disable it.
09794  *
09795  * \bug the use of the word "channel" for those dahdichans is really confusing.
09796  */
09797 static int dahdi_dnd(struct dahdi_pvt *dahdichan, int flag)
09798 {
09799    if (analog_lib_handles(dahdichan->sig, dahdichan->radio, dahdichan->oprmode)) {
09800       return analog_dnd(dahdichan->sig_pvt, flag);
09801    }
09802 
09803    if (flag == -1) {
09804       return dahdichan->dnd;
09805    }
09806 
09807    /* Do not disturb */
09808    dahdichan->dnd = flag;
09809    ast_verb(3, "%s DND on channel %d\n",
09810          flag? "Enabled" : "Disabled",
09811          dahdichan->channel);
09812    manager_event(EVENT_FLAG_SYSTEM, "DNDState",
09813          "Channel: DAHDI/%d\r\n"
09814          "Status: %s\r\n", dahdichan->channel,
09815          flag? "enabled" : "disabled");
09816 
09817    return 0;
09818 }
09819 
09820 static int canmatch_featurecode(const char *exten)
09821 {
09822    int extlen = strlen(exten);
09823    const char *pickup_ext;
09824    if (!extlen) {
09825       return 1;
09826    }
09827    pickup_ext = ast_pickup_ext();
09828    if (extlen < strlen(pickup_ext) && !strncmp(pickup_ext, exten, extlen)) {
09829       return 1;
09830    }
09831    /* hardcoded features are *60, *67, *69, *70, *72, *73, *78, *79, *82, *0 */
09832    if (exten[0] == '*' && extlen < 3) {
09833       if (extlen == 1) {
09834          return 1;
09835       }
09836       /* "*0" should be processed before it gets here */
09837       switch (exten[1]) {
09838       case '6':
09839       case '7':
09840       case '8':
09841          return 1;
09842       }
09843    }
09844    return 0;
09845 }
09846 
09847 static void *analog_ss_thread(void *data)
09848 {
09849    struct ast_channel *chan = data;
09850    struct dahdi_pvt *p = chan->tech_pvt;
09851    char exten[AST_MAX_EXTENSION] = "";
09852    char exten2[AST_MAX_EXTENSION] = "";
09853    unsigned char buf[256];
09854    char dtmfcid[300];
09855    char dtmfbuf[300];
09856    struct callerid_state *cs = NULL;
09857    char *name = NULL, *number = NULL;
09858    int distMatches;
09859    int curRingData[3];
09860    int receivedRingT;
09861    int counter1;
09862    int counter;
09863    int samples = 0;
09864    struct ast_smdi_md_message *smdi_msg = NULL;
09865    int flags = 0;
09866    int i;
09867    int timeout;
09868    int getforward = 0;
09869    char *s1, *s2;
09870    int len = 0;
09871    int res;
09872    int idx;
09873 
09874    ast_mutex_lock(&ss_thread_lock);
09875    ss_thread_count++;
09876    ast_mutex_unlock(&ss_thread_lock);
09877    /* in the bizarre case where the channel has become a zombie before we
09878       even get started here, abort safely
09879    */
09880    if (!p) {
09881       ast_log(LOG_WARNING, "Channel became a zombie before simple switch could be started (%s)\n", chan->name);
09882       ast_hangup(chan);
09883       goto quit;
09884    }
09885    ast_verb(3, "Starting simple switch on '%s'\n", chan->name);
09886    idx = dahdi_get_index(chan, p, 1);
09887    if (idx < 0) {
09888       ast_log(LOG_WARNING, "Huh?\n");
09889       ast_hangup(chan);
09890       goto quit;
09891    }
09892    if (p->dsp)
09893       ast_dsp_digitreset(p->dsp);
09894    switch (p->sig) {
09895    case SIG_FEATD:
09896    case SIG_FEATDMF:
09897    case SIG_FEATDMF_TA:
09898    case SIG_E911:
09899    case SIG_FGC_CAMAMF:
09900    case SIG_FEATB:
09901    case SIG_EMWINK:
09902    case SIG_SF_FEATD:
09903    case SIG_SF_FEATDMF:
09904    case SIG_SF_FEATB:
09905    case SIG_SFWINK:
09906       if (dahdi_wink(p, idx))
09907          goto quit;
09908       /* Fall through */
09909    case SIG_EM:
09910    case SIG_EM_E1:
09911    case SIG_SF:
09912    case SIG_FGC_CAMA:
09913       res = tone_zone_play_tone(p->subs[idx].dfd, -1);
09914       if (p->dsp)
09915          ast_dsp_digitreset(p->dsp);
09916       /* set digit mode appropriately */
09917       if (p->dsp) {
09918          if (NEED_MFDETECT(p))
09919             ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
09920          else
09921             ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
09922       }
09923       memset(dtmfbuf, 0, sizeof(dtmfbuf));
09924       /* Wait for the first digit only if immediate=no */
09925       if (!p->immediate)
09926          /* Wait for the first digit (up to 5 seconds). */
09927          res = ast_waitfordigit(chan, 5000);
09928       else
09929          res = 0;
09930       if (res > 0) {
09931          /* save first char */
09932          dtmfbuf[0] = res;
09933          switch (p->sig) {
09934          case SIG_FEATD:
09935          case SIG_SF_FEATD:
09936             res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
09937             if (res > 0)
09938                res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
09939             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
09940             break;
09941          case SIG_FEATDMF_TA:
09942             res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
09943             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
09944             if (dahdi_wink(p, idx)) goto quit;
09945             dtmfbuf[0] = 0;
09946             /* Wait for the first digit (up to 5 seconds). */
09947             res = ast_waitfordigit(chan, 5000);
09948             if (res <= 0) break;
09949             dtmfbuf[0] = res;
09950             /* fall through intentionally */
09951          case SIG_FEATDMF:
09952          case SIG_E911:
09953          case SIG_FGC_CAMAMF:
09954          case SIG_SF_FEATDMF:
09955             res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
09956             /* if international caca, do it again to get real ANO */
09957             if ((p->sig == SIG_FEATDMF) && (dtmfbuf[1] != '0') && (strlen(dtmfbuf) != 14))
09958             {
09959                if (dahdi_wink(p, idx)) goto quit;
09960                dtmfbuf[0] = 0;
09961                /* Wait for the first digit (up to 5 seconds). */
09962                res = ast_waitfordigit(chan, 5000);
09963                if (res <= 0) break;
09964                dtmfbuf[0] = res;
09965                res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
09966             }
09967             if (res > 0) {
09968                /* if E911, take off hook */
09969                if (p->sig == SIG_E911)
09970                   dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
09971                res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "#", 3000);
09972             }
09973             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
09974             break;
09975          case SIG_FEATB:
09976          case SIG_SF_FEATB:
09977             res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
09978             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
09979             break;
09980          case SIG_EMWINK:
09981             /* if we received a '*', we are actually receiving Feature Group D
09982                dial syntax, so use that mode; otherwise, fall through to normal
09983                mode
09984             */
09985             if (res == '*') {
09986                res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
09987                if (res > 0)
09988                   res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
09989                if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
09990                break;
09991             }
09992          default:
09993             /* If we got the first digit, get the rest */
09994             len = 1;
09995             dtmfbuf[len] = '\0';
09996             while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
09997                if (ast_exists_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
09998                   timeout = matchdigittimeout;
09999                } else {
10000                   timeout = gendigittimeout;
10001                }
10002                res = ast_waitfordigit(chan, timeout);
10003                if (res < 0) {
10004                   ast_debug(1, "waitfordigit returned < 0...\n");
10005                   ast_hangup(chan);
10006                   goto quit;
10007                } else if (res) {
10008                   dtmfbuf[len++] = res;
10009                   dtmfbuf[len] = '\0';
10010                } else {
10011                   break;
10012                }
10013             }
10014             break;
10015          }
10016       }
10017       if (res == -1) {
10018          ast_log(LOG_WARNING, "getdtmf on channel %d: %s\n", p->channel, strerror(errno));
10019          ast_hangup(chan);
10020          goto quit;
10021       } else if (res < 0) {
10022          ast_debug(1, "Got hung up before digits finished\n");
10023          ast_hangup(chan);
10024          goto quit;
10025       }
10026 
10027       if (p->sig == SIG_FGC_CAMA) {
10028          char anibuf[100];
10029 
10030          if (ast_safe_sleep(chan,1000) == -1) {
10031             ast_hangup(chan);
10032             goto quit;
10033          }
10034          dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
10035          ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
10036          res = my_getsigstr(chan, anibuf, "#", 10000);
10037          if ((res > 0) && (strlen(anibuf) > 2)) {
10038             if (anibuf[strlen(anibuf) - 1] == '#')
10039                anibuf[strlen(anibuf) - 1] = 0;
10040             ast_set_callerid(chan, anibuf + 2, NULL, anibuf + 2);
10041          }
10042          ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
10043       }
10044 
10045       ast_copy_string(exten, dtmfbuf, sizeof(exten));
10046       if (ast_strlen_zero(exten))
10047          ast_copy_string(exten, "s", sizeof(exten));
10048       if (p->sig == SIG_FEATD || p->sig == SIG_EMWINK) {
10049          /* Look for Feature Group D on all E&M Wink and Feature Group D trunks */
10050          if (exten[0] == '*') {
10051             char *stringp=NULL;
10052             ast_copy_string(exten2, exten, sizeof(exten2));
10053             /* Parse out extension and callerid */
10054             stringp=exten2 +1;
10055             s1 = strsep(&stringp, "*");
10056             s2 = strsep(&stringp, "*");
10057             if (s2) {
10058                if (!ast_strlen_zero(p->cid_num))
10059                   ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
10060                else
10061                   ast_set_callerid(chan, s1, NULL, s1);
10062                ast_copy_string(exten, s2, sizeof(exten));
10063             } else
10064                ast_copy_string(exten, s1, sizeof(exten));
10065          } else if (p->sig == SIG_FEATD)
10066             ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d.  Assuming E&M Wink instead\n", p->channel);
10067       }
10068       if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
10069          if (exten[0] == '*') {
10070             char *stringp=NULL;
10071             ast_copy_string(exten2, exten, sizeof(exten2));
10072             /* Parse out extension and callerid */
10073             stringp=exten2 +1;
10074             s1 = strsep(&stringp, "#");
10075             s2 = strsep(&stringp, "#");
10076             if (s2) {
10077                if (!ast_strlen_zero(p->cid_num))
10078                   ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
10079                else
10080                   if (*(s1 + 2))
10081                      ast_set_callerid(chan, s1 + 2, NULL, s1 + 2);
10082                ast_copy_string(exten, s2 + 1, sizeof(exten));
10083             } else
10084                ast_copy_string(exten, s1 + 2, sizeof(exten));
10085          } else
10086             ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d.  Assuming E&M Wink instead\n", p->channel);
10087       }
10088       if ((p->sig == SIG_E911) || (p->sig == SIG_FGC_CAMAMF)) {
10089          if (exten[0] == '*') {
10090             char *stringp=NULL;
10091             ast_copy_string(exten2, exten, sizeof(exten2));
10092             /* Parse out extension and callerid */
10093             stringp=exten2 +1;
10094             s1 = strsep(&stringp, "#");
10095             s2 = strsep(&stringp, "#");
10096             if (s2 && (*(s2 + 1) == '0')) {
10097                if (*(s2 + 2))
10098                   ast_set_callerid(chan, s2 + 2, NULL, s2 + 2);
10099             }
10100             if (s1)  ast_copy_string(exten, s1, sizeof(exten));
10101             else ast_copy_string(exten, "911", sizeof(exten));
10102          } else
10103             ast_log(LOG_WARNING, "Got a non-E911/FGC CAMA input on channel %d.  Assuming E&M Wink instead\n", p->channel);
10104       }
10105       if (p->sig == SIG_FEATB) {
10106          if (exten[0] == '*') {
10107             char *stringp=NULL;
10108             ast_copy_string(exten2, exten, sizeof(exten2));
10109             /* Parse out extension and callerid */
10110             stringp=exten2 +1;
10111             s1 = strsep(&stringp, "#");
10112             ast_copy_string(exten, exten2 + 1, sizeof(exten));
10113          } else
10114             ast_log(LOG_WARNING, "Got a non-Feature Group B input on channel %d.  Assuming E&M Wink instead\n", p->channel);
10115       }
10116       if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
10117          dahdi_wink(p, idx);
10118          /* some switches require a minimum guard time between
10119             the last FGD wink and something that answers
10120             immediately. This ensures it */
10121          if (ast_safe_sleep(chan, 100)) {
10122             ast_hangup(chan);
10123             goto quit;
10124          }
10125       }
10126       dahdi_enable_ec(p);
10127       if (NEED_MFDETECT(p)) {
10128          if (p->dsp) {
10129             if (!p->hardwaredtmf)
10130                ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
10131             else {
10132                ast_dsp_free(p->dsp);
10133                p->dsp = NULL;
10134             }
10135          }
10136       }
10137 
10138       if (ast_exists_extension(chan, chan->context, exten, 1,
10139          S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
10140          ast_copy_string(chan->exten, exten, sizeof(chan->exten));
10141          if (p->dsp) ast_dsp_digitreset(p->dsp);
10142          res = ast_pbx_run(chan);
10143          if (res) {
10144             ast_log(LOG_WARNING, "PBX exited non-zero\n");
10145             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10146          }
10147          goto quit;
10148       } else {
10149          ast_verb(2, "Unknown extension '%s' in context '%s' requested\n", exten, chan->context);
10150          sleep(2);
10151          res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_INFO);
10152          if (res < 0)
10153             ast_log(LOG_WARNING, "Unable to start special tone on %d\n", p->channel);
10154          else
10155             sleep(1);
10156          res = ast_streamfile(chan, "ss-noservice", chan->language);
10157          if (res >= 0)
10158             ast_waitstream(chan, "");
10159          res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10160          ast_hangup(chan);
10161          goto quit;
10162       }
10163       break;
10164    case SIG_FXOLS:
10165    case SIG_FXOGS:
10166    case SIG_FXOKS:
10167       /* Read the first digit */
10168       timeout = firstdigittimeout;
10169       /* If starting a threeway call, never timeout on the first digit so someone
10170          can use flash-hook as a "hold" feature */
10171       if (p->subs[SUB_THREEWAY].owner)
10172          timeout = 999999;
10173       while (len < AST_MAX_EXTENSION-1) {
10174          /* Read digit unless it's supposed to be immediate, in which case the
10175             only answer is 's' */
10176          if (p->immediate)
10177             res = 's';
10178          else
10179             res = ast_waitfordigit(chan, timeout);
10180          timeout = 0;
10181          if (res < 0) {
10182             ast_debug(1, "waitfordigit returned < 0...\n");
10183             res = tone_zone_play_tone(p->subs[idx].dfd, -1);
10184             ast_hangup(chan);
10185             goto quit;
10186          } else if (res) {
10187             ast_debug(1,"waitfordigit returned '%c' (%d), timeout = %d\n", res, res, timeout);
10188             exten[len++]=res;
10189             exten[len] = '\0';
10190          }
10191          if (!ast_ignore_pattern(chan->context, exten))
10192             tone_zone_play_tone(p->subs[idx].dfd, -1);
10193          else
10194             tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
10195          if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num) && !ast_parking_ext_valid(exten, chan, chan->context)) {
10196             if (!res || !ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
10197                if (getforward) {
10198                   /* Record this as the forwarding extension */
10199                   ast_copy_string(p->call_forward, exten, sizeof(p->call_forward));
10200                   ast_verb(3, "Setting call forward to '%s' on channel %d\n", p->call_forward, p->channel);
10201                   res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10202                   if (res)
10203                      break;
10204                   usleep(500000);
10205                   res = tone_zone_play_tone(p->subs[idx].dfd, -1);
10206                   sleep(1);
10207                   memset(exten, 0, sizeof(exten));
10208                   res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
10209                   len = 0;
10210                   getforward = 0;
10211                } else {
10212                   res = tone_zone_play_tone(p->subs[idx].dfd, -1);
10213                   ast_copy_string(chan->exten, exten, sizeof(chan->exten));
10214                   if (!ast_strlen_zero(p->cid_num)) {
10215                      if (!p->hidecallerid)
10216                         ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
10217                      else
10218                         ast_set_callerid(chan, NULL, NULL, p->cid_num);
10219                   }
10220                   if (!ast_strlen_zero(p->cid_name)) {
10221                      if (!p->hidecallerid)
10222                         ast_set_callerid(chan, NULL, p->cid_name, NULL);
10223                   }
10224                   ast_setstate(chan, AST_STATE_RING);
10225                   dahdi_enable_ec(p);
10226                   res = ast_pbx_run(chan);
10227                   if (res) {
10228                      ast_log(LOG_WARNING, "PBX exited non-zero\n");
10229                      res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10230                   }
10231                   goto quit;
10232                }
10233             } else {
10234                /* It's a match, but they just typed a digit, and there is an ambiguous match,
10235                   so just set the timeout to matchdigittimeout and wait some more */
10236                timeout = matchdigittimeout;
10237             }
10238          } else if (res == 0) {
10239             ast_debug(1, "not enough digits (and no ambiguous match)...\n");
10240             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10241             dahdi_wait_event(p->subs[idx].dfd);
10242             ast_hangup(chan);
10243             goto quit;
10244          } else if (p->callwaiting && !strcmp(exten, "*70")) {
10245             ast_verb(3, "Disabling call waiting on %s\n", chan->name);
10246             /* Disable call waiting if enabled */
10247             p->callwaiting = 0;
10248             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10249             if (res) {
10250                ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
10251                   chan->name, strerror(errno));
10252             }
10253             len = 0;
10254             ioctl(p->subs[idx].dfd,DAHDI_CONFDIAG,&len);
10255             memset(exten, 0, sizeof(exten));
10256             timeout = firstdigittimeout;
10257 
10258          } else if (!strcmp(exten,ast_pickup_ext())) {
10259             /* Scan all channels and see if there are any
10260              * ringing channels that have call groups
10261              * that equal this channels pickup group
10262              */
10263             if (idx == SUB_REAL) {
10264                /* Switch us from Third call to Call Wait */
10265                if (p->subs[SUB_THREEWAY].owner) {
10266                   /* If you make a threeway call and the *8# a call, it should actually
10267                      look like a callwait */
10268                   alloc_sub(p, SUB_CALLWAIT);
10269                   swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
10270                   unalloc_sub(p, SUB_THREEWAY);
10271                }
10272                dahdi_enable_ec(p);
10273                if (ast_pickup_call(chan)) {
10274                   ast_debug(1, "No call pickup possible...\n");
10275                   res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10276                   dahdi_wait_event(p->subs[idx].dfd);
10277                }
10278                ast_hangup(chan);
10279                goto quit;
10280             } else {
10281                ast_log(LOG_WARNING, "Huh?  Got *8# on call not on real\n");
10282                ast_hangup(chan);
10283                goto quit;
10284             }
10285 
10286          } else if (!p->hidecallerid && !strcmp(exten, "*67")) {
10287             ast_verb(3, "Disabling Caller*ID on %s\n", chan->name);
10288             /* Disable Caller*ID if enabled */
10289             p->hidecallerid = 1;
10290             ast_party_number_free(&chan->caller.id.number);
10291             ast_party_number_init(&chan->caller.id.number);
10292             ast_party_name_free(&chan->caller.id.name);
10293             ast_party_name_init(&chan->caller.id.name);
10294             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10295             if (res) {
10296                ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
10297                   chan->name, strerror(errno));
10298             }
10299             len = 0;
10300             memset(exten, 0, sizeof(exten));
10301             timeout = firstdigittimeout;
10302          } else if (p->callreturn && !strcmp(exten, "*69")) {
10303             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10304             break;
10305          } else if (!strcmp(exten, "*78")) {
10306             dahdi_dnd(p, 1);
10307             /* Do not disturb */
10308             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10309             getforward = 0;
10310             memset(exten, 0, sizeof(exten));
10311             len = 0;
10312          } else if (!strcmp(exten, "*79")) {
10313             dahdi_dnd(p, 0);
10314             /* Do not disturb */
10315             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10316             getforward = 0;
10317             memset(exten, 0, sizeof(exten));
10318             len = 0;
10319          } else if (p->cancallforward && !strcmp(exten, "*72")) {
10320             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10321             getforward = 1;
10322             memset(exten, 0, sizeof(exten));
10323             len = 0;
10324          } else if (p->cancallforward && !strcmp(exten, "*73")) {
10325             ast_verb(3, "Cancelling call forwarding on channel %d\n", p->channel);
10326             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10327             memset(p->call_forward, 0, sizeof(p->call_forward));
10328             getforward = 0;
10329             memset(exten, 0, sizeof(exten));
10330             len = 0;
10331          } else if ((p->transfer || p->canpark) && ast_parking_ext_valid(exten, chan, chan->context) &&
10332                   p->subs[SUB_THREEWAY].owner &&
10333                   ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
10334             /* This is a three way call, the main call being a real channel,
10335                and we're parking the first call. */
10336             ast_masq_park_call_exten(ast_bridged_channel(p->subs[SUB_THREEWAY].owner),
10337                chan, exten, chan->context, 0, NULL);
10338             ast_verb(3, "Parking call to '%s'\n", chan->name);
10339             break;
10340          } else if (p->hidecallerid && !strcmp(exten, "*82")) {
10341             ast_verb(3, "Enabling Caller*ID on %s\n", chan->name);
10342             /* Enable Caller*ID if enabled */
10343             p->hidecallerid = 0;
10344             ast_set_callerid(chan, p->cid_num, p->cid_name, NULL);
10345             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10346             if (res) {
10347                ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
10348                   chan->name, strerror(errno));
10349             }
10350             len = 0;
10351             memset(exten, 0, sizeof(exten));
10352             timeout = firstdigittimeout;
10353          } else if (!strcmp(exten, "*0")) {
10354             struct ast_channel *nbridge =
10355                p->subs[SUB_THREEWAY].owner;
10356             struct dahdi_pvt *pbridge = NULL;
10357             /* set up the private struct of the bridged one, if any */
10358             if (nbridge && ast_bridged_channel(nbridge))
10359                pbridge = ast_bridged_channel(nbridge)->tech_pvt;
10360             if (nbridge && pbridge &&
10361                (nbridge->tech == &dahdi_tech) &&
10362                (ast_bridged_channel(nbridge)->tech == &dahdi_tech) &&
10363                ISTRUNK(pbridge)) {
10364                int func = DAHDI_FLASH;
10365                /* Clear out the dial buffer */
10366                p->dop.dialstr[0] = '\0';
10367                /* flash hookswitch */
10368                if ((ioctl(pbridge->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
10369                   ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
10370                      nbridge->name, strerror(errno));
10371                }
10372                swap_subs(p, SUB_REAL, SUB_THREEWAY);
10373                unalloc_sub(p, SUB_THREEWAY);
10374                p->owner = p->subs[SUB_REAL].owner;
10375                if (ast_bridged_channel(p->subs[SUB_REAL].owner))
10376                   ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
10377                ast_hangup(chan);
10378                goto quit;
10379             } else {
10380                tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10381                dahdi_wait_event(p->subs[idx].dfd);
10382                tone_zone_play_tone(p->subs[idx].dfd, -1);
10383                swap_subs(p, SUB_REAL, SUB_THREEWAY);
10384                unalloc_sub(p, SUB_THREEWAY);
10385                p->owner = p->subs[SUB_REAL].owner;
10386                ast_hangup(chan);
10387                goto quit;
10388             }
10389          } else if (!ast_canmatch_extension(chan, chan->context, exten, 1,
10390             S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))
10391             && !canmatch_featurecode(exten)) {
10392             ast_debug(1, "Can't match %s from '%s' in context %s\n", exten,
10393                S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, "<Unknown Caller>"),
10394                chan->context);
10395             break;
10396          }
10397          if (!timeout)
10398             timeout = gendigittimeout;
10399          if (len && !ast_ignore_pattern(chan->context, exten))
10400             tone_zone_play_tone(p->subs[idx].dfd, -1);
10401       }
10402       break;
10403    case SIG_FXSLS:
10404    case SIG_FXSGS:
10405    case SIG_FXSKS:
10406       /* check for SMDI messages */
10407       if (p->use_smdi && p->smdi_iface) {
10408          smdi_msg = ast_smdi_md_message_wait(p->smdi_iface, SMDI_MD_WAIT_TIMEOUT);
10409 
10410          if (smdi_msg != NULL) {
10411             ast_copy_string(chan->exten, smdi_msg->fwd_st, sizeof(chan->exten));
10412 
10413             if (smdi_msg->type == 'B')
10414                pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "b");
10415             else if (smdi_msg->type == 'N')
10416                pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "u");
10417 
10418             ast_debug(1, "Received SMDI message on %s\n", chan->name);
10419          } else {
10420             ast_log(LOG_WARNING, "SMDI enabled but no SMDI message present\n");
10421          }
10422       }
10423 
10424       if (p->use_callerid && (p->cid_signalling == CID_SIG_SMDI && smdi_msg)) {
10425          number = smdi_msg->calling_st;
10426 
10427       /* If we want caller id, we're in a prering state due to a polarity reversal
10428        * and we're set to use a polarity reversal to trigger the start of caller id,
10429        * grab the caller id and wait for ringing to start... */
10430       } else if (p->use_callerid && (chan->_state == AST_STATE_PRERING &&
10431                    (p->cid_start == CID_START_POLARITY || p->cid_start == CID_START_POLARITY_IN || p->cid_start == CID_START_DTMF_NOALERT))) {
10432          /* If set to use DTMF CID signalling, listen for DTMF */
10433          if (p->cid_signalling == CID_SIG_DTMF) {
10434             int k = 0;
10435             cs = NULL;
10436             ast_debug(1, "Receiving DTMF cid on channel %s\n", chan->name);
10437             dahdi_setlinear(p->subs[idx].dfd, 0);
10438             /*
10439              * We are the only party interested in the Rx stream since
10440              * we have not answered yet.  We don't need or even want DTMF
10441              * emulation.  The DTMF digits can come so fast that emulation
10442              * can drop some of them.
10443              */
10444             ast_set_flag(chan, AST_FLAG_END_DTMF_ONLY);
10445             res = 4000;/* This is a typical OFF time between rings. */
10446             for (;;) {
10447                struct ast_frame *f;
10448                res = ast_waitfor(chan, res);
10449                if (res <= 0) {
10450                   /*
10451                    * We do not need to restore the dahdi_setlinear()
10452                    * or AST_FLAG_END_DTMF_ONLY flag settings since we
10453                    * are hanging up the channel.
10454                    */
10455                   ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
10456                      "Exiting simple switch\n");
10457                   ast_hangup(chan);
10458                   goto quit;
10459                }
10460                f = ast_read(chan);
10461                if (!f)
10462                   break;
10463                if (f->frametype == AST_FRAME_DTMF) {
10464                   if (k < ARRAY_LEN(dtmfbuf) - 1) {
10465                      dtmfbuf[k++] = f->subclass.integer;
10466                   }
10467                   ast_debug(1, "CID got digit '%c'\n", f->subclass.integer);
10468                   res = 4000;/* This is a typical OFF time between rings. */
10469                }
10470                ast_frfree(f);
10471                if (chan->_state == AST_STATE_RING ||
10472                   chan->_state == AST_STATE_RINGING)
10473                   break; /* Got ring */
10474             }
10475             ast_clear_flag(chan, AST_FLAG_END_DTMF_ONLY);
10476             dtmfbuf[k] = '\0';
10477             dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10478             /* Got cid and ring. */
10479             ast_debug(1, "CID got string '%s'\n", dtmfbuf);
10480             callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
10481             ast_debug(1, "CID is '%s', flags %d\n", dtmfcid, flags);
10482             /* If first byte is NULL, we have no cid */
10483             if (!ast_strlen_zero(dtmfcid))
10484                number = dtmfcid;
10485             else
10486                number = NULL;
10487          /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */
10488          } else if ((p->cid_signalling == CID_SIG_V23) || (p->cid_signalling == CID_SIG_V23_JP)) {
10489             cs = callerid_new(p->cid_signalling);
10490             if (cs) {
10491                samples = 0;
10492 #if 1
10493                bump_gains(p);
10494 #endif
10495                /* Take out of linear mode for Caller*ID processing */
10496                dahdi_setlinear(p->subs[idx].dfd, 0);
10497 
10498                /* First we wait and listen for the Caller*ID */
10499                for (;;) {
10500                   i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10501                   if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10502                      ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10503                      callerid_free(cs);
10504                      ast_hangup(chan);
10505                      goto quit;
10506                   }
10507                   if (i & DAHDI_IOMUX_SIGEVENT) {
10508                      res = dahdi_get_event(p->subs[idx].dfd);
10509                      ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10510                      if (res == DAHDI_EVENT_NOALARM) {
10511                         p->inalarm = 0;
10512                      }
10513 
10514                      if (p->cid_signalling == CID_SIG_V23_JP) {
10515                         if (res == DAHDI_EVENT_RINGBEGIN) {
10516                            res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
10517                            usleep(1);
10518                         }
10519                      } else {
10520                         res = 0;
10521                         break;
10522                      }
10523                   } else if (i & DAHDI_IOMUX_READ) {
10524                      res = read(p->subs[idx].dfd, buf, sizeof(buf));
10525                      if (res < 0) {
10526                         if (errno != ELAST) {
10527                            ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10528                            callerid_free(cs);
10529                            ast_hangup(chan);
10530                            goto quit;
10531                         }
10532                         break;
10533                      }
10534                      samples += res;
10535 
10536                      if (p->cid_signalling == CID_SIG_V23_JP) {
10537                         res = callerid_feed_jp(cs, buf, res, AST_LAW(p));
10538                      } else {
10539                         res = callerid_feed(cs, buf, res, AST_LAW(p));
10540                      }
10541                      if (res < 0) {
10542                         /*
10543                          * The previous diagnostic message output likely
10544                          * explains why it failed.
10545                          */
10546                         ast_log(LOG_WARNING,
10547                            "Failed to decode CallerID on channel '%s'\n",
10548                            chan->name);
10549                         break;
10550                      } else if (res)
10551                         break;
10552                      else if (samples > (8000 * 10))
10553                         break;
10554                   }
10555                }
10556                if (res == 1) {
10557                   callerid_get(cs, &name, &number, &flags);
10558                   ast_log(LOG_NOTICE, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
10559                }
10560 
10561                if (p->cid_signalling == CID_SIG_V23_JP) {
10562                   res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
10563                   usleep(1);
10564                }
10565 
10566                /* Finished with Caller*ID, now wait for a ring to make sure there really is a call coming */
10567                res = 4000;/* This is a typical OFF time between rings. */
10568                for (;;) {
10569                   struct ast_frame *f;
10570                   res = ast_waitfor(chan, res);
10571                   if (res <= 0) {
10572                      ast_log(LOG_WARNING, "CID timed out waiting for ring. "
10573                         "Exiting simple switch\n");
10574                      ast_hangup(chan);
10575                      goto quit;
10576                   }
10577                   if (!(f = ast_read(chan))) {
10578                      ast_log(LOG_WARNING, "Hangup received waiting for ring. Exiting simple switch\n");
10579                      ast_hangup(chan);
10580                      goto quit;
10581                   }
10582                   ast_frfree(f);
10583                   if (chan->_state == AST_STATE_RING ||
10584                      chan->_state == AST_STATE_RINGING)
10585                      break; /* Got ring */
10586                }
10587 
10588                /* We must have a ring by now, so, if configured, lets try to listen for
10589                 * distinctive ringing */
10590                if (p->usedistinctiveringdetection) {
10591                   len = 0;
10592                   distMatches = 0;
10593                   /* Clear the current ring data array so we don't have old data in it. */
10594                   for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
10595                      curRingData[receivedRingT] = 0;
10596                   receivedRingT = 0;
10597                   counter = 0;
10598                   counter1 = 0;
10599                   /* Check to see if context is what it should be, if not set to be. */
10600                   if (strcmp(p->context,p->defcontext) != 0) {
10601                      ast_copy_string(p->context, p->defcontext, sizeof(p->context));
10602                      ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
10603                   }
10604 
10605                   for (;;) {
10606                      i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10607                      if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10608                         ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10609                         callerid_free(cs);
10610                         ast_hangup(chan);
10611                         goto quit;
10612                      }
10613                      if (i & DAHDI_IOMUX_SIGEVENT) {
10614                         res = dahdi_get_event(p->subs[idx].dfd);
10615                         ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10616                         if (res == DAHDI_EVENT_NOALARM) {
10617                            p->inalarm = 0;
10618                         }
10619                         res = 0;
10620                         /* Let us detect distinctive ring */
10621 
10622                         curRingData[receivedRingT] = p->ringt;
10623 
10624                         if (p->ringt < p->ringt_base/2)
10625                            break;
10626                         /* Increment the ringT counter so we can match it against
10627                            values in chan_dahdi.conf for distinctive ring */
10628                         if (++receivedRingT == ARRAY_LEN(curRingData))
10629                            break;
10630                      } else if (i & DAHDI_IOMUX_READ) {
10631                         res = read(p->subs[idx].dfd, buf, sizeof(buf));
10632                         if (res < 0) {
10633                            if (errno != ELAST) {
10634                               ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10635                               callerid_free(cs);
10636                               ast_hangup(chan);
10637                               goto quit;
10638                            }
10639                            break;
10640                         }
10641                         if (p->ringt > 0) {
10642                            if (!(--p->ringt)) {
10643                               res = -1;
10644                               break;
10645                            }
10646                         }
10647                      }
10648                   }
10649                      /* this only shows up if you have n of the dring patterns filled in */
10650                   ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
10651                   for (counter = 0; counter < 3; counter++) {
10652                      /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this
10653                      channel */
10654                      distMatches = 0;
10655                      for (counter1 = 0; counter1 < 3; counter1++) {
10656                         ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
10657                         if (p->drings.ringnum[counter].ring[counter1] == -1) {
10658                            ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
10659                            curRingData[counter1]);
10660                            distMatches++;
10661                         } else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
10662                               curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
10663                            ast_verb(3, "Ring pattern matched in range: %d to %d\n",
10664                            (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
10665                            (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
10666                            distMatches++;
10667                         }
10668                      }
10669 
10670                      if (distMatches == 3) {
10671                         /* The ring matches, set the context to whatever is for distinctive ring.. */
10672                         ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context));
10673                         ast_copy_string(chan->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(chan->context));
10674                         ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
10675                         break;
10676                      }
10677                   }
10678                }
10679                /* Restore linear mode (if appropriate) for Caller*ID processing */
10680                dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10681 #if 1
10682                restore_gains(p);
10683 #endif
10684             } else
10685                ast_log(LOG_WARNING, "Unable to get caller ID space\n");
10686          } else {
10687             ast_log(LOG_WARNING, "Channel %s in prering "
10688                "state, but I have nothing to do. "
10689                "Terminating simple switch, should be "
10690                "restarted by the actual ring.\n",
10691                chan->name);
10692             ast_hangup(chan);
10693             goto quit;
10694          }
10695       } else if (p->use_callerid && p->cid_start == CID_START_RING) {
10696          if (p->cid_signalling == CID_SIG_DTMF) {
10697             int k = 0;
10698             cs = NULL;
10699             dahdi_setlinear(p->subs[idx].dfd, 0);
10700             res = 2000;
10701             for (;;) {
10702                struct ast_frame *f;
10703                res = ast_waitfor(chan, res);
10704                if (res <= 0) {
10705                   ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
10706                      "Exiting simple switch\n");
10707                   ast_hangup(chan);
10708                   goto quit;
10709                }
10710                f = ast_read(chan);
10711                if (!f) {
10712                   /* Hangup received waiting for DTMFCID. Exiting simple switch. */
10713                   ast_hangup(chan);
10714                   goto quit;
10715                }
10716                if (f->frametype == AST_FRAME_DTMF) {
10717                   dtmfbuf[k++] = f->subclass.integer;
10718                   ast_log(LOG_DEBUG, "CID got digit '%c'\n", f->subclass.integer);
10719                   res = 2000;
10720                }
10721                ast_frfree(f);
10722 
10723                if (p->ringt_base == p->ringt)
10724                   break;
10725             }
10726             dtmfbuf[k] = '\0';
10727             dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10728             /* Got cid and ring. */
10729             callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
10730             ast_log(LOG_DEBUG, "CID is '%s', flags %d\n",
10731                dtmfcid, flags);
10732             /* If first byte is NULL, we have no cid */
10733             if (!ast_strlen_zero(dtmfcid))
10734                number = dtmfcid;
10735             else
10736                number = NULL;
10737             /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */
10738          } else {
10739             /* FSK Bell202 callerID */
10740             cs = callerid_new(p->cid_signalling);
10741             if (cs) {
10742 #if 1
10743                bump_gains(p);
10744 #endif
10745                samples = 0;
10746                len = 0;
10747                distMatches = 0;
10748                /* Clear the current ring data array so we don't have old data in it. */
10749                for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
10750                   curRingData[receivedRingT] = 0;
10751                receivedRingT = 0;
10752                counter = 0;
10753                counter1 = 0;
10754                /* Check to see if context is what it should be, if not set to be. */
10755                if (strcmp(p->context,p->defcontext) != 0) {
10756                   ast_copy_string(p->context, p->defcontext, sizeof(p->context));
10757                   ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
10758                }
10759 
10760                /* Take out of linear mode for Caller*ID processing */
10761                dahdi_setlinear(p->subs[idx].dfd, 0);
10762                for (;;) {
10763                   i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10764                   if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10765                      ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10766                      callerid_free(cs);
10767                      ast_hangup(chan);
10768                      goto quit;
10769                   }
10770                   if (i & DAHDI_IOMUX_SIGEVENT) {
10771                      res = dahdi_get_event(p->subs[idx].dfd);
10772                      ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10773                      if (res == DAHDI_EVENT_NOALARM) {
10774                         p->inalarm = 0;
10775                      }
10776                      /* If we get a PR event, they hung up while processing calerid */
10777                      if ( res == DAHDI_EVENT_POLARITY && p->hanguponpolarityswitch && p->polarity == POLARITY_REV) {
10778                         ast_log(LOG_DEBUG, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p->channel);
10779                         p->polarity = POLARITY_IDLE;
10780                         callerid_free(cs);
10781                         ast_hangup(chan);
10782                         goto quit;
10783                      }
10784                      res = 0;
10785                      /* Let us detect callerid when the telco uses distinctive ring */
10786 
10787                      curRingData[receivedRingT] = p->ringt;
10788 
10789                      if (p->ringt < p->ringt_base/2)
10790                         break;
10791                      /* Increment the ringT counter so we can match it against
10792                         values in chan_dahdi.conf for distinctive ring */
10793                      if (++receivedRingT == ARRAY_LEN(curRingData))
10794                         break;
10795                   } else if (i & DAHDI_IOMUX_READ) {
10796                      res = read(p->subs[idx].dfd, buf, sizeof(buf));
10797                      if (res < 0) {
10798                         if (errno != ELAST) {
10799                            ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10800                            callerid_free(cs);
10801                            ast_hangup(chan);
10802                            goto quit;
10803                         }
10804                         break;
10805                      }
10806                      if (p->ringt > 0) {
10807                         if (!(--p->ringt)) {
10808                            res = -1;
10809                            break;
10810                         }
10811                      }
10812                      samples += res;
10813                      res = callerid_feed(cs, buf, res, AST_LAW(p));
10814                      if (res < 0) {
10815                         /*
10816                          * The previous diagnostic message output likely
10817                          * explains why it failed.
10818                          */
10819                         ast_log(LOG_WARNING,
10820                            "Failed to decode CallerID on channel '%s'\n",
10821                            chan->name);
10822                         break;
10823                      } else if (res)
10824                         break;
10825                      else if (samples > (8000 * 10))
10826                         break;
10827                   }
10828                }
10829                if (res == 1) {
10830                   callerid_get(cs, &name, &number, &flags);
10831                   ast_debug(1, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
10832                }
10833                if (distinctiveringaftercid == 1) {
10834                   /* Clear the current ring data array so we don't have old data in it. */
10835                   for (receivedRingT = 0; receivedRingT < 3; receivedRingT++) {
10836                      curRingData[receivedRingT] = 0;
10837                   }
10838                   receivedRingT = 0;
10839                   ast_verb(3, "Detecting post-CID distinctive ring\n");
10840                   for (;;) {
10841                      i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10842                      if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10843                         ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10844                         callerid_free(cs);
10845                         ast_hangup(chan);
10846                         goto quit;
10847                      }
10848                      if (i & DAHDI_IOMUX_SIGEVENT) {
10849                         res = dahdi_get_event(p->subs[idx].dfd);
10850                         ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10851                         if (res == DAHDI_EVENT_NOALARM) {
10852                            p->inalarm = 0;
10853                         }
10854                         res = 0;
10855                         /* Let us detect callerid when the telco uses distinctive ring */
10856 
10857                         curRingData[receivedRingT] = p->ringt;
10858 
10859                         if (p->ringt < p->ringt_base/2)
10860                            break;
10861                         /* Increment the ringT counter so we can match it against
10862                            values in chan_dahdi.conf for distinctive ring */
10863                         if (++receivedRingT == ARRAY_LEN(curRingData))
10864                            break;
10865                      } else if (i & DAHDI_IOMUX_READ) {
10866                         res = read(p->subs[idx].dfd, buf, sizeof(buf));
10867                         if (res < 0) {
10868                            if (errno != ELAST) {
10869                               ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10870                               callerid_free(cs);
10871                               ast_hangup(chan);
10872                               goto quit;
10873                            }
10874                            break;
10875                         }
10876                         if (p->ringt > 0) {
10877                            if (!(--p->ringt)) {
10878                               res = -1;
10879                               break;
10880                            }
10881                         }
10882                      }
10883                   }
10884                }
10885                if (p->usedistinctiveringdetection) {
10886                   /* this only shows up if you have n of the dring patterns filled in */
10887                   ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
10888 
10889                   for (counter = 0; counter < 3; counter++) {
10890                      /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this
10891                      channel */
10892                      /* this only shows up if you have n of the dring patterns filled in */
10893                      ast_verb(3, "Checking %d,%d,%d\n",
10894                            p->drings.ringnum[counter].ring[0],
10895                            p->drings.ringnum[counter].ring[1],
10896                            p->drings.ringnum[counter].ring[2]);
10897                      distMatches = 0;
10898                      for (counter1 = 0; counter1 < 3; counter1++) {
10899                         ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
10900                         if (p->drings.ringnum[counter].ring[counter1] == -1) {
10901                            ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
10902                            curRingData[counter1]);
10903                            distMatches++;
10904                         }
10905                         else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
10906                            curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
10907                            ast_verb(3, "Ring pattern matched in range: %d to %d\n",
10908                            (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
10909                            (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
10910                            distMatches++;
10911                         }
10912                      }
10913                      if (distMatches == 3) {
10914                         /* The ring matches, set the context to whatever is for distinctive ring.. */
10915                         ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context));
10916                         ast_copy_string(chan->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(chan->context));
10917                         ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
10918                         break;
10919                      }
10920                   }
10921                }
10922                /* Restore linear mode (if appropriate) for Caller*ID processing */
10923                dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10924 #if 1
10925                restore_gains(p);
10926 #endif
10927                if (res < 0) {
10928                   ast_log(LOG_WARNING, "CallerID returned with error on channel '%s'\n", chan->name);
10929                }
10930             } else
10931                ast_log(LOG_WARNING, "Unable to get caller ID space\n");
10932          }
10933       } else
10934          cs = NULL;
10935 
10936       if (number)
10937          ast_shrink_phone_number(number);
10938       ast_set_callerid(chan, number, name, number);
10939 
10940       if (smdi_msg)
10941          ASTOBJ_UNREF(smdi_msg, ast_smdi_md_message_destroy);
10942 
10943       if (cs)
10944          callerid_free(cs);
10945 
10946       my_handle_notify_message(chan, p, flags, -1);
10947 
10948       ast_setstate(chan, AST_STATE_RING);
10949       chan->rings = 1;
10950       p->ringt = p->ringt_base;
10951       res = ast_pbx_run(chan);
10952       if (res) {
10953          ast_hangup(chan);
10954          ast_log(LOG_WARNING, "PBX exited non-zero\n");
10955       }
10956       goto quit;
10957    default:
10958       ast_log(LOG_WARNING, "Don't know how to handle simple switch with signalling %s on channel %d\n", sig2str(p->sig), p->channel);
10959       res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10960       if (res < 0)
10961             ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
10962    }
10963    res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10964    if (res < 0)
10965          ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
10966    ast_hangup(chan);
10967 quit:
10968    ast_mutex_lock(&ss_thread_lock);
10969    ss_thread_count--;
10970    ast_cond_signal(&ss_thread_complete);
10971    ast_mutex_unlock(&ss_thread_lock);
10972    return NULL;
10973 }
10974 
10975 struct mwi_thread_data {
10976    struct dahdi_pvt *pvt;
10977    unsigned char buf[READ_SIZE];
10978    size_t len;
10979 };
10980 
10981 static int calc_energy(const unsigned char *buf, int len, format_t law)
10982 {
10983    int x;
10984    int sum = 0;
10985 
10986    if (!len)
10987       return 0;
10988 
10989    for (x = 0; x < len; x++)
10990       sum += abs(law == AST_FORMAT_ULAW ? AST_MULAW(buf[x]) : AST_ALAW(buf[x]));
10991 
10992    return sum / len;
10993 }
10994 
10995 static void *mwi_thread(void *data)
10996 {
10997    struct mwi_thread_data *mtd = data;
10998    struct callerid_state *cs;
10999    pthread_t threadid;
11000    int samples = 0;
11001    char *name, *number;
11002    int flags;
11003    int i, res;
11004    unsigned int spill_done = 0;
11005    int spill_result = -1;
11006 
11007    if (!(cs = callerid_new(mtd->pvt->cid_signalling))) {
11008       mtd->pvt->mwimonitoractive = 0;
11009 
11010       return NULL;
11011    }
11012 
11013    callerid_feed(cs, mtd->buf, mtd->len, AST_LAW(mtd->pvt));
11014 
11015    bump_gains(mtd->pvt);
11016 
11017    for (;;) {
11018       i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
11019       if ((res = ioctl(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_IOMUX, &i))) {
11020          ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
11021          goto quit;
11022       }
11023 
11024       if (i & DAHDI_IOMUX_SIGEVENT) {
11025          struct ast_channel *chan;
11026 
11027          /* If we get an event, screen out events that we do not act on.
11028           * Otherwise, cancel and go to the simple switch to let it deal with it.
11029           */
11030          res = dahdi_get_event(mtd->pvt->subs[SUB_REAL].dfd);
11031 
11032          switch (res) {
11033          case DAHDI_EVENT_NEONMWI_ACTIVE:
11034          case DAHDI_EVENT_NEONMWI_INACTIVE:
11035          case DAHDI_EVENT_NONE:
11036          case DAHDI_EVENT_BITSCHANGED:
11037             break;
11038          case DAHDI_EVENT_NOALARM:
11039             if (analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) {
11040                struct analog_pvt *analog_p = mtd->pvt->sig_pvt;
11041 
11042                analog_p->inalarm = 0;
11043             }
11044             mtd->pvt->inalarm = 0;
11045             handle_clear_alarms(mtd->pvt);
11046             break;
11047          case DAHDI_EVENT_ALARM:
11048             if (analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) {
11049                struct analog_pvt *analog_p = mtd->pvt->sig_pvt;
11050 
11051                analog_p->inalarm = 1;
11052             }
11053             mtd->pvt->inalarm = 1;
11054             res = get_alarms(mtd->pvt);
11055             handle_alarms(mtd->pvt, res);
11056             break; /* What to do on channel alarm ???? -- fall thru intentionally?? */
11057          default:
11058             ast_log(LOG_NOTICE, "Got event %d (%s)...  Passing along to analog_ss_thread\n", res, event2str(res));
11059             callerid_free(cs);
11060 
11061             restore_gains(mtd->pvt);
11062             mtd->pvt->ringt = mtd->pvt->ringt_base;
11063 
11064             if ((chan = dahdi_new(mtd->pvt, AST_STATE_RING, 0, SUB_REAL, 0, NULL))) {
11065                int result;
11066                if (analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) {
11067                   result = analog_ss_thread_start(mtd->pvt->sig_pvt, chan);
11068                } else {
11069                   result = ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan);
11070                }
11071                if (result) {
11072                   ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", mtd->pvt->channel);
11073                   res = tone_zone_play_tone(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11074                   if (res < 0)
11075                      ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", mtd->pvt->channel);
11076                   ast_hangup(chan);
11077                   goto quit;
11078                }
11079                goto quit_no_clean;
11080 
11081             } else {
11082                ast_log(LOG_WARNING, "Could not create channel to handle call\n");
11083             }
11084          }
11085       } else if (i & DAHDI_IOMUX_READ) {
11086          if ((res = read(mtd->pvt->subs[SUB_REAL].dfd, mtd->buf, sizeof(mtd->buf))) < 0) {
11087             if (errno != ELAST) {
11088                ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
11089                goto quit;
11090             }
11091             break;
11092          }
11093          samples += res;
11094          if (!spill_done) {
11095             if ((spill_result = callerid_feed(cs, mtd->buf, res, AST_LAW(mtd->pvt))) < 0) {
11096                /*
11097                 * The previous diagnostic message output likely
11098                 * explains why it failed.
11099                 */
11100                ast_log(LOG_WARNING, "Failed to decode CallerID\n");
11101                break;
11102             } else if (spill_result) {
11103                spill_done = 1;
11104             }
11105          } else {
11106             /* keep reading data until the energy level drops below the threshold
11107                so we don't get another 'trigger' on the remaining carrier signal
11108             */
11109             if (calc_energy(mtd->buf, res, AST_LAW(mtd->pvt)) <= mwilevel)
11110                break;
11111          }
11112          if (samples > (8000 * 4)) /*Termination case - time to give up*/
11113             break;
11114       }
11115    }
11116 
11117    if (spill_result == 1) {
11118       callerid_get(cs, &name, &number, &flags);
11119       if (flags & CID_MSGWAITING) {
11120          ast_log(LOG_NOTICE, "mwi: Have Messages on channel %d\n", mtd->pvt->channel);
11121          notify_message(mtd->pvt->mailbox, 1);
11122       } else if (flags & CID_NOMSGWAITING) {
11123          ast_log(LOG_NOTICE, "mwi: No Messages on channel %d\n", mtd->pvt->channel);
11124          notify_message(mtd->pvt->mailbox, 0);
11125       } else {
11126          ast_log(LOG_NOTICE, "mwi: Status unknown on channel %d\n", mtd->pvt->channel);
11127       }
11128    }
11129 
11130 
11131 quit:
11132    callerid_free(cs);
11133 
11134    restore_gains(mtd->pvt);
11135 
11136 quit_no_clean:
11137    mtd->pvt->mwimonitoractive = 0;
11138 
11139    ast_free(mtd);
11140 
11141    return NULL;
11142 }
11143 
11144 /*
11145 * The following three functions (mwi_send_init, mwi_send_process_buffer,
11146 * mwi_send_process_event) work with the do_monitor thread to generate mwi spills
11147 * that are sent out via FXS port on voicemail state change.  The execution of
11148 * the mwi send is state driven and can either generate a ring pulse prior to
11149 * sending the fsk spill or simply send an fsk spill.
11150 */
11151 static int mwi_send_init(struct dahdi_pvt * pvt)
11152 {
11153    int x;
11154 
11155 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11156    /* Determine how this spill is to be sent */
11157    if (pvt->mwisend_rpas) {
11158       pvt->mwisend_data.mwisend_current = MWI_SEND_SA;
11159       pvt->mwisendactive = 1;
11160    } else if (pvt->mwisend_fsk) {
11161       pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
11162       pvt->mwisendactive = 1;
11163    } else {
11164       pvt->mwisendactive = 0;
11165       return 0;
11166    }
11167 #else
11168    if (mwisend_rpas) {
11169       pvt->mwisend_data.mwisend_current = MWI_SEND_SA;
11170    } else {
11171       pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
11172    }
11173    pvt->mwisendactive = 1;
11174 #endif
11175 
11176    if (pvt->cidspill) {
11177       ast_log(LOG_WARNING, "cidspill already exists when trying to send FSK MWI\n");
11178       ast_free(pvt->cidspill);
11179       pvt->cidspill = NULL;
11180       pvt->cidpos = 0;
11181       pvt->cidlen = 0;
11182    }
11183    pvt->cidspill = ast_calloc(1, MAX_CALLERID_SIZE);
11184    if (!pvt->cidspill) {
11185       pvt->mwisendactive = 0;
11186       return -1;
11187    }
11188    x = DAHDI_FLUSH_BOTH;
11189    ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
11190    x = 3000;
11191    ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_ONHOOKTRANSFER, &x);
11192 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11193    if (pvt->mwisend_fsk) {
11194 #endif
11195       pvt->cidlen = ast_callerid_vmwi_generate(pvt->cidspill, has_voicemail(pvt), CID_MWI_TYPE_MDMF_FULL,
11196                       AST_LAW(pvt), pvt->cid_name, pvt->cid_num, 0);
11197       pvt->cidpos = 0;
11198 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11199    }
11200 #endif
11201    return 0;
11202 }
11203 
11204 static int mwi_send_process_buffer(struct dahdi_pvt * pvt, int num_read)
11205 {
11206    struct timeval    now;
11207    int         res;
11208 
11209    /* sanity check to catch if this had been interrupted previously
11210    *  i.e. state says there is more to do but there is no spill allocated
11211    */
11212    if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current && !pvt->cidspill) {
11213       pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11214    } else if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current) {
11215       /* Normal processing -- Perform mwi send action */
11216       switch ( pvt->mwisend_data.mwisend_current) {
11217       case MWI_SEND_SA:
11218          /* Send the Ring Pulse Signal Alert */
11219          res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &AS_RP_cadence);
11220          if (res) {
11221             ast_log(LOG_WARNING, "Unable to set RP-AS ring cadence: %s\n", strerror(errno));
11222             goto quit;
11223          }
11224          res = dahdi_set_hook(pvt->subs[SUB_REAL].dfd, DAHDI_RING);
11225          pvt->mwisend_data.mwisend_current = MWI_SEND_SA_WAIT;
11226          break;
11227       case MWI_SEND_SA_WAIT:  /* do nothing until I get RINGEROFF event */
11228          break;
11229       case MWI_SEND_PAUSE:  /* Wait between alert and spill - min of 500 mS*/
11230 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11231          if (pvt->mwisend_fsk) {
11232 #endif
11233             gettimeofday(&now, NULL);
11234             if ((int)(now.tv_sec - pvt->mwisend_data.pause.tv_sec) * 1000000 + (int)now.tv_usec - (int)pvt->mwisend_data.pause.tv_usec > 500000) {
11235                pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
11236             }
11237 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11238          } else { /* support for mwisendtype=nofsk */
11239             pvt->mwisend_data.mwisend_current = MWI_SEND_CLEANUP;
11240          }
11241 #endif
11242          break;
11243       case MWI_SEND_SPILL:
11244          /* We read some number of bytes.  Write an equal amount of data */
11245          if(0 < num_read) {
11246             if (num_read > pvt->cidlen - pvt->cidpos)
11247                num_read = pvt->cidlen - pvt->cidpos;
11248             res = write(pvt->subs[SUB_REAL].dfd, pvt->cidspill + pvt->cidpos, num_read);
11249             if (res > 0) {
11250                pvt->cidpos += res;
11251                if (pvt->cidpos >= pvt->cidlen) {
11252                   pvt->mwisend_data.mwisend_current = MWI_SEND_CLEANUP;
11253                }
11254             } else {
11255                ast_log(LOG_WARNING, "MWI FSK Send Write failed: %s\n", strerror(errno));
11256                goto quit;
11257             }
11258          }
11259          break;
11260       case MWI_SEND_CLEANUP:
11261          /* For now, do nothing */
11262          pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11263          break;
11264       default:
11265          /* Should not get here, punt*/
11266          goto quit;
11267       }
11268    }
11269 
11270    if (MWI_SEND_DONE == pvt->mwisend_data.mwisend_current) {
11271       if (pvt->cidspill) {
11272          ast_free(pvt->cidspill);
11273          pvt->cidspill = NULL;
11274          pvt->cidpos = 0;
11275          pvt->cidlen = 0;
11276       }
11277       pvt->mwisendactive = 0;
11278    }
11279    return 0;
11280 quit:
11281    if (pvt->cidspill) {
11282       ast_free(pvt->cidspill);
11283       pvt->cidspill = NULL;
11284       pvt->cidpos = 0;
11285       pvt->cidlen = 0;
11286    }
11287    pvt->mwisendactive = 0;
11288    return -1;
11289 }
11290 
11291 static int mwi_send_process_event(struct dahdi_pvt * pvt, int event)
11292 {
11293    int handled = 0;
11294 
11295    if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current) {
11296       switch (event) {
11297       case DAHDI_EVENT_RINGEROFF:
11298          if(pvt->mwisend_data.mwisend_current == MWI_SEND_SA_WAIT) {
11299             handled = 1;
11300 
11301             if (dahdi_set_hook(pvt->subs[SUB_REAL].dfd, DAHDI_RINGOFF) ) {
11302                ast_log(LOG_WARNING, "Unable to finish RP-AS: %s mwi send aborted\n", strerror(errno));
11303                ast_free(pvt->cidspill);
11304                pvt->cidspill = NULL;
11305                pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11306                pvt->mwisendactive = 0;
11307             } else {
11308                pvt->mwisend_data.mwisend_current = MWI_SEND_PAUSE;
11309                gettimeofday(&pvt->mwisend_data.pause, NULL);
11310             }
11311          }
11312          break;
11313       /* Going off hook, I need to punt this spill */
11314       case DAHDI_EVENT_RINGOFFHOOK:
11315          if (pvt->cidspill) {
11316             ast_free(pvt->cidspill);
11317             pvt->cidspill = NULL;
11318             pvt->cidpos = 0;
11319             pvt->cidlen = 0;
11320          }
11321          pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11322          pvt->mwisendactive = 0;
11323          break;
11324       case DAHDI_EVENT_RINGERON:
11325       case DAHDI_EVENT_HOOKCOMPLETE:
11326          break;
11327       default:
11328          break;
11329       }
11330    }
11331    return handled;
11332 }
11333 
11334 /* destroy a DAHDI channel, identified by its number */
11335 static int dahdi_destroy_channel_bynum(int channel)
11336 {
11337    struct dahdi_pvt *cur;
11338 
11339    ast_mutex_lock(&iflock);
11340    for (cur = iflist; cur; cur = cur->next) {
11341       if (cur->channel == channel) {
11342          int x = DAHDI_FLASH;
11343 
11344          /* important to create an event for dahdi_wait_event to register so that all analog_ss_threads terminate */
11345          ioctl(cur->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
11346 
11347          destroy_channel(cur, 1);
11348          ast_mutex_unlock(&iflock);
11349          ast_module_unref(ast_module_info->self);
11350          return RESULT_SUCCESS;
11351       }
11352    }
11353    ast_mutex_unlock(&iflock);
11354    return RESULT_FAILURE;
11355 }
11356 
11357 static struct dahdi_pvt *handle_init_event(struct dahdi_pvt *i, int event)
11358 {
11359    int res;
11360    pthread_t threadid;
11361    struct ast_channel *chan;
11362 
11363    /* Handle an event on a given channel for the monitor thread. */
11364 
11365    switch (event) {
11366    case DAHDI_EVENT_NONE:
11367    case DAHDI_EVENT_BITSCHANGED:
11368       break;
11369    case DAHDI_EVENT_WINKFLASH:
11370    case DAHDI_EVENT_RINGOFFHOOK:
11371       if (i->inalarm) break;
11372       if (i->radio) break;
11373       /* Got a ring/answer.  What kind of channel are we? */
11374       switch (i->sig) {
11375       case SIG_FXOLS:
11376       case SIG_FXOGS:
11377       case SIG_FXOKS:
11378          res = dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
11379          if (res && (errno == EBUSY))
11380             break;
11381 
11382          /* Cancel VMWI spill */
11383          ast_free(i->cidspill);
11384          i->cidspill = NULL;
11385          restore_conference(i);
11386 
11387          if (i->immediate) {
11388             dahdi_enable_ec(i);
11389             /* The channel is immediately up.  Start right away */
11390             res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
11391             chan = dahdi_new(i, AST_STATE_RING, 1, SUB_REAL, 0, NULL);
11392             if (!chan) {
11393                ast_log(LOG_WARNING, "Unable to start PBX on channel %d\n", i->channel);
11394                res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11395                if (res < 0)
11396                   ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11397             }
11398          } else {
11399             /* Check for callerid, digits, etc */
11400             chan = dahdi_new(i, AST_STATE_RESERVED, 0, SUB_REAL, 0, NULL);
11401             if (chan) {
11402                if (has_voicemail(i))
11403                   res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
11404                else
11405                   res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
11406                if (res < 0)
11407                   ast_log(LOG_WARNING, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i->channel);
11408                if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
11409                   ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11410                   res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11411                   if (res < 0)
11412                      ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11413                   ast_hangup(chan);
11414                }
11415             } else
11416                ast_log(LOG_WARNING, "Unable to create channel\n");
11417          }
11418          break;
11419       case SIG_FXSLS:
11420       case SIG_FXSGS:
11421       case SIG_FXSKS:
11422             i->ringt = i->ringt_base;
11423             /* Fall through */
11424       case SIG_EMWINK:
11425       case SIG_FEATD:
11426       case SIG_FEATDMF:
11427       case SIG_FEATDMF_TA:
11428       case SIG_E911:
11429       case SIG_FGC_CAMA:
11430       case SIG_FGC_CAMAMF:
11431       case SIG_FEATB:
11432       case SIG_EM:
11433       case SIG_EM_E1:
11434       case SIG_SFWINK:
11435       case SIG_SF_FEATD:
11436       case SIG_SF_FEATDMF:
11437       case SIG_SF_FEATB:
11438       case SIG_SF:
11439          /* Check for callerid, digits, etc */
11440          if (i->cid_start == CID_START_POLARITY_IN) {
11441             chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL);
11442          } else {
11443             chan = dahdi_new(i, AST_STATE_RING, 0, SUB_REAL, 0, NULL);
11444          }
11445 
11446          if (!chan) {
11447             ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
11448          } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
11449             ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11450             res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11451             if (res < 0) {
11452                ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11453             }
11454             ast_hangup(chan);
11455          }
11456          break;
11457       default:
11458          ast_log(LOG_WARNING, "Don't know how to handle ring/answer with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
11459          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11460          if (res < 0)
11461             ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11462          return NULL;
11463       }
11464       break;
11465    case DAHDI_EVENT_NOALARM:
11466       switch (i->sig) {
11467 #if defined(HAVE_PRI)
11468       case SIG_PRI_LIB_HANDLE_CASES:
11469          ast_mutex_lock(&i->lock);
11470          sig_pri_chan_alarm_notify(i->sig_pvt, 1);
11471          ast_mutex_unlock(&i->lock);
11472          break;
11473 #endif   /* defined(HAVE_PRI) */
11474 #if defined(HAVE_SS7)
11475       case SIG_SS7:
11476          sig_ss7_set_alarm(i->sig_pvt, 0);
11477          break;
11478 #endif   /* defined(HAVE_SS7) */
11479       default:
11480          i->inalarm = 0;
11481          break;
11482       }
11483       handle_clear_alarms(i);
11484       break;
11485    case DAHDI_EVENT_ALARM:
11486       switch (i->sig) {
11487 #if defined(HAVE_PRI)
11488       case SIG_PRI_LIB_HANDLE_CASES:
11489          ast_mutex_lock(&i->lock);
11490          sig_pri_chan_alarm_notify(i->sig_pvt, 0);
11491          ast_mutex_unlock(&i->lock);
11492          break;
11493 #endif   /* defined(HAVE_PRI) */
11494 #if defined(HAVE_SS7)
11495       case SIG_SS7:
11496          sig_ss7_set_alarm(i->sig_pvt, 1);
11497          break;
11498 #endif   /* defined(HAVE_SS7) */
11499       default:
11500          i->inalarm = 1;
11501          break;
11502       }
11503       res = get_alarms(i);
11504       handle_alarms(i, res);
11505       /* fall thru intentionally */
11506    case DAHDI_EVENT_ONHOOK:
11507       if (i->radio)
11508          break;
11509       /* Back on hook.  Hang up. */
11510       switch (i->sig) {
11511       case SIG_FXOLS:
11512       case SIG_FXOGS:
11513       case SIG_FEATD:
11514       case SIG_FEATDMF:
11515       case SIG_FEATDMF_TA:
11516       case SIG_E911:
11517       case SIG_FGC_CAMA:
11518       case SIG_FGC_CAMAMF:
11519       case SIG_FEATB:
11520       case SIG_EM:
11521       case SIG_EM_E1:
11522       case SIG_EMWINK:
11523       case SIG_SF_FEATD:
11524       case SIG_SF_FEATDMF:
11525       case SIG_SF_FEATB:
11526       case SIG_SF:
11527       case SIG_SFWINK:
11528       case SIG_FXSLS:
11529       case SIG_FXSGS:
11530       case SIG_FXSKS:
11531       case SIG_FXOKS:
11532          dahdi_disable_ec(i);
11533          /* Diddle the battery for the zhone */
11534 #ifdef ZHONE_HACK
11535          dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
11536          usleep(1);
11537 #endif
11538          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
11539          dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
11540          break;
11541       case SIG_SS7:
11542       case SIG_PRI_LIB_HANDLE_CASES:
11543          dahdi_disable_ec(i);
11544          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
11545          break;
11546       default:
11547          ast_log(LOG_WARNING, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
11548          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
11549          return NULL;
11550       }
11551       break;
11552    case DAHDI_EVENT_POLARITY:
11553       switch (i->sig) {
11554       case SIG_FXSLS:
11555       case SIG_FXSKS:
11556       case SIG_FXSGS:
11557          /* We have already got a PR before the channel was
11558             created, but it wasn't handled. We need polarity
11559             to be REV for remote hangup detection to work.
11560             At least in Spain */
11561          if (i->hanguponpolarityswitch)
11562             i->polarity = POLARITY_REV;
11563          if (i->cid_start == CID_START_POLARITY || i->cid_start == CID_START_POLARITY_IN) {
11564             i->polarity = POLARITY_REV;
11565             ast_verb(2, "Starting post polarity "
11566                "CID detection on channel %d\n",
11567                i->channel);
11568             chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL);
11569             if (!chan) {
11570                ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
11571             } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
11572                ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11573             }
11574          }
11575          break;
11576       default:
11577          ast_log(LOG_WARNING, "handle_init_event detected "
11578             "polarity reversal on non-FXO (SIG_FXS) "
11579             "interface %d\n", i->channel);
11580       }
11581       break;
11582    case DAHDI_EVENT_REMOVED: /* destroy channel, will actually do so in do_monitor */
11583       ast_log(LOG_NOTICE,
11584             "Got DAHDI_EVENT_REMOVED. Destroying channel %d\n",
11585             i->channel);
11586       return i;
11587    case DAHDI_EVENT_NEONMWI_ACTIVE:
11588       if (i->mwimonitor_neon) {
11589          notify_message(i->mailbox, 1);
11590          ast_log(LOG_NOTICE, "NEON MWI set for channel %d, mailbox %s \n", i->channel, i->mailbox);
11591       }
11592       break;
11593    case DAHDI_EVENT_NEONMWI_INACTIVE:
11594       if (i->mwimonitor_neon) {
11595          notify_message(i->mailbox, 0);
11596          ast_log(LOG_NOTICE, "NEON MWI cleared for channel %d, mailbox %s\n", i->channel, i->mailbox);
11597       }
11598       break;
11599    }
11600    return NULL;
11601 }
11602 
11603 static void *do_monitor(void *data)
11604 {
11605    int count, res, res2, spoint, pollres=0;
11606    struct dahdi_pvt *i;
11607    struct dahdi_pvt *last = NULL;
11608    struct dahdi_pvt *doomed;
11609    time_t thispass = 0, lastpass = 0;
11610    int found;
11611    char buf[1024];
11612    struct pollfd *pfds=NULL;
11613    int lastalloc = -1;
11614    /* This thread monitors all the frame relay interfaces which are not yet in use
11615       (and thus do not have a separate thread) indefinitely */
11616    /* From here on out, we die whenever asked */
11617 #if 0
11618    if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) {
11619       ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n");
11620       return NULL;
11621    }
11622    ast_debug(1, "Monitor starting...\n");
11623 #endif
11624    pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
11625 
11626    for (;;) {
11627       /* Lock the interface list */
11628       ast_mutex_lock(&iflock);
11629       if (!pfds || (lastalloc != ifcount)) {
11630          if (pfds) {
11631             ast_free(pfds);
11632             pfds = NULL;
11633          }
11634          if (ifcount) {
11635             if (!(pfds = ast_calloc(1, ifcount * sizeof(*pfds)))) {
11636                ast_mutex_unlock(&iflock);
11637                return NULL;
11638             }
11639          }
11640          lastalloc = ifcount;
11641       }
11642       /* Build the stuff we're going to poll on, that is the socket of every
11643          dahdi_pvt that does not have an associated owner channel */
11644       count = 0;
11645       for (i = iflist; i; i = i->next) {
11646          ast_mutex_lock(&i->lock);
11647          if ((i->subs[SUB_REAL].dfd > -1) && i->sig && (!i->radio) && !(i->sig & SIG_MFCR2)) {
11648             if (analog_lib_handles(i->sig, i->radio, i->oprmode)) {
11649                struct analog_pvt *p = i->sig_pvt;
11650 
11651                if (!p)
11652                   ast_log(LOG_ERROR, "No sig_pvt?\n");
11653 
11654                if (!p->owner && !p->subs[SUB_REAL].owner) {
11655                   /* This needs to be watched, as it lacks an owner */
11656                   pfds[count].fd = i->subs[SUB_REAL].dfd;
11657                   pfds[count].events = POLLPRI;
11658                   pfds[count].revents = 0;
11659                   /* Message waiting or r2 channels also get watched for reading */
11660                   if (i->cidspill || i->mwisendactive || i->mwimonitor_fsk || 
11661                      (i->cid_start == CID_START_DTMF_NOALERT && (i->sig == SIG_FXSLS || i->sig == SIG_FXSGS || i->sig == SIG_FXSKS))) {
11662                      pfds[count].events |= POLLIN;
11663                   }
11664                   count++;
11665                }
11666             } else {
11667                if (!i->owner && !i->subs[SUB_REAL].owner && !i->mwimonitoractive ) {
11668                   /* This needs to be watched, as it lacks an owner */
11669                   pfds[count].fd = i->subs[SUB_REAL].dfd;
11670                   pfds[count].events = POLLPRI;
11671                   pfds[count].revents = 0;
11672                   /* If we are monitoring for VMWI or sending CID, we need to
11673                      read from the channel as well */
11674                   if (i->cidspill || i->mwisendactive || i->mwimonitor_fsk ||
11675                      (i->cid_start == CID_START_DTMF_NOALERT && (i->sig == SIG_FXSLS || i->sig == SIG_FXSGS || i->sig == SIG_FXSKS))) {
11676                      pfds[count].events |= POLLIN;
11677                   }
11678                   count++;
11679                }
11680             }
11681          }
11682          ast_mutex_unlock(&i->lock);
11683       }
11684       /* Okay, now that we know what to do, release the interface lock */
11685       ast_mutex_unlock(&iflock);
11686 
11687       pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
11688       pthread_testcancel();
11689       /* Wait at least a second for something to happen */
11690       res = poll(pfds, count, 1000);
11691       pthread_testcancel();
11692       pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
11693 
11694       /* Okay, poll has finished.  Let's see what happened.  */
11695       if (res < 0) {
11696          if ((errno != EAGAIN) && (errno != EINTR))
11697             ast_log(LOG_WARNING, "poll return %d: %s\n", res, strerror(errno));
11698          continue;
11699       }
11700       /* Alright, lock the interface list again, and let's look and see what has
11701          happened */
11702       ast_mutex_lock(&iflock);
11703       found = 0;
11704       spoint = 0;
11705       lastpass = thispass;
11706       thispass = time(NULL);
11707       doomed = NULL;
11708       for (i = iflist;; i = i->next) {
11709          if (doomed) {
11710             int res;
11711             res = dahdi_destroy_channel_bynum(doomed->channel);
11712             if (res != RESULT_SUCCESS) {
11713                ast_log(LOG_WARNING, "Couldn't find channel to destroy, hopefully another destroy operation just happened.\n");
11714             }
11715             doomed = NULL;
11716          }
11717          if (!i) {
11718             break;
11719          }
11720 
11721          if (thispass != lastpass) {
11722             if (!found && ((i == last) || ((i == iflist) && !last))) {
11723                last = i;
11724                if (last) {
11725                   struct analog_pvt *analog_p = last->sig_pvt;
11726                   /* Only allow MWI to be initiated on a quiescent fxs port */
11727                   if (analog_p
11728                      && !last->mwisendactive
11729                      && (last->sig & __DAHDI_SIG_FXO)
11730                      && !analog_p->fxsoffhookstate
11731                      && !last->owner
11732                      && !ast_strlen_zero(last->mailbox)
11733                      && (thispass - analog_p->onhooktime > 3)) {
11734                      res = has_voicemail(last);
11735                      if (analog_p->msgstate != res) {
11736                         /* Set driver resources for signalling VMWI */
11737                         res2 = ioctl(last->subs[SUB_REAL].dfd, DAHDI_VMWI, &res);
11738                         if (res2) {
11739                            /* TODO: This message will ALWAYS be generated on some cards; any way to restrict it to those cards where it is interesting? */
11740                            ast_debug(3, "Unable to control message waiting led on channel %d: %s\n", last->channel, strerror(errno));
11741                         }
11742                         /* If enabled for FSK spill then initiate it */
11743                         if (mwi_send_init(last)) {
11744                            ast_log(LOG_WARNING, "Unable to initiate mwi send sequence on channel %d\n", last->channel);
11745                         }
11746                         analog_p->msgstate = res;
11747                         found ++;
11748                      }
11749                   }
11750                   last = last->next;
11751                }
11752             }
11753          }
11754          if ((i->subs[SUB_REAL].dfd > -1) && i->sig) {
11755             if (i->radio && !i->owner)
11756             {
11757                res = dahdi_get_event(i->subs[SUB_REAL].dfd);
11758                if (res)
11759                {
11760                   ast_debug(1, "Monitor doohicky got event %s on radio channel %d\n", event2str(res), i->channel);
11761                   /* Don't hold iflock while handling init events */
11762                   ast_mutex_unlock(&iflock);
11763                   if (analog_lib_handles(i->sig, i->radio, i->oprmode))
11764                      doomed = (struct dahdi_pvt *) analog_handle_init_event(i->sig_pvt, dahdievent_to_analogevent(res));
11765                   else
11766                      doomed = handle_init_event(i, res);
11767                   ast_mutex_lock(&iflock);
11768                }
11769                continue;
11770             }
11771             pollres = ast_fdisset(pfds, i->subs[SUB_REAL].dfd, count, &spoint);
11772             if (pollres & POLLIN) {
11773                if (i->owner || i->subs[SUB_REAL].owner) {
11774 #ifdef HAVE_PRI
11775                   if (!i->pri)
11776 #endif
11777                      ast_log(LOG_WARNING, "Whoa....  I'm owned but found (%d) in read...\n", i->subs[SUB_REAL].dfd);
11778                   continue;
11779                }
11780                if (!i->mwimonitor_fsk && !i->mwisendactive  && i->cid_start != CID_START_DTMF_NOALERT) {
11781                   ast_log(LOG_WARNING, "Whoa....  I'm not looking for MWI or sending MWI but am reading (%d)...\n", i->subs[SUB_REAL].dfd);
11782                   continue;
11783                }
11784                res = read(i->subs[SUB_REAL].dfd, buf, sizeof(buf));
11785                if (res > 0) {
11786                   if (i->mwimonitor_fsk) {
11787                      if (calc_energy((unsigned char *) buf, res, AST_LAW(i)) > mwilevel) {
11788                         pthread_attr_t attr;
11789                         pthread_t threadid;
11790                         struct mwi_thread_data *mtd;
11791 
11792                         pthread_attr_init(&attr);
11793                         pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
11794 
11795                         ast_log(LOG_DEBUG, "Maybe some MWI on port %d!\n", i->channel);
11796                         if ((mtd = ast_calloc(1, sizeof(*mtd)))) {
11797                            mtd->pvt = i;
11798                            memcpy(mtd->buf, buf, res);
11799                            mtd->len = res;
11800                            if (ast_pthread_create_background(&threadid, &attr, mwi_thread, mtd)) {
11801                               ast_log(LOG_WARNING, "Unable to start mwi thread on channel %d\n", i->channel);
11802                               ast_free(mtd);
11803                            }
11804                            i->mwimonitoractive = 1;
11805                         }
11806                      }
11807                   /* If configured to check for a DTMF CID spill that comes without alert (e.g no polarity reversal) */
11808                   } else if (i->cid_start == CID_START_DTMF_NOALERT) {
11809                      int energy;
11810                      struct timeval now;
11811                      /* State machine dtmfcid_holdoff_state allows for the line to settle
11812                       * before checking agin for dtmf energy.  Presently waits for 500 mS before checking again 
11813                      */
11814                      if (1 == i->dtmfcid_holdoff_state) {
11815                         gettimeofday(&i->dtmfcid_delay, NULL);
11816                         i->dtmfcid_holdoff_state = 2;
11817                      } else if (2 == i->dtmfcid_holdoff_state) {
11818                         gettimeofday(&now, NULL);
11819                         if ((int)(now.tv_sec - i->dtmfcid_delay.tv_sec) * 1000000 + (int)now.tv_usec - (int)i->dtmfcid_delay.tv_usec > 500000) {
11820                            i->dtmfcid_holdoff_state = 0;
11821                         }
11822                      } else {
11823                         energy = calc_energy((unsigned char *) buf, res, AST_LAW(i));
11824                         if (!i->mwisendactive && energy > dtmfcid_level) {
11825                            pthread_t threadid;
11826                            struct ast_channel *chan;
11827                            ast_mutex_unlock(&iflock);
11828                            if (analog_lib_handles(i->sig, i->radio, i->oprmode)) {
11829                               /* just in case this event changes or somehow destroys a channel, set doomed here too */
11830                               doomed = analog_handle_init_event(i->sig_pvt, ANALOG_EVENT_DTMFCID);  
11831                               i->dtmfcid_holdoff_state = 1;
11832                            } else {
11833                               chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL);
11834                               if (!chan) {
11835                                  ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
11836                               } else {
11837                                  res = ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan);
11838                                  if (res) {
11839                                     ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11840                                  } else {
11841                                     i->dtmfcid_holdoff_state = 1;
11842                                  }
11843                               }
11844                            }
11845                            ast_mutex_lock(&iflock);
11846                         }
11847                      }
11848                   }
11849                   if (i->mwisendactive) {
11850                      mwi_send_process_buffer(i, res);
11851                   }
11852                } else {
11853                   ast_log(LOG_WARNING, "Read failed with %d: %s\n", res, strerror(errno));
11854                }
11855             }
11856             if (pollres & POLLPRI) {
11857                if (i->owner || i->subs[SUB_REAL].owner) {
11858 #ifdef HAVE_PRI
11859                   if (!i->pri)
11860 #endif
11861                      ast_log(LOG_WARNING, "Whoa....  I'm owned but found (%d)...\n", i->subs[SUB_REAL].dfd);
11862                   continue;
11863                }
11864                res = dahdi_get_event(i->subs[SUB_REAL].dfd);
11865                ast_debug(1, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel);
11866                /* Don't hold iflock while handling init events */
11867                ast_mutex_unlock(&iflock);
11868                if (0 == i->mwisendactive || 0 == mwi_send_process_event(i, res)) {
11869                   if (analog_lib_handles(i->sig, i->radio, i->oprmode))
11870                      doomed = (struct dahdi_pvt *) analog_handle_init_event(i->sig_pvt, dahdievent_to_analogevent(res));
11871                   else
11872                      doomed = handle_init_event(i, res);
11873                }
11874                ast_mutex_lock(&iflock);
11875             }
11876          }
11877       }
11878       ast_mutex_unlock(&iflock);
11879    }
11880    /* Never reached */
11881    return NULL;
11882 
11883 }
11884 
11885 static int restart_monitor(void)
11886 {
11887    /* If we're supposed to be stopped -- stay stopped */
11888    if (monitor_thread == AST_PTHREADT_STOP)
11889       return 0;
11890    ast_mutex_lock(&monlock);
11891    if (monitor_thread == pthread_self()) {
11892       ast_mutex_unlock(&monlock);
11893       ast_log(LOG_WARNING, "Cannot kill myself\n");
11894       return -1;
11895    }
11896    if (monitor_thread != AST_PTHREADT_NULL) {
11897       /* Wake up the thread */
11898       pthread_kill(monitor_thread, SIGURG);
11899    } else {
11900       /* Start a new monitor */
11901       if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) {
11902          ast_mutex_unlock(&monlock);
11903          ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
11904          return -1;
11905       }
11906    }
11907    ast_mutex_unlock(&monlock);
11908    return 0;
11909 }
11910 
11911 #if defined(HAVE_PRI)
11912 static int pri_resolve_span(int *span, int channel, int offset, struct dahdi_spaninfo *si)
11913 {
11914    int x;
11915    int trunkgroup;
11916    /* Get appropriate trunk group if there is one */
11917    trunkgroup = pris[*span].mastertrunkgroup;
11918    if (trunkgroup) {
11919       /* Select a specific trunk group */
11920       for (x = 0; x < NUM_SPANS; x++) {
11921          if (pris[x].pri.trunkgroup == trunkgroup) {
11922             *span = x;
11923             return 0;
11924          }
11925       }
11926       ast_log(LOG_WARNING, "Channel %d on span %d configured to use nonexistent trunk group %d\n", channel, *span, trunkgroup);
11927       *span = -1;
11928    } else {
11929       if (pris[*span].pri.trunkgroup) {
11930          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);
11931          *span = -1;
11932       } else if (pris[*span].mastertrunkgroup) {
11933          ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is already part of trunk group %d\n", *span, pris[*span].mastertrunkgroup);
11934          *span = -1;
11935       } else {
11936          if (si->totalchans == 31) {
11937             /* E1 */
11938             pris[*span].dchannels[0] = 16 + offset;
11939          } else if (si->totalchans == 24) {
11940             /* T1 or J1 */
11941             pris[*span].dchannels[0] = 24 + offset;
11942          } else if (si->totalchans == 3) {
11943             /* BRI */
11944             pris[*span].dchannels[0] = 3 + offset;
11945          } else {
11946             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);
11947             *span = -1;
11948             return 0;
11949          }
11950          pris[*span].pri.span = *span + 1;
11951       }
11952    }
11953    return 0;
11954 }
11955 #endif   /* defined(HAVE_PRI) */
11956 
11957 #if defined(HAVE_PRI)
11958 static int pri_create_trunkgroup(int trunkgroup, int *channels)
11959 {
11960    struct dahdi_spaninfo si;
11961    struct dahdi_params p;
11962    int fd;
11963    int span;
11964    int ospan=0;
11965    int x,y;
11966    for (x = 0; x < NUM_SPANS; x++) {
11967       if (pris[x].pri.trunkgroup == trunkgroup) {
11968          ast_log(LOG_WARNING, "Trunk group %d already exists on span %d, Primary d-channel %d\n", trunkgroup, x + 1, pris[x].dchannels[0]);
11969          return -1;
11970       }
11971    }
11972    for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
11973       if (!channels[y])
11974          break;
11975       memset(&si, 0, sizeof(si));
11976       memset(&p, 0, sizeof(p));
11977       fd = open("/dev/dahdi/channel", O_RDWR);
11978       if (fd < 0) {
11979          ast_log(LOG_WARNING, "Failed to open channel: %s\n", strerror(errno));
11980          return -1;
11981       }
11982       x = channels[y];
11983       if (ioctl(fd, DAHDI_SPECIFY, &x)) {
11984          ast_log(LOG_WARNING, "Failed to specify channel %d: %s\n", channels[y], strerror(errno));
11985          close(fd);
11986          return -1;
11987       }
11988       if (ioctl(fd, DAHDI_GET_PARAMS, &p)) {
11989          ast_log(LOG_WARNING, "Failed to get channel parameters for channel %d: %s\n", channels[y], strerror(errno));
11990          return -1;
11991       }
11992       if (ioctl(fd, DAHDI_SPANSTAT, &si)) {
11993          ast_log(LOG_WARNING, "Failed go get span information on channel %d (span %d): %s\n", channels[y], p.spanno, strerror(errno));
11994          close(fd);
11995          return -1;
11996       }
11997       span = p.spanno - 1;
11998       if (pris[span].pri.trunkgroup) {
11999          ast_log(LOG_WARNING, "Span %d is already provisioned for trunk group %d\n", span + 1, pris[span].pri.trunkgroup);
12000          close(fd);
12001          return -1;
12002       }
12003       if (pris[span].pri.pvts[0]) {
12004          ast_log(LOG_WARNING, "Span %d is already provisioned with channels (implicit PRI maybe?)\n", span + 1);
12005          close(fd);
12006          return -1;
12007       }
12008       if (!y) {
12009          pris[span].pri.trunkgroup = trunkgroup;
12010          ospan = span;
12011       }
12012       pris[ospan].dchannels[y] = channels[y];
12013       pris[span].pri.span = span + 1;
12014       close(fd);
12015    }
12016    return 0;
12017 }
12018 #endif   /* defined(HAVE_PRI) */
12019 
12020 #if defined(HAVE_PRI)
12021 static int pri_create_spanmap(int span, int trunkgroup, int logicalspan)
12022 {
12023    if (pris[span].mastertrunkgroup) {
12024       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);
12025       return -1;
12026    }
12027    pris[span].mastertrunkgroup = trunkgroup;
12028    pris[span].prilogicalspan = logicalspan;
12029    return 0;
12030 }
12031 #endif   /* defined(HAVE_PRI) */
12032 
12033 #if defined(HAVE_SS7)
12034 static unsigned int parse_pointcode(const char *pcstring)
12035 {
12036    unsigned int code1, code2, code3;
12037    int numvals;
12038 
12039    numvals = sscanf(pcstring, "%30d-%30d-%30d", &code1, &code2, &code3);
12040    if (numvals == 1)
12041       return code1;
12042    if (numvals == 3)
12043       return (code1 << 16) | (code2 << 8) | code3;
12044 
12045    return 0;
12046 }
12047 #endif   /* defined(HAVE_SS7) */
12048 
12049 #if defined(HAVE_SS7)
12050 static struct dahdi_ss7 * ss7_resolve_linkset(int linkset)
12051 {
12052    if ((linkset < 0) || (linkset >= NUM_SPANS))
12053       return NULL;
12054    else
12055       return &linksets[linkset - 1];
12056 }
12057 #endif   /* defined(HAVE_SS7) */
12058 
12059 #ifdef HAVE_OPENR2
12060 static void dahdi_r2_destroy_links(void)
12061 {
12062    int i = 0;
12063    if (!r2links) {
12064       return;
12065    }
12066    for (; i < r2links_count; i++) {
12067       if (r2links[i]->r2master != AST_PTHREADT_NULL) {
12068          pthread_cancel(r2links[i]->r2master);
12069          pthread_join(r2links[i]->r2master, NULL);
12070          openr2_context_delete(r2links[i]->protocol_context);
12071       }
12072       ast_free(r2links[i]);
12073    }
12074    ast_free(r2links);
12075    r2links = NULL;
12076    r2links_count = 0;
12077 }
12078 
12079 #define R2_LINK_CAPACITY 10
12080 static struct dahdi_mfcr2 *dahdi_r2_get_link(void)
12081 {
12082    struct dahdi_mfcr2 *new_r2link = NULL;
12083    struct dahdi_mfcr2 **new_r2links = NULL;
12084    /* this function is called just when starting up and no monitor threads have been launched,
12085       no need to lock monitored_count member */
12086    if (!r2links_count || (r2links[r2links_count - 1]->monitored_count == R2_LINK_CAPACITY)) {
12087       new_r2link = ast_calloc(1, sizeof(**r2links));
12088       if (!new_r2link) {
12089          ast_log(LOG_ERROR, "Cannot allocate R2 link!\n");
12090          return NULL;
12091       }
12092       new_r2links = ast_realloc(r2links, ((r2links_count + 1) * sizeof(*r2links)));
12093       if (!new_r2links) {
12094          ast_log(LOG_ERROR, "Cannot allocate R2 link!\n");
12095          ast_free(new_r2link);
12096          return NULL;
12097       }
12098       r2links = new_r2links;
12099       new_r2link->r2master = AST_PTHREADT_NULL;
12100       r2links[r2links_count] = new_r2link;
12101       r2links_count++;
12102       ast_log(LOG_DEBUG, "Created new R2 link!\n");
12103    }
12104    return r2links[r2links_count - 1];
12105 }
12106 
12107 static int dahdi_r2_set_context(struct dahdi_mfcr2 *r2_link, const struct dahdi_chan_conf *conf)
12108 {
12109    char tmplogdir[] = "/tmp";
12110    char logdir[OR2_MAX_PATH];
12111    int threshold = 0;
12112    int snres = 0;
12113    r2_link->protocol_context = openr2_context_new(NULL, &dahdi_r2_event_iface,
12114          &dahdi_r2_transcode_iface, conf->mfcr2.variant, conf->mfcr2.max_ani,
12115          conf->mfcr2.max_dnis);
12116    if (!r2_link->protocol_context) {
12117       return -1;
12118    }
12119    openr2_context_set_log_level(r2_link->protocol_context, conf->mfcr2.loglevel);
12120    openr2_context_set_ani_first(r2_link->protocol_context, conf->mfcr2.get_ani_first);
12121 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
12122    openr2_context_set_skip_category_request(r2_link->protocol_context, conf->mfcr2.skip_category_request);
12123 #endif
12124    openr2_context_set_mf_threshold(r2_link->protocol_context, threshold);
12125    openr2_context_set_mf_back_timeout(r2_link->protocol_context, conf->mfcr2.mfback_timeout);
12126    openr2_context_set_metering_pulse_timeout(r2_link->protocol_context, conf->mfcr2.metering_pulse_timeout);
12127    openr2_context_set_double_answer(r2_link->protocol_context, conf->mfcr2.double_answer);
12128    openr2_context_set_immediate_accept(r2_link->protocol_context, conf->mfcr2.immediate_accept);
12129    if (ast_strlen_zero(conf->mfcr2.logdir)) {
12130       if (openr2_context_set_log_directory(r2_link->protocol_context, tmplogdir)) {
12131          ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir);
12132       }
12133    } else {
12134       snres = snprintf(logdir, sizeof(logdir), "%s/%s/%s", ast_config_AST_LOG_DIR, "mfcr2", conf->mfcr2.logdir);
12135       if (snres >= sizeof(logdir)) {
12136          ast_log(LOG_ERROR, "MFC/R2 logging directory truncated, using %s\n", tmplogdir);
12137          if (openr2_context_set_log_directory(r2_link->protocol_context, tmplogdir)) {
12138             ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir);
12139          }
12140       } else {
12141          if (openr2_context_set_log_directory(r2_link->protocol_context, logdir)) {
12142             ast_log(LOG_ERROR, "Failed setting MFC/R2 log directory %s\n", logdir);
12143          }
12144       }
12145    }
12146    if (!ast_strlen_zero(conf->mfcr2.r2proto_file)) {
12147       if (openr2_context_configure_from_advanced_file(r2_link->protocol_context, conf->mfcr2.r2proto_file)) {
12148          ast_log(LOG_ERROR, "Failed to configure r2context from advanced configuration file %s\n", conf->mfcr2.r2proto_file);
12149       }
12150    }
12151    r2_link->monitored_count = 0;
12152    return 0;
12153 }
12154 #endif
12155 
12156 /* converts a DAHDI sigtype to signalling as can be configured from
12157  * chan_dahdi.conf.
12158  * While both have basically the same values, this will later be the
12159  * place to add filters and sanity checks
12160  */
12161 static int sigtype_to_signalling(int sigtype)
12162 {
12163    return sigtype;
12164 }
12165 
12166 /*!
12167  * \internal
12168  * \brief Get file name and channel number from (subdir,number)
12169  *
12170  * \param subdir name of the subdirectory under /dev/dahdi/
12171  * \param channel name of device file under /dev/dahdi/<subdir>/
12172  * \param path buffer to put file name in
12173  * \param pathlen maximal length of path
12174  *
12175  * \retval minor number of dahdi channel.
12176  * \retval -errno on error.
12177  */
12178 static int device2chan(const char *subdir, int channel, char *path, int pathlen)
12179 {
12180    struct stat stbuf;
12181    int      num;
12182 
12183    snprintf(path, pathlen, "/dev/dahdi/%s/%d", subdir, channel);
12184    if (stat(path, &stbuf) < 0) {
12185       ast_log(LOG_ERROR, "stat(%s) failed: %s\n", path, strerror(errno));
12186       return -errno;
12187    }
12188    if (!S_ISCHR(stbuf.st_mode)) {
12189       ast_log(LOG_ERROR, "%s: Not a character device file\n", path);
12190       return -EINVAL;
12191    }
12192    num = minor(stbuf.st_rdev);
12193    ast_log(LOG_DEBUG, "%s -> %d\n", path, num);
12194    return num;
12195 
12196 }
12197 
12198 /*!
12199  * \internal
12200  * \brief Initialize/create a channel interface.
12201  *
12202  * \param channel Channel interface number to initialize/create.
12203  * \param conf Configuration parameters to initialize interface with.
12204  * \param reloading What we are doing now:
12205  * 0 - initial module load,
12206  * 1 - module reload,
12207  * 2 - module restart
12208  *
12209  * \retval Interface-pointer initialized/created
12210  * \retval NULL if error
12211  */
12212 static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf, int reloading)
12213 {
12214    /* Make a dahdi_pvt structure for this interface */
12215    struct dahdi_pvt *tmp;/*!< Current channel structure initializing */
12216    char fn[80];
12217    struct dahdi_bufferinfo bi;
12218 
12219    int res;
12220 #if defined(HAVE_PRI)
12221    int span = 0;
12222 #endif   /* defined(HAVE_PRI) */
12223    int here = 0;/*!< TRUE if the channel interface already exists. */
12224    int x;
12225    struct analog_pvt *analog_p = NULL;
12226    struct dahdi_params p;
12227 #if defined(HAVE_PRI)
12228    struct dahdi_spaninfo si;
12229    struct sig_pri_chan *pri_chan = NULL;
12230 #endif   /* defined(HAVE_PRI) */
12231 #if defined(HAVE_SS7)
12232    struct sig_ss7_chan *ss7_chan = NULL;
12233 #endif   /* defined(HAVE_SS7) */
12234 
12235    /* Search channel interface list to see if it already exists. */
12236    for (tmp = iflist; tmp; tmp = tmp->next) {
12237       if (!tmp->destroy) {
12238          if (tmp->channel == channel) {
12239             /* The channel interface already exists. */
12240             here = 1;
12241             break;
12242          }
12243          if (tmp->channel > channel) {
12244             /* No way it can be in the sorted list. */
12245             tmp = NULL;
12246             break;
12247          }
12248       }
12249    }
12250 
12251    if (!here && reloading != 1) {
12252       tmp = ast_calloc(1, sizeof(*tmp));
12253       if (!tmp) {
12254          return NULL;
12255       }
12256       tmp->cc_params = ast_cc_config_params_init();
12257       if (!tmp->cc_params) {
12258          ast_free(tmp);
12259          return NULL;
12260       }
12261       ast_mutex_init(&tmp->lock);
12262       ifcount++;
12263       for (x = 0; x < 3; x++)
12264          tmp->subs[x].dfd = -1;
12265       tmp->channel = channel;
12266       tmp->priindication_oob = conf->chan.priindication_oob;
12267    }
12268 
12269    if (tmp) {
12270       int chan_sig = conf->chan.sig;
12271 
12272       /* If there are variables in tmp before it is updated to match the new config, clear them */
12273       if (reloading && tmp->vars) {
12274          ast_variables_destroy(tmp->vars);
12275          tmp->vars = NULL;
12276       }
12277 
12278 
12279       if (!here) {
12280          /* Can only get here if this is a new channel interface being created. */
12281          if ((channel != CHAN_PSEUDO)) {
12282             int count = 0;
12283 
12284             snprintf(fn, sizeof(fn), "%d", channel);
12285             /* Open non-blocking */
12286             tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
12287             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 */
12288                usleep(1);
12289                tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
12290                count++;
12291             }
12292             /* Allocate a DAHDI structure */
12293             if (tmp->subs[SUB_REAL].dfd < 0) {
12294                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);
12295                destroy_dahdi_pvt(tmp);
12296                return NULL;
12297             }
12298             memset(&p, 0, sizeof(p));
12299             res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
12300             if (res < 0) {
12301                ast_log(LOG_ERROR, "Unable to get parameters: %s\n", strerror(errno));
12302                destroy_dahdi_pvt(tmp);
12303                return NULL;
12304             }
12305             if (conf->is_sig_auto)
12306                chan_sig = sigtype_to_signalling(p.sigtype);
12307             if (p.sigtype != (chan_sig & 0x3ffff)) {
12308                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));
12309                destroy_dahdi_pvt(tmp);
12310                return NULL;
12311             }
12312             tmp->law_default = p.curlaw;
12313             tmp->law = p.curlaw;
12314             tmp->span = p.spanno;
12315 #if defined(HAVE_PRI)
12316             span = p.spanno - 1;
12317 #endif   /* defined(HAVE_PRI) */
12318          } else {
12319             chan_sig = 0;
12320          }
12321          tmp->sig = chan_sig;
12322          tmp->outsigmod = conf->chan.outsigmod;
12323 
12324          if (analog_lib_handles(chan_sig, tmp->radio, tmp->oprmode)) {
12325             analog_p = analog_new(dahdisig_to_analogsig(chan_sig), &dahdi_analog_callbacks, tmp);
12326             if (!analog_p) {
12327                destroy_dahdi_pvt(tmp);
12328                return NULL;
12329             }
12330             tmp->sig_pvt = analog_p;
12331          }
12332 #if defined(HAVE_SS7)
12333          if (chan_sig == SIG_SS7) {
12334             struct dahdi_ss7 *ss7;
12335             int clear = 0;
12336 
12337             if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &clear)) {
12338                ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
12339                destroy_dahdi_pvt(tmp);
12340                return NULL;
12341             }
12342 
12343             ss7 = ss7_resolve_linkset(cur_linkset);
12344             if (!ss7) {
12345                ast_log(LOG_ERROR, "Unable to find linkset %d\n", cur_linkset);
12346                destroy_dahdi_pvt(tmp);
12347                return NULL;
12348             }
12349             ss7->ss7.span = cur_linkset;
12350             if (cur_cicbeginswith < 0) {
12351                ast_log(LOG_ERROR, "Need to set cicbeginswith for the channels!\n");
12352                destroy_dahdi_pvt(tmp);
12353                return NULL;
12354             }
12355             ss7_chan = sig_ss7_chan_new(tmp, &dahdi_ss7_callbacks, &ss7->ss7);
12356             if (!ss7_chan) {
12357                destroy_dahdi_pvt(tmp);
12358                return NULL;
12359             }
12360             tmp->sig_pvt = ss7_chan;
12361             tmp->ss7 = &ss7->ss7;
12362 
12363             ss7_chan->channel = tmp->channel;
12364             ss7_chan->cic = cur_cicbeginswith++;
12365 
12366             /* DB: Add CIC's DPC information */
12367             ss7_chan->dpc = cur_defaultdpc;
12368 
12369             ss7->ss7.pvts[ss7->ss7.numchans++] = ss7_chan;
12370 
12371             ast_copy_string(ss7->ss7.internationalprefix, conf->ss7.ss7.internationalprefix, sizeof(ss7->ss7.internationalprefix));
12372             ast_copy_string(ss7->ss7.nationalprefix, conf->ss7.ss7.nationalprefix, sizeof(ss7->ss7.nationalprefix));
12373             ast_copy_string(ss7->ss7.subscriberprefix, conf->ss7.ss7.subscriberprefix, sizeof(ss7->ss7.subscriberprefix));
12374             ast_copy_string(ss7->ss7.unknownprefix, conf->ss7.ss7.unknownprefix, sizeof(ss7->ss7.unknownprefix));
12375 
12376             ss7->ss7.called_nai = conf->ss7.ss7.called_nai;
12377             ss7->ss7.calling_nai = conf->ss7.ss7.calling_nai;
12378          }
12379 #endif   /* defined(HAVE_SS7) */
12380 #ifdef HAVE_OPENR2
12381          if (chan_sig == SIG_MFCR2) {
12382             struct dahdi_mfcr2 *r2_link;
12383             r2_link = dahdi_r2_get_link();
12384             if (!r2_link) {
12385                ast_log(LOG_WARNING, "Cannot get another R2 DAHDI context!\n");
12386                destroy_dahdi_pvt(tmp);
12387                return NULL;
12388             }
12389             if (!r2_link->protocol_context && dahdi_r2_set_context(r2_link, conf)) {
12390                ast_log(LOG_ERROR, "Cannot create OpenR2 protocol context.\n");
12391                destroy_dahdi_pvt(tmp);
12392                return NULL;
12393             }
12394             if (r2_link->numchans == ARRAY_LEN(r2_link->pvts)) {
12395                ast_log(LOG_ERROR, "Cannot add more channels to this link!\n");
12396                destroy_dahdi_pvt(tmp);
12397                return NULL;
12398             }
12399             r2_link->pvts[r2_link->numchans++] = tmp;
12400             tmp->r2chan = openr2_chan_new_from_fd(r2_link->protocol_context,
12401                                         tmp->subs[SUB_REAL].dfd,
12402                                         NULL, NULL);
12403             if (!tmp->r2chan) {
12404                openr2_liberr_t err = openr2_context_get_last_error(r2_link->protocol_context);
12405                ast_log(LOG_ERROR, "Cannot create OpenR2 channel: %s\n", openr2_context_error_string(err));
12406                destroy_dahdi_pvt(tmp);
12407                return NULL;
12408             }
12409             tmp->mfcr2 = r2_link;
12410             if (conf->mfcr2.call_files) {
12411                openr2_chan_enable_call_files(tmp->r2chan);
12412             }
12413             openr2_chan_set_client_data(tmp->r2chan, tmp);
12414             /* cast seems to be needed to get rid of the annoying warning regarding format attribute  */
12415             openr2_chan_set_logging_func(tmp->r2chan, (openr2_logging_func_t)dahdi_r2_on_chan_log);
12416             openr2_chan_set_log_level(tmp->r2chan, conf->mfcr2.loglevel);
12417             tmp->mfcr2_category = conf->mfcr2.category;
12418             tmp->mfcr2_charge_calls = conf->mfcr2.charge_calls;
12419             tmp->mfcr2_allow_collect_calls = conf->mfcr2.allow_collect_calls;
12420             tmp->mfcr2_forced_release = conf->mfcr2.forced_release;
12421             tmp->mfcr2_accept_on_offer = conf->mfcr2.accept_on_offer;
12422             tmp->mfcr2call = 0;
12423             tmp->mfcr2_dnis_index = 0;
12424             tmp->mfcr2_ani_index = 0;
12425             r2_link->monitored_count++;
12426          }
12427 #endif
12428 #ifdef HAVE_PRI
12429          if (dahdi_sig_pri_lib_handles(chan_sig)) {
12430             int offset;
12431             int matchesdchan;
12432             int x,y;
12433             int myswitchtype = 0;
12434 
12435             offset = 0;
12436             if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &offset)) {
12437                ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
12438                destroy_dahdi_pvt(tmp);
12439                return NULL;
12440             }
12441             if (span >= NUM_SPANS) {
12442                ast_log(LOG_ERROR, "Channel %d does not lie on a span I know of (%d)\n", channel, span);
12443                destroy_dahdi_pvt(tmp);
12444                return NULL;
12445             } else {
12446                si.spanno = 0;
12447                if (ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SPANSTAT,&si) == -1) {
12448                   ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno));
12449                   destroy_dahdi_pvt(tmp);
12450                   return NULL;
12451                }
12452                /* Store the logical span first based upon the real span */
12453                tmp->logicalspan = pris[span].prilogicalspan;
12454                pri_resolve_span(&span, channel, (channel - p.chanpos), &si);
12455                if (span < 0) {
12456                   ast_log(LOG_WARNING, "Channel %d: Unable to find locate channel/trunk group!\n", channel);
12457                   destroy_dahdi_pvt(tmp);
12458                   return NULL;
12459                }
12460                myswitchtype = conf->pri.pri.switchtype;
12461                /* Make sure this isn't a d-channel */
12462                matchesdchan=0;
12463                for (x = 0; x < NUM_SPANS; x++) {
12464                   for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
12465                      if (pris[x].dchannels[y] == tmp->channel) {
12466                         matchesdchan = 1;
12467                         break;
12468                      }
12469                   }
12470                }
12471                if (!matchesdchan) {
12472                   if (pris[span].pri.nodetype && (pris[span].pri.nodetype != conf->pri.pri.nodetype)) {
12473                      ast_log(LOG_ERROR, "Span %d is already a %s node\n", span + 1, pri_node2str(pris[span].pri.nodetype));
12474                      destroy_dahdi_pvt(tmp);
12475                      return NULL;
12476                   }
12477                   if (pris[span].pri.switchtype && (pris[span].pri.switchtype != myswitchtype)) {
12478                      ast_log(LOG_ERROR, "Span %d is already a %s switch\n", span + 1, pri_switch2str(pris[span].pri.switchtype));
12479                      destroy_dahdi_pvt(tmp);
12480                      return NULL;
12481                   }
12482                   if ((pris[span].pri.dialplan) && (pris[span].pri.dialplan != conf->pri.pri.dialplan)) {
12483                      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));
12484                      destroy_dahdi_pvt(tmp);
12485                      return NULL;
12486                   }
12487                   if (!ast_strlen_zero(pris[span].pri.idledial) && strcmp(pris[span].pri.idledial, conf->pri.pri.idledial)) {
12488                      ast_log(LOG_ERROR, "Span %d already has idledial '%s'.\n", span + 1, conf->pri.pri.idledial);
12489                      destroy_dahdi_pvt(tmp);
12490                      return NULL;
12491                   }
12492                   if (!ast_strlen_zero(pris[span].pri.idleext) && strcmp(pris[span].pri.idleext, conf->pri.pri.idleext)) {
12493                      ast_log(LOG_ERROR, "Span %d already has idleext '%s'.\n", span + 1, conf->pri.pri.idleext);
12494                      destroy_dahdi_pvt(tmp);
12495                      return NULL;
12496                   }
12497                   if (pris[span].pri.minunused && (pris[span].pri.minunused != conf->pri.pri.minunused)) {
12498                      ast_log(LOG_ERROR, "Span %d already has minunused of %d.\n", span + 1, conf->pri.pri.minunused);
12499                      destroy_dahdi_pvt(tmp);
12500                      return NULL;
12501                   }
12502                   if (pris[span].pri.minidle && (pris[span].pri.minidle != conf->pri.pri.minidle)) {
12503                      ast_log(LOG_ERROR, "Span %d already has minidle of %d.\n", span + 1, conf->pri.pri.minidle);
12504                      destroy_dahdi_pvt(tmp);
12505                      return NULL;
12506                   }
12507                   if (pris[span].pri.numchans >= ARRAY_LEN(pris[span].pri.pvts)) {
12508                      ast_log(LOG_ERROR, "Unable to add channel %d: Too many channels in trunk group %d!\n", channel,
12509                         pris[span].pri.trunkgroup);
12510                      destroy_dahdi_pvt(tmp);
12511                      return NULL;
12512                   }
12513 
12514                   ast_debug(4, "Adding callbacks %p to chan %d\n", &dahdi_pri_callbacks, tmp->channel);
12515                   pri_chan = sig_pri_chan_new(tmp, &dahdi_pri_callbacks, &pris[span].pri, tmp->logicalspan, p.chanpos, pris[span].mastertrunkgroup);
12516                   if (!pri_chan) {
12517                      destroy_dahdi_pvt(tmp);
12518                      return NULL;
12519                   }
12520                   tmp->sig_pvt = pri_chan;
12521                   tmp->pri = &pris[span].pri;
12522 
12523                   tmp->priexclusive = conf->chan.priexclusive;
12524 
12525                   if (!tmp->pri->cc_params) {
12526                      tmp->pri->cc_params = ast_cc_config_params_init();
12527                      if (!tmp->pri->cc_params) {
12528                         destroy_dahdi_pvt(tmp);
12529                         return NULL;
12530                      }
12531                   }
12532                   ast_cc_copy_config_params(tmp->pri->cc_params,
12533                      conf->chan.cc_params);
12534 
12535                   pris[span].pri.sig = chan_sig;
12536                   pris[span].pri.nodetype = conf->pri.pri.nodetype;
12537                   pris[span].pri.switchtype = myswitchtype;
12538                   pris[span].pri.nsf = conf->pri.pri.nsf;
12539                   pris[span].pri.dialplan = conf->pri.pri.dialplan;
12540                   pris[span].pri.localdialplan = conf->pri.pri.localdialplan;
12541                   pris[span].pri.pvts[pris[span].pri.numchans++] = tmp->sig_pvt;
12542                   pris[span].pri.minunused = conf->pri.pri.minunused;
12543                   pris[span].pri.minidle = conf->pri.pri.minidle;
12544                   pris[span].pri.overlapdial = conf->pri.pri.overlapdial;
12545                   pris[span].pri.qsigchannelmapping = conf->pri.pri.qsigchannelmapping;
12546                   pris[span].pri.discardremoteholdretrieval = conf->pri.pri.discardremoteholdretrieval;
12547 #if defined(HAVE_PRI_SERVICE_MESSAGES)
12548                   pris[span].pri.enable_service_message_support = conf->pri.pri.enable_service_message_support;
12549 #endif   /* defined(HAVE_PRI_SERVICE_MESSAGES) */
12550 #ifdef HAVE_PRI_INBANDDISCONNECT
12551                   pris[span].pri.inbanddisconnect = conf->pri.pri.inbanddisconnect;
12552 #endif
12553 #if defined(HAVE_PRI_CALL_HOLD)
12554                   pris[span].pri.hold_disconnect_transfer =
12555                      conf->pri.pri.hold_disconnect_transfer;
12556 #endif   /* defined(HAVE_PRI_CALL_HOLD) */
12557 #if defined(HAVE_PRI_CCSS)
12558                   pris[span].pri.cc_ptmp_recall_mode =
12559                      conf->pri.pri.cc_ptmp_recall_mode;
12560                   pris[span].pri.cc_qsig_signaling_link_req =
12561                      conf->pri.pri.cc_qsig_signaling_link_req;
12562                   pris[span].pri.cc_qsig_signaling_link_rsp =
12563                      conf->pri.pri.cc_qsig_signaling_link_rsp;
12564 #endif   /* defined(HAVE_PRI_CCSS) */
12565 #if defined(HAVE_PRI_CALL_WAITING)
12566                   pris[span].pri.max_call_waiting_calls =
12567                      conf->pri.pri.max_call_waiting_calls;
12568                   pris[span].pri.allow_call_waiting_calls =
12569                      conf->pri.pri.allow_call_waiting_calls;
12570 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
12571                   pris[span].pri.transfer = conf->chan.transfer;
12572                   pris[span].pri.facilityenable = conf->pri.pri.facilityenable;
12573 #if defined(HAVE_PRI_L2_PERSISTENCE)
12574                   pris[span].pri.l2_persistence = conf->pri.pri.l2_persistence;
12575 #endif   /* defined(HAVE_PRI_L2_PERSISTENCE) */
12576 #if defined(HAVE_PRI_AOC_EVENTS)
12577                   pris[span].pri.aoc_passthrough_flag = conf->pri.pri.aoc_passthrough_flag;
12578                   pris[span].pri.aoce_delayhangup = conf->pri.pri.aoce_delayhangup;
12579 #endif   /* defined(HAVE_PRI_AOC_EVENTS) */
12580                   pris[span].pri.append_msn_to_user_tag = conf->pri.pri.append_msn_to_user_tag;
12581                   ast_copy_string(pris[span].pri.initial_user_tag, conf->chan.cid_tag, sizeof(pris[span].pri.initial_user_tag));
12582                   ast_copy_string(pris[span].pri.msn_list, conf->pri.pri.msn_list, sizeof(pris[span].pri.msn_list));
12583 #if defined(HAVE_PRI_MWI)
12584                   ast_copy_string(pris[span].pri.mwi_mailboxes,
12585                      conf->pri.pri.mwi_mailboxes,
12586                      sizeof(pris[span].pri.mwi_mailboxes));
12587 #endif   /* defined(HAVE_PRI_MWI) */
12588                   ast_copy_string(pris[span].pri.idledial, conf->pri.pri.idledial, sizeof(pris[span].pri.idledial));
12589                   ast_copy_string(pris[span].pri.idleext, conf->pri.pri.idleext, sizeof(pris[span].pri.idleext));
12590                   ast_copy_string(pris[span].pri.internationalprefix, conf->pri.pri.internationalprefix, sizeof(pris[span].pri.internationalprefix));
12591                   ast_copy_string(pris[span].pri.nationalprefix, conf->pri.pri.nationalprefix, sizeof(pris[span].pri.nationalprefix));
12592                   ast_copy_string(pris[span].pri.localprefix, conf->pri.pri.localprefix, sizeof(pris[span].pri.localprefix));
12593                   ast_copy_string(pris[span].pri.privateprefix, conf->pri.pri.privateprefix, sizeof(pris[span].pri.privateprefix));
12594                   ast_copy_string(pris[span].pri.unknownprefix, conf->pri.pri.unknownprefix, sizeof(pris[span].pri.unknownprefix));
12595                   pris[span].pri.resetinterval = conf->pri.pri.resetinterval;
12596 
12597                   for (x = 0; x < PRI_MAX_TIMERS; x++) {
12598                      pris[span].pri.pritimers[x] = conf->pri.pri.pritimers[x];
12599                   }
12600 
12601 #if defined(HAVE_PRI_CALL_WAITING)
12602                   /* Channel initial config parameters. */
12603                   pris[span].pri.ch_cfg.stripmsd = conf->chan.stripmsd;
12604                   pris[span].pri.ch_cfg.hidecallerid = conf->chan.hidecallerid;
12605                   pris[span].pri.ch_cfg.hidecalleridname = conf->chan.hidecalleridname;
12606                   pris[span].pri.ch_cfg.immediate = conf->chan.immediate;
12607                   pris[span].pri.ch_cfg.priexclusive = conf->chan.priexclusive;
12608                   pris[span].pri.ch_cfg.priindication_oob = conf->chan.priindication_oob;
12609                   pris[span].pri.ch_cfg.use_callerid = conf->chan.use_callerid;
12610                   pris[span].pri.ch_cfg.use_callingpres = conf->chan.use_callingpres;
12611                   ast_copy_string(pris[span].pri.ch_cfg.context, conf->chan.context, sizeof(pris[span].pri.ch_cfg.context));
12612                   ast_copy_string(pris[span].pri.ch_cfg.mohinterpret, conf->chan.mohinterpret, sizeof(pris[span].pri.ch_cfg.mohinterpret));
12613 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
12614                } else {
12615                   ast_log(LOG_ERROR, "Channel %d is reserved for D-channel.\n", p.chanpos);
12616                   destroy_dahdi_pvt(tmp);
12617                   return NULL;
12618                }
12619             }
12620          }
12621 #endif
12622       } else {
12623          /* already exists in interface list */
12624          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));
12625          chan_sig = tmp->sig;
12626          if (tmp->subs[SUB_REAL].dfd > -1) {
12627             memset(&p, 0, sizeof(p));
12628             res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
12629          }
12630       }
12631       /* Adjust starttime on loopstart and kewlstart trunks to reasonable values */
12632       switch (chan_sig) {
12633       case SIG_FXSKS:
12634       case SIG_FXSLS:
12635       case SIG_EM:
12636       case SIG_EM_E1:
12637       case SIG_EMWINK:
12638       case SIG_FEATD:
12639       case SIG_FEATDMF:
12640       case SIG_FEATDMF_TA:
12641       case SIG_FEATB:
12642       case SIG_E911:
12643       case SIG_SF:
12644       case SIG_SFWINK:
12645       case SIG_FGC_CAMA:
12646       case SIG_FGC_CAMAMF:
12647       case SIG_SF_FEATD:
12648       case SIG_SF_FEATDMF:
12649       case SIG_SF_FEATB:
12650          p.starttime = 250;
12651          break;
12652       }
12653 
12654       if (tmp->radio) {
12655          /* XXX Waiting to hear back from Jim if these should be adjustable XXX */
12656          p.channo = channel;
12657          p.rxwinktime = 1;
12658          p.rxflashtime = 1;
12659          p.starttime = 1;
12660          p.debouncetime = 5;
12661       } else {
12662          p.channo = channel;
12663          /* Override timing settings based on config file */
12664          if (conf->timing.prewinktime >= 0)
12665             p.prewinktime = conf->timing.prewinktime;
12666          if (conf->timing.preflashtime >= 0)
12667             p.preflashtime = conf->timing.preflashtime;
12668          if (conf->timing.winktime >= 0)
12669             p.winktime = conf->timing.winktime;
12670          if (conf->timing.flashtime >= 0)
12671             p.flashtime = conf->timing.flashtime;
12672          if (conf->timing.starttime >= 0)
12673             p.starttime = conf->timing.starttime;
12674          if (conf->timing.rxwinktime >= 0)
12675             p.rxwinktime = conf->timing.rxwinktime;
12676          if (conf->timing.rxflashtime >= 0)
12677             p.rxflashtime = conf->timing.rxflashtime;
12678          if (conf->timing.debouncetime >= 0)
12679             p.debouncetime = conf->timing.debouncetime;
12680       }
12681 
12682       /* don't set parms on a pseudo-channel */
12683       if (tmp->subs[SUB_REAL].dfd >= 0)
12684       {
12685          res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_PARAMS, &p);
12686          if (res < 0) {
12687             ast_log(LOG_ERROR, "Unable to set parameters: %s\n", strerror(errno));
12688             destroy_dahdi_pvt(tmp);
12689             return NULL;
12690          }
12691       }
12692 #if 1
12693       if (!here && (tmp->subs[SUB_REAL].dfd > -1)) {
12694          memset(&bi, 0, sizeof(bi));
12695          res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
12696          if (!res) {
12697             bi.txbufpolicy = conf->chan.buf_policy;
12698             bi.rxbufpolicy = conf->chan.buf_policy;
12699             bi.numbufs = conf->chan.buf_no;
12700             res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
12701             if (res < 0) {
12702                ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", channel, strerror(errno));
12703             }
12704          } else {
12705             ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", channel, strerror(errno));
12706          }
12707          tmp->buf_policy = conf->chan.buf_policy;
12708          tmp->buf_no = conf->chan.buf_no;
12709          tmp->usefaxbuffers = conf->chan.usefaxbuffers;
12710          tmp->faxbuf_policy = conf->chan.faxbuf_policy;
12711          tmp->faxbuf_no = conf->chan.faxbuf_no;
12712          /* This is not as gnarly as it may first appear.  If the ioctl above failed, we'd be setting
12713           * tmp->bufsize to zero which would cause subsequent faxbuffer-related ioctl calls to fail.
12714           * The reason the ioctl call above failed should to be determined before worrying about the
12715           * faxbuffer-related ioctl calls */
12716          tmp->bufsize = bi.bufsize;
12717       }
12718 #endif
12719       tmp->immediate = conf->chan.immediate;
12720       tmp->transfertobusy = conf->chan.transfertobusy;
12721       if (chan_sig & __DAHDI_SIG_FXS) {
12722          tmp->mwimonitor_fsk = conf->chan.mwimonitor_fsk;
12723          tmp->mwimonitor_neon = conf->chan.mwimonitor_neon;
12724          tmp->mwimonitor_rpas = conf->chan.mwimonitor_rpas;
12725       }
12726       tmp->ringt_base = ringt_base;
12727       tmp->firstradio = 0;
12728       if ((chan_sig == SIG_FXOKS) || (chan_sig == SIG_FXOLS) || (chan_sig == SIG_FXOGS))
12729          tmp->permcallwaiting = conf->chan.callwaiting;
12730       else
12731          tmp->permcallwaiting = 0;
12732       /* Flag to destroy the channel must be cleared on new mkif.  Part of changes for reload to work */
12733       tmp->destroy = 0;
12734       tmp->drings = conf->chan.drings;
12735 
12736       /* 10 is a nice default. */
12737       if (tmp->drings.ringnum[0].range == 0)
12738          tmp->drings.ringnum[0].range = 10;
12739       if (tmp->drings.ringnum[1].range == 0)
12740          tmp->drings.ringnum[1].range = 10;
12741       if (tmp->drings.ringnum[2].range == 0)
12742          tmp->drings.ringnum[2].range = 10;
12743 
12744       tmp->usedistinctiveringdetection = usedistinctiveringdetection;
12745       tmp->callwaitingcallerid = conf->chan.callwaitingcallerid;
12746       tmp->threewaycalling = conf->chan.threewaycalling;
12747       tmp->adsi = conf->chan.adsi;
12748       tmp->use_smdi = conf->chan.use_smdi;
12749       tmp->permhidecallerid = conf->chan.hidecallerid;
12750       tmp->hidecalleridname = conf->chan.hidecalleridname;
12751       tmp->callreturn = conf->chan.callreturn;
12752       tmp->echocancel = conf->chan.echocancel;
12753       tmp->echotraining = conf->chan.echotraining;
12754       tmp->pulse = conf->chan.pulse;
12755       if (tmp->echocancel.head.tap_length) {
12756          tmp->echocanbridged = conf->chan.echocanbridged;
12757       } else {
12758          if (conf->chan.echocanbridged)
12759             ast_log(LOG_NOTICE, "echocancelwhenbridged requires echocancel to be enabled; ignoring\n");
12760          tmp->echocanbridged = 0;
12761       }
12762       tmp->busydetect = conf->chan.busydetect;
12763       tmp->busycount = conf->chan.busycount;
12764       tmp->busy_tonelength = conf->chan.busy_tonelength;
12765       tmp->busy_quietlength = conf->chan.busy_quietlength;
12766       tmp->callprogress = conf->chan.callprogress;
12767       tmp->waitfordialtone = conf->chan.waitfordialtone;
12768       tmp->cancallforward = conf->chan.cancallforward;
12769       tmp->dtmfrelax = conf->chan.dtmfrelax;
12770       tmp->callwaiting = tmp->permcallwaiting;
12771       tmp->hidecallerid = tmp->permhidecallerid;
12772       tmp->channel = channel;
12773       tmp->stripmsd = conf->chan.stripmsd;
12774       tmp->use_callerid = conf->chan.use_callerid;
12775       tmp->cid_signalling = conf->chan.cid_signalling;
12776       tmp->cid_start = conf->chan.cid_start;
12777       tmp->dahditrcallerid = conf->chan.dahditrcallerid;
12778       tmp->restrictcid = conf->chan.restrictcid;
12779       tmp->use_callingpres = conf->chan.use_callingpres;
12780       if (tmp->usedistinctiveringdetection) {
12781          if (!tmp->use_callerid) {
12782             ast_log(LOG_NOTICE, "Distinctive Ring detect requires 'usecallerid' be on\n");
12783             tmp->use_callerid = 1;
12784          }
12785       }
12786 
12787       if (tmp->cid_signalling == CID_SIG_SMDI) {
12788          if (!tmp->use_smdi) {
12789             ast_log(LOG_WARNING, "SMDI callerid requires SMDI to be enabled, enabling...\n");
12790             tmp->use_smdi = 1;
12791          }
12792       }
12793       if (tmp->use_smdi) {
12794          tmp->smdi_iface = ast_smdi_interface_find(conf->smdi_port);
12795          if (!(tmp->smdi_iface)) {
12796             ast_log(LOG_ERROR, "Invalid SMDI port specfied, disabling SMDI support\n");
12797             tmp->use_smdi = 0;
12798          }
12799       }
12800 
12801       ast_copy_string(tmp->accountcode, conf->chan.accountcode, sizeof(tmp->accountcode));
12802       tmp->amaflags = conf->chan.amaflags;
12803       if (!here) {
12804          tmp->confno = -1;
12805          tmp->propconfno = -1;
12806       }
12807       tmp->canpark = conf->chan.canpark;
12808       tmp->transfer = conf->chan.transfer;
12809       ast_copy_string(tmp->defcontext,conf->chan.context,sizeof(tmp->defcontext));
12810       ast_copy_string(tmp->language, conf->chan.language, sizeof(tmp->language));
12811       ast_copy_string(tmp->mohinterpret, conf->chan.mohinterpret, sizeof(tmp->mohinterpret));
12812       ast_copy_string(tmp->mohsuggest, conf->chan.mohsuggest, sizeof(tmp->mohsuggest));
12813       ast_copy_string(tmp->context, conf->chan.context, sizeof(tmp->context));
12814       ast_copy_string(tmp->parkinglot, conf->chan.parkinglot, sizeof(tmp->parkinglot));
12815       tmp->cid_ton = 0;
12816       if (analog_lib_handles(tmp->sig, tmp->radio, tmp->oprmode)) {
12817          ast_copy_string(tmp->cid_num, conf->chan.cid_num, sizeof(tmp->cid_num));
12818          ast_copy_string(tmp->cid_name, conf->chan.cid_name, sizeof(tmp->cid_name));
12819       } else {
12820          tmp->cid_num[0] = '\0';
12821          tmp->cid_name[0] = '\0';
12822       }
12823 #if defined(HAVE_PRI)
12824       if (dahdi_sig_pri_lib_handles(tmp->sig)) {
12825          tmp->cid_tag[0] = '\0';
12826       } else
12827 #endif   /* defined(HAVE_PRI) */
12828       {
12829          ast_copy_string(tmp->cid_tag, conf->chan.cid_tag, sizeof(tmp->cid_tag));
12830       }
12831       tmp->cid_subaddr[0] = '\0';
12832       ast_copy_string(tmp->mailbox, conf->chan.mailbox, sizeof(tmp->mailbox));
12833       if (channel != CHAN_PSEUDO && !ast_strlen_zero(tmp->mailbox)) {
12834          char *mailbox, *context;
12835          mailbox = context = ast_strdupa(tmp->mailbox);
12836          strsep(&context, "@");
12837          if (ast_strlen_zero(context))
12838             context = "default";
12839          tmp->mwi_event_sub = ast_event_subscribe(AST_EVENT_MWI, mwi_event_cb, "Dahdi MWI subscription", NULL,
12840             AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
12841             AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
12842             AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS,
12843             AST_EVENT_IE_END);
12844       }
12845 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
12846       tmp->mwisend_setting = conf->chan.mwisend_setting;
12847       tmp->mwisend_fsk  = conf->chan.mwisend_fsk;
12848       tmp->mwisend_rpas = conf->chan.mwisend_rpas;
12849 #endif
12850 
12851       tmp->group = conf->chan.group;
12852       tmp->callgroup = conf->chan.callgroup;
12853       tmp->pickupgroup= conf->chan.pickupgroup;
12854       if (conf->chan.vars) {
12855          struct ast_variable *v, *tmpvar;
12856                    for (v = conf->chan.vars ; v ; v = v->next) {
12857                          if ((tmpvar = ast_variable_new(v->name, v->value, v->file))) {
12858                                   tmpvar->next = tmp->vars;
12859                                    tmp->vars = tmpvar;
12860                            }
12861                   }
12862       }
12863       tmp->cid_rxgain = conf->chan.cid_rxgain;
12864       tmp->rxgain = conf->chan.rxgain;
12865       tmp->txgain = conf->chan.txgain;
12866       tmp->txdrc = conf->chan.txdrc;
12867       tmp->rxdrc = conf->chan.rxdrc;
12868       tmp->tonezone = conf->chan.tonezone;
12869       if (tmp->subs[SUB_REAL].dfd > -1) {
12870          set_actual_gain(tmp->subs[SUB_REAL].dfd, tmp->rxgain, tmp->txgain, tmp->rxdrc, tmp->txdrc, tmp->law);
12871          if (tmp->dsp)
12872             ast_dsp_set_digitmode(tmp->dsp, DSP_DIGITMODE_DTMF | tmp->dtmfrelax);
12873          update_conf(tmp);
12874          if (!here) {
12875             switch (chan_sig) {
12876             case SIG_PRI_LIB_HANDLE_CASES:
12877             case SIG_SS7:
12878             case SIG_MFCR2:
12879                break;
12880             default:
12881                /* Hang it up to be sure it's good */
12882                dahdi_set_hook(tmp->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
12883                break;
12884             }
12885          }
12886          ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SETTONEZONE,&tmp->tonezone);
12887          if ((res = get_alarms(tmp)) != DAHDI_ALARM_NONE) {
12888             /* the dchannel is down so put the channel in alarm */
12889             switch (tmp->sig) {
12890 #ifdef HAVE_PRI
12891             case SIG_PRI_LIB_HANDLE_CASES:
12892                sig_pri_set_alarm(tmp->sig_pvt, 1);
12893                break;
12894 #endif
12895 #if defined(HAVE_SS7)
12896             case SIG_SS7:
12897                sig_ss7_set_alarm(tmp->sig_pvt, 1);
12898                break;
12899 #endif   /* defined(HAVE_SS7) */
12900             default:
12901                /* The only sig submodule left should be sig_analog. */
12902                analog_p = tmp->sig_pvt;
12903                if (analog_p) {
12904                   analog_p->inalarm = 1;
12905                }
12906                tmp->inalarm = 1;
12907                break;
12908             }
12909             handle_alarms(tmp, res);
12910          }
12911       }
12912 
12913       tmp->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
12914       tmp->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
12915       tmp->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
12916       tmp->sendcalleridafter = conf->chan.sendcalleridafter;
12917       ast_cc_copy_config_params(tmp->cc_params, conf->chan.cc_params);
12918 
12919       if (!here) {
12920          tmp->locallyblocked = 0;
12921          tmp->remotelyblocked = 0;
12922          switch (tmp->sig) {
12923 #if defined(HAVE_PRI)
12924          case SIG_PRI_LIB_HANDLE_CASES:
12925             tmp->inservice = 1;/* Inservice until actually implemented. */
12926 #if defined(HAVE_PRI_SERVICE_MESSAGES)
12927             ((struct sig_pri_chan *) tmp->sig_pvt)->service_status = 0;
12928             if (chan_sig == SIG_PRI) {
12929                char db_chan_name[20];
12930                char db_answer[5];
12931 
12932                /*
12933                 * Initialize the active out-of-service status
12934                 * and delete any record if the feature is not enabled.
12935                 */
12936                snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, tmp->span, tmp->channel);
12937                if (!ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) {
12938                   unsigned *why;
12939 
12940                   why = &((struct sig_pri_chan *) tmp->sig_pvt)->service_status;
12941                   if (tmp->pri->enable_service_message_support) {
12942                      char state;
12943 
12944                      sscanf(db_answer, "%1c:%30u", &state, why);
12945 
12946                      /* Ensure that only the implemented bits could be set.*/
12947                      *why &= (SRVST_NEAREND | SRVST_FAREND);
12948                   }
12949                   if (!*why) {
12950                      ast_db_del(db_chan_name, SRVST_DBKEY);
12951                   }
12952                }
12953             }
12954 #endif   /* defined(HAVE_PRI_SERVICE_MESSAGES) */
12955             break;
12956 #endif   /* defined(HAVE_PRI) */
12957 #if defined(HAVE_SS7)
12958          case SIG_SS7:
12959             tmp->inservice = 0;
12960             break;
12961 #endif   /* defined(HAVE_SS7) */
12962          default:
12963              /* We default to in service on protocols that don't have a reset */
12964             tmp->inservice = 1;
12965             break;
12966          }
12967       }
12968 
12969       switch (tmp->sig) {
12970 #if defined(HAVE_PRI)
12971       case SIG_PRI_LIB_HANDLE_CASES:
12972          if (pri_chan) {
12973             pri_chan->channel = tmp->channel;
12974             pri_chan->hidecallerid = tmp->hidecallerid;
12975             pri_chan->hidecalleridname = tmp->hidecalleridname;
12976             pri_chan->immediate = tmp->immediate;
12977             pri_chan->inalarm = tmp->inalarm;
12978             pri_chan->priexclusive = tmp->priexclusive;
12979             pri_chan->priindication_oob = tmp->priindication_oob;
12980             pri_chan->use_callerid = tmp->use_callerid;
12981             pri_chan->use_callingpres = tmp->use_callingpres;
12982             ast_copy_string(pri_chan->context, tmp->context,
12983                sizeof(pri_chan->context));
12984             ast_copy_string(pri_chan->mohinterpret, tmp->mohinterpret,
12985                sizeof(pri_chan->mohinterpret));
12986             pri_chan->stripmsd = tmp->stripmsd;
12987          }
12988          break;
12989 #endif   /* defined(HAVE_PRI) */
12990 #if defined(HAVE_SS7)
12991       case SIG_SS7:
12992          if (ss7_chan) {
12993             ss7_chan->inalarm = tmp->inalarm;
12994 
12995             ss7_chan->stripmsd = tmp->stripmsd;
12996             ss7_chan->hidecallerid = tmp->hidecallerid;
12997             ss7_chan->use_callerid = tmp->use_callerid;
12998             ss7_chan->use_callingpres = tmp->use_callingpres;
12999             ss7_chan->immediate = tmp->immediate;
13000             ss7_chan->locallyblocked = tmp->locallyblocked;
13001             ss7_chan->remotelyblocked = tmp->remotelyblocked;
13002             ast_copy_string(ss7_chan->context, tmp->context,
13003                sizeof(ss7_chan->context));
13004             ast_copy_string(ss7_chan->mohinterpret, tmp->mohinterpret,
13005                sizeof(ss7_chan->mohinterpret));
13006          }
13007          break;
13008 #endif   /* defined(HAVE_SS7) */
13009       default:
13010          /* The only sig submodule left should be sig_analog. */
13011          analog_p = tmp->sig_pvt;
13012          if (analog_p) {
13013             analog_p->channel = tmp->channel;
13014             analog_p->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
13015             analog_p->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
13016             analog_p->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
13017             analog_p->permcallwaiting = conf->chan.callwaiting; /* permcallwaiting possibly modified in analog_config_complete */
13018             analog_p->callreturn = conf->chan.callreturn;
13019             analog_p->cancallforward = conf->chan.cancallforward;
13020             analog_p->canpark = conf->chan.canpark;
13021             analog_p->dahditrcallerid = conf->chan.dahditrcallerid;
13022             analog_p->immediate = conf->chan.immediate;
13023             analog_p->permhidecallerid = conf->chan.permhidecallerid;
13024             analog_p->pulse = conf->chan.pulse;
13025             analog_p->threewaycalling = conf->chan.threewaycalling;
13026             analog_p->transfer = conf->chan.transfer;
13027             analog_p->transfertobusy = conf->chan.transfertobusy;
13028             analog_p->use_callerid = tmp->use_callerid;
13029             analog_p->use_smdi = tmp->use_smdi;
13030             analog_p->smdi_iface = tmp->smdi_iface;
13031             analog_p->outsigmod = ANALOG_SIG_NONE;
13032             analog_p->echotraining = conf->chan.echotraining;
13033             analog_p->cid_signalling = conf->chan.cid_signalling;
13034             analog_p->stripmsd = conf->chan.stripmsd;
13035             switch (conf->chan.cid_start) {
13036             case CID_START_POLARITY:
13037                analog_p->cid_start = ANALOG_CID_START_POLARITY;
13038                break;
13039             case CID_START_POLARITY_IN:
13040                analog_p->cid_start = ANALOG_CID_START_POLARITY_IN;
13041                break;
13042             case CID_START_DTMF_NOALERT:
13043                analog_p->cid_start = ANALOG_CID_START_DTMF_NOALERT;
13044                break;
13045             default:
13046                analog_p->cid_start = ANALOG_CID_START_RING;
13047                break;
13048             }
13049             analog_p->callwaitingcallerid = conf->chan.callwaitingcallerid;
13050             analog_p->ringt = conf->chan.ringt;
13051             analog_p->ringt_base = ringt_base;
13052             analog_p->chan_tech = &dahdi_tech;
13053             analog_p->onhooktime = time(NULL);
13054             if (chan_sig & __DAHDI_SIG_FXO) {
13055                memset(&p, 0, sizeof(p));
13056                res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
13057                if (!res) {
13058                   analog_p->fxsoffhookstate = p.rxisoffhook;
13059                }
13060 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
13061                res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_VMWI_CONFIG, &tmp->mwisend_setting);
13062 #endif
13063             }
13064             analog_p->msgstate = -1;
13065 
13066             ast_copy_string(analog_p->mohsuggest, conf->chan.mohsuggest, sizeof(analog_p->mohsuggest));
13067             ast_copy_string(analog_p->cid_num, conf->chan.cid_num, sizeof(analog_p->cid_num));
13068             ast_copy_string(analog_p->cid_name, conf->chan.cid_name, sizeof(analog_p->cid_name));
13069 
13070             analog_config_complete(analog_p);
13071          }
13072          break;
13073       }
13074 #if defined(HAVE_PRI)
13075       if (tmp->channel == CHAN_PSEUDO) {
13076          /*
13077           * Save off pseudo channel buffer policy values for dynamic creation of
13078           * no B channel interfaces.
13079           */
13080          dahdi_pseudo_parms.buf_no = tmp->buf_no;
13081          dahdi_pseudo_parms.buf_policy = tmp->buf_policy;
13082          dahdi_pseudo_parms.faxbuf_no = tmp->faxbuf_no;
13083          dahdi_pseudo_parms.faxbuf_policy = tmp->faxbuf_policy;
13084       }
13085 #endif   /* defined(HAVE_PRI) */
13086    }
13087    if (tmp && !here) {
13088       /* Add the new channel interface to the sorted channel interface list. */
13089       dahdi_iflist_insert(tmp);
13090    }
13091    return tmp;
13092 }
13093 
13094 static int is_group_or_channel_match(struct dahdi_pvt *p, int span, ast_group_t groupmatch, int *groupmatched, int channelmatch, int *channelmatched)
13095 {
13096 #if defined(HAVE_PRI)
13097    if (0 < span) {
13098       /* The channel must be on the specified PRI span. */
13099       if (!p->pri || p->pri->span != span) {
13100          return 0;
13101       }
13102       if (!groupmatch && channelmatch == -1) {
13103          /* Match any group since it only needs to be on the PRI span. */
13104          *groupmatched = 1;
13105          return 1;
13106       }
13107    }
13108 #endif   /* defined(HAVE_PRI) */
13109    /* check group matching */
13110    if (groupmatch) {
13111       if ((p->group & groupmatch) != groupmatch)
13112          /* Doesn't match the specified group, try the next one */
13113          return 0;
13114       *groupmatched = 1;
13115    }
13116    /* Check to see if we have a channel match */
13117    if (channelmatch != -1) {
13118       if (p->channel != channelmatch)
13119          /* Doesn't match the specified channel, try the next one */
13120          return 0;
13121       *channelmatched = 1;
13122    }
13123 
13124    return 1;
13125 }
13126 
13127 static int available(struct dahdi_pvt **pvt, int is_specific_channel)
13128 {
13129    struct dahdi_pvt *p = *pvt;
13130 
13131    if (p->inalarm)
13132       return 0;
13133 
13134    if (analog_lib_handles(p->sig, p->radio, p->oprmode))
13135       return analog_available(p->sig_pvt);
13136 
13137    switch (p->sig) {
13138 #if defined(HAVE_PRI)
13139    case SIG_PRI_LIB_HANDLE_CASES:
13140       {
13141          struct sig_pri_chan *pvt_chan;
13142          int res;
13143 
13144          pvt_chan = p->sig_pvt;
13145          res = sig_pri_available(&pvt_chan, is_specific_channel);
13146          *pvt = pvt_chan->chan_pvt;
13147          return res;
13148       }
13149 #endif   /* defined(HAVE_PRI) */
13150 #if defined(HAVE_SS7)
13151    case SIG_SS7:
13152       return sig_ss7_available(p->sig_pvt);
13153 #endif   /* defined(HAVE_SS7) */
13154    default:
13155       break;
13156    }
13157 
13158    if (p->locallyblocked || p->remotelyblocked) {
13159       return 0;
13160    }
13161 
13162    /* If no owner definitely available */
13163    if (!p->owner) {
13164 #ifdef HAVE_OPENR2
13165       /* Trust MFC/R2 */
13166       if (p->mfcr2) {
13167          if (p->mfcr2call) {
13168             return 0;
13169          } else {
13170             return 1;
13171          }
13172       }
13173 #endif
13174       return 1;
13175    }
13176 
13177    return 0;
13178 }
13179 
13180 #if defined(HAVE_PRI)
13181 #if defined(HAVE_PRI_CALL_WAITING)
13182 /*!
13183  * \internal
13184  * \brief Init the private channel configuration using the span controller.
13185  * \since 1.8
13186  *
13187  * \param priv Channel to init the configuration.
13188  * \param pri sig_pri PRI control structure.
13189  *
13190  * \note Assumes the pri->lock is already obtained.
13191  *
13192  * \return Nothing
13193  */
13194 static void my_pri_init_config(void *priv, struct sig_pri_span *pri)
13195 {
13196    struct dahdi_pvt *pvt = priv;
13197 
13198    pvt->stripmsd = pri->ch_cfg.stripmsd;
13199    pvt->hidecallerid = pri->ch_cfg.hidecallerid;
13200    pvt->hidecalleridname = pri->ch_cfg.hidecalleridname;
13201    pvt->immediate = pri->ch_cfg.immediate;
13202    pvt->priexclusive = pri->ch_cfg.priexclusive;
13203    pvt->priindication_oob = pri->ch_cfg.priindication_oob;
13204    pvt->use_callerid = pri->ch_cfg.use_callerid;
13205    pvt->use_callingpres = pri->ch_cfg.use_callingpres;
13206    ast_copy_string(pvt->context, pri->ch_cfg.context, sizeof(pvt->context));
13207    ast_copy_string(pvt->mohinterpret, pri->ch_cfg.mohinterpret, sizeof(pvt->mohinterpret));
13208 }
13209 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
13210 #endif   /* defined(HAVE_PRI) */
13211 
13212 #if defined(HAVE_PRI)
13213 /*!
13214  * \internal
13215  * \brief Create a no B channel interface.
13216  * \since 1.8
13217  *
13218  * \param pri sig_pri span controller to add interface.
13219  *
13220  * \note Assumes the pri->lock is already obtained.
13221  *
13222  * \retval array-index into private pointer array on success.
13223  * \retval -1 on error.
13224  */
13225 static int dahdi_new_pri_nobch_channel(struct sig_pri_span *pri)
13226 {
13227    int pvt_idx;
13228    int res;
13229    unsigned idx;
13230    struct dahdi_pvt *pvt;
13231    struct sig_pri_chan *chan;
13232    struct dahdi_bufferinfo bi;
13233 
13234    static int nobch_channel = CHAN_PSEUDO;
13235 
13236    /* Find spot in the private pointer array for new interface. */
13237    for (pvt_idx = 0; pvt_idx < pri->numchans; ++pvt_idx) {
13238       if (!pri->pvts[pvt_idx]) {
13239          break;
13240       }
13241    }
13242    if (pri->numchans == pvt_idx) {
13243       if (ARRAY_LEN(pri->pvts) <= pvt_idx) {
13244          ast_log(LOG_ERROR, "Unable to add a no-B-channel interface!\n");
13245          return -1;
13246       }
13247 
13248       /* Add new spot to the private pointer array. */
13249       pri->pvts[pvt_idx] = NULL;
13250       ++pri->numchans;
13251    }
13252 
13253    pvt = ast_calloc(1, sizeof(*pvt));
13254    if (!pvt) {
13255       return -1;
13256    }
13257    pvt->cc_params = ast_cc_config_params_init();
13258    if (!pvt->cc_params) {
13259       ast_free(pvt);
13260       return -1;
13261    }
13262    ast_mutex_init(&pvt->lock);
13263    for (idx = 0; idx < ARRAY_LEN(pvt->subs); ++idx) {
13264       pvt->subs[idx].dfd = -1;
13265    }
13266    pvt->buf_no = dahdi_pseudo_parms.buf_no;
13267    pvt->buf_policy = dahdi_pseudo_parms.buf_policy;
13268    pvt->faxbuf_no = dahdi_pseudo_parms.faxbuf_no;
13269    pvt->faxbuf_policy = dahdi_pseudo_parms.faxbuf_policy;
13270 
13271    chan = sig_pri_chan_new(pvt, &dahdi_pri_callbacks, pri, 0, 0, 0);
13272    if (!chan) {
13273       destroy_dahdi_pvt(pvt);
13274       return -1;
13275    }
13276    chan->no_b_channel = 1;
13277 
13278    /*
13279     * Pseudo channel companding law.
13280     * Needed for outgoing call waiting calls.
13281     * XXX May need to make this determined by switchtype or user option.
13282     */
13283    pvt->law_default = DAHDI_LAW_ALAW;
13284 
13285    pvt->sig = pri->sig;
13286    pvt->outsigmod = -1;
13287    pvt->pri = pri;
13288    pvt->sig_pvt = chan;
13289    pri->pvts[pvt_idx] = chan;
13290 
13291    pvt->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo");
13292    if (pvt->subs[SUB_REAL].dfd < 0) {
13293       ast_log(LOG_ERROR, "Unable to open no B channel interface pseudo channel: %s\n",
13294          strerror(errno));
13295       destroy_dahdi_pvt(pvt);
13296       return -1;
13297    }
13298    memset(&bi, 0, sizeof(bi));
13299    res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
13300    if (!res) {
13301       pvt->bufsize = bi.bufsize;
13302       bi.txbufpolicy = pvt->buf_policy;
13303       bi.rxbufpolicy = pvt->buf_policy;
13304       bi.numbufs = pvt->buf_no;
13305       res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
13306       if (res < 0) {
13307          ast_log(LOG_WARNING,
13308             "Unable to set buffer policy on no B channel interface: %s\n",
13309             strerror(errno));
13310       }
13311    } else
13312       ast_log(LOG_WARNING,
13313          "Unable to check buffer policy on no B channel interface: %s\n",
13314          strerror(errno));
13315 
13316    --nobch_channel;
13317    if (CHAN_PSEUDO < nobch_channel) {
13318       nobch_channel = CHAN_PSEUDO - 1;
13319    }
13320    pvt->channel = nobch_channel;
13321    pvt->span = pri->span;
13322    chan->channel = pvt->channel;
13323 
13324    dahdi_nobch_insert(pri, pvt);
13325 
13326    return pvt_idx;
13327 }
13328 #endif   /* defined(HAVE_PRI) */
13329 
13330 /* This function can *ONLY* be used for copying pseudo (CHAN_PSEUDO) private
13331    structures; it makes no attempt to safely copy regular channel private
13332    structures that might contain reference-counted object pointers and other
13333    scary bits
13334 */
13335 static struct dahdi_pvt *duplicate_pseudo(struct dahdi_pvt *src)
13336 {
13337    struct dahdi_pvt *p;
13338    struct dahdi_bufferinfo bi;
13339    int res;
13340 
13341    p = ast_malloc(sizeof(*p));
13342    if (!p) {
13343       return NULL;
13344    }
13345    *p = *src;
13346 
13347    /* Must deep copy the cc_params. */
13348    p->cc_params = ast_cc_config_params_init();
13349    if (!p->cc_params) {
13350       ast_free(p);
13351       return NULL;
13352    }
13353    ast_cc_copy_config_params(p->cc_params, src->cc_params);
13354 
13355    p->which_iflist = DAHDI_IFLIST_NONE;
13356    p->next = NULL;
13357    p->prev = NULL;
13358    ast_mutex_init(&p->lock);
13359    p->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo");
13360    if (p->subs[SUB_REAL].dfd < 0) {
13361       ast_log(LOG_ERROR, "Unable to dup channel: %s\n", strerror(errno));
13362       destroy_dahdi_pvt(p);
13363       return NULL;
13364    }
13365    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
13366    if (!res) {
13367       bi.txbufpolicy = src->buf_policy;
13368       bi.rxbufpolicy = src->buf_policy;
13369       bi.numbufs = src->buf_no;
13370       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
13371       if (res < 0) {
13372          ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel: %s\n", strerror(errno));
13373       }
13374    } else
13375       ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel: %s\n", strerror(errno));
13376    p->destroy = 1;
13377    dahdi_iflist_insert(p);
13378    return p;
13379 }
13380 
13381 struct dahdi_starting_point {
13382    /*! Group matching mask.  Zero if not specified. */
13383    ast_group_t groupmatch;
13384    /*! DAHDI channel to match with.  -1 if not specified. */
13385    int channelmatch;
13386    /*! Round robin saved search location index. (Valid if roundrobin TRUE) */
13387    int rr_starting_point;
13388    /*! ISDN span where channels can be picked (Zero if not specified) */
13389    int span;
13390    /*! Analog channel distinctive ring cadance index. */
13391    int cadance;
13392    /*! Dialing option. c/r/d if present and valid. */
13393    char opt;
13394    /*! TRUE if to search the channel list backwards. */
13395    char backwards;
13396    /*! TRUE if search is done with round robin sequence. */
13397    char roundrobin;
13398 };
13399 static struct dahdi_pvt *determine_starting_point(const char *data, struct dahdi_starting_point *param)
13400 {
13401    char *dest;
13402    char *s;
13403    int x;
13404    int res = 0;
13405    struct dahdi_pvt *p;
13406    char *subdir = NULL;
13407    AST_DECLARE_APP_ARGS(args,
13408       AST_APP_ARG(group);  /* channel/group token */
13409       //AST_APP_ARG(ext);  /* extension token */
13410       //AST_APP_ARG(opts); /* options token */
13411       AST_APP_ARG(other);  /* Any remining unused arguments */
13412    );
13413 
13414    /*
13415     * data is ---v
13416     * Dial(DAHDI/pseudo[/extension[/options]])
13417     * Dial(DAHDI/<channel#>[c|r<cadance#>|d][/extension[/options]])
13418     * Dial(DAHDI/<subdir>!<channel#>[c|r<cadance#>|d][/extension[/options]])
13419     * Dial(DAHDI/i<span>[/extension[/options]])
13420     * Dial(DAHDI/[i<span>-](g|G|r|R)<group#(0-63)>[c|r<cadance#>|d][/extension[/options]])
13421     *
13422     * i - ISDN span channel restriction.
13423     *     Used by CC to ensure that the CC recall goes out the same span.
13424     *     Also to make ISDN channel names dialable when the sequence number
13425     *     is stripped off.  (Used by DTMF attended transfer feature.)
13426     *
13427     * g - channel group allocation search forward
13428     * G - channel group allocation search backward
13429     * r - channel group allocation round robin search forward
13430     * R - channel group allocation round robin search backward
13431     *
13432     * c - Wait for DTMF digit to confirm answer
13433     * r<cadance#> - Set distintive ring cadance number
13434     * d - Force bearer capability for ISDN/SS7 call to digital.
13435     */
13436 
13437    if (data) {
13438       dest = ast_strdupa(data);
13439    } else {
13440       ast_log(LOG_WARNING, "Channel requested with no data\n");
13441       return NULL;
13442    }
13443    AST_NONSTANDARD_APP_ARGS(args, dest, '/');
13444    if (!args.argc || ast_strlen_zero(args.group)) {
13445       ast_log(LOG_WARNING, "No channel/group specified\n");
13446       return NULL;
13447    }
13448 
13449    /* Initialize the output parameters */
13450    memset(param, 0, sizeof(*param));
13451    param->channelmatch = -1;
13452 
13453    if (strchr(args.group, '!') != NULL) {
13454       char *prev = args.group;
13455       while ((s = strchr(prev, '!')) != NULL) {
13456          *s++ = '/';
13457          prev = s;
13458       }
13459       *(prev - 1) = '\0';
13460       subdir = args.group;
13461       args.group = prev;
13462    } else if (args.group[0] == 'i') {
13463       /* Extract the ISDN span channel restriction specifier. */
13464       res = sscanf(args.group + 1, "%30d", &x);
13465       if (res < 1) {
13466          ast_log(LOG_WARNING, "Unable to determine ISDN span for data %s\n", data);
13467          return NULL;
13468       }
13469       param->span = x;
13470 
13471       /* Remove the ISDN span channel restriction specifier. */
13472       s = strchr(args.group, '-');
13473       if (!s) {
13474          /* Search all groups since we are ISDN span restricted. */
13475          return iflist;
13476       }
13477       args.group = s + 1;
13478       res = 0;
13479    }
13480    if (toupper(args.group[0]) == 'G' || toupper(args.group[0])=='R') {
13481       /* Retrieve the group number */
13482       s = args.group + 1;
13483       res = sscanf(s, "%30d%1c%30d", &x, &param->opt, &param->cadance);
13484       if (res < 1) {
13485          ast_log(LOG_WARNING, "Unable to determine group for data %s\n", data);
13486          return NULL;
13487       }
13488       param->groupmatch = ((ast_group_t) 1 << x);
13489 
13490       if (toupper(args.group[0]) == 'G') {
13491          if (args.group[0] == 'G') {
13492             param->backwards = 1;
13493             p = ifend;
13494          } else
13495             p = iflist;
13496       } else {
13497          if (ARRAY_LEN(round_robin) <= x) {
13498             ast_log(LOG_WARNING, "Round robin index %d out of range for data %s\n",
13499                x, data);
13500             return NULL;
13501          }
13502          if (args.group[0] == 'R') {
13503             param->backwards = 1;
13504             p = round_robin[x] ? round_robin[x]->prev : ifend;
13505             if (!p)
13506                p = ifend;
13507          } else {
13508             p = round_robin[x] ? round_robin[x]->next : iflist;
13509             if (!p)
13510                p = iflist;
13511          }
13512          param->roundrobin = 1;
13513          param->rr_starting_point = x;
13514       }
13515    } else {
13516       s = args.group;
13517       if (!strcasecmp(s, "pseudo")) {
13518          /* Special case for pseudo */
13519          x = CHAN_PSEUDO;
13520          param->channelmatch = x;
13521       } else {
13522          res = sscanf(s, "%30d%1c%30d", &x, &param->opt, &param->cadance);
13523          if (res < 1) {
13524             ast_log(LOG_WARNING, "Unable to determine channel for data %s\n", data);
13525             return NULL;
13526          } else {
13527             param->channelmatch = x;
13528          }
13529       }
13530       if (subdir) {
13531          char path[PATH_MAX];
13532          struct stat stbuf;
13533 
13534          snprintf(path, sizeof(path), "/dev/dahdi/%s/%d",
13535                subdir, param->channelmatch);
13536          if (stat(path, &stbuf) < 0) {
13537             ast_log(LOG_WARNING, "stat(%s) failed: %s\n",
13538                   path, strerror(errno));
13539             return NULL;
13540          }
13541          if (!S_ISCHR(stbuf.st_mode)) {
13542             ast_log(LOG_ERROR, "%s: Not a character device file\n",
13543                   path);
13544             return NULL;
13545          }
13546          param->channelmatch = minor(stbuf.st_rdev);
13547       }
13548 
13549       p = iflist;
13550    }
13551 
13552    if (param->opt == 'r' && res < 3) {
13553       ast_log(LOG_WARNING, "Distinctive ring missing identifier in '%s'\n", data);
13554       param->opt = '\0';
13555    }
13556 
13557    return p;
13558 }
13559 
13560 static struct ast_channel *dahdi_request(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause)
13561 {
13562    int callwait = 0;
13563    struct dahdi_pvt *p;
13564    struct ast_channel *tmp = NULL;
13565    struct dahdi_pvt *exitpvt;
13566    int channelmatched = 0;
13567    int groupmatched = 0;
13568 #if defined(HAVE_PRI) || defined(HAVE_SS7)
13569    int transcapdigital = 0;
13570 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
13571    struct dahdi_starting_point start;
13572 
13573    ast_mutex_lock(&iflock);
13574    p = determine_starting_point(data, &start);
13575    if (!p) {
13576       /* We couldn't determine a starting point, which likely means badly-formatted channel name. Abort! */
13577       ast_mutex_unlock(&iflock);
13578       return NULL;
13579    }
13580 
13581    /* Search for an unowned channel */
13582    exitpvt = p;
13583    while (p && !tmp) {
13584       if (start.roundrobin)
13585          round_robin[start.rr_starting_point] = p;
13586 
13587       if (is_group_or_channel_match(p, start.span, start.groupmatch, &groupmatched, start.channelmatch, &channelmatched)
13588          && available(&p, channelmatched)) {
13589          ast_debug(1, "Using channel %d\n", p->channel);
13590 
13591          callwait = (p->owner != NULL);
13592 #ifdef HAVE_OPENR2
13593          if (p->mfcr2) {
13594             ast_mutex_lock(&p->lock);
13595             if (p->mfcr2call) {
13596                ast_mutex_unlock(&p->lock);
13597                ast_log(LOG_DEBUG, "Yay!, someone just beat us in the race for channel %d.\n", p->channel);
13598                goto next;
13599             }
13600             p->mfcr2call = 1;
13601             ast_mutex_unlock(&p->lock);
13602          }
13603 #endif
13604          if (p->channel == CHAN_PSEUDO) {
13605             p = duplicate_pseudo(p);
13606             if (!p) {
13607                break;
13608             }
13609          }
13610 
13611          p->distinctivering = 0;
13612          /* Make special notes */
13613          switch (start.opt) {
13614          case '\0':
13615             /* No option present. */
13616             break;
13617          case 'c':
13618             /* Confirm answer */
13619             p->confirmanswer = 1;
13620             break;
13621          case 'r':
13622             /* Distinctive ring */
13623             p->distinctivering = start.cadance;
13624             break;
13625          case 'd':
13626 #if defined(HAVE_PRI) || defined(HAVE_SS7)
13627             /* If this is an ISDN call, make it digital */
13628             transcapdigital = AST_TRANS_CAP_DIGITAL;
13629 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
13630             break;
13631          default:
13632             ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", start.opt, (char *)data);
13633             break;
13634          }
13635 
13636          p->outgoing = 1;
13637          if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
13638             tmp = analog_request(p->sig_pvt, &callwait, requestor);
13639 #ifdef HAVE_PRI
13640          } else if (dahdi_sig_pri_lib_handles(p->sig)) {
13641             /*
13642              * We already have the B channel reserved for this call.  We
13643              * just need to make sure that dahdi_hangup() has completed
13644              * cleaning up before continuing.
13645              */
13646             ast_mutex_lock(&p->lock);
13647             ast_mutex_unlock(&p->lock);
13648 
13649             sig_pri_extract_called_num_subaddr(p->sig_pvt, data, p->dnid,
13650                sizeof(p->dnid));
13651             tmp = sig_pri_request(p->sig_pvt, SIG_PRI_DEFLAW, requestor, transcapdigital);
13652 #endif
13653 #if defined(HAVE_SS7)
13654          } else if (p->sig == SIG_SS7) {
13655             tmp = sig_ss7_request(p->sig_pvt, SIG_SS7_DEFLAW, requestor, transcapdigital);
13656 #endif   /* defined(HAVE_SS7) */
13657          } else {
13658             tmp = dahdi_new(p, AST_STATE_RESERVED, 0, p->owner ? SUB_CALLWAIT : SUB_REAL, 0, requestor ? requestor->linkedid : "");
13659          }
13660          if (!tmp) {
13661             p->outgoing = 0;
13662 #if defined(HAVE_PRI)
13663             switch (p->sig) {
13664             case SIG_PRI_LIB_HANDLE_CASES:
13665 #if defined(HAVE_PRI_CALL_WAITING)
13666                if (((struct sig_pri_chan *) p->sig_pvt)->is_call_waiting) {
13667                   ((struct sig_pri_chan *) p->sig_pvt)->is_call_waiting = 0;
13668                   ast_atomic_fetchadd_int(&p->pri->num_call_waiting_calls, -1);
13669                }
13670 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
13671                /*
13672                 * This should be the last thing to clear when we are done with
13673                 * the channel.
13674                 */
13675                ((struct sig_pri_chan *) p->sig_pvt)->allocated = 0;
13676                break;
13677             default:
13678                break;
13679             }
13680 #endif   /* defined(HAVE_PRI) */
13681          } else {
13682             snprintf(p->dialstring, sizeof(p->dialstring), "DAHDI/%s", (char *) data);
13683          }
13684          break;
13685       }
13686 #ifdef HAVE_OPENR2
13687 next:
13688 #endif
13689       if (start.backwards) {
13690          p = p->prev;
13691          if (!p)
13692             p = ifend;
13693       } else {
13694          p = p->next;
13695          if (!p)
13696             p = iflist;
13697       }
13698       /* stop when you roll to the one that we started from */
13699       if (p == exitpvt)
13700          break;
13701    }
13702    ast_mutex_unlock(&iflock);
13703    restart_monitor();
13704    if (cause && !tmp) {
13705       if (callwait || channelmatched) {
13706          *cause = AST_CAUSE_BUSY;
13707       } else if (groupmatched) {
13708          *cause = AST_CAUSE_CONGESTION;
13709       } else {
13710          /*
13711           * We did not match any channel requested.
13712           * Dialplan error requesting non-existant channel?
13713           */
13714       }
13715    }
13716 
13717    return tmp;
13718 }
13719 
13720 /*!
13721  * \internal
13722  * \brief Determine the device state for a given DAHDI device if we can.
13723  * \since 1.8
13724  *
13725  * \param data DAHDI device name after "DAHDI/".
13726  *
13727  * \retval device_state enum ast_device_state value.
13728  * \retval AST_DEVICE_UNKNOWN if we could not determine the device's state.
13729  */
13730 static int dahdi_devicestate(void *data)
13731 {
13732 #if defined(HAVE_PRI)
13733    char *device;
13734    unsigned span;
13735    int res;
13736 
13737    device = data;
13738 
13739    if (*device != 'I') {
13740       /* The request is not for an ISDN span device. */
13741       return AST_DEVICE_UNKNOWN;
13742    }
13743    res = sscanf(device, "I%30u", &span);
13744    if (res != 1 || !span || NUM_SPANS < span) {
13745       /* Bad format for ISDN span device name. */
13746       return AST_DEVICE_UNKNOWN;
13747    }
13748    device = strchr(device, '/');
13749    if (!device) {
13750       /* Bad format for ISDN span device name. */
13751       return AST_DEVICE_UNKNOWN;
13752    }
13753 
13754    /*
13755     * Since there are currently no other span devstate's defined,
13756     * it must be congestion.
13757     */
13758 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
13759    ++device;
13760    if (!strcmp(device, "congestion"))
13761 #endif   /* defined(THRESHOLD_DEVSTATE_PLACEHOLDER) */
13762    {
13763       return pris[span - 1].pri.congestion_devstate;
13764    }
13765 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
13766    else if (!strcmp(device, "threshold")) {
13767       return pris[span - 1].pri.threshold_devstate;
13768    }
13769    return AST_DEVICE_UNKNOWN;
13770 #endif   /* defined(THRESHOLD_DEVSTATE_PLACEHOLDER) */
13771 #else
13772    return AST_DEVICE_UNKNOWN;
13773 #endif   /* defined(HAVE_PRI) */
13774 }
13775 
13776 /*!
13777  * \brief Callback made when dial failed to get a channel out of dahdi_request().
13778  * \since 1.8
13779  *
13780  * \param inbound Incoming asterisk channel.
13781  * \param dest Same dial string passed to dahdi_request().
13782  * \param callback Callback into CC core to announce a busy channel available for CC.
13783  *
13784  * \details
13785  * This callback acts like a forked dial with all prongs of the fork busy.
13786  * Essentially, for each channel that could have taken the call, indicate that
13787  * it is busy.
13788  *
13789  * \retval 0 on success.
13790  * \retval -1 on error.
13791  */
13792 static int dahdi_cc_callback(struct ast_channel *inbound, const char *dest, ast_cc_callback_fn callback)
13793 {
13794    struct dahdi_pvt *p;
13795    struct dahdi_pvt *exitpvt;
13796    struct dahdi_starting_point start;
13797    int groupmatched = 0;
13798    int channelmatched = 0;
13799 
13800    ast_mutex_lock(&iflock);
13801    p = determine_starting_point(dest, &start);
13802    if (!p) {
13803       ast_mutex_unlock(&iflock);
13804       return -1;
13805    }
13806    exitpvt = p;
13807    for (;;) {
13808       if (is_group_or_channel_match(p, start.span, start.groupmatch, &groupmatched, start.channelmatch, &channelmatched)) {
13809          /* We found a potential match. call the callback */
13810          struct ast_str *device_name;
13811          char *dash;
13812          const char *monitor_type;
13813          char dialstring[AST_CHANNEL_NAME];
13814          char full_device_name[AST_CHANNEL_NAME];
13815 
13816          switch (ast_get_cc_monitor_policy(p->cc_params)) {
13817          case AST_CC_MONITOR_NEVER:
13818             break;
13819          case AST_CC_MONITOR_NATIVE:
13820          case AST_CC_MONITOR_ALWAYS:
13821          case AST_CC_MONITOR_GENERIC:
13822 #if defined(HAVE_PRI)
13823             if (dahdi_sig_pri_lib_handles(p->sig)) {
13824                /*
13825                 * ISDN is in a trunk busy condition so we need to monitor
13826                 * the span congestion device state.
13827                 */
13828                snprintf(full_device_name, sizeof(full_device_name),
13829                   "DAHDI/I%d/congestion", p->pri->span);
13830             } else
13831 #endif   /* defined(HAVE_PRI) */
13832             {
13833 #if defined(HAVE_PRI)
13834                device_name = create_channel_name(p, 1, "");
13835 #else
13836                device_name = create_channel_name(p);
13837 #endif   /* defined(HAVE_PRI) */
13838                snprintf(full_device_name, sizeof(full_device_name), "DAHDI/%s",
13839                   device_name ? ast_str_buffer(device_name) : "");
13840                ast_free(device_name);
13841                /*
13842                 * The portion after the '-' in the channel name is either a random
13843                 * number, a sequence number, or a subchannel number. None are
13844                 * necessary so strip them off.
13845                 */
13846                dash = strrchr(full_device_name, '-');
13847                if (dash) {
13848                   *dash = '\0';
13849                }
13850             }
13851             snprintf(dialstring, sizeof(dialstring), "DAHDI/%s", dest);
13852 
13853             /*
13854              * Analog can only do generic monitoring.
13855              * ISDN is in a trunk busy condition and any "device" is going
13856              * to be busy until a B channel becomes available.  The generic
13857              * monitor can do this task.
13858              */
13859             monitor_type = AST_CC_GENERIC_MONITOR_TYPE;
13860             callback(inbound,
13861 #if defined(HAVE_PRI)
13862                p->pri ? p->pri->cc_params : p->cc_params,
13863 #else
13864                p->cc_params,
13865 #endif   /* defined(HAVE_PRI) */
13866                monitor_type, full_device_name, dialstring, NULL);
13867             break;
13868          }
13869       }
13870       p = start.backwards ? p->prev : p->next;
13871       if (!p) {
13872          p = start.backwards ? ifend : iflist;
13873       }
13874       if (p == exitpvt) {
13875          break;
13876       }
13877    }
13878    ast_mutex_unlock(&iflock);
13879    return 0;
13880 }
13881 
13882 #if defined(HAVE_SS7)
13883 static void dahdi_ss7_message(struct ss7 *ss7, char *s)
13884 {
13885    int i;
13886 
13887    if (ss7) {
13888       for (i = 0; i < NUM_SPANS; i++) {
13889          if (linksets[i].ss7.ss7 == ss7) {
13890             ast_verbose("[%d] %s", i + 1, s);
13891             return;
13892          }
13893       }
13894    }
13895    ast_verbose("%s", s);
13896 }
13897 #endif   /* defined(HAVE_SS7) */
13898 
13899 #if defined(HAVE_SS7)
13900 static void dahdi_ss7_error(struct ss7 *ss7, char *s)
13901 {
13902    int i;
13903 
13904    if (ss7) {
13905       for (i = 0; i < NUM_SPANS; i++) {
13906          if (linksets[i].ss7.ss7 == ss7) {
13907             ast_log(LOG_ERROR, "[%d] %s", i + 1, s);
13908             return;
13909          }
13910       }
13911    }
13912    ast_log(LOG_ERROR, "%s", s);
13913 }
13914 #endif   /* defined(HAVE_SS7) */
13915 
13916 #if defined(HAVE_OPENR2)
13917 static void *mfcr2_monitor(void *data)
13918 {
13919    struct dahdi_mfcr2 *mfcr2 = data;
13920    /* we should be using pthread_key_create
13921       and allocate pollers dynamically.
13922       I think do_monitor() could be leaking, since it
13923       could be cancelled at any time and is not
13924       using thread keys, why?, */
13925    struct pollfd pollers[ARRAY_LEN(mfcr2->pvts)];
13926    int res = 0;
13927    int i = 0;
13928    int oldstate = 0;
13929    int quit_loop = 0;
13930    int maxsleep = 20;
13931    int was_idle = 0;
13932    int pollsize = 0;
13933    /* now that we're ready to get calls, unblock our side and
13934       get current line state */
13935    for (i = 0; i < mfcr2->numchans; i++) {
13936       openr2_chan_set_idle(mfcr2->pvts[i]->r2chan);
13937       openr2_chan_handle_cas(mfcr2->pvts[i]->r2chan);
13938    }
13939    while (1) {
13940       /* we trust here that the mfcr2 channel list will not ever change once
13941          the module is loaded */
13942       pollsize = 0;
13943       for (i = 0; i < mfcr2->numchans; i++) {
13944          pollers[i].revents = 0;
13945          pollers[i].events = 0;
13946          if (mfcr2->pvts[i]->owner) {
13947             continue;
13948          }
13949          if (!mfcr2->pvts[i]->r2chan) {
13950             ast_log(LOG_DEBUG, "Wow, no r2chan on channel %d\n", mfcr2->pvts[i]->channel);
13951             quit_loop = 1;
13952             break;
13953          }
13954          openr2_chan_enable_read(mfcr2->pvts[i]->r2chan);
13955          pollers[i].events = POLLIN | POLLPRI;
13956          pollers[i].fd = mfcr2->pvts[i]->subs[SUB_REAL].dfd;
13957          pollsize++;
13958       }
13959       if (quit_loop) {
13960          break;
13961       }
13962       if (pollsize == 0) {
13963          if (!was_idle) {
13964             ast_log(LOG_DEBUG, "Monitor thread going idle since everybody has an owner\n");
13965             was_idle = 1;
13966          }
13967          poll(NULL, 0, maxsleep);
13968          continue;
13969       }
13970       was_idle = 0;
13971       /* probably poll() is a valid cancel point, lets just be on the safe side
13972          by calling pthread_testcancel */
13973       pthread_testcancel();
13974       res = poll(pollers, mfcr2->numchans, maxsleep);
13975       pthread_testcancel();
13976       if ((res < 0) && (errno != EINTR)) {
13977          ast_log(LOG_ERROR, "going out, poll failed: %s\n", strerror(errno));
13978          break;
13979       }
13980       /* do we want to allow to cancel while processing events? */
13981       pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate);
13982       for (i = 0; i < mfcr2->numchans; i++) {
13983          if (pollers[i].revents & POLLPRI || pollers[i].revents & POLLIN) {
13984             openr2_chan_process_event(mfcr2->pvts[i]->r2chan);
13985          }
13986       }
13987       pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
13988    }
13989    ast_log(LOG_NOTICE, "Quitting MFC/R2 monitor thread\n");
13990    return 0;
13991 }
13992 #endif /* HAVE_OPENR2 */
13993 
13994 #if defined(HAVE_PRI)
13995 #ifndef PRI_RESTART
13996 #error "Upgrade your libpri"
13997 #endif
13998 static void dahdi_pri_message(struct pri *pri, char *s)
13999 {
14000    int x;
14001    int y;
14002    int dchan = -1;
14003    int span = -1;
14004    int dchancount = 0;
14005 
14006    if (pri) {
14007       for (x = 0; x < NUM_SPANS; x++) {
14008          for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
14009             if (pris[x].pri.dchans[y]) {
14010                dchancount++;
14011             }
14012 
14013             if (pris[x].pri.dchans[y] == pri) {
14014                dchan = y;
14015             }
14016          }
14017          if (dchan >= 0) {
14018             span = x;
14019             break;
14020          }
14021          dchancount = 0;
14022       }
14023       if (-1 < span) {
14024          if (1 < dchancount) {
14025             ast_verbose("[PRI Span: %d D-Channel: %d] %s", span + 1, dchan, s);
14026          } else {
14027             ast_verbose("PRI Span: %d %s", span + 1, s);
14028          }
14029       } else {
14030          ast_verbose("PRI Span: ? %s", s);
14031       }
14032    } else {
14033       ast_verbose("PRI Span: ? %s", s);
14034    }
14035 
14036    ast_mutex_lock(&pridebugfdlock);
14037 
14038    if (pridebugfd >= 0) {
14039       if (write(pridebugfd, s, strlen(s)) < 0) {
14040          ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
14041       }
14042    }
14043 
14044    ast_mutex_unlock(&pridebugfdlock);
14045 }
14046 #endif   /* defined(HAVE_PRI) */
14047 
14048 #if defined(HAVE_PRI)
14049 static void dahdi_pri_error(struct pri *pri, char *s)
14050 {
14051    int x;
14052    int y;
14053    int dchan = -1;
14054    int span = -1;
14055    int dchancount = 0;
14056 
14057    if (pri) {
14058       for (x = 0; x < NUM_SPANS; x++) {
14059          for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
14060             if (pris[x].pri.dchans[y]) {
14061                dchancount++;
14062             }
14063 
14064             if (pris[x].pri.dchans[y] == pri) {
14065                dchan = y;
14066             }
14067          }
14068          if (dchan >= 0) {
14069             span = x;
14070             break;
14071          }
14072          dchancount = 0;
14073       }
14074       if (-1 < span) {
14075          if (1 < dchancount) {
14076             ast_log(LOG_ERROR, "[PRI Span: %d D-Channel: %d] %s", span + 1, dchan, s);
14077          } else {
14078             ast_log(LOG_ERROR, "PRI Span: %d %s", span + 1, s);
14079          }
14080       } else {
14081          ast_log(LOG_ERROR, "PRI Span: ? %s", s);
14082       }
14083    } else {
14084       ast_log(LOG_ERROR, "PRI Span: ? %s", s);
14085    }
14086 
14087    ast_mutex_lock(&pridebugfdlock);
14088 
14089    if (pridebugfd >= 0) {
14090       if (write(pridebugfd, s, strlen(s)) < 0) {
14091          ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
14092       }
14093    }
14094 
14095    ast_mutex_unlock(&pridebugfdlock);
14096 }
14097 #endif   /* defined(HAVE_PRI) */
14098 
14099 #if defined(HAVE_PRI)
14100 static int prepare_pri(struct dahdi_pri *pri)
14101 {
14102    int i, res, x;
14103    struct dahdi_params p;
14104    struct dahdi_bufferinfo bi;
14105    struct dahdi_spaninfo si;
14106 
14107    pri->pri.calls = &dahdi_pri_callbacks;
14108 
14109    for (i = 0; i < SIG_PRI_NUM_DCHANS; i++) {
14110       if (!pri->dchannels[i])
14111          break;
14112       pri->pri.fds[i] = open("/dev/dahdi/channel", O_RDWR);
14113       x = pri->dchannels[i];
14114       if ((pri->pri.fds[i] < 0) || (ioctl(pri->pri.fds[i],DAHDI_SPECIFY,&x) == -1)) {
14115          ast_log(LOG_ERROR, "Unable to open D-channel %d (%s)\n", x, strerror(errno));
14116          return -1;
14117       }
14118       memset(&p, 0, sizeof(p));
14119       res = ioctl(pri->pri.fds[i], DAHDI_GET_PARAMS, &p);
14120       if (res) {
14121          dahdi_close_pri_fd(pri, i);
14122          ast_log(LOG_ERROR, "Unable to get parameters for D-channel %d (%s)\n", x, strerror(errno));
14123          return -1;
14124       }
14125       if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC)) {
14126          dahdi_close_pri_fd(pri, i);
14127          ast_log(LOG_ERROR, "D-channel %d is not in HDLC/FCS mode.\n", x);
14128          return -1;
14129       }
14130       memset(&si, 0, sizeof(si));
14131       res = ioctl(pri->pri.fds[i], DAHDI_SPANSTAT, &si);
14132       if (res) {
14133          dahdi_close_pri_fd(pri, i);
14134          ast_log(LOG_ERROR, "Unable to get span state for D-channel %d (%s)\n", x, strerror(errno));
14135       }
14136       if (!si.alarms) {
14137          pri_event_noalarm(&pri->pri, i, 1);
14138       } else {
14139          pri_event_alarm(&pri->pri, i, 1);
14140       }
14141       memset(&bi, 0, sizeof(bi));
14142       bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
14143       bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
14144       bi.numbufs = 32;
14145       bi.bufsize = 1024;
14146       if (ioctl(pri->pri.fds[i], DAHDI_SET_BUFINFO, &bi)) {
14147          ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", x, strerror(errno));
14148          dahdi_close_pri_fd(pri, i);
14149          return -1;
14150       }
14151       pri->pri.dchan_logical_span[i] = pris[p.spanno - 1].prilogicalspan;
14152    }
14153    return 0;
14154 }
14155 #endif   /* defined(HAVE_PRI) */
14156 
14157 #if defined(HAVE_PRI)
14158 static char *complete_span_helper(const char *line, const char *word, int pos, int state, int rpos)
14159 {
14160    int which, span;
14161    char *ret = NULL;
14162 
14163    if (pos != rpos)
14164       return ret;
14165 
14166    for (which = span = 0; span < NUM_SPANS; span++) {
14167       if (pris[span].pri.pri && ++which > state) {
14168          if (asprintf(&ret, "%d", span + 1) < 0) { /* user indexes start from 1 */
14169             ast_log(LOG_WARNING, "asprintf() failed: %s\n", strerror(errno));
14170          }
14171          break;
14172       }
14173    }
14174    return ret;
14175 }
14176 #endif   /* defined(HAVE_PRI) */
14177 
14178 #if defined(HAVE_PRI)
14179 static char *complete_span_4(const char *line, const char *word, int pos, int state)
14180 {
14181    return complete_span_helper(line,word,pos,state,3);
14182 }
14183 #endif   /* defined(HAVE_PRI) */
14184 
14185 #if defined(HAVE_PRI)
14186 static char *handle_pri_set_debug_file(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14187 {
14188    int myfd;
14189    switch (cmd) {
14190    case CLI_INIT:
14191       e->command = "pri set debug file";
14192       e->usage = "Usage: pri set debug file [output-file]\n"
14193          "       Sends PRI debug output to the specified output file\n";
14194       return NULL;
14195    case CLI_GENERATE:
14196       return NULL;
14197    }
14198    if (a->argc < 5)
14199       return CLI_SHOWUSAGE;
14200 
14201    if (ast_strlen_zero(a->argv[4]))
14202       return CLI_SHOWUSAGE;
14203 
14204    myfd = open(a->argv[4], O_CREAT|O_WRONLY, AST_FILE_MODE);
14205    if (myfd < 0) {
14206       ast_cli(a->fd, "Unable to open '%s' for writing\n", a->argv[4]);
14207       return CLI_SUCCESS;
14208    }
14209 
14210    ast_mutex_lock(&pridebugfdlock);
14211 
14212    if (pridebugfd >= 0)
14213       close(pridebugfd);
14214 
14215    pridebugfd = myfd;
14216    ast_copy_string(pridebugfilename,a->argv[4],sizeof(pridebugfilename));
14217    ast_mutex_unlock(&pridebugfdlock);
14218    ast_cli(a->fd, "PRI debug output will be sent to '%s'\n", a->argv[4]);
14219    return CLI_SUCCESS;
14220 }
14221 #endif   /* defined(HAVE_PRI) */
14222 
14223 #if defined(HAVE_PRI)
14224 static char *handle_pri_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14225 {
14226    int span;
14227    int x;
14228    int level = 0;
14229    switch (cmd) {
14230    case CLI_INIT:
14231       e->command = "pri set debug {on|off|0|1|2} span";
14232       e->usage =
14233          "Usage: pri set debug {<level>|on|off} span <span>\n"
14234          "       Enables debugging on a given PRI span\n";
14235       return NULL;
14236    case CLI_GENERATE:
14237       return complete_span_4(a->line, a->word, a->pos, a->n);
14238    }
14239    if (a->argc < 6) {
14240       return CLI_SHOWUSAGE;
14241    }
14242 
14243    if (!strcasecmp(a->argv[3], "on")) {
14244       level = 1;
14245    } else if (!strcasecmp(a->argv[3], "off")) {
14246       level = 0;
14247    } else {
14248       level = atoi(a->argv[3]);
14249    }
14250    span = atoi(a->argv[5]);
14251    if ((span < 1) || (span > NUM_SPANS)) {
14252       ast_cli(a->fd, "Invalid span %s.  Should be a number %d to %d\n", a->argv[5], 1, NUM_SPANS);
14253       return CLI_SUCCESS;
14254    }
14255    if (!pris[span-1].pri.pri) {
14256       ast_cli(a->fd, "No PRI running on span %d\n", span);
14257       return CLI_SUCCESS;
14258    }
14259 
14260    /* Set debug level in libpri */
14261    for (x = 0; x < SIG_PRI_NUM_DCHANS; x++) {
14262       if (pris[span - 1].pri.dchans[x]) {
14263          switch (level) {
14264          case 0:
14265             pri_set_debug(pris[span - 1].pri.dchans[x], 0);
14266             break;
14267          case 1:
14268             pri_set_debug(pris[span - 1].pri.dchans[x], SIG_PRI_DEBUG_NORMAL);
14269             break;
14270          default:
14271             pri_set_debug(pris[span - 1].pri.dchans[x], SIG_PRI_DEBUG_INTENSE);
14272             break;
14273          }
14274       }
14275    }
14276    if (level == 0) {
14277       /* Close the debugging file if it's set */
14278       ast_mutex_lock(&pridebugfdlock);
14279       if (0 <= pridebugfd) {
14280          close(pridebugfd);
14281          pridebugfd = -1;
14282          ast_cli(a->fd, "Disabled PRI debug output to file '%s'\n",
14283             pridebugfilename);
14284       }
14285       ast_mutex_unlock(&pridebugfdlock);
14286    }
14287    pris[span - 1].pri.debug = (level) ? 1 : 0;
14288    ast_cli(a->fd, "%s debugging on span %d\n", (level) ? "Enabled" : "Disabled", span);
14289    return CLI_SUCCESS;
14290 }
14291 #endif   /* defined(HAVE_PRI) */
14292 
14293 #if defined(HAVE_PRI)
14294 #if defined(HAVE_PRI_SERVICE_MESSAGES)
14295 static char *handle_pri_service_generic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a, int changestatus)
14296 {
14297    unsigned *why;
14298    int channel;
14299    int trunkgroup;
14300    int x, y, fd = a->fd;
14301    int interfaceid = 0;
14302    char *c;
14303    char db_chan_name[20], db_answer[5];
14304    struct dahdi_pvt *tmp;
14305    struct dahdi_pri *pri;
14306 
14307    if (a->argc < 5 || a->argc > 6)
14308       return CLI_SHOWUSAGE;
14309    if ((c = strchr(a->argv[4], ':'))) {
14310       if (sscanf(a->argv[4], "%30d:%30d", &trunkgroup, &channel) != 2)
14311          return CLI_SHOWUSAGE;
14312       if ((trunkgroup < 1) || (channel < 1))
14313          return CLI_SHOWUSAGE;
14314       pri = NULL;
14315       for (x=0;x<NUM_SPANS;x++) {
14316          if (pris[x].pri.trunkgroup == trunkgroup) {
14317             pri = pris + x;
14318             break;
14319          }
14320       }
14321       if (!pri) {
14322          ast_cli(fd, "No such trunk group %d\n", trunkgroup);
14323          return CLI_FAILURE;
14324       }
14325    } else
14326       channel = atoi(a->argv[4]);
14327 
14328    if (a->argc == 6)
14329       interfaceid = atoi(a->argv[5]);
14330 
14331    /* either servicing a D-Channel */
14332    for (x = 0; x < NUM_SPANS; x++) {
14333       for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
14334          if (pris[x].dchannels[y] == channel) {
14335             pri = pris + x;
14336             if (pri->pri.enable_service_message_support) {
14337                ast_mutex_lock(&pri->pri.lock);
14338                pri_maintenance_service(pri->pri.pri, interfaceid, -1, changestatus);
14339                ast_mutex_unlock(&pri->pri.lock);
14340             } else {
14341                ast_cli(fd,
14342                   "\n\tThis operation has not been enabled in chan_dahdi.conf, set 'service_message_support=yes' to use this operation.\n"
14343                   "\tNote only 4ESS, 5ESS, and NI2 switch types are supported.\n\n");
14344             }
14345             return CLI_SUCCESS;
14346          }
14347       }
14348    }
14349 
14350    /* or servicing a B-Channel */
14351    ast_mutex_lock(&iflock);
14352    for (tmp = iflist; tmp; tmp = tmp->next) {
14353       if (tmp->pri && tmp->channel == channel) {
14354          ast_mutex_unlock(&iflock);
14355          ast_mutex_lock(&tmp->pri->lock);
14356          if (!tmp->pri->enable_service_message_support) {
14357             ast_mutex_unlock(&tmp->pri->lock);
14358             ast_cli(fd,
14359                "\n\tThis operation has not been enabled in chan_dahdi.conf, set 'service_message_support=yes' to use this operation.\n"
14360                "\tNote only 4ESS, 5ESS, and NI2 switch types are supported.\n\n");
14361             return CLI_SUCCESS;
14362          }
14363          snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, tmp->span, channel);
14364          why = &((struct sig_pri_chan *) tmp->sig_pvt)->service_status;
14365          switch(changestatus) {
14366          case 0: /* enable */
14367             /* Near end wants to be in service now. */
14368             ast_db_del(db_chan_name, SRVST_DBKEY);
14369             *why &= ~SRVST_NEAREND;
14370             if (*why) {
14371                snprintf(db_answer, sizeof(db_answer), "%s:%u", SRVST_TYPE_OOS, *why);
14372                ast_db_put(db_chan_name, SRVST_DBKEY, db_answer);
14373             } else {
14374                dahdi_pri_update_span_devstate(tmp->pri);
14375             }
14376             break;
14377          /* case 1:  -- loop */
14378          case 2: /* disable */
14379             /* Near end wants to be out-of-service now. */
14380             ast_db_del(db_chan_name, SRVST_DBKEY);
14381             *why |= SRVST_NEAREND;
14382             snprintf(db_answer, sizeof(db_answer), "%s:%u", SRVST_TYPE_OOS, *why);
14383             ast_db_put(db_chan_name, SRVST_DBKEY, db_answer);
14384             dahdi_pri_update_span_devstate(tmp->pri);
14385             break;
14386          /* case 3:  -- continuity */
14387          /* case 4:  -- shutdown */
14388          default:
14389             ast_log(LOG_WARNING, "Unsupported changestatus: '%d'\n", changestatus);
14390             break;
14391          }
14392          pri_maintenance_bservice(tmp->pri->pri, tmp->sig_pvt, changestatus);
14393          ast_mutex_unlock(&tmp->pri->lock);
14394          return CLI_SUCCESS;
14395       }
14396    }
14397    ast_mutex_unlock(&iflock);
14398 
14399    ast_cli(fd, "Unable to find given channel %d, possibly not a PRI\n", channel);
14400    return CLI_FAILURE;
14401 }
14402 
14403 static char *handle_pri_service_enable_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14404 {
14405    switch (cmd) {
14406    case CLI_INIT:
14407       e->command = "pri service enable channel";
14408       e->usage =
14409          "Usage: pri service enable channel <channel> [<interface id>]\n"
14410          "       Send an AT&T / NFAS / CCS ANSI T1.607 maintenance message\n"
14411          "  to restore a channel to service, with optional interface id\n"
14412          "  as agreed upon with remote switch operator\n";
14413       return NULL;
14414    case CLI_GENERATE:
14415       return NULL;
14416    }
14417    return handle_pri_service_generic(e, cmd, a, 0);
14418 }
14419 
14420 static char *handle_pri_service_disable_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14421 {
14422    switch (cmd) {
14423    case CLI_INIT:
14424       e->command = "pri service disable channel";
14425       e->usage =
14426          "Usage: pri service disable channel <chan num> [<interface id>]\n"
14427          "  Send an AT&T / NFAS / CCS ANSI T1.607 maintenance message\n"
14428          "  to remove a channel from service, with optional interface id\n"
14429          "  as agreed upon with remote switch operator\n";
14430       return NULL;
14431    case CLI_GENERATE:
14432       return NULL;
14433    }
14434    return handle_pri_service_generic(e, cmd, a, 2);
14435 }
14436 #endif   /* defined(HAVE_PRI_SERVICE_MESSAGES) */
14437 #endif   /* defined(HAVE_PRI) */
14438 
14439 #if defined(HAVE_PRI)
14440 static char *handle_pri_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14441 {
14442    int span;
14443 
14444    switch (cmd) {
14445    case CLI_INIT:
14446       e->command = "pri show channels";
14447       e->usage =
14448          "Usage: pri show channels\n"
14449          "       Displays PRI channel information such as the current mapping\n"
14450          "       of DAHDI B channels to Asterisk channel names and which calls\n"
14451          "       are on hold or call-waiting.  Calls on hold or call-waiting\n"
14452          "       are not associated with any B channel.\n";
14453       return NULL;
14454    case CLI_GENERATE:
14455       return NULL;
14456    }
14457 
14458    if (a->argc != 3)
14459       return CLI_SHOWUSAGE;
14460 
14461    sig_pri_cli_show_channels_header(a->fd);
14462    for (span = 0; span < NUM_SPANS; ++span) {
14463       if (pris[span].pri.pri) {
14464          sig_pri_cli_show_channels(a->fd, &pris[span].pri);
14465       }
14466    }
14467    return CLI_SUCCESS;
14468 }
14469 #endif   /* defined(HAVE_PRI) */
14470 
14471 #if defined(HAVE_PRI)
14472 static char *handle_pri_show_spans(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14473 {
14474    int span;
14475 
14476    switch (cmd) {
14477    case CLI_INIT:
14478       e->command = "pri show spans";
14479       e->usage =
14480          "Usage: pri show spans\n"
14481          "       Displays PRI span information\n";
14482       return NULL;
14483    case CLI_GENERATE:
14484       return NULL;
14485    }
14486 
14487    if (a->argc != 3)
14488       return CLI_SHOWUSAGE;
14489 
14490    for (span = 0; span < NUM_SPANS; span++) {
14491       if (pris[span].pri.pri) {
14492          sig_pri_cli_show_spans(a->fd, span + 1, &pris[span].pri);
14493       }
14494    }
14495    return CLI_SUCCESS;
14496 }
14497 #endif   /* defined(HAVE_PRI) */
14498 
14499 #if defined(HAVE_PRI)
14500 static char *handle_pri_show_span(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14501 {
14502    int span;
14503 
14504    switch (cmd) {
14505    case CLI_INIT:
14506       e->command = "pri show span";
14507       e->usage =
14508          "Usage: pri show span <span>\n"
14509          "       Displays PRI Information on a given PRI span\n";
14510       return NULL;
14511    case CLI_GENERATE:
14512       return complete_span_4(a->line, a->word, a->pos, a->n);
14513    }
14514 
14515    if (a->argc < 4)
14516       return CLI_SHOWUSAGE;
14517    span = atoi(a->argv[3]);
14518    if ((span < 1) || (span > NUM_SPANS)) {
14519       ast_cli(a->fd, "Invalid span '%s'.  Should be a number from %d to %d\n", a->argv[3], 1, NUM_SPANS);
14520       return CLI_SUCCESS;
14521    }
14522    if (!pris[span-1].pri.pri) {
14523       ast_cli(a->fd, "No PRI running on span %d\n", span);
14524       return CLI_SUCCESS;
14525    }
14526 
14527    sig_pri_cli_show_span(a->fd, pris[span-1].dchannels, &pris[span-1].pri);
14528 
14529    return CLI_SUCCESS;
14530 }
14531 #endif   /* defined(HAVE_PRI) */
14532 
14533 #if defined(HAVE_PRI)
14534 static char *handle_pri_show_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14535 {
14536    int x;
14537    int span;
14538    int count=0;
14539    int debug;
14540 
14541    switch (cmd) {
14542    case CLI_INIT:
14543       e->command = "pri show debug";
14544       e->usage =
14545          "Usage: pri show debug\n"
14546          "  Show the debug state of pri spans\n";
14547       return NULL;
14548    case CLI_GENERATE:
14549       return NULL;
14550    }
14551 
14552    for (span = 0; span < NUM_SPANS; span++) {
14553       if (pris[span].pri.pri) {
14554          for (x = 0; x < SIG_PRI_NUM_DCHANS; x++) {
14555             if (pris[span].pri.dchans[x]) {
14556                debug = pri_get_debug(pris[span].pri.dchans[x]);
14557                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" );
14558                count++;
14559             }
14560          }
14561       }
14562 
14563    }
14564    ast_mutex_lock(&pridebugfdlock);
14565    if (pridebugfd >= 0)
14566       ast_cli(a->fd, "Logging PRI debug to file %s\n", pridebugfilename);
14567    ast_mutex_unlock(&pridebugfdlock);
14568 
14569    if (!count)
14570       ast_cli(a->fd, "No PRI running\n");
14571    return CLI_SUCCESS;
14572 }
14573 #endif   /* defined(HAVE_PRI) */
14574 
14575 #if defined(HAVE_PRI)
14576 static char *handle_pri_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14577 {
14578    switch (cmd) {
14579    case CLI_INIT:
14580       e->command = "pri show version";
14581       e->usage =
14582          "Usage: pri show version\n"
14583          "Show libpri version information\n";
14584       return NULL;
14585    case CLI_GENERATE:
14586       return NULL;
14587    }
14588 
14589    ast_cli(a->fd, "libpri version: %s\n", pri_get_version());
14590 
14591    return CLI_SUCCESS;
14592 }
14593 #endif   /* defined(HAVE_PRI) */
14594 
14595 #if defined(HAVE_PRI)
14596 static struct ast_cli_entry dahdi_pri_cli[] = {
14597    AST_CLI_DEFINE(handle_pri_debug, "Enables PRI debugging on a span"),
14598 #if defined(HAVE_PRI_SERVICE_MESSAGES)
14599    AST_CLI_DEFINE(handle_pri_service_enable_channel, "Return a channel to service"),
14600    AST_CLI_DEFINE(handle_pri_service_disable_channel, "Remove a channel from service"),
14601 #endif   /* defined(HAVE_PRI_SERVICE_MESSAGES) */
14602    AST_CLI_DEFINE(handle_pri_show_channels, "Displays PRI channel information"),
14603    AST_CLI_DEFINE(handle_pri_show_spans, "Displays PRI span information"),
14604    AST_CLI_DEFINE(handle_pri_show_span, "Displays PRI span information"),
14605    AST_CLI_DEFINE(handle_pri_show_debug, "Displays current PRI debug settings"),
14606    AST_CLI_DEFINE(handle_pri_set_debug_file, "Sends PRI debug output to the specified file"),
14607    AST_CLI_DEFINE(handle_pri_version, "Displays libpri version"),
14608 };
14609 #endif   /* defined(HAVE_PRI) */
14610 
14611 #ifdef HAVE_OPENR2
14612 
14613 static char *handle_mfcr2_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14614 {
14615    switch (cmd) {
14616    case CLI_INIT:
14617       e->command = "mfcr2 show version";
14618       e->usage =
14619          "Usage: mfcr2 show version\n"
14620          "       Shows the version of the OpenR2 library being used.\n";
14621       return NULL;
14622    case CLI_GENERATE:
14623       return NULL;
14624    }
14625    ast_cli(a->fd, "OpenR2 version: %s, revision: %s\n", openr2_get_version(), openr2_get_revision());
14626    return CLI_SUCCESS;
14627 }
14628 
14629 static char *handle_mfcr2_show_variants(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14630 {
14631 #define FORMAT "%4s %40s\n"
14632    int i = 0;
14633    int numvariants = 0;
14634    const openr2_variant_entry_t *variants;
14635    switch (cmd) {
14636    case CLI_INIT:
14637       e->command = "mfcr2 show variants";
14638       e->usage =
14639          "Usage: mfcr2 show variants\n"
14640          "       Shows the list of MFC/R2 variants supported.\n";
14641       return NULL;
14642    case CLI_GENERATE:
14643       return NULL;
14644    }
14645    if (!(variants = openr2_proto_get_variant_list(&numvariants))) {
14646       ast_cli(a->fd, "Failed to get list of variants.\n");
14647       return CLI_FAILURE;
14648    }
14649    ast_cli(a->fd, FORMAT, "Variant Code", "Country");
14650    for (i = 0; i < numvariants; i++) {
14651       ast_cli(a->fd, FORMAT, variants[i].name, variants[i].country);
14652    }
14653    return CLI_SUCCESS;
14654 #undef FORMAT
14655 }
14656 
14657 static char *handle_mfcr2_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14658 {
14659 #define FORMAT "%4s %-7.7s %-7.7s %-8.8s %-9.9s %-16.16s %-8.8s %-8.8s\n"
14660    int filtertype = 0;
14661    int targetnum = 0;
14662    char channo[5];
14663    char anino[5];
14664    char dnisno[5];
14665    struct dahdi_pvt *p;
14666    openr2_context_t *r2context;
14667    openr2_variant_t r2variant;
14668    switch (cmd) {
14669    case CLI_INIT:
14670       e->command = "mfcr2 show channels [group|context]";
14671       e->usage =
14672          "Usage: mfcr2 show channels [group <group> | context <context>]\n"
14673          "       Shows the DAHDI channels configured with MFC/R2 signaling.\n";
14674       return NULL;
14675    case CLI_GENERATE:
14676       return NULL;
14677    }
14678    if (!((a->argc == 3) || (a->argc == 5))) {
14679       return CLI_SHOWUSAGE;
14680    }
14681    if (a->argc == 5) {
14682       if (!strcasecmp(a->argv[3], "group")) {
14683          targetnum = atoi(a->argv[4]);
14684          if ((targetnum < 0) || (targetnum > 63))
14685             return CLI_SHOWUSAGE;
14686          targetnum = 1 << targetnum;
14687          filtertype = 1;
14688       } else if (!strcasecmp(a->argv[3], "context")) {
14689          filtertype = 2;
14690       } else {
14691          return CLI_SHOWUSAGE;
14692       }
14693    }
14694    ast_cli(a->fd, FORMAT, "Chan", "Variant", "Max ANI", "Max DNIS", "ANI First", "Immediate Accept", "Tx CAS", "Rx CAS");
14695    ast_mutex_lock(&iflock);
14696    for (p = iflist; p; p = p->next) {
14697       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14698          continue;
14699       }
14700       if (filtertype) {
14701          switch(filtertype) {
14702          case 1: /* mfcr2 show channels group <group> */
14703             if (p->group != targetnum) {
14704                continue;
14705             }
14706             break;
14707          case 2: /* mfcr2 show channels context <context> */
14708             if (strcasecmp(p->context, a->argv[4])) {
14709                continue;
14710             }
14711             break;
14712          default:
14713             ;
14714          }
14715       }
14716       r2context = openr2_chan_get_context(p->r2chan);
14717       r2variant = openr2_context_get_variant(r2context);
14718       snprintf(channo, sizeof(channo), "%d", p->channel);
14719       snprintf(anino, sizeof(anino), "%d", openr2_context_get_max_ani(r2context));
14720       snprintf(dnisno, sizeof(dnisno), "%d", openr2_context_get_max_dnis(r2context));
14721       ast_cli(a->fd, FORMAT, channo, openr2_proto_get_variant_string(r2variant),
14722             anino, dnisno, openr2_context_get_ani_first(r2context) ? "Yes" : "No",
14723             openr2_context_get_immediate_accept(r2context) ? "Yes" : "No",
14724             openr2_chan_get_tx_cas_string(p->r2chan), openr2_chan_get_rx_cas_string(p->r2chan));
14725    }
14726    ast_mutex_unlock(&iflock);
14727    return CLI_SUCCESS;
14728 #undef FORMAT
14729 }
14730 
14731 static char *handle_mfcr2_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14732 {
14733    struct dahdi_pvt *p = NULL;
14734    int channo = 0;
14735    char *toklevel = NULL;
14736    char *saveptr = NULL;
14737    char *logval = NULL;
14738    openr2_log_level_t loglevel = OR2_LOG_NOTHING;
14739    openr2_log_level_t tmplevel = OR2_LOG_NOTHING;
14740    switch (cmd) {
14741    case CLI_INIT:
14742       e->command = "mfcr2 set debug";
14743       e->usage =
14744          "Usage: mfcr2 set debug <loglevel> <channel>\n"
14745          "       Set a new logging level for the specified channel.\n"
14746          "       If no channel is specified the logging level will be applied to all channels.\n";
14747       return NULL;
14748    case CLI_GENERATE:
14749       return NULL;
14750    }
14751    if (a->argc < 4) {
14752       return CLI_SHOWUSAGE;
14753    }
14754    channo = (a->argc == 5) ? atoi(a->argv[4]) : -1;
14755    logval = ast_strdupa(a->argv[3]);
14756    toklevel = strtok_r(logval, ",", &saveptr);
14757    if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
14758       ast_cli(a->fd, "Invalid MFC/R2 logging level '%s'.\n", a->argv[3]);
14759       return CLI_FAILURE;
14760    } else if (OR2_LOG_NOTHING == tmplevel) {
14761       loglevel = tmplevel;
14762    } else {
14763       loglevel |= tmplevel;
14764       while ((toklevel = strtok_r(NULL, ",", &saveptr))) {
14765          if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
14766             ast_cli(a->fd, "Ignoring invalid logging level: '%s'.\n", toklevel);
14767             continue;
14768          }
14769          loglevel |= tmplevel;
14770       }
14771    }
14772    ast_mutex_lock(&iflock);
14773    for (p = iflist; p; p = p->next) {
14774       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14775          continue;
14776       }
14777       if ((channo != -1) && (p->channel != channo )) {
14778          continue;
14779       }
14780       openr2_chan_set_log_level(p->r2chan, loglevel);
14781       if (channo != -1) {
14782          ast_cli(a->fd, "MFC/R2 debugging set to '%s' for channel %d.\n", a->argv[3], p->channel);
14783          break;
14784       }
14785    }
14786    if ((channo != -1) && !p) {
14787       ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
14788    }
14789    if (channo == -1) {
14790       ast_cli(a->fd, "MFC/R2 debugging set to '%s' for all channels.\n", a->argv[3]);
14791    }
14792    ast_mutex_unlock(&iflock);
14793    return CLI_SUCCESS;
14794 }
14795 
14796 static char *handle_mfcr2_call_files(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14797 {
14798    struct dahdi_pvt *p = NULL;
14799    int channo = 0;
14800    switch (cmd) {
14801    case CLI_INIT:
14802       e->command = "mfcr2 call files [on|off]";
14803       e->usage =
14804          "Usage: mfcr2 call files [on|off] <channel>\n"
14805          "       Enable call files creation on the specified channel.\n"
14806          "       If no channel is specified call files creation policy will be applied to all channels.\n";
14807       return NULL;
14808    case CLI_GENERATE:
14809       return NULL;
14810    }
14811    if (a->argc < 4) {
14812       return CLI_SHOWUSAGE;
14813    }
14814    channo = (a->argc == 5) ? atoi(a->argv[4]) : -1;
14815    ast_mutex_lock(&iflock);
14816    for (p = iflist; p; p = p->next) {
14817       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14818          continue;
14819       }
14820       if ((channo != -1) && (p->channel != channo )) {
14821          continue;
14822       }
14823       if (ast_true(a->argv[3])) {
14824          openr2_chan_enable_call_files(p->r2chan);
14825       } else {
14826          openr2_chan_disable_call_files(p->r2chan);
14827       }
14828       if (channo != -1) {
14829          if (ast_true(a->argv[3])) {
14830             ast_cli(a->fd, "MFC/R2 call files enabled for channel %d.\n", p->channel);
14831          } else {
14832             ast_cli(a->fd, "MFC/R2 call files disabled for channel %d.\n", p->channel);
14833          }
14834          break;
14835       }
14836    }
14837    if ((channo != -1) && !p) {
14838       ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
14839    }
14840    if (channo == -1) {
14841       if (ast_true(a->argv[3])) {
14842          ast_cli(a->fd, "MFC/R2 Call files enabled for all channels.\n");
14843       } else {
14844          ast_cli(a->fd, "MFC/R2 Call files disabled for all channels.\n");
14845       }
14846    }
14847    ast_mutex_unlock(&iflock);
14848    return CLI_SUCCESS;
14849 }
14850 
14851 static char *handle_mfcr2_set_idle(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14852 {
14853    struct dahdi_pvt *p = NULL;
14854    int channo = 0;
14855    switch (cmd) {
14856    case CLI_INIT:
14857       e->command = "mfcr2 set idle";
14858       e->usage =
14859          "Usage: mfcr2 set idle <channel>\n"
14860          "       DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n"
14861          "       Force the given channel into IDLE state.\n"
14862          "       If no channel is specified, all channels will be set to IDLE.\n";
14863       return NULL;
14864    case CLI_GENERATE:
14865       return NULL;
14866    }
14867    channo = (a->argc == 4) ? atoi(a->argv[3]) : -1;
14868    ast_mutex_lock(&iflock);
14869    for (p = iflist; p; p = p->next) {
14870       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14871          continue;
14872       }
14873       if ((channo != -1) && (p->channel != channo )) {
14874          continue;
14875       }
14876       openr2_chan_set_idle(p->r2chan);
14877       ast_mutex_lock(&p->lock);
14878       p->locallyblocked = 0;
14879       p->mfcr2call = 0;
14880       ast_mutex_unlock(&p->lock);
14881       if (channo != -1) {
14882          break;
14883       }
14884    }
14885    if ((channo != -1) && !p) {
14886       ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
14887    }
14888    ast_mutex_unlock(&iflock);
14889    return CLI_SUCCESS;
14890 }
14891 
14892 static char *handle_mfcr2_set_blocked(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14893 {
14894    struct dahdi_pvt *p = NULL;
14895    int channo = 0;
14896    switch (cmd) {
14897    case CLI_INIT:
14898       e->command = "mfcr2 set blocked";
14899       e->usage =
14900          "Usage: mfcr2 set blocked <channel>\n"
14901          "       DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n"
14902          "       Force the given channel into BLOCKED state.\n"
14903          "       If no channel is specified, all channels will be set to BLOCKED.\n";
14904       return NULL;
14905    case CLI_GENERATE:
14906       return NULL;
14907    }
14908    channo = (a->argc == 4) ? atoi(a->argv[3]) : -1;
14909    ast_mutex_lock(&iflock);
14910    for (p = iflist; p; p = p->next) {
14911       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14912          continue;
14913       }
14914       if ((channo != -1) && (p->channel != channo )) {
14915          continue;
14916       }
14917       openr2_chan_set_blocked(p->r2chan);
14918       ast_mutex_lock(&p->lock);
14919       p->locallyblocked = 1;
14920       ast_mutex_unlock(&p->lock);
14921       if (channo != -1) {
14922          break;
14923       }
14924    }
14925    if ((channo != -1) && !p) {
14926       ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
14927    }
14928    ast_mutex_unlock(&iflock);
14929    return CLI_SUCCESS;
14930 }
14931 
14932 static struct ast_cli_entry dahdi_mfcr2_cli[] = {
14933    AST_CLI_DEFINE(handle_mfcr2_version, "Show OpenR2 library version"),
14934    AST_CLI_DEFINE(handle_mfcr2_show_variants, "Show supported MFC/R2 variants"),
14935    AST_CLI_DEFINE(handle_mfcr2_show_channels, "Show MFC/R2 channels"),
14936    AST_CLI_DEFINE(handle_mfcr2_set_debug, "Set MFC/R2 channel logging level"),
14937    AST_CLI_DEFINE(handle_mfcr2_call_files, "Enable/Disable MFC/R2 call files"),
14938    AST_CLI_DEFINE(handle_mfcr2_set_idle, "Reset MFC/R2 channel forcing it to IDLE"),
14939    AST_CLI_DEFINE(handle_mfcr2_set_blocked, "Reset MFC/R2 channel forcing it to BLOCKED"),
14940 };
14941 
14942 #endif /* HAVE_OPENR2 */
14943 
14944 static char *dahdi_destroy_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14945 {
14946    int channel;
14947    int ret;
14948    switch (cmd) {
14949    case CLI_INIT:
14950       e->command = "dahdi destroy channel";
14951       e->usage =
14952          "Usage: dahdi destroy channel <chan num>\n"
14953          "  DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.  Immediately removes a given channel, whether it is in use or not\n";
14954       return NULL;
14955    case CLI_GENERATE:
14956       return NULL;
14957    }
14958    if (a->argc != 4)
14959       return CLI_SHOWUSAGE;
14960 
14961    channel = atoi(a->argv[3]);
14962    ret = dahdi_destroy_channel_bynum(channel);
14963    return ( RESULT_SUCCESS == ret ) ? CLI_SUCCESS : CLI_FAILURE;
14964 }
14965 
14966 static void dahdi_softhangup_all(void)
14967 {
14968    struct dahdi_pvt *p;
14969 retry:
14970    ast_mutex_lock(&iflock);
14971    for (p = iflist; p; p = p->next) {
14972       ast_mutex_lock(&p->lock);
14973       if (p->owner && !p->restartpending) {
14974          if (ast_channel_trylock(p->owner)) {
14975             if (option_debug > 2)
14976                ast_verbose("Avoiding deadlock\n");
14977             /* Avoid deadlock since you're not supposed to lock iflock or pvt before a channel */
14978             ast_mutex_unlock(&p->lock);
14979             ast_mutex_unlock(&iflock);
14980             goto retry;
14981          }
14982          if (option_debug > 2)
14983             ast_verbose("Softhanging up on %s\n", p->owner->name);
14984          ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_EXPLICIT);
14985          p->restartpending = 1;
14986          num_restart_pending++;
14987          ast_channel_unlock(p->owner);
14988       }
14989       ast_mutex_unlock(&p->lock);
14990    }
14991    ast_mutex_unlock(&iflock);
14992 }
14993 
14994 static int setup_dahdi(int reload);
14995 static int dahdi_restart(void)
14996 {
14997 #if defined(HAVE_PRI) || defined(HAVE_SS7)
14998    int i, j;
14999 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
15000    int cancel_code;
15001    struct dahdi_pvt *p;
15002 
15003    ast_mutex_lock(&restart_lock);
15004    ast_verb(1, "Destroying channels and reloading DAHDI configuration.\n");
15005    dahdi_softhangup_all();
15006    ast_verb(4, "Initial softhangup of all DAHDI channels complete.\n");
15007 #ifdef HAVE_OPENR2
15008    dahdi_r2_destroy_links();
15009 #endif
15010 
15011 #if defined(HAVE_PRI)
15012    for (i = 0; i < NUM_SPANS; i++) {
15013       if (pris[i].pri.master && (pris[i].pri.master != AST_PTHREADT_NULL)) {
15014          cancel_code = pthread_cancel(pris[i].pri.master);
15015          pthread_kill(pris[i].pri.master, SIGURG);
15016          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);
15017          pthread_join(pris[i].pri.master, NULL);
15018          ast_debug(4, "Joined thread of span %d\n", i);
15019       }
15020    }
15021 #endif
15022 
15023 #if defined(HAVE_SS7)
15024    for (i = 0; i < NUM_SPANS; i++) {
15025       if (linksets[i].ss7.master && (linksets[i].ss7.master != AST_PTHREADT_NULL)) {
15026          cancel_code = pthread_cancel(linksets[i].ss7.master);
15027          pthread_kill(linksets[i].ss7.master, SIGURG);
15028          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);
15029          pthread_join(linksets[i].ss7.master, NULL);
15030          ast_debug(4, "Joined thread of span %d\n", i);
15031       }
15032    }
15033 #endif   /* defined(HAVE_SS7) */
15034 
15035    ast_mutex_lock(&monlock);
15036    if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
15037       cancel_code = pthread_cancel(monitor_thread);
15038       pthread_kill(monitor_thread, SIGURG);
15039       ast_debug(4, "Waiting to join monitor thread with pid=%p, cancel_code=%d\n", (void *) monitor_thread, cancel_code);
15040       pthread_join(monitor_thread, NULL);
15041       ast_debug(4, "Joined monitor thread\n");
15042    }
15043    monitor_thread = AST_PTHREADT_NULL; /* prepare to restart thread in setup_dahdi once channels are reconfigured */
15044 
15045    ast_mutex_lock(&ss_thread_lock);
15046    while (ss_thread_count > 0) { /* let ss_threads finish and run dahdi_hangup before dahvi_pvts are destroyed */
15047       int x = DAHDI_FLASH;
15048       ast_debug(3, "Waiting on %d analog_ss_thread(s) to finish\n", ss_thread_count);
15049 
15050       ast_mutex_lock(&iflock);
15051       for (p = iflist; p; p = p->next) {
15052          if (p->owner) {
15053             /* important to create an event for dahdi_wait_event to register so that all analog_ss_threads terminate */
15054             ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
15055          }
15056       }
15057       ast_mutex_unlock(&iflock);
15058       ast_cond_wait(&ss_thread_complete, &ss_thread_lock);
15059    }
15060 
15061    /* ensure any created channels before monitor threads were stopped are hungup */
15062    dahdi_softhangup_all();
15063    ast_verb(4, "Final softhangup of all DAHDI channels complete.\n");
15064    destroy_all_channels();
15065    ast_debug(1, "Channels destroyed. Now re-reading config. %d active channels remaining.\n", ast_active_channels());
15066 
15067    ast_mutex_unlock(&monlock);
15068 
15069 #ifdef HAVE_PRI
15070    for (i = 0; i < NUM_SPANS; i++) {
15071       for (j = 0; j < SIG_PRI_NUM_DCHANS; j++)
15072          dahdi_close_pri_fd(&(pris[i]), j);
15073    }
15074 
15075    memset(pris, 0, sizeof(pris));
15076    for (i = 0; i < NUM_SPANS; i++) {
15077       sig_pri_init_pri(&pris[i].pri);
15078    }
15079    pri_set_error(dahdi_pri_error);
15080    pri_set_message(dahdi_pri_message);
15081 #endif
15082 #if defined(HAVE_SS7)
15083    for (i = 0; i < NUM_SPANS; i++) {
15084       for (j = 0; j < SIG_SS7_NUM_DCHANS; j++)
15085          dahdi_close_ss7_fd(&(linksets[i]), j);
15086    }
15087 
15088    memset(linksets, 0, sizeof(linksets));
15089    for (i = 0; i < NUM_SPANS; i++) {
15090       sig_ss7_init_linkset(&linksets[i].ss7);
15091    }
15092    ss7_set_error(dahdi_ss7_error);
15093    ss7_set_message(dahdi_ss7_message);
15094 #endif   /* defined(HAVE_SS7) */
15095 
15096    if (setup_dahdi(2) != 0) {
15097       ast_log(LOG_WARNING, "Reload channels from dahdi config failed!\n");
15098       ast_mutex_unlock(&ss_thread_lock);
15099       return 1;
15100    }
15101    ast_mutex_unlock(&ss_thread_lock);
15102    ast_mutex_unlock(&restart_lock);
15103    return 0;
15104 }
15105 
15106 static char *dahdi_restart_cmd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15107 {
15108    switch (cmd) {
15109    case CLI_INIT:
15110       e->command = "dahdi restart";
15111       e->usage =
15112          "Usage: dahdi restart\n"
15113          "  Restarts the DAHDI channels: destroys them all and then\n"
15114          "  re-reads them from chan_dahdi.conf.\n"
15115          "  Note that this will STOP any running CALL on DAHDI channels.\n"
15116          "";
15117       return NULL;
15118    case CLI_GENERATE:
15119       return NULL;
15120    }
15121    if (a->argc != 2)
15122       return CLI_SHOWUSAGE;
15123 
15124    if (dahdi_restart() != 0)
15125       return CLI_FAILURE;
15126    return CLI_SUCCESS;
15127 }
15128 
15129 static int action_dahdirestart(struct mansession *s, const struct message *m)
15130 {
15131    if (dahdi_restart() != 0) {
15132       astman_send_error(s, m, "Failed rereading DAHDI configuration");
15133       return 1;
15134    }
15135    astman_send_ack(s, m, "DAHDIRestart: Success");
15136    return 0;
15137 }
15138 
15139 static char *dahdi_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15140 {
15141 #define FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
15142 #define FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
15143    unsigned int targetnum = 0;
15144    int filtertype = 0;
15145    struct dahdi_pvt *tmp = NULL;
15146    char tmps[20] = "";
15147    char statestr[20] = "";
15148    char blockstr[20] = "";
15149 
15150    switch (cmd) {
15151    case CLI_INIT:
15152       e->command = "dahdi show channels [group|context]";
15153       e->usage =
15154          "Usage: dahdi show channels [ group <group> | context <context> ]\n"
15155          "  Shows a list of available channels with optional filtering\n"
15156          "  <group> must be a number between 0 and 63\n";
15157       return NULL;
15158    case CLI_GENERATE:
15159       return NULL;
15160    }
15161 
15162    /* syntax: dahdi show channels [ group <group> | context <context> ] */
15163 
15164    if (!((a->argc == 3) || (a->argc == 5)))
15165       return CLI_SHOWUSAGE;
15166 
15167    if (a->argc == 5) {
15168       if (!strcasecmp(a->argv[3], "group")) {
15169          targetnum = atoi(a->argv[4]);
15170          if ((targetnum < 0) || (targetnum > 63))
15171             return CLI_SHOWUSAGE;
15172          targetnum = 1 << targetnum;
15173          filtertype = 1;
15174       } else if (!strcasecmp(a->argv[3], "context")) {
15175          filtertype = 2;
15176       }
15177    }
15178 
15179    ast_cli(a->fd, FORMAT2, "Chan", "Extension", "Context", "Language", "MOH Interpret", "Blocked", "State");
15180    ast_mutex_lock(&iflock);
15181    for (tmp = iflist; tmp; tmp = tmp->next) {
15182       if (filtertype) {
15183          switch(filtertype) {
15184          case 1: /* dahdi show channels group <group> */
15185             if (!(tmp->group & targetnum)) {
15186                continue;
15187             }
15188             break;
15189          case 2: /* dahdi show channels context <context> */
15190             if (strcasecmp(tmp->context, a->argv[4])) {
15191                continue;
15192             }
15193             break;
15194          default:
15195             break;
15196          }
15197       }
15198       if (tmp->channel > 0) {
15199          snprintf(tmps, sizeof(tmps), "%d", tmp->channel);
15200       } else
15201          ast_copy_string(tmps, "pseudo", sizeof(tmps));
15202 
15203       if (tmp->locallyblocked)
15204          blockstr[0] = 'L';
15205       else
15206          blockstr[0] = ' ';
15207 
15208       if (tmp->remotelyblocked)
15209          blockstr[1] = 'R';
15210       else
15211          blockstr[1] = ' ';
15212 
15213       blockstr[2] = '\0';
15214 
15215       snprintf(statestr, sizeof(statestr), "%s", "In Service");
15216 
15217       ast_cli(a->fd, FORMAT, tmps, tmp->exten, tmp->context, tmp->language, tmp->mohinterpret, blockstr, statestr);
15218    }
15219    ast_mutex_unlock(&iflock);
15220    return CLI_SUCCESS;
15221 #undef FORMAT
15222 #undef FORMAT2
15223 }
15224 
15225 static char *dahdi_show_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15226 {
15227    int channel;
15228    struct dahdi_pvt *tmp = NULL;
15229    struct dahdi_confinfo ci;
15230    struct dahdi_params ps;
15231    int x;
15232 
15233    switch (cmd) {
15234    case CLI_INIT:
15235       e->command = "dahdi show channel";
15236       e->usage =
15237          "Usage: dahdi show channel <chan num>\n"
15238          "  Detailed information about a given channel\n";
15239       return NULL;
15240    case CLI_GENERATE:
15241       return NULL;
15242    }
15243 
15244    if (a->argc != 4)
15245       return CLI_SHOWUSAGE;
15246 
15247    channel = atoi(a->argv[3]);
15248 
15249    ast_mutex_lock(&iflock);
15250    for (tmp = iflist; tmp; tmp = tmp->next) {
15251       if (tmp->channel == channel) {
15252          ast_cli(a->fd, "Channel: %d\n", tmp->channel);
15253          ast_cli(a->fd, "File Descriptor: %d\n", tmp->subs[SUB_REAL].dfd);
15254          ast_cli(a->fd, "Span: %d\n", tmp->span);
15255          ast_cli(a->fd, "Extension: %s\n", tmp->exten);
15256          ast_cli(a->fd, "Dialing: %s\n", tmp->dialing ? "yes" : "no");
15257          ast_cli(a->fd, "Context: %s\n", tmp->context);
15258          ast_cli(a->fd, "Caller ID: %s\n", tmp->cid_num);
15259          ast_cli(a->fd, "Calling TON: %d\n", tmp->cid_ton);
15260 #if defined(HAVE_PRI)
15261 #if defined(HAVE_PRI_SUBADDR)
15262          ast_cli(a->fd, "Caller ID subaddress: %s\n", tmp->cid_subaddr);
15263 #endif   /* defined(HAVE_PRI_SUBADDR) */
15264 #endif   /* defined(HAVE_PRI) */
15265          ast_cli(a->fd, "Caller ID name: %s\n", tmp->cid_name);
15266          ast_cli(a->fd, "Mailbox: %s\n", S_OR(tmp->mailbox, "none"));
15267          if (tmp->vars) {
15268             struct ast_variable *v;
15269             ast_cli(a->fd, "Variables:\n");
15270             for (v = tmp->vars ; v ; v = v->next)
15271                ast_cli(a->fd, "       %s = %s\n", v->name, v->value);
15272          }
15273          ast_cli(a->fd, "Destroy: %d\n", tmp->destroy);
15274          ast_cli(a->fd, "InAlarm: %d\n", tmp->inalarm);
15275          ast_cli(a->fd, "Signalling Type: %s\n", sig2str(tmp->sig));
15276          ast_cli(a->fd, "Radio: %d\n", tmp->radio);
15277          ast_cli(a->fd, "Owner: %s\n", tmp->owner ? tmp->owner->name : "<None>");
15278          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)" : "");
15279          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)" : "");
15280          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)" : "");
15281          ast_cli(a->fd, "Confno: %d\n", tmp->confno);
15282          ast_cli(a->fd, "Propagated Conference: %d\n", tmp->propconfno);
15283          ast_cli(a->fd, "Real in conference: %d\n", tmp->inconference);
15284          ast_cli(a->fd, "DSP: %s\n", tmp->dsp ? "yes" : "no");
15285          ast_cli(a->fd, "Busy Detection: %s\n", tmp->busydetect ? "yes" : "no");
15286          if (tmp->busydetect) {
15287 #if defined(BUSYDETECT_TONEONLY)
15288             ast_cli(a->fd, "    Busy Detector Helper: BUSYDETECT_TONEONLY\n");
15289 #elif defined(BUSYDETECT_COMPARE_TONE_AND_SILENCE)
15290             ast_cli(a->fd, "    Busy Detector Helper: BUSYDETECT_COMPARE_TONE_AND_SILENCE\n");
15291 #endif
15292 #ifdef BUSYDETECT_DEBUG
15293             ast_cli(a->fd, "    Busy Detector Debug: Enabled\n");
15294 #endif
15295             ast_cli(a->fd, "    Busy Count: %d\n", tmp->busycount);
15296             ast_cli(a->fd, "    Busy Pattern: %d,%d\n", tmp->busy_tonelength, tmp->busy_quietlength);
15297          }
15298          ast_cli(a->fd, "TDD: %s\n", tmp->tdd ? "yes" : "no");
15299          ast_cli(a->fd, "Relax DTMF: %s\n", tmp->dtmfrelax ? "yes" : "no");
15300          ast_cli(a->fd, "Dialing/CallwaitCAS: %d/%d\n", tmp->dialing, tmp->callwaitcas);
15301          ast_cli(a->fd, "Default law: %s\n", tmp->law_default == DAHDI_LAW_MULAW ? "ulaw" : tmp->law_default == DAHDI_LAW_ALAW ? "alaw" : "unknown");
15302          ast_cli(a->fd, "Fax Handled: %s\n", tmp->faxhandled ? "yes" : "no");
15303          ast_cli(a->fd, "Pulse phone: %s\n", tmp->pulsedial ? "yes" : "no");
15304          ast_cli(a->fd, "Gains (RX/TX): %.2f/%.2f\n", tmp->rxgain, tmp->txgain);
15305          ast_cli(a->fd, "Dynamic Range Compression (RX/TX): %.2f/%.2f\n", tmp->rxdrc, tmp->txdrc);
15306          ast_cli(a->fd, "DND: %s\n", dahdi_dnd(tmp, -1) ? "yes" : "no");
15307          ast_cli(a->fd, "Echo Cancellation:\n");
15308 
15309          if (tmp->echocancel.head.tap_length) {
15310             ast_cli(a->fd, "\t%d taps\n", tmp->echocancel.head.tap_length);
15311             for (x = 0; x < tmp->echocancel.head.param_count; x++) {
15312                ast_cli(a->fd, "\t\t%s: %ud\n", tmp->echocancel.params[x].name, tmp->echocancel.params[x].value);
15313             }
15314             ast_cli(a->fd, "\t%scurrently %s\n", tmp->echocanbridged ? "" : "(unless TDM bridged) ", tmp->echocanon ? "ON" : "OFF");
15315          } else {
15316             ast_cli(a->fd, "\tnone\n");
15317          }
15318          ast_cli(a->fd, "Wait for dialtone: %dms\n", tmp->waitfordialtone);
15319          if (tmp->master)
15320             ast_cli(a->fd, "Master Channel: %d\n", tmp->master->channel);
15321          for (x = 0; x < MAX_SLAVES; x++) {
15322             if (tmp->slaves[x])
15323                ast_cli(a->fd, "Slave Channel: %d\n", tmp->slaves[x]->channel);
15324          }
15325 #ifdef HAVE_OPENR2
15326          if (tmp->mfcr2) {
15327             char calldir[OR2_MAX_PATH];
15328             openr2_context_t *r2context = openr2_chan_get_context(tmp->r2chan);
15329             openr2_variant_t r2variant = openr2_context_get_variant(r2context);
15330             ast_cli(a->fd, "MFC/R2 MF State: %s\n", openr2_chan_get_mf_state_string(tmp->r2chan));
15331             ast_cli(a->fd, "MFC/R2 MF Group: %s\n", openr2_chan_get_mf_group_string(tmp->r2chan));
15332             ast_cli(a->fd, "MFC/R2 State: %s\n", openr2_chan_get_r2_state_string(tmp->r2chan));
15333             ast_cli(a->fd, "MFC/R2 Call State: %s\n", openr2_chan_get_call_state_string(tmp->r2chan));
15334             ast_cli(a->fd, "MFC/R2 Call Files Enabled: %s\n", openr2_chan_get_call_files_enabled(tmp->r2chan) ? "Yes" : "No");
15335             ast_cli(a->fd, "MFC/R2 Variant: %s\n", openr2_proto_get_variant_string(r2variant));
15336             ast_cli(a->fd, "MFC/R2 Max ANI: %d\n", openr2_context_get_max_ani(r2context));
15337             ast_cli(a->fd, "MFC/R2 Max DNIS: %d\n", openr2_context_get_max_dnis(r2context));
15338             ast_cli(a->fd, "MFC/R2 Get ANI First: %s\n", openr2_context_get_ani_first(r2context) ? "Yes" : "No");
15339 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
15340             ast_cli(a->fd, "MFC/R2 Skip Category Request: %s\n", openr2_context_get_skip_category_request(r2context) ? "Yes" : "No");
15341 #endif
15342             ast_cli(a->fd, "MFC/R2 Immediate Accept: %s\n", openr2_context_get_immediate_accept(r2context) ? "Yes" : "No");
15343             ast_cli(a->fd, "MFC/R2 Accept on Offer: %s\n", tmp->mfcr2_accept_on_offer ? "Yes" : "No");
15344             ast_cli(a->fd, "MFC/R2 Charge Calls: %s\n", tmp->mfcr2_charge_calls ? "Yes" : "No");
15345             ast_cli(a->fd, "MFC/R2 Allow Collect Calls: %s\n", tmp->mfcr2_allow_collect_calls ? "Yes" : "No");
15346             ast_cli(a->fd, "MFC/R2 Forced Release: %s\n", tmp->mfcr2_forced_release ? "Yes" : "No");
15347             ast_cli(a->fd, "MFC/R2 MF Back Timeout: %dms\n", openr2_context_get_mf_back_timeout(r2context));
15348             ast_cli(a->fd, "MFC/R2 R2 Metering Pulse Timeout: %dms\n", openr2_context_get_metering_pulse_timeout(r2context));
15349             ast_cli(a->fd, "MFC/R2 Rx CAS: %s\n", openr2_chan_get_rx_cas_string(tmp->r2chan));
15350             ast_cli(a->fd, "MFC/R2 Tx CAS: %s\n", openr2_chan_get_tx_cas_string(tmp->r2chan));
15351             ast_cli(a->fd, "MFC/R2 MF Tx Signal: %d\n", openr2_chan_get_tx_mf_signal(tmp->r2chan));
15352             ast_cli(a->fd, "MFC/R2 MF Rx Signal: %d\n", openr2_chan_get_rx_mf_signal(tmp->r2chan));
15353             ast_cli(a->fd, "MFC/R2 Call Files Directory: %s\n", openr2_context_get_log_directory(r2context, calldir, sizeof(calldir)));
15354          }
15355 #endif
15356 #if defined(HAVE_SS7)
15357          if (tmp->ss7) {
15358             struct sig_ss7_chan *chan = tmp->sig_pvt;
15359 
15360             ast_cli(a->fd, "CIC: %d\n", chan->cic);
15361          }
15362 #endif   /* defined(HAVE_SS7) */
15363 #ifdef HAVE_PRI
15364          if (tmp->pri) {
15365             struct sig_pri_chan *chan = tmp->sig_pvt;
15366 
15367             ast_cli(a->fd, "PRI Flags: ");
15368             if (chan->resetting)
15369                ast_cli(a->fd, "Resetting ");
15370             if (chan->call)
15371                ast_cli(a->fd, "Call ");
15372             if (chan->allocated) {
15373                ast_cli(a->fd, "Allocated ");
15374             }
15375             ast_cli(a->fd, "\n");
15376             if (tmp->logicalspan)
15377                ast_cli(a->fd, "PRI Logical Span: %d\n", tmp->logicalspan);
15378             else
15379                ast_cli(a->fd, "PRI Logical Span: Implicit\n");
15380          }
15381 #endif
15382          memset(&ci, 0, sizeof(ci));
15383          ps.channo = tmp->channel;
15384          if (tmp->subs[SUB_REAL].dfd > -1) {
15385             memset(&ci, 0, sizeof(ci));
15386             if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
15387                ast_cli(a->fd, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci.confno, ci.confmode);
15388             }
15389             if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONFMUTE, &x)) {
15390                ast_cli(a->fd, "Actual Confmute: %s\n", x ? "Yes" : "No");
15391             }
15392             memset(&ps, 0, sizeof(ps));
15393             if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
15394                ast_log(LOG_WARNING, "Failed to get parameters on channel %d: %s\n", tmp->channel, strerror(errno));
15395             } else {
15396                ast_cli(a->fd, "Hookstate (FXS only): %s\n", ps.rxisoffhook ? "Offhook" : "Onhook");
15397             }
15398          }
15399          ast_mutex_unlock(&iflock);
15400          return CLI_SUCCESS;
15401       }
15402    }
15403    ast_mutex_unlock(&iflock);
15404 
15405    ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15406    return CLI_FAILURE;
15407 }
15408 
15409 static char *handle_dahdi_show_cadences(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15410 {
15411    int i, j;
15412    switch (cmd) {
15413    case CLI_INIT:
15414       e->command = "dahdi show cadences";
15415       e->usage =
15416          "Usage: dahdi show cadences\n"
15417          "       Shows all cadences currently defined\n";
15418       return NULL;
15419    case CLI_GENERATE:
15420       return NULL;
15421    }
15422    for (i = 0; i < num_cadence; i++) {
15423       char output[1024];
15424       char tmp[16], tmp2[64];
15425       snprintf(tmp, sizeof(tmp), "r%d: ", i + 1);
15426       term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output));
15427 
15428       for (j = 0; j < 16; j++) {
15429          if (cadences[i].ringcadence[j] == 0)
15430             break;
15431          snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]);
15432          if (cidrings[i] * 2 - 1 == j)
15433             term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1);
15434          else
15435             term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1);
15436          if (j != 0)
15437             strncat(output, ",", sizeof(output) - strlen(output) - 1);
15438          strncat(output, tmp2, sizeof(output) - strlen(output) - 1);
15439       }
15440       ast_cli(a->fd,"%s\n",output);
15441    }
15442    return CLI_SUCCESS;
15443 }
15444 
15445 /* Based on irqmiss.c */
15446 static char *dahdi_show_status(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15447 {
15448    #define FORMAT "%-40.40s %-7.7s %-6d %-6d %-6d %-3.3s %-4.4s %-8.8s %s\n"
15449    #define FORMAT2 "%-40.40s %-7.7s %-6.6s %-6.6s %-6.6s %-3.3s %-4.4s %-8.8s %s\n"
15450    int span;
15451    int res;
15452    char alarmstr[50];
15453 
15454    int ctl;
15455    struct dahdi_spaninfo s;
15456 
15457    switch (cmd) {
15458    case CLI_INIT:
15459       e->command = "dahdi show status";
15460       e->usage =
15461          "Usage: dahdi show status\n"
15462          "       Shows a list of DAHDI cards with status\n";
15463       return NULL;
15464    case CLI_GENERATE:
15465       return NULL;
15466    }
15467    ctl = open("/dev/dahdi/ctl", O_RDWR);
15468    if (ctl < 0) {
15469       ast_cli(a->fd, "No DAHDI found. Unable to open /dev/dahdi/ctl: %s\n", strerror(errno));
15470       return CLI_FAILURE;
15471    }
15472    ast_cli(a->fd, FORMAT2, "Description", "Alarms", "IRQ", "bpviol", "CRC", "Framing", "Coding", "Options", "LBO");
15473 
15474    for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
15475       s.spanno = span;
15476       res = ioctl(ctl, DAHDI_SPANSTAT, &s);
15477       if (res) {
15478          continue;
15479       }
15480       alarmstr[0] = '\0';
15481       if (s.alarms > 0) {
15482          if (s.alarms & DAHDI_ALARM_BLUE)
15483             strcat(alarmstr, "BLU/");
15484          if (s.alarms & DAHDI_ALARM_YELLOW)
15485             strcat(alarmstr, "YEL/");
15486          if (s.alarms & DAHDI_ALARM_RED)
15487             strcat(alarmstr, "RED/");
15488          if (s.alarms & DAHDI_ALARM_LOOPBACK)
15489             strcat(alarmstr, "LB/");
15490          if (s.alarms & DAHDI_ALARM_RECOVER)
15491             strcat(alarmstr, "REC/");
15492          if (s.alarms & DAHDI_ALARM_NOTOPEN)
15493             strcat(alarmstr, "NOP/");
15494          if (!strlen(alarmstr))
15495             strcat(alarmstr, "UUU/");
15496          if (strlen(alarmstr)) {
15497             /* Strip trailing / */
15498             alarmstr[strlen(alarmstr) - 1] = '\0';
15499          }
15500       } else {
15501          if (s.numchans)
15502             strcpy(alarmstr, "OK");
15503          else
15504             strcpy(alarmstr, "UNCONFIGURED");
15505       }
15506 
15507       ast_cli(a->fd, FORMAT, s.desc, alarmstr, s.irqmisses, s.bpvcount, s.crc4count,
15508          s.lineconfig & DAHDI_CONFIG_D4 ? "D4" :
15509          s.lineconfig & DAHDI_CONFIG_ESF ? "ESF" :
15510          s.lineconfig & DAHDI_CONFIG_CCS ? "CCS" :
15511          "CAS",
15512          s.lineconfig & DAHDI_CONFIG_B8ZS ? "B8ZS" :
15513          s.lineconfig & DAHDI_CONFIG_HDB3 ? "HDB3" :
15514          s.lineconfig & DAHDI_CONFIG_AMI ? "AMI" :
15515          "Unk",
15516          s.lineconfig & DAHDI_CONFIG_CRC4 ?
15517             s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" :
15518             s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "YEL" : "",
15519          lbostr[s.lbo]
15520          );
15521    }
15522    close(ctl);
15523 
15524    return CLI_SUCCESS;
15525 #undef FORMAT
15526 #undef FORMAT2
15527 }
15528 
15529 static char *dahdi_show_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15530 {
15531    int pseudo_fd = -1;
15532    struct dahdi_versioninfo vi;
15533 
15534    switch (cmd) {
15535    case CLI_INIT:
15536       e->command = "dahdi show version";
15537       e->usage =
15538          "Usage: dahdi show version\n"
15539          "       Shows the DAHDI version in use\n";
15540       return NULL;
15541    case CLI_GENERATE:
15542       return NULL;
15543    }
15544    if ((pseudo_fd = open("/dev/dahdi/ctl", O_RDONLY)) < 0) {
15545       ast_cli(a->fd, "Failed to open control file to get version.\n");
15546       return CLI_SUCCESS;
15547    }
15548 
15549    strcpy(vi.version, "Unknown");
15550    strcpy(vi.echo_canceller, "Unknown");
15551 
15552    if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi))
15553       ast_cli(a->fd, "Failed to get DAHDI version: %s\n", strerror(errno));
15554    else
15555       ast_cli(a->fd, "DAHDI Version: %s Echo Canceller: %s\n", vi.version, vi.echo_canceller);
15556 
15557    close(pseudo_fd);
15558 
15559    return CLI_SUCCESS;
15560 }
15561 
15562 static char *dahdi_set_hwgain(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15563 {
15564    int channel;
15565    int gain;
15566    int tx;
15567    struct dahdi_hwgain hwgain;
15568    struct dahdi_pvt *tmp = NULL;
15569 
15570    switch (cmd) {
15571    case CLI_INIT:
15572       e->command = "dahdi set hwgain";
15573       e->usage =
15574          "Usage: dahdi set hwgain <rx|tx> <chan#> <gain>\n"
15575          "  Sets the hardware gain on a a given channel, overriding the\n"
15576          "   value provided at module loadtime, whether the channel is in\n"
15577          "   use or not.  Changes take effect immediately.\n"
15578          "   <rx|tx> which direction do you want to change (relative to our module)\n"
15579          "   <chan num> is the channel number relative to the device\n"
15580          "   <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
15581       return NULL;
15582    case CLI_GENERATE:
15583       return NULL;
15584    }
15585 
15586    if (a->argc != 6)
15587       return CLI_SHOWUSAGE;
15588 
15589    if (!strcasecmp("rx", a->argv[3]))
15590       tx = 0; /* rx */
15591    else if (!strcasecmp("tx", a->argv[3]))
15592       tx = 1; /* tx */
15593    else
15594       return CLI_SHOWUSAGE;
15595 
15596    channel = atoi(a->argv[4]);
15597    gain = atof(a->argv[5])*10.0;
15598 
15599    ast_mutex_lock(&iflock);
15600 
15601    for (tmp = iflist; tmp; tmp = tmp->next) {
15602 
15603       if (tmp->channel != channel)
15604          continue;
15605 
15606       if (tmp->subs[SUB_REAL].dfd == -1)
15607          break;
15608 
15609       hwgain.newgain = gain;
15610       hwgain.tx = tx;
15611       if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_HWGAIN, &hwgain) < 0) {
15612          ast_cli(a->fd, "Unable to set the hardware gain for channel %d: %s\n", channel, strerror(errno));
15613          ast_mutex_unlock(&iflock);
15614          return CLI_FAILURE;
15615       }
15616       ast_cli(a->fd, "hardware %s gain set to %d (%.1f dB) on channel %d\n",
15617          tx ? "tx" : "rx", gain, (float)gain/10.0, channel);
15618       break;
15619    }
15620 
15621    ast_mutex_unlock(&iflock);
15622 
15623    if (tmp)
15624       return CLI_SUCCESS;
15625 
15626    ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15627    return CLI_FAILURE;
15628 
15629 }
15630 
15631 static char *dahdi_set_swgain(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15632 {
15633    int channel;
15634    float gain;
15635    int tx;
15636    int res;
15637    struct dahdi_pvt *tmp = NULL;
15638 
15639    switch (cmd) {
15640    case CLI_INIT:
15641       e->command = "dahdi set swgain";
15642       e->usage =
15643          "Usage: dahdi set swgain <rx|tx> <chan#> <gain>\n"
15644          "  Sets the software gain on a a given channel, overriding the\n"
15645          "   value provided at module loadtime, whether the channel is in\n"
15646          "   use or not.  Changes take effect immediately.\n"
15647          "   <rx|tx> which direction do you want to change (relative to our module)\n"
15648          "   <chan num> is the channel number relative to the device\n"
15649          "   <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
15650       return NULL;
15651    case CLI_GENERATE:
15652       return NULL;
15653    }
15654 
15655    if (a->argc != 6)
15656       return CLI_SHOWUSAGE;
15657 
15658    if (!strcasecmp("rx", a->argv[3]))
15659       tx = 0; /* rx */
15660    else if (!strcasecmp("tx", a->argv[3]))
15661       tx = 1; /* tx */
15662    else
15663       return CLI_SHOWUSAGE;
15664 
15665    channel = atoi(a->argv[4]);
15666    gain = atof(a->argv[5]);
15667 
15668    ast_mutex_lock(&iflock);
15669    for (tmp = iflist; tmp; tmp = tmp->next) {
15670 
15671       if (tmp->channel != channel)
15672          continue;
15673 
15674       if (tmp->subs[SUB_REAL].dfd == -1)
15675          break;
15676 
15677       if (tx)
15678          res = set_actual_txgain(tmp->subs[SUB_REAL].dfd, gain, tmp->txdrc, tmp->law);
15679       else
15680          res = set_actual_rxgain(tmp->subs[SUB_REAL].dfd, gain, tmp->rxdrc, tmp->law);
15681 
15682       if (res) {
15683          ast_cli(a->fd, "Unable to set the software gain for channel %d\n", channel);
15684          ast_mutex_unlock(&iflock);
15685          return CLI_FAILURE;
15686       }
15687 
15688       ast_cli(a->fd, "software %s gain set to %.1f on channel %d\n",
15689          tx ? "tx" : "rx", gain, channel);
15690       break;
15691    }
15692    ast_mutex_unlock(&iflock);
15693 
15694    if (tmp)
15695       return CLI_SUCCESS;
15696 
15697    ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15698    return CLI_FAILURE;
15699 
15700 }
15701 
15702 static char *dahdi_set_dnd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15703 {
15704    int channel;
15705    int on;
15706    struct dahdi_pvt *dahdi_chan = NULL;
15707 
15708    switch (cmd) {
15709    case CLI_INIT:
15710       e->command = "dahdi set dnd";
15711       e->usage =
15712          "Usage: dahdi set dnd <chan#> <on|off>\n"
15713          "  Sets/resets DND (Do Not Disturb) mode on a channel.\n"
15714          "  Changes take effect immediately.\n"
15715          "  <chan num> is the channel number\n"
15716          "  <on|off> Enable or disable DND mode?\n"
15717          ;
15718       return NULL;
15719    case CLI_GENERATE:
15720       return NULL;
15721    }
15722 
15723    if (a->argc != 5)
15724       return CLI_SHOWUSAGE;
15725 
15726    if ((channel = atoi(a->argv[3])) <= 0) {
15727       ast_cli(a->fd, "Expected channel number, got '%s'\n", a->argv[3]);
15728       return CLI_SHOWUSAGE;
15729    }
15730 
15731    if (ast_true(a->argv[4]))
15732       on = 1;
15733    else if (ast_false(a->argv[4]))
15734       on = 0;
15735    else {
15736       ast_cli(a->fd, "Expected 'on' or 'off', got '%s'\n", a->argv[4]);
15737       return CLI_SHOWUSAGE;
15738    }
15739 
15740    ast_mutex_lock(&iflock);
15741    for (dahdi_chan = iflist; dahdi_chan; dahdi_chan = dahdi_chan->next) {
15742       if (dahdi_chan->channel != channel)
15743          continue;
15744 
15745       /* Found the channel. Actually set it */
15746       dahdi_dnd(dahdi_chan, on);
15747       break;
15748    }
15749    ast_mutex_unlock(&iflock);
15750 
15751    if (!dahdi_chan) {
15752       ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15753       return CLI_FAILURE;
15754    }
15755 
15756    return CLI_SUCCESS;
15757 }
15758 
15759 static struct ast_cli_entry dahdi_cli[] = {
15760    AST_CLI_DEFINE(handle_dahdi_show_cadences, "List cadences"),
15761    AST_CLI_DEFINE(dahdi_show_channels, "Show active DAHDI channels"),
15762    AST_CLI_DEFINE(dahdi_show_channel, "Show information on a channel"),
15763    AST_CLI_DEFINE(dahdi_destroy_channel, "Destroy a channel"),
15764    AST_CLI_DEFINE(dahdi_restart_cmd, "Fully restart DAHDI channels"),
15765    AST_CLI_DEFINE(dahdi_show_status, "Show all DAHDI cards status"),
15766    AST_CLI_DEFINE(dahdi_show_version, "Show the DAHDI version in use"),
15767    AST_CLI_DEFINE(dahdi_set_hwgain, "Set hardware gain on a channel"),
15768    AST_CLI_DEFINE(dahdi_set_swgain, "Set software gain on a channel"),
15769    AST_CLI_DEFINE(dahdi_set_dnd, "Sets/resets DND (Do Not Disturb) mode on a channel"),
15770 };
15771 
15772 #define TRANSFER  0
15773 #define HANGUP    1
15774 
15775 static int dahdi_fake_event(struct dahdi_pvt *p, int mode)
15776 {
15777    if (p) {
15778       switch (mode) {
15779       case TRANSFER:
15780          p->fake_event = DAHDI_EVENT_WINKFLASH;
15781          break;
15782       case HANGUP:
15783          p->fake_event = DAHDI_EVENT_ONHOOK;
15784          break;
15785       default:
15786          ast_log(LOG_WARNING, "I don't know how to handle transfer event with this: %d on channel %s\n",mode, p->owner->name);
15787       }
15788    }
15789    return 0;
15790 }
15791 static struct dahdi_pvt *find_channel(int channel)
15792 {
15793    struct dahdi_pvt *p;
15794 
15795    ast_mutex_lock(&iflock);
15796    for (p = iflist; p; p = p->next) {
15797       if (p->channel == channel) {
15798          break;
15799       }
15800    }
15801    ast_mutex_unlock(&iflock);
15802    return p;
15803 }
15804 
15805 /*!
15806  * \internal
15807  * \brief Get private struct using given numeric channel string.
15808  *
15809  * \param channel Numeric channel number string get private struct.
15810  *
15811  * \retval pvt on success.
15812  * \retval NULL on error.
15813  */
15814 static struct dahdi_pvt *find_channel_from_str(const char *channel)
15815 {
15816    int chan_num;
15817 
15818    if (sscanf(channel, "%30d", &chan_num) != 1) {
15819       /* Not numeric string. */
15820       return NULL;
15821    }
15822 
15823    return find_channel(chan_num);
15824 }
15825 
15826 static int action_dahdidndon(struct mansession *s, const struct message *m)
15827 {
15828    struct dahdi_pvt *p;
15829    const char *channel = astman_get_header(m, "DAHDIChannel");
15830 
15831    if (ast_strlen_zero(channel)) {
15832       astman_send_error(s, m, "No channel specified");
15833       return 0;
15834    }
15835    p = find_channel_from_str(channel);
15836    if (!p) {
15837       astman_send_error(s, m, "No such channel");
15838       return 0;
15839    }
15840    dahdi_dnd(p, 1);
15841    astman_send_ack(s, m, "DND Enabled");
15842    return 0;
15843 }
15844 
15845 static int action_dahdidndoff(struct mansession *s, const struct message *m)
15846 {
15847    struct dahdi_pvt *p;
15848    const char *channel = astman_get_header(m, "DAHDIChannel");
15849 
15850    if (ast_strlen_zero(channel)) {
15851       astman_send_error(s, m, "No channel specified");
15852       return 0;
15853    }
15854    p = find_channel_from_str(channel);
15855    if (!p) {
15856       astman_send_error(s, m, "No such channel");
15857       return 0;
15858    }
15859    dahdi_dnd(p, 0);
15860    astman_send_ack(s, m, "DND Disabled");
15861    return 0;
15862 }
15863 
15864 static int action_transfer(struct mansession *s, const struct message *m)
15865 {
15866    struct dahdi_pvt *p;
15867    const char *channel = astman_get_header(m, "DAHDIChannel");
15868 
15869    if (ast_strlen_zero(channel)) {
15870       astman_send_error(s, m, "No channel specified");
15871       return 0;
15872    }
15873    p = find_channel_from_str(channel);
15874    if (!p) {
15875       astman_send_error(s, m, "No such channel");
15876       return 0;
15877    }
15878    if (!analog_lib_handles(p->sig, 0, 0)) {
15879       astman_send_error(s, m, "Channel signaling is not analog");
15880       return 0;
15881    }
15882    dahdi_fake_event(p,TRANSFER);
15883    astman_send_ack(s, m, "DAHDITransfer");
15884    return 0;
15885 }
15886 
15887 static int action_transferhangup(struct mansession *s, const struct message *m)
15888 {
15889    struct dahdi_pvt *p;
15890    const char *channel = astman_get_header(m, "DAHDIChannel");
15891 
15892    if (ast_strlen_zero(channel)) {
15893       astman_send_error(s, m, "No channel specified");
15894       return 0;
15895    }
15896    p = find_channel_from_str(channel);
15897    if (!p) {
15898       astman_send_error(s, m, "No such channel");
15899       return 0;
15900    }
15901    if (!analog_lib_handles(p->sig, 0, 0)) {
15902       astman_send_error(s, m, "Channel signaling is not analog");
15903       return 0;
15904    }
15905    dahdi_fake_event(p,HANGUP);
15906    astman_send_ack(s, m, "DAHDIHangup");
15907    return 0;
15908 }
15909 
15910 static int action_dahdidialoffhook(struct mansession *s, const struct message *m)
15911 {
15912    struct dahdi_pvt *p;
15913    const char *channel = astman_get_header(m, "DAHDIChannel");
15914    const char *number = astman_get_header(m, "Number");
15915    int i;
15916 
15917    if (ast_strlen_zero(channel)) {
15918       astman_send_error(s, m, "No channel specified");
15919       return 0;
15920    }
15921    if (ast_strlen_zero(number)) {
15922       astman_send_error(s, m, "No number specified");
15923       return 0;
15924    }
15925    p = find_channel_from_str(channel);
15926    if (!p) {
15927       astman_send_error(s, m, "No such channel");
15928       return 0;
15929    }
15930    if (!p->owner) {
15931       astman_send_error(s, m, "Channel does not have it's owner");
15932       return 0;
15933    }
15934    for (i = 0; i < strlen(number); i++) {
15935       struct ast_frame f = { AST_FRAME_DTMF, .subclass.integer = number[i] };
15936       dahdi_queue_frame(p, &f);
15937    }
15938    astman_send_ack(s, m, "DAHDIDialOffhook");
15939    return 0;
15940 }
15941 
15942 static int action_dahdishowchannels(struct mansession *s, const struct message *m)
15943 {
15944    struct dahdi_pvt *tmp = NULL;
15945    const char *id = astman_get_header(m, "ActionID");
15946    const char *dahdichannel = astman_get_header(m, "DAHDIChannel");
15947    char idText[256] = "";
15948    int channels = 0;
15949    int dahdichanquery;
15950 
15951    if (!dahdichannel || sscanf(dahdichannel, "%30d", &dahdichanquery) != 1) {
15952       /* Not numeric string. */
15953       dahdichanquery = -1;
15954    }
15955 
15956    astman_send_ack(s, m, "DAHDI channel status will follow");
15957    if (!ast_strlen_zero(id))
15958       snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
15959 
15960    ast_mutex_lock(&iflock);
15961 
15962    for (tmp = iflist; tmp; tmp = tmp->next) {
15963       if (tmp->channel > 0) {
15964          int alm;
15965 
15966          /* If a specific channel is queried for, only deliver status for that channel */
15967          if (dahdichanquery > 0 && tmp->channel != dahdichanquery)
15968             continue;
15969 
15970          alm = get_alarms(tmp);
15971          channels++;
15972          if (tmp->owner) {
15973             /* Add data if we have a current call */
15974             astman_append(s,
15975                "Event: DAHDIShowChannels\r\n"
15976                "DAHDIChannel: %d\r\n"
15977                "Channel: %s\r\n"
15978                "Uniqueid: %s\r\n"
15979                "AccountCode: %s\r\n"
15980                "Signalling: %s\r\n"
15981                "SignallingCode: %d\r\n"
15982                "Context: %s\r\n"
15983                "DND: %s\r\n"
15984                "Alarm: %s\r\n"
15985                "%s"
15986                "\r\n",
15987                tmp->channel,
15988                tmp->owner->name,
15989                tmp->owner->uniqueid,
15990                tmp->owner->accountcode,
15991                sig2str(tmp->sig),
15992                tmp->sig,
15993                tmp->context,
15994                dahdi_dnd(tmp, -1) ? "Enabled" : "Disabled",
15995                alarm2str(alm), idText);
15996          } else {
15997             astman_append(s,
15998                "Event: DAHDIShowChannels\r\n"
15999                "DAHDIChannel: %d\r\n"
16000                "Signalling: %s\r\n"
16001                "SignallingCode: %d\r\n"
16002                "Context: %s\r\n"
16003                "DND: %s\r\n"
16004                "Alarm: %s\r\n"
16005                "%s"
16006                "\r\n",
16007                tmp->channel, sig2str(tmp->sig), tmp->sig,
16008                tmp->context,
16009                dahdi_dnd(tmp, -1) ? "Enabled" : "Disabled",
16010                alarm2str(alm), idText);
16011          }
16012       }
16013    }
16014 
16015    ast_mutex_unlock(&iflock);
16016 
16017    astman_append(s,
16018       "Event: DAHDIShowChannelsComplete\r\n"
16019       "%s"
16020       "Items: %d\r\n"
16021       "\r\n",
16022       idText,
16023       channels);
16024    return 0;
16025 }
16026 
16027 #if defined(HAVE_SS7)
16028 static int linkset_addsigchan(int sigchan)
16029 {
16030    struct dahdi_ss7 *link;
16031    int res;
16032    int curfd;
16033    struct dahdi_params params;
16034    struct dahdi_bufferinfo bi;
16035    struct dahdi_spaninfo si;
16036 
16037    if (sigchan < 0) {
16038       ast_log(LOG_ERROR, "Invalid sigchan!\n");
16039       return -1;
16040    }
16041    if (cur_ss7type < 0) {
16042       ast_log(LOG_ERROR, "Unspecified or invalid ss7type\n");
16043       return -1;
16044    }
16045    if (cur_pointcode < 0) {
16046       ast_log(LOG_ERROR, "Unspecified pointcode!\n");
16047       return -1;
16048    }
16049    if (cur_adjpointcode < 0) {
16050       ast_log(LOG_ERROR, "Unspecified adjpointcode!\n");
16051       return -1;
16052    }
16053    if (cur_defaultdpc < 0) {
16054       ast_log(LOG_ERROR, "Unspecified defaultdpc!\n");
16055       return -1;
16056    }
16057    if (cur_networkindicator < 0) {
16058       ast_log(LOG_ERROR, "Invalid networkindicator!\n");
16059       return -1;
16060    }
16061    link = ss7_resolve_linkset(cur_linkset);
16062    if (!link) {
16063       ast_log(LOG_ERROR, "Invalid linkset number.  Must be between 1 and %d\n", NUM_SPANS + 1);
16064       return -1;
16065    }
16066    if (link->ss7.numsigchans >= SIG_SS7_NUM_DCHANS) {
16067       ast_log(LOG_ERROR, "Too many sigchans on linkset %d\n", cur_linkset);
16068       return -1;
16069    }
16070 
16071    curfd = link->ss7.numsigchans;
16072 
16073    /* Open signaling channel */
16074    link->ss7.fds[curfd] = open("/dev/dahdi/channel", O_RDWR, 0600);
16075    if (link->ss7.fds[curfd] < 0) {
16076       ast_log(LOG_ERROR, "Unable to open SS7 sigchan %d (%s)\n", sigchan,
16077          strerror(errno));
16078       return -1;
16079    }
16080    if (ioctl(link->ss7.fds[curfd], DAHDI_SPECIFY, &sigchan) == -1) {
16081       dahdi_close_ss7_fd(link, curfd);
16082       ast_log(LOG_ERROR, "Unable to specify SS7 sigchan %d (%s)\n", sigchan,
16083          strerror(errno));
16084       return -1;
16085    }
16086 
16087    /* Get signaling channel parameters */
16088    memset(&params, 0, sizeof(params));
16089    res = ioctl(link->ss7.fds[curfd], DAHDI_GET_PARAMS, &params);
16090    if (res) {
16091       dahdi_close_ss7_fd(link, curfd);
16092       ast_log(LOG_ERROR, "Unable to get parameters for sigchan %d (%s)\n", sigchan,
16093          strerror(errno));
16094       return -1;
16095    }
16096    if (params.sigtype != DAHDI_SIG_HDLCFCS
16097       && params.sigtype != DAHDI_SIG_HARDHDLC
16098       && params.sigtype != DAHDI_SIG_MTP2) {
16099       dahdi_close_ss7_fd(link, curfd);
16100       ast_log(LOG_ERROR, "sigchan %d is not in HDLC/FCS mode.\n", sigchan);
16101       return -1;
16102    }
16103 
16104    /* Set signaling channel buffer policy. */
16105    memset(&bi, 0, sizeof(bi));
16106    bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
16107    bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
16108    bi.numbufs = 32;
16109    bi.bufsize = 512;
16110    if (ioctl(link->ss7.fds[curfd], DAHDI_SET_BUFINFO, &bi)) {
16111       ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n",
16112          sigchan, strerror(errno));
16113       dahdi_close_ss7_fd(link, curfd);
16114       return -1;
16115    }
16116 
16117    /* Get current signaling channel alarm status. */
16118    memset(&si, 0, sizeof(si));
16119    res = ioctl(link->ss7.fds[curfd], DAHDI_SPANSTAT, &si);
16120    if (res) {
16121       dahdi_close_ss7_fd(link, curfd);
16122       ast_log(LOG_ERROR, "Unable to get span state for sigchan %d (%s)\n", sigchan,
16123          strerror(errno));
16124    }
16125 
16126    res = sig_ss7_add_sigchan(&link->ss7, curfd, cur_ss7type,
16127       (params.sigtype == DAHDI_SIG_MTP2)
16128          ? SS7_TRANSPORT_DAHDIMTP2
16129          : SS7_TRANSPORT_DAHDIDCHAN,
16130       si.alarms, cur_networkindicator, cur_pointcode, cur_adjpointcode);
16131    if (res) {
16132       dahdi_close_ss7_fd(link, curfd);
16133       return -1;
16134    }
16135 
16136    ++link->ss7.numsigchans;
16137 
16138    return 0;
16139 }
16140 #endif   /* defined(HAVE_SS7) */
16141 
16142 #if defined(HAVE_SS7)
16143 static char *handle_ss7_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16144 {
16145    int span;
16146    switch (cmd) {
16147    case CLI_INIT:
16148       e->command = "ss7 set debug {on|off} linkset";
16149       e->usage =
16150          "Usage: ss7 set debug {on|off} linkset <linkset>\n"
16151          "       Enables debugging on a given SS7 linkset\n";
16152       return NULL;
16153    case CLI_GENERATE:
16154       return NULL;
16155    }
16156    if (a->argc < 6)
16157       return CLI_SHOWUSAGE;
16158    span = atoi(a->argv[5]);
16159    if ((span < 1) || (span > NUM_SPANS)) {
16160       ast_cli(a->fd, "Invalid linkset %s.  Should be a number from %d to %d\n", a->argv[5], 1, NUM_SPANS);
16161       return CLI_SUCCESS;
16162    }
16163    if (!linksets[span-1].ss7.ss7) {
16164       ast_cli(a->fd, "No SS7 running on linkset %d\n", span);
16165    } else {
16166       if (!strcasecmp(a->argv[3], "on")) {
16167          linksets[span - 1].ss7.debug = 1;
16168          ss7_set_debug(linksets[span-1].ss7.ss7, SIG_SS7_DEBUG);
16169          ast_cli(a->fd, "Enabled debugging on linkset %d\n", span);
16170       } else {
16171          linksets[span - 1].ss7.debug = 0;
16172          ss7_set_debug(linksets[span-1].ss7.ss7, 0);
16173          ast_cli(a->fd, "Disabled debugging on linkset %d\n", span);
16174       }
16175    }
16176 
16177    return CLI_SUCCESS;
16178 }
16179 #endif   /* defined(HAVE_SS7) */
16180 
16181 #if defined(HAVE_SS7)
16182 static char *handle_ss7_block_cic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16183 {
16184    int linkset, cic;
16185    int blocked = -1, i;
16186    switch (cmd) {
16187    case CLI_INIT:
16188       e->command = "ss7 block cic";
16189       e->usage =
16190          "Usage: ss7 block cic <linkset> <CIC>\n"
16191          "       Sends a remote blocking request for the given CIC on the specified linkset\n";
16192       return NULL;
16193    case CLI_GENERATE:
16194       return NULL;
16195    }
16196    if (a->argc == 5)
16197       linkset = atoi(a->argv[3]);
16198    else
16199       return CLI_SHOWUSAGE;
16200 
16201    if ((linkset < 1) || (linkset > NUM_SPANS)) {
16202       ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16203       return CLI_SUCCESS;
16204    }
16205 
16206    if (!linksets[linkset-1].ss7.ss7) {
16207       ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16208       return CLI_SUCCESS;
16209    }
16210 
16211    cic = atoi(a->argv[4]);
16212 
16213    if (cic < 1) {
16214       ast_cli(a->fd, "Invalid CIC specified!\n");
16215       return CLI_SUCCESS;
16216    }
16217 
16218    for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
16219       if (linksets[linkset-1].ss7.pvts[i]->cic == cic) {
16220          blocked = linksets[linkset-1].ss7.pvts[i]->locallyblocked;
16221          if (!blocked) {
16222             ast_mutex_lock(&linksets[linkset-1].ss7.lock);
16223             isup_blo(linksets[linkset-1].ss7.ss7, cic, linksets[linkset-1].ss7.pvts[i]->dpc);
16224             ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
16225          }
16226       }
16227    }
16228 
16229    if (blocked < 0) {
16230       ast_cli(a->fd, "Invalid CIC specified!\n");
16231       return CLI_SUCCESS;
16232    }
16233 
16234    if (!blocked)
16235       ast_cli(a->fd, "Sent blocking request for linkset %d on CIC %d\n", linkset, cic);
16236    else
16237       ast_cli(a->fd, "CIC %d already locally blocked\n", cic);
16238 
16239    /* Break poll on the linkset so it sends our messages */
16240    pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
16241 
16242    return CLI_SUCCESS;
16243 }
16244 #endif   /* defined(HAVE_SS7) */
16245 
16246 #if defined(HAVE_SS7)
16247 static char *handle_ss7_block_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16248 {
16249    int linkset;
16250    int i;
16251    switch (cmd) {
16252    case CLI_INIT:
16253       e->command = "ss7 block linkset";
16254       e->usage =
16255          "Usage: ss7 block linkset <linkset number>\n"
16256          "       Sends a remote blocking request for all CICs on the given linkset\n";
16257       return NULL;
16258    case CLI_GENERATE:
16259       return NULL;
16260    }
16261    if (a->argc == 4)
16262       linkset = atoi(a->argv[3]);
16263    else
16264       return CLI_SHOWUSAGE;
16265 
16266    if ((linkset < 1) || (linkset > NUM_SPANS)) {
16267       ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16268       return CLI_SUCCESS;
16269    }
16270 
16271    if (!linksets[linkset-1].ss7.ss7) {
16272       ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16273       return CLI_SUCCESS;
16274    }
16275 
16276    for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
16277       ast_cli(a->fd, "Sending remote blocking request on CIC %d\n", linksets[linkset-1].ss7.pvts[i]->cic);
16278       ast_mutex_lock(&linksets[linkset-1].ss7.lock);
16279       isup_blo(linksets[linkset-1].ss7.ss7, linksets[linkset-1].ss7.pvts[i]->cic, linksets[linkset-1].ss7.pvts[i]->dpc);
16280       ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
16281    }
16282 
16283    /* Break poll on the linkset so it sends our messages */
16284    pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
16285 
16286    return CLI_SUCCESS;
16287 }
16288 #endif   /* defined(HAVE_SS7) */
16289 
16290 #if defined(HAVE_SS7)
16291 static char *handle_ss7_unblock_cic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16292 {
16293    int linkset, cic;
16294    int i, blocked = -1;
16295    switch (cmd) {
16296    case CLI_INIT:
16297       e->command = "ss7 unblock cic";
16298       e->usage =
16299          "Usage: ss7 unblock cic <linkset> <CIC>\n"
16300          "       Sends a remote unblocking request for the given CIC on the specified linkset\n";
16301       return NULL;
16302    case CLI_GENERATE:
16303       return NULL;
16304    }
16305 
16306    if (a->argc == 5)
16307       linkset = atoi(a->argv[3]);
16308    else
16309       return CLI_SHOWUSAGE;
16310 
16311    if ((linkset < 1) || (linkset > NUM_SPANS)) {
16312       ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16313       return CLI_SUCCESS;
16314    }
16315 
16316    if (!linksets[linkset-1].ss7.ss7) {
16317       ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16318       return CLI_SUCCESS;
16319    }
16320 
16321    cic = atoi(a->argv[4]);
16322 
16323    if (cic < 1) {
16324       ast_cli(a->fd, "Invalid CIC specified!\n");
16325       return CLI_SUCCESS;
16326    }
16327 
16328    for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
16329       if (linksets[linkset-1].ss7.pvts[i]->cic == cic) {
16330          blocked = linksets[linkset-1].ss7.pvts[i]->locallyblocked;
16331          if (blocked) {
16332             ast_mutex_lock(&linksets[linkset-1].ss7.lock);
16333             isup_ubl(linksets[linkset-1].ss7.ss7, cic, linksets[linkset-1].ss7.pvts[i]->dpc);
16334             ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
16335          }
16336       }
16337    }
16338 
16339    if (blocked > 0)
16340       ast_cli(a->fd, "Sent unblocking request for linkset %d on CIC %d\n", linkset, cic);
16341 
16342    /* Break poll on the linkset so it sends our messages */
16343    pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
16344 
16345    return CLI_SUCCESS;
16346 }
16347 #endif   /* defined(HAVE_SS7) */
16348 
16349 #if defined(HAVE_SS7)
16350 static char *handle_ss7_unblock_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16351 {
16352    int linkset;
16353    int i;
16354    switch (cmd) {
16355    case CLI_INIT:
16356       e->command = "ss7 unblock linkset";
16357       e->usage =
16358          "Usage: ss7 unblock linkset <linkset number>\n"
16359          "       Sends a remote unblocking request for all CICs on the specified linkset\n";
16360       return NULL;
16361    case CLI_GENERATE:
16362       return NULL;
16363    }
16364 
16365    if (a->argc == 4)
16366       linkset = atoi(a->argv[3]);
16367    else
16368       return CLI_SHOWUSAGE;
16369 
16370    if ((linkset < 1) || (linkset > NUM_SPANS)) {
16371       ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16372       return CLI_SUCCESS;
16373    }
16374 
16375    if (!linksets[linkset-1].ss7.ss7) {
16376       ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16377       return CLI_SUCCESS;
16378    }
16379 
16380    for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
16381       ast_cli(a->fd, "Sending remote unblock request on CIC %d\n", linksets[linkset-1].ss7.pvts[i]->cic);
16382       ast_mutex_lock(&linksets[linkset-1].ss7.lock);
16383       isup_ubl(linksets[linkset-1].ss7.ss7, linksets[linkset-1].ss7.pvts[i]->cic, linksets[linkset-1].ss7.pvts[i]->dpc);
16384       ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
16385    }
16386 
16387    /* Break poll on the linkset so it sends our messages */
16388    pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
16389 
16390    return CLI_SUCCESS;
16391 }
16392 #endif   /* defined(HAVE_SS7) */
16393 
16394 #if defined(HAVE_SS7)
16395 static char *handle_ss7_show_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16396 {
16397    int linkset;
16398    struct sig_ss7_linkset *ss7;
16399    switch (cmd) {
16400    case CLI_INIT:
16401       e->command = "ss7 show linkset";
16402       e->usage =
16403          "Usage: ss7 show linkset <span>\n"
16404          "       Shows the status of an SS7 linkset.\n";
16405       return NULL;
16406    case CLI_GENERATE:
16407       return NULL;
16408    }
16409 
16410    if (a->argc < 4)
16411       return CLI_SHOWUSAGE;
16412    linkset = atoi(a->argv[3]);
16413    if ((linkset < 1) || (linkset > NUM_SPANS)) {
16414       ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16415       return CLI_SUCCESS;
16416    }
16417    ss7 = &linksets[linkset - 1].ss7;
16418    if (!ss7->ss7) {
16419       ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16420       return CLI_SUCCESS;
16421    }
16422 
16423    ast_cli(a->fd, "SS7 linkset %d status: %s\n", linkset, (ss7->state == LINKSET_STATE_UP) ? "Up" : "Down");
16424 
16425    return CLI_SUCCESS;
16426 }
16427 #endif   /* defined(HAVE_SS7) */
16428 
16429 #if defined(HAVE_SS7)
16430 static char *handle_ss7_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16431 {
16432    int linkset;
16433 
16434    switch (cmd) {
16435    case CLI_INIT:
16436       e->command = "ss7 show channels";
16437       e->usage =
16438          "Usage: ss7 show channels\n"
16439          "       Displays SS7 channel information at a glance.\n";
16440       return NULL;
16441    case CLI_GENERATE:
16442       return NULL;
16443    }
16444 
16445    if (a->argc != 3)
16446       return CLI_SHOWUSAGE;
16447 
16448    sig_ss7_cli_show_channels_header(a->fd);
16449    for (linkset = 0; linkset < NUM_SPANS; ++linkset) {
16450       if (linksets[linkset].ss7.ss7) {
16451          sig_ss7_cli_show_channels(a->fd, &linksets[linkset].ss7);
16452       }
16453    }
16454    return CLI_SUCCESS;
16455 }
16456 #endif   /* defined(HAVE_SS7) */
16457 
16458 #if defined(HAVE_SS7)
16459 static char *handle_ss7_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16460 {
16461    switch (cmd) {
16462    case CLI_INIT:
16463       e->command = "ss7 show version";
16464       e->usage =
16465          "Usage: ss7 show version\n"
16466          "  Show the libss7 version\n";
16467       return NULL;
16468    case CLI_GENERATE:
16469       return NULL;
16470    }
16471 
16472    ast_cli(a->fd, "libss7 version: %s\n", ss7_get_version());
16473 
16474    return CLI_SUCCESS;
16475 }
16476 #endif   /* defined(HAVE_SS7) */
16477 
16478 #if defined(HAVE_SS7)
16479 static struct ast_cli_entry dahdi_ss7_cli[] = {
16480    AST_CLI_DEFINE(handle_ss7_debug, "Enables SS7 debugging on a linkset"),
16481    AST_CLI_DEFINE(handle_ss7_block_cic, "Blocks the given CIC"),
16482    AST_CLI_DEFINE(handle_ss7_unblock_cic, "Unblocks the given CIC"),
16483    AST_CLI_DEFINE(handle_ss7_block_linkset, "Blocks all CICs on a linkset"),
16484    AST_CLI_DEFINE(handle_ss7_unblock_linkset, "Unblocks all CICs on a linkset"),
16485    AST_CLI_DEFINE(handle_ss7_show_linkset, "Shows the status of a linkset"),
16486    AST_CLI_DEFINE(handle_ss7_show_channels, "Displays SS7 channel information"),
16487    AST_CLI_DEFINE(handle_ss7_version, "Displays libss7 version"),
16488 };
16489 #endif   /* defined(HAVE_SS7) */
16490 
16491 #if defined(HAVE_PRI)
16492 #if defined(HAVE_PRI_CCSS)
16493 /*!
16494  * \internal
16495  * \brief CC agent initialization.
16496  * \since 1.8
16497  *
16498  * \param agent CC core agent control.
16499  * \param chan Original channel the agent will attempt to recall.
16500  *
16501  * \details
16502  * This callback is called when the CC core is initialized.  Agents should allocate
16503  * any private data necessary for the call and assign it to the private_data
16504  * on the agent.  Additionally, if any ast_cc_agent_flags are pertinent to the
16505  * specific agent type, they should be set in this function as well.
16506  *
16507  * \retval 0 on success.
16508  * \retval -1 on error.
16509  */
16510 static int dahdi_pri_cc_agent_init(struct ast_cc_agent *agent, struct ast_channel *chan)
16511 {
16512    struct dahdi_pvt *pvt;
16513    struct sig_pri_chan *pvt_chan;
16514    int res;
16515 
16516    ast_assert(!strcmp(chan->tech->type, "DAHDI"));
16517 
16518    pvt = chan->tech_pvt;
16519    if (dahdi_sig_pri_lib_handles(pvt->sig)) {
16520       pvt_chan = pvt->sig_pvt;
16521    } else {
16522       pvt_chan = NULL;
16523    }
16524    if (!pvt_chan) {
16525       return -1;
16526    }
16527 
16528    ast_module_ref(ast_module_info->self);
16529 
16530    res = sig_pri_cc_agent_init(agent, pvt_chan);
16531    if (res) {
16532       ast_module_unref(ast_module_info->self);
16533    }
16534    return res;
16535 }
16536 #endif   /* defined(HAVE_PRI_CCSS) */
16537 #endif   /* defined(HAVE_PRI) */
16538 
16539 #if defined(HAVE_PRI)
16540 #if defined(HAVE_PRI_CCSS)
16541 /*!
16542  * \internal
16543  * \brief Destroy private data on the agent.
16544  * \since 1.8
16545  *
16546  * \param agent CC core agent control.
16547  *
16548  * \details
16549  * The core will call this function upon completion
16550  * or failure of CC.
16551  *
16552  * \return Nothing
16553  */
16554 static void dahdi_pri_cc_agent_destructor(struct ast_cc_agent *agent)
16555 {
16556    sig_pri_cc_agent_destructor(agent);
16557 
16558    ast_module_unref(ast_module_info->self);
16559 }
16560 #endif   /* defined(HAVE_PRI_CCSS) */
16561 #endif   /* defined(HAVE_PRI) */
16562 
16563 #if defined(HAVE_PRI)
16564 #if defined(HAVE_PRI_CCSS)
16565 static struct ast_cc_agent_callbacks dahdi_pri_cc_agent_callbacks = {
16566    .type = dahdi_pri_cc_type,
16567    .init = dahdi_pri_cc_agent_init,
16568    .start_offer_timer = sig_pri_cc_agent_start_offer_timer,
16569    .stop_offer_timer = sig_pri_cc_agent_stop_offer_timer,
16570    .respond = sig_pri_cc_agent_req_rsp,
16571    .status_request = sig_pri_cc_agent_status_req,
16572    .stop_ringing = sig_pri_cc_agent_stop_ringing,
16573    .party_b_free = sig_pri_cc_agent_party_b_free,
16574    .start_monitoring = sig_pri_cc_agent_start_monitoring,
16575    .callee_available = sig_pri_cc_agent_callee_available,
16576    .destructor = dahdi_pri_cc_agent_destructor,
16577 };
16578 #endif   /* defined(HAVE_PRI_CCSS) */
16579 #endif   /* defined(HAVE_PRI) */
16580 
16581 #if defined(HAVE_PRI)
16582 #if defined(HAVE_PRI_CCSS)
16583 static struct ast_cc_monitor_callbacks dahdi_pri_cc_monitor_callbacks = {
16584    .type = dahdi_pri_cc_type,
16585    .request_cc = sig_pri_cc_monitor_req_cc,
16586    .suspend = sig_pri_cc_monitor_suspend,
16587    .unsuspend = sig_pri_cc_monitor_unsuspend,
16588    .status_response = sig_pri_cc_monitor_status_rsp,
16589    .cancel_available_timer = sig_pri_cc_monitor_cancel_available_timer,
16590    .destructor = sig_pri_cc_monitor_destructor,
16591 };
16592 #endif   /* defined(HAVE_PRI_CCSS) */
16593 #endif   /* defined(HAVE_PRI) */
16594 
16595 static int __unload_module(void)
16596 {
16597    struct dahdi_pvt *p;
16598 #if defined(HAVE_PRI) || defined(HAVE_SS7)
16599    int i, j;
16600 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
16601 
16602 #ifdef HAVE_PRI
16603    for (i = 0; i < NUM_SPANS; i++) {
16604       if (pris[i].pri.master != AST_PTHREADT_NULL)
16605          pthread_cancel(pris[i].pri.master);
16606    }
16607    ast_cli_unregister_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
16608    ast_unregister_application(dahdi_send_keypad_facility_app);
16609 #ifdef HAVE_PRI_PROG_W_CAUSE
16610    ast_unregister_application(dahdi_send_callrerouting_facility_app);
16611 #endif
16612 #endif
16613 #if defined(HAVE_SS7)
16614    for (i = 0; i < NUM_SPANS; i++) {
16615       if (linksets[i].ss7.master != AST_PTHREADT_NULL)
16616          pthread_cancel(linksets[i].ss7.master);
16617       }
16618    ast_cli_unregister_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
16619 #endif   /* defined(HAVE_SS7) */
16620 #if defined(HAVE_OPENR2)
16621    dahdi_r2_destroy_links();
16622    ast_cli_unregister_multiple(dahdi_mfcr2_cli, ARRAY_LEN(dahdi_mfcr2_cli));
16623    ast_unregister_application(dahdi_accept_r2_call_app);
16624 #endif
16625 
16626    ast_cli_unregister_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli));
16627    ast_manager_unregister("DAHDIDialOffhook");
16628    ast_manager_unregister("DAHDIHangup");
16629    ast_manager_unregister("DAHDITransfer");
16630    ast_manager_unregister("DAHDIDNDoff");
16631    ast_manager_unregister("DAHDIDNDon");
16632    ast_manager_unregister("DAHDIShowChannels");
16633    ast_manager_unregister("DAHDIRestart");
16634    ast_data_unregister(NULL);
16635    ast_channel_unregister(&dahdi_tech);
16636 
16637    /* Hangup all interfaces if they have an owner */
16638    ast_mutex_lock(&iflock);
16639    for (p = iflist; p; p = p->next) {
16640       if (p->owner)
16641          ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
16642    }
16643    ast_mutex_unlock(&iflock);
16644 
16645    ast_mutex_lock(&monlock);
16646    if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
16647       pthread_cancel(monitor_thread);
16648       pthread_kill(monitor_thread, SIGURG);
16649       pthread_join(monitor_thread, NULL);
16650    }
16651    monitor_thread = AST_PTHREADT_STOP;
16652    ast_mutex_unlock(&monlock);
16653 
16654    destroy_all_channels();
16655 
16656 #if defined(HAVE_PRI)
16657    for (i = 0; i < NUM_SPANS; i++) {
16658       if (pris[i].pri.master && (pris[i].pri.master != AST_PTHREADT_NULL))
16659          pthread_join(pris[i].pri.master, NULL);
16660       for (j = 0; j < SIG_PRI_NUM_DCHANS; j++) {
16661          dahdi_close_pri_fd(&(pris[i]), j);
16662       }
16663       sig_pri_stop_pri(&pris[i].pri);
16664    }
16665 #if defined(HAVE_PRI_CCSS)
16666    ast_cc_agent_unregister(&dahdi_pri_cc_agent_callbacks);
16667    ast_cc_monitor_unregister(&dahdi_pri_cc_monitor_callbacks);
16668 #endif   /* defined(HAVE_PRI_CCSS) */
16669    sig_pri_unload();
16670 #endif
16671 
16672 #if defined(HAVE_SS7)
16673    for (i = 0; i < NUM_SPANS; i++) {
16674       if (linksets[i].ss7.master && (linksets[i].ss7.master != AST_PTHREADT_NULL))
16675          pthread_join(linksets[i].ss7.master, NULL);
16676       for (j = 0; j < SIG_SS7_NUM_DCHANS; j++) {
16677          dahdi_close_ss7_fd(&(linksets[i]), j);
16678       }
16679    }
16680 #endif   /* defined(HAVE_SS7) */
16681    ast_cond_destroy(&ss_thread_complete);
16682    return 0;
16683 }
16684 
16685 static int unload_module(void)
16686 {
16687 #if defined(HAVE_PRI) || defined(HAVE_SS7)
16688    int y;
16689 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
16690 #ifdef HAVE_PRI
16691    for (y = 0; y < NUM_SPANS; y++)
16692       ast_mutex_destroy(&pris[y].pri.lock);
16693 #endif
16694 #if defined(HAVE_SS7)
16695    for (y = 0; y < NUM_SPANS; y++)
16696       ast_mutex_destroy(&linksets[y].ss7.lock);
16697 #endif   /* defined(HAVE_SS7) */
16698    return __unload_module();
16699 }
16700 
16701 static void string_replace(char *str, int char1, int char2)
16702 {
16703    for (; *str; str++) {
16704       if (*str == char1) {
16705          *str = char2;
16706       }
16707    }
16708 }
16709 
16710 static char *parse_spanchan(char *chanstr, char **subdir)
16711 {
16712    char *p;
16713 
16714    if ((p = strrchr(chanstr, '!')) == NULL) {
16715       *subdir = NULL;
16716       return chanstr;
16717    }
16718    *p++ = '\0';
16719    string_replace(chanstr, '!', '/');
16720    *subdir = chanstr;
16721    return p;
16722 }
16723 
16724 static int build_channels(struct dahdi_chan_conf *conf, const char *value, int reload, int lineno, int *found_pseudo)
16725 {
16726    char *c, *chan;
16727    char *subdir;
16728    int x, start, finish;
16729    struct dahdi_pvt *tmp;
16730 
16731    if ((reload == 0) && (conf->chan.sig < 0) && !conf->is_sig_auto) {
16732       ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n");
16733       return -1;
16734    }
16735 
16736    c = ast_strdupa(value);
16737    c = parse_spanchan(c, &subdir);
16738 
16739    while ((chan = strsep(&c, ","))) {
16740       if (sscanf(chan, "%30d-%30d", &start, &finish) == 2) {
16741          /* Range */
16742       } else if (sscanf(chan, "%30d", &start)) {
16743          /* Just one */
16744          finish = start;
16745       } else if (!strcasecmp(chan, "pseudo")) {
16746          finish = start = CHAN_PSEUDO;
16747          if (found_pseudo)
16748             *found_pseudo = 1;
16749       } else {
16750          ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan);
16751          return -1;
16752       }
16753       if (finish < start) {
16754          ast_log(LOG_WARNING, "Sillyness: %d < %d\n", start, finish);
16755          x = finish;
16756          finish = start;
16757          start = x;
16758       }
16759 
16760       for (x = start; x <= finish; x++) {
16761          char fn[PATH_MAX];
16762          int real_channel = x;
16763 
16764          if (!ast_strlen_zero(subdir)) {
16765             real_channel = device2chan(subdir, x, fn, sizeof(fn));
16766             if (real_channel < 0) {
16767                if (conf->ignore_failed_channels) {
16768                   ast_log(LOG_WARNING, "Failed configuring %s!%d, (got %d). But moving on to others.\n",
16769                         subdir, x, real_channel);
16770                   continue;
16771                } else {
16772                   ast_log(LOG_ERROR, "Failed configuring %s!%d, (got %d).\n",
16773                         subdir, x, real_channel);
16774                   return -1;
16775                }
16776             }
16777          }
16778          tmp = mkintf(real_channel, conf, reload);
16779 
16780          if (tmp) {
16781             ast_verb(3, "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", real_channel, sig2str(tmp->sig));
16782          } else {
16783             ast_log(LOG_ERROR, "Unable to %s channel '%s'\n",
16784                   (reload == 1) ? "reconfigure" : "register", value);
16785             return -1;
16786          }
16787       }
16788    }
16789 
16790    return 0;
16791 }
16792 
16793 /** The length of the parameters list of 'dahdichan'.
16794  * \todo Move definition of MAX_CHANLIST_LEN to a proper place. */
16795 #define MAX_CHANLIST_LEN 80
16796 
16797 static void process_echocancel(struct dahdi_chan_conf *confp, const char *data, unsigned int line)
16798 {
16799    char *parse = ast_strdupa(data);
16800    char *params[DAHDI_MAX_ECHOCANPARAMS + 1];
16801    unsigned int param_count;
16802    unsigned int x;
16803 
16804    if (!(param_count = ast_app_separate_args(parse, ',', params, ARRAY_LEN(params))))
16805       return;
16806 
16807    memset(&confp->chan.echocancel, 0, sizeof(confp->chan.echocancel));
16808 
16809    /* first parameter is tap length, process it here */
16810 
16811    x = ast_strlen_zero(params[0]) ? 0 : atoi(params[0]);
16812 
16813    if ((x == 32) || (x == 64) || (x == 128) || (x == 256) || (x == 512) || (x == 1024))
16814       confp->chan.echocancel.head.tap_length = x;
16815    else if ((confp->chan.echocancel.head.tap_length = ast_true(params[0])))
16816       confp->chan.echocancel.head.tap_length = 128;
16817 
16818    /* now process any remaining parameters */
16819 
16820    for (x = 1; x < param_count; x++) {
16821       struct {
16822          char *name;
16823          char *value;
16824       } param;
16825 
16826       if (ast_app_separate_args(params[x], '=', (char **) &param, 2) < 1) {
16827          ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, params[x]);
16828          continue;
16829       }
16830 
16831       if (ast_strlen_zero(param.name) || (strlen(param.name) > sizeof(confp->chan.echocancel.params[0].name)-1)) {
16832          ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, param.name);
16833          continue;
16834       }
16835 
16836       strcpy(confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].name, param.name);
16837 
16838       if (param.value) {
16839          if (sscanf(param.value, "%30d", &confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].value) != 1) {
16840             ast_log(LOG_WARNING, "Invalid echocancel parameter value supplied at line %d: '%s'\n", line, param.value);
16841             continue;
16842          }
16843       }
16844       confp->chan.echocancel.head.param_count++;
16845    }
16846 }
16847 
16848 /*! process_dahdi() - ignore keyword 'channel' and similar */
16849 #define PROC_DAHDI_OPT_NOCHAN  (1 << 0)
16850 /*! process_dahdi() - No warnings on non-existing cofiguration keywords */
16851 #define PROC_DAHDI_OPT_NOWARN  (1 << 1)
16852 
16853 static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct ast_variable *v, int reload, int options)
16854 {
16855    struct dahdi_pvt *tmp;
16856    int y;
16857    int found_pseudo = 0;
16858    struct ast_variable *dahdichan = NULL;
16859 
16860    for (; v; v = v->next) {
16861       if (!ast_jb_read_conf(&global_jbconf, v->name, v->value))
16862          continue;
16863 
16864       /* Create the interface list */
16865       if (!strcasecmp(v->name, "channel") || !strcasecmp(v->name, "channels")) {
16866          if (options & PROC_DAHDI_OPT_NOCHAN) {
16867             ast_log(LOG_WARNING, "Channel '%s' ignored.\n", v->value);
16868             continue;
16869          }
16870          if (build_channels(confp, v->value, reload, v->lineno, &found_pseudo)) {
16871             if (confp->ignore_failed_channels) {
16872                ast_log(LOG_WARNING, "Channel '%s' failure ignored: ignore_failed_channels.\n", v->value);
16873                continue;
16874             } else {
16875                return -1;
16876             }
16877          }
16878          ast_log(LOG_DEBUG, "Channel '%s' configured.\n", v->value);
16879       } else if (!strcasecmp(v->name, "ignore_failed_channels")) {
16880          confp->ignore_failed_channels = ast_true(v->value);
16881       } else if (!strcasecmp(v->name, "buffers")) {
16882          if (parse_buffers_policy(v->value, &confp->chan.buf_no, &confp->chan.buf_policy)) {
16883             ast_log(LOG_WARNING, "Using default buffer policy.\n");
16884             confp->chan.buf_no = numbufs;
16885             confp->chan.buf_policy = DAHDI_POLICY_IMMEDIATE;
16886          }
16887       } else if (!strcasecmp(v->name, "faxbuffers")) {
16888          if (!parse_buffers_policy(v->value, &confp->chan.faxbuf_no, &confp->chan.faxbuf_policy)) {
16889             confp->chan.usefaxbuffers = 1;
16890          }
16891       } else if (!strcasecmp(v->name, "dahdichan")) {
16892          /* Only process the last dahdichan value. */
16893          dahdichan = v;
16894       } else if (!strcasecmp(v->name, "usedistinctiveringdetection")) {
16895          usedistinctiveringdetection = ast_true(v->value);
16896       } else if (!strcasecmp(v->name, "distinctiveringaftercid")) {
16897          distinctiveringaftercid = ast_true(v->value);
16898       } else if (!strcasecmp(v->name, "dring1context")) {
16899          ast_copy_string(confp->chan.drings.ringContext[0].contextData,v->value,sizeof(confp->chan.drings.ringContext[0].contextData));
16900       } else if (!strcasecmp(v->name, "dring2context")) {
16901          ast_copy_string(confp->chan.drings.ringContext[1].contextData,v->value,sizeof(confp->chan.drings.ringContext[1].contextData));
16902       } else if (!strcasecmp(v->name, "dring3context")) {
16903          ast_copy_string(confp->chan.drings.ringContext[2].contextData,v->value,sizeof(confp->chan.drings.ringContext[2].contextData));
16904       } else if (!strcasecmp(v->name, "dring1range")) {
16905          confp->chan.drings.ringnum[0].range = atoi(v->value);
16906       } else if (!strcasecmp(v->name, "dring2range")) {
16907          confp->chan.drings.ringnum[1].range = atoi(v->value);
16908       } else if (!strcasecmp(v->name, "dring3range")) {
16909          confp->chan.drings.ringnum[2].range = atoi(v->value);
16910       } else if (!strcasecmp(v->name, "dring1")) {
16911          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]);
16912       } else if (!strcasecmp(v->name, "dring2")) {
16913          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]);
16914       } else if (!strcasecmp(v->name, "dring3")) {
16915          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]);
16916       } else if (!strcasecmp(v->name, "usecallerid")) {
16917          confp->chan.use_callerid = ast_true(v->value);
16918       } else if (!strcasecmp(v->name, "cidsignalling")) {
16919          if (!strcasecmp(v->value, "bell"))
16920             confp->chan.cid_signalling = CID_SIG_BELL;
16921          else if (!strcasecmp(v->value, "v23"))
16922             confp->chan.cid_signalling = CID_SIG_V23;
16923          else if (!strcasecmp(v->value, "dtmf"))
16924             confp->chan.cid_signalling = CID_SIG_DTMF;
16925          else if (!strcasecmp(v->value, "smdi"))
16926             confp->chan.cid_signalling = CID_SIG_SMDI;
16927          else if (!strcasecmp(v->value, "v23_jp"))
16928             confp->chan.cid_signalling = CID_SIG_V23_JP;
16929          else if (ast_true(v->value))
16930             confp->chan.cid_signalling = CID_SIG_BELL;
16931       } else if (!strcasecmp(v->name, "cidstart")) {
16932          if (!strcasecmp(v->value, "ring"))
16933             confp->chan.cid_start = CID_START_RING;
16934          else if (!strcasecmp(v->value, "polarity_in"))
16935             confp->chan.cid_start = CID_START_POLARITY_IN;
16936          else if (!strcasecmp(v->value, "polarity"))
16937             confp->chan.cid_start = CID_START_POLARITY;
16938          else if (!strcasecmp(v->value, "dtmf"))
16939             confp->chan.cid_start = CID_START_DTMF_NOALERT;
16940          else if (ast_true(v->value))
16941             confp->chan.cid_start = CID_START_RING;
16942       } else if (!strcasecmp(v->name, "threewaycalling")) {
16943          confp->chan.threewaycalling = ast_true(v->value);
16944       } else if (!strcasecmp(v->name, "cancallforward")) {
16945          confp->chan.cancallforward = ast_true(v->value);
16946       } else if (!strcasecmp(v->name, "relaxdtmf")) {
16947          if (ast_true(v->value))
16948             confp->chan.dtmfrelax = DSP_DIGITMODE_RELAXDTMF;
16949          else
16950             confp->chan.dtmfrelax = 0;
16951       } else if (!strcasecmp(v->name, "mailbox")) {
16952          ast_copy_string(confp->chan.mailbox, v->value, sizeof(confp->chan.mailbox));
16953       } else if (!strcasecmp(v->name, "hasvoicemail")) {
16954          if (ast_true(v->value) && ast_strlen_zero(confp->chan.mailbox)) {
16955             ast_copy_string(confp->chan.mailbox, cat, sizeof(confp->chan.mailbox));
16956          }
16957       } else if (!strcasecmp(v->name, "adsi")) {
16958          confp->chan.adsi = ast_true(v->value);
16959       } else if (!strcasecmp(v->name, "usesmdi")) {
16960          confp->chan.use_smdi = ast_true(v->value);
16961       } else if (!strcasecmp(v->name, "smdiport")) {
16962          ast_copy_string(confp->smdi_port, v->value, sizeof(confp->smdi_port));
16963       } else if (!strcasecmp(v->name, "transfer")) {
16964          confp->chan.transfer = ast_true(v->value);
16965       } else if (!strcasecmp(v->name, "canpark")) {
16966          confp->chan.canpark = ast_true(v->value);
16967       } else if (!strcasecmp(v->name, "echocancelwhenbridged")) {
16968          confp->chan.echocanbridged = ast_true(v->value);
16969       } else if (!strcasecmp(v->name, "busydetect")) {
16970          confp->chan.busydetect = ast_true(v->value);
16971       } else if (!strcasecmp(v->name, "busycount")) {
16972          confp->chan.busycount = atoi(v->value);
16973       } else if (!strcasecmp(v->name, "busypattern")) {
16974          if (sscanf(v->value, "%30d,%30d", &confp->chan.busy_tonelength, &confp->chan.busy_quietlength) != 2) {
16975             ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength,quietlength at line %d.\n", v->lineno);
16976          }
16977       } else if (!strcasecmp(v->name, "callprogress")) {
16978          confp->chan.callprogress &= ~CALLPROGRESS_PROGRESS;
16979          if (ast_true(v->value))
16980             confp->chan.callprogress |= CALLPROGRESS_PROGRESS;
16981       } else if (!strcasecmp(v->name, "waitfordialtone")) {
16982          confp->chan.waitfordialtone = atoi(v->value);
16983       } else if (!strcasecmp(v->name, "faxdetect")) {
16984          confp->chan.callprogress &= ~CALLPROGRESS_FAX;
16985          if (!strcasecmp(v->value, "incoming")) {
16986             confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING;
16987          } else if (!strcasecmp(v->value, "outgoing")) {
16988             confp->chan.callprogress |= CALLPROGRESS_FAX_OUTGOING;
16989          } else if (!strcasecmp(v->value, "both") || ast_true(v->value))
16990             confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING;
16991       } else if (!strcasecmp(v->name, "echocancel")) {
16992          process_echocancel(confp, v->value, v->lineno);
16993       } else if (!strcasecmp(v->name, "echotraining")) {
16994          if (sscanf(v->value, "%30d", &y) == 1) {
16995             if ((y < 10) || (y > 4000)) {
16996                ast_log(LOG_WARNING, "Echo training time must be within the range of 10 to 4000 ms at line %d.\n", v->lineno);
16997             } else {
16998                confp->chan.echotraining = y;
16999             }
17000          } else if (ast_true(v->value)) {
17001             confp->chan.echotraining = 400;
17002          } else
17003             confp->chan.echotraining = 0;
17004       } else if (!strcasecmp(v->name, "hidecallerid")) {
17005          confp->chan.hidecallerid = ast_true(v->value);
17006       } else if (!strcasecmp(v->name, "hidecalleridname")) {
17007          confp->chan.hidecalleridname = ast_true(v->value);
17008       } else if (!strcasecmp(v->name, "pulsedial")) {
17009          confp->chan.pulse = ast_true(v->value);
17010       } else if (!strcasecmp(v->name, "callreturn")) {
17011          confp->chan.callreturn = ast_true(v->value);
17012       } else if (!strcasecmp(v->name, "callwaiting")) {
17013          confp->chan.callwaiting = ast_true(v->value);
17014       } else if (!strcasecmp(v->name, "callwaitingcallerid")) {
17015          confp->chan.callwaitingcallerid = ast_true(v->value);
17016       } else if (!strcasecmp(v->name, "context")) {
17017          ast_copy_string(confp->chan.context, v->value, sizeof(confp->chan.context));
17018       } else if (!strcasecmp(v->name, "language")) {
17019          ast_copy_string(confp->chan.language, v->value, sizeof(confp->chan.language));
17020       } else if (!strcasecmp(v->name, "progzone")) {
17021          ast_copy_string(progzone, v->value, sizeof(progzone));
17022       } else if (!strcasecmp(v->name, "mohinterpret")
17023          ||!strcasecmp(v->name, "musiconhold") || !strcasecmp(v->name, "musicclass")) {
17024          ast_copy_string(confp->chan.mohinterpret, v->value, sizeof(confp->chan.mohinterpret));
17025       } else if (!strcasecmp(v->name, "mohsuggest")) {
17026          ast_copy_string(confp->chan.mohsuggest, v->value, sizeof(confp->chan.mohsuggest));
17027       } else if (!strcasecmp(v->name, "parkinglot")) {
17028          ast_copy_string(confp->chan.parkinglot, v->value, sizeof(confp->chan.parkinglot));
17029       } else if (!strcasecmp(v->name, "stripmsd")) {
17030          ast_log(LOG_NOTICE, "Configuration option \"%s\" has been deprecated. Please use dialplan instead\n", v->name);
17031          confp->chan.stripmsd = atoi(v->value);
17032       } else if (!strcasecmp(v->name, "jitterbuffers")) {
17033          numbufs = atoi(v->value);
17034       } else if (!strcasecmp(v->name, "group")) {
17035          confp->chan.group = ast_get_group(v->value);
17036       } else if (!strcasecmp(v->name, "callgroup")) {
17037          if (!strcasecmp(v->value, "none"))
17038             confp->chan.callgroup = 0;
17039          else
17040             confp->chan.callgroup = ast_get_group(v->value);
17041       } else if (!strcasecmp(v->name, "pickupgroup")) {
17042          if (!strcasecmp(v->value, "none"))
17043             confp->chan.pickupgroup = 0;
17044          else
17045             confp->chan.pickupgroup = ast_get_group(v->value);
17046       } else if (!strcasecmp(v->name, "setvar")) {
17047          char *varname = ast_strdupa(v->value), *varval = NULL;
17048          struct ast_variable *tmpvar;
17049          if (varname && (varval = strchr(varname, '='))) {
17050             *varval++ = '\0';
17051             if ((tmpvar = ast_variable_new(varname, varval, ""))) {
17052                tmpvar->next = confp->chan.vars;
17053                confp->chan.vars = tmpvar;
17054             }
17055          }
17056       } else if (!strcasecmp(v->name, "immediate")) {
17057          confp->chan.immediate = ast_true(v->value);
17058       } else if (!strcasecmp(v->name, "transfertobusy")) {
17059          confp->chan.transfertobusy = ast_true(v->value);
17060       } else if (!strcasecmp(v->name, "mwimonitor")) {
17061          confp->chan.mwimonitor_neon = 0;
17062          confp->chan.mwimonitor_fsk = 0;
17063          confp->chan.mwimonitor_rpas = 0;
17064          if (strcasestr(v->value, "fsk")) {
17065             confp->chan.mwimonitor_fsk = 1;
17066          }
17067          if (strcasestr(v->value, "rpas")) {
17068             confp->chan.mwimonitor_rpas = 1;
17069          }
17070          if (strcasestr(v->value, "neon")) {
17071             confp->chan.mwimonitor_neon = 1;
17072          }
17073          /* If set to true or yes, assume that simple fsk is desired */
17074          if (ast_true(v->value)) {
17075             confp->chan.mwimonitor_fsk = 1;
17076          }
17077       } else if (!strcasecmp(v->name, "cid_rxgain")) {
17078          if (sscanf(v->value, "%30f", &confp->chan.cid_rxgain) != 1) {
17079             ast_log(LOG_WARNING, "Invalid cid_rxgain: %s at line %d.\n", v->value, v->lineno);
17080          }
17081       } else if (!strcasecmp(v->name, "rxgain")) {
17082          if (sscanf(v->value, "%30f", &confp->chan.rxgain) != 1) {
17083             ast_log(LOG_WARNING, "Invalid rxgain: %s at line %d.\n", v->value, v->lineno);
17084          }
17085       } else if (!strcasecmp(v->name, "txgain")) {
17086          if (sscanf(v->value, "%30f", &confp->chan.txgain) != 1) {
17087             ast_log(LOG_WARNING, "Invalid txgain: %s at line %d.\n", v->value, v->lineno);
17088          }
17089       } else if (!strcasecmp(v->name, "txdrc")) {
17090          if (sscanf(v->value, "%f", &confp->chan.txdrc) != 1) {
17091             ast_log(LOG_WARNING, "Invalid txdrc: %s\n", v->value);
17092          }
17093       } else if (!strcasecmp(v->name, "rxdrc")) {
17094          if (sscanf(v->value, "%f", &confp->chan.rxdrc) != 1) {
17095             ast_log(LOG_WARNING, "Invalid rxdrc: %s\n", v->value);
17096          }
17097       } else if (!strcasecmp(v->name, "tonezone")) {
17098          if (sscanf(v->value, "%30d", &confp->chan.tonezone) != 1) {
17099             ast_log(LOG_WARNING, "Invalid tonezone: %s at line %d.\n", v->value, v->lineno);
17100          }
17101       } else if (!strcasecmp(v->name, "callerid")) {
17102          if (!strcasecmp(v->value, "asreceived")) {
17103             confp->chan.cid_num[0] = '\0';
17104             confp->chan.cid_name[0] = '\0';
17105          } else {
17106             ast_callerid_split(v->value, confp->chan.cid_name, sizeof(confp->chan.cid_name), confp->chan.cid_num, sizeof(confp->chan.cid_num));
17107          }
17108       } else if (!strcasecmp(v->name, "fullname")) {
17109          ast_copy_string(confp->chan.cid_name, v->value, sizeof(confp->chan.cid_name));
17110       } else if (!strcasecmp(v->name, "cid_number")) {
17111          ast_copy_string(confp->chan.cid_num, v->value, sizeof(confp->chan.cid_num));
17112       } else if (!strcasecmp(v->name, "cid_tag")) {
17113          ast_copy_string(confp->chan.cid_tag, v->value, sizeof(confp->chan.cid_tag));
17114       } else if (!strcasecmp(v->name, "useincomingcalleridondahditransfer")) {
17115          confp->chan.dahditrcallerid = ast_true(v->value);
17116       } else if (!strcasecmp(v->name, "restrictcid")) {
17117          confp->chan.restrictcid = ast_true(v->value);
17118       } else if (!strcasecmp(v->name, "usecallingpres")) {
17119          confp->chan.use_callingpres = ast_true(v->value);
17120       } else if (!strcasecmp(v->name, "accountcode")) {
17121          ast_copy_string(confp->chan.accountcode, v->value, sizeof(confp->chan.accountcode));
17122       } else if (!strcasecmp(v->name, "amaflags")) {
17123          y = ast_cdr_amaflags2int(v->value);
17124          if (y < 0)
17125             ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d.\n", v->value, v->lineno);
17126          else
17127             confp->chan.amaflags = y;
17128       } else if (!strcasecmp(v->name, "polarityonanswerdelay")) {
17129          confp->chan.polarityonanswerdelay = atoi(v->value);
17130       } else if (!strcasecmp(v->name, "answeronpolarityswitch")) {
17131          confp->chan.answeronpolarityswitch = ast_true(v->value);
17132       } else if (!strcasecmp(v->name, "hanguponpolarityswitch")) {
17133          confp->chan.hanguponpolarityswitch = ast_true(v->value);
17134       } else if (!strcasecmp(v->name, "sendcalleridafter")) {
17135          confp->chan.sendcalleridafter = atoi(v->value);
17136       } else if (!strcasecmp(v->name, "mwimonitornotify")) {
17137          ast_copy_string(mwimonitornotify, v->value, sizeof(mwimonitornotify));
17138       } else if (ast_cc_is_config_param(v->name)) {
17139          ast_cc_set_param(confp->chan.cc_params, v->name, v->value);
17140       } else if (!strcasecmp(v->name, "mwisendtype")) {
17141 #ifndef HAVE_DAHDI_LINEREVERSE_VMWI  /* backward compatibility for older dahdi VMWI implementation */
17142          if (!strcasecmp(v->value, "rpas")) { /* Ring Pulse Alert Signal */
17143             mwisend_rpas = 1;
17144          } else {
17145             mwisend_rpas = 0;
17146          }
17147 #else
17148          /* Default is fsk, to turn it off you must specify nofsk */
17149          memset(&confp->chan.mwisend_setting, 0, sizeof(confp->chan.mwisend_setting));
17150          if (strcasestr(v->value, "nofsk")) {      /* NoFSK */
17151             confp->chan.mwisend_fsk = 0;
17152          } else {             /* Default FSK */
17153             confp->chan.mwisend_fsk = 1;
17154          }
17155          if (strcasestr(v->value, "rpas")) {       /* Ring Pulse Alert Signal, normally followed by FSK */
17156             confp->chan.mwisend_rpas = 1;
17157          } else {
17158             confp->chan.mwisend_rpas = 0;
17159          }
17160          if (strcasestr(v->value, "lrev")) {       /* Line Reversal */
17161             confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_LREV;
17162          }
17163          if (strcasestr(v->value, "hvdc")) {       /* HV 90VDC */
17164             confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_HVDC;
17165          }
17166          if ( (strcasestr(v->value, "neon")) || (strcasestr(v->value, "hvac")) ){   /* 90V DC pulses */
17167             confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_HVAC;
17168          }
17169 #endif
17170       } else if (reload != 1) {
17171           if (!strcasecmp(v->name, "signalling") || !strcasecmp(v->name, "signaling")) {
17172             int orig_radio = confp->chan.radio;
17173             int orig_outsigmod = confp->chan.outsigmod;
17174             int orig_auto = confp->is_sig_auto;
17175 
17176             confp->chan.radio = 0;
17177             confp->chan.outsigmod = -1;
17178             confp->is_sig_auto = 0;
17179             if (!strcasecmp(v->value, "em")) {
17180                confp->chan.sig = SIG_EM;
17181             } else if (!strcasecmp(v->value, "em_e1")) {
17182                confp->chan.sig = SIG_EM_E1;
17183             } else if (!strcasecmp(v->value, "em_w")) {
17184                confp->chan.sig = SIG_EMWINK;
17185             } else if (!strcasecmp(v->value, "fxs_ls")) {
17186                confp->chan.sig = SIG_FXSLS;
17187             } else if (!strcasecmp(v->value, "fxs_gs")) {
17188                confp->chan.sig = SIG_FXSGS;
17189             } else if (!strcasecmp(v->value, "fxs_ks")) {
17190                confp->chan.sig = SIG_FXSKS;
17191             } else if (!strcasecmp(v->value, "fxo_ls")) {
17192                confp->chan.sig = SIG_FXOLS;
17193             } else if (!strcasecmp(v->value, "fxo_gs")) {
17194                confp->chan.sig = SIG_FXOGS;
17195             } else if (!strcasecmp(v->value, "fxo_ks")) {
17196                confp->chan.sig = SIG_FXOKS;
17197             } else if (!strcasecmp(v->value, "fxs_rx")) {
17198                confp->chan.sig = SIG_FXSKS;
17199                confp->chan.radio = 1;
17200             } else if (!strcasecmp(v->value, "fxo_rx")) {
17201                confp->chan.sig = SIG_FXOLS;
17202                confp->chan.radio = 1;
17203             } else if (!strcasecmp(v->value, "fxs_tx")) {
17204                confp->chan.sig = SIG_FXSLS;
17205                confp->chan.radio = 1;
17206             } else if (!strcasecmp(v->value, "fxo_tx")) {
17207                confp->chan.sig = SIG_FXOGS;
17208                confp->chan.radio = 1;
17209             } else if (!strcasecmp(v->value, "em_rx")) {
17210                confp->chan.sig = SIG_EM;
17211                confp->chan.radio = 1;
17212             } else if (!strcasecmp(v->value, "em_tx")) {
17213                confp->chan.sig = SIG_EM;
17214                confp->chan.radio = 1;
17215             } else if (!strcasecmp(v->value, "em_rxtx")) {
17216                confp->chan.sig = SIG_EM;
17217                confp->chan.radio = 2;
17218             } else if (!strcasecmp(v->value, "em_txrx")) {
17219                confp->chan.sig = SIG_EM;
17220                confp->chan.radio = 2;
17221             } else if (!strcasecmp(v->value, "sf")) {
17222                confp->chan.sig = SIG_SF;
17223             } else if (!strcasecmp(v->value, "sf_w")) {
17224                confp->chan.sig = SIG_SFWINK;
17225             } else if (!strcasecmp(v->value, "sf_featd")) {
17226                confp->chan.sig = SIG_FEATD;
17227             } else if (!strcasecmp(v->value, "sf_featdmf")) {
17228                confp->chan.sig = SIG_FEATDMF;
17229             } else if (!strcasecmp(v->value, "sf_featb")) {
17230                confp->chan.sig = SIG_SF_FEATB;
17231             } else if (!strcasecmp(v->value, "sf")) {
17232                confp->chan.sig = SIG_SF;
17233             } else if (!strcasecmp(v->value, "sf_rx")) {
17234                confp->chan.sig = SIG_SF;
17235                confp->chan.radio = 1;
17236             } else if (!strcasecmp(v->value, "sf_tx")) {
17237                confp->chan.sig = SIG_SF;
17238                confp->chan.radio = 1;
17239             } else if (!strcasecmp(v->value, "sf_rxtx")) {
17240                confp->chan.sig = SIG_SF;
17241                confp->chan.radio = 2;
17242             } else if (!strcasecmp(v->value, "sf_txrx")) {
17243                confp->chan.sig = SIG_SF;
17244                confp->chan.radio = 2;
17245             } else if (!strcasecmp(v->value, "featd")) {
17246                confp->chan.sig = SIG_FEATD;
17247             } else if (!strcasecmp(v->value, "featdmf")) {
17248                confp->chan.sig = SIG_FEATDMF;
17249             } else if (!strcasecmp(v->value, "featdmf_ta")) {
17250                confp->chan.sig = SIG_FEATDMF_TA;
17251             } else if (!strcasecmp(v->value, "e911")) {
17252                confp->chan.sig = SIG_E911;
17253             } else if (!strcasecmp(v->value, "fgccama")) {
17254                confp->chan.sig = SIG_FGC_CAMA;
17255             } else if (!strcasecmp(v->value, "fgccamamf")) {
17256                confp->chan.sig = SIG_FGC_CAMAMF;
17257             } else if (!strcasecmp(v->value, "featb")) {
17258                confp->chan.sig = SIG_FEATB;
17259 #ifdef HAVE_PRI
17260             } else if (!strcasecmp(v->value, "pri_net")) {
17261                confp->chan.sig = SIG_PRI;
17262                confp->pri.pri.nodetype = PRI_NETWORK;
17263             } else if (!strcasecmp(v->value, "pri_cpe")) {
17264                confp->chan.sig = SIG_PRI;
17265                confp->pri.pri.nodetype = PRI_CPE;
17266             } else if (!strcasecmp(v->value, "bri_cpe")) {
17267                confp->chan.sig = SIG_BRI;
17268                confp->pri.pri.nodetype = PRI_CPE;
17269             } else if (!strcasecmp(v->value, "bri_net")) {
17270                confp->chan.sig = SIG_BRI;
17271                confp->pri.pri.nodetype = PRI_NETWORK;
17272             } else if (!strcasecmp(v->value, "bri_cpe_ptmp")) {
17273                confp->chan.sig = SIG_BRI_PTMP;
17274                confp->pri.pri.nodetype = PRI_CPE;
17275             } else if (!strcasecmp(v->value, "bri_net_ptmp")) {
17276 #if defined(HAVE_PRI_CALL_HOLD)
17277                confp->chan.sig = SIG_BRI_PTMP;
17278                confp->pri.pri.nodetype = PRI_NETWORK;
17279 #else
17280                ast_log(LOG_WARNING, "How cool would it be if someone implemented this mode!  For now, sucks for you. (line %d)\n", v->lineno);
17281 #endif   /* !defined(HAVE_PRI_CALL_HOLD) */
17282 #endif
17283 #if defined(HAVE_SS7)
17284             } else if (!strcasecmp(v->value, "ss7")) {
17285                confp->chan.sig = SIG_SS7;
17286 #endif   /* defined(HAVE_SS7) */
17287 #ifdef HAVE_OPENR2
17288             } else if (!strcasecmp(v->value, "mfcr2")) {
17289                confp->chan.sig = SIG_MFCR2;
17290 #endif
17291             } else if (!strcasecmp(v->value, "auto")) {
17292                confp->is_sig_auto = 1;
17293             } else {
17294                confp->chan.outsigmod = orig_outsigmod;
17295                confp->chan.radio = orig_radio;
17296                confp->is_sig_auto = orig_auto;
17297                ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
17298             }
17299           } else if (!strcasecmp(v->name, "outsignalling") || !strcasecmp(v->name, "outsignaling")) {
17300             if (!strcasecmp(v->value, "em")) {
17301                confp->chan.outsigmod = SIG_EM;
17302             } else if (!strcasecmp(v->value, "em_e1")) {
17303                confp->chan.outsigmod = SIG_EM_E1;
17304             } else if (!strcasecmp(v->value, "em_w")) {
17305                confp->chan.outsigmod = SIG_EMWINK;
17306             } else if (!strcasecmp(v->value, "sf")) {
17307                confp->chan.outsigmod = SIG_SF;
17308             } else if (!strcasecmp(v->value, "sf_w")) {
17309                confp->chan.outsigmod = SIG_SFWINK;
17310             } else if (!strcasecmp(v->value, "sf_featd")) {
17311                confp->chan.outsigmod = SIG_FEATD;
17312             } else if (!strcasecmp(v->value, "sf_featdmf")) {
17313                confp->chan.outsigmod = SIG_FEATDMF;
17314             } else if (!strcasecmp(v->value, "sf_featb")) {
17315                confp->chan.outsigmod = SIG_SF_FEATB;
17316             } else if (!strcasecmp(v->value, "sf")) {
17317                confp->chan.outsigmod = SIG_SF;
17318             } else if (!strcasecmp(v->value, "featd")) {
17319                confp->chan.outsigmod = SIG_FEATD;
17320             } else if (!strcasecmp(v->value, "featdmf")) {
17321                confp->chan.outsigmod = SIG_FEATDMF;
17322             } else if (!strcasecmp(v->value, "featdmf_ta")) {
17323                confp->chan.outsigmod = SIG_FEATDMF_TA;
17324             } else if (!strcasecmp(v->value, "e911")) {
17325                confp->chan.outsigmod = SIG_E911;
17326             } else if (!strcasecmp(v->value, "fgccama")) {
17327                confp->chan.outsigmod = SIG_FGC_CAMA;
17328             } else if (!strcasecmp(v->value, "fgccamamf")) {
17329                confp->chan.outsigmod = SIG_FGC_CAMAMF;
17330             } else if (!strcasecmp(v->value, "featb")) {
17331                confp->chan.outsigmod = SIG_FEATB;
17332             } else {
17333                ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
17334             }
17335 #ifdef HAVE_PRI
17336          } else if (!strcasecmp(v->name, "pridialplan")) {
17337             if (!strcasecmp(v->value, "national")) {
17338                confp->pri.pri.dialplan = PRI_NATIONAL_ISDN + 1;
17339             } else if (!strcasecmp(v->value, "unknown")) {
17340                confp->pri.pri.dialplan = PRI_UNKNOWN + 1;
17341             } else if (!strcasecmp(v->value, "private")) {
17342                confp->pri.pri.dialplan = PRI_PRIVATE + 1;
17343             } else if (!strcasecmp(v->value, "international")) {
17344                confp->pri.pri.dialplan = PRI_INTERNATIONAL_ISDN + 1;
17345             } else if (!strcasecmp(v->value, "local")) {
17346                confp->pri.pri.dialplan = PRI_LOCAL_ISDN + 1;
17347             } else if (!strcasecmp(v->value, "dynamic")) {
17348                confp->pri.pri.dialplan = -1;
17349             } else if (!strcasecmp(v->value, "redundant")) {
17350                confp->pri.pri.dialplan = -2;
17351             } else {
17352                ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno);
17353             }
17354          } else if (!strcasecmp(v->name, "prilocaldialplan")) {
17355             if (!strcasecmp(v->value, "national")) {
17356                confp->pri.pri.localdialplan = PRI_NATIONAL_ISDN + 1;
17357             } else if (!strcasecmp(v->value, "unknown")) {
17358                confp->pri.pri.localdialplan = PRI_UNKNOWN + 1;
17359             } else if (!strcasecmp(v->value, "private")) {
17360                confp->pri.pri.localdialplan = PRI_PRIVATE + 1;
17361             } else if (!strcasecmp(v->value, "international")) {
17362                confp->pri.pri.localdialplan = PRI_INTERNATIONAL_ISDN + 1;
17363             } else if (!strcasecmp(v->value, "local")) {
17364                confp->pri.pri.localdialplan = PRI_LOCAL_ISDN + 1;
17365             } else if (!strcasecmp(v->value, "dynamic")) {
17366                confp->pri.pri.localdialplan = -1;
17367             } else if (!strcasecmp(v->value, "redundant")) {
17368                confp->pri.pri.localdialplan = -2;
17369             } else {
17370                ast_log(LOG_WARNING, "Unknown PRI localdialplan '%s' at line %d.\n", v->value, v->lineno);
17371             }
17372          } else if (!strcasecmp(v->name, "switchtype")) {
17373             if (!strcasecmp(v->value, "national"))
17374                confp->pri.pri.switchtype = PRI_SWITCH_NI2;
17375             else if (!strcasecmp(v->value, "ni1"))
17376                confp->pri.pri.switchtype = PRI_SWITCH_NI1;
17377             else if (!strcasecmp(v->value, "dms100"))
17378                confp->pri.pri.switchtype = PRI_SWITCH_DMS100;
17379             else if (!strcasecmp(v->value, "4ess"))
17380                confp->pri.pri.switchtype = PRI_SWITCH_ATT4ESS;
17381             else if (!strcasecmp(v->value, "5ess"))
17382                confp->pri.pri.switchtype = PRI_SWITCH_LUCENT5E;
17383             else if (!strcasecmp(v->value, "euroisdn"))
17384                confp->pri.pri.switchtype = PRI_SWITCH_EUROISDN_E1;
17385             else if (!strcasecmp(v->value, "qsig"))
17386                confp->pri.pri.switchtype = PRI_SWITCH_QSIG;
17387             else {
17388                ast_log(LOG_ERROR, "Unknown switchtype '%s' at line %d.\n", v->value, v->lineno);
17389                return -1;
17390             }
17391          } else if (!strcasecmp(v->name, "msn")) {
17392             ast_copy_string(confp->pri.pri.msn_list, v->value,
17393                sizeof(confp->pri.pri.msn_list));
17394          } else if (!strcasecmp(v->name, "nsf")) {
17395             if (!strcasecmp(v->value, "sdn"))
17396                confp->pri.pri.nsf = PRI_NSF_SDN;
17397             else if (!strcasecmp(v->value, "megacom"))
17398                confp->pri.pri.nsf = PRI_NSF_MEGACOM;
17399             else if (!strcasecmp(v->value, "tollfreemegacom"))
17400                confp->pri.pri.nsf = PRI_NSF_TOLL_FREE_MEGACOM;
17401             else if (!strcasecmp(v->value, "accunet"))
17402                confp->pri.pri.nsf = PRI_NSF_ACCUNET;
17403             else if (!strcasecmp(v->value, "none"))
17404                confp->pri.pri.nsf = PRI_NSF_NONE;
17405             else {
17406                ast_log(LOG_WARNING, "Unknown network-specific facility '%s' at line %d.\n", v->value, v->lineno);
17407                confp->pri.pri.nsf = PRI_NSF_NONE;
17408             }
17409          } else if (!strcasecmp(v->name, "priindication")) {
17410             if (!strcasecmp(v->value, "outofband"))
17411                confp->chan.priindication_oob = 1;
17412             else if (!strcasecmp(v->value, "inband"))
17413                confp->chan.priindication_oob = 0;
17414             else
17415                ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d.\n",
17416                   v->value, v->lineno);
17417          } else if (!strcasecmp(v->name, "priexclusive")) {
17418             confp->chan.priexclusive = ast_true(v->value);
17419          } else if (!strcasecmp(v->name, "internationalprefix")) {
17420             ast_copy_string(confp->pri.pri.internationalprefix, v->value, sizeof(confp->pri.pri.internationalprefix));
17421          } else if (!strcasecmp(v->name, "nationalprefix")) {
17422             ast_copy_string(confp->pri.pri.nationalprefix, v->value, sizeof(confp->pri.pri.nationalprefix));
17423          } else if (!strcasecmp(v->name, "localprefix")) {
17424             ast_copy_string(confp->pri.pri.localprefix, v->value, sizeof(confp->pri.pri.localprefix));
17425          } else if (!strcasecmp(v->name, "privateprefix")) {
17426             ast_copy_string(confp->pri.pri.privateprefix, v->value, sizeof(confp->pri.pri.privateprefix));
17427          } else if (!strcasecmp(v->name, "unknownprefix")) {
17428             ast_copy_string(confp->pri.pri.unknownprefix, v->value, sizeof(confp->pri.pri.unknownprefix));
17429          } else if (!strcasecmp(v->name, "resetinterval")) {
17430             if (!strcasecmp(v->value, "never"))
17431                confp->pri.pri.resetinterval = -1;
17432             else if (atoi(v->value) >= 60)
17433                confp->pri.pri.resetinterval = atoi(v->value);
17434             else
17435                ast_log(LOG_WARNING, "'%s' is not a valid reset interval, should be >= 60 seconds or 'never' at line %d.\n",
17436                   v->value, v->lineno);
17437          } else if (!strcasecmp(v->name, "minunused")) {
17438             confp->pri.pri.minunused = atoi(v->value);
17439          } else if (!strcasecmp(v->name, "minidle")) {
17440             confp->pri.pri.minidle = atoi(v->value);
17441          } else if (!strcasecmp(v->name, "idleext")) {
17442             ast_copy_string(confp->pri.pri.idleext, v->value, sizeof(confp->pri.pri.idleext));
17443          } else if (!strcasecmp(v->name, "idledial")) {
17444             ast_copy_string(confp->pri.pri.idledial, v->value, sizeof(confp->pri.pri.idledial));
17445          } else if (!strcasecmp(v->name, "overlapdial")) {
17446             if (ast_true(v->value)) {
17447                confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
17448             } else if (!strcasecmp(v->value, "incoming")) {
17449                confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_INCOMING;
17450             } else if (!strcasecmp(v->value, "outgoing")) {
17451                confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_OUTGOING;
17452             } else if (!strcasecmp(v->value, "both") || ast_true(v->value)) {
17453                confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
17454             } else {
17455                confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_NONE;
17456             }
17457 #ifdef HAVE_PRI_PROG_W_CAUSE
17458          } else if (!strcasecmp(v->name, "qsigchannelmapping")) {
17459             if (!strcasecmp(v->value, "logical")) {
17460                confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_LOGICAL;
17461             } else if (!strcasecmp(v->value, "physical")) {
17462                confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL;
17463             } else {
17464                confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL;
17465             }
17466 #endif
17467          } else if (!strcasecmp(v->name, "discardremoteholdretrieval")) {
17468             confp->pri.pri.discardremoteholdretrieval = ast_true(v->value);
17469 #if defined(HAVE_PRI_SERVICE_MESSAGES)
17470          } else if (!strcasecmp(v->name, "service_message_support")) {
17471             /* assuming switchtype for this channel group has been configured already */
17472             if ((confp->pri.pri.switchtype == PRI_SWITCH_ATT4ESS 
17473                || confp->pri.pri.switchtype == PRI_SWITCH_LUCENT5E
17474                || confp->pri.pri.switchtype == PRI_SWITCH_NI2) && ast_true(v->value)) {
17475                confp->pri.pri.enable_service_message_support = 1;
17476             } else {
17477                confp->pri.pri.enable_service_message_support = 0;
17478             }
17479 #endif   /* defined(HAVE_PRI_SERVICE_MESSAGES) */
17480 #ifdef HAVE_PRI_INBANDDISCONNECT
17481          } else if (!strcasecmp(v->name, "inbanddisconnect")) {
17482             confp->pri.pri.inbanddisconnect = ast_true(v->value);
17483 #endif
17484          } else if (!strcasecmp(v->name, "pritimer")) {
17485 #ifdef PRI_GETSET_TIMERS
17486             char tmp[20];
17487             char *timerc;
17488             char *c;
17489             int timer;
17490             int timeridx;
17491 
17492             ast_copy_string(tmp, v->value, sizeof(tmp));
17493             c = tmp;
17494             timerc = strsep(&c, ",");
17495             if (!ast_strlen_zero(timerc) && !ast_strlen_zero(c)) {
17496                timeridx = pri_timer2idx(timerc);
17497                timer = atoi(c);
17498                if (timeridx < 0 || PRI_MAX_TIMERS <= timeridx) {
17499                   ast_log(LOG_WARNING,
17500                      "'%s' is not a valid ISDN timer at line %d.\n", timerc,
17501                      v->lineno);
17502                } else if (!timer) {
17503                   ast_log(LOG_WARNING,
17504                      "'%s' is not a valid value for ISDN timer '%s' at line %d.\n",
17505                      c, timerc, v->lineno);
17506                } else {
17507                   confp->pri.pri.pritimers[timeridx] = timer;
17508                }
17509             } else {
17510                ast_log(LOG_WARNING,
17511                   "'%s' is not a valid ISDN timer configuration string at line %d.\n",
17512                   v->value, v->lineno);
17513             }
17514 #endif /* PRI_GETSET_TIMERS */
17515          } else if (!strcasecmp(v->name, "facilityenable")) {
17516             confp->pri.pri.facilityenable = ast_true(v->value);
17517 #if defined(HAVE_PRI_AOC_EVENTS)
17518          } else if (!strcasecmp(v->name, "aoc_enable")) {
17519             confp->pri.pri.aoc_passthrough_flag = 0;
17520             if (strchr(v->value, 's') || strchr(v->value, 'S')) {
17521                confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_S;
17522             }
17523             if (strchr(v->value, 'd') || strchr(v->value, 'D')) {
17524                confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_D;
17525             }
17526             if (strchr(v->value, 'e') || strchr(v->value, 'E')) {
17527                confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_E;
17528             }
17529          } else if (!strcasecmp(v->name, "aoce_delayhangup")) {
17530             confp->pri.pri.aoce_delayhangup = ast_true(v->value);
17531 #endif   /* defined(HAVE_PRI_AOC_EVENTS) */
17532 #if defined(HAVE_PRI_CALL_HOLD)
17533          } else if (!strcasecmp(v->name, "hold_disconnect_transfer")) {
17534             confp->pri.pri.hold_disconnect_transfer = ast_true(v->value);
17535 #endif   /* defined(HAVE_PRI_CALL_HOLD) */
17536 #if defined(HAVE_PRI_CCSS)
17537          } else if (!strcasecmp(v->name, "cc_ptmp_recall_mode")) {
17538             if (!strcasecmp(v->value, "global")) {
17539                confp->pri.pri.cc_ptmp_recall_mode = 0;/* globalRecall */
17540             } else if (!strcasecmp(v->value, "specific")) {
17541                confp->pri.pri.cc_ptmp_recall_mode = 1;/* specificRecall */
17542             } else {
17543                confp->pri.pri.cc_ptmp_recall_mode = 1;/* specificRecall */
17544             }
17545          } else if (!strcasecmp(v->name, "cc_qsig_signaling_link_req")) {
17546             if (!strcasecmp(v->value, "release")) {
17547                confp->pri.pri.cc_qsig_signaling_link_req = 0;/* release */
17548             } else if (!strcasecmp(v->value, "retain")) {
17549                confp->pri.pri.cc_qsig_signaling_link_req = 1;/* retain */
17550             } else if (!strcasecmp(v->value, "do_not_care")) {
17551                confp->pri.pri.cc_qsig_signaling_link_req = 2;/* do-not-care */
17552             } else {
17553                confp->pri.pri.cc_qsig_signaling_link_req = 1;/* retain */
17554             }
17555          } else if (!strcasecmp(v->name, "cc_qsig_signaling_link_rsp")) {
17556             if (!strcasecmp(v->value, "release")) {
17557                confp->pri.pri.cc_qsig_signaling_link_rsp = 0;/* release */
17558             } else if (!strcasecmp(v->value, "retain")) {
17559                confp->pri.pri.cc_qsig_signaling_link_rsp = 1;/* retain */
17560             } else {
17561                confp->pri.pri.cc_qsig_signaling_link_rsp = 1;/* retain */
17562             }
17563 #endif   /* defined(HAVE_PRI_CCSS) */
17564 #if defined(HAVE_PRI_CALL_WAITING)
17565          } else if (!strcasecmp(v->name, "max_call_waiting_calls")) {
17566             confp->pri.pri.max_call_waiting_calls = atoi(v->value);
17567             if (confp->pri.pri.max_call_waiting_calls < 0) {
17568                /* Negative values are not allowed. */
17569                confp->pri.pri.max_call_waiting_calls = 0;
17570             }
17571          } else if (!strcasecmp(v->name, "allow_call_waiting_calls")) {
17572             confp->pri.pri.allow_call_waiting_calls = ast_true(v->value);
17573 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
17574 #if defined(HAVE_PRI_MWI)
17575          } else if (!strcasecmp(v->name, "mwi_mailboxes")) {
17576             ast_copy_string(confp->pri.pri.mwi_mailboxes, v->value,
17577                sizeof(confp->pri.pri.mwi_mailboxes));
17578 #endif   /* defined(HAVE_PRI_MWI) */
17579          } else if (!strcasecmp(v->name, "append_msn_to_cid_tag")) {
17580             confp->pri.pri.append_msn_to_user_tag = ast_true(v->value);
17581 #if defined(HAVE_PRI_L2_PERSISTENCE)
17582          } else if (!strcasecmp(v->name, "layer2_persistence")) {
17583             if (!strcasecmp(v->value, "keep_up")) {
17584                confp->pri.pri.l2_persistence = PRI_L2_PERSISTENCE_KEEP_UP;
17585             } else if (!strcasecmp(v->value, "leave_down")) {
17586                confp->pri.pri.l2_persistence = PRI_L2_PERSISTENCE_LEAVE_DOWN;
17587             } else {
17588                confp->pri.pri.l2_persistence = PRI_L2_PERSISTENCE_DEFAULT;
17589             }
17590 #endif   /* defined(HAVE_PRI_L2_PERSISTENCE) */
17591 #endif /* HAVE_PRI */
17592 #if defined(HAVE_SS7)
17593          } else if (!strcasecmp(v->name, "ss7type")) {
17594             if (!strcasecmp(v->value, "itu")) {
17595                cur_ss7type = SS7_ITU;
17596             } else if (!strcasecmp(v->value, "ansi")) {
17597                cur_ss7type = SS7_ANSI;
17598             } else
17599                ast_log(LOG_WARNING, "'%s' is an unknown ss7 switch type at line %d.!\n", v->value, v->lineno);
17600          } else if (!strcasecmp(v->name, "linkset")) {
17601             cur_linkset = atoi(v->value);
17602          } else if (!strcasecmp(v->name, "pointcode")) {
17603             cur_pointcode = parse_pointcode(v->value);
17604          } else if (!strcasecmp(v->name, "adjpointcode")) {
17605             cur_adjpointcode = parse_pointcode(v->value);
17606          } else if (!strcasecmp(v->name, "defaultdpc")) {
17607             cur_defaultdpc = parse_pointcode(v->value);
17608          } else if (!strcasecmp(v->name, "cicbeginswith")) {
17609             cur_cicbeginswith = atoi(v->value);
17610          } else if (!strcasecmp(v->name, "networkindicator")) {
17611             if (!strcasecmp(v->value, "national"))
17612                cur_networkindicator = SS7_NI_NAT;
17613             else if (!strcasecmp(v->value, "national_spare"))
17614                cur_networkindicator = SS7_NI_NAT_SPARE;
17615             else if (!strcasecmp(v->value, "international"))
17616                cur_networkindicator = SS7_NI_INT;
17617             else if (!strcasecmp(v->value, "international_spare"))
17618                cur_networkindicator = SS7_NI_INT_SPARE;
17619             else
17620                cur_networkindicator = -1;
17621          } else if (!strcasecmp(v->name, "ss7_internationalprefix")) {
17622             ast_copy_string(confp->ss7.ss7.internationalprefix, v->value, sizeof(confp->ss7.ss7.internationalprefix));
17623          } else if (!strcasecmp(v->name, "ss7_nationalprefix")) {
17624             ast_copy_string(confp->ss7.ss7.nationalprefix, v->value, sizeof(confp->ss7.ss7.nationalprefix));
17625          } else if (!strcasecmp(v->name, "ss7_subscriberprefix")) {
17626             ast_copy_string(confp->ss7.ss7.subscriberprefix, v->value, sizeof(confp->ss7.ss7.subscriberprefix));
17627          } else if (!strcasecmp(v->name, "ss7_unknownprefix")) {
17628             ast_copy_string(confp->ss7.ss7.unknownprefix, v->value, sizeof(confp->ss7.ss7.unknownprefix));
17629          } else if (!strcasecmp(v->name, "ss7_called_nai")) {
17630             if (!strcasecmp(v->value, "national")) {
17631                confp->ss7.ss7.called_nai = SS7_NAI_NATIONAL;
17632             } else if (!strcasecmp(v->value, "international")) {
17633                confp->ss7.ss7.called_nai = SS7_NAI_INTERNATIONAL;
17634             } else if (!strcasecmp(v->value, "subscriber")) {
17635                confp->ss7.ss7.called_nai = SS7_NAI_SUBSCRIBER;
17636             } else if (!strcasecmp(v->value, "unknown")) {
17637                confp->ss7.ss7.called_nai = SS7_NAI_UNKNOWN;
17638             } else if (!strcasecmp(v->value, "dynamic")) {
17639                confp->ss7.ss7.called_nai = SS7_NAI_DYNAMIC;
17640             } else {
17641                ast_log(LOG_WARNING, "Unknown SS7 called_nai '%s' at line %d.\n", v->value, v->lineno);
17642             }
17643          } else if (!strcasecmp(v->name, "ss7_calling_nai")) {
17644             if (!strcasecmp(v->value, "national")) {
17645                confp->ss7.ss7.calling_nai = SS7_NAI_NATIONAL;
17646             } else if (!strcasecmp(v->value, "international")) {
17647                confp->ss7.ss7.calling_nai = SS7_NAI_INTERNATIONAL;
17648             } else if (!strcasecmp(v->value, "subscriber")) {
17649                confp->ss7.ss7.calling_nai = SS7_NAI_SUBSCRIBER;
17650             } else if (!strcasecmp(v->value, "unknown")) {
17651                confp->ss7.ss7.calling_nai = SS7_NAI_UNKNOWN;
17652             } else if (!strcasecmp(v->value, "dynamic")) {
17653                confp->ss7.ss7.calling_nai = SS7_NAI_DYNAMIC;
17654             } else {
17655                ast_log(LOG_WARNING, "Unknown SS7 calling_nai '%s' at line %d.\n", v->value, v->lineno);
17656             }
17657          } else if (!strcasecmp(v->name, "sigchan")) {
17658             int sigchan, res;
17659             sigchan = atoi(v->value);
17660             res = linkset_addsigchan(sigchan);
17661             if (res < 0)
17662                return -1;
17663 
17664          } else if (!strcasecmp(v->name, "ss7_explicitacm")) {
17665             struct dahdi_ss7 *link;
17666             link = ss7_resolve_linkset(cur_linkset);
17667             if (!link) {
17668                ast_log(LOG_ERROR, "Invalid linkset number.  Must be between 1 and %d\n", NUM_SPANS + 1);
17669                return -1;
17670             }
17671             if (ast_true(v->value))
17672                link->ss7.flags |= LINKSET_FLAG_EXPLICITACM;
17673 #endif   /* defined(HAVE_SS7) */
17674 #ifdef HAVE_OPENR2
17675          } else if (!strcasecmp(v->name, "mfcr2_advanced_protocol_file")) {
17676             ast_copy_string(confp->mfcr2.r2proto_file, v->value, sizeof(confp->mfcr2.r2proto_file));
17677             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);
17678          } else if (!strcasecmp(v->name, "mfcr2_logdir")) {
17679             ast_copy_string(confp->mfcr2.logdir, v->value, sizeof(confp->mfcr2.logdir));
17680          } else if (!strcasecmp(v->name, "mfcr2_variant")) {
17681             confp->mfcr2.variant = openr2_proto_get_variant(v->value);
17682             if (OR2_VAR_UNKNOWN == confp->mfcr2.variant) {
17683                ast_log(LOG_WARNING, "Unknown MFC/R2 variant '%s' at line %d, defaulting to ITU.\n", v->value, v->lineno);
17684                confp->mfcr2.variant = OR2_VAR_ITU;
17685             }
17686          } else if (!strcasecmp(v->name, "mfcr2_mfback_timeout")) {
17687             confp->mfcr2.mfback_timeout = atoi(v->value);
17688             if (!confp->mfcr2.mfback_timeout) {
17689                ast_log(LOG_WARNING, "MF timeout of 0? hum, I will protect you from your ignorance. Setting default.\n");
17690                confp->mfcr2.mfback_timeout = -1;
17691             } else if (confp->mfcr2.mfback_timeout > 0 && confp->mfcr2.mfback_timeout < 500) {
17692                ast_log(LOG_WARNING, "MF timeout less than 500ms is not recommended, you have been warned!\n");
17693             }
17694          } else if (!strcasecmp(v->name, "mfcr2_metering_pulse_timeout")) {
17695             confp->mfcr2.metering_pulse_timeout = atoi(v->value);
17696             if (confp->mfcr2.metering_pulse_timeout > 500) {
17697                ast_log(LOG_WARNING, "Metering pulse timeout greater than 500ms is not recommended, you have been warned!\n");
17698             }
17699          } else if (!strcasecmp(v->name, "mfcr2_get_ani_first")) {
17700             confp->mfcr2.get_ani_first = ast_true(v->value) ? 1 : 0;
17701          } else if (!strcasecmp(v->name, "mfcr2_double_answer")) {
17702             confp->mfcr2.double_answer = ast_true(v->value) ? 1 : 0;
17703          } else if (!strcasecmp(v->name, "mfcr2_charge_calls")) {
17704             confp->mfcr2.charge_calls = ast_true(v->value) ? 1 : 0;
17705          } else if (!strcasecmp(v->name, "mfcr2_accept_on_offer")) {
17706             confp->mfcr2.accept_on_offer = ast_true(v->value) ? 1 : 0;
17707          } else if (!strcasecmp(v->name, "mfcr2_allow_collect_calls")) {
17708             confp->mfcr2.allow_collect_calls = ast_true(v->value) ? 1 : 0;
17709          } else if (!strcasecmp(v->name, "mfcr2_forced_release")) {
17710             confp->mfcr2.forced_release = ast_true(v->value) ? 1 : 0;
17711          } else if (!strcasecmp(v->name, "mfcr2_immediate_accept")) {
17712             confp->mfcr2.immediate_accept = ast_true(v->value) ? 1 : 0;
17713 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
17714          } else if (!strcasecmp(v->name, "mfcr2_skip_category")) {
17715             confp->mfcr2.skip_category_request = ast_true(v->value) ? 1 : 0;
17716 #endif
17717          } else if (!strcasecmp(v->name, "mfcr2_call_files")) {
17718             confp->mfcr2.call_files = ast_true(v->value) ? 1 : 0;
17719          } else if (!strcasecmp(v->name, "mfcr2_max_ani")) {
17720             confp->mfcr2.max_ani = atoi(v->value);
17721             if (confp->mfcr2.max_ani >= AST_MAX_EXTENSION){
17722                confp->mfcr2.max_ani = AST_MAX_EXTENSION - 1;
17723             }
17724          } else if (!strcasecmp(v->name, "mfcr2_max_dnis")) {
17725             confp->mfcr2.max_dnis = atoi(v->value);
17726             if (confp->mfcr2.max_dnis >= AST_MAX_EXTENSION){
17727                confp->mfcr2.max_dnis = AST_MAX_EXTENSION - 1;
17728             }
17729          } else if (!strcasecmp(v->name, "mfcr2_category")) {
17730             confp->mfcr2.category = openr2_proto_get_category(v->value);
17731             if (OR2_CALLING_PARTY_CATEGORY_UNKNOWN == confp->mfcr2.category) {
17732                confp->mfcr2.category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER;
17733                ast_log(LOG_WARNING, "Invalid MFC/R2 caller category '%s' at line %d. Using national subscriber as default.\n",
17734                      v->value, v->lineno);
17735             }
17736          } else if (!strcasecmp(v->name, "mfcr2_logging")) {
17737             openr2_log_level_t tmplevel;
17738             char *clevel;
17739             char *logval = ast_strdupa(v->value);
17740             while (logval) {
17741                clevel = strsep(&logval,",");
17742                if (-1 == (tmplevel = openr2_log_get_level(clevel))) {
17743                   ast_log(LOG_WARNING, "Ignoring invalid logging level: '%s' at line %d.\n", clevel, v->lineno);
17744                   continue;
17745                }
17746                confp->mfcr2.loglevel |= tmplevel;
17747             }
17748 #endif /* HAVE_OPENR2 */
17749          } else if (!strcasecmp(v->name, "cadence")) {
17750             /* setup to scan our argument */
17751             int element_count, c[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
17752             int i;
17753             struct dahdi_ring_cadence new_cadence;
17754             int cid_location = -1;
17755             int firstcadencepos = 0;
17756             char original_args[80];
17757             int cadence_is_ok = 1;
17758 
17759             ast_copy_string(original_args, v->value, sizeof(original_args));
17760             /* 16 cadences allowed (8 pairs) */
17761             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]);
17762 
17763             /* Cadence must be even (on/off) */
17764             if (element_count % 2 == 1) {
17765                ast_log(LOG_ERROR, "Must be a silence duration for each ring duration: %s at line %d.\n", original_args, v->lineno);
17766                cadence_is_ok = 0;
17767             }
17768 
17769             /* Ring cadences cannot be negative */
17770             for (i = 0; i < element_count; i++) {
17771                if (c[i] == 0) {
17772                   ast_log(LOG_ERROR, "Ring or silence duration cannot be zero: %s at line %d.\n", original_args, v->lineno);
17773                   cadence_is_ok = 0;
17774                   break;
17775                } else if (c[i] < 0) {
17776                   if (i % 2 == 1) {
17777                      /* Silence duration, negative possibly okay */
17778                      if (cid_location == -1) {
17779                         cid_location = i;
17780                         c[i] *= -1;
17781                      } else {
17782                         ast_log(LOG_ERROR, "CID location specified twice: %s at line %d.\n", original_args, v->lineno);
17783                         cadence_is_ok = 0;
17784                         break;
17785                      }
17786                   } else {
17787                      if (firstcadencepos == 0) {
17788                         firstcadencepos = i; /* only recorded to avoid duplicate specification */
17789                                  /* duration will be passed negative to the DAHDI driver */
17790                      } else {
17791                          ast_log(LOG_ERROR, "First cadence position specified twice: %s at line %d.\n", original_args, v->lineno);
17792                         cadence_is_ok = 0;
17793                         break;
17794                      }
17795                   }
17796                }
17797             }
17798 
17799             /* Substitute our scanned cadence */
17800             for (i = 0; i < 16; i++) {
17801                new_cadence.ringcadence[i] = c[i];
17802             }
17803 
17804             if (cadence_is_ok) {
17805                /* ---we scanned it without getting annoyed; now some sanity checks--- */
17806                if (element_count < 2) {
17807                   ast_log(LOG_ERROR, "Minimum cadence is ring,pause: %s at line %d.\n", original_args, v->lineno);
17808                } else {
17809                   if (cid_location == -1) {
17810                      /* user didn't say; default to first pause */
17811                      cid_location = 1;
17812                   } else {
17813                      /* convert element_index to cidrings value */
17814                      cid_location = (cid_location + 1) / 2;
17815                   }
17816                   /* ---we like their cadence; try to install it--- */
17817                   if (!user_has_defined_cadences++)
17818                      /* this is the first user-defined cadence; clear the default user cadences */
17819                      num_cadence = 0;
17820                   if ((num_cadence+1) >= NUM_CADENCE_MAX)
17821                      ast_log(LOG_ERROR, "Already %d cadences; can't add another: %s at line %d.\n", NUM_CADENCE_MAX, original_args, v->lineno);
17822                   else {
17823                      cadences[num_cadence] = new_cadence;
17824                      cidrings[num_cadence++] = cid_location;
17825                      ast_verb(3, "cadence 'r%d' added: %s\n",num_cadence,original_args);
17826                   }
17827                }
17828             }
17829          } else if (!strcasecmp(v->name, "ringtimeout")) {
17830             ringt_base = (atoi(v->value) * 8) / READ_SIZE;
17831          } else if (!strcasecmp(v->name, "prewink")) {
17832             confp->timing.prewinktime = atoi(v->value);
17833          } else if (!strcasecmp(v->name, "preflash")) {
17834             confp->timing.preflashtime = atoi(v->value);
17835          } else if (!strcasecmp(v->name, "wink")) {
17836             confp->timing.winktime = atoi(v->value);
17837          } else if (!strcasecmp(v->name, "flash")) {
17838             confp->timing.flashtime = atoi(v->value);
17839          } else if (!strcasecmp(v->name, "start")) {
17840             confp->timing.starttime = atoi(v->value);
17841          } else if (!strcasecmp(v->name, "rxwink")) {
17842             confp->timing.rxwinktime = atoi(v->value);
17843          } else if (!strcasecmp(v->name, "rxflash")) {
17844             confp->timing.rxflashtime = atoi(v->value);
17845          } else if (!strcasecmp(v->name, "debounce")) {
17846             confp->timing.debouncetime = atoi(v->value);
17847          } else if (!strcasecmp(v->name, "toneduration")) {
17848             int toneduration;
17849             int ctlfd;
17850             int res;
17851             struct dahdi_dialparams dps;
17852 
17853             ctlfd = open("/dev/dahdi/ctl", O_RDWR);
17854             if (ctlfd == -1) {
17855                ast_log(LOG_ERROR, "Unable to open /dev/dahdi/ctl to set toneduration at line %d.\n", v->lineno);
17856                return -1;
17857             }
17858 
17859             toneduration = atoi(v->value);
17860             if (toneduration > -1) {
17861                memset(&dps, 0, sizeof(dps));
17862 
17863                dps.dtmf_tonelen = dps.mfv1_tonelen = toneduration;
17864                res = ioctl(ctlfd, DAHDI_SET_DIALPARAMS, &dps);
17865                if (res < 0) {
17866                   ast_log(LOG_ERROR, "Invalid tone duration: %d ms at line %d: %s\n", toneduration, v->lineno, strerror(errno));
17867                   close(ctlfd);
17868                   return -1;
17869                }
17870             }
17871             close(ctlfd);
17872          } else if (!strcasecmp(v->name, "defaultcic")) {
17873             ast_copy_string(defaultcic, v->value, sizeof(defaultcic));
17874          } else if (!strcasecmp(v->name, "defaultozz")) {
17875             ast_copy_string(defaultozz, v->value, sizeof(defaultozz));
17876          } else if (!strcasecmp(v->name, "mwilevel")) {
17877             mwilevel = atoi(v->value);
17878          } else if (!strcasecmp(v->name, "dtmfcidlevel")) {
17879             dtmfcid_level = atoi(v->value);
17880          } else if (!strcasecmp(v->name, "reportalarms")) {
17881             if (!strcasecmp(v->value, "all"))
17882                report_alarms = REPORT_CHANNEL_ALARMS | REPORT_SPAN_ALARMS;
17883             if (!strcasecmp(v->value, "none"))
17884                report_alarms = 0;
17885             else if (!strcasecmp(v->value, "channels"))
17886                report_alarms = REPORT_CHANNEL_ALARMS;
17887             else if (!strcasecmp(v->value, "spans"))
17888                report_alarms = REPORT_SPAN_ALARMS;
17889           }
17890       } else if (!(options & PROC_DAHDI_OPT_NOWARN) )
17891          ast_log(LOG_WARNING, "Ignoring any changes to '%s' (on reload) at line %d.\n", v->name, v->lineno);
17892    }
17893 
17894    /* Since confp has already filled invidual dahdi_pvt objects with channels at this point, clear the variables in confp's pvt. */
17895    if (confp->chan.vars) {
17896       ast_variables_destroy(confp->chan.vars);
17897       confp->chan.vars = NULL;
17898    }
17899 
17900    if (dahdichan) {
17901       /* Process the deferred dahdichan value. */
17902       if (build_channels(confp, dahdichan->value, reload, dahdichan->lineno,
17903          &found_pseudo)) {
17904          if (confp->ignore_failed_channels) {
17905             ast_log(LOG_WARNING,
17906                "Dahdichan '%s' failure ignored: ignore_failed_channels.\n",
17907                dahdichan->value);
17908          } else {
17909             return -1;
17910          }
17911       }
17912    }
17913 
17914    /* mark the first channels of each DAHDI span to watch for their span alarms */
17915    for (tmp = iflist, y=-1; tmp; tmp = tmp->next) {
17916       if (!tmp->destroy && tmp->span != y) {
17917          tmp->manages_span_alarms = 1;
17918          y = tmp->span; 
17919       } else {
17920          tmp->manages_span_alarms = 0;
17921       }
17922    }
17923 
17924    /*< \todo why check for the pseudo in the per-channel section.
17925     * Any actual use for manual setup of the pseudo channel? */
17926    if (!found_pseudo && reload != 1 && !(options & PROC_DAHDI_OPT_NOCHAN)) {
17927       /* use the default configuration for a channel, so
17928          that any settings from real configured channels
17929          don't "leak" into the pseudo channel config
17930       */
17931       struct dahdi_chan_conf conf = dahdi_chan_conf_default();
17932 
17933       if (conf.chan.cc_params) {
17934          tmp = mkintf(CHAN_PSEUDO, &conf, reload);
17935       } else {
17936          tmp = NULL;
17937       }
17938       if (tmp) {
17939          ast_verb(3, "Automatically generated pseudo channel\n");
17940       } else {
17941          ast_log(LOG_WARNING, "Unable to register pseudo channel!\n");
17942       }
17943       ast_cc_config_params_destroy(conf.chan.cc_params);
17944    }
17945    return 0;
17946 }
17947 
17948 /*!
17949  * \internal
17950  * \brief Deep copy struct dahdi_chan_conf.
17951  * \since 1.8
17952  *
17953  * \param dest Destination.
17954  * \param src Source.
17955  *
17956  * \return Nothing
17957  */
17958 static void deep_copy_dahdi_chan_conf(struct dahdi_chan_conf *dest, const struct dahdi_chan_conf *src)
17959 {
17960    struct ast_cc_config_params *cc_params;
17961 
17962    cc_params = dest->chan.cc_params;
17963    *dest = *src;
17964    dest->chan.cc_params = cc_params;
17965    ast_cc_copy_config_params(dest->chan.cc_params, src->chan.cc_params);
17966 }
17967 
17968 /*!
17969  * \internal
17970  * \brief Setup DAHDI channel driver.
17971  *
17972  * \param reload enum: load_module(0), reload(1), restart(2).
17973  * \param default_conf Default config parameters.  So cc_params can be properly destroyed.
17974  * \param base_conf Default config parameters per section.  So cc_params can be properly destroyed.
17975  * \param conf Local config parameters.  So cc_params can be properly destroyed.
17976  *
17977  * \retval 0 on success.
17978  * \retval -1 on error.
17979  */
17980 static int setup_dahdi_int(int reload, struct dahdi_chan_conf *default_conf, struct dahdi_chan_conf *base_conf, struct dahdi_chan_conf *conf)
17981 {
17982    struct ast_config *cfg;
17983    struct ast_config *ucfg;
17984    struct ast_variable *v;
17985    struct ast_flags config_flags = { reload == 1 ? CONFIG_FLAG_FILEUNCHANGED : 0 };
17986    const char *chans;
17987    const char *cat;
17988    int res;
17989 
17990 #ifdef HAVE_PRI
17991    char *c;
17992    int spanno;
17993    int i;
17994    int logicalspan;
17995    int trunkgroup;
17996    int dchannels[SIG_PRI_NUM_DCHANS];
17997 #endif
17998    int have_cfg_now;
17999    static int had_cfg_before = 1;/* So initial load will complain if we don't have cfg. */
18000 
18001    cfg = ast_config_load(config, config_flags);
18002    have_cfg_now = !!cfg;
18003    if (!cfg) {
18004       /* Error if we have no config file */
18005       if (had_cfg_before) {
18006          ast_log(LOG_ERROR, "Unable to load config %s\n", config);
18007          ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
18008       }
18009       cfg = ast_config_new();/* Dummy config */
18010       if (!cfg) {
18011          return 0;
18012       }
18013       ucfg = ast_config_load("users.conf", config_flags);
18014       if (ucfg == CONFIG_STATUS_FILEUNCHANGED) {
18015          ast_config_destroy(cfg);
18016          return 0;
18017       }
18018       if (ucfg == CONFIG_STATUS_FILEINVALID) {
18019          ast_log(LOG_ERROR, "File users.conf cannot be parsed.  Aborting.\n");
18020          ast_config_destroy(cfg);
18021          return 0;
18022       }
18023    } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
18024       ucfg = ast_config_load("users.conf", config_flags);
18025       if (ucfg == CONFIG_STATUS_FILEUNCHANGED) {
18026          return 0;
18027       }
18028       if (ucfg == CONFIG_STATUS_FILEINVALID) {
18029          ast_log(LOG_ERROR, "File users.conf cannot be parsed.  Aborting.\n");
18030          return 0;
18031       }
18032       ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
18033       cfg = ast_config_load(config, config_flags);
18034       have_cfg_now = !!cfg;
18035       if (!cfg) {
18036          if (had_cfg_before) {
18037             /* We should have been able to load the config. */
18038             ast_log(LOG_ERROR, "Bad. Unable to load config %s\n", config);
18039             ast_config_destroy(ucfg);
18040             return 0;
18041          }
18042          cfg = ast_config_new();/* Dummy config */
18043          if (!cfg) {
18044             ast_config_destroy(ucfg);
18045             return 0;
18046          }
18047       } else if (cfg == CONFIG_STATUS_FILEINVALID) {
18048          ast_log(LOG_ERROR, "File %s cannot be parsed.  Aborting.\n", config);
18049          ast_config_destroy(ucfg);
18050          return 0;
18051       }
18052    } else if (cfg == CONFIG_STATUS_FILEINVALID) {
18053       ast_log(LOG_ERROR, "File %s cannot be parsed.  Aborting.\n", config);
18054       return 0;
18055    } else {
18056       ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
18057       ucfg = ast_config_load("users.conf", config_flags);
18058       if (ucfg == CONFIG_STATUS_FILEINVALID) {
18059          ast_log(LOG_ERROR, "File users.conf cannot be parsed.  Aborting.\n");
18060          ast_config_destroy(cfg);
18061          return 0;
18062       }
18063    }
18064    had_cfg_before = have_cfg_now;
18065 
18066    /* It's a little silly to lock it, but we might as well just to be sure */
18067    ast_mutex_lock(&iflock);
18068 #ifdef HAVE_PRI
18069    if (reload != 1) {
18070       /* Process trunkgroups first */
18071       v = ast_variable_browse(cfg, "trunkgroups");
18072       while (v) {
18073          if (!strcasecmp(v->name, "trunkgroup")) {
18074             trunkgroup = atoi(v->value);
18075             if (trunkgroup > 0) {
18076                if ((c = strchr(v->value, ','))) {
18077                   i = 0;
18078                   memset(dchannels, 0, sizeof(dchannels));
18079                   while (c && (i < SIG_PRI_NUM_DCHANS)) {
18080                      dchannels[i] = atoi(c + 1);
18081                      if (dchannels[i] < 0) {
18082                         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);
18083                      } else
18084                         i++;
18085                      c = strchr(c + 1, ',');
18086                   }
18087                   if (i) {
18088                      if (pri_create_trunkgroup(trunkgroup, dchannels)) {
18089                         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);
18090                   } else
18091                         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");
18092                   } else
18093                      ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
18094                } else
18095                   ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
18096             } else
18097                ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of chan_dahdi.conf\n", v->lineno);
18098          } else if (!strcasecmp(v->name, "spanmap")) {
18099             spanno = atoi(v->value);
18100             if (spanno > 0) {
18101                if ((c = strchr(v->value, ','))) {
18102                   trunkgroup = atoi(c + 1);
18103                   if (trunkgroup > 0) {
18104                      if ((c = strchr(c + 1, ',')))
18105                         logicalspan = atoi(c + 1);
18106                      else
18107                         logicalspan = 0;
18108                      if (logicalspan >= 0) {
18109                         if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) {
18110                            ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
18111                      } else
18112                            ast_verb(2, "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
18113                      } else
18114                         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);
18115                   } else
18116                      ast_log(LOG_WARNING, "Trunk group must be a postive number at line %d of chan_dahdi.conf\n", v->lineno);
18117                } else
18118                   ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of chan_dahdi.conf\n", v->lineno);
18119             } else
18120                ast_log(LOG_WARNING, "Span number must be a postive integer at line %d of chan_dahdi.conf\n", v->lineno);
18121          } else {
18122             ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name);
18123          }
18124          v = v->next;
18125       }
18126    }
18127 #endif
18128 
18129    /* Copy the default jb config over global_jbconf */
18130    memcpy(&global_jbconf, &default_jbconf, sizeof(global_jbconf));
18131 
18132    mwimonitornotify[0] = '\0';
18133 
18134    v = ast_variable_browse(cfg, "channels");
18135    if ((res = process_dahdi(base_conf,
18136       "" /* Must be empty for the channels category.  Silly voicemail mailbox. */,
18137       v, reload, 0))) {
18138       ast_mutex_unlock(&iflock);
18139       ast_config_destroy(cfg);
18140       if (ucfg) {
18141          ast_config_destroy(ucfg);
18142       }
18143       return res;
18144    }
18145 
18146    /* Now get configuration from all normal sections in chan_dahdi.conf: */
18147    for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) {
18148       /* [channels] and [trunkgroups] are used. Let's also reserve
18149        * [globals] and [general] for future use
18150        */
18151       if (!strcasecmp(cat, "general") ||
18152          !strcasecmp(cat, "trunkgroups") ||
18153          !strcasecmp(cat, "globals") ||
18154          !strcasecmp(cat, "channels")) {
18155          continue;
18156       }
18157 
18158       chans = ast_variable_retrieve(cfg, cat, "dahdichan");
18159       if (ast_strlen_zero(chans)) {
18160          /* Section is useless without a dahdichan value present. */
18161          continue;
18162       }
18163 
18164       /* Copy base_conf to conf. */
18165       deep_copy_dahdi_chan_conf(conf, base_conf);
18166 
18167       if ((res = process_dahdi(conf, cat, ast_variable_browse(cfg, cat), reload, PROC_DAHDI_OPT_NOCHAN))) {
18168          ast_mutex_unlock(&iflock);
18169          ast_config_destroy(cfg);
18170          if (ucfg) {
18171             ast_config_destroy(ucfg);
18172          }
18173          return res;
18174       }
18175    }
18176 
18177    ast_config_destroy(cfg);
18178 
18179    if (ucfg) {
18180       /* Reset base_conf, so things don't leak from chan_dahdi.conf */
18181       deep_copy_dahdi_chan_conf(base_conf, default_conf);
18182       process_dahdi(base_conf,
18183          "" /* Must be empty for the general category.  Silly voicemail mailbox. */,
18184          ast_variable_browse(ucfg, "general"), 1, 0);
18185 
18186       for (cat = ast_category_browse(ucfg, NULL); cat ; cat = ast_category_browse(ucfg, cat)) {
18187          if (!strcasecmp(cat, "general")) {
18188             continue;
18189          }
18190 
18191          chans = ast_variable_retrieve(ucfg, cat, "dahdichan");
18192          if (ast_strlen_zero(chans)) {
18193             /* Section is useless without a dahdichan value present. */
18194             continue;
18195          }
18196 
18197          /* Copy base_conf to conf. */
18198          deep_copy_dahdi_chan_conf(conf, base_conf);
18199 
18200          if ((res = process_dahdi(conf, cat, ast_variable_browse(ucfg, cat), reload, PROC_DAHDI_OPT_NOCHAN | PROC_DAHDI_OPT_NOWARN))) {
18201             ast_config_destroy(ucfg);
18202             ast_mutex_unlock(&iflock);
18203             return res;
18204          }
18205       }
18206       ast_config_destroy(ucfg);
18207    }
18208    ast_mutex_unlock(&iflock);
18209 
18210 #ifdef HAVE_PRI
18211    if (reload != 1) {
18212       int x;
18213       for (x = 0; x < NUM_SPANS; x++) {
18214          if (pris[x].pri.pvts[0]) {
18215             prepare_pri(pris + x);
18216             if (sig_pri_start_pri(&pris[x].pri)) {
18217                ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1);
18218                return -1;
18219             } else
18220                ast_verb(2, "Starting D-Channel on span %d\n", x + 1);
18221          }
18222       }
18223    }
18224 #endif
18225 #if defined(HAVE_SS7)
18226    if (reload != 1) {
18227       int x;
18228       for (x = 0; x < NUM_SPANS; x++) {
18229          if (linksets[x].ss7.ss7) {
18230             linksets[x].ss7.calls = &dahdi_ss7_callbacks;
18231             if (ast_pthread_create(&linksets[x].ss7.master, NULL, ss7_linkset, &linksets[x].ss7)) {
18232                ast_log(LOG_ERROR, "Unable to start SS7 linkset on span %d\n", x + 1);
18233                return -1;
18234             } else
18235                ast_verb(2, "Starting SS7 linkset on span %d\n", x + 1);
18236          }
18237       }
18238    }
18239 #endif   /* defined(HAVE_SS7) */
18240 #ifdef HAVE_OPENR2
18241    if (reload != 1) {
18242       int x;
18243       for (x = 0; x < r2links_count; x++) {
18244          if (ast_pthread_create(&r2links[x]->r2master, NULL, mfcr2_monitor, r2links[x])) {
18245             ast_log(LOG_ERROR, "Unable to start R2 monitor on channel group %d\n", x + 1);
18246             return -1;
18247          } else {
18248             ast_verb(2, "Starting R2 monitor on channel group %d\n", x + 1);
18249          }
18250       }
18251    }
18252 #endif
18253    /* And start the monitor for the first time */
18254    restart_monitor();
18255    return 0;
18256 }
18257 
18258 /*!
18259  * \internal
18260  * \brief Setup DAHDI channel driver.
18261  *
18262  * \param reload enum: load_module(0), reload(1), restart(2).
18263  *
18264  * \retval 0 on success.
18265  * \retval -1 on error.
18266  */
18267 static int setup_dahdi(int reload)
18268 {
18269    int res;
18270    struct dahdi_chan_conf default_conf = dahdi_chan_conf_default();
18271    struct dahdi_chan_conf base_conf = dahdi_chan_conf_default();
18272    struct dahdi_chan_conf conf = dahdi_chan_conf_default();
18273 
18274    if (default_conf.chan.cc_params && base_conf.chan.cc_params && conf.chan.cc_params) {
18275       res = setup_dahdi_int(reload, &default_conf, &base_conf, &conf);
18276    } else {
18277       res = -1;
18278    }
18279    ast_cc_config_params_destroy(default_conf.chan.cc_params);
18280    ast_cc_config_params_destroy(base_conf.chan.cc_params);
18281    ast_cc_config_params_destroy(conf.chan.cc_params);
18282 
18283    return res;
18284 }
18285 
18286 /*!
18287  * \internal
18288  * \brief Callback used to generate the dahdi status tree.
18289  * \param[in] search The search pattern tree.
18290  * \retval NULL on error.
18291  * \retval non-NULL The generated tree.
18292  */
18293 static int dahdi_status_data_provider_get(const struct ast_data_search *search,
18294       struct ast_data *data_root)
18295 {
18296    int ctl, res, span;
18297    struct ast_data *data_span, *data_alarms;
18298    struct dahdi_spaninfo s;
18299 
18300    ctl = open("/dev/dahdi/ctl", O_RDWR);
18301    if (ctl < 0) {
18302       ast_log(LOG_ERROR, "No DAHDI found. Unable to open /dev/dahdi/ctl: %s\n", strerror(errno));
18303       return -1;
18304    }
18305    for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
18306       s.spanno = span;
18307       res = ioctl(ctl, DAHDI_SPANSTAT, &s);
18308       if (res) {
18309          continue;
18310       }
18311 
18312       data_span = ast_data_add_node(data_root, "span");
18313       if (!data_span) {
18314          continue;
18315       }
18316       ast_data_add_str(data_span, "description", s.desc);
18317 
18318       /* insert the alarms status */
18319       data_alarms = ast_data_add_node(data_span, "alarms");
18320       if (!data_alarms) {
18321          continue;
18322       }
18323 
18324       ast_data_add_bool(data_alarms, "BLUE", s.alarms & DAHDI_ALARM_BLUE);
18325       ast_data_add_bool(data_alarms, "YELLOW", s.alarms & DAHDI_ALARM_YELLOW);
18326       ast_data_add_bool(data_alarms, "RED", s.alarms & DAHDI_ALARM_RED);
18327       ast_data_add_bool(data_alarms, "LOOPBACK", s.alarms & DAHDI_ALARM_LOOPBACK);
18328       ast_data_add_bool(data_alarms, "RECOVER", s.alarms & DAHDI_ALARM_RECOVER);
18329       ast_data_add_bool(data_alarms, "NOTOPEN", s.alarms & DAHDI_ALARM_NOTOPEN);
18330 
18331       ast_data_add_int(data_span, "irqmisses", s.irqmisses);
18332       ast_data_add_int(data_span, "bpviol", s.bpvcount);
18333       ast_data_add_int(data_span, "crc4", s.crc4count);
18334       ast_data_add_str(data_span, "framing", s.lineconfig & DAHDI_CONFIG_D4 ? "D4" :
18335                      s.lineconfig & DAHDI_CONFIG_ESF ? "ESF" :
18336                      s.lineconfig & DAHDI_CONFIG_CCS ? "CCS" :
18337                      "CAS");
18338       ast_data_add_str(data_span, "coding",  s.lineconfig & DAHDI_CONFIG_B8ZS ? "B8ZS" :
18339                      s.lineconfig & DAHDI_CONFIG_HDB3 ? "HDB3" :
18340                      s.lineconfig & DAHDI_CONFIG_AMI ? "AMI" :
18341                      "Unknown");
18342       ast_data_add_str(data_span, "options", s.lineconfig & DAHDI_CONFIG_CRC4 ?
18343                      s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" :
18344                      s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "YEL" : "");
18345       ast_data_add_str(data_span, "lbo", lbostr[s.lbo]);
18346 
18347       /* if this span doesn't match remove it. */
18348       if (!ast_data_search_match(search, data_span)) {
18349          ast_data_remove_node(data_root, data_span);
18350       }
18351    }
18352    close(ctl);
18353 
18354    return 0;
18355 }
18356 
18357 /*!
18358  * \internal
18359  * \brief Callback used to generate the dahdi channels tree.
18360  * \param[in] search The search pattern tree.
18361  * \retval NULL on error.
18362  * \retval non-NULL The generated tree.
18363  */
18364 static int dahdi_channels_data_provider_get(const struct ast_data_search *search,
18365       struct ast_data *data_root)
18366 {
18367    struct dahdi_pvt *tmp;
18368    struct ast_data *data_channel;
18369 
18370    ast_mutex_lock(&iflock);
18371    for (tmp = iflist; tmp; tmp = tmp->next) {
18372       data_channel = ast_data_add_node(data_root, "channel");
18373       if (!data_channel) {
18374          continue;
18375       }
18376 
18377       ast_data_add_structure(dahdi_pvt, data_channel, tmp);
18378 
18379       /* if this channel doesn't match remove it. */
18380       if (!ast_data_search_match(search, data_channel)) {
18381          ast_data_remove_node(data_root, data_channel);
18382       }
18383    }
18384    ast_mutex_unlock(&iflock);
18385 
18386    return 0;
18387 }
18388 
18389 /*!
18390  * \internal
18391  * \brief Callback used to generate the dahdi channels tree.
18392  * \param[in] search The search pattern tree.
18393  * \retval NULL on error.
18394  * \retval non-NULL The generated tree.
18395  */
18396 static int dahdi_version_data_provider_get(const struct ast_data_search *search,
18397       struct ast_data *data_root)
18398 {
18399    int pseudo_fd = -1;
18400    struct dahdi_versioninfo vi = {
18401       .version = "Unknown",
18402       .echo_canceller = "Unknown"
18403    };
18404 
18405    if ((pseudo_fd = open("/dev/dahdi/ctl", O_RDONLY)) < 0) {
18406       ast_log(LOG_ERROR, "Failed to open control file to get version.\n");
18407       return -1;
18408    }
18409 
18410    if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi)) {
18411       ast_log(LOG_ERROR, "Failed to get DAHDI version: %s\n", strerror(errno));
18412    }
18413 
18414    close(pseudo_fd);
18415 
18416    ast_data_add_str(data_root, "value", vi.version);
18417    ast_data_add_str(data_root, "echocanceller", vi.echo_canceller);
18418 
18419    return 0;
18420 }
18421 
18422 static const struct ast_data_handler dahdi_status_data_provider = {
18423    .version = AST_DATA_HANDLER_VERSION,
18424    .get = dahdi_status_data_provider_get
18425 };
18426 
18427 static const struct ast_data_handler dahdi_channels_data_provider = {
18428    .version = AST_DATA_HANDLER_VERSION,
18429    .get = dahdi_channels_data_provider_get
18430 };
18431 
18432 static const struct ast_data_handler dahdi_version_data_provider = {
18433    .version = AST_DATA_HANDLER_VERSION,
18434    .get = dahdi_version_data_provider_get
18435 };
18436 
18437 static const struct ast_data_entry dahdi_data_providers[] = {
18438    AST_DATA_ENTRY("asterisk/channel/dahdi/status", &dahdi_status_data_provider),
18439    AST_DATA_ENTRY("asterisk/channel/dahdi/channels", &dahdi_channels_data_provider),
18440    AST_DATA_ENTRY("asterisk/channel/dahdi/version", &dahdi_version_data_provider)
18441 };
18442 
18443 static int load_module(void)
18444 {
18445    int res;
18446 #if defined(HAVE_PRI) || defined(HAVE_SS7)
18447    int y;
18448 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
18449 
18450 #ifdef HAVE_PRI
18451    memset(pris, 0, sizeof(pris));
18452    for (y = 0; y < NUM_SPANS; y++) {
18453       sig_pri_init_pri(&pris[y].pri);
18454    }
18455    pri_set_error(dahdi_pri_error);
18456    pri_set_message(dahdi_pri_message);
18457    ast_register_application_xml(dahdi_send_keypad_facility_app, dahdi_send_keypad_facility_exec);
18458 #ifdef HAVE_PRI_PROG_W_CAUSE
18459    ast_register_application_xml(dahdi_send_callrerouting_facility_app, dahdi_send_callrerouting_facility_exec);
18460 #endif
18461 #if defined(HAVE_PRI_CCSS)
18462    if (ast_cc_agent_register(&dahdi_pri_cc_agent_callbacks)
18463       || ast_cc_monitor_register(&dahdi_pri_cc_monitor_callbacks)) {
18464       __unload_module();
18465       return AST_MODULE_LOAD_FAILURE;
18466    }
18467 #endif   /* defined(HAVE_PRI_CCSS) */
18468    if (sig_pri_load(
18469 #if defined(HAVE_PRI_CCSS)
18470       dahdi_pri_cc_type
18471 #else
18472       NULL
18473 #endif   /* defined(HAVE_PRI_CCSS) */
18474       )) {
18475       __unload_module();
18476       return AST_MODULE_LOAD_FAILURE;
18477    }
18478 #endif
18479 #if defined(HAVE_SS7)
18480    memset(linksets, 0, sizeof(linksets));
18481    for (y = 0; y < NUM_SPANS; y++) {
18482       sig_ss7_init_linkset(&linksets[y].ss7);
18483    }
18484    ss7_set_error(dahdi_ss7_error);
18485    ss7_set_message(dahdi_ss7_message);
18486 #endif   /* defined(HAVE_SS7) */
18487    res = setup_dahdi(0);
18488    /* Make sure we can register our DAHDI channel type */
18489    if (res)
18490       return AST_MODULE_LOAD_DECLINE;
18491    if (ast_channel_register(&dahdi_tech)) {
18492       ast_log(LOG_ERROR, "Unable to register channel class 'DAHDI'\n");
18493       __unload_module();
18494       return AST_MODULE_LOAD_FAILURE;
18495    }
18496 #ifdef HAVE_PRI
18497    ast_cli_register_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
18498 #endif
18499 #if defined(HAVE_SS7)
18500    ast_cli_register_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
18501 #endif   /* defined(HAVE_SS7) */
18502 #ifdef HAVE_OPENR2
18503    ast_cli_register_multiple(dahdi_mfcr2_cli, ARRAY_LEN(dahdi_mfcr2_cli));
18504    ast_register_application_xml(dahdi_accept_r2_call_app, dahdi_accept_r2_call_exec);
18505 #endif
18506 
18507    ast_cli_register_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli));
18508    /* register all the data providers */
18509    ast_data_register_multiple(dahdi_data_providers, ARRAY_LEN(dahdi_data_providers));
18510    memset(round_robin, 0, sizeof(round_robin));
18511    ast_manager_register_xml("DAHDITransfer", 0, action_transfer);
18512    ast_manager_register_xml("DAHDIHangup", 0, action_transferhangup);
18513    ast_manager_register_xml("DAHDIDialOffhook", 0, action_dahdidialoffhook);
18514    ast_manager_register_xml("DAHDIDNDon", 0, action_dahdidndon);
18515    ast_manager_register_xml("DAHDIDNDoff", 0, action_dahdidndoff);
18516    ast_manager_register_xml("DAHDIShowChannels", 0, action_dahdishowchannels);
18517    ast_manager_register_xml("DAHDIRestart", 0, action_dahdirestart);
18518 
18519    ast_cond_init(&ss_thread_complete, NULL);
18520 
18521    return res;
18522 }
18523 
18524 static int dahdi_sendtext(struct ast_channel *c, const char *text)
18525 {
18526 #define  END_SILENCE_LEN 400
18527 #define  HEADER_MS 50
18528 #define  TRAILER_MS 5
18529 #define  HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8)
18530 #define  ASCII_BYTES_PER_CHAR 80
18531 
18532    unsigned char *buf,*mybuf;
18533    struct dahdi_pvt *p = c->tech_pvt;
18534    struct pollfd fds[1];
18535    int size,res,fd,len,x;
18536    int bytes=0;
18537    /* Initial carrier (imaginary) */
18538    float cr = 1.0;
18539    float ci = 0.0;
18540    float scont = 0.0;
18541    int idx;
18542 
18543    idx = dahdi_get_index(c, p, 0);
18544    if (idx < 0) {
18545       ast_log(LOG_WARNING, "Huh?  I don't exist?\n");
18546       return -1;
18547    }
18548    if (!text[0]) return(0); /* if nothing to send, don't */
18549    if ((!p->tdd) && (!p->mate)) return(0);  /* if not in TDD mode, just return */
18550    if (p->mate)
18551       buf = ast_malloc(((strlen(text) + 1) * ASCII_BYTES_PER_CHAR) + END_SILENCE_LEN + HEADER_LEN);
18552    else
18553       buf = ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN);
18554    if (!buf)
18555       return -1;
18556    mybuf = buf;
18557    if (p->mate) {
18558       int codec = AST_LAW(p);
18559       for (x = 0; x < HEADER_MS; x++) {   /* 50 ms of Mark */
18560          PUT_CLID_MARKMS;
18561       }
18562       /* Put actual message */
18563       for (x = 0; text[x]; x++) {
18564          PUT_CLID(text[x]);
18565       }
18566       for (x = 0; x < TRAILER_MS; x++) {  /* 5 ms of Mark */
18567          PUT_CLID_MARKMS;
18568       }
18569       len = bytes;
18570       buf = mybuf;
18571    } else {
18572       len = tdd_generate(p->tdd, buf, text);
18573       if (len < 1) {
18574          ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text));
18575          ast_free(mybuf);
18576          return -1;
18577       }
18578    }
18579    memset(buf + len, 0x7f, END_SILENCE_LEN);
18580    len += END_SILENCE_LEN;
18581    fd = p->subs[idx].dfd;
18582    while (len) {
18583       if (ast_check_hangup(c)) {
18584          ast_free(mybuf);
18585          return -1;
18586       }
18587       size = len;
18588       if (size > READ_SIZE)
18589          size = READ_SIZE;
18590       fds[0].fd = fd;
18591       fds[0].events = POLLOUT | POLLPRI;
18592       fds[0].revents = 0;
18593       res = poll(fds, 1, -1);
18594       if (!res) {
18595          ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
18596          continue;
18597       }
18598       /* if got exception */
18599       if (fds[0].revents & POLLPRI) {
18600          ast_free(mybuf);
18601          return -1;
18602       }
18603       if (!(fds[0].revents & POLLOUT)) {
18604          ast_debug(1, "write fd not ready on channel %d\n", p->channel);
18605          continue;
18606       }
18607       res = write(fd, buf, size);
18608       if (res != size) {
18609          if (res == -1) {
18610             ast_free(mybuf);
18611             return -1;
18612          }
18613          ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
18614          break;
18615       }
18616       len -= size;
18617       buf += size;
18618    }
18619    ast_free(mybuf);
18620    return(0);
18621 }
18622 
18623 
18624 static int reload(void)
18625 {
18626    int res = 0;
18627 
18628    res = setup_dahdi(1);
18629    if (res) {
18630       ast_log(LOG_WARNING, "Reload of chan_dahdi.so is unsuccessful!\n");
18631       return -1;
18632    }
18633    return 0;
18634 }
18635 
18636 /* This is a workaround so that menuselect displays a proper description
18637  * AST_MODULE_INFO(, , "DAHDI Telephony"
18638  */
18639 
18640 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, tdesc,
18641    .load = load_module,
18642    .unload = unload_module,
18643    .reload = reload,
18644    .load_pri = AST_MODPRI_CHANNEL_DRIVER,
18645       .nonoptreq = "res_smdi",
18646    );