Fri Apr 15 20:38:04 2016

Asterisk developer's documentation


chan_dahdi.c

Go to the documentation of this file.
00001 /*
00002  * Asterisk -- An open source telephony toolkit.
00003  *
00004  * Copyright (C) 1999 - 2008, Digium, Inc.
00005  *
00006  * Mark Spencer <markster@digium.com>
00007  *
00008  * See http://www.asterisk.org for more information about
00009  * the Asterisk project. Please do not directly contact
00010  * any of the maintainers of this project for assistance;
00011  * the project provides a web site, mailing lists and IRC
00012  * channels for your use.
00013  *
00014  * This program is free software, distributed under the terms of
00015  * the GNU General Public License Version 2. See the LICENSE file
00016  * at the top of the source tree.
00017  */
00018 
00019 /*! \file
00020  *
00021  * \brief DAHDI for Pseudo TDM
00022  *
00023  * \author Mark Spencer <markster@digium.com>
00024  *
00025  * Connects to the DAHDI telephony library as well as
00026  * libpri. Libpri is optional and needed only if you are
00027  * going to use ISDN connections.
00028  *
00029  * You need to install libraries before you attempt to compile
00030  * and install the DAHDI channel.
00031  *
00032  * \par See also
00033  * \arg \ref Config_dahdi
00034  *
00035  * \ingroup channel_drivers
00036  *
00037  * \todo Deprecate the "musiconhold" configuration option post 1.4
00038  */
00039 
00040 /*** MODULEINFO
00041    <use>res_smdi</use>
00042    <depend>dahdi</depend>
00043    <depend>tonezone</depend>
00044    <use>pri</use>
00045    <use>ss7</use>
00046    <use>openr2</use>
00047    <support_level>core</support_level>
00048  ***/
00049 
00050 #include "asterisk.h"
00051 
00052 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 417956 $")
00053 
00054 #if defined(__NetBSD__) || defined(__FreeBSD__)
00055 #include <pthread.h>
00056 #include <signal.h>
00057 #else
00058 #include <sys/signal.h>
00059 #endif
00060 #include <sys/ioctl.h>
00061 #include <sys/stat.h>
00062 #include <math.h>
00063 #include <ctype.h>
00064 
00065 #include <dahdi/user.h>
00066 #include <dahdi/tonezone.h>
00067 #include "sig_analog.h"
00068 /* Analog signaling is currently still present in chan_dahdi for use with
00069  * radio. Sig_analog does not currently handle any radio operations. If
00070  * radio only uses analog signaling, then the radio handling logic could
00071  * be placed in sig_analog and the duplicated code could be removed.
00072  */
00073 
00074 #if defined(HAVE_PRI)
00075 #include "sig_pri.h"
00076 #ifndef PRI_RESTART
00077 #error "Upgrade your libpri"
00078 #endif
00079 #endif   /* defined(HAVE_PRI) */
00080 
00081 #if defined(HAVE_SS7)
00082 #include "sig_ss7.h"
00083 #if defined(LIBSS7_ABI_COMPATIBILITY)
00084 #error "Your installed libss7 is not compatible"
00085 #endif
00086 #endif   /* defined(HAVE_SS7) */
00087 
00088 #ifdef HAVE_OPENR2
00089 /* put this here until sig_mfcr2 comes along */
00090 #define SIG_MFCR2_MAX_CHANNELS   672      /*!< No more than a DS3 per trunk group */
00091 #include <openr2.h>
00092 #endif
00093 
00094 #include "asterisk/lock.h"
00095 #include "asterisk/channel.h"
00096 #include "asterisk/config.h"
00097 #include "asterisk/module.h"
00098 #include "asterisk/pbx.h"
00099 #include "asterisk/file.h"
00100 #include "asterisk/ulaw.h"
00101 #include "asterisk/alaw.h"
00102 #include "asterisk/callerid.h"
00103 #include "asterisk/adsi.h"
00104 #include "asterisk/cli.h"
00105 #include "asterisk/cdr.h"
00106 #include "asterisk/cel.h"
00107 #include "asterisk/features.h"
00108 #include "asterisk/musiconhold.h"
00109 #include "asterisk/say.h"
00110 #include "asterisk/tdd.h"
00111 #include "asterisk/app.h"
00112 #include "asterisk/dsp.h"
00113 #include "asterisk/astdb.h"
00114 #include "asterisk/manager.h"
00115 #include "asterisk/causes.h"
00116 #include "asterisk/term.h"
00117 #include "asterisk/utils.h"
00118 #include "asterisk/transcap.h"
00119 #include "asterisk/stringfields.h"
00120 #include "asterisk/abstract_jb.h"
00121 #include "asterisk/smdi.h"
00122 #include "asterisk/astobj.h"
00123 #include "asterisk/event.h"
00124 #include "asterisk/devicestate.h"
00125 #include "asterisk/paths.h"
00126 #include "asterisk/ccss.h"
00127 #include "asterisk/data.h"
00128 
00129 /*** DOCUMENTATION
00130    <application name="DAHDISendKeypadFacility" language="en_US">
00131       <synopsis>
00132          Send digits out of band over a PRI.
00133       </synopsis>
00134       <syntax>
00135          <parameter name="digits" required="true" />
00136       </syntax>
00137       <description>
00138          <para>This application will send the given string of digits in a Keypad
00139          Facility IE over the current channel.</para>
00140       </description>
00141    </application>
00142    <application name="DAHDISendCallreroutingFacility" language="en_US">
00143       <synopsis>
00144          Send an ISDN call rerouting/deflection facility message.
00145       </synopsis>
00146       <syntax argsep=",">
00147          <parameter name="destination" required="true">
00148             <para>Destination number.</para>
00149          </parameter>
00150          <parameter name="original">
00151             <para>Original called number.</para>
00152          </parameter>
00153          <parameter name="reason">
00154             <para>Diversion reason, if not specified defaults to <literal>unknown</literal></para>
00155          </parameter>
00156       </syntax>
00157       <description>
00158          <para>This application will send an ISDN switch specific call
00159          rerouting/deflection facility message over the current channel.
00160          Supported switches depend upon the version of libpri in use.</para>
00161       </description>
00162    </application>
00163    <application name="DAHDIAcceptR2Call" language="en_US">
00164       <synopsis>
00165          Accept an R2 call if its not already accepted (you still need to answer it)
00166       </synopsis>
00167       <syntax>
00168          <parameter name="charge" required="true">
00169             <para>Yes or No.</para>
00170             <para>Whether you want to accept the call with charge or without charge.</para>
00171          </parameter>
00172       </syntax>
00173       <description>
00174          <para>This application will Accept the R2 call either with charge or no charge.</para>
00175       </description>
00176    </application>
00177    <manager name="DAHDITransfer" language="en_US">
00178       <synopsis>
00179          Transfer DAHDI Channel.
00180       </synopsis>
00181       <syntax>
00182          <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
00183          <parameter name="DAHDIChannel" required="true">
00184             <para>DAHDI channel number to transfer.</para>
00185          </parameter>
00186       </syntax>
00187       <description>
00188          <para>Simulate a flash hook event by the user connected to the channel.</para>
00189          <note><para>Valid only for analog channels.</para></note>
00190       </description>
00191    </manager>
00192    <manager name="DAHDIHangup" language="en_US">
00193       <synopsis>
00194          Hangup DAHDI Channel.
00195       </synopsis>
00196       <syntax>
00197          <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
00198          <parameter name="DAHDIChannel" required="true">
00199             <para>DAHDI channel number to hangup.</para>
00200          </parameter>
00201       </syntax>
00202       <description>
00203          <para>Simulate an on-hook event by the user connected to the channel.</para>
00204          <note><para>Valid only for analog channels.</para></note>
00205       </description>
00206    </manager>
00207    <manager name="DAHDIDialOffhook" language="en_US">
00208       <synopsis>
00209          Dial over DAHDI channel while offhook.
00210       </synopsis>
00211       <syntax>
00212          <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
00213          <parameter name="DAHDIChannel" required="true">
00214             <para>DAHDI channel number to dial digits.</para>
00215          </parameter>
00216          <parameter name="Number" required="true">
00217             <para>Digits to dial.</para>
00218          </parameter>
00219       </syntax>
00220       <description>
00221          <para>Generate DTMF control frames to the bridged peer.</para>
00222       </description>
00223    </manager>
00224    <manager name="DAHDIDNDon" language="en_US">
00225       <synopsis>
00226          Toggle DAHDI channel Do Not Disturb status ON.
00227       </synopsis>
00228       <syntax>
00229          <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
00230          <parameter name="DAHDIChannel" required="true">
00231             <para>DAHDI channel number to set DND on.</para>
00232          </parameter>
00233       </syntax>
00234       <description>
00235          <para>Equivalent to the CLI command "dahdi set dnd <variable>channel</variable> on".</para>
00236          <note><para>Feature only supported by analog channels.</para></note>
00237       </description>
00238    </manager>
00239    <manager name="DAHDIDNDoff" language="en_US">
00240       <synopsis>
00241          Toggle DAHDI channel Do Not Disturb status OFF.
00242       </synopsis>
00243       <syntax>
00244          <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
00245          <parameter name="DAHDIChannel" required="true">
00246             <para>DAHDI channel number to set DND off.</para>
00247          </parameter>
00248       </syntax>
00249       <description>
00250          <para>Equivalent to the CLI command "dahdi set dnd <variable>channel</variable> off".</para>
00251          <note><para>Feature only supported by analog channels.</para></note>
00252       </description>
00253    </manager>
00254    <manager name="DAHDIShowChannels" language="en_US">
00255       <synopsis>
00256          Show status of DAHDI channels.
00257       </synopsis>
00258       <syntax>
00259          <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
00260          <parameter name="DAHDIChannel">
00261             <para>Specify the specific channel number to show.  Show all channels if zero or not present.</para>
00262          </parameter>
00263       </syntax>
00264       <description>
00265          <para>Similar to the CLI command "dahdi show channels".</para>
00266       </description>
00267    </manager>
00268    <manager name="DAHDIRestart" language="en_US">
00269       <synopsis>
00270          Fully Restart DAHDI channels (terminates calls).
00271       </synopsis>
00272       <syntax>
00273          <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
00274       </syntax>
00275       <description>
00276          <para>Equivalent to the CLI command "dahdi restart".</para>
00277       </description>
00278    </manager>
00279  ***/
00280 
00281 #define SMDI_MD_WAIT_TIMEOUT 1500 /* 1.5 seconds */
00282 
00283 static const char * const lbostr[] = {
00284 "0 db (CSU)/0-133 feet (DSX-1)",
00285 "133-266 feet (DSX-1)",
00286 "266-399 feet (DSX-1)",
00287 "399-533 feet (DSX-1)",
00288 "533-655 feet (DSX-1)",
00289 "-7.5db (CSU)",
00290 "-15db (CSU)",
00291 "-22.5db (CSU)"
00292 };
00293 
00294 /*! Global jitterbuffer configuration - by default, jb is disabled
00295  *  \note Values shown here match the defaults shown in chan_dahdi.conf.sample */
00296 static struct ast_jb_conf default_jbconf =
00297 {
00298    .flags = 0,
00299    .max_size = 200,
00300    .resync_threshold = 1000,
00301    .impl = "fixed",
00302    .target_extra = 40,
00303 };
00304 static struct ast_jb_conf global_jbconf;
00305 
00306 /*!
00307  * \note Define ZHONE_HACK to cause us to go off hook and then back on hook when
00308  * the user hangs up to reset the state machine so ring works properly.
00309  * This is used to be able to support kewlstart by putting the zhone in
00310  * groundstart mode since their forward disconnect supervision is entirely
00311  * broken even though their documentation says it isn't and their support
00312  * is entirely unwilling to provide any assistance with their channel banks
00313  * even though their web site says they support their products for life.
00314  */
00315 /* #define ZHONE_HACK */
00316 
00317 /*! \brief Typically, how many rings before we should send Caller*ID */
00318 #define DEFAULT_CIDRINGS 1
00319 
00320 #define AST_LAW(p) (((p)->law == DAHDI_LAW_ALAW) ? AST_FORMAT_ALAW : AST_FORMAT_ULAW)
00321 
00322 
00323 /*! \brief Signaling types that need to use MF detection should be placed in this macro */
00324 #define NEED_MFDETECT(p) (((p)->sig == SIG_FEATDMF) || ((p)->sig == SIG_FEATDMF_TA) || ((p)->sig == SIG_E911) || ((p)->sig == SIG_FGC_CAMA) || ((p)->sig == SIG_FGC_CAMAMF) || ((p)->sig == SIG_FEATB))
00325 
00326 static const char tdesc[] = "DAHDI Telephony Driver"
00327 #if defined(HAVE_PRI) || defined(HAVE_SS7) || defined(HAVE_OPENR2)
00328    " w/"
00329    #if defined(HAVE_PRI)
00330       "PRI"
00331    #endif   /* defined(HAVE_PRI) */
00332    #if defined(HAVE_SS7)
00333       #if defined(HAVE_PRI)
00334       " & "
00335       #endif   /* defined(HAVE_PRI) */
00336       "SS7"
00337    #endif   /* defined(HAVE_SS7) */
00338    #if defined(HAVE_OPENR2)
00339       #if defined(HAVE_PRI) || defined(HAVE_SS7)
00340       " & "
00341       #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
00342       "MFC/R2"
00343    #endif   /* defined(HAVE_OPENR2) */
00344 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) || defined(HAVE_OPENR2) */
00345 ;
00346 
00347 static const char config[] = "chan_dahdi.conf";
00348 
00349 #define SIG_EM    DAHDI_SIG_EM
00350 #define SIG_EMWINK   (0x0100000 | DAHDI_SIG_EM)
00351 #define SIG_FEATD (0x0200000 | DAHDI_SIG_EM)
00352 #define  SIG_FEATDMF (0x0400000 | DAHDI_SIG_EM)
00353 #define  SIG_FEATB   (0x0800000 | DAHDI_SIG_EM)
00354 #define  SIG_E911 (0x1000000 | DAHDI_SIG_EM)
00355 #define  SIG_FEATDMF_TA (0x2000000 | DAHDI_SIG_EM)
00356 #define  SIG_FGC_CAMA   (0x4000000 | DAHDI_SIG_EM)
00357 #define  SIG_FGC_CAMAMF (0x8000000 | DAHDI_SIG_EM)
00358 #define SIG_FXSLS DAHDI_SIG_FXSLS
00359 #define SIG_FXSGS DAHDI_SIG_FXSGS
00360 #define SIG_FXSKS DAHDI_SIG_FXSKS
00361 #define SIG_FXOLS DAHDI_SIG_FXOLS
00362 #define SIG_FXOGS DAHDI_SIG_FXOGS
00363 #define SIG_FXOKS DAHDI_SIG_FXOKS
00364 #define SIG_PRI      DAHDI_SIG_CLEAR
00365 #define SIG_BRI      (0x2000000 | DAHDI_SIG_CLEAR)
00366 #define SIG_BRI_PTMP (0X4000000 | DAHDI_SIG_CLEAR)
00367 #define SIG_SS7      (0x1000000 | DAHDI_SIG_CLEAR)
00368 #define SIG_MFCR2    DAHDI_SIG_CAS
00369 #define  SIG_SF      DAHDI_SIG_SF
00370 #define SIG_SFWINK   (0x0100000 | DAHDI_SIG_SF)
00371 #define SIG_SF_FEATD (0x0200000 | DAHDI_SIG_SF)
00372 #define  SIG_SF_FEATDMF (0x0400000 | DAHDI_SIG_SF)
00373 #define  SIG_SF_FEATB   (0x0800000 | DAHDI_SIG_SF)
00374 #define SIG_EM_E1 DAHDI_SIG_EM_E1
00375 
00376 #ifdef LOTS_OF_SPANS
00377 #define NUM_SPANS DAHDI_MAX_SPANS
00378 #else
00379 #define NUM_SPANS       32
00380 #endif
00381 
00382 #define CHAN_PSEUDO  -2
00383 
00384 #define CALLPROGRESS_PROGRESS    1
00385 #define CALLPROGRESS_FAX_OUTGOING   2
00386 #define CALLPROGRESS_FAX_INCOMING   4
00387 #define CALLPROGRESS_FAX      (CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING)
00388 
00389 #define NUM_CADENCE_MAX 25
00390 static int num_cadence = 4;
00391 static int user_has_defined_cadences = 0;
00392 
00393 static struct dahdi_ring_cadence cadences[NUM_CADENCE_MAX] = {
00394    { { 125, 125, 2000, 4000 } },       /*!< Quick chirp followed by normal ring */
00395    { { 250, 250, 500, 1000, 250, 250, 500, 4000 } }, /*!< British style ring */
00396    { { 125, 125, 125, 125, 125, 4000 } }, /*!< Three short bursts */
00397    { { 1000, 500, 2500, 5000 } },   /*!< Long ring */
00398 };
00399 
00400 /*! \brief cidrings says in which pause to transmit the cid information, where the first pause
00401  * is 1, the second pause is 2 and so on.
00402  */
00403 
00404 static int cidrings[NUM_CADENCE_MAX] = {
00405    2,                            /*!< Right after first long ring */
00406    4,                            /*!< Right after long part */
00407    3,                            /*!< After third chirp */
00408    2,                            /*!< Second spell */
00409 };
00410 
00411 /* ETSI EN300 659-1 specifies the ring pulse between 200 and 300 mS */
00412 static struct dahdi_ring_cadence AS_RP_cadence = {{250, 10000}};
00413 
00414 #define ISTRUNK(p) ((p->sig == SIG_FXSLS) || (p->sig == SIG_FXSKS) || \
00415          (p->sig == SIG_FXSGS) || (p->sig == SIG_PRI))
00416 
00417 #define CANBUSYDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */)
00418 #define CANPROGRESSDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */)
00419 
00420 static char defaultcic[64] = "";
00421 static char defaultozz[64] = "";
00422 
00423 /*! Run this script when the MWI state changes on an FXO line, if mwimonitor is enabled */
00424 static char mwimonitornotify[PATH_MAX] = "";
00425 #ifndef HAVE_DAHDI_LINEREVERSE_VMWI
00426 static int  mwisend_rpas = 0;
00427 #endif
00428 
00429 static char progzone[10] = "";
00430 
00431 static int usedistinctiveringdetection = 0;
00432 static int distinctiveringaftercid = 0;
00433 
00434 static int numbufs = 4;
00435 
00436 static int mwilevel = 512;
00437 static int dtmfcid_level = 256;
00438 
00439 #define REPORT_CHANNEL_ALARMS 1
00440 #define REPORT_SPAN_ALARMS    2 
00441 static int report_alarms = REPORT_CHANNEL_ALARMS;
00442 
00443 #ifdef HAVE_PRI
00444 static int pridebugfd = -1;
00445 static char pridebugfilename[1024] = "";
00446 #endif
00447 
00448 /*! \brief Wait up to 16 seconds for first digit (FXO logic) */
00449 static int firstdigittimeout = 16000;
00450 
00451 /*! \brief How long to wait for following digits (FXO logic) */
00452 static int gendigittimeout = 8000;
00453 
00454 /*! \brief How long to wait for an extra digit, if there is an ambiguous match */
00455 static int matchdigittimeout = 3000;
00456 
00457 /*! \brief Protect the interface list (of dahdi_pvt's) */
00458 AST_MUTEX_DEFINE_STATIC(iflock);
00459 
00460 
00461 static int ifcount = 0;
00462 
00463 #ifdef HAVE_PRI
00464 AST_MUTEX_DEFINE_STATIC(pridebugfdlock);
00465 #endif
00466 
00467 /*! \brief Protect the monitoring thread, so only one process can kill or start it, and not
00468    when it's doing something critical. */
00469 AST_MUTEX_DEFINE_STATIC(monlock);
00470 
00471 /*! \brief This is the thread for the monitor which checks for input on the channels
00472    which are not currently in use. */
00473 static pthread_t monitor_thread = AST_PTHREADT_NULL;
00474 static ast_cond_t ss_thread_complete;
00475 AST_MUTEX_DEFINE_STATIC(ss_thread_lock);
00476 AST_MUTEX_DEFINE_STATIC(restart_lock);
00477 static int ss_thread_count = 0;
00478 static int num_restart_pending = 0;
00479 
00480 static int restart_monitor(void);
00481 
00482 static enum ast_bridge_result dahdi_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc, int timeoutms);
00483 
00484 static int dahdi_sendtext(struct ast_channel *c, const char *text);
00485 
00486 static void mwi_event_cb(const struct ast_event *event, void *userdata)
00487 {
00488    /* This module does not handle MWI in an event-based manner.  However, it
00489     * subscribes to MWI for each mailbox that is configured so that the core
00490     * knows that we care about it.  Then, chan_dahdi will get the MWI from the
00491     * event cache instead of checking the mailbox directly. */
00492 }
00493 
00494 /*! \brief Avoid the silly dahdi_getevent which ignores a bunch of events */
00495 static inline int dahdi_get_event(int fd)
00496 {
00497    int j;
00498    if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
00499       return -1;
00500    return j;
00501 }
00502 
00503 /*! \brief Avoid the silly dahdi_waitevent which ignores a bunch of events */
00504 static inline int dahdi_wait_event(int fd)
00505 {
00506    int i, j = 0;
00507    i = DAHDI_IOMUX_SIGEVENT;
00508    if (ioctl(fd, DAHDI_IOMUX, &i) == -1)
00509       return -1;
00510    if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
00511       return -1;
00512    return j;
00513 }
00514 
00515 /*! Chunk size to read -- we use 20ms chunks to make things happy. */
00516 #define READ_SIZE 160
00517 
00518 #define MASK_AVAIL      (1 << 0) /*!< Channel available for PRI use */
00519 #define MASK_INUSE      (1 << 1) /*!< Channel currently in use */
00520 
00521 #define CALLWAITING_SILENT_SAMPLES     ((300 * 8) / READ_SIZE) /*!< 300 ms */
00522 #define CALLWAITING_REPEAT_SAMPLES     ((10000 * 8) / READ_SIZE) /*!< 10,000 ms */
00523 #define CALLWAITING_SUPPRESS_SAMPLES   ((100 * 8) / READ_SIZE) /*!< 100 ms */
00524 #define CIDCW_EXPIRE_SAMPLES        ((500 * 8) / READ_SIZE) /*!< 500 ms */
00525 #define MIN_MS_SINCE_FLASH          ((2000) )   /*!< 2000 ms */
00526 #define DEFAULT_RINGT               ((8000 * 8) / READ_SIZE) /*!< 8,000 ms */
00527 
00528 struct dahdi_pvt;
00529 
00530 /*!
00531  * \brief Configured ring timeout base.
00532  * \note Value computed from "ringtimeout" read in from chan_dahdi.conf if it exists.
00533  */
00534 static int ringt_base = DEFAULT_RINGT;
00535 
00536 #if defined(HAVE_SS7)
00537 
00538 struct dahdi_ss7 {
00539    struct sig_ss7_linkset ss7;
00540 };
00541 
00542 static struct dahdi_ss7 linksets[NUM_SPANS];
00543 
00544 static int cur_ss7type = -1;
00545 static int cur_linkset = -1;
00546 static int cur_pointcode = -1;
00547 static int cur_cicbeginswith = -1;
00548 static int cur_adjpointcode = -1;
00549 static int cur_networkindicator = -1;
00550 static int cur_defaultdpc = -1;
00551 #endif   /* defined(HAVE_SS7) */
00552 
00553 #ifdef HAVE_OPENR2
00554 struct dahdi_mfcr2_conf {
00555    openr2_variant_t variant;
00556    int mfback_timeout;
00557    int metering_pulse_timeout;
00558    int max_ani;
00559    int max_dnis;
00560    signed int get_ani_first:2;
00561 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
00562    signed int skip_category_request:2;
00563 #endif
00564    unsigned int call_files:1;
00565    unsigned int allow_collect_calls:1;
00566    unsigned int charge_calls:1;
00567    unsigned int accept_on_offer:1;
00568    unsigned int forced_release:1;
00569    unsigned int double_answer:1;
00570    signed int immediate_accept:2;
00571    char logdir[OR2_MAX_PATH];
00572    char r2proto_file[OR2_MAX_PATH];
00573    openr2_log_level_t loglevel;
00574    openr2_calling_party_category_t category;
00575 };
00576 
00577 /* MFC-R2 pseudo-link structure */
00578 struct dahdi_mfcr2 {
00579    pthread_t r2master;            /*!< Thread of master */
00580    openr2_context_t *protocol_context;    /*!< OpenR2 context handle */
00581    struct dahdi_pvt *pvts[SIG_MFCR2_MAX_CHANNELS];     /*!< Member channel pvt structs */
00582    int numchans;                          /*!< Number of channels in this R2 block */
00583    struct dahdi_mfcr2_conf conf;         /*!< Configuration used to setup this pseudo-link */
00584 };
00585 
00586 /* malloc'd array of malloc'd r2links */
00587 static struct dahdi_mfcr2 **r2links;
00588 /* how many r2links have been malloc'd */
00589 static int r2links_count = 0;
00590 
00591 #endif /* HAVE_OPENR2 */
00592 
00593 #ifdef HAVE_PRI
00594 
00595 struct dahdi_pri {
00596    int dchannels[SIG_PRI_NUM_DCHANS];     /*!< What channel are the dchannels on */
00597    int mastertrunkgroup;               /*!< What trunk group is our master */
00598    int prilogicalspan;                 /*!< Logical span number within trunk group */
00599    struct sig_pri_span pri;
00600 };
00601 
00602 static struct dahdi_pri pris[NUM_SPANS];
00603 
00604 #if defined(HAVE_PRI_CCSS)
00605 /*! DAHDI PRI CCSS agent and monitor type name. */
00606 static const char dahdi_pri_cc_type[] = "DAHDI/PRI";
00607 #endif   /* defined(HAVE_PRI_CCSS) */
00608 
00609 #else
00610 /*! Shut up the compiler */
00611 struct dahdi_pri;
00612 #endif
00613 
00614 #define SUB_REAL  0        /*!< Active call */
00615 #define SUB_CALLWAIT 1        /*!< Call-Waiting call on hold */
00616 #define SUB_THREEWAY 2        /*!< Three-way call */
00617 
00618 /* Polarity states */
00619 #define POLARITY_IDLE   0
00620 #define POLARITY_REV    1
00621 
00622 
00623 struct distRingData {
00624    int ring[3];
00625    int range;
00626 };
00627 struct ringContextData {
00628    char contextData[AST_MAX_CONTEXT];
00629 };
00630 struct dahdi_distRings {
00631    struct distRingData ringnum[3];
00632    struct ringContextData ringContext[3];
00633 };
00634 
00635 static const char * const subnames[] = {
00636    "Real",
00637    "Callwait",
00638    "Threeway"
00639 };
00640 
00641 struct dahdi_subchannel {
00642    int dfd;
00643    struct ast_channel *owner;
00644    int chan;
00645    short buffer[AST_FRIENDLY_OFFSET/2 + READ_SIZE];
00646    struct ast_frame f;     /*!< One frame for each channel.  How did this ever work before? */
00647    unsigned int needringing:1;
00648    unsigned int needbusy:1;
00649    unsigned int needcongestion:1;
00650    unsigned int needanswer:1;
00651    unsigned int needflash:1;
00652    unsigned int needhold:1;
00653    unsigned int needunhold:1;
00654    unsigned int linear:1;
00655    unsigned int inthreeway:1;
00656    struct dahdi_confinfo curconf;
00657 };
00658 
00659 #define CONF_USER_REAL     (1 << 0)
00660 #define CONF_USER_THIRDCALL   (1 << 1)
00661 
00662 #define MAX_SLAVES   4
00663 
00664 /* States for sending MWI message
00665  * First three states are required for send Ring Pulse Alert Signal
00666  */
00667 typedef enum {
00668    MWI_SEND_NULL = 0,
00669    MWI_SEND_SA,
00670    MWI_SEND_SA_WAIT,
00671    MWI_SEND_PAUSE,
00672    MWI_SEND_SPILL,
00673    MWI_SEND_CLEANUP,
00674    MWI_SEND_DONE,
00675 } mwisend_states;
00676 
00677 struct mwisend_info {
00678    struct   timeval  pause;
00679    mwisend_states    mwisend_current;
00680 };
00681 
00682 /*! Specify the lists dahdi_pvt can be put in. */
00683 enum DAHDI_IFLIST {
00684    DAHDI_IFLIST_NONE,   /*!< The dahdi_pvt is not in any list. */
00685    DAHDI_IFLIST_MAIN,   /*!< The dahdi_pvt is in the main interface list */
00686 #if defined(HAVE_PRI)
00687    DAHDI_IFLIST_NO_B_CHAN, /*!< The dahdi_pvt is in a no B channel interface list */
00688 #endif   /* defined(HAVE_PRI) */
00689 };
00690 
00691 struct dahdi_pvt {
00692    ast_mutex_t lock;             /*!< Channel private lock. */
00693    struct callerid_state *cs;
00694    struct ast_channel *owner;       /*!< Our current active owner (if applicable) */
00695                      /*!< Up to three channels can be associated with this call */
00696 
00697    struct dahdi_subchannel sub_unused;    /*!< Just a safety precaution */
00698    struct dahdi_subchannel subs[3];       /*!< Sub-channels */
00699    struct dahdi_confinfo saveconf;        /*!< Saved conference info */
00700 
00701    struct dahdi_pvt *slaves[MAX_SLAVES];     /*!< Slave to us (follows our conferencing) */
00702    struct dahdi_pvt *master;           /*!< Master to us (we follow their conferencing) */
00703    int inconference;          /*!< If our real should be in the conference */
00704 
00705    int bufsize;                /*!< Size of the buffers */
00706    int buf_no;             /*!< Number of buffers */
00707    int buf_policy;            /*!< Buffer policy */
00708    int faxbuf_no;              /*!< Number of Fax buffers */
00709    int faxbuf_policy;          /*!< Fax buffer policy */
00710    int sig;             /*!< Signalling style */
00711    /*!
00712     * \brief Nonzero if the signaling type is sent over a radio.
00713     * \note Set to a couple of nonzero values but it is only tested like a boolean.
00714     */
00715    int radio;
00716    int outsigmod;             /*!< Outbound Signalling style (modifier) */
00717    int oprmode;               /*!< "Operator Services" mode */
00718    struct dahdi_pvt *oprpeer;          /*!< "Operator Services" peer tech_pvt ptr */
00719    /*! \brief Amount of gain to increase during caller id */
00720    float cid_rxgain;
00721    /*! \brief Software Rx gain set by chan_dahdi.conf */
00722    float rxgain;
00723    /*! \brief Software Tx gain set by chan_dahdi.conf */
00724    float txgain;
00725 
00726    float txdrc; /*!< Dynamic Range Compression factor. a number between 1 and 6ish */
00727    float rxdrc;
00728    
00729    int tonezone;              /*!< tone zone for this chan, or -1 for default */
00730    enum DAHDI_IFLIST which_iflist;  /*!< Which interface list is this structure listed? */
00731    struct dahdi_pvt *next;          /*!< Next channel in list */
00732    struct dahdi_pvt *prev;          /*!< Prev channel in list */
00733 
00734    /* flags */
00735 
00736    /*!
00737     * \brief TRUE if ADSI (Analog Display Services Interface) available
00738     * \note Set from the "adsi" value read in from chan_dahdi.conf
00739     */
00740    unsigned int adsi:1;
00741    /*!
00742     * \brief TRUE if we can use a polarity reversal to mark when an outgoing
00743     * call is answered by the remote party.
00744     * \note Set from the "answeronpolarityswitch" value read in from chan_dahdi.conf
00745     */
00746    unsigned int answeronpolarityswitch:1;
00747    /*!
00748     * \brief TRUE if busy detection is enabled.
00749     * (Listens for the beep-beep busy pattern.)
00750     * \note Set from the "busydetect" value read in from chan_dahdi.conf
00751     */
00752    unsigned int busydetect:1;
00753    /*!
00754     * \brief TRUE if call return is enabled.
00755     * (*69, if your dialplan doesn't catch this first)
00756     * \note Set from the "callreturn" value read in from chan_dahdi.conf
00757     */
00758    unsigned int callreturn:1;
00759    /*!
00760     * \brief TRUE if busy extensions will hear the call-waiting tone
00761     * and can use hook-flash to switch between callers.
00762     * \note Can be disabled by dialing *70.
00763     * \note Initialized with the "callwaiting" value read in from chan_dahdi.conf
00764     */
00765    unsigned int callwaiting:1;
00766    /*!
00767     * \brief TRUE if send caller ID for Call Waiting
00768     * \note Set from the "callwaitingcallerid" value read in from chan_dahdi.conf
00769     */
00770    unsigned int callwaitingcallerid:1;
00771    /*!
00772     * \brief TRUE if support for call forwarding enabled.
00773     * Dial *72 to enable call forwarding.
00774     * Dial *73 to disable call forwarding.
00775     * \note Set from the "cancallforward" value read in from chan_dahdi.conf
00776     */
00777    unsigned int cancallforward:1;
00778    /*!
00779     * \brief TRUE if support for call parking is enabled.
00780     * \note Set from the "canpark" value read in from chan_dahdi.conf
00781     */
00782    unsigned int canpark:1;
00783    /*! \brief TRUE if to wait for a DTMF digit to confirm answer */
00784    unsigned int confirmanswer:1;
00785    /*!
00786     * \brief TRUE if the channel is to be destroyed on hangup.
00787     * (Used by pseudo channels.)
00788     */
00789    unsigned int destroy:1;
00790    unsigned int didtdd:1;           /*!< flag to say its done it once */
00791    /*! \brief TRUE if analog type line dialed no digits in Dial() */
00792    unsigned int dialednone:1;
00793    /*!
00794     * \brief TRUE if in the process of dialing digits or sending something.
00795     * \note This is used as a receive squelch for ISDN until connected.
00796     */
00797    unsigned int dialing:1;
00798    /*! \brief TRUE if the transfer capability of the call is digital. */
00799    unsigned int digital:1;
00800    /*! \brief TRUE if Do-Not-Disturb is enabled, present only for non sig_analog */
00801    unsigned int dnd:1;
00802    /*! \brief XXX BOOLEAN Purpose??? */
00803    unsigned int echobreak:1;
00804    /*!
00805     * \brief TRUE if echo cancellation enabled when bridged.
00806     * \note Initialized with the "echocancelwhenbridged" value read in from chan_dahdi.conf
00807     * \note Disabled if the echo canceller is not setup.
00808     */
00809    unsigned int echocanbridged:1;
00810    /*! \brief TRUE if echo cancellation is turned on. */
00811    unsigned int echocanon:1;
00812    /*! \brief TRUE if a fax tone has already been handled. */
00813    unsigned int faxhandled:1;
00814    /*! TRUE if dynamic faxbuffers are configured for use, default is OFF */
00815    unsigned int usefaxbuffers:1;
00816    /*! TRUE while buffer configuration override is in use */
00817    unsigned int bufferoverrideinuse:1;
00818    /*! \brief TRUE if over a radio and dahdi_read() has been called. */
00819    unsigned int firstradio:1;
00820    /*!
00821     * \brief TRUE if the call will be considered "hung up" on a polarity reversal.
00822     * \note Set from the "hanguponpolarityswitch" value read in from chan_dahdi.conf
00823     */
00824    unsigned int hanguponpolarityswitch:1;
00825    /*! \brief TRUE if DTMF detection needs to be done by hardware. */
00826    unsigned int hardwaredtmf:1;
00827    /*!
00828     * \brief TRUE if the outgoing caller ID is blocked/hidden.
00829     * \note Caller ID can be disabled by dialing *67.
00830     * \note Caller ID can be enabled by dialing *82.
00831     * \note Initialized with the "hidecallerid" value read in from chan_dahdi.conf
00832     */
00833    unsigned int hidecallerid:1;
00834    /*!
00835     * \brief TRUE if hide just the name not the number for legacy PBX use.
00836     * \note Only applies to PRI channels.
00837     * \note Set from the "hidecalleridname" value read in from chan_dahdi.conf
00838     */
00839    unsigned int hidecalleridname:1;
00840    /*! \brief TRUE if DTMF detection is disabled. */
00841    unsigned int ignoredtmf:1;
00842    /*!
00843     * \brief TRUE if the channel should be answered immediately
00844     * without attempting to gather any digits.
00845     * \note Set from the "immediate" value read in from chan_dahdi.conf
00846     */
00847    unsigned int immediate:1;
00848    /*! \brief TRUE if in an alarm condition. */
00849    unsigned int inalarm:1;
00850    /*! \brief TRUE if TDD in MATE mode */
00851    unsigned int mate:1;
00852    /*! \brief TRUE if we originated the call leg. */
00853    unsigned int outgoing:1;
00854    /* unsigned int overlapdial:1;         unused and potentially confusing */
00855    /*!
00856     * \brief TRUE if busy extensions will hear the call-waiting tone
00857     * and can use hook-flash to switch between callers.
00858     * \note Set from the "callwaiting" value read in from chan_dahdi.conf
00859     */
00860    unsigned int permcallwaiting:1;
00861    /*!
00862     * \brief TRUE if the outgoing caller ID is blocked/restricted/hidden.
00863     * \note Set from the "hidecallerid" value read in from chan_dahdi.conf
00864     */
00865    unsigned int permhidecallerid:1;
00866    /*!
00867     * \brief TRUE if PRI congestion/busy indications are sent out-of-band.
00868     * \note Set from the "priindication" value read in from chan_dahdi.conf
00869     */
00870    unsigned int priindication_oob:1;
00871    /*!
00872     * \brief TRUE if PRI B channels are always exclusively selected.
00873     * \note Set from the "priexclusive" value read in from chan_dahdi.conf
00874     */
00875    unsigned int priexclusive:1;
00876    /*!
00877     * \brief TRUE if we will pulse dial.
00878     * \note Set from the "pulsedial" value read in from chan_dahdi.conf
00879     */
00880    unsigned int pulse:1;
00881    /*! \brief TRUE if a pulsed digit was detected. (Pulse dial phone detected) */
00882    unsigned int pulsedial:1;
00883    unsigned int restartpending:1;      /*!< flag to ensure counted only once for restart */
00884    /*!
00885     * \brief TRUE if caller ID is restricted.
00886     * \note Set but not used.  Should be deleted.  Redundant with permhidecallerid.
00887     * \note Set from the "restrictcid" value read in from chan_dahdi.conf
00888     */
00889    unsigned int restrictcid:1;
00890    /*!
00891     * \brief TRUE if three way calling is enabled
00892     * \note Set from the "threewaycalling" value read in from chan_dahdi.conf
00893     */
00894    unsigned int threewaycalling:1;
00895    /*!
00896     * \brief TRUE if call transfer is enabled
00897     * \note For FXS ports (either direct analog or over T1/E1):
00898     *   Support flash-hook call transfer
00899     * \note For digital ports using ISDN PRI protocols:
00900     *   Support switch-side transfer (called 2BCT, RLT or other names)
00901     * \note Set from the "transfer" value read in from chan_dahdi.conf
00902     */
00903    unsigned int transfer:1;
00904    /*!
00905     * \brief TRUE if caller ID is used on this channel.
00906     * \note PRI and SS7 spans will save caller ID from the networking peer.
00907     * \note FXS ports will generate the caller ID spill.
00908     * \note FXO ports will listen for the caller ID spill.
00909     * \note Set from the "usecallerid" value read in from chan_dahdi.conf
00910     */
00911    unsigned int use_callerid:1;
00912    /*!
00913     * \brief TRUE if we will use the calling presentation setting
00914     * from the Asterisk channel for outgoing calls.
00915     * \note Only applies to PRI and SS7 channels.
00916     * \note Set from the "usecallingpres" value read in from chan_dahdi.conf
00917     */
00918    unsigned int use_callingpres:1;
00919    /*!
00920     * \brief TRUE if distinctive rings are to be detected.
00921     * \note For FXO lines
00922     * \note Set indirectly from the "usedistinctiveringdetection" value read in from chan_dahdi.conf
00923     */
00924    unsigned int usedistinctiveringdetection:1;
00925    /*!
00926     * \brief TRUE if we should use the callerid from incoming call on dahdi transfer.
00927     * \note Set from the "useincomingcalleridondahditransfer" value read in from chan_dahdi.conf
00928     */
00929    unsigned int dahditrcallerid:1;
00930    /*!
00931     * \brief TRUE if allowed to flash-transfer to busy channels.
00932     * \note Set from the "transfertobusy" value read in from chan_dahdi.conf
00933     */
00934    unsigned int transfertobusy:1;
00935    /*!
00936     * \brief TRUE if the FXO port monitors for neon type MWI indications from the other end.
00937     * \note Set if the "mwimonitor" value read in contains "neon" from chan_dahdi.conf
00938     */
00939    unsigned int mwimonitor_neon:1;
00940    /*!
00941     * \brief TRUE if the FXO port monitors for fsk type MWI indications from the other end.
00942     * \note Set if the "mwimonitor" value read in contains "fsk" from chan_dahdi.conf
00943     */
00944    unsigned int mwimonitor_fsk:1;
00945    /*!
00946     * \brief TRUE if the FXO port monitors for rpas precursor to fsk MWI indications from the other end.
00947     * \note RPAS - Ring Pulse Alert Signal
00948     * \note Set if the "mwimonitor" value read in contains "rpas" from chan_dahdi.conf
00949     */
00950    unsigned int mwimonitor_rpas:1;
00951    /*! \brief TRUE if an MWI monitor thread is currently active */
00952    unsigned int mwimonitoractive:1;
00953    /*! \brief TRUE if a MWI message sending thread is active */
00954    unsigned int mwisendactive:1;
00955    /*!
00956     * \brief TRUE if channel is out of reset and ready
00957     * \note Set but not used.
00958     */
00959    unsigned int inservice:1;
00960    /*!
00961     * \brief TRUE if the channel is locally blocked.
00962     * \note Applies to SS7 and MFCR2 channels.
00963     */
00964    unsigned int locallyblocked:1;
00965    /*!
00966     * \brief TRUE if the channel is remotely blocked.
00967     * \note Applies to SS7 and MFCR2 channels.
00968     */
00969    unsigned int remotelyblocked:1;
00970    /*!
00971     * \brief TRUE if the channel alarms will be managed also as Span ones
00972     * \note Applies to all channels
00973     */
00974    unsigned int manages_span_alarms:1;
00975 
00976 #if defined(HAVE_PRI)
00977    struct sig_pri_span *pri;
00978    int logicalspan;
00979 #endif
00980    /*!
00981     * \brief TRUE if SMDI (Simplified Message Desk Interface) is enabled
00982     * \note Set from the "usesmdi" value read in from chan_dahdi.conf
00983     */
00984    unsigned int use_smdi:1;
00985    struct mwisend_info mwisend_data;
00986    /*! \brief The SMDI interface to get SMDI messages from. */
00987    struct ast_smdi_interface *smdi_iface;
00988 
00989    /*! \brief Distinctive Ring data */
00990    struct dahdi_distRings drings;
00991 
00992    /*!
00993     * \brief The configured context for incoming calls.
00994     * \note The "context" string read in from chan_dahdi.conf
00995     */
00996    char context[AST_MAX_CONTEXT];
00997    /*!
00998     * \brief Saved context string.
00999     */
01000    char defcontext[AST_MAX_CONTEXT];
01001    /*! \brief Extension to use in the dialplan. */
01002    char exten[AST_MAX_EXTENSION];
01003    /*!
01004     * \brief Language configured for calls.
01005     * \note The "language" string read in from chan_dahdi.conf
01006     */
01007    char language[MAX_LANGUAGE];
01008    /*!
01009     * \brief The configured music-on-hold class to use for calls.
01010     * \note The "musicclass" or "mohinterpret" or "musiconhold" string read in from chan_dahdi.conf
01011     */
01012    char mohinterpret[MAX_MUSICCLASS];
01013    /*!
01014     * \brief Suggested music-on-hold class for peer channel to use for calls.
01015     * \note The "mohsuggest" string read in from chan_dahdi.conf
01016     */
01017    char mohsuggest[MAX_MUSICCLASS];
01018    char parkinglot[AST_MAX_EXTENSION]; /*!< Parking lot for this channel */
01019 #if defined(HAVE_PRI) || defined(HAVE_SS7)
01020    /*! \brief Automatic Number Identification number (Alternate PRI caller ID number) */
01021    char cid_ani[AST_MAX_EXTENSION];
01022 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
01023    /*! \brief Automatic Number Identification code from PRI */
01024    int cid_ani2;
01025    /*! \brief Caller ID number from an incoming call. */
01026    char cid_num[AST_MAX_EXTENSION];
01027    /*!
01028     * \brief Caller ID tag from incoming call
01029     * \note the "cid_tag" string read in from chan_dahdi.conf
01030     */
01031    char cid_tag[AST_MAX_EXTENSION];
01032    /*! \brief Caller ID Q.931 TON/NPI field values.  Set by PRI. Zero otherwise. */
01033    int cid_ton;
01034    /*! \brief Caller ID name from an incoming call. */
01035    char cid_name[AST_MAX_EXTENSION];
01036    /*! \brief Caller ID subaddress from an incoming call. */
01037    char cid_subaddr[AST_MAX_EXTENSION];
01038    char *origcid_num;            /*!< malloced original callerid */
01039    char *origcid_name;           /*!< malloced original callerid */
01040    /*! \brief Call waiting number. */
01041    char callwait_num[AST_MAX_EXTENSION];
01042    /*! \brief Call waiting name. */
01043    char callwait_name[AST_MAX_EXTENSION];
01044    /*! \brief Redirecting Directory Number Information Service (RDNIS) number */
01045    char rdnis[AST_MAX_EXTENSION];
01046    /*! \brief Dialed Number Identifier */
01047    char dnid[AST_MAX_EXTENSION];
01048    /*!
01049     * \brief Bitmapped groups this belongs to.
01050     * \note The "group" bitmapped group string read in from chan_dahdi.conf
01051     */
01052    ast_group_t group;
01053    /*! \brief Default call PCM encoding format: DAHDI_LAW_ALAW or DAHDI_LAW_MULAW. */
01054    int law_default;
01055    /*! \brief Active PCM encoding format: DAHDI_LAW_ALAW or DAHDI_LAW_MULAW */
01056    int law;
01057    int confno;             /*!< Our conference */
01058    int confusers;             /*!< Who is using our conference */
01059    int propconfno;               /*!< Propagated conference number */
01060    /*!
01061     * \brief Bitmapped call groups this belongs to.
01062     * \note The "callgroup" bitmapped group string read in from chan_dahdi.conf
01063     */
01064    ast_group_t callgroup;
01065    /*!
01066     * \brief Bitmapped pickup groups this belongs to.
01067     * \note The "pickupgroup" bitmapped group string read in from chan_dahdi.conf
01068     */
01069    ast_group_t pickupgroup;
01070    /*!
01071     * \brief Channel variable list with associated values to set when a channel is created.
01072     * \note The "setvar" strings read in from chan_dahdi.conf
01073     */
01074    struct ast_variable *vars;
01075    int channel;               /*!< Channel Number */
01076    int span;               /*!< Span number */
01077    time_t guardtime;          /*!< Must wait this much time before using for new call */
01078    int cid_signalling;           /*!< CID signalling type bell202 or v23 */
01079    int cid_start;             /*!< CID start indicator, polarity or ring or DTMF without warning event */
01080    int dtmfcid_holdoff_state;    /*!< State indicator that allows for line to settle before checking for dtmf energy */
01081    struct timeval dtmfcid_delay;  /*!< Time value used for allow line to settle */
01082    int callingpres;           /*!< The value of calling presentation that we're going to use when placing a PRI call */
01083    int callwaitingrepeat;           /*!< How many samples to wait before repeating call waiting */
01084    int cidcwexpire;           /*!< When to stop waiting for CID/CW CAS response (In samples) */
01085    int cid_suppress_expire;      /*!< How many samples to suppress after a CID spill. */
01086    /*! \brief Analog caller ID waveform sample buffer */
01087    unsigned char *cidspill;
01088    /*! \brief Position in the cidspill buffer to send out next. */
01089    int cidpos;
01090    /*! \brief Length of the cidspill buffer containing samples. */
01091    int cidlen;
01092    /*! \brief Ring timeout timer?? */
01093    int ringt;
01094    /*!
01095     * \brief Ring timeout base.
01096     * \note Value computed indirectly from "ringtimeout" read in from chan_dahdi.conf
01097     */
01098    int ringt_base;
01099    /*!
01100     * \brief Number of most significant digits/characters to strip from the dialed number.
01101     * \note Feature is deprecated.  Use dialplan logic.
01102     * \note The characters are stripped before the PRI TON/NPI prefix
01103     * characters are processed.
01104     */
01105    int stripmsd;
01106    /*!
01107     * \brief TRUE if Call Waiting (CW) CPE Alert Signal (CAS) is being sent.
01108     * \note
01109     * After CAS is sent, the call waiting caller id will be sent if the phone
01110     * gives a positive reply.
01111     */
01112    int callwaitcas;
01113    /*! \brief Number of call waiting rings. */
01114    int callwaitrings;
01115    /*! \brief Echo cancel parameters. */
01116    struct {
01117       struct dahdi_echocanparams head;
01118       struct dahdi_echocanparam params[DAHDI_MAX_ECHOCANPARAMS];
01119    } echocancel;
01120    /*!
01121     * \brief Echo training time. 0 = disabled
01122     * \note Set from the "echotraining" value read in from chan_dahdi.conf
01123     */
01124    int echotraining;
01125    /*! \brief Filled with 'w'.  XXX Purpose?? */
01126    char echorest[20];
01127    /*!
01128     * \brief Number of times to see "busy" tone before hanging up.
01129     * \note Set from the "busycount" value read in from chan_dahdi.conf
01130     */
01131    int busycount;
01132    /*!
01133     * \brief Length of "busy" tone on time.
01134     * \note Set from the "busypattern" value read in from chan_dahdi.conf
01135     */
01136    int busy_tonelength;
01137    /*!
01138     * \brief Length of "busy" tone off time.
01139     * \note Set from the "busypattern" value read in from chan_dahdi.conf
01140     */
01141    int busy_quietlength;
01142    /*!
01143     * \brief Bitmapped call progress detection flags. CALLPROGRESS_xxx values.
01144     * \note Bits set from the "callprogress" and "faxdetect" values read in from chan_dahdi.conf
01145     */
01146    int callprogress;
01147    /*!
01148     * \brief Number of milliseconds to wait for dialtone.
01149     * \note Set from the "waitfordialtone" value read in from chan_dahdi.conf
01150     */
01151    int waitfordialtone;
01152    struct timeval waitingfordt;        /*!< Time we started waiting for dialtone */
01153    struct timeval flashtime;        /*!< Last flash-hook time */
01154    /*! \brief Opaque DSP configuration structure. */
01155    struct ast_dsp *dsp;
01156    /*! \brief DAHDI dial operation command struct for ioctl() call. */
01157    struct dahdi_dialoperation dop;
01158    int whichwink;             /*!< SIG_FEATDMF_TA Which wink are we on? */
01159    /*! \brief Second part of SIG_FEATDMF_TA wink operation. */
01160    char finaldial[64];
01161    char accountcode[AST_MAX_ACCOUNT_CODE];      /*!< Account code */
01162    int amaflags;              /*!< AMA Flags */
01163    struct tdd_state *tdd;           /*!< TDD flag */
01164    /*! \brief Accumulated call forwarding number. */
01165    char call_forward[AST_MAX_EXTENSION];
01166    /*!
01167     * \brief Voice mailbox location.
01168     * \note Set from the "mailbox" string read in from chan_dahdi.conf
01169     */
01170    char mailbox[AST_MAX_EXTENSION];
01171    /*! \brief Opaque event subscription parameters for message waiting indication support. */
01172    struct ast_event_sub *mwi_event_sub;
01173    /*! \brief Delayed dialing for E911.  Overlap digits for ISDN. */
01174    char dialdest[256];
01175 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
01176    struct dahdi_vmwi_info mwisend_setting;            /*!< Which VMWI methods to use */
01177    unsigned int mwisend_fsk: 1;     /*! Variable for enabling FSK MWI handling in chan_dahdi */
01178    unsigned int mwisend_rpas:1;     /*! Variable for enabling Ring Pulse Alert before MWI FSK Spill */
01179 #endif
01180    int distinctivering;          /*!< Which distinctivering to use */
01181    int dtmfrelax;             /*!< whether to run in relaxed DTMF mode */
01182    /*! \brief Holding place for event injected from outside normal operation. */
01183    int fake_event;
01184    /*!
01185     * \brief Minimal time period (ms) between the answer polarity
01186     * switch and hangup polarity switch.
01187     */
01188    int polarityonanswerdelay;
01189    /*! \brief Start delay time if polarityonanswerdelay is nonzero. */
01190    struct timeval polaritydelaytv;
01191    /*!
01192     * \brief Send caller ID on FXS after this many rings. Set to 1 for US.
01193     * \note Set from the "sendcalleridafter" value read in from chan_dahdi.conf
01194     */
01195    int sendcalleridafter;
01196    /*! \brief Current line interface polarity. POLARITY_IDLE, POLARITY_REV */
01197    int polarity;
01198    /*! \brief DSP feature flags: DSP_FEATURE_xxx */
01199    int dsp_features;
01200 #if defined(HAVE_SS7)
01201    /*! \brief SS7 control parameters */
01202    struct sig_ss7_linkset *ss7;
01203 #endif   /* defined(HAVE_SS7) */
01204 #ifdef HAVE_OPENR2
01205    struct dahdi_mfcr2 *mfcr2;
01206    openr2_chan_t *r2chan;
01207    openr2_calling_party_category_t mfcr2_recvd_category;
01208    openr2_calling_party_category_t mfcr2_category;
01209    int mfcr2_dnis_index;
01210    int mfcr2_ani_index;
01211    int mfcr2call:1;
01212    int mfcr2_answer_pending:1;
01213    int mfcr2_charge_calls:1;
01214    int mfcr2_allow_collect_calls:1;
01215    int mfcr2_forced_release:1;
01216    int mfcr2_dnis_matched:1;
01217    int mfcr2_call_accepted:1;
01218    int mfcr2_progress:1;
01219    int mfcr2_accept_on_offer:1;
01220 #endif
01221    /*! \brief DTMF digit in progress.  0 when no digit in progress. */
01222    char begindigit;
01223    /*! \brief TRUE if confrence is muted. */
01224    int muting;
01225    void *sig_pvt;
01226    struct ast_cc_config_params *cc_params;
01227    /* DAHDI channel names may differ greatly from the
01228     * string that was provided to an app such as Dial. We
01229     * need to save the original string passed to dahdi_request
01230     * for call completion purposes. This way, we can replicate
01231     * the original dialed string later.
01232     */
01233    char dialstring[AST_CHANNEL_NAME];
01234 };
01235 
01236 #define DATA_EXPORT_DAHDI_PVT(MEMBER)              \
01237    MEMBER(dahdi_pvt, cid_rxgain, AST_DATA_DOUBLE)        \
01238    MEMBER(dahdi_pvt, rxgain, AST_DATA_DOUBLE)         \
01239    MEMBER(dahdi_pvt, txgain, AST_DATA_DOUBLE)         \
01240    MEMBER(dahdi_pvt, txdrc, AST_DATA_DOUBLE)       \
01241    MEMBER(dahdi_pvt, rxdrc, AST_DATA_DOUBLE)       \
01242    MEMBER(dahdi_pvt, adsi, AST_DATA_BOOLEAN)       \
01243    MEMBER(dahdi_pvt, answeronpolarityswitch, AST_DATA_BOOLEAN) \
01244    MEMBER(dahdi_pvt, busydetect, AST_DATA_BOOLEAN)       \
01245    MEMBER(dahdi_pvt, callreturn, AST_DATA_BOOLEAN)       \
01246    MEMBER(dahdi_pvt, callwaiting, AST_DATA_BOOLEAN)      \
01247    MEMBER(dahdi_pvt, callwaitingcallerid, AST_DATA_BOOLEAN) \
01248    MEMBER(dahdi_pvt, cancallforward, AST_DATA_BOOLEAN)      \
01249    MEMBER(dahdi_pvt, canpark, AST_DATA_BOOLEAN)       \
01250    MEMBER(dahdi_pvt, confirmanswer, AST_DATA_BOOLEAN)    \
01251    MEMBER(dahdi_pvt, destroy, AST_DATA_BOOLEAN)       \
01252    MEMBER(dahdi_pvt, didtdd, AST_DATA_BOOLEAN)        \
01253    MEMBER(dahdi_pvt, dialednone, AST_DATA_BOOLEAN)       \
01254    MEMBER(dahdi_pvt, dialing, AST_DATA_BOOLEAN)       \
01255    MEMBER(dahdi_pvt, digital, AST_DATA_BOOLEAN)       \
01256    MEMBER(dahdi_pvt, dnd, AST_DATA_BOOLEAN)        \
01257    MEMBER(dahdi_pvt, echobreak, AST_DATA_BOOLEAN)        \
01258    MEMBER(dahdi_pvt, echocanbridged, AST_DATA_BOOLEAN)      \
01259    MEMBER(dahdi_pvt, echocanon, AST_DATA_BOOLEAN)        \
01260    MEMBER(dahdi_pvt, faxhandled, AST_DATA_BOOLEAN)       \
01261    MEMBER(dahdi_pvt, usefaxbuffers, AST_DATA_BOOLEAN)    \
01262    MEMBER(dahdi_pvt, bufferoverrideinuse, AST_DATA_BOOLEAN) \
01263    MEMBER(dahdi_pvt, firstradio, AST_DATA_BOOLEAN)       \
01264    MEMBER(dahdi_pvt, hanguponpolarityswitch, AST_DATA_BOOLEAN) \
01265    MEMBER(dahdi_pvt, hardwaredtmf, AST_DATA_BOOLEAN)     \
01266    MEMBER(dahdi_pvt, hidecallerid, AST_DATA_BOOLEAN)     \
01267    MEMBER(dahdi_pvt, hidecalleridname, AST_DATA_BOOLEAN)    \
01268    MEMBER(dahdi_pvt, ignoredtmf, AST_DATA_BOOLEAN)       \
01269    MEMBER(dahdi_pvt, immediate, AST_DATA_BOOLEAN)        \
01270    MEMBER(dahdi_pvt, inalarm, AST_DATA_BOOLEAN)       \
01271    MEMBER(dahdi_pvt, mate, AST_DATA_BOOLEAN)       \
01272    MEMBER(dahdi_pvt, outgoing, AST_DATA_BOOLEAN)         \
01273    MEMBER(dahdi_pvt, permcallwaiting, AST_DATA_BOOLEAN)     \
01274    MEMBER(dahdi_pvt, priindication_oob, AST_DATA_BOOLEAN)      \
01275    MEMBER(dahdi_pvt, priexclusive, AST_DATA_BOOLEAN)     \
01276    MEMBER(dahdi_pvt, pulse, AST_DATA_BOOLEAN)         \
01277    MEMBER(dahdi_pvt, pulsedial, AST_DATA_BOOLEAN)        \
01278    MEMBER(dahdi_pvt, restartpending, AST_DATA_BOOLEAN)      \
01279    MEMBER(dahdi_pvt, restrictcid, AST_DATA_BOOLEAN)      \
01280    MEMBER(dahdi_pvt, threewaycalling, AST_DATA_BOOLEAN)     \
01281    MEMBER(dahdi_pvt, transfer, AST_DATA_BOOLEAN)         \
01282    MEMBER(dahdi_pvt, use_callerid, AST_DATA_BOOLEAN)     \
01283    MEMBER(dahdi_pvt, use_callingpres, AST_DATA_BOOLEAN)     \
01284    MEMBER(dahdi_pvt, usedistinctiveringdetection, AST_DATA_BOOLEAN)  \
01285    MEMBER(dahdi_pvt, dahditrcallerid, AST_DATA_BOOLEAN)        \
01286    MEMBER(dahdi_pvt, transfertobusy, AST_DATA_BOOLEAN)         \
01287    MEMBER(dahdi_pvt, mwimonitor_neon, AST_DATA_BOOLEAN)        \
01288    MEMBER(dahdi_pvt, mwimonitor_fsk, AST_DATA_BOOLEAN)         \
01289    MEMBER(dahdi_pvt, mwimonitor_rpas, AST_DATA_BOOLEAN)        \
01290    MEMBER(dahdi_pvt, mwimonitoractive, AST_DATA_BOOLEAN)       \
01291    MEMBER(dahdi_pvt, mwisendactive, AST_DATA_BOOLEAN)       \
01292    MEMBER(dahdi_pvt, inservice, AST_DATA_BOOLEAN)           \
01293    MEMBER(dahdi_pvt, locallyblocked, AST_DATA_BOOLEAN)         \
01294    MEMBER(dahdi_pvt, remotelyblocked, AST_DATA_BOOLEAN)        \
01295    MEMBER(dahdi_pvt, manages_span_alarms, AST_DATA_BOOLEAN)    \
01296    MEMBER(dahdi_pvt, use_smdi, AST_DATA_BOOLEAN)            \
01297    MEMBER(dahdi_pvt, context, AST_DATA_STRING)           \
01298    MEMBER(dahdi_pvt, defcontext, AST_DATA_STRING)           \
01299    MEMBER(dahdi_pvt, exten, AST_DATA_STRING)          \
01300    MEMBER(dahdi_pvt, language, AST_DATA_STRING)          \
01301    MEMBER(dahdi_pvt, mohinterpret, AST_DATA_STRING)         \
01302    MEMBER(dahdi_pvt, mohsuggest, AST_DATA_STRING)           \
01303    MEMBER(dahdi_pvt, parkinglot, AST_DATA_STRING)
01304 
01305 AST_DATA_STRUCTURE(dahdi_pvt, DATA_EXPORT_DAHDI_PVT);
01306 
01307 static struct dahdi_pvt *iflist = NULL;   /*!< Main interface list start */
01308 static struct dahdi_pvt *ifend = NULL; /*!< Main interface list end */
01309 
01310 #if defined(HAVE_PRI)
01311 static struct dahdi_parms_pseudo {
01312    int buf_no;             /*!< Number of buffers */
01313    int buf_policy;            /*!< Buffer policy */
01314    int faxbuf_no;              /*!< Number of Fax buffers */
01315    int faxbuf_policy;          /*!< Fax buffer policy */
01316 } dahdi_pseudo_parms;
01317 #endif   /* defined(HAVE_PRI) */
01318 
01319 /*! \brief Channel configuration from chan_dahdi.conf .
01320  * This struct is used for parsing the [channels] section of chan_dahdi.conf.
01321  * Generally there is a field here for every possible configuration item.
01322  *
01323  * The state of fields is saved along the parsing and whenever a 'channel'
01324  * statement is reached, the current dahdi_chan_conf is used to configure the
01325  * channel (struct dahdi_pvt)
01326  *
01327  * \see dahdi_chan_init for the default values.
01328  */
01329 struct dahdi_chan_conf {
01330    struct dahdi_pvt chan;
01331 #ifdef HAVE_PRI
01332    struct dahdi_pri pri;
01333 #endif
01334 
01335 #if defined(HAVE_SS7)
01336    struct dahdi_ss7 ss7;
01337 #endif   /* defined(HAVE_SS7) */
01338 
01339 #ifdef HAVE_OPENR2
01340    struct dahdi_mfcr2_conf mfcr2;
01341 #endif
01342    struct dahdi_params timing;
01343    int is_sig_auto; /*!< Use channel signalling from DAHDI? */
01344    /*! Continue configuration even if a channel is not there. */
01345    int ignore_failed_channels;
01346 
01347    /*!
01348     * \brief The serial port to listen for SMDI data on
01349     * \note Set from the "smdiport" string read in from chan_dahdi.conf
01350     */
01351    char smdi_port[SMDI_MAX_FILENAME_LEN];
01352 };
01353 
01354 /*! returns a new dahdi_chan_conf with default values (by-value) */
01355 static struct dahdi_chan_conf dahdi_chan_conf_default(void)
01356 {
01357    /* recall that if a field is not included here it is initialized
01358     * to 0 or equivalent
01359     */
01360    struct dahdi_chan_conf conf = {
01361 #ifdef HAVE_PRI
01362       .pri.pri = {
01363          .nsf = PRI_NSF_NONE,
01364          .switchtype = PRI_SWITCH_NI2,
01365          .dialplan = PRI_UNKNOWN + 1,
01366          .localdialplan = PRI_NATIONAL_ISDN + 1,
01367          .nodetype = PRI_CPE,
01368          .qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL,
01369          .inband_on_setup_ack = 1,
01370          .inband_on_proceeding = 1,
01371 
01372 #if defined(HAVE_PRI_CCSS)
01373          .cc_ptmp_recall_mode = 1,/* specificRecall */
01374          .cc_qsig_signaling_link_req = 1,/* retain */
01375          .cc_qsig_signaling_link_rsp = 1,/* retain */
01376 #endif   /* defined(HAVE_PRI_CCSS) */
01377 
01378          .minunused = 2,
01379          .idleext = "",
01380          .idledial = "",
01381          .internationalprefix = "",
01382          .nationalprefix = "",
01383          .localprefix = "",
01384          .privateprefix = "",
01385          .unknownprefix = "",
01386          .resetinterval = -1,
01387       },
01388 #endif
01389 #if defined(HAVE_SS7)
01390       .ss7.ss7 = {
01391          .called_nai = SS7_NAI_NATIONAL,
01392          .calling_nai = SS7_NAI_NATIONAL,
01393          .internationalprefix = "",
01394          .nationalprefix = "",
01395          .subscriberprefix = "",
01396          .unknownprefix = ""
01397       },
01398 #endif   /* defined(HAVE_SS7) */
01399 #ifdef HAVE_OPENR2
01400       .mfcr2 = {
01401          .variant = OR2_VAR_ITU,
01402          .mfback_timeout = -1,
01403          .metering_pulse_timeout = -1,
01404          .max_ani = 10,
01405          .max_dnis = 4,
01406          .get_ani_first = -1,
01407 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
01408          .skip_category_request = -1,
01409 #endif
01410          .call_files = 0,
01411          .allow_collect_calls = 0,
01412          .charge_calls = 1,
01413          .accept_on_offer = 1,
01414          .forced_release = 0,
01415          .double_answer = 0,
01416          .immediate_accept = -1,
01417          .logdir = "",
01418          .r2proto_file = "",
01419          .loglevel = OR2_LOG_ERROR | OR2_LOG_WARNING,
01420          .category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER
01421       },
01422 #endif
01423       .chan = {
01424          .context = "default",
01425          .cid_num = "",
01426          .cid_name = "",
01427          .cid_tag = "",
01428          .mohinterpret = "default",
01429          .mohsuggest = "",
01430          .parkinglot = "",
01431          .transfertobusy = 1,
01432 
01433          .cid_signalling = CID_SIG_BELL,
01434          .cid_start = CID_START_RING,
01435          .dahditrcallerid = 0,
01436          .use_callerid = 1,
01437          .sig = -1,
01438          .outsigmod = -1,
01439 
01440          .cid_rxgain = +5.0,
01441 
01442          .tonezone = -1,
01443 
01444          .echocancel.head.tap_length = 1,
01445 
01446          .busycount = 3,
01447 
01448          .accountcode = "",
01449 
01450          .mailbox = "",
01451 
01452 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
01453          .mwisend_fsk = 1,
01454 #endif
01455          .polarityonanswerdelay = 600,
01456 
01457          .sendcalleridafter = DEFAULT_CIDRINGS,
01458 
01459          .buf_policy = DAHDI_POLICY_IMMEDIATE,
01460          .buf_no = numbufs,
01461          .usefaxbuffers = 0,
01462          .cc_params = ast_cc_config_params_init(),
01463       },
01464       .timing = {
01465          .prewinktime = -1,
01466          .preflashtime = -1,
01467          .winktime = -1,
01468          .flashtime = -1,
01469          .starttime = -1,
01470          .rxwinktime = -1,
01471          .rxflashtime = -1,
01472          .debouncetime = -1
01473       },
01474       .is_sig_auto = 1,
01475       .smdi_port = "/dev/ttyS0",
01476    };
01477 
01478    return conf;
01479 }
01480 
01481 
01482 static struct ast_channel *dahdi_request(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause);
01483 static int dahdi_digit_begin(struct ast_channel *ast, char digit);
01484 static int dahdi_digit_end(struct ast_channel *ast, char digit, unsigned int duration);
01485 static int dahdi_sendtext(struct ast_channel *c, const char *text);
01486 static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout);
01487 static int dahdi_hangup(struct ast_channel *ast);
01488 static int dahdi_answer(struct ast_channel *ast);
01489 static struct ast_frame *dahdi_read(struct ast_channel *ast);
01490 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame);
01491 static struct ast_frame *dahdi_exception(struct ast_channel *ast);
01492 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen);
01493 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
01494 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen);
01495 static int dahdi_queryoption(struct ast_channel *chan, int option, void *data, int *datalen);
01496 static int dahdi_func_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len);
01497 static int dahdi_func_write(struct ast_channel *chan, const char *function, char *data, const char *value);
01498 static int dahdi_devicestate(void *data);
01499 static int dahdi_cc_callback(struct ast_channel *inbound, const char *dest, ast_cc_callback_fn callback);
01500 
01501 static const struct ast_channel_tech dahdi_tech = {
01502    .type = "DAHDI",
01503    .description = tdesc,
01504    .capabilities = AST_FORMAT_SLINEAR | AST_FORMAT_ULAW | AST_FORMAT_ALAW,
01505    .requester = dahdi_request,
01506    .send_digit_begin = dahdi_digit_begin,
01507    .send_digit_end = dahdi_digit_end,
01508    .send_text = dahdi_sendtext,
01509    .call = dahdi_call,
01510    .hangup = dahdi_hangup,
01511    .answer = dahdi_answer,
01512    .read = dahdi_read,
01513    .write = dahdi_write,
01514    .bridge = dahdi_bridge,
01515    .exception = dahdi_exception,
01516    .indicate = dahdi_indicate,
01517    .fixup = dahdi_fixup,
01518    .setoption = dahdi_setoption,
01519    .queryoption = dahdi_queryoption,
01520    .func_channel_read = dahdi_func_read,
01521    .func_channel_write = dahdi_func_write,
01522    .devicestate = dahdi_devicestate,
01523    .cc_callback = dahdi_cc_callback,
01524 };
01525 
01526 #define GET_CHANNEL(p) ((p)->channel)
01527 
01528 #define SIG_PRI_LIB_HANDLE_CASES \
01529    SIG_PRI:                \
01530    case SIG_BRI:              \
01531    case SIG_BRI_PTMP
01532 
01533 /*!
01534  * \internal
01535  * \brief Determine if sig_pri handles the signaling.
01536  * \since 1.8
01537  *
01538  * \param signaling Signaling to determine if is for sig_pri.
01539  *
01540  * \return TRUE if the signaling is for sig_pri.
01541  */
01542 static inline int dahdi_sig_pri_lib_handles(int signaling)
01543 {
01544    int handles;
01545 
01546    switch (signaling) {
01547    case SIG_PRI_LIB_HANDLE_CASES:
01548       handles = 1;
01549       break;
01550    default:
01551       handles = 0;
01552       break;
01553    }
01554 
01555    return handles;
01556 }
01557 
01558 static int analog_lib_handles(int signalling, int radio, int oprmode)
01559 {
01560    switch (signalling) {
01561    case SIG_FXOLS:
01562    case SIG_FXOGS:
01563    case SIG_FXOKS:
01564    case SIG_FXSLS:
01565    case SIG_FXSGS:
01566    case SIG_FXSKS:
01567    case SIG_EMWINK:
01568    case SIG_EM:
01569    case SIG_EM_E1:
01570    case SIG_FEATD:
01571    case SIG_FEATDMF:
01572    case SIG_E911:
01573    case SIG_FGC_CAMA:
01574    case SIG_FGC_CAMAMF:
01575    case SIG_FEATB:
01576    case SIG_SFWINK:
01577    case SIG_SF:
01578    case SIG_SF_FEATD:
01579    case SIG_SF_FEATDMF:
01580    case SIG_FEATDMF_TA:
01581    case SIG_SF_FEATB:
01582       break;
01583    default:
01584       /* The rest of the function should cover the remainder of signalling types */
01585       return 0;
01586    }
01587 
01588    if (radio) {
01589       return 0;
01590    }
01591 
01592    if (oprmode) {
01593       return 0;
01594    }
01595 
01596    return 1;
01597 }
01598 
01599 static enum analog_sigtype dahdisig_to_analogsig(int sig)
01600 {
01601    switch (sig) {
01602    case SIG_FXOLS:
01603       return ANALOG_SIG_FXOLS;
01604    case SIG_FXOGS:
01605       return ANALOG_SIG_FXOGS;
01606    case SIG_FXOKS:
01607       return ANALOG_SIG_FXOKS;
01608    case SIG_FXSLS:
01609       return ANALOG_SIG_FXSLS;
01610    case SIG_FXSGS:
01611       return ANALOG_SIG_FXSGS;
01612    case SIG_FXSKS:
01613       return ANALOG_SIG_FXSKS;
01614    case SIG_EMWINK:
01615       return ANALOG_SIG_EMWINK;
01616    case SIG_EM:
01617       return ANALOG_SIG_EM;
01618    case SIG_EM_E1:
01619       return ANALOG_SIG_EM_E1;
01620    case SIG_FEATD:
01621       return ANALOG_SIG_FEATD;
01622    case SIG_FEATDMF:
01623       return ANALOG_SIG_FEATDMF;
01624    case SIG_E911:
01625       return SIG_E911;
01626    case SIG_FGC_CAMA:
01627       return ANALOG_SIG_FGC_CAMA;
01628    case SIG_FGC_CAMAMF:
01629       return ANALOG_SIG_FGC_CAMAMF;
01630    case SIG_FEATB:
01631       return ANALOG_SIG_FEATB;
01632    case SIG_SFWINK:
01633       return ANALOG_SIG_SFWINK;
01634    case SIG_SF:
01635       return ANALOG_SIG_SF;
01636    case SIG_SF_FEATD:
01637       return ANALOG_SIG_SF_FEATD;
01638    case SIG_SF_FEATDMF:
01639       return ANALOG_SIG_SF_FEATDMF;
01640    case SIG_FEATDMF_TA:
01641       return ANALOG_SIG_FEATDMF_TA;
01642    case SIG_SF_FEATB:
01643       return ANALOG_SIG_FEATB;
01644    default:
01645       return -1;
01646    }
01647 }
01648 
01649 
01650 static int analog_tone_to_dahditone(enum analog_tone tone)
01651 {
01652    switch (tone) {
01653    case ANALOG_TONE_RINGTONE:
01654       return DAHDI_TONE_RINGTONE;
01655    case ANALOG_TONE_STUTTER:
01656       return DAHDI_TONE_STUTTER;
01657    case ANALOG_TONE_CONGESTION:
01658       return DAHDI_TONE_CONGESTION;
01659    case ANALOG_TONE_DIALTONE:
01660       return DAHDI_TONE_DIALTONE;
01661    case ANALOG_TONE_DIALRECALL:
01662       return DAHDI_TONE_DIALRECALL;
01663    case ANALOG_TONE_INFO:
01664       return DAHDI_TONE_INFO;
01665    default:
01666       return -1;
01667    }
01668 }
01669 
01670 static int analogsub_to_dahdisub(enum analog_sub analogsub)
01671 {
01672    int index;
01673 
01674    switch (analogsub) {
01675    case ANALOG_SUB_REAL:
01676       index = SUB_REAL;
01677       break;
01678    case ANALOG_SUB_CALLWAIT:
01679       index = SUB_CALLWAIT;
01680       break;
01681    case ANALOG_SUB_THREEWAY:
01682       index = SUB_THREEWAY;
01683       break;
01684    default:
01685       ast_log(LOG_ERROR, "Unidentified sub!\n");
01686       index = SUB_REAL;
01687    }
01688 
01689    return index;
01690 }
01691 
01692 static enum analog_event dahdievent_to_analogevent(int event);
01693 static int bump_gains(struct dahdi_pvt *p);
01694 static int dahdi_setlinear(int dfd, int linear);
01695 
01696 static int my_start_cid_detect(void *pvt, int cid_signalling)
01697 {
01698    struct dahdi_pvt *p = pvt;
01699    int index = SUB_REAL;
01700    p->cs = callerid_new(cid_signalling);
01701    if (!p->cs) {
01702       ast_log(LOG_ERROR, "Unable to alloc callerid\n");
01703       return -1;
01704    }
01705    bump_gains(p);
01706    dahdi_setlinear(p->subs[index].dfd, 0);
01707 
01708    return 0;
01709 }
01710 
01711 static int my_stop_cid_detect(void *pvt)
01712 {
01713    struct dahdi_pvt *p = pvt;
01714    int index = SUB_REAL;
01715    if (p->cs)
01716       callerid_free(p->cs);
01717    dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
01718    return 0;
01719 }
01720 
01721 static int my_get_callerid(void *pvt, char *namebuf, char *numbuf, enum analog_event *ev, size_t timeout)
01722 {
01723    struct dahdi_pvt *p = pvt;
01724    struct analog_pvt *analog_p = p->sig_pvt;
01725    struct pollfd poller;
01726    char *name, *num;
01727    int index = SUB_REAL;
01728    int res;
01729    unsigned char buf[256];
01730    int flags;
01731 
01732    poller.fd = p->subs[SUB_REAL].dfd;
01733    poller.events = POLLPRI | POLLIN;
01734    poller.revents = 0;
01735 
01736    res = poll(&poller, 1, timeout);
01737 
01738    if (poller.revents & POLLPRI) {
01739       *ev = dahdievent_to_analogevent(dahdi_get_event(p->subs[SUB_REAL].dfd));
01740       return 1;
01741    }
01742 
01743    if (poller.revents & POLLIN) {
01744       /*** NOTES ***/
01745       /* Change API: remove cid_signalling from get_callerid, add a new start_cid_detect and stop_cid_detect function
01746        * to enable slin mode and allocate cid detector. get_callerid should be able to be called any number of times until
01747        * either a timeout occurs or CID is detected (returns 0). returning 1 should be event received, and -1 should be
01748        * a failure and die, and returning 2 means no event was received. */
01749       res = read(p->subs[index].dfd, buf, sizeof(buf));
01750       if (res < 0) {
01751          ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
01752          return -1;
01753       }
01754 
01755       if (analog_p->ringt > 0) {
01756          if (!(--analog_p->ringt)) {
01757             /* only return if we timeout from a ring event */
01758             return -1;
01759          }
01760       }
01761 
01762       if (p->cid_signalling == CID_SIG_V23_JP) {
01763          res = callerid_feed_jp(p->cs, buf, res, AST_LAW(p));
01764       } else {
01765          res = callerid_feed(p->cs, buf, res, AST_LAW(p));
01766       }
01767       if (res < 0) {
01768          /*
01769           * The previous diagnostic message output likely
01770           * explains why it failed.
01771           */
01772          ast_log(LOG_WARNING, "Failed to decode CallerID\n");
01773          return -1;
01774       }
01775 
01776       if (res == 1) {
01777          callerid_get(p->cs, &name, &num, &flags);
01778          if (name)
01779             ast_copy_string(namebuf, name, ANALOG_MAX_CID);
01780          if (num)
01781             ast_copy_string(numbuf, num, ANALOG_MAX_CID);
01782 
01783          ast_debug(1, "CallerID number: %s, name: %s, flags=%d\n", num, name, flags);
01784          return 0;
01785       }
01786    }
01787 
01788    *ev = ANALOG_EVENT_NONE;
01789    return 2;
01790 }
01791 
01792 static const char *event2str(int event);
01793 static int restore_gains(struct dahdi_pvt *p);
01794 
01795 static int my_distinctive_ring(struct ast_channel *chan, void *pvt, int idx, int *ringdata)
01796 {
01797    unsigned char buf[256];
01798    int distMatches;
01799    int curRingData[RING_PATTERNS];
01800    int receivedRingT;
01801    int counter1;
01802    int counter;
01803    int i;
01804    int res;
01805    int checkaftercid = 0;
01806 
01807    struct dahdi_pvt *p = pvt;
01808    struct analog_pvt *analog_p = p->sig_pvt;
01809 
01810    if (ringdata == NULL) {
01811       ringdata = curRingData;
01812    } else {
01813       checkaftercid = 1;
01814    }
01815 
01816    /* We must have a ring by now, so, if configured, lets try to listen for
01817     * distinctive ringing */
01818    if ((checkaftercid && distinctiveringaftercid) || !checkaftercid) {
01819       /* Clear the current ring data array so we don't have old data in it. */
01820       for (receivedRingT = 0; receivedRingT < RING_PATTERNS; receivedRingT++)
01821          ringdata[receivedRingT] = 0;
01822       receivedRingT = 0;
01823       if (checkaftercid && distinctiveringaftercid)
01824          ast_verb(3, "Detecting post-CID distinctive ring\n");
01825       /* Check to see if context is what it should be, if not set to be. */
01826       else if (strcmp(p->context,p->defcontext) != 0) {
01827          ast_copy_string(p->context, p->defcontext, sizeof(p->context));
01828          ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
01829       }
01830 
01831       for (;;) {
01832          i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
01833          if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
01834             ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
01835             ast_hangup(chan);
01836             return 1;
01837          }
01838          if (i & DAHDI_IOMUX_SIGEVENT) {
01839             res = dahdi_get_event(p->subs[idx].dfd);
01840             if (res == DAHDI_EVENT_NOALARM) {
01841                p->inalarm = 0;
01842                analog_p->inalarm = 0;
01843             }
01844             ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
01845             res = 0;
01846             /* Let us detect distinctive ring */
01847 
01848             ringdata[receivedRingT] = analog_p->ringt;
01849 
01850             if (analog_p->ringt < analog_p->ringt_base/2)
01851                break;
01852             /* Increment the ringT counter so we can match it against
01853                values in chan_dahdi.conf for distinctive ring */
01854             if (++receivedRingT == RING_PATTERNS)
01855                break;
01856          } else if (i & DAHDI_IOMUX_READ) {
01857             res = read(p->subs[idx].dfd, buf, sizeof(buf));
01858             if (res < 0) {
01859                if (errno != ELAST) {
01860                   ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
01861                   ast_hangup(chan);
01862                   return 1;
01863                }
01864                break;
01865             }
01866             if (analog_p->ringt > 0) {
01867                if (!(--analog_p->ringt)) {
01868                   res = -1;
01869                   break;
01870                }
01871             }
01872          }
01873       }
01874    }
01875    if ((checkaftercid && usedistinctiveringdetection) || !checkaftercid) {
01876       /* this only shows up if you have n of the dring patterns filled in */
01877       ast_verb(3, "Detected ring pattern: %d,%d,%d\n",ringdata[0],ringdata[1],ringdata[2]);
01878       for (counter = 0; counter < 3; counter++) {
01879       /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this channel */
01880          distMatches = 0;
01881          /* this only shows up if you have n of the dring patterns filled in */
01882          ast_verb(3, "Checking %d,%d,%d\n",
01883                p->drings.ringnum[counter].ring[0],
01884                p->drings.ringnum[counter].ring[1],
01885                p->drings.ringnum[counter].ring[2]);
01886          for (counter1 = 0; counter1 < 3; counter1++) {
01887             ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
01888             if (p->drings.ringnum[counter].ring[counter1] == -1) {
01889                ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
01890                ringdata[counter1]);
01891                distMatches++;
01892             } else if (ringdata[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
01893                               ringdata[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
01894                ast_verb(3, "Ring pattern matched in range: %d to %d\n",
01895                (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
01896                (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
01897                distMatches++;
01898             }
01899          }
01900 
01901          if (distMatches == 3) {
01902             /* The ring matches, set the context to whatever is for distinctive ring.. */
01903             ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context));
01904             ast_copy_string(chan->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(chan->context));
01905             ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
01906             break;
01907          }
01908       }
01909    }
01910    /* Restore linear mode (if appropriate) for Caller*ID processing */
01911    dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
01912    restore_gains(p);
01913 
01914    return 0;
01915 }
01916 
01917 static int my_stop_callwait(void *pvt)
01918 {
01919    struct dahdi_pvt *p = pvt;
01920    p->callwaitingrepeat = 0;
01921    p->cidcwexpire = 0;
01922    p->cid_suppress_expire = 0;
01923 
01924    return 0;
01925 }
01926 
01927 static int send_callerid(struct dahdi_pvt *p);
01928 static int save_conference(struct dahdi_pvt *p);
01929 static int restore_conference(struct dahdi_pvt *p);
01930 
01931 static int my_callwait(void *pvt)
01932 {
01933    struct dahdi_pvt *p = pvt;
01934    p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
01935    if (p->cidspill) {
01936       ast_log(LOG_WARNING, "Spill already exists?!?\n");
01937       ast_free(p->cidspill);
01938    }
01939 
01940    /*
01941     * SAS: Subscriber Alert Signal, 440Hz for 300ms
01942     * CAS: CPE Alert Signal, 2130Hz * 2750Hz sine waves
01943     */
01944    if (!(p->cidspill = ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE * 4)))
01945       return -1;
01946    save_conference(p);
01947    /* Silence */
01948    memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
01949    if (!p->callwaitrings && p->callwaitingcallerid) {
01950       ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
01951       p->callwaitcas = 1;
01952       p->cidlen = 2400 + 680 + READ_SIZE * 4;
01953    } else {
01954       ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
01955       p->callwaitcas = 0;
01956       p->cidlen = 2400 + READ_SIZE * 4;
01957    }
01958    p->cidpos = 0;
01959    send_callerid(p);
01960 
01961    return 0;
01962 }
01963 
01964 static int my_send_callerid(void *pvt, int cwcid, struct ast_party_caller *caller)
01965 {
01966    struct dahdi_pvt *p = pvt;
01967 
01968    ast_debug(2, "Starting cid spill\n");
01969 
01970    if (p->cidspill) {
01971       ast_log(LOG_WARNING, "cidspill already exists??\n");
01972       ast_free(p->cidspill);
01973    }
01974 
01975    if ((p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) {
01976       if (cwcid == 0) {
01977          p->cidlen = ast_callerid_generate(p->cidspill,
01978             caller->id.name.str,
01979             caller->id.number.str,
01980             AST_LAW(p));
01981       } else {
01982          ast_verb(3, "CPE supports Call Waiting Caller*ID.  Sending '%s/%s'\n",
01983             caller->id.name.str, caller->id.number.str);
01984          p->callwaitcas = 0;
01985          p->cidcwexpire = 0;
01986          p->cidlen = ast_callerid_callwaiting_generate(p->cidspill,
01987             caller->id.name.str,
01988             caller->id.number.str,
01989             AST_LAW(p));
01990          p->cidlen += READ_SIZE * 4;
01991       }
01992       p->cidpos = 0;
01993       p->cid_suppress_expire = 0;
01994       send_callerid(p);
01995    }
01996    return 0;
01997 }
01998 
01999 static int my_dsp_reset_and_flush_digits(void *pvt)
02000 {
02001    struct dahdi_pvt *p = pvt;
02002    if (p->dsp)
02003       ast_dsp_digitreset(p->dsp);
02004 
02005    return 0;
02006 }
02007 
02008 static int my_dsp_set_digitmode(void *pvt, enum analog_dsp_digitmode mode)
02009 {
02010    struct dahdi_pvt *p = pvt;
02011 
02012    if (p->channel == CHAN_PSEUDO)
02013       ast_log(LOG_ERROR, "You have assumed incorrectly sir!\n");
02014 
02015    if (mode == ANALOG_DIGITMODE_DTMF) {
02016       /* If we do hardware dtmf, no need for a DSP */
02017       if (p->hardwaredtmf) {
02018          if (p->dsp) {
02019             ast_dsp_free(p->dsp);
02020             p->dsp = NULL;
02021          }
02022          return 0;
02023       }
02024 
02025       if (!p->dsp) {
02026          p->dsp = ast_dsp_new();
02027          if (!p->dsp) {
02028             ast_log(LOG_ERROR, "Unable to allocate DSP\n");
02029             return -1;
02030          }
02031       }
02032 
02033       ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
02034    } else if (mode == ANALOG_DIGITMODE_MF) {
02035       if (!p->dsp) {
02036          p->dsp = ast_dsp_new();
02037          if (!p->dsp) {
02038             ast_log(LOG_ERROR, "Unable to allocate DSP\n");
02039             return -1;
02040          }
02041       }
02042       ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
02043    }
02044    return 0;
02045 }
02046 
02047 static int dahdi_wink(struct dahdi_pvt *p, int index);
02048 
02049 static int my_wink(void *pvt, enum analog_sub sub)
02050 {
02051    struct dahdi_pvt *p = pvt;
02052    int index = analogsub_to_dahdisub(sub);
02053    if (index != SUB_REAL) {
02054       ast_log(LOG_ERROR, "We used a sub other than SUB_REAL (incorrect assumption sir)\n");
02055    }
02056    return dahdi_wink(p, index);
02057 }
02058 
02059 static void wakeup_sub(struct dahdi_pvt *p, int a);
02060 
02061 static int reset_conf(struct dahdi_pvt *p);
02062 
02063 static inline int dahdi_confmute(struct dahdi_pvt *p, int muted);
02064 
02065 static void my_handle_dtmf(void *pvt, struct ast_channel *ast, enum analog_sub analog_index, struct ast_frame **dest)
02066 {
02067    struct ast_frame *f = *dest;
02068    struct dahdi_pvt *p = pvt;
02069    int idx = analogsub_to_dahdisub(analog_index);
02070 
02071    ast_debug(1, "%s DTMF digit: 0x%02X '%c' on %s\n",
02072       f->frametype == AST_FRAME_DTMF_BEGIN ? "Begin" : "End",
02073       (unsigned)f->subclass.integer, f->subclass.integer, ast->name);
02074 
02075    if (f->subclass.integer == 'f') {
02076       if (f->frametype == AST_FRAME_DTMF_END) {
02077          /* Fax tone -- Handle and return NULL */
02078          if ((p->callprogress & CALLPROGRESS_FAX) && !p->faxhandled) {
02079             /* If faxbuffers are configured, use them for the fax transmission */
02080             if (p->usefaxbuffers && !p->bufferoverrideinuse) {
02081                struct dahdi_bufferinfo bi = {
02082                   .txbufpolicy = p->faxbuf_policy,
02083                   .bufsize = p->bufsize,
02084                   .numbufs = p->faxbuf_no
02085                };
02086                int res;
02087 
02088                if ((res = ioctl(p->subs[idx].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
02089                   ast_log(LOG_WARNING, "Channel '%s' unable to set buffer policy, reason: %s\n", ast->name, strerror(errno));
02090                } else {
02091                   p->bufferoverrideinuse = 1;
02092                }
02093             }
02094             p->faxhandled = 1;
02095             if (p->dsp) {
02096                p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
02097                ast_dsp_set_features(p->dsp, p->dsp_features);
02098                ast_debug(1, "Disabling FAX tone detection on %s after tone received\n", ast->name);
02099             }
02100             if (strcmp(ast->exten, "fax")) {
02101                const char *target_context = S_OR(ast->macrocontext, ast->context);
02102 
02103                /* We need to unlock 'ast' here because ast_exists_extension has the
02104                 * potential to start autoservice on the channel. Such action is prone
02105                 * to deadlock.
02106                 */
02107                ast_mutex_unlock(&p->lock);
02108                ast_channel_unlock(ast);
02109                if (ast_exists_extension(ast, target_context, "fax", 1,
02110                   S_COR(ast->caller.id.number.valid, ast->caller.id.number.str, NULL))) {
02111                   ast_channel_lock(ast);
02112                   ast_mutex_lock(&p->lock);
02113                   ast_verb(3, "Redirecting %s to fax extension\n", ast->name);
02114                   /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
02115                   pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten);
02116                   if (ast_async_goto(ast, target_context, "fax", 1))
02117                      ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context);
02118                } else {
02119                   ast_channel_lock(ast);
02120                   ast_mutex_lock(&p->lock);
02121                   ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
02122                }
02123             } else {
02124                ast_debug(1, "Already in a fax extension, not redirecting\n");
02125             }
02126          } else {
02127             ast_debug(1, "Fax already handled\n");
02128          }
02129          dahdi_confmute(p, 0);
02130       }
02131       p->subs[idx].f.frametype = AST_FRAME_NULL;
02132       p->subs[idx].f.subclass.integer = 0;
02133       *dest = &p->subs[idx].f;
02134    }
02135 }
02136 
02137 static void my_lock_private(void *pvt)
02138 {
02139    struct dahdi_pvt *p = pvt;
02140    ast_mutex_lock(&p->lock);
02141 }
02142 
02143 static void my_unlock_private(void *pvt)
02144 {
02145    struct dahdi_pvt *p = pvt;
02146    ast_mutex_unlock(&p->lock);
02147 }
02148 
02149 static void my_deadlock_avoidance_private(void *pvt)
02150 {
02151    struct dahdi_pvt *p = pvt;
02152 
02153    DEADLOCK_AVOIDANCE(&p->lock);
02154 }
02155 
02156 /*!
02157  * \internal
02158  * \brief Post an AMI DAHDI channel association event.
02159  * \since 1.8
02160  *
02161  * \param p DAHDI private pointer
02162  * \param chan Channel associated with the private pointer
02163  *
02164  * \return Nothing
02165  */
02166 static void dahdi_ami_channel_event(struct dahdi_pvt *p, struct ast_channel *chan)
02167 {
02168    char ch_name[20];
02169 
02170    if (p->channel < CHAN_PSEUDO) {
02171       /* No B channel */
02172       snprintf(ch_name, sizeof(ch_name), "no-media (%d)", p->channel);
02173    } else if (p->channel == CHAN_PSEUDO) {
02174       /* Pseudo channel */
02175       strcpy(ch_name, "pseudo");
02176    } else {
02177       /* Real channel */
02178       snprintf(ch_name, sizeof(ch_name), "%d", p->channel);
02179    }
02180    ast_manager_event(chan, EVENT_FLAG_CALL, "DAHDIChannel",
02181       "Channel: %s\r\n"
02182       "Uniqueid: %s\r\n"
02183       "DAHDISpan: %d\r\n"
02184       "DAHDIChannel: %s\r\n",
02185       chan->name,
02186       chan->uniqueid,
02187       p->span,
02188       ch_name);
02189 }
02190 
02191 #ifdef HAVE_PRI
02192 /*!
02193  * \internal
02194  * \brief Post an AMI DAHDI channel association event.
02195  * \since 1.8
02196  *
02197  * \param pvt DAHDI private pointer
02198  * \param chan Channel associated with the private pointer
02199  *
02200  * \return Nothing
02201  */
02202 static void my_ami_channel_event(void *pvt, struct ast_channel *chan)
02203 {
02204    struct dahdi_pvt *p = pvt;
02205 
02206    dahdi_ami_channel_event(p, chan);
02207 }
02208 #endif
02209 
02210 /* linear_mode = 0 - turn linear mode off, >0 - turn linear mode on
02211 *  returns the last value of the linear setting 
02212 */ 
02213 static int my_set_linear_mode(void *pvt, enum analog_sub sub, int linear_mode)
02214 {
02215    struct dahdi_pvt *p = pvt;
02216    int oldval;
02217    int idx = analogsub_to_dahdisub(sub);
02218    
02219    dahdi_setlinear(p->subs[idx].dfd, linear_mode);
02220    oldval = p->subs[idx].linear;
02221    p->subs[idx].linear = linear_mode ? 1 : 0;
02222    return oldval;
02223 }
02224 
02225 static void my_set_inthreeway(void *pvt, enum analog_sub sub, int inthreeway)
02226 {
02227    struct dahdi_pvt *p = pvt;
02228    int idx = analogsub_to_dahdisub(sub);
02229 
02230    p->subs[idx].inthreeway = inthreeway;
02231 }
02232 
02233 static int get_alarms(struct dahdi_pvt *p);
02234 static void handle_alarms(struct dahdi_pvt *p, int alms);
02235 static void my_get_and_handle_alarms(void *pvt)
02236 {
02237    int res;
02238    struct dahdi_pvt *p = pvt;
02239 
02240    res = get_alarms(p);
02241    handle_alarms(p, res);
02242 }
02243 
02244 static void *my_get_sigpvt_bridged_channel(struct ast_channel *chan)
02245 {
02246    struct ast_channel *bridged = ast_bridged_channel(chan);
02247 
02248    if (bridged && bridged->tech == &dahdi_tech) {
02249       struct dahdi_pvt *p = bridged->tech_pvt;
02250 
02251       if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
02252          return p->sig_pvt;
02253       }
02254    }
02255    return NULL;
02256 }
02257 
02258 static int my_get_sub_fd(void *pvt, enum analog_sub sub)
02259 {
02260    struct dahdi_pvt *p = pvt;
02261    int dahdi_sub = analogsub_to_dahdisub(sub);
02262    return p->subs[dahdi_sub].dfd;
02263 }
02264 
02265 static void my_set_cadence(void *pvt, int *cid_rings, struct ast_channel *ast)
02266 {
02267    struct dahdi_pvt *p = pvt;
02268 
02269    /* Choose proper cadence */
02270    if ((p->distinctivering > 0) && (p->distinctivering <= num_cadence)) {
02271       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &cadences[p->distinctivering - 1]))
02272          ast_log(LOG_WARNING, "Unable to set distinctive ring cadence %d on '%s': %s\n", p->distinctivering, ast->name, strerror(errno));
02273       *cid_rings = cidrings[p->distinctivering - 1];
02274    } else {
02275       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, NULL))
02276          ast_log(LOG_WARNING, "Unable to reset default ring on '%s': %s\n", ast->name, strerror(errno));
02277       *cid_rings = p->sendcalleridafter;
02278    }
02279 }
02280 
02281 static void my_set_alarm(void *pvt, int in_alarm)
02282 {
02283    struct dahdi_pvt *p = pvt;
02284 
02285    p->inalarm = in_alarm;
02286 }
02287 
02288 static void my_set_dialing(void *pvt, int is_dialing)
02289 {
02290    struct dahdi_pvt *p = pvt;
02291 
02292    p->dialing = is_dialing;
02293 }
02294 
02295 static void my_set_outgoing(void *pvt, int is_outgoing)
02296 {
02297    struct dahdi_pvt *p = pvt;
02298 
02299    p->outgoing = is_outgoing;
02300 }
02301 
02302 #if defined(HAVE_PRI) || defined(HAVE_SS7)
02303 static void my_set_digital(void *pvt, int is_digital)
02304 {
02305    struct dahdi_pvt *p = pvt;
02306 
02307    p->digital = is_digital;
02308 }
02309 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
02310 
02311 #if defined(HAVE_SS7)
02312 static void my_set_inservice(void *pvt, int is_inservice)
02313 {
02314    struct dahdi_pvt *p = pvt;
02315 
02316    p->inservice = is_inservice;
02317 }
02318 #endif   /* defined(HAVE_SS7) */
02319 
02320 #if defined(HAVE_SS7)
02321 static void my_set_locallyblocked(void *pvt, int is_blocked)
02322 {
02323    struct dahdi_pvt *p = pvt;
02324 
02325    p->locallyblocked = is_blocked;
02326 }
02327 #endif   /* defined(HAVE_SS7) */
02328 
02329 #if defined(HAVE_SS7)
02330 static void my_set_remotelyblocked(void *pvt, int is_blocked)
02331 {
02332    struct dahdi_pvt *p = pvt;
02333 
02334    p->remotelyblocked = is_blocked;
02335 }
02336 #endif   /* defined(HAVE_SS7) */
02337 
02338 static void my_set_ringtimeout(void *pvt, int ringt)
02339 {
02340    struct dahdi_pvt *p = pvt;
02341    p->ringt = ringt;
02342 }
02343 
02344 static void my_set_waitingfordt(void *pvt, struct ast_channel *ast)
02345 {
02346    struct dahdi_pvt *p = pvt;
02347 
02348    if (p->waitfordialtone && CANPROGRESSDETECT(p) && p->dsp) {
02349       ast_log(LOG_DEBUG, "Defer dialing for %dms or dialtone\n", p->waitfordialtone);
02350       gettimeofday(&p->waitingfordt, NULL);
02351       ast_setstate(ast, AST_STATE_OFFHOOK);
02352    }
02353 }
02354 
02355 static int my_check_waitingfordt(void *pvt)
02356 {
02357    struct dahdi_pvt *p = pvt;
02358 
02359    if (p->waitingfordt.tv_sec) {
02360       return 1;
02361    }
02362 
02363    return 0;
02364 }
02365 
02366 static void my_set_confirmanswer(void *pvt, int flag)
02367 {
02368    struct dahdi_pvt *p = pvt;
02369    p->confirmanswer = flag;
02370 }
02371 
02372 static int my_check_confirmanswer(void *pvt)
02373 {
02374    struct dahdi_pvt *p = pvt;
02375    if (p->confirmanswer) {
02376       return 1;
02377    }
02378 
02379    return 0;
02380 }
02381 
02382 static void my_set_callwaiting(void *pvt, int callwaiting_enable)
02383 {
02384    struct dahdi_pvt *p = pvt;
02385 
02386    p->callwaiting = callwaiting_enable;
02387 }
02388 
02389 static void my_cancel_cidspill(void *pvt)
02390 {
02391    struct dahdi_pvt *p = pvt;
02392 
02393    ast_free(p->cidspill);
02394    p->cidspill = NULL;
02395    restore_conference(p);
02396 }
02397 
02398 static int my_confmute(void *pvt, int mute)
02399 {
02400    struct dahdi_pvt *p = pvt;
02401    return dahdi_confmute(p, mute);
02402 }
02403 
02404 static void my_set_pulsedial(void *pvt, int flag)
02405 {
02406    struct dahdi_pvt *p = pvt;
02407    p->pulsedial = flag;
02408 }
02409 
02410 static void my_set_new_owner(void *pvt, struct ast_channel *new_owner)
02411 {
02412    struct dahdi_pvt *p = pvt;
02413 
02414    p->owner = new_owner;
02415 }
02416 
02417 static const char *my_get_orig_dialstring(void *pvt)
02418 {
02419    struct dahdi_pvt *p = pvt;
02420 
02421    return p->dialstring;
02422 }
02423 
02424 static void my_increase_ss_count(void)
02425 {
02426    ast_mutex_lock(&ss_thread_lock);
02427    ss_thread_count++;
02428    ast_mutex_unlock(&ss_thread_lock);
02429 }
02430 
02431 static void my_decrease_ss_count(void)
02432 {
02433    ast_mutex_lock(&ss_thread_lock);
02434    ss_thread_count--;
02435    ast_cond_signal(&ss_thread_complete);
02436    ast_mutex_unlock(&ss_thread_lock);
02437 }
02438 
02439 static void my_all_subchannels_hungup(void *pvt)
02440 {
02441    struct dahdi_pvt *p = pvt;
02442    int res, law;
02443 
02444    p->faxhandled = 0;
02445    p->didtdd = 0;
02446 
02447    if (p->dsp) {
02448       ast_dsp_free(p->dsp);
02449       p->dsp = NULL;
02450    }
02451 
02452    p->law = p->law_default;
02453    law = p->law_default;
02454    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
02455    if (res < 0)
02456       ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
02457 
02458    dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
02459 
02460 #if 1
02461    {
02462    int i;
02463    p->owner = NULL;
02464    /* Cleanup owners here */
02465    for (i = 0; i < 3; i++) {
02466       p->subs[i].owner = NULL;
02467    }
02468    }
02469 #endif
02470 
02471    reset_conf(p);
02472    if (num_restart_pending == 0) {
02473       restart_monitor();
02474    }
02475 }
02476 
02477 static int conf_del(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index);
02478 
02479 static int my_conf_del(void *pvt, enum analog_sub sub)
02480 {
02481    struct dahdi_pvt *p = pvt;
02482    int x = analogsub_to_dahdisub(sub);
02483 
02484    return conf_del(p, &p->subs[x], x);
02485 }
02486 
02487 static int conf_add(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index, int slavechannel);
02488 
02489 static int my_conf_add(void *pvt, enum analog_sub sub)
02490 {
02491    struct dahdi_pvt *p = pvt;
02492    int x = analogsub_to_dahdisub(sub);
02493 
02494    return conf_add(p, &p->subs[x], x, 0);
02495 }
02496 
02497 static int isslavenative(struct dahdi_pvt *p, struct dahdi_pvt **out);
02498 
02499 static int my_complete_conference_update(void *pvt, int needconference)
02500 {
02501    struct dahdi_pvt *p = pvt;
02502    int needconf = needconference;
02503    int x;
02504    int useslavenative;
02505    struct dahdi_pvt *slave = NULL;
02506 
02507    useslavenative = isslavenative(p, &slave);
02508 
02509    /* If we have a slave, add him to our conference now. or DAX
02510       if this is slave native */
02511    for (x = 0; x < MAX_SLAVES; x++) {
02512       if (p->slaves[x]) {
02513          if (useslavenative)
02514             conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
02515          else {
02516             conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
02517             needconf++;
02518          }
02519       }
02520    }
02521    /* If we're supposed to be in there, do so now */
02522    if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
02523       if (useslavenative)
02524          conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
02525       else {
02526          conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
02527          needconf++;
02528       }
02529    }
02530    /* If we have a master, add ourselves to his conference */
02531    if (p->master) {
02532       if (isslavenative(p->master, NULL)) {
02533          conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
02534       } else {
02535          conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
02536       }
02537    }
02538    if (!needconf) {
02539       /* Nobody is left (or should be left) in our conference.
02540          Kill it. */
02541       p->confno = -1;
02542    }
02543 
02544    return 0;
02545 }
02546 
02547 static int check_for_conference(struct dahdi_pvt *p);
02548 
02549 static int my_check_for_conference(void *pvt)
02550 {
02551    struct dahdi_pvt *p = pvt;
02552    return check_for_conference(p);
02553 }
02554 
02555 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)
02556 {
02557    struct dahdi_pvt *p = pvt;
02558    int da, db;
02559    int tchan;
02560    int tinthreeway;
02561 
02562    da = analogsub_to_dahdisub(a);
02563    db = analogsub_to_dahdisub(b);
02564 
02565    tchan = p->subs[da].chan;
02566    p->subs[da].chan = p->subs[db].chan;
02567    p->subs[db].chan = tchan;
02568 
02569    tinthreeway = p->subs[da].inthreeway;
02570    p->subs[da].inthreeway = p->subs[db].inthreeway;
02571    p->subs[db].inthreeway = tinthreeway;
02572 
02573    p->subs[da].owner = ast_a;
02574    p->subs[db].owner = ast_b;
02575 
02576    if (ast_a)
02577       ast_channel_set_fd(ast_a, 0, p->subs[da].dfd);
02578    if (ast_b)
02579       ast_channel_set_fd(ast_b, 0, p->subs[db].dfd);
02580 
02581    wakeup_sub(p, a);
02582    wakeup_sub(p, b);
02583 
02584    return;
02585 }
02586 
02587 static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpbx, int idx, int law, const char *linkedid);
02588 
02589 static struct ast_channel *my_new_analog_ast_channel(void *pvt, int state, int startpbx, enum analog_sub sub, const struct ast_channel *requestor)
02590 {
02591    struct dahdi_pvt *p = pvt;
02592    int dsub = analogsub_to_dahdisub(sub);
02593 
02594    return dahdi_new(p, state, startpbx, dsub, 0, requestor ? requestor->linkedid : "");
02595 }
02596 
02597 #if defined(HAVE_PRI) || defined(HAVE_SS7)
02598 static int dahdi_setlaw(int dfd, int law)
02599 {
02600    int res;
02601    res = ioctl(dfd, DAHDI_SETLAW, &law);
02602    if (res)
02603       return res;
02604    return 0;
02605 }
02606 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
02607 
02608 #if defined(HAVE_PRI)
02609 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)
02610 {
02611    struct dahdi_pvt *p = pvt;
02612    int audio;
02613    int newlaw = -1;
02614 
02615    switch (p->sig) {
02616    case SIG_PRI_LIB_HANDLE_CASES:
02617       if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
02618          /* PRI nobch pseudo channel.  Does not handle ioctl(DAHDI_AUDIOMODE) */
02619          break;
02620       }
02621       /* Fall through */
02622    default:
02623       /* Set to audio mode at this point */
02624       audio = 1;
02625       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &audio) == -1) {
02626          ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n",
02627             p->channel, audio, strerror(errno));
02628       }
02629       break;
02630    }
02631 
02632    if (law != SIG_PRI_DEFLAW) {
02633       dahdi_setlaw(p->subs[SUB_REAL].dfd, (law == SIG_PRI_ULAW) ? DAHDI_LAW_MULAW : DAHDI_LAW_ALAW);
02634    }
02635 
02636    ast_copy_string(p->exten, exten, sizeof(p->exten));
02637 
02638    switch (law) {
02639       case SIG_PRI_DEFLAW:
02640          newlaw = 0;
02641          break;
02642       case SIG_PRI_ALAW:
02643          newlaw = DAHDI_LAW_ALAW;
02644          break;
02645       case SIG_PRI_ULAW:
02646          newlaw = DAHDI_LAW_MULAW;
02647          break;
02648    }
02649    return dahdi_new(p, state, 0, SUB_REAL, newlaw, requestor ? requestor->linkedid : "");
02650 }
02651 #endif   /* defined(HAVE_PRI) */
02652 
02653 static int set_actual_gain(int fd, float rxgain, float txgain, float rxdrc, float txdrc, int law);
02654 
02655 #if defined(HAVE_PRI) || defined(HAVE_SS7)
02656 /*!
02657  * \internal
02658  * \brief Open the PRI/SS7 channel media path.
02659  * \since 1.8
02660  *
02661  * \param p Channel private control structure.
02662  *
02663  * \return Nothing
02664  */
02665 static void my_pri_ss7_open_media(void *p)
02666 {
02667    struct dahdi_pvt *pvt = p;
02668    int res;
02669    int dfd;
02670    int set_val;
02671 
02672    dfd = pvt->subs[SUB_REAL].dfd;
02673 
02674    /* Open the media path. */
02675    set_val = 1;
02676    res = ioctl(dfd, DAHDI_AUDIOMODE, &set_val);
02677    if (res < 0) {
02678       ast_log(LOG_WARNING, "Unable to enable audio mode on channel %d (%s)\n",
02679          pvt->channel, strerror(errno));
02680    }
02681 
02682    /* Set correct companding law for this call. */
02683    res = dahdi_setlaw(dfd, pvt->law);
02684    if (res < 0) {
02685       ast_log(LOG_WARNING, "Unable to set law on channel %d\n", pvt->channel);
02686    }
02687 
02688    /* Set correct gain for this call. */
02689    if (pvt->digital) {
02690       res = set_actual_gain(dfd, 0, 0, pvt->rxdrc, pvt->txdrc, pvt->law);
02691    } else {
02692       res = set_actual_gain(dfd, pvt->rxgain, pvt->txgain, pvt->rxdrc, pvt->txdrc,
02693          pvt->law);
02694    }
02695    if (res < 0) {
02696       ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", pvt->channel);
02697    }
02698 
02699    if (pvt->dsp_features && pvt->dsp) {
02700       ast_dsp_set_features(pvt->dsp, pvt->dsp_features);
02701       pvt->dsp_features = 0;
02702    }
02703 }
02704 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
02705 
02706 #if defined(HAVE_PRI)
02707 /*!
02708  * \internal
02709  * \brief Ask DAHDI to dial the given dial string.
02710  * \since 1.8.11
02711  *
02712  * \param p Channel private control structure.
02713  * \param dial_string String to pass to DAHDI to dial.
02714  *
02715  * \note The channel private lock needs to be held when calling.
02716  *
02717  * \return Nothing
02718  */
02719 static void my_pri_dial_digits(void *p, const char *dial_string)
02720 {
02721    struct dahdi_dialoperation zo = {
02722       .op = DAHDI_DIAL_OP_APPEND,
02723    };
02724    struct dahdi_pvt *pvt = p;
02725    int res;
02726 
02727    snprintf(zo.dialstr, sizeof(zo.dialstr), "T%s", dial_string);
02728    ast_debug(1, "Channel %d: Sending '%s' to DAHDI_DIAL.\n", pvt->channel, zo.dialstr);
02729    res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo);
02730    if (res) {
02731       ast_log(LOG_WARNING, "Channel %d: Couldn't dial '%s': %s\n",
02732          pvt->channel, dial_string, strerror(errno));
02733    } else {
02734       pvt->dialing = 1;
02735    }
02736 }
02737 #endif   /* defined(HAVE_PRI) */
02738 
02739 static int unalloc_sub(struct dahdi_pvt *p, int x);
02740 
02741 static int my_unallocate_sub(void *pvt, enum analog_sub analogsub)
02742 {
02743    struct dahdi_pvt *p = pvt;
02744 
02745    return unalloc_sub(p, analogsub_to_dahdisub(analogsub));
02746 }
02747 
02748 static int alloc_sub(struct dahdi_pvt *p, int x);
02749 
02750 static int my_allocate_sub(void *pvt, enum analog_sub analogsub)
02751 {
02752    struct dahdi_pvt *p = pvt;
02753 
02754    return alloc_sub(p, analogsub_to_dahdisub(analogsub));
02755 }
02756 
02757 static int has_voicemail(struct dahdi_pvt *p);
02758 
02759 static int my_has_voicemail(void *pvt)
02760 {
02761    struct dahdi_pvt *p = pvt;
02762 
02763    return has_voicemail(p);
02764 }
02765 
02766 static int my_play_tone(void *pvt, enum analog_sub sub, enum analog_tone tone)
02767 {
02768    struct dahdi_pvt *p = pvt;
02769    int index;
02770 
02771    index = analogsub_to_dahdisub(sub);
02772 
02773    return tone_zone_play_tone(p->subs[index].dfd, analog_tone_to_dahditone(tone));
02774 }
02775 
02776 static enum analog_event dahdievent_to_analogevent(int event)
02777 {
02778    enum analog_event res;
02779 
02780    switch (event) {
02781    case DAHDI_EVENT_ONHOOK:
02782       res = ANALOG_EVENT_ONHOOK;
02783       break;
02784    case DAHDI_EVENT_RINGOFFHOOK:
02785       res = ANALOG_EVENT_RINGOFFHOOK;
02786       break;
02787    case DAHDI_EVENT_WINKFLASH:
02788       res = ANALOG_EVENT_WINKFLASH;
02789       break;
02790    case DAHDI_EVENT_ALARM:
02791       res = ANALOG_EVENT_ALARM;
02792       break;
02793    case DAHDI_EVENT_NOALARM:
02794       res = ANALOG_EVENT_NOALARM;
02795       break;
02796    case DAHDI_EVENT_DIALCOMPLETE:
02797       res = ANALOG_EVENT_DIALCOMPLETE;
02798       break;
02799    case DAHDI_EVENT_RINGERON:
02800       res = ANALOG_EVENT_RINGERON;
02801       break;
02802    case DAHDI_EVENT_RINGEROFF:
02803       res = ANALOG_EVENT_RINGEROFF;
02804       break;
02805    case DAHDI_EVENT_HOOKCOMPLETE:
02806       res = ANALOG_EVENT_HOOKCOMPLETE;
02807       break;
02808    case DAHDI_EVENT_PULSE_START:
02809       res = ANALOG_EVENT_PULSE_START;
02810       break;
02811    case DAHDI_EVENT_POLARITY:
02812       res = ANALOG_EVENT_POLARITY;
02813       break;
02814    case DAHDI_EVENT_RINGBEGIN:
02815       res = ANALOG_EVENT_RINGBEGIN;
02816       break;
02817    case DAHDI_EVENT_EC_DISABLED:
02818       res = ANALOG_EVENT_EC_DISABLED;
02819       break;
02820    case DAHDI_EVENT_REMOVED:
02821       res = ANALOG_EVENT_REMOVED;
02822       break;
02823    case DAHDI_EVENT_NEONMWI_ACTIVE:
02824       res = ANALOG_EVENT_NEONMWI_ACTIVE;
02825       break;
02826    case DAHDI_EVENT_NEONMWI_INACTIVE:
02827       res = ANALOG_EVENT_NEONMWI_INACTIVE;
02828       break;
02829 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
02830    case DAHDI_EVENT_TX_CED_DETECTED:
02831       res = ANALOG_EVENT_TX_CED_DETECTED;
02832       break;
02833    case DAHDI_EVENT_RX_CED_DETECTED:
02834       res = ANALOG_EVENT_RX_CED_DETECTED;
02835       break;
02836    case DAHDI_EVENT_EC_NLP_DISABLED:
02837       res = ANALOG_EVENT_EC_NLP_DISABLED;
02838       break;
02839    case DAHDI_EVENT_EC_NLP_ENABLED:
02840       res = ANALOG_EVENT_EC_NLP_ENABLED;
02841       break;
02842 #endif
02843    case DAHDI_EVENT_PULSEDIGIT:
02844       res = ANALOG_EVENT_PULSEDIGIT;
02845       break;
02846    case DAHDI_EVENT_DTMFDOWN:
02847       res = ANALOG_EVENT_DTMFDOWN;
02848       break;
02849    case DAHDI_EVENT_DTMFUP:
02850       res = ANALOG_EVENT_DTMFUP;
02851       break;
02852    default:
02853       switch(event & 0xFFFF0000) {
02854       case DAHDI_EVENT_PULSEDIGIT:
02855       case DAHDI_EVENT_DTMFDOWN:
02856       case DAHDI_EVENT_DTMFUP:
02857          /* The event includes a digit number in the low word.
02858           * Converting it to a 'enum analog_event' would remove
02859           * that information. Thus it is returned as-is.
02860           */
02861          return event;
02862       }
02863 
02864       res = ANALOG_EVENT_ERROR;
02865       break;
02866    }
02867 
02868    return res;
02869 }
02870 
02871 static inline int dahdi_wait_event(int fd);
02872 
02873 static int my_wait_event(void *pvt)
02874 {
02875    struct dahdi_pvt *p = pvt;
02876 
02877    return dahdi_wait_event(p->subs[SUB_REAL].dfd);
02878 }
02879 
02880 static int my_get_event(void *pvt)
02881 {
02882    struct dahdi_pvt *p = pvt;
02883    int res;
02884 
02885    if (p->fake_event) {
02886       res = p->fake_event;
02887       p->fake_event = 0;
02888    } else
02889       res = dahdi_get_event(p->subs[SUB_REAL].dfd);
02890 
02891    return dahdievent_to_analogevent(res);
02892 }
02893 
02894 static int my_is_off_hook(void *pvt)
02895 {
02896    struct dahdi_pvt *p = pvt;
02897    int res;
02898    struct dahdi_params par;
02899 
02900    memset(&par, 0, sizeof(par));
02901 
02902    if (p->subs[SUB_REAL].dfd > -1)
02903       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
02904    else {
02905       /* Assume not off hook on CVRS */
02906       res = 0;
02907       par.rxisoffhook = 0;
02908    }
02909    if (res) {
02910       ast_log(LOG_WARNING, "Unable to check hook state on channel %d: %s\n", p->channel, strerror(errno));
02911    }
02912 
02913    if ((p->sig == SIG_FXSKS) || (p->sig == SIG_FXSGS)) {
02914       /* When "onhook" that means no battery on the line, and thus
02915       it is out of service..., if it's on a TDM card... If it's a channel
02916       bank, there is no telling... */
02917       return (par.rxbits > -1) || par.rxisoffhook;
02918    }
02919 
02920    return par.rxisoffhook;
02921 }
02922 
02923 static void dahdi_enable_ec(struct dahdi_pvt *p);
02924 static void dahdi_disable_ec(struct dahdi_pvt *p);
02925 
02926 static int my_set_echocanceller(void *pvt, int enable)
02927 {
02928    struct dahdi_pvt *p = pvt;
02929 
02930    if (enable)
02931       dahdi_enable_ec(p);
02932    else
02933       dahdi_disable_ec(p);
02934 
02935    return 0;
02936 }
02937 
02938 static int dahdi_ring_phone(struct dahdi_pvt *p);
02939 
02940 static int my_ring(void *pvt)
02941 {
02942    struct dahdi_pvt *p = pvt;
02943 
02944    return dahdi_ring_phone(p);
02945 }
02946 
02947 static int my_flash(void *pvt)
02948 {
02949    struct dahdi_pvt *p = pvt;
02950    int func = DAHDI_FLASH;
02951    return ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &func);
02952 }
02953 
02954 static inline int dahdi_set_hook(int fd, int hs);
02955 
02956 static int my_off_hook(void *pvt)
02957 {
02958    struct dahdi_pvt *p = pvt;
02959    return dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
02960 }
02961 
02962 static void my_set_needringing(void *pvt, int value)
02963 {
02964    struct dahdi_pvt *p = pvt;
02965    p->subs[SUB_REAL].needringing = value;
02966 }
02967 
02968 static void my_set_polarity(void *pvt, int value)
02969 {
02970    struct dahdi_pvt *p = pvt;
02971 
02972    if (p->channel == CHAN_PSEUDO) {
02973       return;
02974    }
02975    p->polarity = value;
02976    ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETPOLARITY, &value);
02977 }
02978 
02979 static void my_start_polarityswitch(void *pvt)
02980 {
02981    struct dahdi_pvt *p = pvt;
02982 
02983    if (p->answeronpolarityswitch || p->hanguponpolarityswitch) {
02984       my_set_polarity(pvt, 0);
02985    }
02986 }
02987 
02988 static void my_answer_polarityswitch(void *pvt)
02989 {
02990    struct dahdi_pvt *p = pvt;
02991 
02992    if (!p->answeronpolarityswitch) {
02993       return;
02994    }
02995 
02996    my_set_polarity(pvt, 1);
02997 }
02998 
02999 static void my_hangup_polarityswitch(void *pvt)
03000 {
03001    struct dahdi_pvt *p = pvt;
03002 
03003    if (!p->hanguponpolarityswitch) {
03004       return;
03005    }
03006 
03007    if (p->answeronpolarityswitch) {
03008       my_set_polarity(pvt, 0);
03009    } else {
03010       my_set_polarity(pvt, 1);
03011    }
03012 }
03013 
03014 static int my_start(void *pvt)
03015 {
03016    struct dahdi_pvt *p = pvt;
03017    int x = DAHDI_START;
03018 
03019    return ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
03020 }
03021 
03022 static int my_dial_digits(void *pvt, enum analog_sub sub, struct analog_dialoperation *dop)
03023 {
03024    int index = analogsub_to_dahdisub(sub);
03025    int res;
03026    struct dahdi_pvt *p = pvt;
03027    struct dahdi_dialoperation ddop;
03028 
03029    if (dop->op != ANALOG_DIAL_OP_REPLACE) {
03030       ast_log(LOG_ERROR, "Fix the dial_digits callback!\n");
03031       return -1;
03032    }
03033 
03034    if (sub != ANALOG_SUB_REAL) {
03035       ast_log(LOG_ERROR, "Trying to dial_digits '%s' on channel %d subchannel %u\n",
03036          dop->dialstr, p->channel, sub);
03037       return -1;
03038    }
03039 
03040    ddop.op = DAHDI_DIAL_OP_REPLACE;
03041    ast_copy_string(ddop.dialstr, dop->dialstr, sizeof(ddop.dialstr));
03042 
03043    ast_debug(1, "Channel %d: Sending '%s' to DAHDI_DIAL.\n", p->channel, ddop.dialstr);
03044 
03045    res = ioctl(p->subs[index].dfd, DAHDI_DIAL, &ddop);
03046    if (res == -1) {
03047       ast_debug(1, "DAHDI_DIAL ioctl failed on %s: %s\n", p->owner->name, strerror(errno));
03048    }
03049 
03050    return res;
03051 }
03052 
03053 static void dahdi_train_ec(struct dahdi_pvt *p);
03054 
03055 static int my_train_echocanceller(void *pvt)
03056 {
03057    struct dahdi_pvt *p = pvt;
03058 
03059    dahdi_train_ec(p);
03060 
03061    return 0;
03062 }
03063 
03064 static int my_is_dialing(void *pvt, enum analog_sub sub)
03065 {
03066    struct dahdi_pvt *p = pvt;
03067    int index;
03068    int x;
03069 
03070    index = analogsub_to_dahdisub(sub);
03071 
03072    if (ioctl(p->subs[index].dfd, DAHDI_DIALING, &x)) {
03073       ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed!\n");
03074       return -1;
03075    }
03076 
03077    return x;
03078 }
03079 
03080 static int my_on_hook(void *pvt)
03081 {
03082    struct dahdi_pvt *p = pvt;
03083    return dahdi_set_hook(p->subs[ANALOG_SUB_REAL].dfd, DAHDI_ONHOOK);
03084 }
03085 
03086 #if defined(HAVE_PRI)
03087 static void my_pri_fixup_chans(void *chan_old, void *chan_new)
03088 {
03089    struct dahdi_pvt *old_chan = chan_old;
03090    struct dahdi_pvt *new_chan = chan_new;
03091 
03092    new_chan->owner = old_chan->owner;
03093    old_chan->owner = NULL;
03094    if (new_chan->owner) {
03095       new_chan->owner->tech_pvt = new_chan;
03096       new_chan->owner->fds[0] = new_chan->subs[SUB_REAL].dfd;
03097       new_chan->subs[SUB_REAL].owner = old_chan->subs[SUB_REAL].owner;
03098       old_chan->subs[SUB_REAL].owner = NULL;
03099    }
03100    /* Copy any DSP that may be present */
03101    new_chan->dsp = old_chan->dsp;
03102    new_chan->dsp_features = old_chan->dsp_features;
03103    old_chan->dsp = NULL;
03104    old_chan->dsp_features = 0;
03105 
03106    /* Transfer flags from the old channel. */
03107    new_chan->dialing = old_chan->dialing;
03108    new_chan->digital = old_chan->digital;
03109    new_chan->outgoing = old_chan->outgoing;
03110    old_chan->dialing = 0;
03111    old_chan->digital = 0;
03112    old_chan->outgoing = 0;
03113 
03114    /* More stuff to transfer to the new channel. */
03115    new_chan->law = old_chan->law;
03116    strcpy(new_chan->dialstring, old_chan->dialstring);
03117 }
03118 #endif   /* defined(HAVE_PRI) */
03119 
03120 #if defined(HAVE_PRI)
03121 static int sig_pri_tone_to_dahditone(enum sig_pri_tone tone)
03122 {
03123    switch (tone) {
03124    case SIG_PRI_TONE_RINGTONE:
03125       return DAHDI_TONE_RINGTONE;
03126    case SIG_PRI_TONE_STUTTER:
03127       return DAHDI_TONE_STUTTER;
03128    case SIG_PRI_TONE_CONGESTION:
03129       return DAHDI_TONE_CONGESTION;
03130    case SIG_PRI_TONE_DIALTONE:
03131       return DAHDI_TONE_DIALTONE;
03132    case SIG_PRI_TONE_DIALRECALL:
03133       return DAHDI_TONE_DIALRECALL;
03134    case SIG_PRI_TONE_INFO:
03135       return DAHDI_TONE_INFO;
03136    case SIG_PRI_TONE_BUSY:
03137       return DAHDI_TONE_BUSY;
03138    default:
03139       return -1;
03140    }
03141 }
03142 #endif   /* defined(HAVE_PRI) */
03143 
03144 #if defined(HAVE_PRI)
03145 static int pri_destroy_dchan(struct sig_pri_span *pri);
03146 
03147 static void my_handle_dchan_exception(struct sig_pri_span *pri, int index)
03148 {
03149    int x;
03150 
03151    ioctl(pri->fds[index], DAHDI_GETEVENT, &x);
03152    switch (x) {
03153    case DAHDI_EVENT_NONE:
03154       break;
03155    case DAHDI_EVENT_ALARM:
03156    case DAHDI_EVENT_NOALARM:
03157       if (sig_pri_is_alarm_ignored(pri)) {
03158          break;
03159       }
03160       /* Fall through */
03161    default:
03162       ast_log(LOG_NOTICE, "PRI got event: %s (%d) on D-channel of span %d\n",
03163          event2str(x), x, pri->span);
03164       break;
03165    }
03166    /* Keep track of alarm state */
03167    switch (x) {
03168    case DAHDI_EVENT_ALARM:
03169       pri_event_alarm(pri, index, 0);
03170       break;
03171    case DAHDI_EVENT_NOALARM:
03172       pri_event_noalarm(pri, index, 0);
03173       break;
03174    case DAHDI_EVENT_REMOVED:
03175       pri_destroy_dchan(pri);
03176       break;
03177    default:
03178       break;
03179    }
03180 }
03181 #endif   /* defined(HAVE_PRI) */
03182 
03183 #if defined(HAVE_PRI)
03184 static int my_pri_play_tone(void *pvt, enum sig_pri_tone tone)
03185 {
03186    struct dahdi_pvt *p = pvt;
03187 
03188    return tone_zone_play_tone(p->subs[SUB_REAL].dfd, sig_pri_tone_to_dahditone(tone));
03189 }
03190 #endif   /* defined(HAVE_PRI) */
03191 
03192 #if defined(HAVE_PRI) || defined(HAVE_SS7)
03193 /*!
03194  * \internal
03195  * \brief Set the caller id information.
03196  * \since 1.8
03197  *
03198  * \param pvt DAHDI private structure
03199  * \param caller Caller-id information to set.
03200  *
03201  * \return Nothing
03202  */
03203 static void my_set_callerid(void *pvt, const struct ast_party_caller *caller)
03204 {
03205    struct dahdi_pvt *p = pvt;
03206 
03207    ast_copy_string(p->cid_num,
03208       S_COR(caller->id.number.valid, caller->id.number.str, ""),
03209       sizeof(p->cid_num));
03210    ast_copy_string(p->cid_name,
03211       S_COR(caller->id.name.valid, caller->id.name.str, ""),
03212       sizeof(p->cid_name));
03213    ast_copy_string(p->cid_subaddr,
03214       S_COR(caller->id.subaddress.valid, caller->id.subaddress.str, ""),
03215       sizeof(p->cid_subaddr));
03216    p->cid_ton = caller->id.number.plan;
03217    p->callingpres = ast_party_id_presentation(&caller->id);
03218    if (caller->id.tag) {
03219       ast_copy_string(p->cid_tag, caller->id.tag, sizeof(p->cid_tag));
03220    }
03221    ast_copy_string(p->cid_ani,
03222       S_COR(caller->ani.number.valid, caller->ani.number.str, ""),
03223       sizeof(p->cid_ani));
03224    p->cid_ani2 = caller->ani2;
03225 }
03226 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
03227 
03228 #if defined(HAVE_PRI) || defined(HAVE_SS7)
03229 /*!
03230  * \internal
03231  * \brief Set the Dialed Number Identifier.
03232  * \since 1.8
03233  *
03234  * \param pvt DAHDI private structure
03235  * \param dnid Dialed Number Identifier string.
03236  *
03237  * \return Nothing
03238  */
03239 static void my_set_dnid(void *pvt, const char *dnid)
03240 {
03241    struct dahdi_pvt *p = pvt;
03242 
03243    ast_copy_string(p->dnid, dnid, sizeof(p->dnid));
03244 }
03245 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
03246 
03247 #if defined(HAVE_PRI)
03248 /*!
03249  * \internal
03250  * \brief Set the Redirecting Directory Number Information Service (RDNIS).
03251  * \since 1.8
03252  *
03253  * \param pvt DAHDI private structure
03254  * \param rdnis Redirecting Directory Number Information Service (RDNIS) string.
03255  *
03256  * \return Nothing
03257  */
03258 static void my_set_rdnis(void *pvt, const char *rdnis)
03259 {
03260    struct dahdi_pvt *p = pvt;
03261 
03262    ast_copy_string(p->rdnis, rdnis, sizeof(p->rdnis));
03263 }
03264 #endif   /* defined(HAVE_PRI) */
03265 
03266 #if defined(HAVE_PRI)
03267 /*!
03268  * \internal
03269  * \brief Make a dialstring for native ISDN CC to recall properly.
03270  * \since 1.8
03271  *
03272  * \param priv Channel private control structure.
03273  * \param buf Where to put the modified dialstring.
03274  * \param buf_size Size of modified dialstring buffer.
03275  *
03276  * \details
03277  * original dialstring:
03278  * DAHDI/[i<span>-](g|G|r|R)<group#(0-63)>[c|r<cadance#>|d][/extension[/options]]
03279  *
03280  * The modified dialstring will have prefixed the channel-group section
03281  * with the ISDN channel restriction.
03282  *
03283  * buf:
03284  * DAHDI/i<span>-(g|G|r|R)<group#(0-63)>[c|r<cadance#>|d][/extension[/options]]
03285  *
03286  * The routine will check to see if the ISDN channel restriction is already
03287  * in the original dialstring.
03288  *
03289  * \return Nothing
03290  */
03291 static void my_pri_make_cc_dialstring(void *priv, char *buf, size_t buf_size)
03292 {
03293    char *dial;
03294    struct dahdi_pvt *pvt;
03295    AST_DECLARE_APP_ARGS(args,
03296       AST_APP_ARG(tech);   /* channel technology token */
03297       AST_APP_ARG(group);  /* channel/group token */
03298       //AST_APP_ARG(ext);  /* extension token */
03299       //AST_APP_ARG(opts); /* options token */
03300       //AST_APP_ARG(other);   /* Any remining unused arguments */
03301    );
03302 
03303    pvt = priv;
03304    dial = ast_strdupa(pvt->dialstring);
03305    AST_NONSTANDARD_APP_ARGS(args, dial, '/');
03306    if (!args.tech) {
03307       ast_copy_string(buf, pvt->dialstring, buf_size);
03308       return;
03309    }
03310    if (!args.group) {
03311       /* Append the ISDN span channel restriction to the dialstring. */
03312       snprintf(buf, buf_size, "%s/i%d-", args.tech, pvt->pri->span);
03313       return;
03314    }
03315    if (isdigit(args.group[0]) || args.group[0] == 'i' || strchr(args.group, '!')) {
03316       /* The ISDN span channel restriction is not needed or already
03317        * in the dialstring. */
03318       ast_copy_string(buf, pvt->dialstring, buf_size);
03319       return;
03320    }
03321    /* Insert the ISDN span channel restriction into the dialstring. */
03322    snprintf(buf, buf_size, "%s/i%d-%s", args.tech, pvt->pri->span, args.group);
03323 }
03324 #endif   /* defined(HAVE_PRI) */
03325 
03326 #if defined(HAVE_PRI)
03327 /*!
03328  * \internal
03329  * \brief Reevaluate the PRI span device state.
03330  * \since 1.8
03331  *
03332  * \param pri Asterisk D channel control structure.
03333  *
03334  * \return Nothing
03335  *
03336  * \note Assumes the pri->lock is already obtained.
03337  */
03338 static void dahdi_pri_update_span_devstate(struct sig_pri_span *pri)
03339 {
03340    unsigned idx;
03341    unsigned num_b_chans;   /* Number of B channels provisioned on the span. */
03342    unsigned in_use;     /* Number of B channels in use on the span. */
03343    unsigned in_alarm;      /* TRUE if the span is in alarm condition. */
03344    enum ast_device_state new_state;
03345 
03346    /* Count the number of B channels and the number of B channels in use. */
03347    num_b_chans = 0;
03348    in_use = 0;
03349    in_alarm = 1;
03350    for (idx = pri->numchans; idx--;) {
03351       if (pri->pvts[idx] && !pri->pvts[idx]->no_b_channel) {
03352          /* This is a B channel interface. */
03353          ++num_b_chans;
03354          if (!sig_pri_is_chan_available(pri->pvts[idx])) {
03355             ++in_use;
03356          }
03357          if (!pri->pvts[idx]->inalarm) {
03358             /* There is a channel that is not in alarm. */
03359             in_alarm = 0;
03360          }
03361       }
03362    }
03363 
03364    /* Update the span congestion device state and report any change. */
03365    if (in_alarm) {
03366       new_state = AST_DEVICE_UNAVAILABLE;
03367    } else {
03368       new_state = num_b_chans == in_use ? AST_DEVICE_BUSY : AST_DEVICE_NOT_INUSE;
03369    }
03370    if (pri->congestion_devstate != new_state) {
03371       pri->congestion_devstate = new_state;
03372       ast_devstate_changed(AST_DEVICE_UNKNOWN, AST_DEVSTATE_NOT_CACHABLE, "DAHDI/I%d/congestion", pri->span);
03373    }
03374 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
03375    /* Update the span threshold device state and report any change. */
03376    if (in_alarm) {
03377       new_state = AST_DEVICE_UNAVAILABLE;
03378    } else if (!in_use) {
03379       new_state = AST_DEVICE_NOT_INUSE;
03380    } else if (!pri->user_busy_threshold) {
03381       new_state = in_use < num_b_chans ? AST_DEVICE_INUSE : AST_DEVICE_BUSY;
03382    } else {
03383       new_state = in_use < pri->user_busy_threshold ? AST_DEVICE_INUSE
03384          : AST_DEVICE_BUSY;
03385    }
03386    if (pri->threshold_devstate != new_state) {
03387       pri->threshold_devstate = new_state;
03388       ast_devstate_changed(AST_DEVICE_UNKNOWN, AST_DEVSTATE_NOT_CACHABLE, "DAHDI/I%d/threshold", pri->span);
03389    }
03390 #endif   /* defined(THRESHOLD_DEVSTATE_PLACEHOLDER) */
03391 }
03392 #endif   /* defined(HAVE_PRI) */
03393 
03394 #if defined(HAVE_PRI)
03395 /*!
03396  * \internal
03397  * \brief Reference this module.
03398  * \since 1.8
03399  *
03400  * \return Nothing
03401  */
03402 static void my_module_ref(void)
03403 {
03404    ast_module_ref(ast_module_info->self);
03405 }
03406 #endif   /* defined(HAVE_PRI) */
03407 
03408 #if defined(HAVE_PRI)
03409 /*!
03410  * \internal
03411  * \brief Unreference this module.
03412  * \since 1.8
03413  *
03414  * \return Nothing
03415  */
03416 static void my_module_unref(void)
03417 {
03418    ast_module_unref(ast_module_info->self);
03419 }
03420 #endif   /* defined(HAVE_PRI) */
03421 
03422 #if defined(HAVE_PRI)
03423 #if defined(HAVE_PRI_CALL_WAITING)
03424 static void my_pri_init_config(void *priv, struct sig_pri_span *pri);
03425 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
03426 static int dahdi_new_pri_nobch_channel(struct sig_pri_span *pri);
03427 
03428 static struct sig_pri_callback dahdi_pri_callbacks =
03429 {
03430    .handle_dchan_exception = my_handle_dchan_exception,
03431    .play_tone = my_pri_play_tone,
03432    .set_echocanceller = my_set_echocanceller,
03433    .dsp_reset_and_flush_digits = my_dsp_reset_and_flush_digits,
03434    .lock_private = my_lock_private,
03435    .unlock_private = my_unlock_private,
03436    .new_ast_channel = my_new_pri_ast_channel,
03437    .fixup_chans = my_pri_fixup_chans,
03438    .set_alarm = my_set_alarm,
03439    .set_dialing = my_set_dialing,
03440    .set_outgoing = my_set_outgoing,
03441    .set_digital = my_set_digital,
03442    .set_callerid = my_set_callerid,
03443    .set_dnid = my_set_dnid,
03444    .set_rdnis = my_set_rdnis,
03445    .new_nobch_intf = dahdi_new_pri_nobch_channel,
03446 #if defined(HAVE_PRI_CALL_WAITING)
03447    .init_config = my_pri_init_config,
03448 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
03449    .get_orig_dialstring = my_get_orig_dialstring,
03450    .make_cc_dialstring = my_pri_make_cc_dialstring,
03451    .update_span_devstate = dahdi_pri_update_span_devstate,
03452    .module_ref = my_module_ref,
03453    .module_unref = my_module_unref,
03454    .dial_digits = my_pri_dial_digits,
03455    .open_media = my_pri_ss7_open_media,
03456    .ami_channel_event = my_ami_channel_event,
03457 };
03458 #endif   /* defined(HAVE_PRI) */
03459 
03460 #if defined(HAVE_SS7)
03461 /*!
03462  * \internal
03463  * \brief Handle the SS7 link exception.
03464  * \since 1.8
03465  *
03466  * \param linkset Controlling linkset for the channel.
03467  * \param which Link index of the signaling channel.
03468  *
03469  * \return Nothing
03470  */
03471 static void my_handle_link_exception(struct sig_ss7_linkset *linkset, int which)
03472 {
03473    int event;
03474 
03475    if (ioctl(linkset->fds[which], DAHDI_GETEVENT, &event)) {
03476       ast_log(LOG_ERROR, "SS7: Error in exception retrieval on span %d/%d!\n",
03477          linkset->span, which);
03478       return;
03479    }
03480    switch (event) {
03481    case DAHDI_EVENT_NONE:
03482       break;
03483    case DAHDI_EVENT_ALARM:
03484       ast_log(LOG_ERROR, "SS7 got event: %s(%d) on span %d/%d\n",
03485          event2str(event), event, linkset->span, which);
03486       sig_ss7_link_alarm(linkset, which);
03487       break;
03488    case DAHDI_EVENT_NOALARM:
03489       ast_log(LOG_ERROR, "SS7 got event: %s(%d) on span %d/%d\n",
03490          event2str(event), event, linkset->span, which);
03491       sig_ss7_link_noalarm(linkset, which);
03492       break;
03493    default:
03494       ast_log(LOG_NOTICE, "SS7 got event: %s(%d) on span %d/%d\n",
03495          event2str(event), event, linkset->span, which);
03496       break;
03497    }
03498 }
03499 #endif   /* defined(HAVE_SS7) */
03500 
03501 #if defined(HAVE_SS7)
03502 static void my_ss7_set_loopback(void *pvt, int enable)
03503 {
03504    struct dahdi_pvt *p = pvt;
03505 
03506    if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_LOOPBACK, &enable)) {
03507       ast_log(LOG_WARNING, "Unable to set loopback on channel %d: %s\n", p->channel,
03508          strerror(errno));
03509    }
03510 }
03511 #endif   /* defined(HAVE_SS7) */
03512 
03513 #if defined(HAVE_SS7)
03514 /*!
03515  * \internal
03516  * \brief Create a new asterisk channel structure for SS7.
03517  * \since 1.8
03518  *
03519  * \param pvt Private channel structure.
03520  * \param state Initial state of new channel.
03521  * \param law Combanding law to use.
03522  * \param exten Dialplan extension for incoming call.
03523  * \param requestor Channel requesting this new channel.
03524  *
03525  * \retval ast_channel on success.
03526  * \retval NULL on error.
03527  */
03528 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)
03529 {
03530    struct dahdi_pvt *p = pvt;
03531    int audio;
03532    int newlaw;
03533 
03534    /* Set to audio mode at this point */
03535    audio = 1;
03536    if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &audio) == -1)
03537       ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n",
03538          p->channel, audio, strerror(errno));
03539 
03540    if (law != SIG_SS7_DEFLAW) {
03541       dahdi_setlaw(p->subs[SUB_REAL].dfd,
03542          (law == SIG_SS7_ULAW) ? DAHDI_LAW_MULAW : DAHDI_LAW_ALAW);
03543    }
03544 
03545    ast_copy_string(p->exten, exten, sizeof(p->exten));
03546 
03547    newlaw = -1;
03548    switch (law) {
03549    case SIG_SS7_DEFLAW:
03550       newlaw = 0;
03551       break;
03552    case SIG_SS7_ALAW:
03553       newlaw = DAHDI_LAW_ALAW;
03554       break;
03555    case SIG_SS7_ULAW:
03556       newlaw = DAHDI_LAW_MULAW;
03557       break;
03558    }
03559    return dahdi_new(p, state, 0, SUB_REAL, newlaw, requestor ? requestor->linkedid : "");
03560 }
03561 #endif   /* defined(HAVE_SS7) */
03562 
03563 #if defined(HAVE_SS7)
03564 static int sig_ss7_tone_to_dahditone(enum sig_ss7_tone tone)
03565 {
03566    switch (tone) {
03567    case SIG_SS7_TONE_RINGTONE:
03568       return DAHDI_TONE_RINGTONE;
03569    case SIG_SS7_TONE_STUTTER:
03570       return DAHDI_TONE_STUTTER;
03571    case SIG_SS7_TONE_CONGESTION:
03572       return DAHDI_TONE_CONGESTION;
03573    case SIG_SS7_TONE_DIALTONE:
03574       return DAHDI_TONE_DIALTONE;
03575    case SIG_SS7_TONE_DIALRECALL:
03576       return DAHDI_TONE_DIALRECALL;
03577    case SIG_SS7_TONE_INFO:
03578       return DAHDI_TONE_INFO;
03579    case SIG_SS7_TONE_BUSY:
03580       return DAHDI_TONE_BUSY;
03581    default:
03582       return -1;
03583    }
03584 }
03585 #endif   /* defined(HAVE_SS7) */
03586 
03587 #if defined(HAVE_SS7)
03588 static int my_ss7_play_tone(void *pvt, enum sig_ss7_tone tone)
03589 {
03590    struct dahdi_pvt *p = pvt;
03591 
03592    return tone_zone_play_tone(p->subs[SUB_REAL].dfd, sig_ss7_tone_to_dahditone(tone));
03593 }
03594 #endif   /* defined(HAVE_SS7) */
03595 
03596 #if defined(HAVE_SS7)
03597 static struct sig_ss7_callback dahdi_ss7_callbacks =
03598 {
03599    .lock_private = my_lock_private,
03600    .unlock_private = my_unlock_private,
03601 
03602    .set_echocanceller = my_set_echocanceller,
03603    .set_loopback = my_ss7_set_loopback,
03604 
03605    .new_ast_channel = my_new_ss7_ast_channel,
03606    .play_tone = my_ss7_play_tone,
03607 
03608    .handle_link_exception = my_handle_link_exception,
03609    .set_alarm = my_set_alarm,
03610    .set_dialing = my_set_dialing,
03611    .set_outgoing = my_set_outgoing,
03612    .set_digital = my_set_digital,
03613    .set_inservice = my_set_inservice,
03614    .set_locallyblocked = my_set_locallyblocked,
03615    .set_remotelyblocked = my_set_remotelyblocked,
03616    .set_callerid = my_set_callerid,
03617    .set_dnid = my_set_dnid,
03618    .open_media = my_pri_ss7_open_media,
03619 };
03620 #endif   /* defined(HAVE_SS7) */
03621 
03622 /*!
03623  * \brief Send MWI state change
03624  *
03625  * \arg mailbox_full This is the mailbox associated with the FXO line that the
03626  *      MWI state has changed on.
03627  * \arg thereornot This argument should simply be set to 1 or 0, to indicate
03628  *      whether there are messages waiting or not.
03629  *
03630  *  \return nothing
03631  *
03632  * This function does two things:
03633  *
03634  * 1) It generates an internal Asterisk event notifying any other module that
03635  *    cares about MWI that the state of a mailbox has changed.
03636  *
03637  * 2) It runs the script specified by the mwimonitornotify option to allow
03638  *    some custom handling of the state change.
03639  */
03640 static void notify_message(char *mailbox_full, int thereornot)
03641 {
03642    char s[sizeof(mwimonitornotify) + 80];
03643    struct ast_event *event;
03644    char *mailbox, *context;
03645 
03646    /* Strip off @default */
03647    context = mailbox = ast_strdupa(mailbox_full);
03648    strsep(&context, "@");
03649    if (ast_strlen_zero(context))
03650       context = "default";
03651 
03652    if (!(event = ast_event_new(AST_EVENT_MWI,
03653          AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
03654          AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
03655          AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot,
03656          AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot,
03657          AST_EVENT_IE_END))) {
03658       return;
03659    }
03660 
03661    ast_event_queue_and_cache(event);
03662 
03663    if (!ast_strlen_zero(mailbox) && !ast_strlen_zero(mwimonitornotify)) {
03664       snprintf(s, sizeof(s), "%s %s %d", mwimonitornotify, mailbox, thereornot);
03665       ast_safe_system(s);
03666    }
03667 }
03668 
03669 static void my_handle_notify_message(struct ast_channel *chan, void *pvt, int cid_flags, int neon_mwievent)
03670 {
03671    struct dahdi_pvt *p = pvt;
03672 
03673    if (neon_mwievent > -1 && !p->mwimonitor_neon)
03674       return;
03675 
03676    if (neon_mwievent == ANALOG_EVENT_NEONMWI_ACTIVE || cid_flags & CID_MSGWAITING) {
03677       ast_log(LOG_NOTICE, "MWI: Channel %d message waiting, mailbox %s\n", p->channel, p->mailbox);
03678       notify_message(p->mailbox, 1);
03679    } else if (neon_mwievent == ANALOG_EVENT_NEONMWI_INACTIVE || cid_flags & CID_NOMSGWAITING) {
03680       ast_log(LOG_NOTICE, "MWI: Channel %d no message waiting, mailbox %s\n", p->channel, p->mailbox);
03681       notify_message(p->mailbox, 0);
03682    }
03683    /* If the CID had Message waiting payload, assume that this for MWI only and hangup the call */
03684    /* If generated using Ring Pulse Alert, then ring has been answered as a call and needs to be hungup */
03685    if (neon_mwievent == -1 && p->mwimonitor_rpas) {
03686       ast_hangup(chan);
03687       return;
03688    }
03689 }
03690 
03691 static int my_have_progressdetect(void *pvt)
03692 {
03693    struct dahdi_pvt *p = pvt;
03694 
03695    if ((p->callprogress & CALLPROGRESS_PROGRESS)
03696       && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
03697       return 1;
03698    } else {
03699       /* Don't have progress detection. */
03700       return 0;
03701    }
03702 }
03703 
03704 static struct analog_callback dahdi_analog_callbacks =
03705 {
03706    .play_tone = my_play_tone,
03707    .get_event = my_get_event,
03708    .wait_event = my_wait_event,
03709    .is_off_hook = my_is_off_hook,
03710    .set_echocanceller = my_set_echocanceller,
03711    .ring = my_ring,
03712    .flash = my_flash,
03713    .off_hook = my_off_hook,
03714    .dial_digits = my_dial_digits,
03715    .train_echocanceller = my_train_echocanceller,
03716    .on_hook = my_on_hook,
03717    .is_dialing = my_is_dialing,
03718    .allocate_sub = my_allocate_sub,
03719    .unallocate_sub = my_unallocate_sub,
03720    .swap_subs = my_swap_subchannels,
03721    .has_voicemail = my_has_voicemail,
03722    .check_for_conference = my_check_for_conference,
03723    .conf_add = my_conf_add,
03724    .conf_del = my_conf_del,
03725    .complete_conference_update = my_complete_conference_update,
03726    .start = my_start,
03727    .all_subchannels_hungup = my_all_subchannels_hungup,
03728    .lock_private = my_lock_private,
03729    .unlock_private = my_unlock_private,
03730    .deadlock_avoidance_private = my_deadlock_avoidance_private,
03731    .handle_dtmf = my_handle_dtmf,
03732    .wink = my_wink,
03733    .new_ast_channel = my_new_analog_ast_channel,
03734    .dsp_set_digitmode = my_dsp_set_digitmode,
03735    .dsp_reset_and_flush_digits = my_dsp_reset_and_flush_digits,
03736    .send_callerid = my_send_callerid,
03737    .callwait = my_callwait,
03738    .stop_callwait = my_stop_callwait,
03739    .get_callerid = my_get_callerid,
03740    .start_cid_detect = my_start_cid_detect,
03741    .stop_cid_detect = my_stop_cid_detect,
03742    .handle_notify_message = my_handle_notify_message,
03743    .increase_ss_count = my_increase_ss_count,
03744    .decrease_ss_count = my_decrease_ss_count,
03745    .distinctive_ring = my_distinctive_ring,
03746    .set_linear_mode = my_set_linear_mode,
03747    .set_inthreeway = my_set_inthreeway,
03748    .get_and_handle_alarms = my_get_and_handle_alarms,
03749    .get_sigpvt_bridged_channel = my_get_sigpvt_bridged_channel,
03750    .get_sub_fd = my_get_sub_fd,
03751    .set_cadence = my_set_cadence,
03752    .set_alarm = my_set_alarm,
03753    .set_dialing = my_set_dialing,
03754    .set_outgoing = my_set_outgoing,
03755    .set_ringtimeout = my_set_ringtimeout,
03756    .set_waitingfordt = my_set_waitingfordt,
03757    .check_waitingfordt = my_check_waitingfordt,
03758    .set_confirmanswer = my_set_confirmanswer,
03759    .check_confirmanswer = my_check_confirmanswer,
03760    .set_callwaiting = my_set_callwaiting,
03761    .cancel_cidspill = my_cancel_cidspill,
03762    .confmute = my_confmute,
03763    .set_pulsedial = my_set_pulsedial,
03764    .set_new_owner = my_set_new_owner,
03765    .get_orig_dialstring = my_get_orig_dialstring,
03766    .set_needringing = my_set_needringing,
03767    .set_polarity = my_set_polarity,
03768    .start_polarityswitch = my_start_polarityswitch,
03769    .answer_polarityswitch = my_answer_polarityswitch,
03770    .hangup_polarityswitch = my_hangup_polarityswitch,
03771    .have_progressdetect = my_have_progressdetect,
03772 };
03773 
03774 /*! Round robin search locations. */
03775 static struct dahdi_pvt *round_robin[32];
03776 
03777 #define dahdi_get_index(ast, p, nullok)   _dahdi_get_index(ast, p, nullok, __PRETTY_FUNCTION__, __LINE__)
03778 static int _dahdi_get_index(struct ast_channel *ast, struct dahdi_pvt *p, int nullok, const char *fname, unsigned long line)
03779 {
03780    int res;
03781    if (p->subs[SUB_REAL].owner == ast)
03782       res = 0;
03783    else if (p->subs[SUB_CALLWAIT].owner == ast)
03784       res = 1;
03785    else if (p->subs[SUB_THREEWAY].owner == ast)
03786       res = 2;
03787    else {
03788       res = -1;
03789       if (!nullok)
03790          ast_log(LOG_WARNING,
03791             "Unable to get index for '%s' on channel %d (%s(), line %lu)\n",
03792             ast ? ast->name : "", p->channel, fname, line);
03793    }
03794    return res;
03795 }
03796 
03797 /*!
03798  * \internal
03799  * \brief Obtain the specified subchannel owner lock if the owner exists.
03800  *
03801  * \param pvt Channel private struct.
03802  * \param sub_idx Subchannel owner to lock.
03803  *
03804  * \note Assumes the pvt->lock is already obtained.
03805  *
03806  * \note
03807  * Because deadlock avoidance may have been necessary, you need to confirm
03808  * the state of things before continuing.
03809  *
03810  * \return Nothing
03811  */
03812 static void dahdi_lock_sub_owner(struct dahdi_pvt *pvt, int sub_idx)
03813 {
03814    for (;;) {
03815       if (!pvt->subs[sub_idx].owner) {
03816          /* No subchannel owner pointer */
03817          break;
03818       }
03819       if (!ast_channel_trylock(pvt->subs[sub_idx].owner)) {
03820          /* Got subchannel owner lock */
03821          break;
03822       }
03823       /* We must unlock the private to avoid the possibility of a deadlock */
03824       DEADLOCK_AVOIDANCE(&pvt->lock);
03825    }
03826 }
03827 
03828 static void wakeup_sub(struct dahdi_pvt *p, int a)
03829 {
03830    dahdi_lock_sub_owner(p, a);
03831    if (p->subs[a].owner) {
03832       ast_queue_frame(p->subs[a].owner, &ast_null_frame);
03833       ast_channel_unlock(p->subs[a].owner);
03834    }
03835 }
03836 
03837 static void dahdi_queue_frame(struct dahdi_pvt *p, struct ast_frame *f)
03838 {
03839    for (;;) {
03840       if (p->owner) {
03841          if (ast_channel_trylock(p->owner)) {
03842             DEADLOCK_AVOIDANCE(&p->lock);
03843          } else {
03844             ast_queue_frame(p->owner, f);
03845             ast_channel_unlock(p->owner);
03846             break;
03847          }
03848       } else
03849          break;
03850    }
03851 }
03852 
03853 static void handle_clear_alarms(struct dahdi_pvt *p)
03854 {
03855 #if defined(HAVE_PRI)
03856    if (dahdi_sig_pri_lib_handles(p->sig) && sig_pri_is_alarm_ignored(p->pri)) {
03857       return;
03858    }
03859 #endif   /* defined(HAVE_PRI) */
03860 
03861    if (report_alarms & REPORT_CHANNEL_ALARMS) {
03862       ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel);
03863       manager_event(EVENT_FLAG_SYSTEM, "AlarmClear", "Channel: %d\r\n", p->channel);
03864    }
03865    if (report_alarms & REPORT_SPAN_ALARMS && p->manages_span_alarms) {
03866       ast_log(LOG_NOTICE, "Alarm cleared on span %d\n", p->span);
03867       manager_event(EVENT_FLAG_SYSTEM, "SpanAlarmClear", "Span: %d\r\n", p->span);
03868    }
03869 }
03870 
03871 #ifdef HAVE_OPENR2
03872 
03873 static int dahdi_r2_answer(struct dahdi_pvt *p)
03874 {
03875    int res = 0;
03876    /* openr2 1.1.0 and older does not even define OR2_LIB_INTERFACE
03877    * and does not has support for openr2_chan_answer_call_with_mode
03878    *  */
03879 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
03880    const char *double_answer = pbx_builtin_getvar_helper(p->owner, "MFCR2_DOUBLE_ANSWER");
03881    int wants_double_answer = ast_true(double_answer) ? 1 : 0;
03882    if (!double_answer) {
03883       /* this still can result in double answer if the channel context
03884       * was configured that way */
03885       res = openr2_chan_answer_call(p->r2chan);
03886    } else if (wants_double_answer) {
03887       res = openr2_chan_answer_call_with_mode(p->r2chan, OR2_ANSWER_DOUBLE);
03888    } else {
03889       res = openr2_chan_answer_call_with_mode(p->r2chan, OR2_ANSWER_SIMPLE);
03890    }
03891 #else
03892    res = openr2_chan_answer_call(p->r2chan);
03893 #endif
03894    return res;
03895 }
03896 
03897 
03898 
03899 /* should be called with the ast_channel locked */
03900 static openr2_calling_party_category_t dahdi_r2_get_channel_category(struct ast_channel *c)
03901 {
03902    openr2_calling_party_category_t cat;
03903    const char *catstr = pbx_builtin_getvar_helper(c, "MFCR2_CATEGORY");
03904    struct dahdi_pvt *p = c->tech_pvt;
03905    if (ast_strlen_zero(catstr)) {
03906       ast_debug(1, "No MFC/R2 category specified for chan %s, using default %s\n",
03907             c->name, openr2_proto_get_category_string(p->mfcr2_category));
03908       return p->mfcr2_category;
03909    }
03910    if ((cat = openr2_proto_get_category(catstr)) == OR2_CALLING_PARTY_CATEGORY_UNKNOWN) {
03911       ast_log(LOG_WARNING, "Invalid category specified '%s' for chan %s, using default %s\n",
03912             catstr, c->name, openr2_proto_get_category_string(p->mfcr2_category));
03913       return p->mfcr2_category;
03914    }
03915    ast_debug(1, "Using category %s\n", catstr);
03916    return cat;
03917 }
03918 
03919 static void dahdi_r2_on_call_init(openr2_chan_t *r2chan)
03920 {
03921    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
03922    ast_mutex_lock(&p->lock);
03923    if (p->mfcr2call) {
03924       ast_mutex_unlock(&p->lock);
03925       /* TODO: This can happen when some other thread just finished dahdi_request requesting this very same
03926          interface but has not yet seized the line (dahdi_call), and the far end wins and seize the line,
03927          can we avoid this somehow?, at this point when dahdi_call send the seize, it is likely that since
03928          the other end will see our seize as a forced release and drop the call, we will see an invalid
03929          pattern that will be seen and treated as protocol error. */
03930       ast_log(LOG_ERROR, "Collision of calls on chan %d detected!.\n", openr2_chan_get_number(r2chan));
03931       return;
03932    }
03933    p->mfcr2call = 1;
03934    /* better safe than sorry ... */
03935    p->cid_name[0] = '\0';
03936    p->cid_num[0] = '\0';
03937    p->cid_subaddr[0] = '\0';
03938    p->rdnis[0] = '\0';
03939    p->exten[0] = '\0';
03940    p->mfcr2_ani_index = '\0';
03941    p->mfcr2_dnis_index = '\0';
03942    p->mfcr2_dnis_matched = 0;
03943    p->mfcr2_answer_pending = 0;
03944    p->mfcr2_call_accepted = 0;
03945    ast_mutex_unlock(&p->lock);
03946    ast_verbose("New MFC/R2 call detected on chan %d.\n", openr2_chan_get_number(r2chan));
03947 }
03948 
03949 static void dahdi_r2_on_hardware_alarm(openr2_chan_t *r2chan, int alarm)
03950 {
03951    int res;
03952    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
03953    ast_mutex_lock(&p->lock);
03954    p->inalarm = alarm ? 1 : 0;
03955    if (p->inalarm) {
03956       res = get_alarms(p);
03957       handle_alarms(p, res);
03958    } else {
03959       handle_clear_alarms(p);
03960    }
03961    ast_mutex_unlock(&p->lock);
03962 }
03963 
03964 static void dahdi_r2_on_os_error(openr2_chan_t *r2chan, int errorcode)
03965 {
03966    ast_log(LOG_ERROR, "OS error on chan %d: %s\n", openr2_chan_get_number(r2chan), strerror(errorcode));
03967 }
03968 
03969 static void dahdi_r2_on_protocol_error(openr2_chan_t *r2chan, openr2_protocol_error_t reason)
03970 {
03971    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
03972    ast_log(LOG_ERROR, "MFC/R2 protocol error on chan %d: %s\n", openr2_chan_get_number(r2chan), openr2_proto_get_error(reason));
03973    if (p->owner) {
03974       p->owner->hangupcause = AST_CAUSE_PROTOCOL_ERROR;
03975       p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
03976    }
03977    ast_mutex_lock(&p->lock);
03978    p->mfcr2call = 0;
03979    ast_mutex_unlock(&p->lock);
03980 }
03981 
03982 static void dahdi_r2_disconnect_call(struct dahdi_pvt *p, openr2_call_disconnect_cause_t cause)
03983 {
03984    if (openr2_chan_disconnect_call(p->r2chan, cause)) {
03985       ast_log(LOG_NOTICE, "Bad! failed to disconnect call on channel %d with reason %s, hope for the best!\n",
03986          p->channel, openr2_proto_get_disconnect_string(cause));
03987       /* force the chan to idle and release the call flag now since we will not see a clean on_call_end */
03988       openr2_chan_set_idle(p->r2chan);
03989       ast_mutex_lock(&p->lock);
03990       p->mfcr2call = 0;
03991       ast_mutex_unlock(&p->lock);
03992    }
03993 }
03994 
03995 static void dahdi_r2_on_call_offered(openr2_chan_t *r2chan, const char *ani, const char *dnis, openr2_calling_party_category_t category)
03996 {
03997    struct dahdi_pvt *p;
03998    struct ast_channel *c;
03999    ast_verbose("MFC/R2 call offered on chan %d. ANI = %s, DNIS = %s, Category = %s\n",
04000          openr2_chan_get_number(r2chan), ani ? ani : "(restricted)", dnis,
04001          openr2_proto_get_category_string(category));
04002    p = openr2_chan_get_client_data(r2chan);
04003    /* if collect calls are not allowed and this is a collect call, reject it! */
04004    if (!p->mfcr2_allow_collect_calls && category == OR2_CALLING_PARTY_CATEGORY_COLLECT_CALL) {
04005       ast_log(LOG_NOTICE, "Rejecting MFC/R2 collect call\n");
04006       dahdi_r2_disconnect_call(p, OR2_CAUSE_COLLECT_CALL_REJECTED);
04007       return;
04008    }
04009    ast_mutex_lock(&p->lock);
04010    p->mfcr2_recvd_category = category;
04011    /* if we're not supposed to use CID, clear whatever we have */
04012    if (!p->use_callerid) {
04013       ast_log(LOG_DEBUG, "No CID allowed in configuration, CID is being cleared!\n");
04014       p->cid_num[0] = 0;
04015       p->cid_name[0] = 0;
04016    }
04017    /* if we're supposed to answer immediately, clear DNIS and set 's' exten */
04018    if (p->immediate || !openr2_context_get_max_dnis(openr2_chan_get_context(r2chan))) {
04019       ast_log(LOG_DEBUG, "Setting exten => s because of immediate or 0 DNIS configured\n");
04020       p->exten[0] = 's';
04021       p->exten[1] = 0;
04022    }
04023    ast_mutex_unlock(&p->lock);
04024    if (!ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
04025       ast_log(LOG_NOTICE, "MFC/R2 call on channel %d requested non-existent extension '%s' in context '%s'. Rejecting call.\n",
04026             p->channel, p->exten, p->context);
04027       dahdi_r2_disconnect_call(p, OR2_CAUSE_UNALLOCATED_NUMBER);
04028       return;
04029    }
04030    if (!p->mfcr2_accept_on_offer) {
04031       /* The user wants us to start the PBX thread right away without accepting the call first */
04032       c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, NULL);
04033       if (c) {
04034          /* Done here, don't disable reading now since we still need to generate MF tones to accept
04035             the call or reject it and detect the tone off condition of the other end, all of this
04036             will be done in the PBX thread now */
04037          return;
04038       }
04039       ast_log(LOG_WARNING, "Unable to create PBX channel in DAHDI channel %d\n", p->channel);
04040       dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER);
04041    } else if (p->mfcr2_charge_calls) {
04042       ast_log(LOG_DEBUG, "Accepting MFC/R2 call with charge on chan %d\n", p->channel);
04043       openr2_chan_accept_call(r2chan, OR2_CALL_WITH_CHARGE);
04044    } else {
04045       ast_log(LOG_DEBUG, "Accepting MFC/R2 call with no charge on chan %d\n", p->channel);
04046       openr2_chan_accept_call(r2chan, OR2_CALL_NO_CHARGE);
04047    }
04048 }
04049 
04050 static void dahdi_r2_on_call_end(openr2_chan_t *r2chan)
04051 {
04052    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04053    ast_verbose("MFC/R2 call end on channel %d\n", p->channel);
04054    ast_mutex_lock(&p->lock);
04055    p->mfcr2call = 0;
04056    ast_mutex_unlock(&p->lock);
04057 }
04058 
04059 static void dahdi_enable_ec(struct dahdi_pvt *p);
04060 static void dahdi_r2_on_call_accepted(openr2_chan_t *r2chan, openr2_call_mode_t mode)
04061 {
04062    struct dahdi_pvt *p = NULL;
04063    struct ast_channel *c = NULL;
04064    p = openr2_chan_get_client_data(r2chan);
04065    dahdi_enable_ec(p);
04066    p->mfcr2_call_accepted = 1;
04067    /* if it's an incoming call ... */
04068    if (OR2_DIR_BACKWARD == openr2_chan_get_direction(r2chan)) {
04069       ast_verbose("MFC/R2 call has been accepted on backward channel %d\n", openr2_chan_get_number(r2chan));
04070       /* If accept on offer is not set, it means at this point the PBX thread is already
04071          launched (was launched in the 'on call offered' handler) and therefore this callback
04072          is being executed already in the PBX thread rather than the monitor thread, don't launch
04073          any other thread, just disable the openr2 reading and answer the call if needed */
04074       if (!p->mfcr2_accept_on_offer) {
04075          openr2_chan_disable_read(r2chan);
04076          if (p->mfcr2_answer_pending) {
04077             ast_log(LOG_DEBUG, "Answering MFC/R2 call after accepting it on chan %d\n", openr2_chan_get_number(r2chan));
04078             dahdi_r2_answer(p);
04079          }
04080          return;
04081       }
04082       c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, NULL);
04083       if (c) {
04084          /* chan_dahdi will take care of reading from now on in the PBX thread, tell the
04085             library to forget about it */
04086          openr2_chan_disable_read(r2chan);
04087          return;
04088       }
04089       ast_log(LOG_WARNING, "Unable to create PBX channel in DAHDI channel %d\n", p->channel);
04090       /* failed to create the channel, bail out and report it as an out of order line */
04091       dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER);
04092       return;
04093    }
04094    /* this is an outgoing call, no need to launch the PBX thread, most likely we're in one already */
04095    ast_verbose("MFC/R2 call has been accepted on forward channel %d\n", p->channel);
04096    p->subs[SUB_REAL].needringing = 1;
04097    p->dialing = 0;
04098    /* chan_dahdi will take care of reading from now on in the PBX thread, tell the library to forget about it */
04099    openr2_chan_disable_read(r2chan);
04100 }
04101 
04102 static void dahdi_r2_on_call_answered(openr2_chan_t *r2chan)
04103 {
04104    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04105    ast_verbose("MFC/R2 call has been answered on channel %d\n", openr2_chan_get_number(r2chan));
04106    p->subs[SUB_REAL].needanswer = 1;
04107 }
04108 
04109 static void dahdi_r2_on_call_read(openr2_chan_t *r2chan, const unsigned char *buf, int buflen)
04110 {
04111    /*ast_log(LOG_DEBUG, "Read data from dahdi channel %d\n", openr2_chan_get_number(r2chan));*/
04112 }
04113 
04114 static int dahdi_r2_cause_to_ast_cause(openr2_call_disconnect_cause_t cause)
04115 {
04116    switch (cause) {
04117    case OR2_CAUSE_BUSY_NUMBER:
04118       return AST_CAUSE_BUSY;
04119    case OR2_CAUSE_NETWORK_CONGESTION:
04120       return AST_CAUSE_CONGESTION;
04121    case OR2_CAUSE_OUT_OF_ORDER:
04122       return AST_CAUSE_DESTINATION_OUT_OF_ORDER;
04123    case OR2_CAUSE_UNALLOCATED_NUMBER:
04124       return AST_CAUSE_UNREGISTERED;
04125    case OR2_CAUSE_NO_ANSWER:
04126       return AST_CAUSE_NO_ANSWER;
04127    case OR2_CAUSE_NORMAL_CLEARING:
04128       return AST_CAUSE_NORMAL_CLEARING;
04129    case OR2_CAUSE_UNSPECIFIED:
04130    default:
04131       return AST_CAUSE_NOTDEFINED;
04132    }
04133 }
04134 
04135 static void dahdi_r2_on_call_disconnect(openr2_chan_t *r2chan, openr2_call_disconnect_cause_t cause)
04136 {
04137    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04138    ast_verbose("MFC/R2 call disconnected on channel %d\n", openr2_chan_get_number(r2chan));
04139    ast_mutex_lock(&p->lock);
04140    if (!p->owner) {
04141       ast_mutex_unlock(&p->lock);
04142       /* no owner, therefore we can't use dahdi_hangup to disconnect, do it right now */
04143       dahdi_r2_disconnect_call(p, OR2_CAUSE_NORMAL_CLEARING);
04144       return;
04145    }
04146    /* when we have an owner we don't call dahdi_r2_disconnect_call here, that will
04147       be done in dahdi_hangup */
04148    if (p->owner->_state == AST_STATE_UP) {
04149       p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
04150       ast_mutex_unlock(&p->lock);
04151    } else if (openr2_chan_get_direction(r2chan) == OR2_DIR_FORWARD) {
04152       /* being the forward side we must report what happened to the call to whoever requested it */
04153       switch (cause) {
04154       case OR2_CAUSE_BUSY_NUMBER:
04155          p->subs[SUB_REAL].needbusy = 1;
04156          break;
04157       case OR2_CAUSE_NETWORK_CONGESTION:
04158       case OR2_CAUSE_OUT_OF_ORDER:
04159       case OR2_CAUSE_UNALLOCATED_NUMBER:
04160       case OR2_CAUSE_NO_ANSWER:
04161       case OR2_CAUSE_UNSPECIFIED:
04162       case OR2_CAUSE_NORMAL_CLEARING:
04163          p->subs[SUB_REAL].needcongestion = 1;
04164          break;
04165       default:
04166          p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
04167       }
04168       ast_mutex_unlock(&p->lock);
04169    } else {
04170       ast_mutex_unlock(&p->lock);
04171       /* being the backward side and not UP yet, we only need to request hangup */
04172       /* TODO: what about doing this same thing when were AST_STATE_UP? */
04173       ast_queue_hangup_with_cause(p->owner, dahdi_r2_cause_to_ast_cause(cause));
04174    }
04175 }
04176 
04177 static void dahdi_r2_write_log(openr2_log_level_t level, char *logmessage)
04178 {
04179    switch (level) {
04180    case OR2_LOG_NOTICE:
04181       ast_verbose("%s", logmessage);
04182       break;
04183    case OR2_LOG_WARNING:
04184       ast_log(LOG_WARNING, "%s", logmessage);
04185       break;
04186    case OR2_LOG_ERROR:
04187       ast_log(LOG_ERROR, "%s", logmessage);
04188       break;
04189    case OR2_LOG_STACK_TRACE:
04190    case OR2_LOG_MF_TRACE:
04191    case OR2_LOG_CAS_TRACE:
04192    case OR2_LOG_DEBUG:
04193    case OR2_LOG_EX_DEBUG:
04194       ast_log(LOG_DEBUG, "%s", logmessage);
04195       break;
04196    default:
04197       ast_log(LOG_WARNING, "We should handle logging level %d here.\n", level);
04198       ast_log(LOG_DEBUG, "%s", logmessage);
04199       break;
04200    }
04201 }
04202 
04203 static void dahdi_r2_on_line_blocked(openr2_chan_t *r2chan)
04204 {
04205    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04206    ast_mutex_lock(&p->lock);
04207    p->remotelyblocked = 1;
04208    ast_mutex_unlock(&p->lock);
04209    ast_log(LOG_NOTICE, "Far end blocked on chan %d\n", openr2_chan_get_number(r2chan));
04210 }
04211 
04212 static void dahdi_r2_on_line_idle(openr2_chan_t *r2chan)
04213 {
04214    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04215    ast_mutex_lock(&p->lock);
04216    p->remotelyblocked = 0;
04217    ast_mutex_unlock(&p->lock);
04218    ast_log(LOG_NOTICE, "Far end unblocked on chan %d\n", openr2_chan_get_number(r2chan));
04219 }
04220 
04221 static void dahdi_r2_on_context_log(openr2_context_t *r2context, openr2_log_level_t level, const char *fmt, va_list ap)
04222    __attribute__((format (printf, 3, 0)));
04223 static void dahdi_r2_on_context_log(openr2_context_t *r2context, openr2_log_level_t level, const char *fmt, va_list ap)
04224 {
04225 #define CONTEXT_TAG "Context - "
04226    char logmsg[256];
04227    char completemsg[sizeof(logmsg) + sizeof(CONTEXT_TAG) - 1];
04228    vsnprintf(logmsg, sizeof(logmsg), fmt, ap);
04229    snprintf(completemsg, sizeof(completemsg), CONTEXT_TAG "%s", logmsg);
04230    dahdi_r2_write_log(level, completemsg);
04231 #undef CONTEXT_TAG
04232 }
04233 
04234 static void dahdi_r2_on_chan_log(openr2_chan_t *r2chan, openr2_log_level_t level, const char *fmt, va_list ap)
04235    __attribute__((format (printf, 3, 0)));
04236 static void dahdi_r2_on_chan_log(openr2_chan_t *r2chan, openr2_log_level_t level, const char *fmt, va_list ap)
04237 {
04238 #define CHAN_TAG "Chan "
04239    char logmsg[256];
04240    char completemsg[sizeof(logmsg) + sizeof(CHAN_TAG) - 1];
04241    vsnprintf(logmsg, sizeof(logmsg), fmt, ap);
04242    snprintf(completemsg, sizeof(completemsg), CHAN_TAG "%d - %s", openr2_chan_get_number(r2chan), logmsg);
04243    dahdi_r2_write_log(level, completemsg);
04244 }
04245 
04246 static int dahdi_r2_on_dnis_digit_received(openr2_chan_t *r2chan, char digit)
04247 {
04248    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04249    /* if 'immediate' is set, let's stop requesting DNIS */
04250    if (p->immediate) {
04251       return 0;
04252    }
04253    p->exten[p->mfcr2_dnis_index] = digit;
04254    p->rdnis[p->mfcr2_dnis_index] = digit;
04255    p->mfcr2_dnis_index++;
04256    p->exten[p->mfcr2_dnis_index] = 0;
04257    p->rdnis[p->mfcr2_dnis_index] = 0;
04258    /* if the DNIS is a match and cannot match more, stop requesting DNIS */
04259    if ((p->mfcr2_dnis_matched ||
04260        (ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num) && (p->mfcr2_dnis_matched = 1))) &&
04261        !ast_matchmore_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
04262       return 0;
04263    }
04264    /* otherwise keep going */
04265    return 1;
04266 }
04267 
04268 static void dahdi_r2_on_ani_digit_received(openr2_chan_t *r2chan, char digit)
04269 {
04270    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04271    p->cid_num[p->mfcr2_ani_index] = digit;
04272    p->cid_name[p->mfcr2_ani_index] = digit;
04273    p->mfcr2_ani_index++;
04274    p->cid_num[p->mfcr2_ani_index] = 0;
04275    p->cid_name[p->mfcr2_ani_index] = 0;
04276 }
04277 
04278 static void dahdi_r2_on_billing_pulse_received(openr2_chan_t *r2chan)
04279 {
04280    ast_verbose("MFC/R2 billing pulse received on channel %d\n", openr2_chan_get_number(r2chan));
04281 }
04282 
04283 static openr2_event_interface_t dahdi_r2_event_iface = {
04284    .on_call_init = dahdi_r2_on_call_init,
04285    .on_call_offered = dahdi_r2_on_call_offered,
04286    .on_call_accepted = dahdi_r2_on_call_accepted,
04287    .on_call_answered = dahdi_r2_on_call_answered,
04288    .on_call_disconnect = dahdi_r2_on_call_disconnect,
04289    .on_call_end = dahdi_r2_on_call_end,
04290    .on_call_read = dahdi_r2_on_call_read,
04291    .on_hardware_alarm = dahdi_r2_on_hardware_alarm,
04292    .on_os_error = dahdi_r2_on_os_error,
04293    .on_protocol_error = dahdi_r2_on_protocol_error,
04294    .on_line_blocked = dahdi_r2_on_line_blocked,
04295    .on_line_idle = dahdi_r2_on_line_idle,
04296    /* cast seems to be needed to get rid of the annoying warning regarding format attribute  */
04297    .on_context_log = (openr2_handle_context_logging_func)dahdi_r2_on_context_log,
04298    .on_dnis_digit_received = dahdi_r2_on_dnis_digit_received,
04299    .on_ani_digit_received = dahdi_r2_on_ani_digit_received,
04300    /* so far we do nothing with billing pulses */
04301    .on_billing_pulse_received = dahdi_r2_on_billing_pulse_received
04302 };
04303 
04304 static inline int16_t dahdi_r2_alaw_to_linear(uint8_t sample)
04305 {
04306    return AST_ALAW(sample);
04307 }
04308 
04309 static inline uint8_t dahdi_r2_linear_to_alaw(int sample)
04310 {
04311    return AST_LIN2A(sample);
04312 }
04313 
04314 static openr2_transcoder_interface_t dahdi_r2_transcode_iface = {
04315    dahdi_r2_alaw_to_linear,
04316    dahdi_r2_linear_to_alaw
04317 };
04318 
04319 #endif /* HAVE_OPENR2 */
04320 
04321 static void swap_subs(struct dahdi_pvt *p, int a, int b)
04322 {
04323    int tchan;
04324    int tinthreeway;
04325    struct ast_channel *towner;
04326 
04327    ast_debug(1, "Swapping %d and %d\n", a, b);
04328 
04329    tchan = p->subs[a].chan;
04330    towner = p->subs[a].owner;
04331    tinthreeway = p->subs[a].inthreeway;
04332 
04333    p->subs[a].chan = p->subs[b].chan;
04334    p->subs[a].owner = p->subs[b].owner;
04335    p->subs[a].inthreeway = p->subs[b].inthreeway;
04336 
04337    p->subs[b].chan = tchan;
04338    p->subs[b].owner = towner;
04339    p->subs[b].inthreeway = tinthreeway;
04340 
04341    if (p->subs[a].owner)
04342       ast_channel_set_fd(p->subs[a].owner, 0, p->subs[a].dfd);
04343    if (p->subs[b].owner)
04344       ast_channel_set_fd(p->subs[b].owner, 0, p->subs[b].dfd);
04345    wakeup_sub(p, a);
04346    wakeup_sub(p, b);
04347 }
04348 
04349 static int dahdi_open(char *fn)
04350 {
04351    int fd;
04352    int isnum;
04353    int chan = 0;
04354    int bs;
04355    int x;
04356    isnum = 1;
04357    for (x = 0; x < strlen(fn); x++) {
04358       if (!isdigit(fn[x])) {
04359          isnum = 0;
04360          break;
04361       }
04362    }
04363    if (isnum) {
04364       chan = atoi(fn);
04365       if (chan < 1) {
04366          ast_log(LOG_WARNING, "Invalid channel number '%s'\n", fn);
04367          return -1;
04368       }
04369       fn = "/dev/dahdi/channel";
04370    }
04371    fd = open(fn, O_RDWR | O_NONBLOCK);
04372    if (fd < 0) {
04373       ast_log(LOG_WARNING, "Unable to open '%s': %s\n", fn, strerror(errno));
04374       return -1;
04375    }
04376    if (chan) {
04377       if (ioctl(fd, DAHDI_SPECIFY, &chan)) {
04378          x = errno;
04379          close(fd);
04380          errno = x;
04381          ast_log(LOG_WARNING, "Unable to specify channel %d: %s\n", chan, strerror(errno));
04382          return -1;
04383       }
04384    }
04385    bs = READ_SIZE;
04386    if (ioctl(fd, DAHDI_SET_BLOCKSIZE, &bs) == -1) {
04387       ast_log(LOG_WARNING, "Unable to set blocksize '%d': %s\n", bs,  strerror(errno));
04388       x = errno;
04389       close(fd);
04390       errno = x;
04391       return -1;
04392    }
04393    return fd;
04394 }
04395 
04396 static void dahdi_close(int fd)
04397 {
04398    if (fd > 0)
04399       close(fd);
04400 }
04401 
04402 static void dahdi_close_sub(struct dahdi_pvt *chan_pvt, int sub_num)
04403 {
04404    dahdi_close(chan_pvt->subs[sub_num].dfd);
04405    chan_pvt->subs[sub_num].dfd = -1;
04406 }
04407 
04408 #if defined(HAVE_PRI)
04409 static void dahdi_close_pri_fd(struct dahdi_pri *pri, int fd_num)
04410 {
04411    dahdi_close(pri->pri.fds[fd_num]);
04412    pri->pri.fds[fd_num] = -1;
04413 }
04414 #endif   /* defined(HAVE_PRI) */
04415 
04416 #if defined(HAVE_SS7)
04417 static void dahdi_close_ss7_fd(struct dahdi_ss7 *ss7, int fd_num)
04418 {
04419    dahdi_close(ss7->ss7.fds[fd_num]);
04420    ss7->ss7.fds[fd_num] = -1;
04421 }
04422 #endif   /* defined(HAVE_SS7) */
04423 
04424 static int dahdi_setlinear(int dfd, int linear)
04425 {
04426    return ioctl(dfd, DAHDI_SETLINEAR, &linear);
04427 }
04428 
04429 
04430 static int alloc_sub(struct dahdi_pvt *p, int x)
04431 {
04432    struct dahdi_bufferinfo bi;
04433    int res;
04434    if (p->subs[x].dfd >= 0) {
04435       ast_log(LOG_WARNING, "%s subchannel of %d already in use\n", subnames[x], p->channel);
04436       return -1;
04437    }
04438 
04439    p->subs[x].dfd = dahdi_open("/dev/dahdi/pseudo");
04440    if (p->subs[x].dfd <= -1) {
04441       ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno));
04442       return -1;
04443    }
04444 
04445    res = ioctl(p->subs[x].dfd, DAHDI_GET_BUFINFO, &bi);
04446    if (!res) {
04447       bi.txbufpolicy = p->buf_policy;
04448       bi.rxbufpolicy = p->buf_policy;
04449       bi.numbufs = p->buf_no;
04450       res = ioctl(p->subs[x].dfd, DAHDI_SET_BUFINFO, &bi);
04451       if (res < 0) {
04452          ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", x, strerror(errno));
04453       }
04454    } else
04455       ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", x, strerror(errno));
04456 
04457    if (ioctl(p->subs[x].dfd, DAHDI_CHANNO, &p->subs[x].chan) == 1) {
04458       ast_log(LOG_WARNING, "Unable to get channel number for pseudo channel on FD %d: %s\n", p->subs[x].dfd, strerror(errno));
04459       dahdi_close_sub(p, x);
04460       p->subs[x].dfd = -1;
04461       return -1;
04462    }
04463    ast_debug(1, "Allocated %s subchannel on FD %d channel %d\n", subnames[x], p->subs[x].dfd, p->subs[x].chan);
04464    return 0;
04465 }
04466 
04467 static int unalloc_sub(struct dahdi_pvt *p, int x)
04468 {
04469    if (!x) {
04470       ast_log(LOG_WARNING, "Trying to unalloc the real channel %d?!?\n", p->channel);
04471       return -1;
04472    }
04473    ast_debug(1, "Released sub %d of channel %d\n", x, p->channel);
04474    dahdi_close_sub(p, x);
04475    p->subs[x].linear = 0;
04476    p->subs[x].chan = 0;
04477    p->subs[x].owner = NULL;
04478    p->subs[x].inthreeway = 0;
04479    p->polarity = POLARITY_IDLE;
04480    memset(&p->subs[x].curconf, 0, sizeof(p->subs[x].curconf));
04481    return 0;
04482 }
04483 
04484 static int digit_to_dtmfindex(char digit)
04485 {
04486    if (isdigit(digit))
04487       return DAHDI_TONE_DTMF_BASE + (digit - '0');
04488    else if (digit >= 'A' && digit <= 'D')
04489       return DAHDI_TONE_DTMF_A + (digit - 'A');
04490    else if (digit >= 'a' && digit <= 'd')
04491       return DAHDI_TONE_DTMF_A + (digit - 'a');
04492    else if (digit == '*')
04493       return DAHDI_TONE_DTMF_s;
04494    else if (digit == '#')
04495       return DAHDI_TONE_DTMF_p;
04496    else
04497       return -1;
04498 }
04499 
04500 static int dahdi_digit_begin(struct ast_channel *chan, char digit)
04501 {
04502    struct dahdi_pvt *pvt;
04503    int idx;
04504    int dtmf = -1;
04505    int res;
04506 
04507    pvt = chan->tech_pvt;
04508 
04509    ast_mutex_lock(&pvt->lock);
04510 
04511    idx = dahdi_get_index(chan, pvt, 0);
04512 
04513    if ((idx != SUB_REAL) || !pvt->owner)
04514       goto out;
04515 
04516 #ifdef HAVE_PRI
04517    switch (pvt->sig) {
04518    case SIG_PRI_LIB_HANDLE_CASES:
04519       res = sig_pri_digit_begin(pvt->sig_pvt, chan, digit);
04520       if (!res)
04521          goto out;
04522       break;
04523    default:
04524       break;
04525    }
04526 #endif
04527    if ((dtmf = digit_to_dtmfindex(digit)) == -1)
04528       goto out;
04529 
04530    if (pvt->pulse || ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &dtmf)) {
04531       struct dahdi_dialoperation zo = {
04532          .op = DAHDI_DIAL_OP_APPEND,
04533       };
04534 
04535       zo.dialstr[0] = 'T';
04536       zo.dialstr[1] = digit;
04537       zo.dialstr[2] = '\0';
04538       if ((res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo)))
04539          ast_log(LOG_WARNING, "Channel %s couldn't dial digit %c: %s\n",
04540             chan->name, digit, strerror(errno));
04541       else
04542          pvt->dialing = 1;
04543    } else {
04544       ast_debug(1, "Channel %s started VLDTMF digit '%c'\n",
04545          chan->name, digit);
04546       pvt->dialing = 1;
04547       pvt->begindigit = digit;
04548    }
04549 
04550 out:
04551    ast_mutex_unlock(&pvt->lock);
04552 
04553    return 0;
04554 }
04555 
04556 static int dahdi_digit_end(struct ast_channel *chan, char digit, unsigned int duration)
04557 {
04558    struct dahdi_pvt *pvt;
04559    int res = 0;
04560    int idx;
04561    int x;
04562 
04563    pvt = chan->tech_pvt;
04564 
04565    ast_mutex_lock(&pvt->lock);
04566 
04567    idx = dahdi_get_index(chan, pvt, 0);
04568 
04569    if ((idx != SUB_REAL) || !pvt->owner || pvt->pulse)
04570       goto out;
04571 
04572 #ifdef HAVE_PRI
04573    /* This means that the digit was already sent via PRI signalling */
04574    if (dahdi_sig_pri_lib_handles(pvt->sig) && !pvt->begindigit) {
04575       goto out;
04576    }
04577 #endif
04578 
04579    if (pvt->begindigit) {
04580       x = -1;
04581       ast_debug(1, "Channel %s ending VLDTMF digit '%c'\n",
04582          chan->name, digit);
04583       res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &x);
04584       pvt->dialing = 0;
04585       pvt->begindigit = 0;
04586    }
04587 
04588 out:
04589    ast_mutex_unlock(&pvt->lock);
04590 
04591    return res;
04592 }
04593 
04594 static const char * const events[] = {
04595    "No event",
04596    "On hook",
04597    "Ring/Answered",
04598    "Wink/Flash",
04599    "Alarm",
04600    "No more alarm",
04601    "HDLC Abort",
04602    "HDLC Overrun",
04603    "HDLC Bad FCS",
04604    "Dial Complete",
04605    "Ringer On",
04606    "Ringer Off",
04607    "Hook Transition Complete",
04608    "Bits Changed",
04609    "Pulse Start",
04610    "Timer Expired",
04611    "Timer Ping",
04612    "Polarity Reversal",
04613    "Ring Begin",
04614 };
04615 
04616 static struct {
04617    int alarm;
04618    char *name;
04619 } alarms[] = {
04620    { DAHDI_ALARM_RED, "Red Alarm" },
04621    { DAHDI_ALARM_YELLOW, "Yellow Alarm" },
04622    { DAHDI_ALARM_BLUE, "Blue Alarm" },
04623    { DAHDI_ALARM_RECOVER, "Recovering" },
04624    { DAHDI_ALARM_LOOPBACK, "Loopback" },
04625    { DAHDI_ALARM_NOTOPEN, "Not Open" },
04626    { DAHDI_ALARM_NONE, "None" },
04627 };
04628 
04629 static char *alarm2str(int alm)
04630 {
04631    int x;
04632    for (x = 0; x < ARRAY_LEN(alarms); x++) {
04633       if (alarms[x].alarm & alm)
04634          return alarms[x].name;
04635    }
04636    return alm ? "Unknown Alarm" : "No Alarm";
04637 }
04638 
04639 static const char *event2str(int event)
04640 {
04641    static char buf[256];
04642    if ((event < (ARRAY_LEN(events))) && (event > -1))
04643       return events[event];
04644    sprintf(buf, "Event %d", event); /* safe */
04645    return buf;
04646 }
04647 
04648 static char *dahdi_sig2str(int sig)
04649 {
04650    static char buf[256];
04651    switch (sig) {
04652    case SIG_EM:
04653       return "E & M Immediate";
04654    case SIG_EMWINK:
04655       return "E & M Wink";
04656    case SIG_EM_E1:
04657       return "E & M E1";
04658    case SIG_FEATD:
04659       return "Feature Group D (DTMF)";
04660    case SIG_FEATDMF:
04661       return "Feature Group D (MF)";
04662    case SIG_FEATDMF_TA:
04663       return "Feature Groud D (MF) Tandem Access";
04664    case SIG_FEATB:
04665       return "Feature Group B (MF)";
04666    case SIG_E911:
04667       return "E911 (MF)";
04668    case SIG_FGC_CAMA:
04669       return "FGC/CAMA (Dialpulse)";
04670    case SIG_FGC_CAMAMF:
04671       return "FGC/CAMA (MF)";
04672    case SIG_FXSLS:
04673       return "FXS Loopstart";
04674    case SIG_FXSGS:
04675       return "FXS Groundstart";
04676    case SIG_FXSKS:
04677       return "FXS Kewlstart";
04678    case SIG_FXOLS:
04679       return "FXO Loopstart";
04680    case SIG_FXOGS:
04681       return "FXO Groundstart";
04682    case SIG_FXOKS:
04683       return "FXO Kewlstart";
04684    case SIG_PRI:
04685       return "ISDN PRI";
04686    case SIG_BRI:
04687       return "ISDN BRI Point to Point";
04688    case SIG_BRI_PTMP:
04689       return "ISDN BRI Point to MultiPoint";
04690    case SIG_SS7:
04691       return "SS7";
04692    case SIG_MFCR2:
04693       return "MFC/R2";
04694    case SIG_SF:
04695       return "SF (Tone) Immediate";
04696    case SIG_SFWINK:
04697       return "SF (Tone) Wink";
04698    case SIG_SF_FEATD:
04699       return "SF (Tone) with Feature Group D (DTMF)";
04700    case SIG_SF_FEATDMF:
04701       return "SF (Tone) with Feature Group D (MF)";
04702    case SIG_SF_FEATB:
04703       return "SF (Tone) with Feature Group B (MF)";
04704    case 0:
04705       return "Pseudo";
04706    default:
04707       snprintf(buf, sizeof(buf), "Unknown signalling %d", sig);
04708       return buf;
04709    }
04710 }
04711 
04712 #define sig2str dahdi_sig2str
04713 
04714 static int conf_add(struct dahdi_pvt *p, struct dahdi_subchannel *c, int idx, int slavechannel)
04715 {
04716    /* If the conference already exists, and we're already in it
04717       don't bother doing anything */
04718    struct dahdi_confinfo zi;
04719 
04720    memset(&zi, 0, sizeof(zi));
04721    zi.chan = 0;
04722 
04723    if (slavechannel > 0) {
04724       /* If we have only one slave, do a digital mon */
04725       zi.confmode = DAHDI_CONF_DIGITALMON;
04726       zi.confno = slavechannel;
04727    } else {
04728       if (!idx) {
04729          /* Real-side and pseudo-side both participate in conference */
04730          zi.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER |
04731             DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER;
04732       } else
04733          zi.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER;
04734       zi.confno = p->confno;
04735    }
04736    if ((zi.confno == c->curconf.confno) && (zi.confmode == c->curconf.confmode))
04737       return 0;
04738    if (c->dfd < 0)
04739       return 0;
04740    if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
04741       ast_log(LOG_WARNING, "Failed to add %d to conference %d/%d: %s\n", c->dfd, zi.confmode, zi.confno, strerror(errno));
04742       return -1;
04743    }
04744    if (slavechannel < 1) {
04745       p->confno = zi.confno;
04746    }
04747    c->curconf = zi;
04748    ast_debug(1, "Added %d to conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
04749    return 0;
04750 }
04751 
04752 static int isourconf(struct dahdi_pvt *p, struct dahdi_subchannel *c)
04753 {
04754    /* If they're listening to our channel, they're ours */
04755    if ((p->channel == c->curconf.confno) && (c->curconf.confmode == DAHDI_CONF_DIGITALMON))
04756       return 1;
04757    /* If they're a talker on our (allocated) conference, they're ours */
04758    if ((p->confno > 0) && (p->confno == c->curconf.confno) && (c->curconf.confmode & DAHDI_CONF_TALKER))
04759       return 1;
04760    return 0;
04761 }
04762 
04763 static int conf_del(struct dahdi_pvt *p, struct dahdi_subchannel *c, int idx)
04764 {
04765    struct dahdi_confinfo zi;
04766    if (/* Can't delete if there's no dfd */
04767       (c->dfd < 0) ||
04768       /* Don't delete from the conference if it's not our conference */
04769       !isourconf(p, c)
04770       /* Don't delete if we don't think it's conferenced at all (implied) */
04771       ) return 0;
04772    memset(&zi, 0, sizeof(zi));
04773    if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
04774       ast_log(LOG_WARNING, "Failed to drop %d from conference %d/%d: %s\n", c->dfd, c->curconf.confmode, c->curconf.confno, strerror(errno));
04775       return -1;
04776    }
04777    ast_debug(1, "Removed %d from conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
04778    memcpy(&c->curconf, &zi, sizeof(c->curconf));
04779    return 0;
04780 }
04781 
04782 static int isslavenative(struct dahdi_pvt *p, struct dahdi_pvt **out)
04783 {
04784    int x;
04785    int useslavenative;
04786    struct dahdi_pvt *slave = NULL;
04787    /* Start out optimistic */
04788    useslavenative = 1;
04789    /* Update conference state in a stateless fashion */
04790    for (x = 0; x < 3; x++) {
04791       /* Any three-way calling makes slave native mode *definitely* out
04792          of the question */
04793       if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway)
04794          useslavenative = 0;
04795    }
04796    /* If we don't have any 3-way calls, check to see if we have
04797       precisely one slave */
04798    if (useslavenative) {
04799       for (x = 0; x < MAX_SLAVES; x++) {
04800          if (p->slaves[x]) {
04801             if (slave) {
04802                /* Whoops already have a slave!  No
04803                   slave native and stop right away */
04804                slave = NULL;
04805                useslavenative = 0;
04806                break;
04807             } else {
04808                /* We have one slave so far */
04809                slave = p->slaves[x];
04810             }
04811          }
04812       }
04813    }
04814    /* If no slave, slave native definitely out */
04815    if (!slave)
04816       useslavenative = 0;
04817    else if (slave->law != p->law) {
04818       useslavenative = 0;
04819       slave = NULL;
04820    }
04821    if (out)
04822       *out = slave;
04823    return useslavenative;
04824 }
04825 
04826 static int reset_conf(struct dahdi_pvt *p)
04827 {
04828    p->confno = -1;
04829    memset(&p->subs[SUB_REAL].curconf, 0, sizeof(p->subs[SUB_REAL].curconf));
04830    if (p->subs[SUB_REAL].dfd > -1) {
04831       struct dahdi_confinfo zi;
04832 
04833       memset(&zi, 0, sizeof(zi));
04834       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &zi))
04835          ast_log(LOG_WARNING, "Failed to reset conferencing on channel %d: %s\n", p->channel, strerror(errno));
04836    }
04837    return 0;
04838 }
04839 
04840 static int update_conf(struct dahdi_pvt *p)
04841 {
04842    int needconf = 0;
04843    int x;
04844    int useslavenative;
04845    struct dahdi_pvt *slave = NULL;
04846 
04847    useslavenative = isslavenative(p, &slave);
04848    /* Start with the obvious, general stuff */
04849    for (x = 0; x < 3; x++) {
04850       /* Look for three way calls */
04851       if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) {
04852          conf_add(p, &p->subs[x], x, 0);
04853          needconf++;
04854       } else {
04855          conf_del(p, &p->subs[x], x);
04856       }
04857    }
04858    /* If we have a slave, add him to our conference now. or DAX
04859       if this is slave native */
04860    for (x = 0; x < MAX_SLAVES; x++) {
04861       if (p->slaves[x]) {
04862          if (useslavenative)
04863             conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
04864          else {
04865             conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
04866             needconf++;
04867          }
04868       }
04869    }
04870    /* If we're supposed to be in there, do so now */
04871    if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
04872       if (useslavenative)
04873          conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
04874       else {
04875          conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
04876          needconf++;
04877       }
04878    }
04879    /* If we have a master, add ourselves to his conference */
04880    if (p->master) {
04881       if (isslavenative(p->master, NULL)) {
04882          conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
04883       } else {
04884          conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
04885       }
04886    }
04887    if (!needconf) {
04888       /* Nobody is left (or should be left) in our conference.
04889          Kill it. */
04890       p->confno = -1;
04891    }
04892    ast_debug(1, "Updated conferencing on %d, with %d conference users\n", p->channel, needconf);
04893    return 0;
04894 }
04895 
04896 static void dahdi_enable_ec(struct dahdi_pvt *p)
04897 {
04898    int res;
04899    if (!p)
04900       return;
04901    if (p->echocanon) {
04902       ast_debug(1, "Echo cancellation already on\n");
04903       return;
04904    }
04905    if (p->digital) {
04906       ast_debug(1, "Echo cancellation isn't required on digital connection\n");
04907       return;
04908    }
04909    if (p->echocancel.head.tap_length) {
04910 #if defined(HAVE_PRI) || defined(HAVE_SS7)
04911       switch (p->sig) {
04912 #if defined(HAVE_PRI)
04913       case SIG_PRI_LIB_HANDLE_CASES:
04914          if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
04915             /*
04916              * PRI nobch pseudo channel.  Does not need ec anyway.
04917              * Does not handle ioctl(DAHDI_AUDIOMODE)
04918              */
04919             return;
04920          }
04921          /* Fall through */
04922 #endif   /* defined(HAVE_PRI) */
04923 #if defined(HAVE_SS7)
04924       case SIG_SS7:
04925 #endif   /* defined(HAVE_SS7) */
04926          {
04927             int x = 1;
04928 
04929             res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x);
04930             if (res)
04931                ast_log(LOG_WARNING,
04932                   "Unable to enable audio mode on channel %d (%s)\n",
04933                   p->channel, strerror(errno));
04934          }
04935          break;
04936       default:
04937          break;
04938       }
04939 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
04940       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &p->echocancel);
04941       if (res) {
04942          ast_log(LOG_WARNING, "Unable to enable echo cancellation on channel %d (%s)\n", p->channel, strerror(errno));
04943       } else {
04944          p->echocanon = 1;
04945          ast_debug(1, "Enabled echo cancellation on channel %d\n", p->channel);
04946       }
04947    } else
04948       ast_debug(1, "No echo cancellation requested\n");
04949 }
04950 
04951 static void dahdi_train_ec(struct dahdi_pvt *p)
04952 {
04953    int x;
04954    int res;
04955 
04956    if (p && p->echocanon && p->echotraining) {
04957       x = p->echotraining;
04958       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOTRAIN, &x);
04959       if (res)
04960          ast_log(LOG_WARNING, "Unable to request echo training on channel %d: %s\n", p->channel, strerror(errno));
04961       else
04962          ast_debug(1, "Engaged echo training on channel %d\n", p->channel);
04963    } else {
04964       ast_debug(1, "No echo training requested\n");
04965    }
04966 }
04967 
04968 static void dahdi_disable_ec(struct dahdi_pvt *p)
04969 {
04970    int res;
04971 
04972    if (p->echocanon) {
04973       struct dahdi_echocanparams ecp = { .tap_length = 0 };
04974 
04975       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &ecp);
04976 
04977       if (res)
04978          ast_log(LOG_WARNING, "Unable to disable echo cancellation on channel %d: %s\n", p->channel, strerror(errno));
04979       else
04980          ast_debug(1, "Disabled echo cancellation on channel %d\n", p->channel);
04981    }
04982 
04983    p->echocanon = 0;
04984 }
04985 
04986 /* perform a dynamic range compression transform on the given sample */
04987 static int drc_sample(int sample, float drc)
04988 {
04989    float neg;
04990    float shallow, steep;
04991    float max = SHRT_MAX;
04992    
04993    neg = (sample < 0 ? -1 : 1);
04994    steep = drc*sample;
04995    shallow = neg*(max-max/drc)+(float)sample/drc;
04996    if (abs(steep) < abs(shallow)) {
04997       sample = steep;
04998    }
04999    else {
05000       sample = shallow;
05001    }
05002 
05003    return sample;
05004 }
05005 
05006 
05007 static void fill_txgain(struct dahdi_gains *g, float gain, float drc, int law)
05008 {
05009    int j;
05010    int k;
05011 
05012    float linear_gain = pow(10.0, gain / 20.0);
05013 
05014    switch (law) {
05015    case DAHDI_LAW_ALAW:
05016       for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
05017          if (gain || drc) {
05018             k = AST_ALAW(j);
05019             if (drc) {
05020                k = drc_sample(k, drc);
05021             }
05022             k = (float)k * linear_gain;
05023             if (k > 32767) {
05024                k = 32767;
05025             } else if (k < -32768) {
05026                k = -32768;
05027             }
05028             g->txgain[j] = AST_LIN2A(k);
05029          } else {
05030             g->txgain[j] = j;
05031          }
05032       }
05033       break;
05034    case DAHDI_LAW_MULAW:
05035       for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
05036          if (gain || drc) {
05037             k = AST_MULAW(j);
05038             if (drc) {
05039                k = drc_sample(k, drc);
05040             }
05041             k = (float)k * linear_gain;
05042             if (k > 32767) {
05043                k = 32767;
05044             } else if (k < -32768) {
05045                k = -32768;
05046             }
05047             g->txgain[j] = AST_LIN2MU(k);
05048 
05049          } else {
05050             g->txgain[j] = j;
05051          }
05052       }
05053       break;
05054    }
05055 }
05056 
05057 static void fill_rxgain(struct dahdi_gains *g, float gain, float drc, int law)
05058 {
05059    int j;
05060    int k;
05061    float linear_gain = pow(10.0, gain / 20.0);
05062 
05063    switch (law) {
05064    case DAHDI_LAW_ALAW:
05065       for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
05066          if (gain || drc) {
05067             k = AST_ALAW(j);
05068             if (drc) {
05069                k = drc_sample(k, drc);
05070             }
05071             k = (float)k * linear_gain;
05072             if (k > 32767) {
05073                k = 32767;
05074             } else if (k < -32768) {
05075                k = -32768;
05076             }
05077             g->rxgain[j] = AST_LIN2A(k);
05078          } else {
05079             g->rxgain[j] = j;
05080          }
05081       }
05082       break;
05083    case DAHDI_LAW_MULAW:
05084       for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
05085          if (gain || drc) {
05086             k = AST_MULAW(j);
05087             if (drc) {
05088                k = drc_sample(k, drc);
05089             }
05090             k = (float)k * linear_gain;
05091             if (k > 32767) {
05092                k = 32767;
05093             } else if (k < -32768) {
05094                k = -32768;
05095             }
05096             g->rxgain[j] = AST_LIN2MU(k);
05097          } else {
05098             g->rxgain[j] = j;
05099          }
05100       }
05101       break;
05102    }
05103 }
05104 
05105 static int set_actual_txgain(int fd, float gain, float drc, int law)
05106 {
05107    struct dahdi_gains g;
05108    int res;
05109 
05110    memset(&g, 0, sizeof(g));
05111    res = ioctl(fd, DAHDI_GETGAINS, &g);
05112    if (res) {
05113       ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
05114       return res;
05115    }
05116 
05117    fill_txgain(&g, gain, drc, law);
05118 
05119    return ioctl(fd, DAHDI_SETGAINS, &g);
05120 }
05121 
05122 static int set_actual_rxgain(int fd, float gain, float drc, int law)
05123 {
05124    struct dahdi_gains g;
05125    int res;
05126 
05127    memset(&g, 0, sizeof(g));
05128    res = ioctl(fd, DAHDI_GETGAINS, &g);
05129    if (res) {
05130       ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
05131       return res;
05132    }
05133 
05134    fill_rxgain(&g, gain, drc, law);
05135 
05136    return ioctl(fd, DAHDI_SETGAINS, &g);
05137 }
05138 
05139 static int set_actual_gain(int fd, float rxgain, float txgain, float rxdrc, float txdrc, int law)
05140 {
05141    return set_actual_txgain(fd, txgain, txdrc, law) | set_actual_rxgain(fd, rxgain, rxdrc, law);
05142 }
05143 
05144 static int bump_gains(struct dahdi_pvt *p)
05145 {
05146    int res;
05147 
05148    /* Bump receive gain by value stored in cid_rxgain */
05149    res = set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain + p->cid_rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
05150    if (res) {
05151       ast_log(LOG_WARNING, "Unable to bump gain: %s\n", strerror(errno));
05152       return -1;
05153    }
05154 
05155    return 0;
05156 }
05157 
05158 static int restore_gains(struct dahdi_pvt *p)
05159 {
05160    int res;
05161 
05162    res = set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
05163    if (res) {
05164       ast_log(LOG_WARNING, "Unable to restore gains: %s\n", strerror(errno));
05165       return -1;
05166    }
05167 
05168    return 0;
05169 }
05170 
05171 static inline int dahdi_set_hook(int fd, int hs)
05172 {
05173    int x, res;
05174 
05175    x = hs;
05176    res = ioctl(fd, DAHDI_HOOK, &x);
05177 
05178    if (res < 0) {
05179       if (errno == EINPROGRESS)
05180          return 0;
05181       ast_log(LOG_WARNING, "DAHDI hook failed returned %d (trying %d): %s\n", res, hs, strerror(errno));
05182       /* will expectedly fail if phone is off hook during operation, such as during a restart */
05183    }
05184 
05185    return res;
05186 }
05187 
05188 static inline int dahdi_confmute(struct dahdi_pvt *p, int muted)
05189 {
05190    int x, res;
05191 
05192    x = muted;
05193 #if defined(HAVE_PRI) || defined(HAVE_SS7)
05194    switch (p->sig) {
05195 #if defined(HAVE_PRI)
05196    case SIG_PRI_LIB_HANDLE_CASES:
05197       if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
05198          /* PRI nobch pseudo channel.  Does not handle ioctl(DAHDI_AUDIOMODE) */
05199          break;
05200       }
05201       /* Fall through */
05202 #endif   /* defined(HAVE_PRI) */
05203 #if defined(HAVE_SS7)
05204    case SIG_SS7:
05205 #endif   /* defined(HAVE_SS7) */
05206       {
05207          int y = 1;
05208 
05209          res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &y);
05210          if (res)
05211             ast_log(LOG_WARNING, "Unable to set audio mode on %d: %s\n",
05212                p->channel, strerror(errno));
05213       }
05214       break;
05215    default:
05216       break;
05217    }
05218 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
05219    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_CONFMUTE, &x);
05220    if (res < 0)
05221       ast_log(LOG_WARNING, "DAHDI confmute(%d) failed on channel %d: %s\n", muted, p->channel, strerror(errno));
05222    return res;
05223 }
05224 
05225 static int save_conference(struct dahdi_pvt *p)
05226 {
05227    struct dahdi_confinfo c;
05228    int res;
05229    if (p->saveconf.confmode) {
05230       ast_log(LOG_WARNING, "Can't save conference -- already in use\n");
05231       return -1;
05232    }
05233    p->saveconf.chan = 0;
05234    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &p->saveconf);
05235    if (res) {
05236       ast_log(LOG_WARNING, "Unable to get conference info: %s\n", strerror(errno));
05237       p->saveconf.confmode = 0;
05238       return -1;
05239    }
05240    memset(&c, 0, sizeof(c));
05241    c.confmode = DAHDI_CONF_NORMAL;
05242    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &c);
05243    if (res) {
05244       ast_log(LOG_WARNING, "Unable to set conference info: %s\n", strerror(errno));
05245       return -1;
05246    }
05247    ast_debug(1, "Disabled conferencing\n");
05248    return 0;
05249 }
05250 
05251 static int restore_conference(struct dahdi_pvt *p)
05252 {
05253    int res;
05254    if (p->saveconf.confmode) {
05255       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &p->saveconf);
05256       p->saveconf.confmode = 0;
05257       if (res) {
05258          ast_log(LOG_WARNING, "Unable to restore conference info: %s\n", strerror(errno));
05259          return -1;
05260       }
05261       ast_debug(1, "Restored conferencing\n");
05262    }
05263    return 0;
05264 }
05265 
05266 static int send_cwcidspill(struct dahdi_pvt *p)
05267 {
05268    p->callwaitcas = 0;
05269    p->cidcwexpire = 0;
05270    p->cid_suppress_expire = 0;
05271    if (!(p->cidspill = ast_malloc(MAX_CALLERID_SIZE)))
05272       return -1;
05273    p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, p->callwait_name, p->callwait_num, AST_LAW(p));
05274    /* Make sure we account for the end */
05275    p->cidlen += READ_SIZE * 4;
05276    p->cidpos = 0;
05277    send_callerid(p);
05278    ast_verb(3, "CPE supports Call Waiting Caller*ID.  Sending '%s/%s'\n", p->callwait_name, p->callwait_num);
05279    return 0;
05280 }
05281 
05282 static int has_voicemail(struct dahdi_pvt *p)
05283 {
05284    int new_msgs;
05285    struct ast_event *event;
05286    char *mailbox, *context;
05287 
05288    mailbox = context = ast_strdupa(p->mailbox);
05289    strsep(&context, "@");
05290    if (ast_strlen_zero(context))
05291       context = "default";
05292 
05293    event = ast_event_get_cached(AST_EVENT_MWI,
05294       AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
05295       AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
05296       AST_EVENT_IE_END);
05297 
05298    if (event) {
05299       new_msgs = ast_event_get_ie_uint(event, AST_EVENT_IE_NEWMSGS);
05300       ast_event_destroy(event);
05301    } else
05302       new_msgs = ast_app_has_voicemail(p->mailbox, NULL);
05303 
05304    return new_msgs;
05305 }
05306 
05307 
05308 
05309 static int send_callerid(struct dahdi_pvt *p)
05310 {
05311    /* Assumes spill in p->cidspill, p->cidlen in length and we're p->cidpos into it */
05312    int res;
05313    /* Take out of linear mode if necessary */
05314    if (p->subs[SUB_REAL].linear) {
05315       p->subs[SUB_REAL].linear = 0;
05316       dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
05317    }
05318    while (p->cidpos < p->cidlen) {
05319       res = write(p->subs[SUB_REAL].dfd, p->cidspill + p->cidpos, p->cidlen - p->cidpos);
05320       ast_debug(4, "writing callerid at pos %d of %d, res = %d\n", p->cidpos, p->cidlen, res);
05321       if (res < 0) {
05322          if (errno == EAGAIN)
05323             return 0;
05324          else {
05325             ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
05326             return -1;
05327          }
05328       }
05329       if (!res)
05330          return 0;
05331       p->cidpos += res;
05332    }
05333    p->cid_suppress_expire = CALLWAITING_SUPPRESS_SAMPLES;
05334    ast_free(p->cidspill);
05335    p->cidspill = NULL;
05336    if (p->callwaitcas) {
05337       /* Wait for CID/CW to expire */
05338       p->cidcwexpire = CIDCW_EXPIRE_SAMPLES;
05339       p->cid_suppress_expire = p->cidcwexpire;
05340    } else
05341       restore_conference(p);
05342    return 0;
05343 }
05344 
05345 static int dahdi_callwait(struct ast_channel *ast)
05346 {
05347    struct dahdi_pvt *p = ast->tech_pvt;
05348    p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
05349    if (p->cidspill) {
05350       ast_log(LOG_WARNING, "Spill already exists?!?\n");
05351       ast_free(p->cidspill);
05352    }
05353 
05354    /*
05355     * SAS: Subscriber Alert Signal, 440Hz for 300ms
05356     * CAS: CPE Alert Signal, 2130Hz * 2750Hz sine waves
05357     */
05358    if (!(p->cidspill = ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE * 4)))
05359       return -1;
05360    save_conference(p);
05361    /* Silence */
05362    memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
05363    if (!p->callwaitrings && p->callwaitingcallerid) {
05364       ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
05365       p->callwaitcas = 1;
05366       p->cidlen = 2400 + 680 + READ_SIZE * 4;
05367    } else {
05368       ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
05369       p->callwaitcas = 0;
05370       p->cidlen = 2400 + READ_SIZE * 4;
05371    }
05372    p->cidpos = 0;
05373    send_callerid(p);
05374 
05375    return 0;
05376 }
05377 
05378 static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout)
05379 {
05380    struct dahdi_pvt *p = ast->tech_pvt;
05381    int x, res, mysig;
05382    char dest[256]; /* must be same length as p->dialdest */
05383 
05384    ast_mutex_lock(&p->lock);
05385    ast_copy_string(dest, rdest, sizeof(dest));
05386    ast_copy_string(p->dialdest, rdest, sizeof(p->dialdest));
05387    if ((ast->_state == AST_STATE_BUSY)) {
05388       p->subs[SUB_REAL].needbusy = 1;
05389       ast_mutex_unlock(&p->lock);
05390       return 0;
05391    }
05392    if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
05393       ast_log(LOG_WARNING, "dahdi_call called on %s, neither down nor reserved\n", ast->name);
05394       ast_mutex_unlock(&p->lock);
05395       return -1;
05396    }
05397    p->waitingfordt.tv_sec = 0;
05398    p->dialednone = 0;
05399    if ((p->radio || (p->oprmode < 0)))  /* if a radio channel, up immediately */
05400    {
05401       /* Special pseudo -- automatically up */
05402       ast_setstate(ast, AST_STATE_UP);
05403       ast_mutex_unlock(&p->lock);
05404       return 0;
05405    }
05406    x = DAHDI_FLUSH_READ | DAHDI_FLUSH_WRITE;
05407    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
05408    if (res)
05409       ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", p->channel, strerror(errno));
05410    p->outgoing = 1;
05411 
05412    if (IS_DIGITAL(ast->transfercapability)){
05413       set_actual_gain(p->subs[SUB_REAL].dfd, 0, 0, p->rxdrc, p->txdrc, p->law);
05414    } else {
05415       set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
05416    }  
05417 
05418 #ifdef HAVE_PRI
05419    if (dahdi_sig_pri_lib_handles(p->sig)) {
05420       res = sig_pri_call(p->sig_pvt, ast, rdest, timeout,
05421          (p->law == DAHDI_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW);
05422       ast_mutex_unlock(&p->lock);
05423       return res;
05424    }
05425 #endif
05426 
05427 #if defined(HAVE_SS7)
05428    if (p->sig == SIG_SS7) {
05429       res = sig_ss7_call(p->sig_pvt, ast, rdest);
05430       ast_mutex_unlock(&p->lock);
05431       return res;
05432    }
05433 #endif   /* defined(HAVE_SS7) */
05434 
05435    /* If this is analog signalling we can exit here */
05436    if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
05437       p->callwaitrings = 0;
05438       res = analog_call(p->sig_pvt, ast, rdest, timeout);
05439       ast_mutex_unlock(&p->lock);
05440       return res;
05441    }
05442 
05443    mysig = p->outsigmod > -1 ? p->outsigmod : p->sig;
05444    switch (mysig) {
05445    case 0:
05446       /* Special pseudo -- automatically up*/
05447       ast_setstate(ast, AST_STATE_UP);
05448       break;
05449    case SIG_MFCR2:
05450       break;
05451    default:
05452       ast_debug(1, "not yet implemented\n");
05453       ast_mutex_unlock(&p->lock);
05454       return -1;
05455    }
05456 
05457 #ifdef HAVE_OPENR2
05458    if (p->mfcr2) {
05459       openr2_calling_party_category_t chancat;
05460       int callres = 0;
05461       char *c, *l;
05462 
05463       /* We'll get it in a moment -- but use dialdest to store pre-setup_ack digits */
05464       p->dialdest[0] = '\0';
05465 
05466       c = strchr(dest, '/');
05467       if (c) {
05468          c++;
05469       } else {
05470          c = "";
05471       }
05472       if (!p->hidecallerid) {
05473          l = ast->connected.id.number.valid ? ast->connected.id.number.str : NULL;
05474       } else {
05475          l = NULL;
05476       }
05477       if (strlen(c) < p->stripmsd) {
05478          ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
05479          ast_mutex_unlock(&p->lock);
05480          return -1;
05481       }
05482       p->dialing = 1;
05483       chancat = dahdi_r2_get_channel_category(ast);
05484       callres = openr2_chan_make_call(p->r2chan, l, (c + p->stripmsd), chancat);
05485       if (-1 == callres) {
05486          ast_mutex_unlock(&p->lock);
05487          ast_log(LOG_ERROR, "unable to make new MFC/R2 call!\n");
05488          return -1;
05489       }
05490       p->mfcr2_call_accepted = 0;
05491       p->mfcr2_progress = 0;
05492       ast_setstate(ast, AST_STATE_DIALING);
05493    }
05494 #endif /* HAVE_OPENR2 */
05495    ast_mutex_unlock(&p->lock);
05496    return 0;
05497 }
05498 
05499 /*!
05500  * \internal
05501  * \brief Insert the given chan_dahdi interface structure into the interface list.
05502  * \since 1.8
05503  *
05504  * \param pvt chan_dahdi private interface structure to insert.
05505  *
05506  * \details
05507  * The interface list is a doubly linked list sorted by the chan_dahdi channel number.
05508  * Any duplicates are inserted after the existing entries.
05509  *
05510  * \note The new interface must not already be in the list.
05511  *
05512  * \return Nothing
05513  */
05514 static void dahdi_iflist_insert(struct dahdi_pvt *pvt)
05515 {
05516    struct dahdi_pvt *cur;
05517 
05518    pvt->which_iflist = DAHDI_IFLIST_MAIN;
05519 
05520    /* Find place in middle of list for the new interface. */
05521    for (cur = iflist; cur; cur = cur->next) {
05522       if (pvt->channel < cur->channel) {
05523          /* New interface goes before the current interface. */
05524          pvt->prev = cur->prev;
05525          pvt->next = cur;
05526          if (cur->prev) {
05527             /* Insert into the middle of the list. */
05528             cur->prev->next = pvt;
05529          } else {
05530             /* Insert at head of list. */
05531             iflist = pvt;
05532          }
05533          cur->prev = pvt;
05534          return;
05535       }
05536    }
05537 
05538    /* New interface goes onto the end of the list */
05539    pvt->prev = ifend;
05540    pvt->next = NULL;
05541    if (ifend) {
05542       ifend->next = pvt;
05543    }
05544    ifend = pvt;
05545    if (!iflist) {
05546       /* List was empty */
05547       iflist = pvt;
05548    }
05549 }
05550 
05551 /*!
05552  * \internal
05553  * \brief Extract the given chan_dahdi interface structure from the interface list.
05554  * \since 1.8
05555  *
05556  * \param pvt chan_dahdi private interface structure to extract.
05557  *
05558  * \note
05559  * The given interface structure can be either in the interface list or a stand alone
05560  * structure that has not been put in the list if the next and prev pointers are NULL.
05561  *
05562  * \return Nothing
05563  */
05564 static void dahdi_iflist_extract(struct dahdi_pvt *pvt)
05565 {
05566    /* Extract from the forward chain. */
05567    if (pvt->prev) {
05568       pvt->prev->next = pvt->next;
05569    } else if (iflist == pvt) {
05570       /* Node is at the head of the list. */
05571       iflist = pvt->next;
05572    }
05573 
05574    /* Extract from the reverse chain. */
05575    if (pvt->next) {
05576       pvt->next->prev = pvt->prev;
05577    } else if (ifend == pvt) {
05578       /* Node is at the end of the list. */
05579       ifend = pvt->prev;
05580    }
05581 
05582    /* Node is no longer in the list. */
05583    pvt->which_iflist = DAHDI_IFLIST_NONE;
05584    pvt->prev = NULL;
05585    pvt->next = NULL;
05586 }
05587 
05588 #if defined(HAVE_PRI)
05589 /*!
05590  * \internal
05591  * \brief Insert the given chan_dahdi interface structure into the no B channel list.
05592  * \since 1.8
05593  *
05594  * \param pri sig_pri span control structure holding no B channel list.
05595  * \param pvt chan_dahdi private interface structure to insert.
05596  *
05597  * \details
05598  * The interface list is a doubly linked list sorted by the chan_dahdi channel number.
05599  * Any duplicates are inserted after the existing entries.
05600  *
05601  * \note The new interface must not already be in the list.
05602  *
05603  * \return Nothing
05604  */
05605 static void dahdi_nobch_insert(struct sig_pri_span *pri, struct dahdi_pvt *pvt)
05606 {
05607    struct dahdi_pvt *cur;
05608 
05609    pvt->which_iflist = DAHDI_IFLIST_NO_B_CHAN;
05610 
05611    /* Find place in middle of list for the new interface. */
05612    for (cur = pri->no_b_chan_iflist; cur; cur = cur->next) {
05613       if (pvt->channel < cur->channel) {
05614          /* New interface goes before the current interface. */
05615          pvt->prev = cur->prev;
05616          pvt->next = cur;
05617          if (cur->prev) {
05618             /* Insert into the middle of the list. */
05619             cur->prev->next = pvt;
05620          } else {
05621             /* Insert at head of list. */
05622             pri->no_b_chan_iflist = pvt;
05623          }
05624          cur->prev = pvt;
05625          return;
05626       }
05627    }
05628 
05629    /* New interface goes onto the end of the list */
05630    pvt->prev = pri->no_b_chan_end;
05631    pvt->next = NULL;
05632    if (pri->no_b_chan_end) {
05633       ((struct dahdi_pvt *) pri->no_b_chan_end)->next = pvt;
05634    }
05635    pri->no_b_chan_end = pvt;
05636    if (!pri->no_b_chan_iflist) {
05637       /* List was empty */
05638       pri->no_b_chan_iflist = pvt;
05639    }
05640 }
05641 #endif   /* defined(HAVE_PRI) */
05642 
05643 #if defined(HAVE_PRI)
05644 /*!
05645  * \internal
05646  * \brief Extract the given chan_dahdi interface structure from the no B channel list.
05647  * \since 1.8
05648  *
05649  * \param pri sig_pri span control structure holding no B channel list.
05650  * \param pvt chan_dahdi private interface structure to extract.
05651  *
05652  * \note
05653  * The given interface structure can be either in the interface list or a stand alone
05654  * structure that has not been put in the list if the next and prev pointers are NULL.
05655  *
05656  * \return Nothing
05657  */
05658 static void dahdi_nobch_extract(struct sig_pri_span *pri, struct dahdi_pvt *pvt)
05659 {
05660    /* Extract from the forward chain. */
05661    if (pvt->prev) {
05662       pvt->prev->next = pvt->next;
05663    } else if (pri->no_b_chan_iflist == pvt) {
05664       /* Node is at the head of the list. */
05665       pri->no_b_chan_iflist = pvt->next;
05666    }
05667 
05668    /* Extract from the reverse chain. */
05669    if (pvt->next) {
05670       pvt->next->prev = pvt->prev;
05671    } else if (pri->no_b_chan_end == pvt) {
05672       /* Node is at the end of the list. */
05673       pri->no_b_chan_end = pvt->prev;
05674    }
05675 
05676    /* Node is no longer in the list. */
05677    pvt->which_iflist = DAHDI_IFLIST_NONE;
05678    pvt->prev = NULL;
05679    pvt->next = NULL;
05680 }
05681 #endif   /* defined(HAVE_PRI) */
05682 
05683 #if defined(HAVE_PRI)
05684 /*!
05685  * \internal
05686  * \brief Unlink the channel interface from the PRI private pointer array.
05687  * \since 1.8
05688  *
05689  * \param pvt chan_dahdi private interface structure to unlink.
05690  *
05691  * \return Nothing
05692  */
05693 static void dahdi_unlink_pri_pvt(struct dahdi_pvt *pvt)
05694 {
05695    unsigned idx;
05696    struct sig_pri_span *pri;
05697 
05698    pri = pvt->pri;
05699    if (!pri) {
05700       /* Not PRI signaling so cannot be in a PRI private pointer array. */
05701       return;
05702    }
05703    ast_mutex_lock(&pri->lock);
05704    for (idx = 0; idx < pri->numchans; ++idx) {
05705       if (pri->pvts[idx] == pvt->sig_pvt) {
05706          pri->pvts[idx] = NULL;
05707          ast_mutex_unlock(&pri->lock);
05708          return;
05709       }
05710    }
05711    ast_mutex_unlock(&pri->lock);
05712 }
05713 #endif   /* defined(HAVE_PRI) */
05714 
05715 #if defined(HAVE_SS7)
05716 /*!
05717  * \internal
05718  * \brief Unlink the channel interface from the SS7 private pointer array.
05719  * \since 1.8
05720  *
05721  * \param pvt chan_dahdi private interface structure to unlink.
05722  *
05723  * \return Nothing
05724  */
05725 static void dahdi_unlink_ss7_pvt(struct dahdi_pvt *pvt)
05726 {
05727    unsigned idx;
05728    struct sig_ss7_linkset *ss7;
05729 
05730    ss7 = pvt->ss7;
05731    if (!ss7) {
05732       /* Not SS7 signaling so cannot be in a SS7 private pointer array. */
05733       return;
05734    }
05735    ast_mutex_lock(&ss7->lock);
05736    for (idx = 0; idx < ss7->numchans; ++idx) {
05737       if (ss7->pvts[idx] == pvt->sig_pvt) {
05738          ss7->pvts[idx] = NULL;
05739          ast_mutex_unlock(&ss7->lock);
05740          return;
05741       }
05742    }
05743    ast_mutex_unlock(&ss7->lock);
05744 }
05745 #endif   /* defined(HAVE_SS7) */
05746 
05747 static struct dahdi_pvt *find_next_iface_in_span(struct dahdi_pvt *cur)
05748 {
05749    if (cur->next && cur->next->span == cur->span) {
05750       return cur->next;
05751    } else if (cur->prev && cur->prev->span == cur->span) {
05752       return cur->prev;
05753    }
05754 
05755    return NULL;
05756 }
05757 
05758 static void destroy_dahdi_pvt(struct dahdi_pvt *pvt)
05759 {
05760    struct dahdi_pvt *p = pvt;
05761 
05762    if (p->manages_span_alarms) {
05763       struct dahdi_pvt *next = find_next_iface_in_span(p);
05764       if (next) {
05765          next->manages_span_alarms = 1;
05766       }
05767    }
05768 
05769    /* Remove channel from the list */
05770 #if defined(HAVE_PRI)
05771    dahdi_unlink_pri_pvt(p);
05772 #endif   /* defined(HAVE_PRI) */
05773 #if defined(HAVE_SS7)
05774    dahdi_unlink_ss7_pvt(p);
05775 #endif   /* defined(HAVE_SS7) */
05776    switch (pvt->which_iflist) {
05777    case DAHDI_IFLIST_NONE:
05778       break;
05779    case DAHDI_IFLIST_MAIN:
05780       dahdi_iflist_extract(p);
05781       break;
05782 #if defined(HAVE_PRI)
05783    case DAHDI_IFLIST_NO_B_CHAN:
05784       if (p->pri) {
05785          dahdi_nobch_extract(p->pri, p);
05786       }
05787       break;
05788 #endif   /* defined(HAVE_PRI) */
05789    }
05790 
05791    if (p->sig_pvt) {
05792       if (analog_lib_handles(p->sig, 0, 0)) {
05793          analog_delete(p->sig_pvt);
05794       }
05795       switch (p->sig) {
05796 #if defined(HAVE_PRI)
05797       case SIG_PRI_LIB_HANDLE_CASES:
05798          sig_pri_chan_delete(p->sig_pvt);
05799          break;
05800 #endif   /* defined(HAVE_PRI) */
05801 #if defined(HAVE_SS7)
05802       case SIG_SS7:
05803          sig_ss7_chan_delete(p->sig_pvt);
05804          break;
05805 #endif   /* defined(HAVE_SS7) */
05806       default:
05807          break;
05808       }
05809    }
05810    ast_free(p->cidspill);
05811    if (p->use_smdi)
05812       ast_smdi_interface_unref(p->smdi_iface);
05813    if (p->mwi_event_sub)
05814       ast_event_unsubscribe(p->mwi_event_sub);
05815    if (p->vars) {
05816       ast_variables_destroy(p->vars);
05817    }
05818    if (p->cc_params) {
05819       ast_cc_config_params_destroy(p->cc_params);
05820    }
05821    ast_mutex_destroy(&p->lock);
05822    dahdi_close_sub(p, SUB_REAL);
05823    if (p->owner)
05824       p->owner->tech_pvt = NULL;
05825    ast_free(p);
05826 }
05827 
05828 static void destroy_channel(struct dahdi_pvt *cur, int now)
05829 {
05830    int i;
05831 
05832    if (!now) {
05833       /* Do not destroy the channel now if it is owned by someone. */
05834       if (cur->owner) {
05835          return;
05836       }
05837       for (i = 0; i < 3; i++) {
05838          if (cur->subs[i].owner) {
05839             return;
05840          }
05841       }
05842    }
05843    destroy_dahdi_pvt(cur);
05844 }
05845 
05846 static void destroy_all_channels(void)
05847 {
05848    int chan;
05849 #if defined(HAVE_PRI)
05850    unsigned span;
05851    struct sig_pri_span *pri;
05852 #endif   /* defined(HAVE_PRI) */
05853    struct dahdi_pvt *p;
05854 
05855    while (num_restart_pending) {
05856       usleep(1);
05857    }
05858 
05859    ast_mutex_lock(&iflock);
05860    /* Destroy all the interfaces and free their memory */
05861    while (iflist) {
05862       p = iflist;
05863 
05864       chan = p->channel;
05865 #if defined(HAVE_PRI_SERVICE_MESSAGES)
05866       {
05867          char db_chan_name[20];
05868          char db_answer[5];
05869          char state;
05870          int why = -1;
05871 
05872          snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, p->span, chan);
05873          if (!ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) {
05874             sscanf(db_answer, "%1c:%30d", &state, &why);
05875          }
05876          if (!why) {
05877             /* SRVST persistence is not required */
05878             ast_db_del(db_chan_name, SRVST_DBKEY);
05879          }
05880       }
05881 #endif   /* defined(HAVE_PRI_SERVICE_MESSAGES) */
05882       /* Free associated memory */
05883       destroy_dahdi_pvt(p);
05884       ast_verb(3, "Unregistered channel %d\n", chan);
05885    }
05886    ifcount = 0;
05887    ast_mutex_unlock(&iflock);
05888 
05889 #if defined(HAVE_PRI)
05890    /* Destroy all of the no B channel interface lists */
05891    for (span = 0; span < NUM_SPANS; ++span) {
05892       if (!pris[span].dchannels[0]) {
05893          break;
05894       }
05895       pri = &pris[span].pri;
05896       ast_mutex_lock(&pri->lock);
05897       while (pri->no_b_chan_iflist) {
05898          p = pri->no_b_chan_iflist;
05899 
05900          /* Free associated memory */
05901          destroy_dahdi_pvt(p);
05902       }
05903       ast_mutex_unlock(&pri->lock);
05904    }
05905 #endif   /* defined(HAVE_PRI) */
05906 }
05907 
05908 #if defined(HAVE_PRI)
05909 static char *dahdi_send_keypad_facility_app = "DAHDISendKeypadFacility";
05910 
05911 static int dahdi_send_keypad_facility_exec(struct ast_channel *chan, const char *digits)
05912 {
05913    /* Data will be our digit string */
05914    struct dahdi_pvt *p;
05915 
05916    if (ast_strlen_zero(digits)) {
05917       ast_debug(1, "No digit string sent to application!\n");
05918       return -1;
05919    }
05920 
05921    p = (struct dahdi_pvt *)chan->tech_pvt;
05922 
05923    if (!p) {
05924       ast_debug(1, "Unable to find technology private\n");
05925       return -1;
05926    }
05927 
05928    pri_send_keypad_facility_exec(p->sig_pvt, digits);
05929 
05930    return 0;
05931 }
05932 #endif   /* defined(HAVE_PRI) */
05933 
05934 #if defined(HAVE_PRI)
05935 #if defined(HAVE_PRI_PROG_W_CAUSE)
05936 static char *dahdi_send_callrerouting_facility_app = "DAHDISendCallreroutingFacility";
05937 
05938 static int dahdi_send_callrerouting_facility_exec(struct ast_channel *chan, const char *data)
05939 {
05940    /* Data will be our digit string */
05941    struct dahdi_pvt *pvt;
05942    char *parse;
05943    int res;
05944    AST_DECLARE_APP_ARGS(args,
05945       AST_APP_ARG(destination);
05946       AST_APP_ARG(original);
05947       AST_APP_ARG(reason);
05948    );
05949 
05950    if (ast_strlen_zero(data)) {
05951       ast_log(LOG_DEBUG, "No data sent to application!\n");
05952       return -1;
05953    }
05954    if (chan->tech != &dahdi_tech) {
05955       ast_log(LOG_DEBUG, "Only DAHDI technology accepted!\n");
05956       return -1;
05957    }
05958    pvt = (struct dahdi_pvt *) chan->tech_pvt;
05959    if (!pvt) {
05960       ast_log(LOG_DEBUG, "Unable to find technology private\n");
05961       return -1;
05962    }
05963    switch (pvt->sig) {
05964    case SIG_PRI_LIB_HANDLE_CASES:
05965       break;
05966    default:
05967       ast_log(LOG_DEBUG, "callrerouting attempted on non-ISDN channel %s\n",
05968          chan->name);
05969       return -1;
05970    }
05971 
05972    parse = ast_strdupa(data);
05973    AST_STANDARD_APP_ARGS(args, parse);
05974 
05975    if (ast_strlen_zero(args.destination)) {
05976       ast_log(LOG_WARNING, "callrerouting facility requires at least destination number argument\n");
05977       return -1;
05978    }
05979 
05980    if (ast_strlen_zero(args.original)) {
05981       ast_log(LOG_WARNING, "Callrerouting Facility without original called number argument\n");
05982       args.original = NULL;
05983    }
05984 
05985    if (ast_strlen_zero(args.reason)) {
05986       ast_log(LOG_NOTICE, "Callrerouting Facility without diversion reason argument, defaulting to unknown\n");
05987       args.reason = NULL;
05988    }
05989 
05990    res = pri_send_callrerouting_facility_exec(pvt->sig_pvt, chan->_state,
05991       args.destination, args.original, args.reason);
05992    if (!res) {
05993       /*
05994        * Wait up to 5 seconds for a reply before hanging up this call
05995        * leg if the peer does not disconnect first.
05996        */
05997       ast_safe_sleep(chan, 5000);
05998    }
05999 
06000    return -1;
06001 }
06002 #endif   /* defined(HAVE_PRI_PROG_W_CAUSE) */
06003 #endif   /* defined(HAVE_PRI) */
06004 
06005 #if defined(HAVE_OPENR2)
06006 static const char * const dahdi_accept_r2_call_app = "DAHDIAcceptR2Call";
06007 
06008 static int dahdi_accept_r2_call_exec(struct ast_channel *chan, const char *data)
06009 {
06010    /* data is whether to accept with charge or no charge */
06011    openr2_call_mode_t accept_mode;
06012    int res, timeout, maxloops;
06013    struct ast_frame *f;
06014    struct dahdi_pvt *p;
06015    char *parse;
06016    AST_DECLARE_APP_ARGS(args,
06017          AST_APP_ARG(charge);
06018    );
06019 
06020    if (ast_strlen_zero(data)) {
06021       ast_log(LOG_DEBUG, "No data sent to application!\n");
06022       return -1;
06023    }
06024 
06025    if (chan->tech != &dahdi_tech) {
06026       ast_log(LOG_DEBUG, "Only DAHDI technology accepted!\n");
06027       return -1;
06028    }
06029 
06030    p = (struct dahdi_pvt *)chan->tech_pvt;
06031    if (!p) {
06032       ast_log(LOG_DEBUG, "Unable to find technology private!\n");
06033       return -1;
06034    }
06035 
06036    parse = ast_strdupa(data);
06037    AST_STANDARD_APP_ARGS(args, parse);
06038 
06039    if (ast_strlen_zero(args.charge)) {
06040       ast_log(LOG_WARNING, "DAHDIAcceptR2Call requires 'yes' or 'no' for the charge parameter\n");
06041       return -1;
06042    }
06043 
06044    ast_mutex_lock(&p->lock);
06045    if (!p->mfcr2 || !p->mfcr2call) {
06046       ast_mutex_unlock(&p->lock);
06047       ast_log(LOG_DEBUG, "Channel %s does not seems to be an R2 active channel!\n", chan->name);
06048       return -1;
06049    }
06050 
06051    if (p->mfcr2_call_accepted) {
06052       ast_mutex_unlock(&p->lock);
06053       ast_log(LOG_DEBUG, "MFC/R2 call already accepted on channel %s!\n", chan->name);
06054       return 0;
06055    }
06056    accept_mode = ast_true(args.charge) ? OR2_CALL_WITH_CHARGE : OR2_CALL_NO_CHARGE;
06057    if (openr2_chan_accept_call(p->r2chan, accept_mode)) {
06058       ast_mutex_unlock(&p->lock);
06059       ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n");
06060       return -1;
06061    }
06062    ast_mutex_unlock(&p->lock);
06063 
06064    res = 0;
06065    timeout = 100;
06066    maxloops = 50; /* wait up to 5 seconds */
06067    /* we need to read() until the call is accepted */
06068    while (maxloops > 0) {
06069       maxloops--;
06070       if (ast_check_hangup(chan)) {
06071          break;
06072       }
06073       res = ast_waitfor(chan, timeout);
06074       if (res < 0) {
06075          ast_log(LOG_DEBUG, "ast_waitfor failed on channel %s, going out ...\n", chan->name);
06076          res = -1;
06077          break;
06078       }
06079       if (res == 0) {
06080          continue;
06081       }
06082       res = 0;
06083       f = ast_read(chan);
06084       if (!f) {
06085          ast_log(LOG_DEBUG, "No frame read on channel %s, going out ...\n", chan->name);
06086          res = -1;
06087          break;
06088       }
06089       if (f->frametype == AST_FRAME_CONTROL && f->subclass.integer == AST_CONTROL_HANGUP) {
06090          ast_log(LOG_DEBUG, "Got HANGUP frame on channel %s, going out ...\n", chan->name);
06091          ast_frfree(f);
06092          res = -1;
06093          break;
06094       }
06095       ast_frfree(f);
06096       ast_mutex_lock(&p->lock);
06097       if (p->mfcr2_call_accepted) {
06098          ast_mutex_unlock(&p->lock);
06099          ast_log(LOG_DEBUG, "Accepted MFC/R2 call!\n");
06100          break;
06101       }
06102       ast_mutex_unlock(&p->lock);
06103    }
06104    if (res == -1) {
06105       ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n");
06106    }
06107    return res;
06108 }
06109 
06110 static openr2_call_disconnect_cause_t dahdi_ast_cause_to_r2_cause(int cause)
06111 {
06112    openr2_call_disconnect_cause_t r2cause = OR2_CAUSE_NORMAL_CLEARING;
06113    switch (cause) {
06114    case AST_CAUSE_USER_BUSY:
06115    case AST_CAUSE_CALL_REJECTED:
06116    case AST_CAUSE_INTERWORKING: /* I don't know wtf is this but is used sometimes when ekiga rejects a call */
06117       r2cause = OR2_CAUSE_BUSY_NUMBER;
06118       break;
06119 
06120    case AST_CAUSE_NORMAL_CIRCUIT_CONGESTION:
06121    case AST_CAUSE_SWITCH_CONGESTION:
06122       r2cause = OR2_CAUSE_NETWORK_CONGESTION;
06123       break;
06124 
06125    case AST_CAUSE_UNALLOCATED:
06126       r2cause = OR2_CAUSE_UNALLOCATED_NUMBER;
06127       break;
06128 
06129    case AST_CAUSE_NETWORK_OUT_OF_ORDER:
06130    case AST_CAUSE_DESTINATION_OUT_OF_ORDER:
06131       r2cause = OR2_CAUSE_OUT_OF_ORDER;
06132       break;
06133 
06134    case AST_CAUSE_NO_ANSWER:
06135    case AST_CAUSE_NO_USER_RESPONSE:
06136       r2cause = OR2_CAUSE_NO_ANSWER;
06137       break;
06138 
06139    default:
06140       r2cause = OR2_CAUSE_NORMAL_CLEARING;
06141       break;
06142    }
06143    ast_log(LOG_DEBUG, "ast cause %d resulted in openr2 cause %d/%s\n",
06144          cause, r2cause, openr2_proto_get_disconnect_string(r2cause));
06145    return r2cause;
06146 }
06147 #endif
06148 
06149 static int revert_fax_buffers(struct dahdi_pvt *p, struct ast_channel *ast)
06150 {
06151    if (p->bufferoverrideinuse) {
06152       /* faxbuffers are in use, revert them */
06153       struct dahdi_bufferinfo bi = {
06154          .txbufpolicy = p->buf_policy,
06155          .rxbufpolicy = p->buf_policy,
06156          .bufsize = p->bufsize,
06157          .numbufs = p->buf_no
06158       };
06159       int bpres;
06160 
06161       if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
06162          ast_log(LOG_WARNING, "Channel '%s' unable to revert buffer policy: %s\n", ast->name, strerror(errno));
06163       }
06164       p->bufferoverrideinuse = 0;
06165       return bpres;
06166    }
06167 
06168    return -1;
06169 }
06170 
06171 static int dahdi_hangup(struct ast_channel *ast)
06172 {
06173    int res = 0;
06174    int idx,x;
06175    int law;
06176    /*static int restore_gains(struct dahdi_pvt *p);*/
06177    struct dahdi_pvt *p = ast->tech_pvt;
06178    struct dahdi_params par;
06179 
06180    ast_debug(1, "dahdi_hangup(%s)\n", ast->name);
06181    if (!ast->tech_pvt) {
06182       ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
06183       return 0;
06184    }
06185 
06186    ast_mutex_lock(&p->lock);
06187    p->exten[0] = '\0';
06188    if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
06189       dahdi_confmute(p, 0);
06190       restore_gains(p);
06191       p->ignoredtmf = 0;
06192       p->waitingfordt.tv_sec = 0;
06193 
06194       res = analog_hangup(p->sig_pvt, ast);
06195       revert_fax_buffers(p, ast);
06196 
06197       goto hangup_out;
06198    } else {
06199       p->cid_num[0] = '\0';
06200       p->cid_name[0] = '\0';
06201       p->cid_subaddr[0] = '\0';
06202    }
06203 
06204 #if defined(HAVE_PRI)
06205    if (dahdi_sig_pri_lib_handles(p->sig)) {
06206       x = 1;
06207       ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
06208 
06209       dahdi_confmute(p, 0);
06210       p->muting = 0;
06211       restore_gains(p);
06212       if (p->dsp) {
06213          ast_dsp_free(p->dsp);
06214          p->dsp = NULL;
06215       }
06216       p->ignoredtmf = 0;
06217 
06218       /* Real channel, do some fixup */
06219       p->subs[SUB_REAL].owner = NULL;
06220       p->subs[SUB_REAL].needbusy = 0;
06221       dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
06222 
06223       p->owner = NULL;
06224       p->cid_tag[0] = '\0';
06225       p->ringt = 0;/* Probably not used in this mode.  Reset anyway. */
06226       p->distinctivering = 0;/* Probably not used in this mode. Reset anyway. */
06227       p->confirmanswer = 0;/* Probably not used in this mode. Reset anyway. */
06228       p->outgoing = 0;
06229       p->digital = 0;
06230       p->faxhandled = 0;
06231       p->pulsedial = 0;/* Probably not used in this mode. Reset anyway. */
06232 
06233       revert_fax_buffers(p, ast);
06234 
06235       p->law = p->law_default;
06236       law = p->law_default;
06237       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
06238       if (res < 0) {
06239          ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n",
06240             p->channel, strerror(errno));
06241       }
06242 
06243       sig_pri_hangup(p->sig_pvt, ast);
06244 
06245       tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06246       dahdi_disable_ec(p);
06247 
06248       x = 0;
06249       ast_channel_setoption(ast, AST_OPTION_TDD, &x, sizeof(char), 0);
06250       p->didtdd = 0;/* Probably not used in this mode. Reset anyway. */
06251 
06252       p->rdnis[0] = '\0';
06253       update_conf(p);
06254       reset_conf(p);
06255 
06256       /* Restore data mode */
06257       x = 0;
06258       ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
06259 
06260       if (num_restart_pending == 0) {
06261          restart_monitor();
06262       }
06263       goto hangup_out;
06264    }
06265 #endif   /* defined(HAVE_PRI) */
06266 
06267 #if defined(HAVE_SS7)
06268    if (p->sig == SIG_SS7) {
06269       x = 1;
06270       ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
06271 
06272       dahdi_confmute(p, 0);
06273       p->muting = 0;
06274       restore_gains(p);
06275       if (p->dsp) {
06276          ast_dsp_free(p->dsp);
06277          p->dsp = NULL;
06278       }
06279       p->ignoredtmf = 0;
06280 
06281       /* Real channel, do some fixup */
06282       p->subs[SUB_REAL].owner = NULL;
06283       p->subs[SUB_REAL].needbusy = 0;
06284       dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
06285 
06286       p->owner = NULL;
06287       p->ringt = 0;/* Probably not used in this mode.  Reset anyway. */
06288       p->distinctivering = 0;/* Probably not used in this mode. Reset anyway. */
06289       p->confirmanswer = 0;/* Probably not used in this mode. Reset anyway. */
06290       p->outgoing = 0;
06291       p->digital = 0;
06292       p->faxhandled = 0;
06293       p->pulsedial = 0;/* Probably not used in this mode. Reset anyway. */
06294 
06295       revert_fax_buffers(p, ast);
06296 
06297       p->law = p->law_default;
06298       law = p->law_default;
06299       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
06300       if (res < 0) {
06301          ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n",
06302             p->channel, strerror(errno));
06303       }
06304 
06305       sig_ss7_hangup(p->sig_pvt, ast);
06306 
06307       tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06308       dahdi_disable_ec(p);
06309 
06310       x = 0;
06311       ast_channel_setoption(ast, AST_OPTION_TDD, &x, sizeof(char), 0);
06312       p->didtdd = 0;/* Probably not used in this mode. Reset anyway. */
06313 
06314       update_conf(p);
06315       reset_conf(p);
06316 
06317       /* Restore data mode */
06318       x = 0;
06319       ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
06320 
06321       if (num_restart_pending == 0) {
06322          restart_monitor();
06323       }
06324       goto hangup_out;
06325    }
06326 #endif   /* defined(HAVE_SS7) */
06327 
06328    idx = dahdi_get_index(ast, p, 1);
06329 
06330    dahdi_confmute(p, 0);
06331    p->muting = 0;
06332    restore_gains(p);
06333    if (p->origcid_num) {
06334       ast_copy_string(p->cid_num, p->origcid_num, sizeof(p->cid_num));
06335       ast_free(p->origcid_num);
06336       p->origcid_num = NULL;
06337    }
06338    if (p->origcid_name) {
06339       ast_copy_string(p->cid_name, p->origcid_name, sizeof(p->cid_name));
06340       ast_free(p->origcid_name);
06341       p->origcid_name = NULL;
06342    }
06343    if (p->dsp)
06344       ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
06345 
06346    ast_debug(1, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n",
06347       p->channel, idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
06348    p->ignoredtmf = 0;
06349 
06350    if (idx > -1) {
06351       /* Real channel, do some fixup */
06352       p->subs[idx].owner = NULL;
06353       p->subs[idx].needanswer = 0;
06354       p->subs[idx].needflash = 0;
06355       p->subs[idx].needringing = 0;
06356       p->subs[idx].needbusy = 0;
06357       p->subs[idx].needcongestion = 0;
06358       p->subs[idx].linear = 0;
06359       p->polarity = POLARITY_IDLE;
06360       dahdi_setlinear(p->subs[idx].dfd, 0);
06361       if (idx == SUB_REAL) {
06362          if ((p->subs[SUB_CALLWAIT].dfd > -1) && (p->subs[SUB_THREEWAY].dfd > -1)) {
06363             ast_debug(1, "Normal call hung up with both three way call and a call waiting call in place?\n");
06364             if (p->subs[SUB_CALLWAIT].inthreeway) {
06365                /* We had flipped over to answer a callwait and now it's gone */
06366                ast_debug(1, "We were flipped over to the callwait, moving back and unowning.\n");
06367                /* Move to the call-wait, but un-own us until they flip back. */
06368                swap_subs(p, SUB_CALLWAIT, SUB_REAL);
06369                unalloc_sub(p, SUB_CALLWAIT);
06370                p->owner = NULL;
06371             } else {
06372                /* The three way hung up, but we still have a call wait */
06373                ast_debug(1, "We were in the threeway and have a callwait still.  Ditching the threeway.\n");
06374                swap_subs(p, SUB_THREEWAY, SUB_REAL);
06375                unalloc_sub(p, SUB_THREEWAY);
06376                if (p->subs[SUB_REAL].inthreeway) {
06377                   /* This was part of a three way call.  Immediately make way for
06378                      another call */
06379                   ast_debug(1, "Call was complete, setting owner to former third call\n");
06380                   p->owner = p->subs[SUB_REAL].owner;
06381                } else {
06382                   /* This call hasn't been completed yet...  Set owner to NULL */
06383                   ast_debug(1, "Call was incomplete, setting owner to NULL\n");
06384                   p->owner = NULL;
06385                }
06386                p->subs[SUB_REAL].inthreeway = 0;
06387             }
06388          } else if (p->subs[SUB_CALLWAIT].dfd > -1) {
06389             /* Move to the call-wait and switch back to them. */
06390             swap_subs(p, SUB_CALLWAIT, SUB_REAL);
06391             unalloc_sub(p, SUB_CALLWAIT);
06392             p->owner = p->subs[SUB_REAL].owner;
06393             if (p->owner->_state != AST_STATE_UP)
06394                p->subs[SUB_REAL].needanswer = 1;
06395             if (ast_bridged_channel(p->subs[SUB_REAL].owner))
06396                ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
06397          } else if (p->subs[SUB_THREEWAY].dfd > -1) {
06398             swap_subs(p, SUB_THREEWAY, SUB_REAL);
06399             unalloc_sub(p, SUB_THREEWAY);
06400             if (p->subs[SUB_REAL].inthreeway) {
06401                /* This was part of a three way call.  Immediately make way for
06402                   another call */
06403                ast_debug(1, "Call was complete, setting owner to former third call\n");
06404                p->owner = p->subs[SUB_REAL].owner;
06405             } else {
06406                /* This call hasn't been completed yet...  Set owner to NULL */
06407                ast_debug(1, "Call was incomplete, setting owner to NULL\n");
06408                p->owner = NULL;
06409             }
06410             p->subs[SUB_REAL].inthreeway = 0;
06411          }
06412       } else if (idx == SUB_CALLWAIT) {
06413          /* Ditch the holding callwait call, and immediately make it availabe */
06414          if (p->subs[SUB_CALLWAIT].inthreeway) {
06415             /* This is actually part of a three way, placed on hold.  Place the third part
06416                on music on hold now */
06417             if (p->subs[SUB_THREEWAY].owner && ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
06418                ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
06419                   S_OR(p->mohsuggest, NULL),
06420                   !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
06421             }
06422             p->subs[SUB_THREEWAY].inthreeway = 0;
06423             /* Make it the call wait now */
06424             swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
06425             unalloc_sub(p, SUB_THREEWAY);
06426          } else
06427             unalloc_sub(p, SUB_CALLWAIT);
06428       } else if (idx == SUB_THREEWAY) {
06429          if (p->subs[SUB_CALLWAIT].inthreeway) {
06430             /* The other party of the three way call is currently in a call-wait state.
06431                Start music on hold for them, and take the main guy out of the third call */
06432             if (p->subs[SUB_CALLWAIT].owner && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
06433                ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
06434                   S_OR(p->mohsuggest, NULL),
06435                   !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
06436             }
06437             p->subs[SUB_CALLWAIT].inthreeway = 0;
06438          }
06439          p->subs[SUB_REAL].inthreeway = 0;
06440          /* If this was part of a three way call index, let us make
06441             another three way call */
06442          unalloc_sub(p, SUB_THREEWAY);
06443       } else {
06444          /* This wasn't any sort of call, but how are we an index? */
06445          ast_log(LOG_WARNING, "Index found but not any type of call?\n");
06446       }
06447    }
06448 
06449    if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) {
06450       p->owner = NULL;
06451       p->ringt = 0;
06452       p->distinctivering = 0;
06453       p->confirmanswer = 0;
06454       p->outgoing = 0;
06455       p->digital = 0;
06456       p->faxhandled = 0;
06457       p->pulsedial = 0;
06458       if (p->dsp) {
06459          ast_dsp_free(p->dsp);
06460          p->dsp = NULL;
06461       }
06462 
06463       revert_fax_buffers(p, ast);
06464 
06465       p->law = p->law_default;
06466       law = p->law_default;
06467       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
06468       if (res < 0)
06469          ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
06470       /* Perform low level hangup if no owner left */
06471 #ifdef HAVE_OPENR2
06472       if (p->mfcr2 && p->mfcr2call && openr2_chan_get_direction(p->r2chan) != OR2_DIR_STOPPED) {
06473          ast_log(LOG_DEBUG, "disconnecting MFC/R2 call on chan %d\n", p->channel);
06474          /* If it's an incoming call, check the mfcr2_forced_release setting */
06475          if (openr2_chan_get_direction(p->r2chan) == OR2_DIR_BACKWARD && p->mfcr2_forced_release) {
06476             dahdi_r2_disconnect_call(p, OR2_CAUSE_FORCED_RELEASE);
06477          } else {
06478             const char *r2causestr = pbx_builtin_getvar_helper(ast, "MFCR2_CAUSE");
06479             int r2cause_user = r2causestr ? atoi(r2causestr) : 0;
06480             openr2_call_disconnect_cause_t r2cause = r2cause_user ? dahdi_ast_cause_to_r2_cause(r2cause_user)
06481                                                              : dahdi_ast_cause_to_r2_cause(ast->hangupcause);
06482             dahdi_r2_disconnect_call(p, r2cause);
06483          }
06484       } else if (p->mfcr2call) {
06485          ast_log(LOG_DEBUG, "Clearing call request on channel %d\n", p->channel);
06486          /* since ast_request() was called but not ast_call() we have not yet dialed
06487          and the openr2 stack will not call on_call_end callback, we need to unset
06488          the mfcr2call flag and bump the monitor count so the monitor thread can take
06489          care of this channel events from now on */
06490          p->mfcr2call = 0;
06491       }
06492 #endif
06493       switch (p->sig) {
06494       case SIG_SS7:
06495       case SIG_MFCR2:
06496       case SIG_PRI_LIB_HANDLE_CASES:
06497       case 0:
06498          break;
06499       default:
06500          res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
06501          break;
06502       }
06503       if (res < 0) {
06504          ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast->name);
06505       }
06506       switch (p->sig) {
06507       case SIG_FXOGS:
06508       case SIG_FXOLS:
06509       case SIG_FXOKS:
06510          memset(&par, 0, sizeof(par));
06511          res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
06512          if (!res) {
06513             struct analog_pvt *analog_p = p->sig_pvt;
06514 #if 0
06515             ast_debug(1, "Hanging up channel %d, offhook = %d\n", p->channel, par.rxisoffhook);
06516 #endif
06517             /* If they're off hook, try playing congestion */
06518             if ((par.rxisoffhook) && (!(p->radio || (p->oprmode < 0))))
06519                tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
06520             else
06521                tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06522             analog_p->fxsoffhookstate = par.rxisoffhook;
06523          }
06524          break;
06525       case SIG_FXSGS:
06526       case SIG_FXSLS:
06527       case SIG_FXSKS:
06528          /* Make sure we're not made available for at least two seconds assuming
06529          we were actually used for an inbound or outbound call. */
06530          if (ast->_state != AST_STATE_RESERVED) {
06531             time(&p->guardtime);
06532             p->guardtime += 2;
06533          }
06534          break;
06535       default:
06536          tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06537          break;
06538       }
06539       if (p->sig)
06540          dahdi_disable_ec(p);
06541       x = 0;
06542       ast_channel_setoption(ast,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0);
06543       ast_channel_setoption(ast,AST_OPTION_TDD,&x,sizeof(char),0);
06544       p->didtdd = 0;
06545       p->callwaitcas = 0;
06546       p->callwaiting = p->permcallwaiting;
06547       p->hidecallerid = p->permhidecallerid;
06548       p->waitingfordt.tv_sec = 0;
06549       p->dialing = 0;
06550       p->rdnis[0] = '\0';
06551       update_conf(p);
06552       reset_conf(p);
06553       /* Restore data mode */
06554       switch (p->sig) {
06555       case SIG_PRI_LIB_HANDLE_CASES:
06556       case SIG_SS7:
06557          x = 0;
06558          ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
06559          break;
06560       default:
06561          break;
06562       }
06563       if (num_restart_pending == 0)
06564          restart_monitor();
06565    }
06566 
06567    p->callwaitingrepeat = 0;
06568    p->cidcwexpire = 0;
06569    p->cid_suppress_expire = 0;
06570    p->oprmode = 0;
06571 hangup_out:
06572    ast->tech_pvt = NULL;
06573    ast_free(p->cidspill);
06574    p->cidspill = NULL;
06575 
06576    ast_mutex_unlock(&p->lock);
06577    ast_verb(3, "Hungup '%s'\n", ast->name);
06578 
06579    ast_mutex_lock(&iflock);
06580    if (p->restartpending) {
06581       num_restart_pending--;
06582    }
06583 
06584    if (p->destroy) {
06585       destroy_channel(p, 0);
06586    }
06587    ast_mutex_unlock(&iflock);
06588 
06589    ast_module_unref(ast_module_info->self);
06590    return 0;
06591 }
06592 
06593 static int dahdi_answer(struct ast_channel *ast)
06594 {
06595    struct dahdi_pvt *p = ast->tech_pvt;
06596    int res = 0;
06597    int idx;
06598    ast_setstate(ast, AST_STATE_UP);/*! \todo XXX this is redundantly set by the analog and PRI submodules! */
06599    ast_mutex_lock(&p->lock);
06600    idx = dahdi_get_index(ast, p, 0);
06601    if (idx < 0)
06602       idx = SUB_REAL;
06603    /* nothing to do if a radio channel */
06604    if ((p->radio || (p->oprmode < 0))) {
06605       ast_mutex_unlock(&p->lock);
06606       return 0;
06607    }
06608 
06609    if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
06610       res = analog_answer(p->sig_pvt, ast);
06611       ast_mutex_unlock(&p->lock);
06612       return res;
06613    }
06614 
06615    switch (p->sig) {
06616 #if defined(HAVE_PRI)
06617    case SIG_PRI_LIB_HANDLE_CASES:
06618       res = sig_pri_answer(p->sig_pvt, ast);
06619       break;
06620 #endif   /* defined(HAVE_PRI) */
06621 #if defined(HAVE_SS7)
06622    case SIG_SS7:
06623       res = sig_ss7_answer(p->sig_pvt, ast);
06624       break;
06625 #endif   /* defined(HAVE_SS7) */
06626 #ifdef HAVE_OPENR2
06627    case SIG_MFCR2:
06628       if (!p->mfcr2_call_accepted) {
06629          /* The call was not accepted on offer nor the user, so it must be accepted now before answering,
06630             openr2_chan_answer_call will be called when the callback on_call_accepted is executed */
06631          p->mfcr2_answer_pending = 1;
06632          if (p->mfcr2_charge_calls) {
06633             ast_log(LOG_DEBUG, "Accepting MFC/R2 call with charge before answering on chan %d\n", p->channel);
06634             openr2_chan_accept_call(p->r2chan, OR2_CALL_WITH_CHARGE);
06635          } else {
06636             ast_log(LOG_DEBUG, "Accepting MFC/R2 call with no charge before answering on chan %d\n", p->channel);
06637             openr2_chan_accept_call(p->r2chan, OR2_CALL_NO_CHARGE);
06638          }
06639       } else {
06640          ast_log(LOG_DEBUG, "Answering MFC/R2 call on chan %d\n", p->channel);
06641          dahdi_r2_answer(p);
06642       }
06643       break;
06644 #endif
06645    case 0:
06646       ast_mutex_unlock(&p->lock);
06647       return 0;
06648    default:
06649       ast_log(LOG_WARNING, "Don't know how to answer signalling %d (channel %d)\n", p->sig, p->channel);
06650       res = -1;
06651       break;
06652    }
06653    ast_mutex_unlock(&p->lock);
06654    return res;
06655 }
06656 
06657 static void disable_dtmf_detect(struct dahdi_pvt *p)
06658 {
06659    int val = 0;
06660 
06661    p->ignoredtmf = 1;
06662 
06663    ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
06664 
06665    if (!p->hardwaredtmf && p->dsp) {
06666       p->dsp_features &= ~DSP_FEATURE_DIGIT_DETECT;
06667       ast_dsp_set_features(p->dsp, p->dsp_features);
06668    }
06669 }
06670 
06671 static void enable_dtmf_detect(struct dahdi_pvt *p)
06672 {
06673    int val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
06674 
06675    if (p->channel == CHAN_PSEUDO)
06676       return;
06677 
06678    p->ignoredtmf = 0;
06679 
06680    ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
06681 
06682    if (!p->hardwaredtmf && p->dsp) {
06683       p->dsp_features |= DSP_FEATURE_DIGIT_DETECT;
06684       ast_dsp_set_features(p->dsp, p->dsp_features);
06685    }
06686 }
06687 
06688 static int dahdi_queryoption(struct ast_channel *chan, int option, void *data, int *datalen)
06689 {
06690    char *cp;
06691    struct dahdi_pvt *p = chan->tech_pvt;
06692 
06693    /* all supported options require data */
06694    if (!p || !data || (*datalen < 1)) {
06695       errno = EINVAL;
06696       return -1;
06697    }
06698 
06699    switch (option) {
06700    case AST_OPTION_DIGIT_DETECT:
06701       cp = (char *) data;
06702       *cp = p->ignoredtmf ? 0 : 1;
06703       ast_debug(1, "Reporting digit detection %sabled on %s\n", *cp ? "en" : "dis", chan->name);
06704       break;
06705    case AST_OPTION_FAX_DETECT:
06706       cp = (char *) data;
06707       *cp = (p->dsp_features & DSP_FEATURE_FAX_DETECT) ? 0 : 1;
06708       ast_debug(1, "Reporting fax tone detection %sabled on %s\n", *cp ? "en" : "dis", chan->name);
06709       break;
06710    case AST_OPTION_CC_AGENT_TYPE:
06711 #if defined(HAVE_PRI)
06712 #if defined(HAVE_PRI_CCSS)
06713       if (dahdi_sig_pri_lib_handles(p->sig)) {
06714          ast_copy_string((char *) data, dahdi_pri_cc_type, *datalen);
06715          break;
06716       }
06717 #endif   /* defined(HAVE_PRI_CCSS) */
06718 #endif   /* defined(HAVE_PRI) */
06719       return -1;
06720    default:
06721       return -1;
06722    }
06723 
06724    errno = 0;
06725 
06726    return 0;
06727 }
06728 
06729 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen)
06730 {
06731    char *cp;
06732    signed char *scp;
06733    int x;
06734    int idx;
06735    struct dahdi_pvt *p = chan->tech_pvt, *pp;
06736    struct oprmode *oprmode;
06737 
06738 
06739    /* all supported options require data */
06740    if (!p || !data || (datalen < 1)) {
06741       errno = EINVAL;
06742       return -1;
06743    }
06744 
06745    switch (option) {
06746    case AST_OPTION_TXGAIN:
06747       scp = (signed char *) data;
06748       idx = dahdi_get_index(chan, p, 0);
06749       if (idx < 0) {
06750          ast_log(LOG_WARNING, "No index in TXGAIN?\n");
06751          return -1;
06752       }
06753       ast_debug(1, "Setting actual tx gain on %s to %f\n", chan->name, p->txgain + (float) *scp);
06754       return set_actual_txgain(p->subs[idx].dfd, p->txgain + (float) *scp, p->txdrc, p->law);
06755    case AST_OPTION_RXGAIN:
06756       scp = (signed char *) data;
06757       idx = dahdi_get_index(chan, p, 0);
06758       if (idx < 0) {
06759          ast_log(LOG_WARNING, "No index in RXGAIN?\n");
06760          return -1;
06761       }
06762       ast_debug(1, "Setting actual rx gain on %s to %f\n", chan->name, p->rxgain + (float) *scp);
06763       return set_actual_rxgain(p->subs[idx].dfd, p->rxgain + (float) *scp, p->rxdrc, p->law);
06764    case AST_OPTION_TONE_VERIFY:
06765       if (!p->dsp)
06766          break;
06767       cp = (char *) data;
06768       switch (*cp) {
06769       case 1:
06770          ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",chan->name);
06771          ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | p->dtmfrelax);  /* set mute mode if desired */
06772          break;
06773       case 2:
06774          ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",chan->name);
06775          ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX | p->dtmfrelax);  /* set mute mode if desired */
06776          break;
06777       default:
06778          ast_debug(1, "Set option TONE VERIFY, mode: OFF(0) on %s\n",chan->name);
06779          ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);  /* set mute mode if desired */
06780          break;
06781       }
06782       break;
06783    case AST_OPTION_TDD:
06784       /* turn on or off TDD */
06785       cp = (char *) data;
06786       p->mate = 0;
06787       if (!*cp) { /* turn it off */
06788          ast_debug(1, "Set option TDD MODE, value: OFF(0) on %s\n",chan->name);
06789          if (p->tdd)
06790             tdd_free(p->tdd);
06791          p->tdd = 0;
06792          break;
06793       }
06794       ast_debug(1, "Set option TDD MODE, value: %s(%d) on %s\n",
06795          (*cp == 2) ? "MATE" : "ON", (int) *cp, chan->name);
06796       dahdi_disable_ec(p);
06797       /* otherwise, turn it on */
06798       if (!p->didtdd) { /* if havent done it yet */
06799          unsigned char mybuf[41000];/*! \todo XXX This is an abuse of the stack!! */
06800          unsigned char *buf;
06801          int size, res, fd, len;
06802          struct pollfd fds[1];
06803 
06804          buf = mybuf;
06805          memset(buf, 0x7f, sizeof(mybuf)); /* set to silence */
06806          ast_tdd_gen_ecdisa(buf + 16000, 16000);  /* put in tone */
06807          len = 40000;
06808          idx = dahdi_get_index(chan, p, 0);
06809          if (idx < 0) {
06810             ast_log(LOG_WARNING, "No index in TDD?\n");
06811             return -1;
06812          }
06813          fd = p->subs[idx].dfd;
06814          while (len) {
06815             if (ast_check_hangup(chan))
06816                return -1;
06817             size = len;
06818             if (size > READ_SIZE)
06819                size = READ_SIZE;
06820             fds[0].fd = fd;
06821             fds[0].events = POLLPRI | POLLOUT;
06822             fds[0].revents = 0;
06823             res = poll(fds, 1, -1);
06824             if (!res) {
06825                ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
06826                continue;
06827             }
06828             /* if got exception */
06829             if (fds[0].revents & POLLPRI)
06830                return -1;
06831             if (!(fds[0].revents & POLLOUT)) {
06832                ast_debug(1, "write fd not ready on channel %d\n", p->channel);
06833                continue;
06834             }
06835             res = write(fd, buf, size);
06836             if (res != size) {
06837                if (res == -1) return -1;
06838                ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
06839                break;
06840             }
06841             len -= size;
06842             buf += size;
06843          }
06844          p->didtdd = 1; /* set to have done it now */
06845       }
06846       if (*cp == 2) { /* Mate mode */
06847          if (p->tdd)
06848             tdd_free(p->tdd);
06849          p->tdd = 0;
06850          p->mate = 1;
06851          break;
06852       }
06853       if (!p->tdd) { /* if we don't have one yet */
06854          p->tdd = tdd_new(); /* allocate one */
06855       }
06856       break;
06857    case AST_OPTION_RELAXDTMF:  /* Relax DTMF decoding (or not) */
06858       if (!p->dsp)
06859          break;
06860       cp = (char *) data;
06861       ast_debug(1, "Set option RELAX DTMF, value: %s(%d) on %s\n",
06862          *cp ? "ON" : "OFF", (int) *cp, chan->name);
06863       ast_dsp_set_digitmode(p->dsp, ((*cp) ? DSP_DIGITMODE_RELAXDTMF : DSP_DIGITMODE_DTMF) | p->dtmfrelax);
06864       break;
06865    case AST_OPTION_AUDIO_MODE:  /* Set AUDIO mode (or not) */
06866 #if defined(HAVE_PRI)
06867       if (dahdi_sig_pri_lib_handles(p->sig)
06868          && ((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
06869          /* PRI nobch pseudo channel.  Does not handle ioctl(DAHDI_AUDIOMODE) */
06870          break;
06871       }
06872 #endif   /* defined(HAVE_PRI) */
06873 
06874       cp = (char *) data;
06875       if (!*cp) {
06876          ast_debug(1, "Set option AUDIO MODE, value: OFF(0) on %s\n", chan->name);
06877          x = 0;
06878          dahdi_disable_ec(p);
06879       } else {
06880          ast_debug(1, "Set option AUDIO MODE, value: ON(1) on %s\n", chan->name);
06881          x = 1;
06882       }
06883       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x) == -1)
06884          ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, x, strerror(errno));
06885       break;
06886    case AST_OPTION_OPRMODE:  /* Operator services mode */
06887       oprmode = (struct oprmode *) data;
06888       /* We don't support operator mode across technologies */
06889       if (strcasecmp(chan->tech->type, oprmode->peer->tech->type)) {
06890          ast_log(LOG_NOTICE, "Operator mode not supported on %s to %s calls.\n",
06891                chan->tech->type, oprmode->peer->tech->type);
06892          errno = EINVAL;
06893          return -1;
06894       }
06895       pp = oprmode->peer->tech_pvt;
06896       p->oprmode = pp->oprmode = 0;
06897       /* setup peers */
06898       p->oprpeer = pp;
06899       pp->oprpeer = p;
06900       /* setup modes, if any */
06901       if (oprmode->mode)
06902       {
06903          pp->oprmode = oprmode->mode;
06904          p->oprmode = -oprmode->mode;
06905       }
06906       ast_debug(1, "Set Operator Services mode, value: %d on %s/%s\n",
06907          oprmode->mode, chan->name,oprmode->peer->name);
06908       break;
06909    case AST_OPTION_ECHOCAN:
06910       cp = (char *) data;
06911       if (*cp) {
06912          ast_debug(1, "Enabling echo cancellation on %s\n", chan->name);
06913          dahdi_enable_ec(p);
06914       } else {
06915          ast_debug(1, "Disabling echo cancellation on %s\n", chan->name);
06916          dahdi_disable_ec(p);
06917       }
06918       break;
06919    case AST_OPTION_DIGIT_DETECT:
06920       cp = (char *) data;
06921       ast_debug(1, "%sabling digit detection on %s\n", *cp ? "En" : "Dis", chan->name);
06922       if (*cp) {
06923          enable_dtmf_detect(p);
06924       } else {
06925          disable_dtmf_detect(p);
06926       }
06927       break;
06928    case AST_OPTION_FAX_DETECT:
06929       cp = (char *) data;
06930       if (p->dsp) {
06931          ast_debug(1, "%sabling fax tone detection on %s\n", *cp ? "En" : "Dis", chan->name);
06932          if (*cp) {
06933             p->dsp_features |= DSP_FEATURE_FAX_DETECT;
06934          } else {
06935             p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
06936          }
06937          ast_dsp_set_features(p->dsp, p->dsp_features);
06938       }
06939       break;
06940    default:
06941       return -1;
06942    }
06943    errno = 0;
06944 
06945    return 0;
06946 }
06947 
06948 static int dahdi_func_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len)
06949 {
06950    struct dahdi_pvt *p = chan->tech_pvt;
06951    int res = 0;
06952 
06953    if (!p) {
06954       /* No private structure! */
06955       *buf = '\0';
06956       return -1;
06957    }
06958 
06959    if (!strcasecmp(data, "rxgain")) {
06960       ast_mutex_lock(&p->lock);
06961       snprintf(buf, len, "%f", p->rxgain);
06962       ast_mutex_unlock(&p->lock);
06963    } else if (!strcasecmp(data, "txgain")) {
06964       ast_mutex_lock(&p->lock);
06965       snprintf(buf, len, "%f", p->txgain);
06966       ast_mutex_unlock(&p->lock);
06967    } else if (!strcasecmp(data, "dahdi_channel")) {
06968       ast_mutex_lock(&p->lock);
06969       snprintf(buf, len, "%d", p->channel);
06970       ast_mutex_unlock(&p->lock);
06971    } else if (!strcasecmp(data, "dahdi_span")) {
06972       ast_mutex_lock(&p->lock);
06973       snprintf(buf, len, "%d", p->span);
06974       ast_mutex_unlock(&p->lock);
06975    } else if (!strcasecmp(data, "dahdi_type")) {
06976       ast_mutex_lock(&p->lock);
06977       switch (p->sig) {
06978 #if defined(HAVE_OPENR2)
06979       case SIG_MFCR2:
06980          ast_copy_string(buf, "mfc/r2", len);
06981          break;
06982 #endif   /* defined(HAVE_OPENR2) */
06983 #if defined(HAVE_PRI)
06984       case SIG_PRI_LIB_HANDLE_CASES:
06985          ast_copy_string(buf, "pri", len);
06986          break;
06987 #endif   /* defined(HAVE_PRI) */
06988       case 0:
06989          ast_copy_string(buf, "pseudo", len);
06990          break;
06991 #if defined(HAVE_SS7)
06992       case SIG_SS7:
06993          ast_copy_string(buf, "ss7", len);
06994          break;
06995 #endif   /* defined(HAVE_SS7) */
06996       default:
06997          /* The only thing left is analog ports. */
06998          ast_copy_string(buf, "analog", len);
06999          break;
07000       }
07001       ast_mutex_unlock(&p->lock);
07002 #if defined(HAVE_PRI)
07003 #if defined(HAVE_PRI_REVERSE_CHARGE)
07004    } else if (!strcasecmp(data, "reversecharge")) {
07005       ast_mutex_lock(&p->lock);
07006       switch (p->sig) {
07007       case SIG_PRI_LIB_HANDLE_CASES:
07008          snprintf(buf, len, "%d", ((struct sig_pri_chan *) p->sig_pvt)->reverse_charging_indication);
07009          break;
07010       default:
07011          *buf = '\0';
07012          res = -1;
07013          break;
07014       }
07015       ast_mutex_unlock(&p->lock);
07016 #endif
07017 #if defined(HAVE_PRI_SETUP_KEYPAD)
07018    } else if (!strcasecmp(data, "keypad_digits")) {
07019       ast_mutex_lock(&p->lock);
07020       switch (p->sig) {
07021       case SIG_PRI_LIB_HANDLE_CASES:
07022          ast_copy_string(buf, ((struct sig_pri_chan *) p->sig_pvt)->keypad_digits,
07023             len);
07024          break;
07025       default:
07026          *buf = '\0';
07027          res = -1;
07028          break;
07029       }
07030       ast_mutex_unlock(&p->lock);
07031 #endif   /* defined(HAVE_PRI_SETUP_KEYPAD) */
07032    } else if (!strcasecmp(data, "no_media_path")) {
07033       ast_mutex_lock(&p->lock);
07034       switch (p->sig) {
07035       case SIG_PRI_LIB_HANDLE_CASES:
07036          /*
07037           * TRUE if the call is on hold or is call waiting because
07038           * there is no media path available.
07039           */
07040          snprintf(buf, len, "%d", ((struct sig_pri_chan *) p->sig_pvt)->no_b_channel);
07041          break;
07042       default:
07043          *buf = '\0';
07044          res = -1;
07045          break;
07046       }
07047       ast_mutex_unlock(&p->lock);
07048 #endif   /* defined(HAVE_PRI) */
07049    } else {
07050       *buf = '\0';
07051       res = -1;
07052    }
07053 
07054    return res;
07055 }
07056 
07057 
07058 static int parse_buffers_policy(const char *parse, int *num_buffers, int *policy)
07059 {
07060    int res;
07061    char policy_str[21] = "";
07062 
07063    if ((res = sscanf(parse, "%30d,%20s", num_buffers, policy_str)) != 2) {
07064       ast_log(LOG_WARNING, "Parsing buffer string '%s' failed.\n", parse);
07065       return 1;
07066    }
07067    if (*num_buffers < 0) {
07068       ast_log(LOG_WARNING, "Invalid buffer count given '%d'.\n", *num_buffers);
07069       return -1;
07070    }
07071    if (!strcasecmp(policy_str, "full")) {
07072       *policy = DAHDI_POLICY_WHEN_FULL;
07073    } else if (!strcasecmp(policy_str, "immediate")) {
07074       *policy = DAHDI_POLICY_IMMEDIATE;
07075 #if defined(HAVE_DAHDI_HALF_FULL)
07076    } else if (!strcasecmp(policy_str, "half")) {
07077       *policy = DAHDI_POLICY_HALF_FULL;
07078 #endif
07079    } else {
07080       ast_log(LOG_WARNING, "Invalid policy name given '%s'.\n", policy_str);
07081       return -1;
07082    }
07083 
07084    return 0;
07085 }
07086 
07087 static int dahdi_func_write(struct ast_channel *chan, const char *function, char *data, const char *value)
07088 {
07089    struct dahdi_pvt *p = chan->tech_pvt;
07090    int res = 0;
07091 
07092    if (!p) {
07093       /* No private structure! */
07094       return -1;
07095    }
07096 
07097    if (!strcasecmp(data, "buffers")) {
07098       int num_bufs, policy;
07099 
07100       if (!(parse_buffers_policy(value, &num_bufs, &policy))) {
07101          struct dahdi_bufferinfo bi = {
07102             .txbufpolicy = policy,
07103             .rxbufpolicy = policy,
07104             .bufsize = p->bufsize,
07105             .numbufs = num_bufs,
07106          };
07107          int bpres;
07108 
07109          if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
07110             ast_log(LOG_WARNING, "Channel '%d' unable to override buffer policy: %s\n", p->channel, strerror(errno));
07111          } else {
07112             p->bufferoverrideinuse = 1;
07113          }
07114       } else {
07115          res = -1;
07116       }
07117    } else if (!strcasecmp(data, "echocan_mode")) {
07118       if (!strcasecmp(value, "on")) {
07119          ast_mutex_lock(&p->lock);
07120          dahdi_enable_ec(p);
07121          ast_mutex_unlock(&p->lock);
07122       } else if (!strcasecmp(value, "off")) {
07123          ast_mutex_lock(&p->lock);
07124          dahdi_disable_ec(p);
07125          ast_mutex_unlock(&p->lock);
07126 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
07127       } else if (!strcasecmp(value, "fax")) {
07128          int blah = 1;
07129 
07130          ast_mutex_lock(&p->lock);
07131          if (!p->echocanon) {
07132             dahdi_enable_ec(p);
07133          }
07134          if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_FAX_MODE, &blah)) {
07135             ast_log(LOG_WARNING, "Unable to place echocan into fax mode on channel %d: %s\n", p->channel, strerror(errno));
07136          }
07137          ast_mutex_unlock(&p->lock);
07138       } else if (!strcasecmp(value, "voice")) {
07139          int blah = 0;
07140 
07141          ast_mutex_lock(&p->lock);
07142          if (!p->echocanon) {
07143             dahdi_enable_ec(p);
07144          }
07145          if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_FAX_MODE, &blah)) {
07146             ast_log(LOG_WARNING, "Unable to place echocan into voice mode on channel %d: %s\n", p->channel, strerror(errno));
07147          }
07148          ast_mutex_unlock(&p->lock);
07149 #endif
07150       } else {
07151          ast_log(LOG_WARNING, "Unsupported value '%s' provided for '%s' item.\n", value, data);
07152          res = -1;
07153       }
07154    } else {
07155       res = -1;
07156    }
07157 
07158    return res;
07159 }
07160 
07161 static void dahdi_unlink(struct dahdi_pvt *slave, struct dahdi_pvt *master, int needlock)
07162 {
07163    /* Unlink a specific slave or all slaves/masters from a given master */
07164    int x;
07165    int hasslaves;
07166    if (!master)
07167       return;
07168    if (needlock) {
07169       ast_mutex_lock(&master->lock);
07170       if (slave) {
07171          while (ast_mutex_trylock(&slave->lock)) {
07172             DEADLOCK_AVOIDANCE(&master->lock);
07173          }
07174       }
07175    }
07176    hasslaves = 0;
07177    for (x = 0; x < MAX_SLAVES; x++) {
07178       if (master->slaves[x]) {
07179          if (!slave || (master->slaves[x] == slave)) {
07180             /* Take slave out of the conference */
07181             ast_debug(1, "Unlinking slave %d from %d\n", master->slaves[x]->channel, master->channel);
07182             conf_del(master, &master->slaves[x]->subs[SUB_REAL], SUB_REAL);
07183             conf_del(master->slaves[x], &master->subs[SUB_REAL], SUB_REAL);
07184             master->slaves[x]->master = NULL;
07185             master->slaves[x] = NULL;
07186          } else
07187             hasslaves = 1;
07188       }
07189       if (!hasslaves)
07190          master->inconference = 0;
07191    }
07192    if (!slave) {
07193       if (master->master) {
07194          /* Take master out of the conference */
07195          conf_del(master->master, &master->subs[SUB_REAL], SUB_REAL);
07196          conf_del(master, &master->master->subs[SUB_REAL], SUB_REAL);
07197          hasslaves = 0;
07198          for (x = 0; x < MAX_SLAVES; x++) {
07199             if (master->master->slaves[x] == master)
07200                master->master->slaves[x] = NULL;
07201             else if (master->master->slaves[x])
07202                hasslaves = 1;
07203          }
07204          if (!hasslaves)
07205             master->master->inconference = 0;
07206       }
07207       master->master = NULL;
07208    }
07209    update_conf(master);
07210    if (needlock) {
07211       if (slave)
07212          ast_mutex_unlock(&slave->lock);
07213       ast_mutex_unlock(&master->lock);
07214    }
07215 }
07216 
07217 static void dahdi_link(struct dahdi_pvt *slave, struct dahdi_pvt *master) {
07218    int x;
07219    if (!slave || !master) {
07220       ast_log(LOG_WARNING, "Tried to link to/from NULL??\n");
07221       return;
07222    }
07223    for (x = 0; x < MAX_SLAVES; x++) {
07224       if (!master->slaves[x]) {
07225          master->slaves[x] = slave;
07226          break;
07227       }
07228    }
07229    if (x >= MAX_SLAVES) {
07230       ast_log(LOG_WARNING, "Replacing slave %d with new slave, %d\n", master->slaves[MAX_SLAVES - 1]->channel, slave->channel);
07231       master->slaves[MAX_SLAVES - 1] = slave;
07232    }
07233    if (slave->master)
07234       ast_log(LOG_WARNING, "Replacing master %d with new master, %d\n", slave->master->channel, master->channel);
07235    slave->master = master;
07236 
07237    ast_debug(1, "Making %d slave to master %d at %d\n", slave->channel, master->channel, x);
07238 }
07239 
07240 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)
07241 {
07242    struct ast_channel *who;
07243    struct dahdi_pvt *p0, *p1, *op0, *op1;
07244    struct dahdi_pvt *master = NULL, *slave = NULL;
07245    struct ast_frame *f;
07246    int inconf = 0;
07247    int nothingok = 1;
07248    int ofd0, ofd1;
07249    int oi0, oi1, i0 = -1, i1 = -1, t0, t1;
07250    int os0 = -1, os1 = -1;
07251    int priority = 0;
07252    struct ast_channel *oc0, *oc1;
07253    enum ast_bridge_result res;
07254    struct timeval start = ast_tvnow();
07255 #ifdef PRI_2BCT
07256    int triedtopribridge = 0;
07257    q931_call *q931c0;
07258    q931_call *q931c1;
07259 #endif
07260 
07261    /* For now, don't attempt to native bridge if either channel needs DTMF detection.
07262       There is code below to handle it properly until DTMF is actually seen,
07263       but due to currently unresolved issues it's ignored...
07264    */
07265 
07266    if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1))
07267       return AST_BRIDGE_FAILED_NOWARN;
07268 
07269    ast_channel_lock(c0);
07270    while (ast_channel_trylock(c1)) {
07271       CHANNEL_DEADLOCK_AVOIDANCE(c0);
07272    }
07273 
07274    p0 = c0->tech_pvt;
07275    p1 = c1->tech_pvt;
07276    /* cant do pseudo-channels here */
07277    if (!p0 || (!p0->sig) || !p1 || (!p1->sig)) {
07278       ast_channel_unlock(c0);
07279       ast_channel_unlock(c1);
07280       return AST_BRIDGE_FAILED_NOWARN;
07281    }
07282 
07283    oi0 = dahdi_get_index(c0, p0, 0);
07284    oi1 = dahdi_get_index(c1, p1, 0);
07285    if ((oi0 < 0) || (oi1 < 0)) {
07286       ast_channel_unlock(c0);
07287       ast_channel_unlock(c1);
07288       return AST_BRIDGE_FAILED;
07289    }
07290 
07291    op0 = p0 = c0->tech_pvt;
07292    op1 = p1 = c1->tech_pvt;
07293    ofd0 = c0->fds[0];
07294    ofd1 = c1->fds[0];
07295    oc0 = p0->owner;
07296    oc1 = p1->owner;
07297 
07298    if (ast_mutex_trylock(&p0->lock)) {
07299       /* Don't block, due to potential for deadlock */
07300       ast_channel_unlock(c0);
07301       ast_channel_unlock(c1);
07302       ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
07303       return AST_BRIDGE_RETRY;
07304    }
07305    if (ast_mutex_trylock(&p1->lock)) {
07306       /* Don't block, due to potential for deadlock */
07307       ast_mutex_unlock(&p0->lock);
07308       ast_channel_unlock(c0);
07309       ast_channel_unlock(c1);
07310       ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
07311       return AST_BRIDGE_RETRY;
07312    }
07313 
07314    if ((p0->callwaiting && p0->callwaitingcallerid)
07315       || (p1->callwaiting && p1->callwaitingcallerid)) {
07316       /*
07317        * Call Waiting Caller ID requires DTMF detection to know if it
07318        * can send the CID spill.
07319        *
07320        * For now, don't attempt to native bridge if either channel
07321        * needs DTMF detection.  There is code below to handle it
07322        * properly until DTMF is actually seen, but due to currently
07323        * unresolved issues it's ignored...
07324        */
07325       ast_mutex_unlock(&p0->lock);
07326       ast_mutex_unlock(&p1->lock);
07327       ast_channel_unlock(c0);
07328       ast_channel_unlock(c1);
07329       return AST_BRIDGE_FAILED_NOWARN;
07330    }
07331 
07332 #if defined(HAVE_PRI)
07333    if ((dahdi_sig_pri_lib_handles(p0->sig)
07334          && ((struct sig_pri_chan *) p0->sig_pvt)->no_b_channel)
07335       || (dahdi_sig_pri_lib_handles(p1->sig)
07336          && ((struct sig_pri_chan *) p1->sig_pvt)->no_b_channel)) {
07337       /*
07338        * PRI nobch channels (hold and call waiting) are equivalent to
07339        * pseudo channels and cannot be done here.
07340        */
07341       ast_mutex_unlock(&p0->lock);
07342       ast_mutex_unlock(&p1->lock);
07343       ast_channel_unlock(c0);
07344       ast_channel_unlock(c1);
07345       return AST_BRIDGE_FAILED_NOWARN;
07346    }
07347 #endif   /* defined(HAVE_PRI) */
07348 
07349    if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
07350       if (p0->owner && p1->owner) {
07351          /* If we don't have a call-wait in a 3-way, and we aren't in a 3-way, we can be master */
07352          if (!p0->subs[SUB_CALLWAIT].inthreeway && !p1->subs[SUB_REAL].inthreeway) {
07353             master = p0;
07354             slave = p1;
07355             inconf = 1;
07356          } else if (!p1->subs[SUB_CALLWAIT].inthreeway && !p0->subs[SUB_REAL].inthreeway) {
07357             master = p1;
07358             slave = p0;
07359             inconf = 1;
07360          } else {
07361             ast_log(LOG_WARNING, "Huh?  Both calls are callwaits or 3-ways?  That's clever...?\n");
07362             ast_log(LOG_WARNING, "p0: chan %d/%d/CW%d/3W%d, p1: chan %d/%d/CW%d/3W%d\n",
07363                p0->channel,
07364                oi0, (p0->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
07365                p0->subs[SUB_REAL].inthreeway, p0->channel,
07366                oi0, (p1->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
07367                p1->subs[SUB_REAL].inthreeway);
07368          }
07369          nothingok = 0;
07370       }
07371    } else if ((oi0 == SUB_REAL) && (oi1 == SUB_THREEWAY)) {
07372       if (p1->subs[SUB_THREEWAY].inthreeway) {
07373          master = p1;
07374          slave = p0;
07375          nothingok = 0;
07376       }
07377    } else if ((oi0 == SUB_THREEWAY) && (oi1 == SUB_REAL)) {
07378       if (p0->subs[SUB_THREEWAY].inthreeway) {
07379          master = p0;
07380          slave = p1;
07381          nothingok = 0;
07382       }
07383    } else if ((oi0 == SUB_REAL) && (oi1 == SUB_CALLWAIT)) {
07384       /* We have a real and a call wait.  If we're in a three way call, put us in it, otherwise,
07385          don't put us in anything */
07386       if (p1->subs[SUB_CALLWAIT].inthreeway) {
07387          master = p1;
07388          slave = p0;
07389          nothingok = 0;
07390       }
07391    } else if ((oi0 == SUB_CALLWAIT) && (oi1 == SUB_REAL)) {
07392       /* Same as previous */
07393       if (p0->subs[SUB_CALLWAIT].inthreeway) {
07394          master = p0;
07395          slave = p1;
07396          nothingok = 0;
07397       }
07398    }
07399    ast_debug(1, "master: %d, slave: %d, nothingok: %d\n",
07400       master ? master->channel : 0, slave ? slave->channel : 0, nothingok);
07401    if (master && slave) {
07402       /* Stop any tones, or play ringtone as appropriate.  If they're bridged
07403          in an active threeway call with a channel that is ringing, we should
07404          indicate ringing. */
07405       if ((oi1 == SUB_THREEWAY) &&
07406          p1->subs[SUB_THREEWAY].inthreeway &&
07407          p1->subs[SUB_REAL].owner &&
07408          p1->subs[SUB_REAL].inthreeway &&
07409          (p1->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
07410          ast_debug(1,
07411             "Playing ringback on %d/%d(%s) since %d/%d(%s) is in a ringing three-way\n",
07412             p0->channel, oi0, c0->name, p1->channel, oi1, c1->name);
07413          tone_zone_play_tone(p0->subs[oi0].dfd, DAHDI_TONE_RINGTONE);
07414          os1 = p1->subs[SUB_REAL].owner->_state;
07415       } else {
07416          ast_debug(1, "Stopping tones on %d/%d(%s) talking to %d/%d(%s)\n",
07417             p0->channel, oi0, c0->name, p1->channel, oi1, c1->name);
07418          tone_zone_play_tone(p0->subs[oi0].dfd, -1);
07419       }
07420       if ((oi0 == SUB_THREEWAY) &&
07421          p0->subs[SUB_THREEWAY].inthreeway &&
07422          p0->subs[SUB_REAL].owner &&
07423          p0->subs[SUB_REAL].inthreeway &&
07424          (p0->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
07425          ast_debug(1,
07426             "Playing ringback on %d/%d(%s) since %d/%d(%s) is in a ringing three-way\n",
07427             p1->channel, oi1, c1->name, p0->channel, oi0, c0->name);
07428          tone_zone_play_tone(p1->subs[oi1].dfd, DAHDI_TONE_RINGTONE);
07429          os0 = p0->subs[SUB_REAL].owner->_state;
07430       } else {
07431          ast_debug(1, "Stopping tones on %d/%d(%s) talking to %d/%d(%s)\n",
07432             p1->channel, oi1, c1->name, p0->channel, oi0, c0->name);
07433          tone_zone_play_tone(p1->subs[oi1].dfd, -1);
07434       }
07435       if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
07436          if (!p0->echocanbridged || !p1->echocanbridged) {
07437             /* Disable echo cancellation if appropriate */
07438             dahdi_disable_ec(p0);
07439             dahdi_disable_ec(p1);
07440          }
07441       }
07442       dahdi_link(slave, master);
07443       master->inconference = inconf;
07444    } else if (!nothingok)
07445       ast_log(LOG_WARNING, "Can't link %d/%s with %d/%s\n", p0->channel, subnames[oi0], p1->channel, subnames[oi1]);
07446 
07447    update_conf(p0);
07448    update_conf(p1);
07449    t0 = p0->subs[SUB_REAL].inthreeway;
07450    t1 = p1->subs[SUB_REAL].inthreeway;
07451 
07452    ast_mutex_unlock(&p0->lock);
07453    ast_mutex_unlock(&p1->lock);
07454 
07455    ast_channel_unlock(c0);
07456    ast_channel_unlock(c1);
07457 
07458    /* Native bridge failed */
07459    if ((!master || !slave) && !nothingok) {
07460       dahdi_enable_ec(p0);
07461       dahdi_enable_ec(p1);
07462       return AST_BRIDGE_FAILED;
07463    }
07464 
07465    ast_verb(3, "Native bridging %s and %s\n", c0->name, c1->name);
07466 
07467    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
07468       disable_dtmf_detect(op0);
07469 
07470    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
07471       disable_dtmf_detect(op1);
07472 
07473    for (;;) {
07474       struct ast_channel *c0_priority[2] = {c0, c1};
07475       struct ast_channel *c1_priority[2] = {c1, c0};
07476       int ms;
07477 
07478       /* Here's our main loop...  Start by locking things, looking for private parts,
07479          and then balking if anything is wrong */
07480 
07481       ast_channel_lock(c0);
07482       while (ast_channel_trylock(c1)) {
07483          CHANNEL_DEADLOCK_AVOIDANCE(c0);
07484       }
07485 
07486       p0 = c0->tech_pvt;
07487       p1 = c1->tech_pvt;
07488 
07489       if (op0 == p0)
07490          i0 = dahdi_get_index(c0, p0, 1);
07491       if (op1 == p1)
07492          i1 = dahdi_get_index(c1, p1, 1);
07493 
07494       ast_channel_unlock(c0);
07495       ast_channel_unlock(c1);
07496       ms = ast_remaining_ms(start, timeoutms);
07497       if (!ms ||
07498          (op0 != p0) ||
07499          (op1 != p1) ||
07500          (ofd0 != c0->fds[0]) ||
07501          (ofd1 != c1->fds[0]) ||
07502          (p0->subs[SUB_REAL].owner && (os0 > -1) && (os0 != p0->subs[SUB_REAL].owner->_state)) ||
07503          (p1->subs[SUB_REAL].owner && (os1 > -1) && (os1 != p1->subs[SUB_REAL].owner->_state)) ||
07504          (oc0 != p0->owner) ||
07505          (oc1 != p1->owner) ||
07506          (t0 != p0->subs[SUB_REAL].inthreeway) ||
07507          (t1 != p1->subs[SUB_REAL].inthreeway) ||
07508          (oi0 != i0) ||
07509          (oi1 != i1)) {
07510          ast_debug(1, "Something changed out on %d/%d to %d/%d, returning -3 to restart\n",
07511             op0->channel, oi0, op1->channel, oi1);
07512          res = AST_BRIDGE_RETRY;
07513          goto return_from_bridge;
07514       }
07515 
07516 #ifdef PRI_2BCT
07517       if (!triedtopribridge) {
07518          triedtopribridge = 1;
07519          if (p0->pri && p0->pri == p1->pri && p0->pri->transfer) {
07520             ast_mutex_lock(&p0->pri->lock);
07521             switch (p0->sig) {
07522             case SIG_PRI_LIB_HANDLE_CASES:
07523                q931c0 = ((struct sig_pri_chan *) (p0->sig_pvt))->call;
07524                break;
07525             default:
07526                q931c0 = NULL;
07527                break;
07528             }
07529             switch (p1->sig) {
07530             case SIG_PRI_LIB_HANDLE_CASES:
07531                q931c1 = ((struct sig_pri_chan *) (p1->sig_pvt))->call;
07532                break;
07533             default:
07534                q931c1 = NULL;
07535                break;
07536             }
07537             if (q931c0 && q931c1) {
07538                pri_channel_bridge(q931c0, q931c1);
07539             }
07540             ast_mutex_unlock(&p0->pri->lock);
07541          }
07542       }
07543 #endif
07544 
07545       who = ast_waitfor_n(priority ? c0_priority : c1_priority, 2, &ms);
07546       if (!who) {
07547          ast_debug(1, "Ooh, empty read...\n");
07548          continue;
07549       }
07550       f = ast_read(who);
07551       if (!f || (f->frametype == AST_FRAME_CONTROL)) {
07552          *fo = f;
07553          *rc = who;
07554          res = AST_BRIDGE_COMPLETE;
07555          goto return_from_bridge;
07556       }
07557       if (f->frametype == AST_FRAME_DTMF) {
07558          if ((who == c0) && p0->pulsedial) {
07559             ast_write(c1, f);
07560          } else if ((who == c1) && p1->pulsedial) {
07561             ast_write(c0, f);
07562          } else {
07563             *fo = f;
07564             *rc = who;
07565             res = AST_BRIDGE_COMPLETE;
07566             goto return_from_bridge;
07567          }
07568       }
07569       ast_frfree(f);
07570 
07571       /* Swap who gets priority */
07572       priority = !priority;
07573    }
07574 
07575 return_from_bridge:
07576    if (op0 == p0)
07577       dahdi_enable_ec(p0);
07578 
07579    if (op1 == p1)
07580       dahdi_enable_ec(p1);
07581 
07582    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
07583       enable_dtmf_detect(op0);
07584 
07585    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
07586       enable_dtmf_detect(op1);
07587 
07588    dahdi_unlink(slave, master, 1);
07589 
07590    return res;
07591 }
07592 
07593 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
07594 {
07595    struct dahdi_pvt *p = newchan->tech_pvt;
07596    int x;
07597 
07598    ast_mutex_lock(&p->lock);
07599 
07600    ast_debug(1, "New owner for channel %d is %s\n", p->channel, newchan->name);
07601    if (p->owner == oldchan) {
07602       p->owner = newchan;
07603    }
07604    for (x = 0; x < 3; x++) {
07605       if (p->subs[x].owner == oldchan) {
07606          if (!x) {
07607             dahdi_unlink(NULL, p, 0);
07608          }
07609          p->subs[x].owner = newchan;
07610       }
07611    }
07612    if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
07613       analog_fixup(oldchan, newchan, p->sig_pvt);
07614 #if defined(HAVE_PRI)
07615    } else if (dahdi_sig_pri_lib_handles(p->sig)) {
07616       sig_pri_fixup(oldchan, newchan, p->sig_pvt);
07617 #endif   /* defined(HAVE_PRI) */
07618 #if defined(HAVE_SS7)
07619    } else if (p->sig == SIG_SS7) {
07620       sig_ss7_fixup(oldchan, newchan, p->sig_pvt);
07621 #endif   /* defined(HAVE_SS7) */
07622    }
07623    update_conf(p);
07624 
07625    ast_mutex_unlock(&p->lock);
07626 
07627    if (newchan->_state == AST_STATE_RINGING) {
07628       dahdi_indicate(newchan, AST_CONTROL_RINGING, NULL, 0);
07629    }
07630    return 0;
07631 }
07632 
07633 static int dahdi_ring_phone(struct dahdi_pvt *p)
07634 {
07635    int x;
07636    int res;
07637    /* Make sure our transmit state is on hook */
07638    x = 0;
07639    x = DAHDI_ONHOOK;
07640    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
07641    do {
07642       x = DAHDI_RING;
07643       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
07644       if (res) {
07645          switch (errno) {
07646          case EBUSY:
07647          case EINTR:
07648             /* Wait just in case */
07649             usleep(10000);
07650             continue;
07651          case EINPROGRESS:
07652             res = 0;
07653             break;
07654          default:
07655             ast_log(LOG_WARNING, "Couldn't ring the phone: %s\n", strerror(errno));
07656             res = 0;
07657          }
07658       }
07659    } while (res);
07660    return res;
07661 }
07662 
07663 static void *analog_ss_thread(void *data);
07664 
07665 static int attempt_transfer(struct dahdi_pvt *p)
07666 {
07667    /* In order to transfer, we need at least one of the channels to
07668       actually be in a call bridge.  We can't conference two applications
07669       together (but then, why would we want to?) */
07670    if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
07671       /* The three-way person we're about to transfer to could still be in MOH, so
07672          stop if now if appropriate */
07673       if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner))
07674          ast_queue_control(p->subs[SUB_THREEWAY].owner, AST_CONTROL_UNHOLD);
07675       if (p->subs[SUB_REAL].owner->_state == AST_STATE_RINGING) {
07676          ast_indicate(ast_bridged_channel(p->subs[SUB_REAL].owner), AST_CONTROL_RINGING);
07677       }
07678       if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RING) {
07679          tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE);
07680       }
07681        if (ast_channel_masquerade(p->subs[SUB_THREEWAY].owner, ast_bridged_channel(p->subs[SUB_REAL].owner))) {
07682          ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
07683                ast_bridged_channel(p->subs[SUB_REAL].owner)->name, p->subs[SUB_THREEWAY].owner->name);
07684          return -1;
07685       }
07686       /* Orphan the channel after releasing the lock */
07687       ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
07688       unalloc_sub(p, SUB_THREEWAY);
07689    } else if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
07690       ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
07691       if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RINGING) {
07692          ast_indicate(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), AST_CONTROL_RINGING);
07693       }
07694       if (p->subs[SUB_REAL].owner->_state == AST_STATE_RING) {
07695          tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
07696       }
07697       if (ast_channel_masquerade(p->subs[SUB_REAL].owner, ast_bridged_channel(p->subs[SUB_THREEWAY].owner))) {
07698          ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
07699                ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->name, p->subs[SUB_REAL].owner->name);
07700          return -1;
07701       }
07702       /* Three-way is now the REAL */
07703       swap_subs(p, SUB_THREEWAY, SUB_REAL);
07704       ast_channel_unlock(p->subs[SUB_REAL].owner);
07705       unalloc_sub(p, SUB_THREEWAY);
07706       /* Tell the caller not to hangup */
07707       return 1;
07708    } else {
07709       ast_debug(1, "Neither %s nor %s are in a bridge, nothing to transfer\n",
07710          p->subs[SUB_REAL].owner->name, p->subs[SUB_THREEWAY].owner->name);
07711       p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
07712       return -1;
07713    }
07714    return 0;
07715 }
07716 
07717 static int check_for_conference(struct dahdi_pvt *p)
07718 {
07719    struct dahdi_confinfo ci;
07720    /* Fine if we already have a master, etc */
07721    if (p->master || (p->confno > -1))
07722       return 0;
07723    memset(&ci, 0, sizeof(ci));
07724    if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
07725       ast_log(LOG_WARNING, "Failed to get conference info on channel %d: %s\n", p->channel, strerror(errno));
07726       return 0;
07727    }
07728    /* If we have no master and don't have a confno, then
07729       if we're in a conference, it's probably a MeetMe room or
07730       some such, so don't let us 3-way out! */
07731    if ((p->subs[SUB_REAL].curconf.confno != ci.confno) || (p->subs[SUB_REAL].curconf.confmode != ci.confmode)) {
07732       ast_verb(3, "Avoiding 3-way call when in an external conference\n");
07733       return 1;
07734    }
07735    return 0;
07736 }
07737 
07738 /*! Checks channel for alarms
07739  * \param p a channel to check for alarms.
07740  * \returns the alarms on the span to which the channel belongs, or alarms on
07741  *          the channel if no span alarms.
07742  */
07743 static int get_alarms(struct dahdi_pvt *p)
07744 {
07745    int res;
07746    struct dahdi_spaninfo zi;
07747    struct dahdi_params params;
07748 
07749    memset(&zi, 0, sizeof(zi));
07750    zi.spanno = p->span;
07751 
07752    if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SPANSTAT, &zi)) >= 0) {
07753       if (zi.alarms != DAHDI_ALARM_NONE)
07754          return zi.alarms;
07755    } else {
07756       ast_log(LOG_WARNING, "Unable to determine alarm on channel %d: %s\n", p->channel, strerror(errno));
07757       return 0;
07758    }
07759 
07760    /* No alarms on the span. Check for channel alarms. */
07761    memset(&params, 0, sizeof(params));
07762    if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &params)) >= 0)
07763       return params.chan_alarms;
07764 
07765    ast_log(LOG_WARNING, "Unable to determine alarm on channel %d\n", p->channel);
07766 
07767    return DAHDI_ALARM_NONE;
07768 }
07769 
07770 static void dahdi_handle_dtmf(struct ast_channel *ast, int idx, struct ast_frame **dest)
07771 {
07772    struct dahdi_pvt *p = ast->tech_pvt;
07773    struct ast_frame *f = *dest;
07774 
07775    ast_debug(1, "%s DTMF digit: 0x%02X '%c' on %s\n",
07776       f->frametype == AST_FRAME_DTMF_BEGIN ? "Begin" : "End",
07777       (unsigned)f->subclass.integer, f->subclass.integer, ast->name);
07778 
07779    if (p->confirmanswer) {
07780       if (f->frametype == AST_FRAME_DTMF_END) {
07781          ast_debug(1, "Confirm answer on %s!\n", ast->name);
07782          /* Upon receiving a DTMF digit, consider this an answer confirmation instead
07783             of a DTMF digit */
07784          p->subs[idx].f.frametype = AST_FRAME_CONTROL;
07785          p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
07786          /* Reset confirmanswer so DTMF's will behave properly for the duration of the call */
07787          p->confirmanswer = 0;
07788       } else {
07789          p->subs[idx].f.frametype = AST_FRAME_NULL;
07790          p->subs[idx].f.subclass.integer = 0;
07791       }
07792       *dest = &p->subs[idx].f;
07793    } else if (p->callwaitcas) {
07794       if (f->frametype == AST_FRAME_DTMF_END) {
07795          if ((f->subclass.integer == 'A') || (f->subclass.integer == 'D')) {
07796             ast_debug(1, "Got some DTMF, but it's for the CAS\n");
07797             ast_free(p->cidspill);
07798             p->cidspill = NULL;
07799             send_cwcidspill(p);
07800          }
07801          p->callwaitcas = 0;
07802       }
07803       p->subs[idx].f.frametype = AST_FRAME_NULL;
07804       p->subs[idx].f.subclass.integer = 0;
07805       *dest = &p->subs[idx].f;
07806    } else if (f->subclass.integer == 'f') {
07807       if (f->frametype == AST_FRAME_DTMF_END) {
07808          /* Fax tone -- Handle and return NULL */
07809          if ((p->callprogress & CALLPROGRESS_FAX) && !p->faxhandled) {
07810             /* If faxbuffers are configured, use them for the fax transmission */
07811             if (p->usefaxbuffers && !p->bufferoverrideinuse) {
07812                struct dahdi_bufferinfo bi = {
07813                   .txbufpolicy = p->faxbuf_policy,
07814                   .bufsize = p->bufsize,
07815                   .numbufs = p->faxbuf_no
07816                };
07817                int res;
07818 
07819                if ((res = ioctl(p->subs[idx].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
07820                   ast_log(LOG_WARNING, "Channel '%s' unable to set buffer policy, reason: %s\n", ast->name, strerror(errno));
07821                } else {
07822                   p->bufferoverrideinuse = 1;
07823                }
07824             }
07825             p->faxhandled = 1;
07826             if (p->dsp) {
07827                p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
07828                ast_dsp_set_features(p->dsp, p->dsp_features);
07829                ast_debug(1, "Disabling FAX tone detection on %s after tone received\n", ast->name);
07830             }
07831             if (strcmp(ast->exten, "fax")) {
07832                const char *target_context = S_OR(ast->macrocontext, ast->context);
07833 
07834                /* We need to unlock 'ast' here because ast_exists_extension has the
07835                 * potential to start autoservice on the channel. Such action is prone
07836                 * to deadlock.
07837                 */
07838                ast_mutex_unlock(&p->lock);
07839                ast_channel_unlock(ast);
07840                if (ast_exists_extension(ast, target_context, "fax", 1,
07841                   S_COR(ast->caller.id.number.valid, ast->caller.id.number.str, NULL))) {
07842                   ast_channel_lock(ast);
07843                   ast_mutex_lock(&p->lock);
07844                   ast_verb(3, "Redirecting %s to fax extension\n", ast->name);
07845                   /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
07846                   pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten);
07847                   if (ast_async_goto(ast, target_context, "fax", 1))
07848                      ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context);
07849                } else {
07850                   ast_channel_lock(ast);
07851                   ast_mutex_lock(&p->lock);
07852                   ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
07853                }
07854             } else {
07855                ast_debug(1, "Already in a fax extension, not redirecting\n");
07856             }
07857          } else {
07858             ast_debug(1, "Fax already handled\n");
07859          }
07860          dahdi_confmute(p, 0);
07861       }
07862       p->subs[idx].f.frametype = AST_FRAME_NULL;
07863       p->subs[idx].f.subclass.integer = 0;
07864       *dest = &p->subs[idx].f;
07865    }
07866 }
07867 
07868 static void handle_alarms(struct dahdi_pvt *p, int alms)
07869 {
07870    const char *alarm_str;
07871 
07872 #if defined(HAVE_PRI)
07873    if (dahdi_sig_pri_lib_handles(p->sig) && sig_pri_is_alarm_ignored(p->pri)) {
07874       return;
07875    }
07876 #endif   /* defined(HAVE_PRI) */
07877 
07878    alarm_str = alarm2str(alms);
07879    if (report_alarms & REPORT_CHANNEL_ALARMS) {
07880       ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", p->channel, alarm_str);
07881       manager_event(EVENT_FLAG_SYSTEM, "Alarm",
07882                  "Alarm: %s\r\n"
07883                  "Channel: %d\r\n",
07884                  alarm_str, p->channel);
07885    }
07886 
07887    if (report_alarms & REPORT_SPAN_ALARMS && p->manages_span_alarms) {
07888       ast_log(LOG_WARNING, "Detected alarm on span %d: %s\n", p->span, alarm_str);
07889       manager_event(EVENT_FLAG_SYSTEM, "SpanAlarm",
07890                  "Alarm: %s\r\n"
07891                  "Span: %d\r\n",
07892                  alarm_str, p->span);
07893    }
07894 }
07895 
07896 static struct ast_frame *dahdi_handle_event(struct ast_channel *ast)
07897 {
07898    int res, x;
07899    int idx, mysig;
07900    char *c;
07901    struct dahdi_pvt *p = ast->tech_pvt;
07902    pthread_t threadid;
07903    struct ast_channel *chan;
07904    struct ast_frame *f;
07905 
07906    idx = dahdi_get_index(ast, p, 0);
07907    if (idx < 0) {
07908       return &ast_null_frame;
07909    }
07910    mysig = p->sig;
07911    if (p->outsigmod > -1)
07912       mysig = p->outsigmod;
07913    p->subs[idx].f.frametype = AST_FRAME_NULL;
07914    p->subs[idx].f.subclass.integer = 0;
07915    p->subs[idx].f.datalen = 0;
07916    p->subs[idx].f.samples = 0;
07917    p->subs[idx].f.mallocd = 0;
07918    p->subs[idx].f.offset = 0;
07919    p->subs[idx].f.src = "dahdi_handle_event";
07920    p->subs[idx].f.data.ptr = NULL;
07921    f = &p->subs[idx].f;
07922 
07923    if (p->fake_event) {
07924       res = p->fake_event;
07925       p->fake_event = 0;
07926    } else
07927       res = dahdi_get_event(p->subs[idx].dfd);
07928 
07929    ast_debug(1, "Got event %s(%d) on channel %d (index %d)\n", event2str(res), res, p->channel, idx);
07930 
07931    if (res & (DAHDI_EVENT_PULSEDIGIT | DAHDI_EVENT_DTMFUP)) {
07932       p->pulsedial = (res & DAHDI_EVENT_PULSEDIGIT) ? 1 : 0;
07933       ast_debug(1, "Detected %sdigit '%c'\n", p->pulsedial ? "pulse ": "", res & 0xff);
07934 #if defined(HAVE_PRI)
07935       if (dahdi_sig_pri_lib_handles(p->sig)
07936          && ((struct sig_pri_chan *) p->sig_pvt)->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING
07937          && p->pri
07938          && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
07939          /* absorb event */
07940       } else
07941 #endif   /* defined(HAVE_PRI) */
07942       {
07943          /* Unmute conference */
07944          dahdi_confmute(p, 0);
07945          p->subs[idx].f.frametype = AST_FRAME_DTMF_END;
07946          p->subs[idx].f.subclass.integer = res & 0xff;
07947          dahdi_handle_dtmf(ast, idx, &f);
07948       }
07949       return f;
07950    }
07951 
07952    if (res & DAHDI_EVENT_DTMFDOWN) {
07953       ast_debug(1, "DTMF Down '%c'\n", res & 0xff);
07954 #if defined(HAVE_PRI)
07955       if (dahdi_sig_pri_lib_handles(p->sig)
07956          && ((struct sig_pri_chan *) p->sig_pvt)->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING
07957          && p->pri
07958          && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
07959          /* absorb event */
07960       } else
07961 #endif   /* defined(HAVE_PRI) */
07962       {
07963          /* Mute conference */
07964          dahdi_confmute(p, 1);
07965          p->subs[idx].f.frametype = AST_FRAME_DTMF_BEGIN;
07966          p->subs[idx].f.subclass.integer = res & 0xff;
07967          dahdi_handle_dtmf(ast, idx, &f);
07968       }
07969       return &p->subs[idx].f;
07970    }
07971 
07972    switch (res) {
07973    case DAHDI_EVENT_EC_DISABLED:
07974       ast_verb(3, "Channel %d echo canceler disabled.\n", p->channel);
07975       p->echocanon = 0;
07976       break;
07977 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
07978    case DAHDI_EVENT_TX_CED_DETECTED:
07979       ast_verb(3, "Channel %d detected a CED tone towards the network.\n", p->channel);
07980       break;
07981    case DAHDI_EVENT_RX_CED_DETECTED:
07982       ast_verb(3, "Channel %d detected a CED tone from the network.\n", p->channel);
07983       break;
07984    case DAHDI_EVENT_EC_NLP_DISABLED:
07985       ast_verb(3, "Channel %d echo canceler disabled its NLP.\n", p->channel);
07986       break;
07987    case DAHDI_EVENT_EC_NLP_ENABLED:
07988       ast_verb(3, "Channel %d echo canceler enabled its NLP.\n", p->channel);
07989       break;
07990 #endif
07991    case DAHDI_EVENT_BITSCHANGED:
07992 #ifdef HAVE_OPENR2
07993       if (p->sig != SIG_MFCR2) {
07994          ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig));
07995       } else {
07996          ast_log(LOG_DEBUG, "bits changed in chan %d\n", p->channel);
07997          openr2_chan_handle_cas(p->r2chan);
07998       }
07999 #else
08000       ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig));
08001 #endif
08002       break;
08003    case DAHDI_EVENT_PULSE_START:
08004       /* Stop tone if there's a pulse start and the PBX isn't started */
08005       if (!ast->pbx)
08006          tone_zone_play_tone(p->subs[idx].dfd, -1);
08007       break;
08008    case DAHDI_EVENT_DIALCOMPLETE:
08009       /* DAHDI has completed dialing all digits sent using DAHDI_DIAL. */
08010 #if defined(HAVE_PRI)
08011       if (dahdi_sig_pri_lib_handles(p->sig)) {
08012          if (p->inalarm) {
08013             break;
08014          }
08015          if (ioctl(p->subs[idx].dfd, DAHDI_DIALING, &x) == -1) {
08016             ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed on %s: %s\n", ast->name,
08017                strerror(errno));
08018             return NULL;
08019          }
08020          if (x) {
08021             /* Still dialing in DAHDI driver */
08022             break;
08023          }
08024          /*
08025           * The ast channel is locked and the private may be locked more
08026           * than once.
08027           */
08028          sig_pri_dial_complete(p->sig_pvt, ast);
08029          break;
08030       }
08031 #endif   /* defined(HAVE_PRI) */
08032 #ifdef HAVE_OPENR2
08033       if ((p->sig & SIG_MFCR2) && p->r2chan && ast->_state != AST_STATE_UP) {
08034          /* we don't need to do anything for this event for R2 signaling
08035             if the call is being setup */
08036          break;
08037       }
08038 #endif
08039       if (p->inalarm) break;
08040       if ((p->radio || (p->oprmode < 0))) break;
08041       if (ioctl(p->subs[idx].dfd,DAHDI_DIALING,&x) == -1) {
08042          ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed on %s: %s\n",ast->name, strerror(errno));
08043          return NULL;
08044       }
08045       if (!x) { /* if not still dialing in driver */
08046          dahdi_enable_ec(p);
08047          if (p->echobreak) {
08048             dahdi_train_ec(p);
08049             ast_copy_string(p->dop.dialstr, p->echorest, sizeof(p->dop.dialstr));
08050             p->dop.op = DAHDI_DIAL_OP_REPLACE;
08051             res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
08052             p->echobreak = 0;
08053          } else {
08054             p->dialing = 0;
08055             if ((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) {
08056                /* if thru with dialing after offhook */
08057                if (ast->_state == AST_STATE_DIALING_OFFHOOK) {
08058                   ast_setstate(ast, AST_STATE_UP);
08059                   p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08060                   p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
08061                   break;
08062                } else { /* if to state wait for offhook to dial rest */
08063                   /* we now wait for off hook */
08064                   ast_setstate(ast,AST_STATE_DIALING_OFFHOOK);
08065                }
08066             }
08067             if (ast->_state == AST_STATE_DIALING) {
08068                if ((p->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
08069                   ast_debug(1, "Done dialing, but waiting for progress detection before doing more...\n");
08070                } else if (p->confirmanswer || (!p->dialednone
08071                   && ((mysig == SIG_EM) || (mysig == SIG_EM_E1)
08072                      || (mysig == SIG_EMWINK) || (mysig == SIG_FEATD)
08073                      || (mysig == SIG_FEATDMF_TA) || (mysig == SIG_FEATDMF)
08074                      || (mysig == SIG_E911) || (mysig == SIG_FGC_CAMA)
08075                      || (mysig == SIG_FGC_CAMAMF) || (mysig == SIG_FEATB)
08076                      || (mysig == SIG_SF) || (mysig == SIG_SFWINK)
08077                      || (mysig == SIG_SF_FEATD) || (mysig == SIG_SF_FEATDMF)
08078                      || (mysig == SIG_SF_FEATB)))) {
08079                   ast_setstate(ast, AST_STATE_RINGING);
08080                } else if (!p->answeronpolarityswitch) {
08081                   ast_setstate(ast, AST_STATE_UP);
08082                   p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08083                   p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
08084                   /* If aops=0 and hops=1, this is necessary */
08085                   p->polarity = POLARITY_REV;
08086                } else {
08087                   /* Start clean, so we can catch the change to REV polarity when party answers */
08088                   p->polarity = POLARITY_IDLE;
08089                }
08090             }
08091          }
08092       }
08093       break;
08094    case DAHDI_EVENT_ALARM:
08095       switch (p->sig) {
08096 #if defined(HAVE_PRI)
08097       case SIG_PRI_LIB_HANDLE_CASES:
08098          sig_pri_chan_alarm_notify(p->sig_pvt, 0);
08099          break;
08100 #endif   /* defined(HAVE_PRI) */
08101 #if defined(HAVE_SS7)
08102       case SIG_SS7:
08103          sig_ss7_set_alarm(p->sig_pvt, 1);
08104          break;
08105 #endif   /* defined(HAVE_SS7) */
08106       default:
08107          p->inalarm = 1;
08108          break;
08109       }
08110       res = get_alarms(p);
08111       handle_alarms(p, res);
08112 #ifdef HAVE_PRI
08113       if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
08114          /* fall through intentionally */
08115       } else {
08116          break;
08117       }
08118 #endif
08119 #if defined(HAVE_SS7)
08120       if (p->sig == SIG_SS7)
08121          break;
08122 #endif   /* defined(HAVE_SS7) */
08123 #ifdef HAVE_OPENR2
08124       if (p->sig == SIG_MFCR2)
08125          break;
08126 #endif
08127    case DAHDI_EVENT_ONHOOK:
08128       if (p->radio) {
08129          p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08130          p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_UNKEY;
08131          break;
08132       }
08133       if (p->oprmode < 0)
08134       {
08135          if (p->oprmode != -1) break;
08136          if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
08137          {
08138             /* Make sure it starts ringing */
08139             dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
08140             dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RING);
08141             save_conference(p->oprpeer);
08142             tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
08143          }
08144          break;
08145       }
08146       switch (p->sig) {
08147       case SIG_FXOLS:
08148       case SIG_FXOGS:
08149       case SIG_FXOKS:
08150          /* Check for some special conditions regarding call waiting */
08151          if (idx == SUB_REAL) {
08152             /* The normal line was hung up */
08153             if (p->subs[SUB_CALLWAIT].owner) {
08154                /* There's a call waiting call, so ring the phone, but make it unowned in the mean time */
08155                swap_subs(p, SUB_CALLWAIT, SUB_REAL);
08156                ast_verb(3, "Channel %d still has (callwait) call, ringing phone\n", p->channel);
08157                unalloc_sub(p, SUB_CALLWAIT);
08158 #if 0
08159                p->subs[idx].needanswer = 0;
08160                p->subs[idx].needringing = 0;
08161 #endif
08162                p->callwaitingrepeat = 0;
08163                p->cidcwexpire = 0;
08164                p->cid_suppress_expire = 0;
08165                p->owner = NULL;
08166                /* Don't start streaming audio yet if the incoming call isn't up yet */
08167                if (p->subs[SUB_REAL].owner->_state != AST_STATE_UP)
08168                   p->dialing = 1;
08169                dahdi_ring_phone(p);
08170             } else if (p->subs[SUB_THREEWAY].owner) {
08171                unsigned int mssinceflash;
08172                /* Here we have to retain the lock on both the main channel, the 3-way channel, and
08173                   the private structure -- not especially easy or clean */
08174                while (p->subs[SUB_THREEWAY].owner && ast_channel_trylock(p->subs[SUB_THREEWAY].owner)) {
08175                   /* Yuck, didn't get the lock on the 3-way, gotta release everything and re-grab! */
08176                   DLA_UNLOCK(&p->lock);
08177                   CHANNEL_DEADLOCK_AVOIDANCE(ast);
08178                   /* We can grab ast and p in that order, without worry.  We should make sure
08179                      nothing seriously bad has happened though like some sort of bizarre double
08180                      masquerade! */
08181                   DLA_LOCK(&p->lock);
08182                   if (p->owner != ast) {
08183                      ast_log(LOG_WARNING, "This isn't good...\n");
08184                      return NULL;
08185                   }
08186                }
08187                if (!p->subs[SUB_THREEWAY].owner) {
08188                   ast_log(LOG_NOTICE, "Whoa, threeway disappeared kinda randomly.\n");
08189                   return NULL;
08190                }
08191                mssinceflash = ast_tvdiff_ms(ast_tvnow(), p->flashtime);
08192                ast_debug(1, "Last flash was %u ms ago\n", mssinceflash);
08193                if (mssinceflash < MIN_MS_SINCE_FLASH) {
08194                   /* It hasn't been long enough since the last flashook.  This is probably a bounce on
08195                      hanging up.  Hangup both channels now */
08196                   if (p->subs[SUB_THREEWAY].owner)
08197                      ast_queue_hangup_with_cause(p->subs[SUB_THREEWAY].owner, AST_CAUSE_NO_ANSWER);
08198                   p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08199                   ast_debug(1, "Looks like a bounced flash, hanging up both calls on %d\n", p->channel);
08200                   ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08201                } else if ((ast->pbx) || (ast->_state == AST_STATE_UP)) {
08202                   if (p->transfer) {
08203                      /* In any case this isn't a threeway call anymore */
08204                      p->subs[SUB_REAL].inthreeway = 0;
08205                      p->subs[SUB_THREEWAY].inthreeway = 0;
08206                      /* Only attempt transfer if the phone is ringing; why transfer to busy tone eh? */
08207                      if (!p->transfertobusy && ast->_state == AST_STATE_BUSY) {
08208                         ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08209                         /* Swap subs and dis-own channel */
08210                         swap_subs(p, SUB_THREEWAY, SUB_REAL);
08211                         p->owner = NULL;
08212                         /* Ring the phone */
08213                         dahdi_ring_phone(p);
08214                      } else {
08215                         if ((res = attempt_transfer(p)) < 0) {
08216                            p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08217                            if (p->subs[SUB_THREEWAY].owner)
08218                               ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08219                         } else if (res) {
08220                            /* Don't actually hang up at this point */
08221                            if (p->subs[SUB_THREEWAY].owner)
08222                               ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08223                            break;
08224                         }
08225                      }
08226                   } else {
08227                      p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08228                      if (p->subs[SUB_THREEWAY].owner)
08229                         ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08230                   }
08231                } else {
08232                   ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08233                   /* Swap subs and dis-own channel */
08234                   swap_subs(p, SUB_THREEWAY, SUB_REAL);
08235                   p->owner = NULL;
08236                   /* Ring the phone */
08237                   dahdi_ring_phone(p);
08238                }
08239             }
08240          } else {
08241             ast_log(LOG_WARNING, "Got a hangup and my index is %d?\n", idx);
08242          }
08243          /* Fall through */
08244       default:
08245          dahdi_disable_ec(p);
08246          return NULL;
08247       }
08248       break;
08249    case DAHDI_EVENT_RINGOFFHOOK:
08250       if (p->inalarm) break;
08251       if (p->oprmode < 0)
08252       {
08253          if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
08254          {
08255             /* Make sure it stops ringing */
08256             dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
08257             tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, -1);
08258             restore_conference(p->oprpeer);
08259          }
08260          break;
08261       }
08262       if (p->radio)
08263       {
08264          p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08265          p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_KEY;
08266          break;
08267       }
08268       /* for E911, its supposed to wait for offhook then dial
08269          the second half of the dial string */
08270       if (((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) && (ast->_state == AST_STATE_DIALING_OFFHOOK)) {
08271          c = strchr(p->dialdest, '/');
08272          if (c)
08273             c++;
08274          else
08275             c = p->dialdest;
08276          if (*c) snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*0%s#", c);
08277          else ast_copy_string(p->dop.dialstr,"M*2#", sizeof(p->dop.dialstr));
08278          if (strlen(p->dop.dialstr) > 4) {
08279             memset(p->echorest, 'w', sizeof(p->echorest) - 1);
08280             strcpy(p->echorest + (p->echotraining / 401) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
08281             p->echorest[sizeof(p->echorest) - 1] = '\0';
08282             p->echobreak = 1;
08283             p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
08284          } else
08285             p->echobreak = 0;
08286          if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
08287             int saveerr = errno;
08288 
08289             x = DAHDI_ONHOOK;
08290             ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
08291             ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
08292             return NULL;
08293             }
08294          p->dialing = 1;
08295          return &p->subs[idx].f;
08296       }
08297       switch (p->sig) {
08298       case SIG_FXOLS:
08299       case SIG_FXOGS:
08300       case SIG_FXOKS:
08301          switch (ast->_state) {
08302          case AST_STATE_RINGING:
08303             dahdi_enable_ec(p);
08304             dahdi_train_ec(p);
08305             p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08306             p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
08307             /* Make sure it stops ringing */
08308             p->subs[SUB_REAL].needringing = 0;
08309             dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
08310             ast_debug(1, "channel %d answered\n", p->channel);
08311 
08312             /* Cancel any running CallerID spill */
08313             ast_free(p->cidspill);
08314             p->cidspill = NULL;
08315             restore_conference(p);
08316 
08317             p->dialing = 0;
08318             p->callwaitcas = 0;
08319             if (p->confirmanswer) {
08320                /* Ignore answer if "confirm answer" is enabled */
08321                p->subs[idx].f.frametype = AST_FRAME_NULL;
08322                p->subs[idx].f.subclass.integer = 0;
08323             } else if (!ast_strlen_zero(p->dop.dialstr)) {
08324                /* nick@dccinc.com 4/3/03 - fxo should be able to do deferred dialing */
08325                res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
08326                if (res < 0) {
08327                   ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
08328                   p->dop.dialstr[0] = '\0';
08329                   return NULL;
08330                } else {
08331                   ast_debug(1, "Sent FXO deferred digit string: %s\n", p->dop.dialstr);
08332                   p->subs[idx].f.frametype = AST_FRAME_NULL;
08333                   p->subs[idx].f.subclass.integer = 0;
08334                   p->dialing = 1;
08335                }
08336                p->dop.dialstr[0] = '\0';
08337                ast_setstate(ast, AST_STATE_DIALING);
08338             } else
08339                ast_setstate(ast, AST_STATE_UP);
08340             return &p->subs[idx].f;
08341          case AST_STATE_DOWN:
08342             ast_setstate(ast, AST_STATE_RING);
08343             ast->rings = 1;
08344             p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08345             p->subs[idx].f.subclass.integer = AST_CONTROL_OFFHOOK;
08346             ast_debug(1, "channel %d picked up\n", p->channel);
08347             return &p->subs[idx].f;
08348          case AST_STATE_UP:
08349             /* Make sure it stops ringing */
08350             dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
08351             /* Okay -- probably call waiting*/
08352             if (ast_bridged_channel(p->owner))
08353                ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
08354             p->subs[idx].needunhold = 1;
08355             break;
08356          case AST_STATE_RESERVED:
08357             /* Start up dialtone */
08358             if (has_voicemail(p))
08359                res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
08360             else
08361                res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
08362             break;
08363          default:
08364             ast_log(LOG_WARNING, "FXO phone off hook in weird state %u??\n", ast->_state);
08365          }
08366          break;
08367       case SIG_FXSLS:
08368       case SIG_FXSGS:
08369       case SIG_FXSKS:
08370          if (ast->_state == AST_STATE_RING) {
08371             p->ringt = p->ringt_base;
08372          }
08373 
08374          /* If we get a ring then we cannot be in
08375           * reversed polarity. So we reset to idle */
08376          ast_debug(1, "Setting IDLE polarity due "
08377             "to ring. Old polarity was %d\n",
08378             p->polarity);
08379          p->polarity = POLARITY_IDLE;
08380 
08381          /* Fall through */
08382       case SIG_EM:
08383       case SIG_EM_E1:
08384       case SIG_EMWINK:
08385       case SIG_FEATD:
08386       case SIG_FEATDMF:
08387       case SIG_FEATDMF_TA:
08388       case SIG_E911:
08389       case SIG_FGC_CAMA:
08390       case SIG_FGC_CAMAMF:
08391       case SIG_FEATB:
08392       case SIG_SF:
08393       case SIG_SFWINK:
08394       case SIG_SF_FEATD:
08395       case SIG_SF_FEATDMF:
08396       case SIG_SF_FEATB:
08397          if (ast->_state == AST_STATE_PRERING)
08398             ast_setstate(ast, AST_STATE_RING);
08399          if ((ast->_state == AST_STATE_DOWN) || (ast->_state == AST_STATE_RING)) {
08400             ast_debug(1, "Ring detected\n");
08401             p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08402             p->subs[idx].f.subclass.integer = AST_CONTROL_RING;
08403          } else if (p->outgoing && ((ast->_state == AST_STATE_RINGING) || (ast->_state == AST_STATE_DIALING))) {
08404             ast_debug(1, "Line answered\n");
08405             if (p->confirmanswer) {
08406                p->subs[idx].f.frametype = AST_FRAME_NULL;
08407                p->subs[idx].f.subclass.integer = 0;
08408             } else {
08409                p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08410                p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
08411                ast_setstate(ast, AST_STATE_UP);
08412             }
08413          } else if (ast->_state != AST_STATE_RING)
08414             ast_log(LOG_WARNING, "Ring/Off-hook in strange state %u on channel %d\n", ast->_state, p->channel);
08415          break;
08416       default:
08417          ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
08418       }
08419       break;
08420    case DAHDI_EVENT_RINGBEGIN:
08421       switch (p->sig) {
08422       case SIG_FXSLS:
08423       case SIG_FXSGS:
08424       case SIG_FXSKS:
08425          if (ast->_state == AST_STATE_RING) {
08426             p->ringt = p->ringt_base;
08427          }
08428          break;
08429       }
08430       break;
08431    case DAHDI_EVENT_RINGERON:
08432       break;
08433    case DAHDI_EVENT_NOALARM:
08434       switch (p->sig) {
08435 #if defined(HAVE_PRI)
08436       case SIG_PRI_LIB_HANDLE_CASES:
08437          sig_pri_chan_alarm_notify(p->sig_pvt, 1);
08438          break;
08439 #endif   /* defined(HAVE_PRI) */
08440 #if defined(HAVE_SS7)
08441       case SIG_SS7:
08442          sig_ss7_set_alarm(p->sig_pvt, 0);
08443          break;
08444 #endif   /* defined(HAVE_SS7) */
08445       default:
08446          p->inalarm = 0;
08447          break;
08448       }
08449       handle_clear_alarms(p);
08450       break;
08451    case DAHDI_EVENT_WINKFLASH:
08452       if (p->inalarm) break;
08453       if (p->radio) break;
08454       if (p->oprmode < 0) break;
08455       if (p->oprmode > 1)
08456       {
08457          struct dahdi_params par;
08458 
08459          memset(&par, 0, sizeof(par));
08460          if (ioctl(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par) != -1)
08461          {
08462             if (!par.rxisoffhook)
08463             {
08464                /* Make sure it stops ringing */
08465                dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
08466                dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RING);
08467                save_conference(p);
08468                tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
08469             }
08470          }
08471          break;
08472       }
08473       /* Remember last time we got a flash-hook */
08474       p->flashtime = ast_tvnow();
08475       switch (mysig) {
08476       case SIG_FXOLS:
08477       case SIG_FXOGS:
08478       case SIG_FXOKS:
08479          ast_debug(1, "Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n",
08480             idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
08481 
08482          /* Cancel any running CallerID spill */
08483          ast_free(p->cidspill);
08484          p->cidspill = NULL;
08485          restore_conference(p);
08486          p->callwaitcas = 0;
08487 
08488          if (idx != SUB_REAL) {
08489             ast_log(LOG_WARNING, "Got flash hook with index %d on channel %d?!?\n", idx, p->channel);
08490             goto winkflashdone;
08491          }
08492 
08493          if (p->subs[SUB_CALLWAIT].owner) {
08494             /* Swap to call-wait */
08495             swap_subs(p, SUB_REAL, SUB_CALLWAIT);
08496             tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
08497             p->owner = p->subs[SUB_REAL].owner;
08498             ast_debug(1, "Making %s the new owner\n", p->owner->name);
08499             if (p->owner->_state == AST_STATE_RINGING) {
08500                ast_setstate(p->owner, AST_STATE_UP);
08501                p->subs[SUB_REAL].needanswer = 1;
08502             }
08503             p->callwaitingrepeat = 0;
08504             p->cidcwexpire = 0;
08505             p->cid_suppress_expire = 0;
08506             /* Start music on hold if appropriate */
08507             if (!p->subs[SUB_CALLWAIT].inthreeway && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
08508                ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
08509                   S_OR(p->mohsuggest, NULL),
08510                   !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
08511             }
08512             p->subs[SUB_CALLWAIT].needhold = 1;
08513             if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
08514                ast_queue_control_data(p->subs[SUB_REAL].owner, AST_CONTROL_HOLD,
08515                   S_OR(p->mohsuggest, NULL),
08516                   !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
08517             }
08518             p->subs[SUB_REAL].needunhold = 1;
08519          } else if (!p->subs[SUB_THREEWAY].owner) {
08520             if (!p->threewaycalling) {
08521                /* Just send a flash if no 3-way calling */
08522                p->subs[SUB_REAL].needflash = 1;
08523                goto winkflashdone;
08524             } else if (!check_for_conference(p)) {
08525                char cid_num[256];
08526                char cid_name[256];
08527 
08528                cid_num[0] = 0;
08529                cid_name[0] = 0;
08530                if (p->dahditrcallerid && p->owner) {
08531                   if (p->owner->caller.id.number.valid
08532                      && p->owner->caller.id.number.str) {
08533                      ast_copy_string(cid_num, p->owner->caller.id.number.str,
08534                         sizeof(cid_num));
08535                   }
08536                   if (p->owner->caller.id.name.valid
08537                      && p->owner->caller.id.name.str) {
08538                      ast_copy_string(cid_name, p->owner->caller.id.name.str,
08539                         sizeof(cid_name));
08540                   }
08541                }
08542                /* XXX This section needs much more error checking!!! XXX */
08543                /* Start a 3-way call if feasible */
08544                if (!((ast->pbx) ||
08545                   (ast->_state == AST_STATE_UP) ||
08546                   (ast->_state == AST_STATE_RING))) {
08547                   ast_debug(1, "Flash when call not up or ringing\n");
08548                   goto winkflashdone;
08549                }
08550                if (alloc_sub(p, SUB_THREEWAY)) {
08551                   ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n");
08552                   goto winkflashdone;
08553                }
08554 
08555                /*
08556                 * Make new channel
08557                 *
08558                 * We cannot hold the p or ast locks while creating a new
08559                 * channel.
08560                 */
08561                ast_mutex_unlock(&p->lock);
08562                ast_channel_unlock(ast);
08563                chan = dahdi_new(p, AST_STATE_RESERVED, 0, SUB_THREEWAY, 0, NULL);
08564                ast_channel_lock(ast);
08565                ast_mutex_lock(&p->lock);
08566                if (p->dahditrcallerid) {
08567                   if (!p->origcid_num)
08568                      p->origcid_num = ast_strdup(p->cid_num);
08569                   if (!p->origcid_name)
08570                      p->origcid_name = ast_strdup(p->cid_name);
08571                   ast_copy_string(p->cid_num, cid_num, sizeof(p->cid_num));
08572                   ast_copy_string(p->cid_name, cid_name, sizeof(p->cid_name));
08573                }
08574                /* Swap things around between the three-way and real call */
08575                swap_subs(p, SUB_THREEWAY, SUB_REAL);
08576                /* Disable echo canceller for better dialing */
08577                dahdi_disable_ec(p);
08578                res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALRECALL);
08579                if (res)
08580                   ast_log(LOG_WARNING, "Unable to start dial recall tone on channel %d\n", p->channel);
08581                p->owner = chan;
08582                if (!chan) {
08583                   ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", p->channel);
08584                } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
08585                   ast_log(LOG_WARNING, "Unable to start simple switch on channel %d\n", p->channel);
08586                   res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
08587                   dahdi_enable_ec(p);
08588                   ast_hangup(chan);
08589                } else {
08590                   ast_verb(3, "Started three way call on channel %d\n", p->channel);
08591 
08592                   /* Start music on hold if appropriate */
08593                   if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
08594                      ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
08595                         S_OR(p->mohsuggest, NULL),
08596                         !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
08597                   }
08598                   p->subs[SUB_THREEWAY].needhold = 1;
08599                }
08600             }
08601          } else {
08602             /* Already have a 3 way call */
08603             if (p->subs[SUB_THREEWAY].inthreeway) {
08604                /* Call is already up, drop the last person */
08605                ast_debug(1, "Got flash with three way call up, dropping last call on %d\n", p->channel);
08606                /* If the primary call isn't answered yet, use it */
08607                if ((p->subs[SUB_REAL].owner->_state != AST_STATE_UP) && (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_UP)) {
08608                   /* Swap back -- we're dropping the real 3-way that isn't finished yet*/
08609                   swap_subs(p, SUB_THREEWAY, SUB_REAL);
08610                   p->owner = p->subs[SUB_REAL].owner;
08611                }
08612                /* Drop the last call and stop the conference */
08613                ast_verb(3, "Dropping three-way call on %s\n", p->subs[SUB_THREEWAY].owner->name);
08614                p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08615                p->subs[SUB_REAL].inthreeway = 0;
08616                p->subs[SUB_THREEWAY].inthreeway = 0;
08617             } else {
08618                /* Lets see what we're up to */
08619                if (((ast->pbx) || (ast->_state == AST_STATE_UP)) &&
08620                   (p->transfertobusy || (ast->_state != AST_STATE_BUSY))) {
08621                   int otherindex = SUB_THREEWAY;
08622 
08623                   ast_verb(3, "Building conference call with %s and %s\n",
08624                      p->subs[SUB_THREEWAY].owner->name,
08625                      p->subs[SUB_REAL].owner->name);
08626                   /* Put them in the threeway, and flip */
08627                   p->subs[SUB_THREEWAY].inthreeway = 1;
08628                   p->subs[SUB_REAL].inthreeway = 1;
08629                   if (ast->_state == AST_STATE_UP) {
08630                      swap_subs(p, SUB_THREEWAY, SUB_REAL);
08631                      otherindex = SUB_REAL;
08632                   }
08633                   if (p->subs[otherindex].owner && ast_bridged_channel(p->subs[otherindex].owner))
08634                      ast_queue_control(p->subs[otherindex].owner, AST_CONTROL_UNHOLD);
08635                   p->subs[otherindex].needunhold = 1;
08636                   p->owner = p->subs[SUB_REAL].owner;
08637                } else {
08638                   ast_verb(3, "Dumping incomplete call on on %s\n", p->subs[SUB_THREEWAY].owner->name);
08639                   swap_subs(p, SUB_THREEWAY, SUB_REAL);
08640                   p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08641                   p->owner = p->subs[SUB_REAL].owner;
08642                   if (p->subs[SUB_REAL].owner && ast_bridged_channel(p->subs[SUB_REAL].owner))
08643                      ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
08644                   p->subs[SUB_REAL].needunhold = 1;
08645                   dahdi_enable_ec(p);
08646                }
08647             }
08648          }
08649 winkflashdone:
08650          update_conf(p);
08651          break;
08652       case SIG_EM:
08653       case SIG_EM_E1:
08654       case SIG_FEATD:
08655       case SIG_SF:
08656       case SIG_SFWINK:
08657       case SIG_SF_FEATD:
08658       case SIG_FXSLS:
08659       case SIG_FXSGS:
08660          if (p->dialing)
08661             ast_debug(1, "Ignoring wink on channel %d\n", p->channel);
08662          else
08663             ast_debug(1, "Got wink in weird state %u on channel %d\n", ast->_state, p->channel);
08664          break;
08665       case SIG_FEATDMF_TA:
08666          switch (p->whichwink) {
08667          case 0:
08668             ast_debug(1, "ANI2 set to '%d' and ANI is '%s'\n", p->owner->caller.ani2,
08669                S_COR(p->owner->caller.ani.number.valid,
08670                   p->owner->caller.ani.number.str, ""));
08671             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%d%s#",
08672                p->owner->caller.ani2,
08673                S_COR(p->owner->caller.ani.number.valid,
08674                   p->owner->caller.ani.number.str, ""));
08675             break;
08676          case 1:
08677             ast_copy_string(p->dop.dialstr, p->finaldial, sizeof(p->dop.dialstr));
08678             break;
08679          case 2:
08680             ast_log(LOG_WARNING, "Received unexpected wink on channel of type SIG_FEATDMF_TA\n");
08681             return NULL;
08682          }
08683          p->whichwink++;
08684          /* Fall through */
08685       case SIG_FEATDMF:
08686       case SIG_E911:
08687       case SIG_FGC_CAMAMF:
08688       case SIG_FGC_CAMA:
08689       case SIG_FEATB:
08690       case SIG_SF_FEATDMF:
08691       case SIG_SF_FEATB:
08692       case SIG_EMWINK:
08693          /* FGD MF and EMWINK *Must* wait for wink */
08694          if (!ast_strlen_zero(p->dop.dialstr)) {
08695             res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
08696             if (res < 0) {
08697                ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
08698                p->dop.dialstr[0] = '\0';
08699                return NULL;
08700             } else
08701                ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
08702          }
08703          p->dop.dialstr[0] = '\0';
08704          break;
08705       default:
08706          ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
08707       }
08708       break;
08709    case DAHDI_EVENT_HOOKCOMPLETE:
08710       if (p->inalarm) break;
08711       if ((p->radio || (p->oprmode < 0))) break;
08712       if (p->waitingfordt.tv_sec) break;
08713       switch (mysig) {
08714       case SIG_FXSLS:  /* only interesting for FXS */
08715       case SIG_FXSGS:
08716       case SIG_FXSKS:
08717       case SIG_EM:
08718       case SIG_EM_E1:
08719       case SIG_EMWINK:
08720       case SIG_FEATD:
08721       case SIG_SF:
08722       case SIG_SFWINK:
08723       case SIG_SF_FEATD:
08724          if (!ast_strlen_zero(p->dop.dialstr)) {
08725             res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
08726             if (res < 0) {
08727                ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
08728                p->dop.dialstr[0] = '\0';
08729                return NULL;
08730             } else
08731                ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
08732          }
08733          p->dop.dialstr[0] = '\0';
08734          p->dop.op = DAHDI_DIAL_OP_REPLACE;
08735          break;
08736       case SIG_FEATDMF:
08737       case SIG_FEATDMF_TA:
08738       case SIG_E911:
08739       case SIG_FGC_CAMA:
08740       case SIG_FGC_CAMAMF:
08741       case SIG_FEATB:
08742       case SIG_SF_FEATDMF:
08743       case SIG_SF_FEATB:
08744          ast_debug(1, "Got hook complete in MF FGD, waiting for wink now on channel %d\n",p->channel);
08745          break;
08746       default:
08747          break;
08748       }
08749       break;
08750    case DAHDI_EVENT_POLARITY:
08751       /*
08752        * If we get a Polarity Switch event, check to see
08753        * if we should change the polarity state and
08754        * mark the channel as UP or if this is an indication
08755        * of remote end disconnect.
08756        */
08757       if (p->polarity == POLARITY_IDLE) {
08758          p->polarity = POLARITY_REV;
08759          if (p->answeronpolarityswitch &&
08760             ((ast->_state == AST_STATE_DIALING) ||
08761             (ast->_state == AST_STATE_RINGING))) {
08762             ast_debug(1, "Answering on polarity switch!\n");
08763             ast_setstate(p->owner, AST_STATE_UP);
08764             if (p->hanguponpolarityswitch) {
08765                p->polaritydelaytv = ast_tvnow();
08766             }
08767          } else
08768             ast_debug(1, "Ignore switch to REVERSED Polarity on channel %d, state %u\n", p->channel, ast->_state);
08769       }
08770       /* Removed else statement from here as it was preventing hangups from ever happening*/
08771       /* Added AST_STATE_RING in if statement below to deal with calling party hangups that take place when ringing */
08772       if (p->hanguponpolarityswitch &&
08773          (p->polarityonanswerdelay > 0) &&
08774          (p->polarity == POLARITY_REV) &&
08775          ((ast->_state == AST_STATE_UP) || (ast->_state == AST_STATE_RING)) ) {
08776          /* Added log_debug information below to provide a better indication of what is going on */
08777          ast_debug(1, "Polarity Reversal event occured - DEBUG 1: channel %d, state %u, pol= %d, aonp= %d, honp= %d, pdelay= %d, tv= %" PRIi64 "\n", p->channel, ast->_state, p->polarity, p->answeronpolarityswitch, p->hanguponpolarityswitch, p->polarityonanswerdelay, ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) );
08778 
08779          if (ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) > p->polarityonanswerdelay) {
08780             ast_debug(1, "Polarity Reversal detected and now Hanging up on channel %d\n", p->channel);
08781             ast_softhangup(p->owner, AST_SOFTHANGUP_EXPLICIT);
08782             p->polarity = POLARITY_IDLE;
08783          } else
08784             ast_debug(1, "Polarity Reversal detected but NOT hanging up (too close to answer event) on channel %d, state %u\n", p->channel, ast->_state);
08785 
08786       } else {
08787          p->polarity = POLARITY_IDLE;
08788          ast_debug(1, "Ignoring Polarity switch to IDLE on channel %d, state %u\n", p->channel, ast->_state);
08789       }
08790       /* Added more log_debug information below to provide a better indication of what is going on */
08791       ast_debug(1, "Polarity Reversal event occured - DEBUG 2: channel %d, state %u, pol= %d, aonp= %d, honp= %d, pdelay= %d, tv= %" PRIi64 "\n", p->channel, ast->_state, p->polarity, p->answeronpolarityswitch, p->hanguponpolarityswitch, p->polarityonanswerdelay, ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) );
08792       break;
08793    default:
08794       ast_debug(1, "Dunno what to do with event %d on channel %d\n", res, p->channel);
08795    }
08796    return &p->subs[idx].f;
08797 }
08798 
08799 static struct ast_frame *__dahdi_exception(struct ast_channel *ast)
08800 {
08801    int res;
08802    int idx;
08803    struct ast_frame *f;
08804    int usedindex = -1;
08805    struct dahdi_pvt *p = ast->tech_pvt;
08806 
08807    if ((idx = dahdi_get_index(ast, p, 0)) < 0) {
08808       idx = SUB_REAL;
08809    }
08810 
08811    p->subs[idx].f.frametype = AST_FRAME_NULL;
08812    p->subs[idx].f.datalen = 0;
08813    p->subs[idx].f.samples = 0;
08814    p->subs[idx].f.mallocd = 0;
08815    p->subs[idx].f.offset = 0;
08816    p->subs[idx].f.subclass.integer = 0;
08817    p->subs[idx].f.delivery = ast_tv(0,0);
08818    p->subs[idx].f.src = "dahdi_exception";
08819    p->subs[idx].f.data.ptr = NULL;
08820 
08821 
08822    if ((!p->owner) && (!(p->radio || (p->oprmode < 0)))) {
08823       /* If nobody owns us, absorb the event appropriately, otherwise
08824          we loop indefinitely.  This occurs when, during call waiting, the
08825          other end hangs up our channel so that it no longer exists, but we
08826          have neither FLASH'd nor ONHOOK'd to signify our desire to
08827          change to the other channel. */
08828       if (p->fake_event) {
08829          res = p->fake_event;
08830          p->fake_event = 0;
08831       } else
08832          res = dahdi_get_event(p->subs[SUB_REAL].dfd);
08833       /* Switch to real if there is one and this isn't something really silly... */
08834       if ((res != DAHDI_EVENT_RINGEROFF) && (res != DAHDI_EVENT_RINGERON) &&
08835          (res != DAHDI_EVENT_HOOKCOMPLETE)) {
08836          ast_debug(1, "Restoring owner of channel %d on event %d\n", p->channel, res);
08837          p->owner = p->subs[SUB_REAL].owner;
08838          if (p->owner && ast_bridged_channel(p->owner))
08839             ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
08840          p->subs[SUB_REAL].needunhold = 1;
08841       }
08842       switch (res) {
08843       case DAHDI_EVENT_ONHOOK:
08844          dahdi_disable_ec(p);
08845          if (p->owner) {
08846             ast_verb(3, "Channel %s still has call, ringing phone\n", p->owner->name);
08847             dahdi_ring_phone(p);
08848             p->callwaitingrepeat = 0;
08849             p->cidcwexpire = 0;
08850             p->cid_suppress_expire = 0;
08851          } else
08852             ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
08853          update_conf(p);
08854          break;
08855       case DAHDI_EVENT_RINGOFFHOOK:
08856          dahdi_enable_ec(p);
08857          dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
08858          if (p->owner && (p->owner->_state == AST_STATE_RINGING)) {
08859             p->subs[SUB_REAL].needanswer = 1;
08860             p->dialing = 0;
08861          }
08862          break;
08863       case DAHDI_EVENT_HOOKCOMPLETE:
08864       case DAHDI_EVENT_RINGERON:
08865       case DAHDI_EVENT_RINGEROFF:
08866          /* Do nothing */
08867          break;
08868       case DAHDI_EVENT_WINKFLASH:
08869          p->flashtime = ast_tvnow();
08870          if (p->owner) {
08871             ast_verb(3, "Channel %d flashed to other channel %s\n", p->channel, p->owner->name);
08872             if (p->owner->_state != AST_STATE_UP) {
08873                /* Answer if necessary */
08874                usedindex = dahdi_get_index(p->owner, p, 0);
08875                if (usedindex > -1) {
08876                   p->subs[usedindex].needanswer = 1;
08877                }
08878                ast_setstate(p->owner, AST_STATE_UP);
08879             }
08880             p->callwaitingrepeat = 0;
08881             p->cidcwexpire = 0;
08882             p->cid_suppress_expire = 0;
08883             if (ast_bridged_channel(p->owner))
08884                ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
08885             p->subs[SUB_REAL].needunhold = 1;
08886          } else
08887             ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
08888          update_conf(p);
08889          break;
08890       default:
08891          ast_log(LOG_WARNING, "Don't know how to absorb event %s\n", event2str(res));
08892       }
08893       f = &p->subs[idx].f;
08894       return f;
08895    }
08896    if (!(p->radio || (p->oprmode < 0)))
08897       ast_debug(1, "Exception on %d, channel %d\n", ast->fds[0],p->channel);
08898    /* If it's not us, return NULL immediately */
08899    if (ast != p->owner) {
08900       if (p->owner) {
08901          ast_log(LOG_WARNING, "We're %s, not %s\n", ast->name, p->owner->name);
08902       }
08903       f = &p->subs[idx].f;
08904       return f;
08905    }
08906 
08907    f = dahdi_handle_event(ast);
08908    if (!f) {
08909       const char *name = ast_strdupa(ast->name);
08910 
08911       /* Tell the CDR this DAHDI device hung up */
08912       ast_mutex_unlock(&p->lock);
08913       ast_channel_unlock(ast);
08914       ast_set_hangupsource(ast, name, 0);
08915       ast_channel_lock(ast);
08916       ast_mutex_lock(&p->lock);
08917    }
08918    return f;
08919 }
08920 
08921 static struct ast_frame *dahdi_exception(struct ast_channel *ast)
08922 {
08923    struct dahdi_pvt *p = ast->tech_pvt;
08924    struct ast_frame *f;
08925    ast_mutex_lock(&p->lock);
08926    if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
08927       struct analog_pvt *analog_p = p->sig_pvt;
08928       f = analog_exception(analog_p, ast);
08929    } else {
08930       f = __dahdi_exception(ast);
08931    }
08932    ast_mutex_unlock(&p->lock);
08933    return f;
08934 }
08935 
08936 static struct ast_frame *dahdi_read(struct ast_channel *ast)
08937 {
08938    struct dahdi_pvt *p;
08939    int res;
08940    int idx;
08941    void *readbuf;
08942    struct ast_frame *f;
08943 
08944    /*
08945     * For analog channels, we must do deadlock avoidance because
08946     * analog ports can have more than one Asterisk channel using
08947     * the same private structure.
08948     */
08949    p = ast->tech_pvt;
08950    while (ast_mutex_trylock(&p->lock)) {
08951       CHANNEL_DEADLOCK_AVOIDANCE(ast);
08952 
08953       /*
08954        * Check to see if the channel is still associated with the same
08955        * private structure.  While the Asterisk channel was unlocked
08956        * the following events may have occured:
08957        *
08958        * 1) A masquerade may have associated the channel with another
08959        * technology or private structure.
08960        *
08961        * 2) For PRI calls, call signaling could change the channel
08962        * association to another B channel (private structure).
08963        */
08964       if (ast->tech_pvt != p) {
08965          /* The channel is no longer associated.  Quit gracefully. */
08966          return &ast_null_frame;
08967       }
08968    }
08969 
08970    idx = dahdi_get_index(ast, p, 0);
08971 
08972    /* Hang up if we don't really exist */
08973    if (idx < 0)   {
08974       ast_log(LOG_WARNING, "We don't exist?\n");
08975       ast_mutex_unlock(&p->lock);
08976       return NULL;
08977    }
08978 
08979    if ((p->radio || (p->oprmode < 0)) && p->inalarm) {
08980       ast_mutex_unlock(&p->lock);
08981       return NULL;
08982    }
08983 
08984    p->subs[idx].f.frametype = AST_FRAME_NULL;
08985    p->subs[idx].f.datalen = 0;
08986    p->subs[idx].f.samples = 0;
08987    p->subs[idx].f.mallocd = 0;
08988    p->subs[idx].f.offset = 0;
08989    p->subs[idx].f.subclass.integer = 0;
08990    p->subs[idx].f.delivery = ast_tv(0,0);
08991    p->subs[idx].f.src = "dahdi_read";
08992    p->subs[idx].f.data.ptr = NULL;
08993 
08994    /* make sure it sends initial key state as first frame */
08995    if ((p->radio || (p->oprmode < 0)) && (!p->firstradio))
08996    {
08997       struct dahdi_params ps;
08998 
08999       memset(&ps, 0, sizeof(ps));
09000       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
09001          ast_mutex_unlock(&p->lock);
09002          return NULL;
09003       }
09004       p->firstradio = 1;
09005       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09006       if (ps.rxisoffhook)
09007       {
09008          p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_KEY;
09009       }
09010       else
09011       {
09012          p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_UNKEY;
09013       }
09014       ast_mutex_unlock(&p->lock);
09015       return &p->subs[idx].f;
09016    }
09017    if (p->ringt > 0) {
09018       if (!(--p->ringt)) {
09019          ast_mutex_unlock(&p->lock);
09020          return NULL;
09021       }
09022    }
09023 
09024 #ifdef HAVE_OPENR2
09025    if (p->mfcr2) {
09026       openr2_chan_process_event(p->r2chan);
09027       if (OR2_DIR_FORWARD == openr2_chan_get_direction(p->r2chan)) {
09028          struct ast_frame f = { AST_FRAME_CONTROL, { AST_CONTROL_PROGRESS }, };
09029          /* if the call is already accepted and we already delivered AST_CONTROL_RINGING
09030           * now enqueue a progress frame to bridge the media up */
09031          if (p->mfcr2_call_accepted &&
09032              !p->mfcr2_progress && 
09033              ast->_state == AST_STATE_RINGING) {
09034             ast_log(LOG_DEBUG, "Enqueuing progress frame after R2 accept in chan %d\n", p->channel);
09035             ast_queue_frame(p->owner, &f);
09036             p->mfcr2_progress = 1;
09037          }
09038       }
09039    }
09040 #endif
09041 
09042    if (p->subs[idx].needringing) {
09043       /* Send ringing frame if requested */
09044       p->subs[idx].needringing = 0;
09045       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09046       p->subs[idx].f.subclass.integer = AST_CONTROL_RINGING;
09047       ast_setstate(ast, AST_STATE_RINGING);
09048       ast_mutex_unlock(&p->lock);
09049       return &p->subs[idx].f;
09050    }
09051 
09052    if (p->subs[idx].needbusy) {
09053       /* Send busy frame if requested */
09054       p->subs[idx].needbusy = 0;
09055       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09056       p->subs[idx].f.subclass.integer = AST_CONTROL_BUSY;
09057       ast_mutex_unlock(&p->lock);
09058       return &p->subs[idx].f;
09059    }
09060 
09061    if (p->subs[idx].needcongestion) {
09062       /* Send congestion frame if requested */
09063       p->subs[idx].needcongestion = 0;
09064       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09065       p->subs[idx].f.subclass.integer = AST_CONTROL_CONGESTION;
09066       ast_mutex_unlock(&p->lock);
09067       return &p->subs[idx].f;
09068    }
09069 
09070    if (p->subs[idx].needanswer) {
09071       /* Send answer frame if requested */
09072       p->subs[idx].needanswer = 0;
09073       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09074       p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
09075       ast_mutex_unlock(&p->lock);
09076       return &p->subs[idx].f;
09077    }
09078 #ifdef HAVE_OPENR2
09079    if (p->mfcr2 && openr2_chan_get_read_enabled(p->r2chan)) {
09080       /* openr2 took care of reading and handling any event
09081         (needanswer, needbusy etc), if we continue we will read()
09082         twice, lets just return a null frame. This should only
09083         happen when openr2 is dialing out */
09084       ast_mutex_unlock(&p->lock);
09085       return &ast_null_frame;
09086    }
09087 #endif
09088 
09089    if (p->subs[idx].needflash) {
09090       /* Send answer frame if requested */
09091       p->subs[idx].needflash = 0;
09092       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09093       p->subs[idx].f.subclass.integer = AST_CONTROL_FLASH;
09094       ast_mutex_unlock(&p->lock);
09095       return &p->subs[idx].f;
09096    }
09097 
09098    if (p->subs[idx].needhold) {
09099       /* Send answer frame if requested */
09100       p->subs[idx].needhold = 0;
09101       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09102       p->subs[idx].f.subclass.integer = AST_CONTROL_HOLD;
09103       ast_mutex_unlock(&p->lock);
09104       ast_debug(1, "Sending hold on '%s'\n", ast->name);
09105       return &p->subs[idx].f;
09106    }
09107 
09108    if (p->subs[idx].needunhold) {
09109       /* Send answer frame if requested */
09110       p->subs[idx].needunhold = 0;
09111       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09112       p->subs[idx].f.subclass.integer = AST_CONTROL_UNHOLD;
09113       ast_mutex_unlock(&p->lock);
09114       ast_debug(1, "Sending unhold on '%s'\n", ast->name);
09115       return &p->subs[idx].f;
09116    }
09117 
09118    /*
09119     * If we have a fake_event, fake an exception to handle it only
09120     * if this channel owns the private.
09121     */
09122    if (p->fake_event && p->owner == ast) {
09123       if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
09124          struct analog_pvt *analog_p = p->sig_pvt;
09125 
09126          f = analog_exception(analog_p, ast);
09127       } else {
09128          f = __dahdi_exception(ast);
09129       }
09130       ast_mutex_unlock(&p->lock);
09131       return f;
09132    }
09133 
09134    if (ast->rawreadformat == AST_FORMAT_SLINEAR) {
09135       if (!p->subs[idx].linear) {
09136          p->subs[idx].linear = 1;
09137          res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09138          if (res)
09139             ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to linear mode.\n", p->channel, idx);
09140       }
09141    } else if ((ast->rawreadformat == AST_FORMAT_ULAW) ||
09142       (ast->rawreadformat == AST_FORMAT_ALAW)) {
09143       if (p->subs[idx].linear) {
09144          p->subs[idx].linear = 0;
09145          res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09146          if (res)
09147             ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to companded mode.\n", p->channel, idx);
09148       }
09149    } else {
09150       ast_log(LOG_WARNING, "Don't know how to read frames in format %s\n", ast_getformatname(ast->rawreadformat));
09151       ast_mutex_unlock(&p->lock);
09152       return NULL;
09153    }
09154    readbuf = ((unsigned char *)p->subs[idx].buffer) + AST_FRIENDLY_OFFSET;
09155    CHECK_BLOCKING(ast);
09156    res = read(p->subs[idx].dfd, readbuf, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
09157    ast_clear_flag(ast, AST_FLAG_BLOCKING);
09158    /* Check for hangup */
09159    if (res < 0) {
09160       f = NULL;
09161       if (res == -1) {
09162          if (errno == EAGAIN) {
09163             /* Return "NULL" frame if there is nobody there */
09164             ast_mutex_unlock(&p->lock);
09165             return &p->subs[idx].f;
09166          } else if (errno == ELAST) {
09167             if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
09168                struct analog_pvt *analog_p = p->sig_pvt;
09169                f = analog_exception(analog_p, ast);
09170             } else {
09171                f = __dahdi_exception(ast);
09172             }
09173          } else
09174             ast_log(LOG_WARNING, "dahdi_rec: %s\n", strerror(errno));
09175       }
09176       ast_mutex_unlock(&p->lock);
09177       return f;
09178    }
09179    if (res != (p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE)) {
09180       ast_debug(1, "Short read (%d/%d), must be an event...\n", res, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
09181       if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
09182          struct analog_pvt *analog_p = p->sig_pvt;
09183          f = analog_exception(analog_p, ast);
09184       } else {
09185          f = __dahdi_exception(ast);
09186       }
09187       ast_mutex_unlock(&p->lock);
09188       return f;
09189    }
09190    if (p->tdd) { /* if in TDD mode, see if we receive that */
09191       int c;
09192 
09193       c = tdd_feed(p->tdd,readbuf,READ_SIZE);
09194       if (c < 0) {
09195          ast_debug(1,"tdd_feed failed\n");
09196          ast_mutex_unlock(&p->lock);
09197          return NULL;
09198       }
09199       if (c) { /* if a char to return */
09200          p->subs[idx].f.subclass.integer = 0;
09201          p->subs[idx].f.frametype = AST_FRAME_TEXT;
09202          p->subs[idx].f.mallocd = 0;
09203          p->subs[idx].f.offset = AST_FRIENDLY_OFFSET;
09204          p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET;
09205          p->subs[idx].f.datalen = 1;
09206          *((char *) p->subs[idx].f.data.ptr) = c;
09207          ast_mutex_unlock(&p->lock);
09208          return &p->subs[idx].f;
09209       }
09210    }
09211    if (idx == SUB_REAL) {
09212       /* Ensure the CW timers decrement only on a single subchannel */
09213       if (p->cidcwexpire) {
09214          if (!--p->cidcwexpire) {
09215             /* Expired CID/CW */
09216             ast_verb(3, "CPE does not support Call Waiting Caller*ID.\n");
09217             restore_conference(p);
09218          }
09219       }
09220       if (p->cid_suppress_expire) {
09221          --p->cid_suppress_expire;
09222       }
09223       if (p->callwaitingrepeat) {
09224          if (!--p->callwaitingrepeat) {
09225             /* Expired, Repeat callwaiting tone */
09226             ++p->callwaitrings;
09227             dahdi_callwait(ast);
09228          }
09229       }
09230    }
09231    if (p->subs[idx].linear) {
09232       p->subs[idx].f.datalen = READ_SIZE * 2;
09233    } else
09234       p->subs[idx].f.datalen = READ_SIZE;
09235 
09236    /* Handle CallerID Transmission */
09237    if ((p->owner == ast) && p->cidspill) {
09238       send_callerid(p);
09239    }
09240 
09241    p->subs[idx].f.frametype = AST_FRAME_VOICE;
09242    p->subs[idx].f.subclass.codec = ast->rawreadformat;
09243    p->subs[idx].f.samples = READ_SIZE;
09244    p->subs[idx].f.mallocd = 0;
09245    p->subs[idx].f.offset = AST_FRIENDLY_OFFSET;
09246    p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET / sizeof(p->subs[idx].buffer[0]);
09247 #if 0
09248    ast_debug(1, "Read %d of voice on %s\n", p->subs[idx].f.datalen, ast->name);
09249 #endif
09250    if ((p->dialing && !p->waitingfordt.tv_sec) ||  p->radio || /* Transmitting something */
09251       (idx && (ast->_state != AST_STATE_UP)) || /* Three-way or callwait that isn't up */
09252       ((idx == SUB_CALLWAIT) && !p->subs[SUB_CALLWAIT].inthreeway) /* Inactive and non-confed call-wait */
09253       ) {
09254       /* Whoops, we're still dialing, or in a state where we shouldn't transmit....
09255          don't send anything */
09256       p->subs[idx].f.frametype = AST_FRAME_NULL;
09257       p->subs[idx].f.subclass.integer = 0;
09258       p->subs[idx].f.samples = 0;
09259       p->subs[idx].f.mallocd = 0;
09260       p->subs[idx].f.offset = 0;
09261       p->subs[idx].f.data.ptr = NULL;
09262       p->subs[idx].f.datalen= 0;
09263    }
09264    if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect || p->callprogress || p->waitingfordt.tv_sec) && !idx) {
09265       /* Perform busy detection etc on the dahdi line */
09266       int mute;
09267 
09268       f = ast_dsp_process(ast, p->dsp, &p->subs[idx].f);
09269 
09270       /* Check if DSP code thinks we should be muting this frame and mute the conference if so */
09271       mute = ast_dsp_was_muted(p->dsp);
09272       if (p->muting != mute) {
09273          p->muting = mute;
09274          dahdi_confmute(p, mute);
09275       }
09276 
09277       if (f) {
09278          if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass.integer == AST_CONTROL_BUSY)) {
09279             if ((ast->_state == AST_STATE_UP) && !p->outgoing) {
09280                /* Treat this as a "hangup" instead of a "busy" on the assumption that
09281                   a busy */
09282                ast_frfree(f);
09283                f = NULL;
09284             }
09285          } else if (f->frametype == AST_FRAME_DTMF_BEGIN
09286             || f->frametype == AST_FRAME_DTMF_END) {
09287 #ifdef HAVE_PRI
09288             if (dahdi_sig_pri_lib_handles(p->sig)
09289                && ((struct sig_pri_chan *) p->sig_pvt)->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING
09290                && p->pri
09291                && ((!p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING))
09292                   || (p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)))) {
09293                /* Don't accept in-band DTMF when in overlap dial mode */
09294                ast_debug(1, "Absorbing inband %s DTMF digit: 0x%02X '%c' on %s\n",
09295                   f->frametype == AST_FRAME_DTMF_BEGIN ? "begin" : "end",
09296                   (unsigned)f->subclass.integer, f->subclass.integer, ast->name);
09297 
09298                f->frametype = AST_FRAME_NULL;
09299                f->subclass.integer = 0;
09300             }
09301 #endif
09302             /* DSP clears us of being pulse */
09303             p->pulsedial = 0;
09304          } else if (p->waitingfordt.tv_sec) {
09305             if (ast_tvdiff_ms(ast_tvnow(), p->waitingfordt) >= p->waitfordialtone ) {
09306                p->waitingfordt.tv_sec = 0;
09307                ast_log(LOG_WARNING, "Never saw dialtone on channel %d\n", p->channel);
09308                ast_frfree(f);
09309                f = NULL;
09310             } else if (f->frametype == AST_FRAME_VOICE) {
09311                f->frametype = AST_FRAME_NULL;
09312                f->subclass.integer = 0;
09313                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) {
09314                   p->waitingfordt.tv_sec = 0;
09315                   p->dsp_features &= ~DSP_FEATURE_WAITDIALTONE;
09316                   ast_dsp_set_features(p->dsp, p->dsp_features);
09317                   ast_log(LOG_DEBUG, "Got 10 samples of dialtone!\n");
09318                   if (!ast_strlen_zero(p->dop.dialstr)) { /* Dial deferred digits */
09319                      res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
09320                      if (res < 0) {
09321                         ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d\n", p->channel);
09322                         p->dop.dialstr[0] = '\0';
09323                         ast_mutex_unlock(&p->lock);
09324                         ast_frfree(f);
09325                         return NULL;
09326                      } else {
09327                         ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", p->dop.dialstr);
09328                         p->dialing = 1;
09329                         p->dop.dialstr[0] = '\0';
09330                         p->dop.op = DAHDI_DIAL_OP_REPLACE;
09331                         ast_setstate(ast, AST_STATE_DIALING);
09332                      }
09333                   }
09334                }
09335             }
09336          }
09337       }
09338    } else
09339       f = &p->subs[idx].f;
09340 
09341    if (f) {
09342       switch (f->frametype) {
09343       case AST_FRAME_DTMF_BEGIN:
09344       case AST_FRAME_DTMF_END:
09345          if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
09346             analog_handle_dtmf(p->sig_pvt, ast, idx, &f);
09347          } else {
09348             dahdi_handle_dtmf(ast, idx, &f);
09349          }
09350          break;
09351       case AST_FRAME_VOICE:
09352          if (p->cidspill || p->cid_suppress_expire) {
09353             /* We are/were sending a caller id spill.  Suppress any echo. */
09354             p->subs[idx].f.frametype = AST_FRAME_NULL;
09355             p->subs[idx].f.subclass.integer = 0;
09356             p->subs[idx].f.samples = 0;
09357             p->subs[idx].f.mallocd = 0;
09358             p->subs[idx].f.offset = 0;
09359             p->subs[idx].f.data.ptr = NULL;
09360             p->subs[idx].f.datalen= 0;
09361          }
09362          break;
09363       default:
09364          break;
09365       }
09366    }
09367 
09368    ast_mutex_unlock(&p->lock);
09369    return f;
09370 }
09371 
09372 static int my_dahdi_write(struct dahdi_pvt *p, unsigned char *buf, int len, int idx, int linear)
09373 {
09374    int sent=0;
09375    int size;
09376    int res;
09377    int fd;
09378    fd = p->subs[idx].dfd;
09379    while (len) {
09380       size = len;
09381       if (size > (linear ? READ_SIZE * 2 : READ_SIZE))
09382          size = (linear ? READ_SIZE * 2 : READ_SIZE);
09383       res = write(fd, buf, size);
09384       if (res != size) {
09385          ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
09386          return sent;
09387       }
09388       len -= size;
09389       buf += size;
09390    }
09391    return sent;
09392 }
09393 
09394 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame)
09395 {
09396    struct dahdi_pvt *p = ast->tech_pvt;
09397    int res;
09398    int idx;
09399    idx = dahdi_get_index(ast, p, 0);
09400    if (idx < 0) {
09401       ast_log(LOG_WARNING, "%s doesn't really exist?\n", ast->name);
09402       return -1;
09403    }
09404 
09405    /* Write a frame of (presumably voice) data */
09406    if (frame->frametype != AST_FRAME_VOICE) {
09407       if (frame->frametype != AST_FRAME_IMAGE)
09408          ast_log(LOG_WARNING, "Don't know what to do with frame type '%u'\n", frame->frametype);
09409       return 0;
09410    }
09411    if ((frame->subclass.codec != AST_FORMAT_SLINEAR) &&
09412       (frame->subclass.codec != AST_FORMAT_ULAW) &&
09413       (frame->subclass.codec != AST_FORMAT_ALAW)) {
09414       ast_log(LOG_WARNING, "Cannot handle frames in %s format\n", ast_getformatname(frame->subclass.codec));
09415       return -1;
09416    }
09417    if (p->dialing) {
09418       ast_debug(1, "Dropping frame since I'm still dialing on %s...\n",ast->name);
09419       return 0;
09420    }
09421    if (!p->owner) {
09422       ast_debug(1, "Dropping frame since there is no active owner on %s...\n",ast->name);
09423       return 0;
09424    }
09425    if (p->cidspill) {
09426       ast_debug(1, "Dropping frame since I've still got a callerid spill on %s...\n",
09427          ast->name);
09428       return 0;
09429    }
09430    /* Return if it's not valid data */
09431    if (!frame->data.ptr || !frame->datalen)
09432       return 0;
09433 
09434    if (frame->subclass.codec == AST_FORMAT_SLINEAR) {
09435       if (!p->subs[idx].linear) {
09436          p->subs[idx].linear = 1;
09437          res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09438          if (res)
09439             ast_log(LOG_WARNING, "Unable to set linear mode on channel %d\n", p->channel);
09440       }
09441       res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 1);
09442    } else {
09443       /* x-law already */
09444       if (p->subs[idx].linear) {
09445          p->subs[idx].linear = 0;
09446          res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09447          if (res)
09448             ast_log(LOG_WARNING, "Unable to set companded mode on channel %d\n", p->channel);
09449       }
09450       res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 0);
09451    }
09452    if (res < 0) {
09453       ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
09454       return -1;
09455    }
09456    return 0;
09457 }
09458 
09459 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen)
09460 {
09461    struct dahdi_pvt *p = chan->tech_pvt;
09462    int res=-1;
09463    int idx;
09464    int func = DAHDI_FLASH;
09465 
09466    ast_mutex_lock(&p->lock);
09467    ast_debug(1, "Requested indication %d on channel %s\n", condition, chan->name);
09468    switch (p->sig) {
09469 #if defined(HAVE_PRI)
09470    case SIG_PRI_LIB_HANDLE_CASES:
09471       res = sig_pri_indicate(p->sig_pvt, chan, condition, data, datalen);
09472       ast_mutex_unlock(&p->lock);
09473       return res;
09474 #endif   /* defined(HAVE_PRI) */
09475 #if defined(HAVE_SS7)
09476    case SIG_SS7:
09477       res = sig_ss7_indicate(p->sig_pvt, chan, condition, data, datalen);
09478       ast_mutex_unlock(&p->lock);
09479       return res;
09480 #endif   /* defined(HAVE_SS7) */
09481    default:
09482       break;
09483    }
09484 #ifdef HAVE_OPENR2
09485    if (p->mfcr2 && !p->mfcr2_call_accepted) {
09486       ast_mutex_unlock(&p->lock);
09487       /* if this is an R2 call and the call is not yet accepted, we don't want the
09488          tone indications to mess up with the MF tones */
09489       return 0;
09490    }
09491 #endif
09492    idx = dahdi_get_index(chan, p, 0);
09493    if (idx == SUB_REAL) {
09494       switch (condition) {
09495       case AST_CONTROL_BUSY:
09496          res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_BUSY);
09497          break;
09498       case AST_CONTROL_RINGING:
09499          res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_RINGTONE);
09500 
09501          if (chan->_state != AST_STATE_UP) {
09502             if ((chan->_state != AST_STATE_RING) ||
09503                ((p->sig != SIG_FXSKS) &&
09504              (p->sig != SIG_FXSLS) &&
09505              (p->sig != SIG_FXSGS)))
09506             ast_setstate(chan, AST_STATE_RINGING);
09507          }
09508          break;
09509       case AST_CONTROL_INCOMPLETE:
09510          ast_debug(1, "Received AST_CONTROL_INCOMPLETE on %s\n", chan->name);
09511          /* act as a progress or proceeding, allowing the caller to enter additional numbers */
09512          res = 0;
09513          break;
09514       case AST_CONTROL_PROCEEDING:
09515          ast_debug(1, "Received AST_CONTROL_PROCEEDING on %s\n", chan->name);
09516          /* don't continue in ast_indicate */
09517          res = 0;
09518          break;
09519       case AST_CONTROL_PROGRESS:
09520          ast_debug(1, "Received AST_CONTROL_PROGRESS on %s\n", chan->name);
09521          /* don't continue in ast_indicate */
09522          res = 0;
09523          break;
09524       case AST_CONTROL_CONGESTION:
09525          /* There are many cause codes that generate an AST_CONTROL_CONGESTION. */
09526          switch (chan->hangupcause) {
09527          case AST_CAUSE_USER_BUSY:
09528          case AST_CAUSE_NORMAL_CLEARING:
09529          case 0:/* Cause has not been set. */
09530             /* Supply a more appropriate cause. */
09531             chan->hangupcause = AST_CAUSE_CONGESTION;
09532             break;
09533          default:
09534             break;
09535          }
09536          break;
09537       case AST_CONTROL_HOLD:
09538          ast_moh_start(chan, data, p->mohinterpret);
09539          break;
09540       case AST_CONTROL_UNHOLD:
09541          ast_moh_stop(chan);
09542          break;
09543       case AST_CONTROL_RADIO_KEY:
09544          if (p->radio)
09545             res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
09546          res = 0;
09547          break;
09548       case AST_CONTROL_RADIO_UNKEY:
09549          if (p->radio)
09550             res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_RINGOFF);
09551          res = 0;
09552          break;
09553       case AST_CONTROL_FLASH:
09554          /* flash hookswitch */
09555          if (ISTRUNK(p) && (p->sig != SIG_PRI)) {
09556             /* Clear out the dial buffer */
09557             p->dop.dialstr[0] = '\0';
09558             if ((ioctl(p->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
09559                ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
09560                   chan->name, strerror(errno));
09561             } else
09562                res = 0;
09563          } else
09564             res = 0;
09565          break;
09566       case AST_CONTROL_SRCUPDATE:
09567          res = 0;
09568          break;
09569       case -1:
09570          res = tone_zone_play_tone(p->subs[idx].dfd, -1);
09571          break;
09572       }
09573    } else {
09574       res = 0;
09575    }
09576    ast_mutex_unlock(&p->lock);
09577    return res;
09578 }
09579 
09580 #if defined(HAVE_PRI)
09581 static struct ast_str *create_channel_name(struct dahdi_pvt *i, int is_outgoing, char *address)
09582 #else
09583 static struct ast_str *create_channel_name(struct dahdi_pvt *i)
09584 #endif   /* defined(HAVE_PRI) */
09585 {
09586    struct ast_str *chan_name;
09587    int x, y;
09588 
09589    /* Create the new channel name tail. */
09590    if (!(chan_name = ast_str_create(32))) {
09591       return NULL;
09592    }
09593    if (i->channel == CHAN_PSEUDO) {
09594       ast_str_set(&chan_name, 0, "pseudo-%ld", ast_random());
09595 #if defined(HAVE_PRI)
09596    } else if (i->pri) {
09597       ast_mutex_lock(&i->pri->lock);
09598       y = ++i->pri->new_chan_seq;
09599       if (is_outgoing) {
09600          ast_str_set(&chan_name, 0, "i%d/%s-%x", i->pri->span, address, (unsigned)y);
09601          address[0] = '\0';
09602       } else if (ast_strlen_zero(i->cid_subaddr)) {
09603          /* Put in caller-id number only since there is no subaddress. */
09604          ast_str_set(&chan_name, 0, "i%d/%s-%x", i->pri->span, i->cid_num, (unsigned)y);
09605       } else {
09606          /* Put in caller-id number and subaddress. */
09607          ast_str_set(&chan_name, 0, "i%d/%s:%s-%x", i->pri->span, i->cid_num,
09608             i->cid_subaddr, (unsigned)y);
09609       }
09610       ast_mutex_unlock(&i->pri->lock);
09611 #endif   /* defined(HAVE_PRI) */
09612    } else {
09613       y = 1;
09614       do {
09615          ast_str_set(&chan_name, 0, "%d-%d", i->channel, y);
09616          for (x = 0; x < 3; ++x) {
09617             if (i->subs[x].owner && !strcasecmp(ast_str_buffer(chan_name),
09618                i->subs[x].owner->name + 6)) {
09619                break;
09620             }
09621          }
09622          ++y;
09623       } while (x < 3);
09624    }
09625    return chan_name;
09626 }
09627 
09628 static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpbx, int idx, int law, const char *linkedid)
09629 {
09630    struct ast_channel *tmp;
09631    format_t deflaw;
09632    int x;
09633    int features;
09634    struct ast_str *chan_name;
09635    struct ast_variable *v;
09636    char *dashptr;
09637    char device_name[AST_CHANNEL_NAME];
09638 
09639    if (i->subs[idx].owner) {
09640       ast_log(LOG_WARNING, "Channel %d already has a %s call\n", i->channel,subnames[idx]);
09641       return NULL;
09642    }
09643 
09644 #if defined(HAVE_PRI)
09645    /*
09646     * The dnid has been stuffed with the called-number[:subaddress]
09647     * by dahdi_request() for outgoing calls.
09648     */
09649    chan_name = create_channel_name(i, i->outgoing, i->dnid);
09650 #else
09651    chan_name = create_channel_name(i);
09652 #endif   /* defined(HAVE_PRI) */
09653    if (!chan_name) {
09654       return NULL;
09655    }
09656 
09657    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));
09658    ast_free(chan_name);
09659    if (!tmp)
09660       return NULL;
09661    tmp->tech = &dahdi_tech;
09662 #if defined(HAVE_PRI)
09663    if (i->pri) {
09664       ast_cc_copy_config_params(i->cc_params, i->pri->cc_params);
09665    }
09666 #endif   /* defined(HAVE_PRI) */
09667    ast_channel_cc_params_init(tmp, i->cc_params);
09668    if (law) {
09669       i->law = law;
09670       if (law == DAHDI_LAW_ALAW) {
09671          deflaw = AST_FORMAT_ALAW;
09672       } else {
09673          deflaw = AST_FORMAT_ULAW;
09674       }
09675    } else {
09676       switch (i->sig) {
09677       case SIG_PRI_LIB_HANDLE_CASES:
09678          /* Make sure companding law is known. */
09679          i->law = (i->law_default == DAHDI_LAW_ALAW)
09680             ? DAHDI_LAW_ALAW : DAHDI_LAW_MULAW;
09681          break;
09682       default:
09683          i->law = i->law_default;
09684          break;
09685       }
09686       if (i->law_default == DAHDI_LAW_ALAW) {
09687          deflaw = AST_FORMAT_ALAW;
09688       } else {
09689          deflaw = AST_FORMAT_ULAW;
09690       }
09691    }
09692    ast_channel_set_fd(tmp, 0, i->subs[idx].dfd);
09693    tmp->nativeformats = deflaw;
09694    /* Start out assuming ulaw since it's smaller :) */
09695    tmp->rawreadformat = deflaw;
09696    tmp->readformat = deflaw;
09697    tmp->rawwriteformat = deflaw;
09698    tmp->writeformat = deflaw;
09699    i->subs[idx].linear = 0;
09700    dahdi_setlinear(i->subs[idx].dfd, i->subs[idx].linear);
09701    features = 0;
09702    if (idx == SUB_REAL) {
09703       if (i->busydetect && CANBUSYDETECT(i))
09704          features |= DSP_FEATURE_BUSY_DETECT;
09705       if ((i->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(i))
09706          features |= DSP_FEATURE_CALL_PROGRESS;
09707       if ((i->waitfordialtone) && CANPROGRESSDETECT(i))
09708          features |= DSP_FEATURE_WAITDIALTONE;
09709       if ((!i->outgoing && (i->callprogress & CALLPROGRESS_FAX_INCOMING)) ||
09710          (i->outgoing && (i->callprogress & CALLPROGRESS_FAX_OUTGOING))) {
09711          features |= DSP_FEATURE_FAX_DETECT;
09712       }
09713       x = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
09714       if (ioctl(i->subs[idx].dfd, DAHDI_TONEDETECT, &x)) {
09715          i->hardwaredtmf = 0;
09716          features |= DSP_FEATURE_DIGIT_DETECT;
09717       } else if (NEED_MFDETECT(i)) {
09718          i->hardwaredtmf = 1;
09719          features |= DSP_FEATURE_DIGIT_DETECT;
09720       }
09721    }
09722    if (features) {
09723       if (i->dsp) {
09724          ast_debug(1, "Already have a dsp on %s?\n", tmp->name);
09725       } else {
09726          if (i->channel != CHAN_PSEUDO)
09727             i->dsp = ast_dsp_new();
09728          else
09729             i->dsp = NULL;
09730          if (i->dsp) {
09731             i->dsp_features = features;
09732 #if defined(HAVE_PRI) || defined(HAVE_SS7)
09733             /* We cannot do progress detection until receive PROGRESS message */
09734             if (i->outgoing && (dahdi_sig_pri_lib_handles(i->sig) || (i->sig == SIG_SS7))) {
09735                /* Remember requested DSP features, don't treat
09736                   talking as ANSWER */
09737                i->dsp_features = features & ~DSP_PROGRESS_TALK;
09738                features = 0;
09739             }
09740 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
09741             ast_dsp_set_features(i->dsp, features);
09742             ast_dsp_set_digitmode(i->dsp, DSP_DIGITMODE_DTMF | i->dtmfrelax);
09743             if (!ast_strlen_zero(progzone))
09744                ast_dsp_set_call_progress_zone(i->dsp, progzone);
09745             if (i->busydetect && CANBUSYDETECT(i)) {
09746                ast_dsp_set_busy_count(i->dsp, i->busycount);
09747                ast_dsp_set_busy_pattern(i->dsp, i->busy_tonelength, i->busy_quietlength);
09748             }
09749          }
09750       }
09751    }
09752 
09753    if (state == AST_STATE_RING)
09754       tmp->rings = 1;
09755    tmp->tech_pvt = i;
09756    if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) {
09757       /* Only FXO signalled stuff can be picked up */
09758       tmp->callgroup = i->callgroup;
09759       tmp->pickupgroup = i->pickupgroup;
09760    }
09761    if (!ast_strlen_zero(i->parkinglot))
09762       ast_string_field_set(tmp, parkinglot, i->parkinglot);
09763    if (!ast_strlen_zero(i->language))
09764       ast_string_field_set(tmp, language, i->language);
09765    if (!i->owner)
09766       i->owner = tmp;
09767    if (!ast_strlen_zero(i->accountcode))
09768       ast_string_field_set(tmp, accountcode, i->accountcode);
09769    if (i->amaflags)
09770       tmp->amaflags = i->amaflags;
09771    i->subs[idx].owner = tmp;
09772    ast_copy_string(tmp->context, i->context, sizeof(tmp->context));
09773    if (!analog_lib_handles(i->sig, i->radio, i->oprmode)) {
09774       ast_string_field_set(tmp, call_forward, i->call_forward);
09775    }
09776    /* If we've been told "no ADSI" then enforce it */
09777    if (!i->adsi)
09778       tmp->adsicpe = AST_ADSI_UNAVAILABLE;
09779    if (!ast_strlen_zero(i->exten))
09780       ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten));
09781    if (!ast_strlen_zero(i->rdnis)) {
09782       tmp->redirecting.from.number.valid = 1;
09783       tmp->redirecting.from.number.str = ast_strdup(i->rdnis);
09784    }
09785    if (!ast_strlen_zero(i->dnid)) {
09786       tmp->dialed.number.str = ast_strdup(i->dnid);
09787    }
09788 
09789    /* Don't use ast_set_callerid() here because it will
09790     * generate a needless NewCallerID event */
09791 #if defined(HAVE_PRI) || defined(HAVE_SS7)
09792    if (!ast_strlen_zero(i->cid_ani)) {
09793       tmp->caller.ani.number.valid = 1;
09794       tmp->caller.ani.number.str = ast_strdup(i->cid_ani);
09795    } else if (!ast_strlen_zero(i->cid_num)) {
09796       tmp->caller.ani.number.valid = 1;
09797       tmp->caller.ani.number.str = ast_strdup(i->cid_num);
09798    }
09799 #else
09800    if (!ast_strlen_zero(i->cid_num)) {
09801       tmp->caller.ani.number.valid = 1;
09802       tmp->caller.ani.number.str = ast_strdup(i->cid_num);
09803    }
09804 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
09805    tmp->caller.id.name.presentation = i->callingpres;
09806    tmp->caller.id.number.presentation = i->callingpres;
09807    tmp->caller.id.number.plan = i->cid_ton;
09808    tmp->caller.ani2 = i->cid_ani2;
09809    tmp->caller.id.tag = ast_strdup(i->cid_tag);
09810    /* clear the fake event in case we posted one before we had ast_channel */
09811    i->fake_event = 0;
09812    /* Assure there is no confmute on this channel */
09813    dahdi_confmute(i, 0);
09814    i->muting = 0;
09815    /* Configure the new channel jb */
09816    ast_jb_configure(tmp, &global_jbconf);
09817 
09818    /* Set initial device state */
09819    ast_copy_string(device_name, tmp->name, sizeof(device_name));
09820    dashptr = strrchr(device_name, '-');
09821    if (dashptr) {
09822       *dashptr = '\0';
09823    }
09824    tmp->flags |= AST_FLAG_DISABLE_DEVSTATE_CACHE;
09825    ast_devstate_changed_literal(AST_DEVICE_UNKNOWN, AST_DEVSTATE_NOT_CACHABLE, device_name);
09826 
09827    for (v = i->vars ; v ; v = v->next)
09828       pbx_builtin_setvar_helper(tmp, v->name, v->value);
09829 
09830    ast_module_ref(ast_module_info->self);
09831 
09832    dahdi_ami_channel_event(i, tmp);
09833    if (startpbx) {
09834 #ifdef HAVE_OPENR2
09835       if (i->mfcr2call) {
09836          pbx_builtin_setvar_helper(tmp, "MFCR2_CATEGORY", openr2_proto_get_category_string(i->mfcr2_recvd_category));
09837       }
09838 #endif
09839       if (ast_pbx_start(tmp)) {
09840          ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
09841          ast_hangup(tmp);
09842          return NULL;
09843       }
09844    }
09845    return tmp;
09846 }
09847 
09848 
09849 static int my_getsigstr(struct ast_channel *chan, char *str, const char *term, int ms)
09850 {
09851    char c;
09852 
09853    *str = 0; /* start with empty output buffer */
09854    for (;;)
09855    {
09856       /* Wait for the first digit (up to specified ms). */
09857       c = ast_waitfordigit(chan, ms);
09858       /* if timeout, hangup or error, return as such */
09859       if (c < 1)
09860          return c;
09861       *str++ = c;
09862       *str = 0;
09863       if (strchr(term, c))
09864          return 1;
09865    }
09866 }
09867 
09868 static int dahdi_wink(struct dahdi_pvt *p, int idx)
09869 {
09870    int j;
09871    dahdi_set_hook(p->subs[idx].dfd, DAHDI_WINK);
09872    for (;;)
09873    {
09874       /* set bits of interest */
09875       j = DAHDI_IOMUX_SIGEVENT;
09876       /* wait for some happening */
09877       if (ioctl(p->subs[idx].dfd,DAHDI_IOMUX,&j) == -1) return(-1);
09878       /* exit loop if we have it */
09879       if (j & DAHDI_IOMUX_SIGEVENT) break;
09880    }
09881    /* get the event info */
09882    if (ioctl(p->subs[idx].dfd,DAHDI_GETEVENT,&j) == -1) return(-1);
09883    return 0;
09884 }
09885 
09886 /*! \brief enable or disable the chan_dahdi Do-Not-Disturb mode for a DAHDI channel
09887  * \param dahdichan "Physical" DAHDI channel (e.g: DAHDI/5)
09888  * \param flag on 1 to enable, 0 to disable, -1 return dnd value
09889  *
09890  * chan_dahdi has a DND (Do Not Disturb) mode for each dahdichan (physical
09891  * DAHDI channel). Use this to enable or disable it.
09892  *
09893  * \bug the use of the word "channel" for those dahdichans is really confusing.
09894  */
09895 static int dahdi_dnd(struct dahdi_pvt *dahdichan, int flag)
09896 {
09897    if (analog_lib_handles(dahdichan->sig, dahdichan->radio, dahdichan->oprmode)) {
09898       return analog_dnd(dahdichan->sig_pvt, flag);
09899    }
09900 
09901    if (flag == -1) {
09902       return dahdichan->dnd;
09903    }
09904 
09905    /* Do not disturb */
09906    dahdichan->dnd = flag;
09907    ast_verb(3, "%s DND on channel %d\n",
09908          flag? "Enabled" : "Disabled",
09909          dahdichan->channel);
09910    manager_event(EVENT_FLAG_SYSTEM, "DNDState",
09911          "Channel: DAHDI/%d\r\n"
09912          "Status: %s\r\n", dahdichan->channel,
09913          flag? "enabled" : "disabled");
09914 
09915    return 0;
09916 }
09917 
09918 static int canmatch_featurecode(const char *exten)
09919 {
09920    int extlen = strlen(exten);
09921    const char *pickup_ext;
09922    if (!extlen) {
09923       return 1;
09924    }
09925    pickup_ext = ast_pickup_ext();
09926    if (extlen < strlen(pickup_ext) && !strncmp(pickup_ext, exten, extlen)) {
09927       return 1;
09928    }
09929    /* hardcoded features are *60, *67, *69, *70, *72, *73, *78, *79, *82, *0 */
09930    if (exten[0] == '*' && extlen < 3) {
09931       if (extlen == 1) {
09932          return 1;
09933       }
09934       /* "*0" should be processed before it gets here */
09935       switch (exten[1]) {
09936       case '6':
09937       case '7':
09938       case '8':
09939          return 1;
09940       }
09941    }
09942    return 0;
09943 }
09944 
09945 static void *analog_ss_thread(void *data)
09946 {
09947    struct ast_channel *chan = data;
09948    struct dahdi_pvt *p = chan->tech_pvt;
09949    char exten[AST_MAX_EXTENSION] = "";
09950    char exten2[AST_MAX_EXTENSION] = "";
09951    unsigned char buf[256];
09952    char dtmfcid[300];
09953    char dtmfbuf[300];
09954    struct callerid_state *cs = NULL;
09955    char *name = NULL, *number = NULL;
09956    int distMatches;
09957    int curRingData[3];
09958    int receivedRingT;
09959    int counter1;
09960    int counter;
09961    int samples = 0;
09962    struct ast_smdi_md_message *smdi_msg = NULL;
09963    int flags = 0;
09964    int i;
09965    int timeout;
09966    int getforward = 0;
09967    char *s1, *s2;
09968    int len = 0;
09969    int res;
09970    int idx;
09971 
09972    ast_mutex_lock(&ss_thread_lock);
09973    ss_thread_count++;
09974    ast_mutex_unlock(&ss_thread_lock);
09975    /* in the bizarre case where the channel has become a zombie before we
09976       even get started here, abort safely
09977    */
09978    if (!p) {
09979       ast_log(LOG_WARNING, "Channel became a zombie before simple switch could be started (%s)\n", chan->name);
09980       ast_hangup(chan);
09981       goto quit;
09982    }
09983    ast_verb(3, "Starting simple switch on '%s'\n", chan->name);
09984    idx = dahdi_get_index(chan, p, 1);
09985    if (idx < 0) {
09986       ast_log(LOG_WARNING, "Huh?\n");
09987       ast_hangup(chan);
09988       goto quit;
09989    }
09990    if (p->dsp)
09991       ast_dsp_digitreset(p->dsp);
09992    switch (p->sig) {
09993    case SIG_FEATD:
09994    case SIG_FEATDMF:
09995    case SIG_FEATDMF_TA:
09996    case SIG_E911:
09997    case SIG_FGC_CAMAMF:
09998    case SIG_FEATB:
09999    case SIG_EMWINK:
10000    case SIG_SF_FEATD:
10001    case SIG_SF_FEATDMF:
10002    case SIG_SF_FEATB:
10003    case SIG_SFWINK:
10004       if (dahdi_wink(p, idx))
10005          goto quit;
10006       /* Fall through */
10007    case SIG_EM:
10008    case SIG_EM_E1:
10009    case SIG_SF:
10010    case SIG_FGC_CAMA:
10011       res = tone_zone_play_tone(p->subs[idx].dfd, -1);
10012       if (p->dsp)
10013          ast_dsp_digitreset(p->dsp);
10014       /* set digit mode appropriately */
10015       if (p->dsp) {
10016          if (NEED_MFDETECT(p))
10017             ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
10018          else
10019             ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
10020       }
10021       memset(dtmfbuf, 0, sizeof(dtmfbuf));
10022       /* Wait for the first digit only if immediate=no */
10023       if (!p->immediate)
10024          /* Wait for the first digit (up to 5 seconds). */
10025          res = ast_waitfordigit(chan, 5000);
10026       else
10027          res = 0;
10028       if (res > 0) {
10029          /* save first char */
10030          dtmfbuf[0] = res;
10031          switch (p->sig) {
10032          case SIG_FEATD:
10033          case SIG_SF_FEATD:
10034             res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
10035             if (res > 0)
10036                res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
10037             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
10038             break;
10039          case SIG_FEATDMF_TA:
10040             res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
10041             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
10042             if (dahdi_wink(p, idx)) goto quit;
10043             dtmfbuf[0] = 0;
10044             /* Wait for the first digit (up to 5 seconds). */
10045             res = ast_waitfordigit(chan, 5000);
10046             if (res <= 0) break;
10047             dtmfbuf[0] = res;
10048             /* fall through intentionally */
10049          case SIG_FEATDMF:
10050          case SIG_E911:
10051          case SIG_FGC_CAMAMF:
10052          case SIG_SF_FEATDMF:
10053             res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
10054             /* if international caca, do it again to get real ANO */
10055             if ((p->sig == SIG_FEATDMF) && (dtmfbuf[1] != '0') && (strlen(dtmfbuf) != 14))
10056             {
10057                if (dahdi_wink(p, idx)) goto quit;
10058                dtmfbuf[0] = 0;
10059                /* Wait for the first digit (up to 5 seconds). */
10060                res = ast_waitfordigit(chan, 5000);
10061                if (res <= 0) break;
10062                dtmfbuf[0] = res;
10063                res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
10064             }
10065             if (res > 0) {
10066                /* if E911, take off hook */
10067                if (p->sig == SIG_E911)
10068                   dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
10069                res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "#", 3000);
10070             }
10071             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
10072             break;
10073          case SIG_FEATB:
10074          case SIG_SF_FEATB:
10075             res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
10076             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
10077             break;
10078          case SIG_EMWINK:
10079             /* if we received a '*', we are actually receiving Feature Group D
10080                dial syntax, so use that mode; otherwise, fall through to normal
10081                mode
10082             */
10083             if (res == '*') {
10084                res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
10085                if (res > 0)
10086                   res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
10087                if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
10088                break;
10089             }
10090          default:
10091             /* If we got the first digit, get the rest */
10092             len = 1;
10093             dtmfbuf[len] = '\0';
10094             while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
10095                if (ast_exists_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
10096                   timeout = matchdigittimeout;
10097                } else {
10098                   timeout = gendigittimeout;
10099                }
10100                res = ast_waitfordigit(chan, timeout);
10101                if (res < 0) {
10102                   ast_debug(1, "waitfordigit returned < 0...\n");
10103                   ast_hangup(chan);
10104                   goto quit;
10105                } else if (res) {
10106                   dtmfbuf[len++] = res;
10107                   dtmfbuf[len] = '\0';
10108                } else {
10109                   break;
10110                }
10111             }
10112             break;
10113          }
10114       }
10115       if (res == -1) {
10116          ast_log(LOG_WARNING, "getdtmf on channel %d: %s\n", p->channel, strerror(errno));
10117          ast_hangup(chan);
10118          goto quit;
10119       } else if (res < 0) {
10120          ast_debug(1, "Got hung up before digits finished\n");
10121          ast_hangup(chan);
10122          goto quit;
10123       }
10124 
10125       if (p->sig == SIG_FGC_CAMA) {
10126          char anibuf[100];
10127 
10128          if (ast_safe_sleep(chan,1000) == -1) {
10129             ast_hangup(chan);
10130             goto quit;
10131          }
10132          dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
10133          ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
10134          res = my_getsigstr(chan, anibuf, "#", 10000);
10135          if ((res > 0) && (strlen(anibuf) > 2)) {
10136             if (anibuf[strlen(anibuf) - 1] == '#')
10137                anibuf[strlen(anibuf) - 1] = 0;
10138             ast_set_callerid(chan, anibuf + 2, NULL, anibuf + 2);
10139          }
10140          ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
10141       }
10142 
10143       ast_copy_string(exten, dtmfbuf, sizeof(exten));
10144       if (ast_strlen_zero(exten))
10145          ast_copy_string(exten, "s", sizeof(exten));
10146       if (p->sig == SIG_FEATD || p->sig == SIG_EMWINK) {
10147          /* Look for Feature Group D on all E&M Wink and Feature Group D trunks */
10148          if (exten[0] == '*') {
10149             char *stringp=NULL;
10150             ast_copy_string(exten2, exten, sizeof(exten2));
10151             /* Parse out extension and callerid */
10152             stringp=exten2 +1;
10153             s1 = strsep(&stringp, "*");
10154             s2 = strsep(&stringp, "*");
10155             if (s2) {
10156                if (!ast_strlen_zero(p->cid_num))
10157                   ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
10158                else
10159                   ast_set_callerid(chan, s1, NULL, s1);
10160                ast_copy_string(exten, s2, sizeof(exten));
10161             } else
10162                ast_copy_string(exten, s1, sizeof(exten));
10163          } else if (p->sig == SIG_FEATD)
10164             ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d.  Assuming E&M Wink instead\n", p->channel);
10165       }
10166       if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
10167          if (exten[0] == '*') {
10168             char *stringp=NULL;
10169             ast_copy_string(exten2, exten, sizeof(exten2));
10170             /* Parse out extension and callerid */
10171             stringp=exten2 +1;
10172             s1 = strsep(&stringp, "#");
10173             s2 = strsep(&stringp, "#");
10174             if (s2) {
10175                if (!ast_strlen_zero(p->cid_num))
10176                   ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
10177                else
10178                   if (*(s1 + 2))
10179                      ast_set_callerid(chan, s1 + 2, NULL, s1 + 2);
10180                ast_copy_string(exten, s2 + 1, sizeof(exten));
10181             } else
10182                ast_copy_string(exten, s1 + 2, sizeof(exten));
10183          } else
10184             ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d.  Assuming E&M Wink instead\n", p->channel);
10185       }
10186       if ((p->sig == SIG_E911) || (p->sig == SIG_FGC_CAMAMF)) {
10187          if (exten[0] == '*') {
10188             char *stringp=NULL;
10189             ast_copy_string(exten2, exten, sizeof(exten2));
10190             /* Parse out extension and callerid */
10191             stringp=exten2 +1;
10192             s1 = strsep(&stringp, "#");
10193             s2 = strsep(&stringp, "#");
10194             if (s2 && (*(s2 + 1) == '0')) {
10195                if (*(s2 + 2))
10196                   ast_set_callerid(chan, s2 + 2, NULL, s2 + 2);
10197             }
10198             if (s1)  ast_copy_string(exten, s1, sizeof(exten));
10199             else ast_copy_string(exten, "911", sizeof(exten));
10200          } else
10201             ast_log(LOG_WARNING, "Got a non-E911/FGC CAMA input on channel %d.  Assuming E&M Wink instead\n", p->channel);
10202       }
10203       if (p->sig == SIG_FEATB) {
10204          if (exten[0] == '*') {
10205             char *stringp=NULL;
10206             ast_copy_string(exten2, exten, sizeof(exten2));
10207             /* Parse out extension and callerid */
10208             stringp=exten2 +1;
10209             s1 = strsep(&stringp, "#");
10210             ast_copy_string(exten, exten2 + 1, sizeof(exten));
10211          } else
10212             ast_log(LOG_WARNING, "Got a non-Feature Group B input on channel %d.  Assuming E&M Wink instead\n", p->channel);
10213       }
10214       if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
10215          dahdi_wink(p, idx);
10216          /* some switches require a minimum guard time between
10217             the last FGD wink and something that answers
10218             immediately. This ensures it */
10219          if (ast_safe_sleep(chan, 100)) {
10220             ast_hangup(chan);
10221             goto quit;
10222          }
10223       }
10224       dahdi_enable_ec(p);
10225       if (NEED_MFDETECT(p)) {
10226          if (p->dsp) {
10227             if (!p->hardwaredtmf)
10228                ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
10229             else {
10230                ast_dsp_free(p->dsp);
10231                p->dsp = NULL;
10232             }
10233          }
10234       }
10235 
10236       if (ast_exists_extension(chan, chan->context, exten, 1,
10237          S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
10238          ast_copy_string(chan->exten, exten, sizeof(chan->exten));
10239          if (p->dsp) ast_dsp_digitreset(p->dsp);
10240          res = ast_pbx_run(chan);
10241          if (res) {
10242             ast_log(LOG_WARNING, "PBX exited non-zero\n");
10243             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10244          }
10245          goto quit;
10246       } else {
10247          ast_verb(2, "Unknown extension '%s' in context '%s' requested\n", exten, chan->context);
10248          sleep(2);
10249          res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_INFO);
10250          if (res < 0)
10251             ast_log(LOG_WARNING, "Unable to start special tone on %d\n", p->channel);
10252          else
10253             sleep(1);
10254          res = ast_streamfile(chan, "ss-noservice", chan->language);
10255          if (res >= 0)
10256             ast_waitstream(chan, "");
10257          res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10258          ast_hangup(chan);
10259          goto quit;
10260       }
10261       break;
10262    case SIG_FXOLS:
10263    case SIG_FXOGS:
10264    case SIG_FXOKS:
10265       /* Read the first digit */
10266       timeout = firstdigittimeout;
10267       /* If starting a threeway call, never timeout on the first digit so someone
10268          can use flash-hook as a "hold" feature */
10269       if (p->subs[SUB_THREEWAY].owner)
10270          timeout = 999999;
10271       while (len < AST_MAX_EXTENSION-1) {
10272          /* Read digit unless it's supposed to be immediate, in which case the
10273             only answer is 's' */
10274          if (p->immediate)
10275             res = 's';
10276          else
10277             res = ast_waitfordigit(chan, timeout);
10278          timeout = 0;
10279          if (res < 0) {
10280             ast_debug(1, "waitfordigit returned < 0...\n");
10281             res = tone_zone_play_tone(p->subs[idx].dfd, -1);
10282             ast_hangup(chan);
10283             goto quit;
10284          } else if (res) {
10285             ast_debug(1,"waitfordigit returned '%c' (%d), timeout = %d\n", res, res, timeout);
10286             exten[len++]=res;
10287             exten[len] = '\0';
10288          }
10289          if (!ast_ignore_pattern(chan->context, exten))
10290             tone_zone_play_tone(p->subs[idx].dfd, -1);
10291          else
10292             tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
10293          if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num) && !ast_parking_ext_valid(exten, chan, chan->context)) {
10294             if (!res || !ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
10295                if (getforward) {
10296                   /* Record this as the forwarding extension */
10297                   ast_copy_string(p->call_forward, exten, sizeof(p->call_forward));
10298                   ast_verb(3, "Setting call forward to '%s' on channel %d\n", p->call_forward, p->channel);
10299                   res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10300                   if (res)
10301                      break;
10302                   usleep(500000);
10303                   res = tone_zone_play_tone(p->subs[idx].dfd, -1);
10304                   sleep(1);
10305                   memset(exten, 0, sizeof(exten));
10306                   res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
10307                   len = 0;
10308                   getforward = 0;
10309                } else {
10310                   res = tone_zone_play_tone(p->subs[idx].dfd, -1);
10311                   ast_copy_string(chan->exten, exten, sizeof(chan->exten));
10312                   if (!ast_strlen_zero(p->cid_num)) {
10313                      if (!p->hidecallerid)
10314                         ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
10315                      else
10316                         ast_set_callerid(chan, NULL, NULL, p->cid_num);
10317                   }
10318                   if (!ast_strlen_zero(p->cid_name)) {
10319                      if (!p->hidecallerid)
10320                         ast_set_callerid(chan, NULL, p->cid_name, NULL);
10321                   }
10322                   ast_setstate(chan, AST_STATE_RING);
10323                   dahdi_enable_ec(p);
10324                   res = ast_pbx_run(chan);
10325                   if (res) {
10326                      ast_log(LOG_WARNING, "PBX exited non-zero\n");
10327                      res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10328                   }
10329                   goto quit;
10330                }
10331             } else {
10332                /* It's a match, but they just typed a digit, and there is an ambiguous match,
10333                   so just set the timeout to matchdigittimeout and wait some more */
10334                timeout = matchdigittimeout;
10335             }
10336          } else if (res == 0) {
10337             ast_debug(1, "not enough digits (and no ambiguous match)...\n");
10338             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10339             dahdi_wait_event(p->subs[idx].dfd);
10340             ast_hangup(chan);
10341             goto quit;
10342          } else if (p->callwaiting && !strcmp(exten, "*70")) {
10343             ast_verb(3, "Disabling call waiting on %s\n", chan->name);
10344             /* Disable call waiting if enabled */
10345             p->callwaiting = 0;
10346             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10347             if (res) {
10348                ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
10349                   chan->name, strerror(errno));
10350             }
10351             len = 0;
10352             ioctl(p->subs[idx].dfd,DAHDI_CONFDIAG,&len);
10353             memset(exten, 0, sizeof(exten));
10354             timeout = firstdigittimeout;
10355 
10356          } else if (!strcmp(exten,ast_pickup_ext())) {
10357             /* Scan all channels and see if there are any
10358              * ringing channels that have call groups
10359              * that equal this channels pickup group
10360              */
10361             if (idx == SUB_REAL) {
10362                /* Switch us from Third call to Call Wait */
10363                if (p->subs[SUB_THREEWAY].owner) {
10364                   /* If you make a threeway call and the *8# a call, it should actually
10365                      look like a callwait */
10366                   alloc_sub(p, SUB_CALLWAIT);
10367                   swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
10368                   unalloc_sub(p, SUB_THREEWAY);
10369                }
10370                dahdi_enable_ec(p);
10371                if (ast_pickup_call(chan)) {
10372                   ast_debug(1, "No call pickup possible...\n");
10373                   res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10374                   dahdi_wait_event(p->subs[idx].dfd);
10375                }
10376                ast_hangup(chan);
10377                goto quit;
10378             } else {
10379                ast_log(LOG_WARNING, "Huh?  Got *8# on call not on real\n");
10380                ast_hangup(chan);
10381                goto quit;
10382             }
10383 
10384          } else if (!p->hidecallerid && !strcmp(exten, "*67")) {
10385             ast_verb(3, "Disabling Caller*ID on %s\n", chan->name);
10386             /* Disable Caller*ID if enabled */
10387             p->hidecallerid = 1;
10388             ast_party_number_free(&chan->caller.id.number);
10389             ast_party_number_init(&chan->caller.id.number);
10390             ast_party_name_free(&chan->caller.id.name);
10391             ast_party_name_init(&chan->caller.id.name);
10392             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10393             if (res) {
10394                ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
10395                   chan->name, strerror(errno));
10396             }
10397             len = 0;
10398             memset(exten, 0, sizeof(exten));
10399             timeout = firstdigittimeout;
10400          } else if (p->callreturn && !strcmp(exten, "*69")) {
10401             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10402             break;
10403          } else if (!strcmp(exten, "*78")) {
10404             dahdi_dnd(p, 1);
10405             /* Do not disturb */
10406             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10407             getforward = 0;
10408             memset(exten, 0, sizeof(exten));
10409             len = 0;
10410          } else if (!strcmp(exten, "*79")) {
10411             dahdi_dnd(p, 0);
10412             /* Do not disturb */
10413             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10414             getforward = 0;
10415             memset(exten, 0, sizeof(exten));
10416             len = 0;
10417          } else if (p->cancallforward && !strcmp(exten, "*72")) {
10418             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10419             getforward = 1;
10420             memset(exten, 0, sizeof(exten));
10421             len = 0;
10422          } else if (p->cancallforward && !strcmp(exten, "*73")) {
10423             ast_verb(3, "Cancelling call forwarding on channel %d\n", p->channel);
10424             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10425             memset(p->call_forward, 0, sizeof(p->call_forward));
10426             getforward = 0;
10427             memset(exten, 0, sizeof(exten));
10428             len = 0;
10429          } else if ((p->transfer || p->canpark) && ast_parking_ext_valid(exten, chan, chan->context) &&
10430                   p->subs[SUB_THREEWAY].owner &&
10431                   ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
10432             /* This is a three way call, the main call being a real channel,
10433                and we're parking the first call. */
10434             ast_masq_park_call_exten(ast_bridged_channel(p->subs[SUB_THREEWAY].owner),
10435                chan, exten, chan->context, 0, NULL);
10436             ast_verb(3, "Parking call to '%s'\n", chan->name);
10437             break;
10438          } else if (p->hidecallerid && !strcmp(exten, "*82")) {
10439             ast_verb(3, "Enabling Caller*ID on %s\n", chan->name);
10440             /* Enable Caller*ID if enabled */
10441             p->hidecallerid = 0;
10442             ast_set_callerid(chan, p->cid_num, p->cid_name, NULL);
10443             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10444             if (res) {
10445                ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
10446                   chan->name, strerror(errno));
10447             }
10448             len = 0;
10449             memset(exten, 0, sizeof(exten));
10450             timeout = firstdigittimeout;
10451          } else if (!strcmp(exten, "*0")) {
10452             struct ast_channel *nbridge =
10453                p->subs[SUB_THREEWAY].owner;
10454             struct dahdi_pvt *pbridge = NULL;
10455             /* set up the private struct of the bridged one, if any */
10456             if (nbridge && ast_bridged_channel(nbridge))
10457                pbridge = ast_bridged_channel(nbridge)->tech_pvt;
10458             if (nbridge && pbridge &&
10459                (nbridge->tech == &dahdi_tech) &&
10460                (ast_bridged_channel(nbridge)->tech == &dahdi_tech) &&
10461                ISTRUNK(pbridge)) {
10462                int func = DAHDI_FLASH;
10463                /* Clear out the dial buffer */
10464                p->dop.dialstr[0] = '\0';
10465                /* flash hookswitch */
10466                if ((ioctl(pbridge->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
10467                   ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
10468                      nbridge->name, strerror(errno));
10469                }
10470                swap_subs(p, SUB_REAL, SUB_THREEWAY);
10471                unalloc_sub(p, SUB_THREEWAY);
10472                p->owner = p->subs[SUB_REAL].owner;
10473                if (ast_bridged_channel(p->subs[SUB_REAL].owner))
10474                   ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
10475                ast_hangup(chan);
10476                goto quit;
10477             } else {
10478                tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10479                dahdi_wait_event(p->subs[idx].dfd);
10480                tone_zone_play_tone(p->subs[idx].dfd, -1);
10481                swap_subs(p, SUB_REAL, SUB_THREEWAY);
10482                unalloc_sub(p, SUB_THREEWAY);
10483                p->owner = p->subs[SUB_REAL].owner;
10484                ast_hangup(chan);
10485                goto quit;
10486             }
10487          } else if (!ast_canmatch_extension(chan, chan->context, exten, 1,
10488             S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))
10489             && !canmatch_featurecode(exten)) {
10490             ast_debug(1, "Can't match %s from '%s' in context %s\n", exten,
10491                S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, "<Unknown Caller>"),
10492                chan->context);
10493             break;
10494          }
10495          if (!timeout)
10496             timeout = gendigittimeout;
10497          if (len && !ast_ignore_pattern(chan->context, exten))
10498             tone_zone_play_tone(p->subs[idx].dfd, -1);
10499       }
10500       break;
10501    case SIG_FXSLS:
10502    case SIG_FXSGS:
10503    case SIG_FXSKS:
10504       /* check for SMDI messages */
10505       if (p->use_smdi && p->smdi_iface) {
10506          smdi_msg = ast_smdi_md_message_wait(p->smdi_iface, SMDI_MD_WAIT_TIMEOUT);
10507 
10508          if (smdi_msg != NULL) {
10509             ast_copy_string(chan->exten, smdi_msg->fwd_st, sizeof(chan->exten));
10510 
10511             if (smdi_msg->type == 'B')
10512                pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "b");
10513             else if (smdi_msg->type == 'N')
10514                pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "u");
10515 
10516             ast_debug(1, "Received SMDI message on %s\n", chan->name);
10517          } else {
10518             ast_log(LOG_WARNING, "SMDI enabled but no SMDI message present\n");
10519          }
10520       }
10521 
10522       if (p->use_callerid && (p->cid_signalling == CID_SIG_SMDI && smdi_msg)) {
10523          number = smdi_msg->calling_st;
10524 
10525       /* If we want caller id, we're in a prering state due to a polarity reversal
10526        * and we're set to use a polarity reversal to trigger the start of caller id,
10527        * grab the caller id and wait for ringing to start... */
10528       } else if (p->use_callerid && (chan->_state == AST_STATE_PRERING &&
10529                    (p->cid_start == CID_START_POLARITY || p->cid_start == CID_START_POLARITY_IN || p->cid_start == CID_START_DTMF_NOALERT))) {
10530          /* If set to use DTMF CID signalling, listen for DTMF */
10531          if (p->cid_signalling == CID_SIG_DTMF) {
10532             int k = 0;
10533             int off_ms;
10534             struct timeval start = ast_tvnow();
10535             int ms;
10536             cs = NULL;
10537             ast_debug(1, "Receiving DTMF cid on channel %s\n", chan->name);
10538             dahdi_setlinear(p->subs[idx].dfd, 0);
10539             /*
10540              * We are the only party interested in the Rx stream since
10541              * we have not answered yet.  We don't need or even want DTMF
10542              * emulation.  The DTMF digits can come so fast that emulation
10543              * can drop some of them.
10544              */
10545             ast_set_flag(chan, AST_FLAG_END_DTMF_ONLY);
10546             off_ms = 4000;/* This is a typical OFF time between rings. */
10547             for (;;) {
10548                struct ast_frame *f;
10549 
10550                ms = ast_remaining_ms(start, off_ms);
10551                res = ast_waitfor(chan, ms);
10552                if (res <= 0) {
10553                   /*
10554                    * We do not need to restore the dahdi_setlinear()
10555                    * or AST_FLAG_END_DTMF_ONLY flag settings since we
10556                    * are hanging up the channel.
10557                    */
10558                   ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
10559                      "Exiting simple switch\n");
10560                   ast_hangup(chan);
10561                   goto quit;
10562                }
10563                f = ast_read(chan);
10564                if (!f)
10565                   break;
10566                if (f->frametype == AST_FRAME_DTMF) {
10567                   if (k < ARRAY_LEN(dtmfbuf) - 1) {
10568                      dtmfbuf[k++] = f->subclass.integer;
10569                   }
10570                   ast_debug(1, "CID got digit '%c'\n", f->subclass.integer);
10571                   start = ast_tvnow();
10572                }
10573                ast_frfree(f);
10574                if (chan->_state == AST_STATE_RING ||
10575                   chan->_state == AST_STATE_RINGING)
10576                   break; /* Got ring */
10577             }
10578             ast_clear_flag(chan, AST_FLAG_END_DTMF_ONLY);
10579             dtmfbuf[k] = '\0';
10580             dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10581             /* Got cid and ring. */
10582             ast_debug(1, "CID got string '%s'\n", dtmfbuf);
10583             callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
10584             ast_debug(1, "CID is '%s', flags %d\n", dtmfcid, flags);
10585             /* If first byte is NULL, we have no cid */
10586             if (!ast_strlen_zero(dtmfcid))
10587                number = dtmfcid;
10588             else
10589                number = NULL;
10590          /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */
10591          } else if ((p->cid_signalling == CID_SIG_V23) || (p->cid_signalling == CID_SIG_V23_JP)) {
10592             cs = callerid_new(p->cid_signalling);
10593             if (cs) {
10594                int off_ms;
10595                struct timeval start;
10596                int ms;
10597                samples = 0;
10598 #if 1
10599                bump_gains(p);
10600 #endif
10601                /* Take out of linear mode for Caller*ID processing */
10602                dahdi_setlinear(p->subs[idx].dfd, 0);
10603 
10604                /* First we wait and listen for the Caller*ID */
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 
10620                      if (p->cid_signalling == CID_SIG_V23_JP) {
10621                         if (res == DAHDI_EVENT_RINGBEGIN) {
10622                            res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
10623                            usleep(1);
10624                         }
10625                      } else {
10626                         res = 0;
10627                         break;
10628                      }
10629                   } else if (i & DAHDI_IOMUX_READ) {
10630                      res = read(p->subs[idx].dfd, buf, sizeof(buf));
10631                      if (res < 0) {
10632                         if (errno != ELAST) {
10633                            ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10634                            callerid_free(cs);
10635                            ast_hangup(chan);
10636                            goto quit;
10637                         }
10638                         break;
10639                      }
10640                      samples += res;
10641 
10642                      if (p->cid_signalling == CID_SIG_V23_JP) {
10643                         res = callerid_feed_jp(cs, buf, res, AST_LAW(p));
10644                      } else {
10645                         res = callerid_feed(cs, buf, res, AST_LAW(p));
10646                      }
10647                      if (res < 0) {
10648                         /*
10649                          * The previous diagnostic message output likely
10650                          * explains why it failed.
10651                          */
10652                         ast_log(LOG_WARNING,
10653                            "Failed to decode CallerID on channel '%s'\n",
10654                            chan->name);
10655                         break;
10656                      } else if (res)
10657                         break;
10658                      else if (samples > (8000 * 10))
10659                         break;
10660                   }
10661                }
10662                if (res == 1) {
10663                   callerid_get(cs, &name, &number, &flags);
10664                   ast_log(LOG_NOTICE, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
10665                }
10666 
10667                if (p->cid_signalling == CID_SIG_V23_JP) {
10668                   res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
10669                   usleep(1);
10670                }
10671 
10672                /* Finished with Caller*ID, now wait for a ring to make sure there really is a call coming */
10673                start = ast_tvnow();
10674                off_ms = 4000;/* This is a typical OFF time between rings. */
10675                for (;;) {
10676                   struct ast_frame *f;
10677 
10678                   ms = ast_remaining_ms(start, off_ms);
10679                   res = ast_waitfor(chan, ms);
10680                   if (res <= 0) {
10681                      ast_log(LOG_WARNING, "CID timed out waiting for ring. "
10682                         "Exiting simple switch\n");
10683                      ast_hangup(chan);
10684                      goto quit;
10685                   }
10686                   if (!(f = ast_read(chan))) {
10687                      ast_log(LOG_WARNING, "Hangup received waiting for ring. Exiting simple switch\n");
10688                      ast_hangup(chan);
10689                      goto quit;
10690                   }
10691                   ast_frfree(f);
10692                   if (chan->_state == AST_STATE_RING ||
10693                      chan->_state == AST_STATE_RINGING)
10694                      break; /* Got ring */
10695                }
10696 
10697                /* We must have a ring by now, so, if configured, lets try to listen for
10698                 * distinctive ringing */
10699                if (p->usedistinctiveringdetection) {
10700                   len = 0;
10701                   distMatches = 0;
10702                   /* Clear the current ring data array so we don't have old data in it. */
10703                   for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
10704                      curRingData[receivedRingT] = 0;
10705                   receivedRingT = 0;
10706                   counter = 0;
10707                   counter1 = 0;
10708                   /* Check to see if context is what it should be, if not set to be. */
10709                   if (strcmp(p->context,p->defcontext) != 0) {
10710                      ast_copy_string(p->context, p->defcontext, sizeof(p->context));
10711                      ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
10712                   }
10713 
10714                   for (;;) {
10715                      i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10716                      if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10717                         ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10718                         callerid_free(cs);
10719                         ast_hangup(chan);
10720                         goto quit;
10721                      }
10722                      if (i & DAHDI_IOMUX_SIGEVENT) {
10723                         res = dahdi_get_event(p->subs[idx].dfd);
10724                         ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10725                         if (res == DAHDI_EVENT_NOALARM) {
10726                            p->inalarm = 0;
10727                         }
10728                         res = 0;
10729                         /* Let us detect distinctive ring */
10730 
10731                         curRingData[receivedRingT] = p->ringt;
10732 
10733                         if (p->ringt < p->ringt_base/2)
10734                            break;
10735                         /* Increment the ringT counter so we can match it against
10736                            values in chan_dahdi.conf for distinctive ring */
10737                         if (++receivedRingT == ARRAY_LEN(curRingData))
10738                            break;
10739                      } else if (i & DAHDI_IOMUX_READ) {
10740                         res = read(p->subs[idx].dfd, buf, sizeof(buf));
10741                         if (res < 0) {
10742                            if (errno != ELAST) {
10743                               ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10744                               callerid_free(cs);
10745                               ast_hangup(chan);
10746                               goto quit;
10747                            }
10748                            break;
10749                         }
10750                         if (p->ringt > 0) {
10751                            if (!(--p->ringt)) {
10752                               res = -1;
10753                               break;
10754                            }
10755                         }
10756                      }
10757                   }
10758                      /* this only shows up if you have n of the dring patterns filled in */
10759                   ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
10760                   for (counter = 0; counter < 3; counter++) {
10761                      /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this
10762                      channel */
10763                      distMatches = 0;
10764                      for (counter1 = 0; counter1 < 3; counter1++) {
10765                         ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
10766                         if (p->drings.ringnum[counter].ring[counter1] == -1) {
10767                            ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
10768                            curRingData[counter1]);
10769                            distMatches++;
10770                         } else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
10771                               curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
10772                            ast_verb(3, "Ring pattern matched in range: %d to %d\n",
10773                            (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
10774                            (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
10775                            distMatches++;
10776                         }
10777                      }
10778 
10779                      if (distMatches == 3) {
10780                         /* The ring matches, set the context to whatever is for distinctive ring.. */
10781                         ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context));
10782                         ast_copy_string(chan->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(chan->context));
10783                         ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
10784                         break;
10785                      }
10786                   }
10787                }
10788                /* Restore linear mode (if appropriate) for Caller*ID processing */
10789                dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10790 #if 1
10791                restore_gains(p);
10792 #endif
10793             } else
10794                ast_log(LOG_WARNING, "Unable to get caller ID space\n");
10795          } else {
10796             ast_log(LOG_WARNING, "Channel %s in prering "
10797                "state, but I have nothing to do. "
10798                "Terminating simple switch, should be "
10799                "restarted by the actual ring.\n",
10800                chan->name);
10801             ast_hangup(chan);
10802             goto quit;
10803          }
10804       } else if (p->use_callerid && p->cid_start == CID_START_RING) {
10805          if (p->cid_signalling == CID_SIG_DTMF) {
10806             int k = 0;
10807             int off_ms;
10808             struct timeval start;
10809             int ms;
10810             cs = NULL;
10811             dahdi_setlinear(p->subs[idx].dfd, 0);
10812             off_ms = 2000;
10813             start = ast_tvnow();
10814             for (;;) {
10815                struct ast_frame *f;
10816 
10817                ms = ast_remaining_ms(start, off_ms);
10818                res = ast_waitfor(chan, ms);
10819                if (res <= 0) {
10820                   ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
10821                      "Exiting simple switch\n");
10822                   ast_hangup(chan);
10823                   goto quit;
10824                }
10825                f = ast_read(chan);
10826                if (!f) {
10827                   /* Hangup received waiting for DTMFCID. Exiting simple switch. */
10828                   ast_hangup(chan);
10829                   goto quit;
10830                }
10831                if (f->frametype == AST_FRAME_DTMF) {
10832                   dtmfbuf[k++] = f->subclass.integer;
10833                   ast_log(LOG_DEBUG, "CID got digit '%c'\n", f->subclass.integer);
10834                   start = ast_tvnow();
10835                }
10836                ast_frfree(f);
10837 
10838                if (p->ringt_base == p->ringt)
10839                   break;
10840             }
10841             dtmfbuf[k] = '\0';
10842             dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10843             /* Got cid and ring. */
10844             callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
10845             ast_log(LOG_DEBUG, "CID is '%s', flags %d\n",
10846                dtmfcid, flags);
10847             /* If first byte is NULL, we have no cid */
10848             if (!ast_strlen_zero(dtmfcid))
10849                number = dtmfcid;
10850             else
10851                number = NULL;
10852             /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */
10853          } else {
10854             /* FSK Bell202 callerID */
10855             cs = callerid_new(p->cid_signalling);
10856             if (cs) {
10857 #if 1
10858                bump_gains(p);
10859 #endif
10860                samples = 0;
10861                len = 0;
10862                distMatches = 0;
10863                /* Clear the current ring data array so we don't have old data in it. */
10864                for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
10865                   curRingData[receivedRingT] = 0;
10866                receivedRingT = 0;
10867                counter = 0;
10868                counter1 = 0;
10869                /* Check to see if context is what it should be, if not set to be. */
10870                if (strcmp(p->context,p->defcontext) != 0) {
10871                   ast_copy_string(p->context, p->defcontext, sizeof(p->context));
10872                   ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
10873                }
10874 
10875                /* Take out of linear mode for Caller*ID processing */
10876                dahdi_setlinear(p->subs[idx].dfd, 0);
10877                for (;;) {
10878                   i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10879                   if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10880                      ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10881                      callerid_free(cs);
10882                      ast_hangup(chan);
10883                      goto quit;
10884                   }
10885                   if (i & DAHDI_IOMUX_SIGEVENT) {
10886                      res = dahdi_get_event(p->subs[idx].dfd);
10887                      ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10888                      if (res == DAHDI_EVENT_NOALARM) {
10889                         p->inalarm = 0;
10890                      }
10891                      /* If we get a PR event, they hung up while processing calerid */
10892                      if ( res == DAHDI_EVENT_POLARITY && p->hanguponpolarityswitch && p->polarity == POLARITY_REV) {
10893                         ast_log(LOG_DEBUG, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p->channel);
10894                         p->polarity = POLARITY_IDLE;
10895                         callerid_free(cs);
10896                         ast_hangup(chan);
10897                         goto quit;
10898                      }
10899                      res = 0;
10900                      /* Let us detect callerid when the telco uses distinctive ring */
10901 
10902                      curRingData[receivedRingT] = p->ringt;
10903 
10904                      if (p->ringt < p->ringt_base/2)
10905                         break;
10906                      /* Increment the ringT counter so we can match it against
10907                         values in chan_dahdi.conf for distinctive ring */
10908                      if (++receivedRingT == ARRAY_LEN(curRingData))
10909                         break;
10910                   } else if (i & DAHDI_IOMUX_READ) {
10911                      res = read(p->subs[idx].dfd, buf, sizeof(buf));
10912                      if (res < 0) {
10913                         if (errno != ELAST) {
10914                            ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10915                            callerid_free(cs);
10916                            ast_hangup(chan);
10917                            goto quit;
10918                         }
10919                         break;
10920                      }
10921                      if (p->ringt > 0) {
10922                         if (!(--p->ringt)) {
10923                            res = -1;
10924                            break;
10925                         }
10926                      }
10927                      samples += res;
10928                      res = callerid_feed(cs, buf, res, AST_LAW(p));
10929                      if (res < 0) {
10930                         /*
10931                          * The previous diagnostic message output likely
10932                          * explains why it failed.
10933                          */
10934                         ast_log(LOG_WARNING,
10935                            "Failed to decode CallerID on channel '%s'\n",
10936                            chan->name);
10937                         break;
10938                      } else if (res)
10939                         break;
10940                      else if (samples > (8000 * 10))
10941                         break;
10942                   }
10943                }
10944                if (res == 1) {
10945                   callerid_get(cs, &name, &number, &flags);
10946                   ast_debug(1, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
10947                }
10948                if (distinctiveringaftercid == 1) {
10949                   /* Clear the current ring data array so we don't have old data in it. */
10950                   for (receivedRingT = 0; receivedRingT < 3; receivedRingT++) {
10951                      curRingData[receivedRingT] = 0;
10952                   }
10953                   receivedRingT = 0;
10954                   ast_verb(3, "Detecting post-CID distinctive ring\n");
10955                   for (;;) {
10956                      i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10957                      if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10958                         ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10959                         callerid_free(cs);
10960                         ast_hangup(chan);
10961                         goto quit;
10962                      }
10963                      if (i & DAHDI_IOMUX_SIGEVENT) {
10964                         res = dahdi_get_event(p->subs[idx].dfd);
10965                         ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10966                         if (res == DAHDI_EVENT_NOALARM) {
10967                            p->inalarm = 0;
10968                         }
10969                         res = 0;
10970                         /* Let us detect callerid when the telco uses distinctive ring */
10971 
10972                         curRingData[receivedRingT] = p->ringt;
10973 
10974                         if (p->ringt < p->ringt_base/2)
10975                            break;
10976                         /* Increment the ringT counter so we can match it against
10977                            values in chan_dahdi.conf for distinctive ring */
10978                         if (++receivedRingT == ARRAY_LEN(curRingData))
10979                            break;
10980                      } else if (i & DAHDI_IOMUX_READ) {
10981                         res = read(p->subs[idx].dfd, buf, sizeof(buf));
10982                         if (res < 0) {
10983                            if (errno != ELAST) {
10984                               ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10985                               callerid_free(cs);
10986                               ast_hangup(chan);
10987                               goto quit;
10988                            }
10989                            break;
10990                         }
10991                         if (p->ringt > 0) {
10992                            if (!(--p->ringt)) {
10993                               res = -1;
10994                               break;
10995                            }
10996                         }
10997                      }
10998                   }
10999                }
11000                if (p->usedistinctiveringdetection) {
11001                   /* this only shows up if you have n of the dring patterns filled in */
11002                   ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
11003 
11004                   for (counter = 0; counter < 3; counter++) {
11005                      /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this
11006                      channel */
11007                      /* this only shows up if you have n of the dring patterns filled in */
11008                      ast_verb(3, "Checking %d,%d,%d\n",
11009                            p->drings.ringnum[counter].ring[0],
11010                            p->drings.ringnum[counter].ring[1],
11011                            p->drings.ringnum[counter].ring[2]);
11012                      distMatches = 0;
11013                      for (counter1 = 0; counter1 < 3; counter1++) {
11014                         ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
11015                         if (p->drings.ringnum[counter].ring[counter1] == -1) {
11016                            ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
11017                            curRingData[counter1]);
11018                            distMatches++;
11019                         }
11020                         else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
11021                            curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
11022                            ast_verb(3, "Ring pattern matched in range: %d to %d\n",
11023                            (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
11024                            (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
11025                            distMatches++;
11026                         }
11027                      }
11028                      if (distMatches == 3) {
11029                         /* The ring matches, set the context to whatever is for distinctive ring.. */
11030                         ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context));
11031                         ast_copy_string(chan->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(chan->context));
11032                         ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
11033                         break;
11034                      }
11035                   }
11036                }
11037                /* Restore linear mode (if appropriate) for Caller*ID processing */
11038                dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
11039 #if 1
11040                restore_gains(p);
11041 #endif
11042                if (res < 0) {
11043                   ast_log(LOG_WARNING, "CallerID returned with error on channel '%s'\n", chan->name);
11044                }
11045             } else
11046                ast_log(LOG_WARNING, "Unable to get caller ID space\n");
11047          }
11048       } else
11049          cs = NULL;
11050 
11051       if (number)
11052          ast_shrink_phone_number(number);
11053       ast_set_callerid(chan, number, name, number);
11054 
11055       if (smdi_msg)
11056          ASTOBJ_UNREF(smdi_msg, ast_smdi_md_message_destroy);
11057 
11058       if (cs)
11059          callerid_free(cs);
11060 
11061       my_handle_notify_message(chan, p, flags, -1);
11062 
11063       ast_setstate(chan, AST_STATE_RING);
11064       chan->rings = 1;
11065       p->ringt = p->ringt_base;
11066       res = ast_pbx_run(chan);
11067       if (res) {
11068          ast_hangup(chan);
11069          ast_log(LOG_WARNING, "PBX exited non-zero\n");
11070       }
11071       goto quit;
11072    default:
11073       ast_log(LOG_WARNING, "Don't know how to handle simple switch with signalling %s on channel %d\n", sig2str(p->sig), p->channel);
11074       res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
11075       if (res < 0)
11076             ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
11077    }
11078    res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
11079    if (res < 0)
11080          ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
11081    ast_hangup(chan);
11082 quit:
11083    ast_mutex_lock(&ss_thread_lock);
11084    ss_thread_count--;
11085    ast_cond_signal(&ss_thread_complete);
11086    ast_mutex_unlock(&ss_thread_lock);
11087    return NULL;
11088 }
11089 
11090 struct mwi_thread_data {
11091    struct dahdi_pvt *pvt;
11092    unsigned char buf[READ_SIZE];
11093    size_t len;
11094 };
11095 
11096 static int calc_energy(const unsigned char *buf, int len, format_t law)
11097 {
11098    int x;
11099    int sum = 0;
11100 
11101    if (!len)
11102       return 0;
11103 
11104    for (x = 0; x < len; x++)
11105       sum += abs(law == AST_FORMAT_ULAW ? AST_MULAW(buf[x]) : AST_ALAW(buf[x]));
11106 
11107    return sum / len;
11108 }
11109 
11110 static void *mwi_thread(void *data)
11111 {
11112    struct mwi_thread_data *mtd = data;
11113    struct callerid_state *cs;
11114    pthread_t threadid;
11115    int samples = 0;
11116    char *name, *number;
11117    int flags;
11118    int i, res;
11119    unsigned int spill_done = 0;
11120    int spill_result = -1;
11121 
11122    if (!(cs = callerid_new(mtd->pvt->cid_signalling))) {
11123       goto quit_no_clean;
11124    }
11125 
11126    callerid_feed(cs, mtd->buf, mtd->len, AST_LAW(mtd->pvt));
11127 
11128    bump_gains(mtd->pvt);
11129 
11130    for (;;) {
11131       i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
11132       if ((res = ioctl(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_IOMUX, &i))) {
11133          ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
11134          goto quit;
11135       }
11136 
11137       if (i & DAHDI_IOMUX_SIGEVENT) {
11138          struct ast_channel *chan;
11139 
11140          /* If we get an event, screen out events that we do not act on.
11141           * Otherwise, cancel and go to the simple switch to let it deal with it.
11142           */
11143          res = dahdi_get_event(mtd->pvt->subs[SUB_REAL].dfd);
11144 
11145          switch (res) {
11146          case DAHDI_EVENT_NEONMWI_ACTIVE:
11147          case DAHDI_EVENT_NEONMWI_INACTIVE:
11148          case DAHDI_EVENT_NONE:
11149          case DAHDI_EVENT_BITSCHANGED:
11150             break;
11151          case DAHDI_EVENT_NOALARM:
11152             if (analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) {
11153                struct analog_pvt *analog_p = mtd->pvt->sig_pvt;
11154 
11155                analog_p->inalarm = 0;
11156             }
11157             mtd->pvt->inalarm = 0;
11158             handle_clear_alarms(mtd->pvt);
11159             break;
11160          case DAHDI_EVENT_ALARM:
11161             if (analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) {
11162                struct analog_pvt *analog_p = mtd->pvt->sig_pvt;
11163 
11164                analog_p->inalarm = 1;
11165             }
11166             mtd->pvt->inalarm = 1;
11167             res = get_alarms(mtd->pvt);
11168             handle_alarms(mtd->pvt, res);
11169             break; /* What to do on channel alarm ???? -- fall thru intentionally?? */
11170          default:
11171             ast_log(LOG_NOTICE, "Got event %d (%s)...  Passing along to analog_ss_thread\n", res, event2str(res));
11172             callerid_free(cs);
11173 
11174             restore_gains(mtd->pvt);
11175             mtd->pvt->ringt = mtd->pvt->ringt_base;
11176 
11177             if ((chan = dahdi_new(mtd->pvt, AST_STATE_RING, 0, SUB_REAL, 0, NULL))) {
11178                int result;
11179 
11180                if (analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) {
11181                   result = analog_ss_thread_start(mtd->pvt->sig_pvt, chan);
11182                } else {
11183                   result = ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan);
11184                }
11185                if (result) {
11186                   ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", mtd->pvt->channel);
11187                   res = tone_zone_play_tone(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11188                   if (res < 0)
11189                      ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", mtd->pvt->channel);
11190                   ast_hangup(chan);
11191                }
11192             } else {
11193                ast_log(LOG_WARNING, "Could not create channel to handle call\n");
11194             }
11195             goto quit_no_clean;
11196          }
11197       } else if (i & DAHDI_IOMUX_READ) {
11198          if ((res = read(mtd->pvt->subs[SUB_REAL].dfd, mtd->buf, sizeof(mtd->buf))) < 0) {
11199             if (errno != ELAST) {
11200                ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
11201                goto quit;
11202             }
11203             break;
11204          }
11205          samples += res;
11206          if (!spill_done) {
11207             if ((spill_result = callerid_feed(cs, mtd->buf, res, AST_LAW(mtd->pvt))) < 0) {
11208                /*
11209                 * The previous diagnostic message output likely
11210                 * explains why it failed.
11211                 */
11212                ast_log(LOG_WARNING, "Failed to decode CallerID\n");
11213                break;
11214             } else if (spill_result) {
11215                spill_done = 1;
11216             }
11217          } else {
11218             /* keep reading data until the energy level drops below the threshold
11219                so we don't get another 'trigger' on the remaining carrier signal
11220             */
11221             if (calc_energy(mtd->buf, res, AST_LAW(mtd->pvt)) <= mwilevel)
11222                break;
11223          }
11224          if (samples > (8000 * 4)) /*Termination case - time to give up*/
11225             break;
11226       }
11227    }
11228 
11229    if (spill_result == 1) {
11230       callerid_get(cs, &name, &number, &flags);
11231       if (flags & CID_MSGWAITING) {
11232          ast_log(LOG_NOTICE, "mwi: Have Messages on channel %d\n", mtd->pvt->channel);
11233          notify_message(mtd->pvt->mailbox, 1);
11234       } else if (flags & CID_NOMSGWAITING) {
11235          ast_log(LOG_NOTICE, "mwi: No Messages on channel %d\n", mtd->pvt->channel);
11236          notify_message(mtd->pvt->mailbox, 0);
11237       } else {
11238          ast_log(LOG_NOTICE, "mwi: Status unknown on channel %d\n", mtd->pvt->channel);
11239       }
11240    }
11241 
11242 
11243 quit:
11244    callerid_free(cs);
11245 
11246    restore_gains(mtd->pvt);
11247 
11248 quit_no_clean:
11249    mtd->pvt->mwimonitoractive = 0;
11250    ast_free(mtd);
11251 
11252    return NULL;
11253 }
11254 
11255 /*
11256 * The following three functions (mwi_send_init, mwi_send_process_buffer,
11257 * mwi_send_process_event) work with the do_monitor thread to generate mwi spills
11258 * that are sent out via FXS port on voicemail state change.  The execution of
11259 * the mwi send is state driven and can either generate a ring pulse prior to
11260 * sending the fsk spill or simply send an fsk spill.
11261 */
11262 static int mwi_send_init(struct dahdi_pvt * pvt)
11263 {
11264    int x;
11265 
11266 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11267    /* Determine how this spill is to be sent */
11268    if (pvt->mwisend_rpas) {
11269       pvt->mwisend_data.mwisend_current = MWI_SEND_SA;
11270       pvt->mwisendactive = 1;
11271    } else if (pvt->mwisend_fsk) {
11272       pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
11273       pvt->mwisendactive = 1;
11274    } else {
11275       pvt->mwisendactive = 0;
11276       return 0;
11277    }
11278 #else
11279    if (mwisend_rpas) {
11280       pvt->mwisend_data.mwisend_current = MWI_SEND_SA;
11281    } else {
11282       pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
11283    }
11284    pvt->mwisendactive = 1;
11285 #endif
11286 
11287    if (pvt->cidspill) {
11288       ast_log(LOG_WARNING, "cidspill already exists when trying to send FSK MWI\n");
11289       ast_free(pvt->cidspill);
11290       pvt->cidspill = NULL;
11291       pvt->cidpos = 0;
11292       pvt->cidlen = 0;
11293    }
11294    pvt->cidspill = ast_calloc(1, MAX_CALLERID_SIZE);
11295    if (!pvt->cidspill) {
11296       pvt->mwisendactive = 0;
11297       return -1;
11298    }
11299    x = DAHDI_FLUSH_BOTH;
11300    ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
11301    x = 3000;
11302    ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_ONHOOKTRANSFER, &x);
11303 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11304    if (pvt->mwisend_fsk) {
11305 #endif
11306       pvt->cidlen = ast_callerid_vmwi_generate(pvt->cidspill, has_voicemail(pvt), CID_MWI_TYPE_MDMF_FULL,
11307                       AST_LAW(pvt), pvt->cid_name, pvt->cid_num, 0);
11308       pvt->cidpos = 0;
11309 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11310    }
11311 #endif
11312    return 0;
11313 }
11314 
11315 static int mwi_send_process_buffer(struct dahdi_pvt * pvt, int num_read)
11316 {
11317    struct timeval    now;
11318    int         res;
11319 
11320    /* sanity check to catch if this had been interrupted previously
11321    *  i.e. state says there is more to do but there is no spill allocated
11322    */
11323    if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current && !pvt->cidspill) {
11324       pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11325    } else if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current) {
11326       /* Normal processing -- Perform mwi send action */
11327       switch ( pvt->mwisend_data.mwisend_current) {
11328       case MWI_SEND_SA:
11329          /* Send the Ring Pulse Signal Alert */
11330          res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &AS_RP_cadence);
11331          if (res) {
11332             ast_log(LOG_WARNING, "Unable to set RP-AS ring cadence: %s\n", strerror(errno));
11333             goto quit;
11334          }
11335          res = dahdi_set_hook(pvt->subs[SUB_REAL].dfd, DAHDI_RING);
11336          pvt->mwisend_data.mwisend_current = MWI_SEND_SA_WAIT;
11337          break;
11338       case MWI_SEND_SA_WAIT:  /* do nothing until I get RINGEROFF event */
11339          break;
11340       case MWI_SEND_PAUSE:  /* Wait between alert and spill - min of 500 mS*/
11341 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11342          if (pvt->mwisend_fsk) {
11343 #endif
11344             gettimeofday(&now, NULL);
11345             if ((int)(now.tv_sec - pvt->mwisend_data.pause.tv_sec) * 1000000 + (int)now.tv_usec - (int)pvt->mwisend_data.pause.tv_usec > 500000) {
11346                pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
11347             }
11348 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11349          } else { /* support for mwisendtype=nofsk */
11350             pvt->mwisend_data.mwisend_current = MWI_SEND_CLEANUP;
11351          }
11352 #endif
11353          break;
11354       case MWI_SEND_SPILL:
11355          /* We read some number of bytes.  Write an equal amount of data */
11356          if(0 < num_read) {
11357             if (num_read > pvt->cidlen - pvt->cidpos)
11358                num_read = pvt->cidlen - pvt->cidpos;
11359             res = write(pvt->subs[SUB_REAL].dfd, pvt->cidspill + pvt->cidpos, num_read);
11360             if (res > 0) {
11361                pvt->cidpos += res;
11362                if (pvt->cidpos >= pvt->cidlen) {
11363                   pvt->mwisend_data.mwisend_current = MWI_SEND_CLEANUP;
11364                }
11365             } else {
11366                ast_log(LOG_WARNING, "MWI FSK Send Write failed: %s\n", strerror(errno));
11367                goto quit;
11368             }
11369          }
11370          break;
11371       case MWI_SEND_CLEANUP:
11372          /* For now, do nothing */
11373          pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11374          break;
11375       default:
11376          /* Should not get here, punt*/
11377          goto quit;
11378       }
11379    }
11380 
11381    if (MWI_SEND_DONE == pvt->mwisend_data.mwisend_current) {
11382       if (pvt->cidspill) {
11383          ast_free(pvt->cidspill);
11384          pvt->cidspill = NULL;
11385          pvt->cidpos = 0;
11386          pvt->cidlen = 0;
11387       }
11388       pvt->mwisendactive = 0;
11389    }
11390    return 0;
11391 quit:
11392    if (pvt->cidspill) {
11393       ast_free(pvt->cidspill);
11394       pvt->cidspill = NULL;
11395       pvt->cidpos = 0;
11396       pvt->cidlen = 0;
11397    }
11398    pvt->mwisendactive = 0;
11399    return -1;
11400 }
11401 
11402 static int mwi_send_process_event(struct dahdi_pvt * pvt, int event)
11403 {
11404    int handled = 0;
11405 
11406    if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current) {
11407       switch (event) {
11408       case DAHDI_EVENT_RINGEROFF:
11409          if(pvt->mwisend_data.mwisend_current == MWI_SEND_SA_WAIT) {
11410             handled = 1;
11411 
11412             if (dahdi_set_hook(pvt->subs[SUB_REAL].dfd, DAHDI_RINGOFF) ) {
11413                ast_log(LOG_WARNING, "Unable to finish RP-AS: %s mwi send aborted\n", strerror(errno));
11414                ast_free(pvt->cidspill);
11415                pvt->cidspill = NULL;
11416                pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11417                pvt->mwisendactive = 0;
11418             } else {
11419                pvt->mwisend_data.mwisend_current = MWI_SEND_PAUSE;
11420                gettimeofday(&pvt->mwisend_data.pause, NULL);
11421             }
11422          }
11423          break;
11424       /* Going off hook, I need to punt this spill */
11425       case DAHDI_EVENT_RINGOFFHOOK:
11426          if (pvt->cidspill) {
11427             ast_free(pvt->cidspill);
11428             pvt->cidspill = NULL;
11429             pvt->cidpos = 0;
11430             pvt->cidlen = 0;
11431          }
11432          pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11433          pvt->mwisendactive = 0;
11434          break;
11435       case DAHDI_EVENT_RINGERON:
11436       case DAHDI_EVENT_HOOKCOMPLETE:
11437          break;
11438       default:
11439          break;
11440       }
11441    }
11442    return handled;
11443 }
11444 
11445 /* destroy a DAHDI channel, identified by its number */
11446 static int dahdi_destroy_channel_bynum(int channel)
11447 {
11448    struct dahdi_pvt *cur;
11449 
11450    ast_mutex_lock(&iflock);
11451    for (cur = iflist; cur; cur = cur->next) {
11452       if (cur->channel == channel) {
11453          int x = DAHDI_FLASH;
11454 
11455          /* important to create an event for dahdi_wait_event to register so that all analog_ss_threads terminate */
11456          ioctl(cur->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
11457 
11458          destroy_channel(cur, 1);
11459          ast_mutex_unlock(&iflock);
11460          ast_module_unref(ast_module_info->self);
11461          return RESULT_SUCCESS;
11462       }
11463    }
11464    ast_mutex_unlock(&iflock);
11465    return RESULT_FAILURE;
11466 }
11467 
11468 static struct dahdi_pvt *handle_init_event(struct dahdi_pvt *i, int event)
11469 {
11470    int res;
11471    pthread_t threadid;
11472    struct ast_channel *chan;
11473 
11474    /* Handle an event on a given channel for the monitor thread. */
11475 
11476    switch (event) {
11477    case DAHDI_EVENT_NONE:
11478    case DAHDI_EVENT_BITSCHANGED:
11479       break;
11480    case DAHDI_EVENT_WINKFLASH:
11481    case DAHDI_EVENT_RINGOFFHOOK:
11482       if (i->inalarm) break;
11483       if (i->radio) break;
11484       /* Got a ring/answer.  What kind of channel are we? */
11485       switch (i->sig) {
11486       case SIG_FXOLS:
11487       case SIG_FXOGS:
11488       case SIG_FXOKS:
11489          res = dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
11490          if (res && (errno == EBUSY))
11491             break;
11492 
11493          /* Cancel VMWI spill */
11494          ast_free(i->cidspill);
11495          i->cidspill = NULL;
11496          restore_conference(i);
11497 
11498          if (i->immediate) {
11499             dahdi_enable_ec(i);
11500             /* The channel is immediately up.  Start right away */
11501             res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
11502             chan = dahdi_new(i, AST_STATE_RING, 1, SUB_REAL, 0, NULL);
11503             if (!chan) {
11504                ast_log(LOG_WARNING, "Unable to start PBX on channel %d\n", i->channel);
11505                res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11506                if (res < 0)
11507                   ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11508             }
11509          } else {
11510             /* Check for callerid, digits, etc */
11511             chan = dahdi_new(i, AST_STATE_RESERVED, 0, SUB_REAL, 0, NULL);
11512             if (chan) {
11513                if (has_voicemail(i))
11514                   res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
11515                else
11516                   res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
11517                if (res < 0)
11518                   ast_log(LOG_WARNING, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i->channel);
11519                if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
11520                   ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11521                   res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11522                   if (res < 0)
11523                      ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11524                   ast_hangup(chan);
11525                }
11526             } else
11527                ast_log(LOG_WARNING, "Unable to create channel\n");
11528          }
11529          break;
11530       case SIG_FXSLS:
11531       case SIG_FXSGS:
11532       case SIG_FXSKS:
11533             i->ringt = i->ringt_base;
11534             /* Fall through */
11535       case SIG_EMWINK:
11536       case SIG_FEATD:
11537       case SIG_FEATDMF:
11538       case SIG_FEATDMF_TA:
11539       case SIG_E911:
11540       case SIG_FGC_CAMA:
11541       case SIG_FGC_CAMAMF:
11542       case SIG_FEATB:
11543       case SIG_EM:
11544       case SIG_EM_E1:
11545       case SIG_SFWINK:
11546       case SIG_SF_FEATD:
11547       case SIG_SF_FEATDMF:
11548       case SIG_SF_FEATB:
11549       case SIG_SF:
11550          /* Check for callerid, digits, etc */
11551          if (i->cid_start == CID_START_POLARITY_IN) {
11552             chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL);
11553          } else {
11554             chan = dahdi_new(i, AST_STATE_RING, 0, SUB_REAL, 0, NULL);
11555          }
11556 
11557          if (!chan) {
11558             ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
11559          } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
11560             ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11561             res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11562             if (res < 0) {
11563                ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11564             }
11565             ast_hangup(chan);
11566          }
11567          break;
11568       default:
11569          ast_log(LOG_WARNING, "Don't know how to handle ring/answer with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
11570          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11571          if (res < 0)
11572             ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11573          return NULL;
11574       }
11575       break;
11576    case DAHDI_EVENT_NOALARM:
11577       switch (i->sig) {
11578 #if defined(HAVE_PRI)
11579       case SIG_PRI_LIB_HANDLE_CASES:
11580          ast_mutex_lock(&i->lock);
11581          sig_pri_chan_alarm_notify(i->sig_pvt, 1);
11582          ast_mutex_unlock(&i->lock);
11583          break;
11584 #endif   /* defined(HAVE_PRI) */
11585 #if defined(HAVE_SS7)
11586       case SIG_SS7:
11587          sig_ss7_set_alarm(i->sig_pvt, 0);
11588          break;
11589 #endif   /* defined(HAVE_SS7) */
11590       default:
11591          i->inalarm = 0;
11592          break;
11593       }
11594       handle_clear_alarms(i);
11595       break;
11596    case DAHDI_EVENT_ALARM:
11597       switch (i->sig) {
11598 #if defined(HAVE_PRI)
11599       case SIG_PRI_LIB_HANDLE_CASES:
11600          ast_mutex_lock(&i->lock);
11601          sig_pri_chan_alarm_notify(i->sig_pvt, 0);
11602          ast_mutex_unlock(&i->lock);
11603          break;
11604 #endif   /* defined(HAVE_PRI) */
11605 #if defined(HAVE_SS7)
11606       case SIG_SS7:
11607          sig_ss7_set_alarm(i->sig_pvt, 1);
11608          break;
11609 #endif   /* defined(HAVE_SS7) */
11610       default:
11611          i->inalarm = 1;
11612          break;
11613       }
11614       res = get_alarms(i);
11615       handle_alarms(i, res);
11616       /* fall thru intentionally */
11617    case DAHDI_EVENT_ONHOOK:
11618       if (i->radio)
11619          break;
11620       /* Back on hook.  Hang up. */
11621       switch (i->sig) {
11622       case SIG_FXOLS:
11623       case SIG_FXOGS:
11624       case SIG_FEATD:
11625       case SIG_FEATDMF:
11626       case SIG_FEATDMF_TA:
11627       case SIG_E911:
11628       case SIG_FGC_CAMA:
11629       case SIG_FGC_CAMAMF:
11630       case SIG_FEATB:
11631       case SIG_EM:
11632       case SIG_EM_E1:
11633       case SIG_EMWINK:
11634       case SIG_SF_FEATD:
11635       case SIG_SF_FEATDMF:
11636       case SIG_SF_FEATB:
11637       case SIG_SF:
11638       case SIG_SFWINK:
11639       case SIG_FXSLS:
11640       case SIG_FXSGS:
11641       case SIG_FXSKS:
11642       case SIG_FXOKS:
11643          dahdi_disable_ec(i);
11644          /* Diddle the battery for the zhone */
11645 #ifdef ZHONE_HACK
11646          dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
11647          usleep(1);
11648 #endif
11649          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
11650          dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
11651          break;
11652       case SIG_SS7:
11653       case SIG_PRI_LIB_HANDLE_CASES:
11654          dahdi_disable_ec(i);
11655          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
11656          break;
11657       default:
11658          ast_log(LOG_WARNING, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
11659          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
11660          return NULL;
11661       }
11662       break;
11663    case DAHDI_EVENT_POLARITY:
11664       switch (i->sig) {
11665       case SIG_FXSLS:
11666       case SIG_FXSKS:
11667       case SIG_FXSGS:
11668          /* We have already got a PR before the channel was
11669             created, but it wasn't handled. We need polarity
11670             to be REV for remote hangup detection to work.
11671             At least in Spain */
11672          if (i->hanguponpolarityswitch)
11673             i->polarity = POLARITY_REV;
11674          if (i->cid_start == CID_START_POLARITY || i->cid_start == CID_START_POLARITY_IN) {
11675             i->polarity = POLARITY_REV;
11676             ast_verb(2, "Starting post polarity "
11677                "CID detection on channel %d\n",
11678                i->channel);
11679             chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL);
11680             if (!chan) {
11681                ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
11682             } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
11683                ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11684                ast_hangup(chan);
11685             }
11686          }
11687          break;
11688       default:
11689          ast_log(LOG_WARNING, "handle_init_event detected "
11690             "polarity reversal on non-FXO (SIG_FXS) "
11691             "interface %d\n", i->channel);
11692       }
11693       break;
11694    case DAHDI_EVENT_REMOVED: /* destroy channel, will actually do so in do_monitor */
11695       ast_log(LOG_NOTICE,
11696             "Got DAHDI_EVENT_REMOVED. Destroying channel %d\n",
11697             i->channel);
11698       return i;
11699    case DAHDI_EVENT_NEONMWI_ACTIVE:
11700       if (i->mwimonitor_neon) {
11701          notify_message(i->mailbox, 1);
11702          ast_log(LOG_NOTICE, "NEON MWI set for channel %d, mailbox %s \n", i->channel, i->mailbox);
11703       }
11704       break;
11705    case DAHDI_EVENT_NEONMWI_INACTIVE:
11706       if (i->mwimonitor_neon) {
11707          notify_message(i->mailbox, 0);
11708          ast_log(LOG_NOTICE, "NEON MWI cleared for channel %d, mailbox %s\n", i->channel, i->mailbox);
11709       }
11710       break;
11711    }
11712    return NULL;
11713 }
11714 
11715 static void monitor_pfds_clean(void *arg) {
11716    struct pollfd **pfds = arg;
11717    ast_free(*pfds);
11718 }
11719 
11720 static void *do_monitor(void *data)
11721 {
11722    int count, res, res2, spoint, pollres=0;
11723    struct dahdi_pvt *i;
11724    struct dahdi_pvt *last = NULL;
11725    struct dahdi_pvt *doomed;
11726    time_t thispass = 0, lastpass = 0;
11727    int found;
11728    char buf[1024];
11729    struct pollfd *pfds=NULL;
11730    int lastalloc = -1;
11731    /* This thread monitors all the frame relay interfaces which are not yet in use
11732       (and thus do not have a separate thread) indefinitely */
11733    /* From here on out, we die whenever asked */
11734 #if 0
11735    if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) {
11736       ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n");
11737       return NULL;
11738    }
11739    ast_debug(1, "Monitor starting...\n");
11740 #endif
11741    pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
11742 
11743    pthread_cleanup_push(monitor_pfds_clean, &pfds);
11744    for (;;) {
11745       /* Lock the interface list */
11746       ast_mutex_lock(&iflock);
11747       if (!pfds || (lastalloc != ifcount)) {
11748          if (pfds) {
11749             ast_free(pfds);
11750             pfds = NULL;
11751          }
11752          if (ifcount) {
11753             if (!(pfds = ast_calloc(1, ifcount * sizeof(*pfds)))) {
11754                ast_mutex_unlock(&iflock);
11755                return NULL;
11756             }
11757          }
11758          lastalloc = ifcount;
11759       }
11760       /* Build the stuff we're going to poll on, that is the socket of every
11761          dahdi_pvt that does not have an associated owner channel */
11762       count = 0;
11763       for (i = iflist; i; i = i->next) {
11764          ast_mutex_lock(&i->lock);
11765          if (pfds && (i->subs[SUB_REAL].dfd > -1) && i->sig && (!i->radio) && !(i->sig & SIG_MFCR2)) {
11766             if (analog_lib_handles(i->sig, i->radio, i->oprmode)) {
11767                struct analog_pvt *p = i->sig_pvt;
11768 
11769                if (!p) {
11770                   ast_log(LOG_ERROR, "No sig_pvt?\n");
11771                } else if (!p->owner && !p->subs[SUB_REAL].owner) {
11772                   /* This needs to be watched, as it lacks an owner */
11773                   pfds[count].fd = i->subs[SUB_REAL].dfd;
11774                   pfds[count].events = POLLPRI;
11775                   pfds[count].revents = 0;
11776                   /* Message waiting or r2 channels also get watched for reading */
11777                   if (i->cidspill || i->mwisendactive || i->mwimonitor_fsk || 
11778                      (i->cid_start == CID_START_DTMF_NOALERT && (i->sig == SIG_FXSLS || i->sig == SIG_FXSGS || i->sig == SIG_FXSKS))) {
11779                      pfds[count].events |= POLLIN;
11780                   }
11781                   count++;
11782                }
11783             } else {
11784                if (!i->owner && !i->subs[SUB_REAL].owner && !i->mwimonitoractive ) {
11785                   /* This needs to be watched, as it lacks an owner */
11786                   pfds[count].fd = i->subs[SUB_REAL].dfd;
11787                   pfds[count].events = POLLPRI;
11788                   pfds[count].revents = 0;
11789                   /* If we are monitoring for VMWI or sending CID, we need to
11790                      read from the channel as well */
11791                   if (i->cidspill || i->mwisendactive || i->mwimonitor_fsk ||
11792                      (i->cid_start == CID_START_DTMF_NOALERT && (i->sig == SIG_FXSLS || i->sig == SIG_FXSGS || i->sig == SIG_FXSKS))) {
11793                      pfds[count].events |= POLLIN;
11794                   }
11795                   count++;
11796                }
11797             }
11798          }
11799          ast_mutex_unlock(&i->lock);
11800       }
11801       /* Okay, now that we know what to do, release the interface lock */
11802       ast_mutex_unlock(&iflock);
11803 
11804       pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
11805       pthread_testcancel();
11806       /* Wait at least a second for something to happen */
11807       res = poll(pfds, count, 1000);
11808       pthread_testcancel();
11809       pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
11810 
11811       /* Okay, poll has finished.  Let's see what happened.  */
11812       if (res < 0) {
11813          if ((errno != EAGAIN) && (errno != EINTR))
11814             ast_log(LOG_WARNING, "poll return %d: %s\n", res, strerror(errno));
11815          continue;
11816       }
11817       /* Alright, lock the interface list again, and let's look and see what has
11818          happened */
11819       ast_mutex_lock(&iflock);
11820       found = 0;
11821       spoint = 0;
11822       lastpass = thispass;
11823       thispass = time(NULL);
11824       doomed = NULL;
11825       for (i = iflist;; i = i->next) {
11826          if (doomed) {
11827             int res;
11828             res = dahdi_destroy_channel_bynum(doomed->channel);
11829             if (res != RESULT_SUCCESS) {
11830                ast_log(LOG_WARNING, "Couldn't find channel to destroy, hopefully another destroy operation just happened.\n");
11831             }
11832             doomed = NULL;
11833          }
11834          if (!i) {
11835             break;
11836          }
11837 
11838          if (thispass != lastpass) {
11839             if (!found && ((i == last) || ((i == iflist) && !last))) {
11840                last = i;
11841                if (last) {
11842                   struct analog_pvt *analog_p = last->sig_pvt;
11843                   /* Only allow MWI to be initiated on a quiescent fxs port */
11844                   if (analog_p
11845                      && !last->mwisendactive
11846                      && (last->sig & __DAHDI_SIG_FXO)
11847                      && !analog_p->fxsoffhookstate
11848                      && !last->owner
11849                      && !ast_strlen_zero(last->mailbox)
11850                      && (thispass - analog_p->onhooktime > 3)) {
11851                      res = has_voicemail(last);
11852                      if (analog_p->msgstate != res) {
11853                         /* Set driver resources for signalling VMWI */
11854                         res2 = ioctl(last->subs[SUB_REAL].dfd, DAHDI_VMWI, &res);
11855                         if (res2) {
11856                            /* TODO: This message will ALWAYS be generated on some cards; any way to restrict it to those cards where it is interesting? */
11857                            ast_debug(3, "Unable to control message waiting led on channel %d: %s\n", last->channel, strerror(errno));
11858                         }
11859                         /* If enabled for FSK spill then initiate it */
11860                         if (mwi_send_init(last)) {
11861                            ast_log(LOG_WARNING, "Unable to initiate mwi send sequence on channel %d\n", last->channel);
11862                         }
11863                         analog_p->msgstate = res;
11864                         found ++;
11865                      }
11866                   }
11867                   last = last->next;
11868                }
11869             }
11870          }
11871          if ((i->subs[SUB_REAL].dfd > -1) && i->sig) {
11872             if (i->radio && !i->owner)
11873             {
11874                res = dahdi_get_event(i->subs[SUB_REAL].dfd);
11875                if (res)
11876                {
11877                   ast_debug(1, "Monitor doohicky got event %s on radio channel %d\n", event2str(res), i->channel);
11878                   /* Don't hold iflock while handling init events */
11879                   ast_mutex_unlock(&iflock);
11880                   if (analog_lib_handles(i->sig, i->radio, i->oprmode))
11881                      doomed = (struct dahdi_pvt *) analog_handle_init_event(i->sig_pvt, dahdievent_to_analogevent(res));
11882                   else
11883                      doomed = handle_init_event(i, res);
11884                   ast_mutex_lock(&iflock);
11885                }
11886                continue;
11887             }
11888             pollres = ast_fdisset(pfds, i->subs[SUB_REAL].dfd, count, &spoint);
11889             if (pollres & POLLIN) {
11890                if (i->owner || i->subs[SUB_REAL].owner) {
11891 #ifdef HAVE_PRI
11892                   if (!i->pri)
11893 #endif
11894                      ast_log(LOG_WARNING, "Whoa....  I'm owned but found (%d) in read...\n", i->subs[SUB_REAL].dfd);
11895                   continue;
11896                }
11897                if (!i->mwimonitor_fsk && !i->mwisendactive  && i->cid_start != CID_START_DTMF_NOALERT) {
11898                   ast_log(LOG_WARNING, "Whoa....  I'm not looking for MWI or sending MWI but am reading (%d)...\n", i->subs[SUB_REAL].dfd);
11899                   continue;
11900                }
11901                res = read(i->subs[SUB_REAL].dfd, buf, sizeof(buf));
11902                if (res > 0) {
11903                   if (i->mwimonitor_fsk) {
11904                      if (calc_energy((unsigned char *) buf, res, AST_LAW(i)) > mwilevel) {
11905                         pthread_attr_t attr;
11906                         pthread_t threadid;
11907                         struct mwi_thread_data *mtd;
11908 
11909                         pthread_attr_init(&attr);
11910                         pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
11911 
11912                         ast_log(LOG_DEBUG, "Maybe some MWI on port %d!\n", i->channel);
11913                         if ((mtd = ast_calloc(1, sizeof(*mtd)))) {
11914                            mtd->pvt = i;
11915                            memcpy(mtd->buf, buf, res);
11916                            mtd->len = res;
11917                            i->mwimonitoractive = 1;
11918                            if (ast_pthread_create_background(&threadid, &attr, mwi_thread, mtd)) {
11919                               ast_log(LOG_WARNING, "Unable to start mwi thread on channel %d\n", i->channel);
11920                               i->mwimonitoractive = 0;
11921                               ast_free(mtd);
11922                            }
11923                         }
11924                      }
11925                   /* If configured to check for a DTMF CID spill that comes without alert (e.g no polarity reversal) */
11926                   } else if (i->cid_start == CID_START_DTMF_NOALERT) {
11927                      int energy;
11928                      struct timeval now;
11929                      /* State machine dtmfcid_holdoff_state allows for the line to settle
11930                       * before checking agin for dtmf energy.  Presently waits for 500 mS before checking again 
11931                      */
11932                      if (1 == i->dtmfcid_holdoff_state) {
11933                         gettimeofday(&i->dtmfcid_delay, NULL);
11934                         i->dtmfcid_holdoff_state = 2;
11935                      } else if (2 == i->dtmfcid_holdoff_state) {
11936                         gettimeofday(&now, NULL);
11937                         if ((int)(now.tv_sec - i->dtmfcid_delay.tv_sec) * 1000000 + (int)now.tv_usec - (int)i->dtmfcid_delay.tv_usec > 500000) {
11938                            i->dtmfcid_holdoff_state = 0;
11939                         }
11940                      } else {
11941                         energy = calc_energy((unsigned char *) buf, res, AST_LAW(i));
11942                         if (!i->mwisendactive && energy > dtmfcid_level) {
11943                            pthread_t threadid;
11944                            struct ast_channel *chan;
11945                            ast_mutex_unlock(&iflock);
11946                            if (analog_lib_handles(i->sig, i->radio, i->oprmode)) {
11947                               /* just in case this event changes or somehow destroys a channel, set doomed here too */
11948                               doomed = analog_handle_init_event(i->sig_pvt, ANALOG_EVENT_DTMFCID);  
11949                               i->dtmfcid_holdoff_state = 1;
11950                            } else {
11951                               chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL);
11952                               if (!chan) {
11953                                  ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
11954                               } else {
11955                                  res = ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan);
11956                                  if (res) {
11957                                     ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11958                                     ast_hangup(chan);
11959                                  } else {
11960                                     i->dtmfcid_holdoff_state = 1;
11961                                  }
11962                               }
11963                            }
11964                            ast_mutex_lock(&iflock);
11965                         }
11966                      }
11967                   }
11968                   if (i->mwisendactive) {
11969                      mwi_send_process_buffer(i, res);
11970                   }
11971                } else {
11972                   ast_log(LOG_WARNING, "Read failed with %d: %s\n", res, strerror(errno));
11973                }
11974             }
11975             if (pollres & POLLPRI) {
11976                if (i->owner || i->subs[SUB_REAL].owner) {
11977 #ifdef HAVE_PRI
11978                   if (!i->pri)
11979 #endif
11980                      ast_log(LOG_WARNING, "Whoa....  I'm owned but found (%d)...\n", i->subs[SUB_REAL].dfd);
11981                   continue;
11982                }
11983                res = dahdi_get_event(i->subs[SUB_REAL].dfd);
11984                ast_debug(1, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel);
11985                /* Don't hold iflock while handling init events */
11986                ast_mutex_unlock(&iflock);
11987                if (0 == i->mwisendactive || 0 == mwi_send_process_event(i, res)) {
11988                   if (analog_lib_handles(i->sig, i->radio, i->oprmode))
11989                      doomed = (struct dahdi_pvt *) analog_handle_init_event(i->sig_pvt, dahdievent_to_analogevent(res));
11990                   else
11991                      doomed = handle_init_event(i, res);
11992                }
11993                ast_mutex_lock(&iflock);
11994             }
11995          }
11996       }
11997       ast_mutex_unlock(&iflock);
11998    }
11999    /* Never reached */
12000    pthread_cleanup_pop(1);
12001    return NULL;
12002 
12003 }
12004 
12005 static int restart_monitor(void)
12006 {
12007    /* If we're supposed to be stopped -- stay stopped */
12008    if (monitor_thread == AST_PTHREADT_STOP)
12009       return 0;
12010    ast_mutex_lock(&monlock);
12011    if (monitor_thread == pthread_self()) {
12012       ast_mutex_unlock(&monlock);
12013       ast_log(LOG_WARNING, "Cannot kill myself\n");
12014       return -1;
12015    }
12016    if (monitor_thread != AST_PTHREADT_NULL) {
12017       /* Wake up the thread */
12018       pthread_kill(monitor_thread, SIGURG);
12019    } else {
12020       /* Start a new monitor */
12021       if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) {
12022          ast_mutex_unlock(&monlock);
12023          ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
12024          return -1;
12025       }
12026    }
12027    ast_mutex_unlock(&monlock);
12028    return 0;
12029 }
12030 
12031 #if defined(HAVE_PRI)
12032 static int pri_resolve_span(int *span, int channel, int offset, struct dahdi_spaninfo *si)
12033 {
12034    int x;
12035    int trunkgroup;
12036    /* Get appropriate trunk group if there is one */
12037    trunkgroup = pris[*span].mastertrunkgroup;
12038    if (trunkgroup) {
12039       /* Select a specific trunk group */
12040       for (x = 0; x < NUM_SPANS; x++) {
12041          if (pris[x].pri.trunkgroup == trunkgroup) {
12042             *span = x;
12043             return 0;
12044          }
12045       }
12046       ast_log(LOG_WARNING, "Channel %d on span %d configured to use nonexistent trunk group %d\n", channel, *span, trunkgroup);
12047       *span = -1;
12048    } else {
12049       if (pris[*span].pri.trunkgroup) {
12050          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);
12051          *span = -1;
12052       } else if (pris[*span].mastertrunkgroup) {
12053          ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is already part of trunk group %d\n", *span, pris[*span].mastertrunkgroup);
12054          *span = -1;
12055       } else {
12056          if (si->totalchans == 31) {
12057             /* E1 */
12058             pris[*span].dchannels[0] = 16 + offset;
12059          } else if (si->totalchans == 24) {
12060             /* T1 or J1 */
12061             pris[*span].dchannels[0] = 24 + offset;
12062          } else if (si->totalchans == 3) {
12063             /* BRI */
12064             pris[*span].dchannels[0] = 3 + offset;
12065          } else {
12066             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);
12067             *span = -1;
12068             return 0;
12069          }
12070          pris[*span].pri.span = *span + 1;
12071       }
12072    }
12073    return 0;
12074 }
12075 #endif   /* defined(HAVE_PRI) */
12076 
12077 #if defined(HAVE_PRI)
12078 static int pri_create_trunkgroup(int trunkgroup, int *channels)
12079 {
12080    struct dahdi_spaninfo si;
12081    struct dahdi_params p;
12082    int fd;
12083    int span;
12084    int ospan=0;
12085    int x,y;
12086    for (x = 0; x < NUM_SPANS; x++) {
12087       if (pris[x].pri.trunkgroup == trunkgroup) {
12088          ast_log(LOG_WARNING, "Trunk group %d already exists on span %d, Primary d-channel %d\n", trunkgroup, x + 1, pris[x].dchannels[0]);
12089          return -1;
12090       }
12091    }
12092    for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
12093       if (!channels[y])
12094          break;
12095       memset(&si, 0, sizeof(si));
12096       memset(&p, 0, sizeof(p));
12097       fd = open("/dev/dahdi/channel", O_RDWR);
12098       if (fd < 0) {
12099          ast_log(LOG_WARNING, "Failed to open channel: %s\n", strerror(errno));
12100          return -1;
12101       }
12102       x = channels[y];
12103       if (ioctl(fd, DAHDI_SPECIFY, &x)) {
12104          ast_log(LOG_WARNING, "Failed to specify channel %d: %s\n", channels[y], strerror(errno));
12105          close(fd);
12106          return -1;
12107       }
12108       if (ioctl(fd, DAHDI_GET_PARAMS, &p)) {
12109          ast_log(LOG_WARNING, "Failed to get channel parameters for channel %d: %s\n", channels[y], strerror(errno));
12110          return -1;
12111       }
12112       if (ioctl(fd, DAHDI_SPANSTAT, &si)) {
12113          ast_log(LOG_WARNING, "Failed go get span information on channel %d (span %d): %s\n", channels[y], p.spanno, strerror(errno));
12114          close(fd);
12115          return -1;
12116       }
12117       span = p.spanno - 1;
12118       if (pris[span].pri.trunkgroup) {
12119          ast_log(LOG_WARNING, "Span %d is already provisioned for trunk group %d\n", span + 1, pris[span].pri.trunkgroup);
12120          close(fd);
12121          return -1;
12122       }
12123       if (pris[span].pri.pvts[0]) {
12124          ast_log(LOG_WARNING, "Span %d is already provisioned with channels (implicit PRI maybe?)\n", span + 1);
12125          close(fd);
12126          return -1;
12127       }
12128       if (!y) {
12129          pris[span].pri.trunkgroup = trunkgroup;
12130          ospan = span;
12131       }
12132       pris[ospan].dchannels[y] = channels[y];
12133       pris[span].pri.span = span + 1;
12134       close(fd);
12135    }
12136    return 0;
12137 }
12138 #endif   /* defined(HAVE_PRI) */
12139 
12140 #if defined(HAVE_PRI)
12141 static int pri_create_spanmap(int span, int trunkgroup, int logicalspan)
12142 {
12143    if (pris[span].mastertrunkgroup) {
12144       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);
12145       return -1;
12146    }
12147    pris[span].mastertrunkgroup = trunkgroup;
12148    pris[span].prilogicalspan = logicalspan;
12149    return 0;
12150 }
12151 #endif   /* defined(HAVE_PRI) */
12152 
12153 #if defined(HAVE_SS7)
12154 static unsigned int parse_pointcode(const char *pcstring)
12155 {
12156    unsigned int code1, code2, code3;
12157    int numvals;
12158 
12159    numvals = sscanf(pcstring, "%30d-%30d-%30d", &code1, &code2, &code3);
12160    if (numvals == 1)
12161       return code1;
12162    if (numvals == 3)
12163       return (code1 << 16) | (code2 << 8) | code3;
12164 
12165    return 0;
12166 }
12167 #endif   /* defined(HAVE_SS7) */
12168 
12169 #if defined(HAVE_SS7)
12170 static struct dahdi_ss7 * ss7_resolve_linkset(int linkset)
12171 {
12172    if ((linkset < 0) || (linkset >= NUM_SPANS))
12173       return NULL;
12174    else
12175       return &linksets[linkset - 1];
12176 }
12177 #endif   /* defined(HAVE_SS7) */
12178 
12179 #ifdef HAVE_OPENR2
12180 static void dahdi_r2_destroy_links(void)
12181 {
12182    int i = 0;
12183    if (!r2links) {
12184       return;
12185    }
12186    for (; i < r2links_count; i++) {
12187       if (r2links[i]->r2master != AST_PTHREADT_NULL) {
12188          pthread_cancel(r2links[i]->r2master);
12189          pthread_join(r2links[i]->r2master, NULL);
12190          openr2_context_delete(r2links[i]->protocol_context);
12191       }
12192       ast_free(r2links[i]);
12193    }
12194    ast_free(r2links);
12195    r2links = NULL;
12196    r2links_count = 0;
12197 }
12198 
12199 /* This is an artificial convenient capacity, to keep at most a full E1 of channels in a single thread */
12200 #define R2_LINK_CAPACITY 30
12201 static struct dahdi_mfcr2 *dahdi_r2_get_link(const struct dahdi_chan_conf *conf)
12202 {
12203    struct dahdi_mfcr2 *new_r2link = NULL;
12204    struct dahdi_mfcr2 **new_r2links = NULL;
12205 
12206    /* Only create a new R2 link if 
12207       1. This is the first link requested
12208       2. Configuration changed 
12209       3. We got more channels than supported per link */
12210    if (!r2links_count ||
12211        memcmp(&conf->mfcr2, &r2links[r2links_count - 1]->conf, sizeof(conf->mfcr2)) ||
12212       (r2links[r2links_count - 1]->numchans == R2_LINK_CAPACITY)) {
12213       new_r2link = ast_calloc(1, sizeof(**r2links));
12214       if (!new_r2link) {
12215          ast_log(LOG_ERROR, "Cannot allocate R2 link!\n");
12216          return NULL;
12217       }
12218       new_r2links = ast_realloc(r2links, ((r2links_count + 1) * sizeof(*r2links)));
12219       if (!new_r2links) {
12220          ast_log(LOG_ERROR, "Cannot allocate R2 link!\n");
12221          ast_free(new_r2link);
12222          return NULL;
12223       }
12224       r2links = new_r2links;
12225       new_r2link->r2master = AST_PTHREADT_NULL;
12226       r2links[r2links_count] = new_r2link;
12227       r2links_count++;
12228       ast_log(LOG_DEBUG, "Created new R2 link!\n");
12229    }
12230    return r2links[r2links_count - 1];
12231 }
12232 
12233 static int dahdi_r2_set_context(struct dahdi_mfcr2 *r2_link, const struct dahdi_chan_conf *conf)
12234 {
12235    char tmplogdir[] = "/tmp";
12236    char logdir[OR2_MAX_PATH];
12237    int threshold = 0;
12238    int snres = 0;
12239    r2_link->protocol_context = openr2_context_new(NULL, &dahdi_r2_event_iface,
12240          &dahdi_r2_transcode_iface, conf->mfcr2.variant, conf->mfcr2.max_ani,
12241          conf->mfcr2.max_dnis);
12242    if (!r2_link->protocol_context) {
12243       return -1;
12244    }
12245    openr2_context_set_log_level(r2_link->protocol_context, conf->mfcr2.loglevel);
12246    openr2_context_set_ani_first(r2_link->protocol_context, conf->mfcr2.get_ani_first);
12247 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
12248    openr2_context_set_skip_category_request(r2_link->protocol_context, conf->mfcr2.skip_category_request);
12249 #endif
12250    openr2_context_set_mf_threshold(r2_link->protocol_context, threshold);
12251    openr2_context_set_mf_back_timeout(r2_link->protocol_context, conf->mfcr2.mfback_timeout);
12252    openr2_context_set_metering_pulse_timeout(r2_link->protocol_context, conf->mfcr2.metering_pulse_timeout);
12253    openr2_context_set_double_answer(r2_link->protocol_context, conf->mfcr2.double_answer);
12254    openr2_context_set_immediate_accept(r2_link->protocol_context, conf->mfcr2.immediate_accept);
12255    if (ast_strlen_zero(conf->mfcr2.logdir)) {
12256       if (openr2_context_set_log_directory(r2_link->protocol_context, tmplogdir)) {
12257          ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir);
12258       }
12259    } else {
12260       snres = snprintf(logdir, sizeof(logdir), "%s/%s/%s", ast_config_AST_LOG_DIR, "mfcr2", conf->mfcr2.logdir);
12261       if (snres >= sizeof(logdir)) {
12262          ast_log(LOG_ERROR, "MFC/R2 logging directory truncated, using %s\n", tmplogdir);
12263          if (openr2_context_set_log_directory(r2_link->protocol_context, tmplogdir)) {
12264             ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir);
12265          }
12266       } else {
12267          if (openr2_context_set_log_directory(r2_link->protocol_context, logdir)) {
12268             ast_log(LOG_ERROR, "Failed setting MFC/R2 log directory %s\n", logdir);
12269          }
12270       }
12271    }
12272    if (!ast_strlen_zero(conf->mfcr2.r2proto_file)) {
12273       if (openr2_context_configure_from_advanced_file(r2_link->protocol_context, conf->mfcr2.r2proto_file)) {
12274          ast_log(LOG_ERROR, "Failed to configure r2context from advanced configuration file %s\n", conf->mfcr2.r2proto_file);
12275       }
12276    }
12277    /* Save the configuration used to setup this link */
12278    memcpy(&r2_link->conf, conf, sizeof(r2_link->conf));
12279    return 0;
12280 }
12281 #endif
12282 
12283 /* converts a DAHDI sigtype to signalling as can be configured from
12284  * chan_dahdi.conf.
12285  * While both have basically the same values, this will later be the
12286  * place to add filters and sanity checks
12287  */
12288 static int sigtype_to_signalling(int sigtype)
12289 {
12290    return sigtype;
12291 }
12292 
12293 /*!
12294  * \internal
12295  * \brief Get file name and channel number from (subdir,number)
12296  *
12297  * \param subdir name of the subdirectory under /dev/dahdi/
12298  * \param channel name of device file under /dev/dahdi/<subdir>/
12299  * \param path buffer to put file name in
12300  * \param pathlen maximal length of path
12301  *
12302  * \retval minor number of dahdi channel.
12303  * \retval -errno on error.
12304  */
12305 static int device2chan(const char *subdir, int channel, char *path, int pathlen)
12306 {
12307    struct stat stbuf;
12308    int      num;
12309 
12310    snprintf(path, pathlen, "/dev/dahdi/%s/%d", subdir, channel);
12311    if (stat(path, &stbuf) < 0) {
12312       ast_log(LOG_ERROR, "stat(%s) failed: %s\n", path, strerror(errno));
12313       return -errno;
12314    }
12315    if (!S_ISCHR(stbuf.st_mode)) {
12316       ast_log(LOG_ERROR, "%s: Not a character device file\n", path);
12317       return -EINVAL;
12318    }
12319    num = minor(stbuf.st_rdev);
12320    ast_log(LOG_DEBUG, "%s -> %d\n", path, num);
12321    return num;
12322 
12323 }
12324 
12325 /*!
12326  * \internal
12327  * \brief Initialize/create a channel interface.
12328  *
12329  * \param channel Channel interface number to initialize/create.
12330  * \param conf Configuration parameters to initialize interface with.
12331  * \param reloading What we are doing now:
12332  * 0 - initial module load,
12333  * 1 - module reload,
12334  * 2 - module restart
12335  *
12336  * \retval Interface-pointer initialized/created
12337  * \retval NULL if error
12338  */
12339 static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf, int reloading)
12340 {
12341    /* Make a dahdi_pvt structure for this interface */
12342    struct dahdi_pvt *tmp;/*!< Current channel structure initializing */
12343    char fn[80];
12344    struct dahdi_bufferinfo bi;
12345 
12346    int res;
12347 #if defined(HAVE_PRI)
12348    int span = 0;
12349 #endif   /* defined(HAVE_PRI) */
12350    int here = 0;/*!< TRUE if the channel interface already exists. */
12351    int x;
12352    struct analog_pvt *analog_p = NULL;
12353    struct dahdi_params p;
12354 #if defined(HAVE_PRI)
12355    struct dahdi_spaninfo si;
12356    struct sig_pri_chan *pri_chan = NULL;
12357 #endif   /* defined(HAVE_PRI) */
12358 #if defined(HAVE_SS7)
12359    struct sig_ss7_chan *ss7_chan = NULL;
12360 #endif   /* defined(HAVE_SS7) */
12361 
12362    /* Search channel interface list to see if it already exists. */
12363    for (tmp = iflist; tmp; tmp = tmp->next) {
12364       if (!tmp->destroy) {
12365          if (tmp->channel == channel) {
12366             /* The channel interface already exists. */
12367             here = 1;
12368             break;
12369          }
12370          if (tmp->channel > channel) {
12371             /* No way it can be in the sorted list. */
12372             tmp = NULL;
12373             break;
12374          }
12375       }
12376    }
12377 
12378    if (!here && reloading != 1) {
12379       tmp = ast_calloc(1, sizeof(*tmp));
12380       if (!tmp) {
12381          return NULL;
12382       }
12383       tmp->cc_params = ast_cc_config_params_init();
12384       if (!tmp->cc_params) {
12385          ast_free(tmp);
12386          return NULL;
12387       }
12388       ast_mutex_init(&tmp->lock);
12389       ifcount++;
12390       for (x = 0; x < 3; x++)
12391          tmp->subs[x].dfd = -1;
12392       tmp->channel = channel;
12393       tmp->priindication_oob = conf->chan.priindication_oob;
12394    }
12395 
12396    if (tmp) {
12397       int chan_sig = conf->chan.sig;
12398 
12399       /* If there are variables in tmp before it is updated to match the new config, clear them */
12400       if (reloading && tmp->vars) {
12401          ast_variables_destroy(tmp->vars);
12402          tmp->vars = NULL;
12403       }
12404 
12405 
12406       if (!here) {
12407          /* Can only get here if this is a new channel interface being created. */
12408          if ((channel != CHAN_PSEUDO)) {
12409             int count = 0;
12410 
12411             snprintf(fn, sizeof(fn), "%d", channel);
12412             /* Open non-blocking */
12413             tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
12414             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 */
12415                usleep(1);
12416                tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
12417                count++;
12418             }
12419             /* Allocate a DAHDI structure */
12420             if (tmp->subs[SUB_REAL].dfd < 0) {
12421                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);
12422                destroy_dahdi_pvt(tmp);
12423                return NULL;
12424             }
12425             memset(&p, 0, sizeof(p));
12426             res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
12427             if (res < 0) {
12428                ast_log(LOG_ERROR, "Unable to get parameters: %s\n", strerror(errno));
12429                destroy_dahdi_pvt(tmp);
12430                return NULL;
12431             }
12432             if (conf->is_sig_auto)
12433                chan_sig = sigtype_to_signalling(p.sigtype);
12434             if (p.sigtype != (chan_sig & 0x3ffff)) {
12435                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));
12436                destroy_dahdi_pvt(tmp);
12437                return NULL;
12438             }
12439             tmp->law_default = p.curlaw;
12440             tmp->law = p.curlaw;
12441             tmp->span = p.spanno;
12442 #if defined(HAVE_PRI)
12443             span = p.spanno - 1;
12444 #endif   /* defined(HAVE_PRI) */
12445          } else {
12446             chan_sig = 0;
12447          }
12448          tmp->sig = chan_sig;
12449          tmp->outsigmod = conf->chan.outsigmod;
12450 
12451          if (analog_lib_handles(chan_sig, tmp->radio, tmp->oprmode)) {
12452             analog_p = analog_new(dahdisig_to_analogsig(chan_sig), &dahdi_analog_callbacks, tmp);
12453             if (!analog_p) {
12454                destroy_dahdi_pvt(tmp);
12455                return NULL;
12456             }
12457             tmp->sig_pvt = analog_p;
12458          }
12459 #if defined(HAVE_SS7)
12460          if (chan_sig == SIG_SS7) {
12461             struct dahdi_ss7 *ss7;
12462             int clear = 0;
12463 
12464             if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &clear)) {
12465                ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
12466                destroy_dahdi_pvt(tmp);
12467                return NULL;
12468             }
12469 
12470             ss7 = ss7_resolve_linkset(cur_linkset);
12471             if (!ss7) {
12472                ast_log(LOG_ERROR, "Unable to find linkset %d\n", cur_linkset);
12473                destroy_dahdi_pvt(tmp);
12474                return NULL;
12475             }
12476             ss7->ss7.span = cur_linkset;
12477             if (cur_cicbeginswith < 0) {
12478                ast_log(LOG_ERROR, "Need to set cicbeginswith for the channels!\n");
12479                destroy_dahdi_pvt(tmp);
12480                return NULL;
12481             }
12482             ss7_chan = sig_ss7_chan_new(tmp, &dahdi_ss7_callbacks, &ss7->ss7);
12483             if (!ss7_chan) {
12484                destroy_dahdi_pvt(tmp);
12485                return NULL;
12486             }
12487             tmp->sig_pvt = ss7_chan;
12488             tmp->ss7 = &ss7->ss7;
12489 
12490             ss7_chan->channel = tmp->channel;
12491             ss7_chan->cic = cur_cicbeginswith++;
12492 
12493             /* DB: Add CIC's DPC information */
12494             ss7_chan->dpc = cur_defaultdpc;
12495 
12496             ss7->ss7.pvts[ss7->ss7.numchans++] = ss7_chan;
12497 
12498             ast_copy_string(ss7->ss7.internationalprefix, conf->ss7.ss7.internationalprefix, sizeof(ss7->ss7.internationalprefix));
12499             ast_copy_string(ss7->ss7.nationalprefix, conf->ss7.ss7.nationalprefix, sizeof(ss7->ss7.nationalprefix));
12500             ast_copy_string(ss7->ss7.subscriberprefix, conf->ss7.ss7.subscriberprefix, sizeof(ss7->ss7.subscriberprefix));
12501             ast_copy_string(ss7->ss7.unknownprefix, conf->ss7.ss7.unknownprefix, sizeof(ss7->ss7.unknownprefix));
12502 
12503             ss7->ss7.called_nai = conf->ss7.ss7.called_nai;
12504             ss7->ss7.calling_nai = conf->ss7.ss7.calling_nai;
12505          }
12506 #endif   /* defined(HAVE_SS7) */
12507 #ifdef HAVE_OPENR2
12508          if (chan_sig == SIG_MFCR2) {
12509             struct dahdi_mfcr2 *r2_link;
12510             r2_link = dahdi_r2_get_link(conf);
12511             if (!r2_link) {
12512                ast_log(LOG_WARNING, "Cannot get another R2 DAHDI context!\n");
12513                destroy_dahdi_pvt(tmp);
12514                return NULL;
12515             }
12516             if (!r2_link->protocol_context && dahdi_r2_set_context(r2_link, conf)) {
12517                ast_log(LOG_ERROR, "Cannot create OpenR2 protocol context.\n");
12518                destroy_dahdi_pvt(tmp);
12519                return NULL;
12520             }
12521             if (r2_link->numchans == ARRAY_LEN(r2_link->pvts)) {
12522                ast_log(LOG_ERROR, "Cannot add more channels to this link!\n");
12523                destroy_dahdi_pvt(tmp);
12524                return NULL;
12525             }
12526             r2_link->pvts[r2_link->numchans++] = tmp;
12527             tmp->r2chan = openr2_chan_new_from_fd(r2_link->protocol_context,
12528                                         tmp->subs[SUB_REAL].dfd,
12529                                         NULL, NULL);
12530             if (!tmp->r2chan) {
12531                openr2_liberr_t err = openr2_context_get_last_error(r2_link->protocol_context);
12532                ast_log(LOG_ERROR, "Cannot create OpenR2 channel: %s\n", openr2_context_error_string(err));
12533                destroy_dahdi_pvt(tmp);
12534                return NULL;
12535             }
12536             tmp->mfcr2 = r2_link;
12537             if (conf->mfcr2.call_files) {
12538                openr2_chan_enable_call_files(tmp->r2chan);
12539             }
12540             openr2_chan_set_client_data(tmp->r2chan, tmp);
12541             /* cast seems to be needed to get rid of the annoying warning regarding format attribute  */
12542             openr2_chan_set_logging_func(tmp->r2chan, (openr2_logging_func_t)dahdi_r2_on_chan_log);
12543             openr2_chan_set_log_level(tmp->r2chan, conf->mfcr2.loglevel);
12544             tmp->mfcr2_category = conf->mfcr2.category;
12545             tmp->mfcr2_charge_calls = conf->mfcr2.charge_calls;
12546             tmp->mfcr2_allow_collect_calls = conf->mfcr2.allow_collect_calls;
12547             tmp->mfcr2_forced_release = conf->mfcr2.forced_release;
12548             tmp->mfcr2_accept_on_offer = conf->mfcr2.accept_on_offer;
12549             tmp->mfcr2call = 0;
12550             tmp->mfcr2_dnis_index = 0;
12551             tmp->mfcr2_ani_index = 0;
12552          }
12553 #endif
12554 #ifdef HAVE_PRI
12555          if (dahdi_sig_pri_lib_handles(chan_sig)) {
12556             int offset;
12557             int matchesdchan;
12558             int x,y;
12559             int myswitchtype = 0;
12560 
12561             offset = 0;
12562             if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &offset)) {
12563                ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
12564                destroy_dahdi_pvt(tmp);
12565                return NULL;
12566             }
12567             if (span >= NUM_SPANS) {
12568                ast_log(LOG_ERROR, "Channel %d does not lie on a span I know of (%d)\n", channel, span);
12569                destroy_dahdi_pvt(tmp);
12570                return NULL;
12571             } else {
12572                si.spanno = 0;
12573                if (ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SPANSTAT,&si) == -1) {
12574                   ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno));
12575                   destroy_dahdi_pvt(tmp);
12576                   return NULL;
12577                }
12578                /* Store the logical span first based upon the real span */
12579                tmp->logicalspan = pris[span].prilogicalspan;
12580                pri_resolve_span(&span, channel, (channel - p.chanpos), &si);
12581                if (span < 0) {
12582                   ast_log(LOG_WARNING, "Channel %d: Unable to find locate channel/trunk group!\n", channel);
12583                   destroy_dahdi_pvt(tmp);
12584                   return NULL;
12585                }
12586                myswitchtype = conf->pri.pri.switchtype;
12587                /* Make sure this isn't a d-channel */
12588                matchesdchan=0;
12589                for (x = 0; x < NUM_SPANS; x++) {
12590                   for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
12591                      if (pris[x].dchannels[y] == tmp->channel) {
12592                         matchesdchan = 1;
12593                         break;
12594                      }
12595                   }
12596                }
12597                if (!matchesdchan) {
12598                   if (pris[span].pri.nodetype && (pris[span].pri.nodetype != conf->pri.pri.nodetype)) {
12599                      ast_log(LOG_ERROR, "Span %d is already a %s node\n", span + 1, pri_node2str(pris[span].pri.nodetype));
12600                      destroy_dahdi_pvt(tmp);
12601                      return NULL;
12602                   }
12603                   if (pris[span].pri.switchtype && (pris[span].pri.switchtype != myswitchtype)) {
12604                      ast_log(LOG_ERROR, "Span %d is already a %s switch\n", span + 1, pri_switch2str(pris[span].pri.switchtype));
12605                      destroy_dahdi_pvt(tmp);
12606                      return NULL;
12607                   }
12608                   if ((pris[span].pri.dialplan) && (pris[span].pri.dialplan != conf->pri.pri.dialplan)) {
12609                      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));
12610                      destroy_dahdi_pvt(tmp);
12611                      return NULL;
12612                   }
12613                   if (!ast_strlen_zero(pris[span].pri.idledial) && strcmp(pris[span].pri.idledial, conf->pri.pri.idledial)) {
12614                      ast_log(LOG_ERROR, "Span %d already has idledial '%s'.\n", span + 1, conf->pri.pri.idledial);
12615                      destroy_dahdi_pvt(tmp);
12616                      return NULL;
12617                   }
12618                   if (!ast_strlen_zero(pris[span].pri.idleext) && strcmp(pris[span].pri.idleext, conf->pri.pri.idleext)) {
12619                      ast_log(LOG_ERROR, "Span %d already has idleext '%s'.\n", span + 1, conf->pri.pri.idleext);
12620                      destroy_dahdi_pvt(tmp);
12621                      return NULL;
12622                   }
12623                   if (pris[span].pri.minunused && (pris[span].pri.minunused != conf->pri.pri.minunused)) {
12624                      ast_log(LOG_ERROR, "Span %d already has minunused of %d.\n", span + 1, conf->pri.pri.minunused);
12625                      destroy_dahdi_pvt(tmp);
12626                      return NULL;
12627                   }
12628                   if (pris[span].pri.minidle && (pris[span].pri.minidle != conf->pri.pri.minidle)) {
12629                      ast_log(LOG_ERROR, "Span %d already has minidle of %d.\n", span + 1, conf->pri.pri.minidle);
12630                      destroy_dahdi_pvt(tmp);
12631                      return NULL;
12632                   }
12633                   if (pris[span].pri.numchans >= ARRAY_LEN(pris[span].pri.pvts)) {
12634                      ast_log(LOG_ERROR, "Unable to add channel %d: Too many channels in trunk group %d!\n", channel,
12635                         pris[span].pri.trunkgroup);
12636                      destroy_dahdi_pvt(tmp);
12637                      return NULL;
12638                   }
12639 
12640                   ast_debug(4, "Adding callbacks %p to chan %d\n", &dahdi_pri_callbacks, tmp->channel);
12641                   pri_chan = sig_pri_chan_new(tmp, &dahdi_pri_callbacks, &pris[span].pri, tmp->logicalspan, p.chanpos, pris[span].mastertrunkgroup);
12642                   if (!pri_chan) {
12643                      destroy_dahdi_pvt(tmp);
12644                      return NULL;
12645                   }
12646                   tmp->sig_pvt = pri_chan;
12647                   tmp->pri = &pris[span].pri;
12648 
12649                   tmp->priexclusive = conf->chan.priexclusive;
12650 
12651                   if (!tmp->pri->cc_params) {
12652                      tmp->pri->cc_params = ast_cc_config_params_init();
12653                      if (!tmp->pri->cc_params) {
12654                         destroy_dahdi_pvt(tmp);
12655                         return NULL;
12656                      }
12657                   }
12658                   ast_cc_copy_config_params(tmp->pri->cc_params,
12659                      conf->chan.cc_params);
12660 
12661                   pris[span].pri.sig = chan_sig;
12662                   pris[span].pri.nodetype = conf->pri.pri.nodetype;
12663                   pris[span].pri.switchtype = myswitchtype;
12664                   pris[span].pri.nsf = conf->pri.pri.nsf;
12665                   pris[span].pri.dialplan = conf->pri.pri.dialplan;
12666                   pris[span].pri.localdialplan = conf->pri.pri.localdialplan;
12667                   pris[span].pri.pvts[pris[span].pri.numchans++] = tmp->sig_pvt;
12668                   pris[span].pri.minunused = conf->pri.pri.minunused;
12669                   pris[span].pri.minidle = conf->pri.pri.minidle;
12670                   pris[span].pri.overlapdial = conf->pri.pri.overlapdial;
12671                   pris[span].pri.qsigchannelmapping = conf->pri.pri.qsigchannelmapping;
12672                   pris[span].pri.discardremoteholdretrieval = conf->pri.pri.discardremoteholdretrieval;
12673 #if defined(HAVE_PRI_SERVICE_MESSAGES)
12674                   pris[span].pri.enable_service_message_support = conf->pri.pri.enable_service_message_support;
12675 #endif   /* defined(HAVE_PRI_SERVICE_MESSAGES) */
12676 #ifdef HAVE_PRI_INBANDDISCONNECT
12677                   pris[span].pri.inbanddisconnect = conf->pri.pri.inbanddisconnect;
12678 #endif
12679 #if defined(HAVE_PRI_CALL_HOLD)
12680                   pris[span].pri.hold_disconnect_transfer =
12681                      conf->pri.pri.hold_disconnect_transfer;
12682 #endif   /* defined(HAVE_PRI_CALL_HOLD) */
12683 #if defined(HAVE_PRI_CCSS)
12684                   pris[span].pri.cc_ptmp_recall_mode =
12685                      conf->pri.pri.cc_ptmp_recall_mode;
12686                   pris[span].pri.cc_qsig_signaling_link_req =
12687                      conf->pri.pri.cc_qsig_signaling_link_req;
12688                   pris[span].pri.cc_qsig_signaling_link_rsp =
12689                      conf->pri.pri.cc_qsig_signaling_link_rsp;
12690 #endif   /* defined(HAVE_PRI_CCSS) */
12691 #if defined(HAVE_PRI_CALL_WAITING)
12692                   pris[span].pri.max_call_waiting_calls =
12693                      conf->pri.pri.max_call_waiting_calls;
12694                   pris[span].pri.allow_call_waiting_calls =
12695                      conf->pri.pri.allow_call_waiting_calls;
12696 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
12697                   pris[span].pri.transfer = conf->chan.transfer;
12698                   pris[span].pri.facilityenable = conf->pri.pri.facilityenable;
12699 #if defined(HAVE_PRI_L2_PERSISTENCE)
12700                   pris[span].pri.l2_persistence = conf->pri.pri.l2_persistence;
12701 #endif   /* defined(HAVE_PRI_L2_PERSISTENCE) */
12702 #if defined(HAVE_PRI_AOC_EVENTS)
12703                   pris[span].pri.aoc_passthrough_flag = conf->pri.pri.aoc_passthrough_flag;
12704                   pris[span].pri.aoce_delayhangup = conf->pri.pri.aoce_delayhangup;
12705 #endif   /* defined(HAVE_PRI_AOC_EVENTS) */
12706                   if (chan_sig == SIG_BRI_PTMP) {
12707                      pris[span].pri.layer1_ignored = conf->pri.pri.layer1_ignored;
12708                   } else {
12709                      /* Option does not apply to this line type. */
12710                      pris[span].pri.layer1_ignored = 0;
12711                   }
12712                   pris[span].pri.append_msn_to_user_tag = conf->pri.pri.append_msn_to_user_tag;
12713                   pris[span].pri.inband_on_setup_ack = conf->pri.pri.inband_on_setup_ack;
12714                   pris[span].pri.inband_on_proceeding = conf->pri.pri.inband_on_proceeding;
12715                   ast_copy_string(pris[span].pri.initial_user_tag, conf->chan.cid_tag, sizeof(pris[span].pri.initial_user_tag));
12716                   ast_copy_string(pris[span].pri.msn_list, conf->pri.pri.msn_list, sizeof(pris[span].pri.msn_list));
12717 #if defined(HAVE_PRI_MWI)
12718                   ast_copy_string(pris[span].pri.mwi_mailboxes,
12719                      conf->pri.pri.mwi_mailboxes,
12720                      sizeof(pris[span].pri.mwi_mailboxes));
12721 #endif   /* defined(HAVE_PRI_MWI) */
12722                   ast_copy_string(pris[span].pri.idledial, conf->pri.pri.idledial, sizeof(pris[span].pri.idledial));
12723                   ast_copy_string(pris[span].pri.idleext, conf->pri.pri.idleext, sizeof(pris[span].pri.idleext));
12724                   ast_copy_string(pris[span].pri.internationalprefix, conf->pri.pri.internationalprefix, sizeof(pris[span].pri.internationalprefix));
12725                   ast_copy_string(pris[span].pri.nationalprefix, conf->pri.pri.nationalprefix, sizeof(pris[span].pri.nationalprefix));
12726                   ast_copy_string(pris[span].pri.localprefix, conf->pri.pri.localprefix, sizeof(pris[span].pri.localprefix));
12727                   ast_copy_string(pris[span].pri.privateprefix, conf->pri.pri.privateprefix, sizeof(pris[span].pri.privateprefix));
12728                   ast_copy_string(pris[span].pri.unknownprefix, conf->pri.pri.unknownprefix, sizeof(pris[span].pri.unknownprefix));
12729                   pris[span].pri.resetinterval = conf->pri.pri.resetinterval;
12730 
12731                   for (x = 0; x < PRI_MAX_TIMERS; x++) {
12732                      pris[span].pri.pritimers[x] = conf->pri.pri.pritimers[x];
12733                   }
12734 
12735 #if defined(HAVE_PRI_CALL_WAITING)
12736                   /* Channel initial config parameters. */
12737                   pris[span].pri.ch_cfg.stripmsd = conf->chan.stripmsd;
12738                   pris[span].pri.ch_cfg.hidecallerid = conf->chan.hidecallerid;
12739                   pris[span].pri.ch_cfg.hidecalleridname = conf->chan.hidecalleridname;
12740                   pris[span].pri.ch_cfg.immediate = conf->chan.immediate;
12741                   pris[span].pri.ch_cfg.priexclusive = conf->chan.priexclusive;
12742                   pris[span].pri.ch_cfg.priindication_oob = conf->chan.priindication_oob;
12743                   pris[span].pri.ch_cfg.use_callerid = conf->chan.use_callerid;
12744                   pris[span].pri.ch_cfg.use_callingpres = conf->chan.use_callingpres;
12745                   ast_copy_string(pris[span].pri.ch_cfg.context, conf->chan.context, sizeof(pris[span].pri.ch_cfg.context));
12746                   ast_copy_string(pris[span].pri.ch_cfg.mohinterpret, conf->chan.mohinterpret, sizeof(pris[span].pri.ch_cfg.mohinterpret));
12747 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
12748                } else {
12749                   ast_log(LOG_ERROR, "Channel %d is reserved for D-channel.\n", p.chanpos);
12750                   destroy_dahdi_pvt(tmp);
12751                   return NULL;
12752                }
12753             }
12754          }
12755 #endif
12756       } else {
12757          /* already exists in interface list */
12758          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));
12759          chan_sig = tmp->sig;
12760          if (tmp->subs[SUB_REAL].dfd > -1) {
12761             memset(&p, 0, sizeof(p));
12762             res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
12763          }
12764       }
12765       /* Adjust starttime on loopstart and kewlstart trunks to reasonable values */
12766       switch (chan_sig) {
12767       case SIG_FXSKS:
12768       case SIG_FXSLS:
12769       case SIG_EM:
12770       case SIG_EM_E1:
12771       case SIG_EMWINK:
12772       case SIG_FEATD:
12773       case SIG_FEATDMF:
12774       case SIG_FEATDMF_TA:
12775       case SIG_FEATB:
12776       case SIG_E911:
12777       case SIG_SF:
12778       case SIG_SFWINK:
12779       case SIG_FGC_CAMA:
12780       case SIG_FGC_CAMAMF:
12781       case SIG_SF_FEATD:
12782       case SIG_SF_FEATDMF:
12783       case SIG_SF_FEATB:
12784          p.starttime = 250;
12785          break;
12786       }
12787 
12788       if (tmp->radio) {
12789          /* XXX Waiting to hear back from Jim if these should be adjustable XXX */
12790          p.channo = channel;
12791          p.rxwinktime = 1;
12792          p.rxflashtime = 1;
12793          p.starttime = 1;
12794          p.debouncetime = 5;
12795       } else {
12796          p.channo = channel;
12797          /* Override timing settings based on config file */
12798          if (conf->timing.prewinktime >= 0)
12799             p.prewinktime = conf->timing.prewinktime;
12800          if (conf->timing.preflashtime >= 0)
12801             p.preflashtime = conf->timing.preflashtime;
12802          if (conf->timing.winktime >= 0)
12803             p.winktime = conf->timing.winktime;
12804          if (conf->timing.flashtime >= 0)
12805             p.flashtime = conf->timing.flashtime;
12806          if (conf->timing.starttime >= 0)
12807             p.starttime = conf->timing.starttime;
12808          if (conf->timing.rxwinktime >= 0)
12809             p.rxwinktime = conf->timing.rxwinktime;
12810          if (conf->timing.rxflashtime >= 0)
12811             p.rxflashtime = conf->timing.rxflashtime;
12812          if (conf->timing.debouncetime >= 0)
12813             p.debouncetime = conf->timing.debouncetime;
12814       }
12815 
12816       /* don't set parms on a pseudo-channel */
12817       if (tmp->subs[SUB_REAL].dfd >= 0)
12818       {
12819          res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_PARAMS, &p);
12820          if (res < 0) {
12821             ast_log(LOG_ERROR, "Unable to set parameters: %s\n", strerror(errno));
12822             destroy_dahdi_pvt(tmp);
12823             return NULL;
12824          }
12825       }
12826 #if 1
12827       if (!here && (tmp->subs[SUB_REAL].dfd > -1)) {
12828          memset(&bi, 0, sizeof(bi));
12829          res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
12830          if (!res) {
12831             bi.txbufpolicy = conf->chan.buf_policy;
12832             bi.rxbufpolicy = conf->chan.buf_policy;
12833             bi.numbufs = conf->chan.buf_no;
12834             res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
12835             if (res < 0) {
12836                ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", channel, strerror(errno));
12837             }
12838          } else {
12839             ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", channel, strerror(errno));
12840          }
12841          tmp->buf_policy = conf->chan.buf_policy;
12842          tmp->buf_no = conf->chan.buf_no;
12843          tmp->usefaxbuffers = conf->chan.usefaxbuffers;
12844          tmp->faxbuf_policy = conf->chan.faxbuf_policy;
12845          tmp->faxbuf_no = conf->chan.faxbuf_no;
12846          /* This is not as gnarly as it may first appear.  If the ioctl above failed, we'd be setting
12847           * tmp->bufsize to zero which would cause subsequent faxbuffer-related ioctl calls to fail.
12848           * The reason the ioctl call above failed should to be determined before worrying about the
12849           * faxbuffer-related ioctl calls */
12850          tmp->bufsize = bi.bufsize;
12851       }
12852 #endif
12853       tmp->immediate = conf->chan.immediate;
12854       tmp->transfertobusy = conf->chan.transfertobusy;
12855       if (chan_sig & __DAHDI_SIG_FXS) {
12856          tmp->mwimonitor_fsk = conf->chan.mwimonitor_fsk;
12857          tmp->mwimonitor_neon = conf->chan.mwimonitor_neon;
12858          tmp->mwimonitor_rpas = conf->chan.mwimonitor_rpas;
12859       }
12860       tmp->ringt_base = ringt_base;
12861       tmp->firstradio = 0;
12862       if ((chan_sig == SIG_FXOKS) || (chan_sig == SIG_FXOLS) || (chan_sig == SIG_FXOGS))
12863          tmp->permcallwaiting = conf->chan.callwaiting;
12864       else
12865          tmp->permcallwaiting = 0;
12866       /* Flag to destroy the channel must be cleared on new mkif.  Part of changes for reload to work */
12867       tmp->destroy = 0;
12868       tmp->drings = conf->chan.drings;
12869 
12870       /* 10 is a nice default. */
12871       if (tmp->drings.ringnum[0].range == 0)
12872          tmp->drings.ringnum[0].range = 10;
12873       if (tmp->drings.ringnum[1].range == 0)
12874          tmp->drings.ringnum[1].range = 10;
12875       if (tmp->drings.ringnum[2].range == 0)
12876          tmp->drings.ringnum[2].range = 10;
12877 
12878       tmp->usedistinctiveringdetection = usedistinctiveringdetection;
12879       tmp->callwaitingcallerid = conf->chan.callwaitingcallerid;
12880       tmp->threewaycalling = conf->chan.threewaycalling;
12881       tmp->adsi = conf->chan.adsi;
12882       tmp->use_smdi = conf->chan.use_smdi;
12883       tmp->permhidecallerid = conf->chan.hidecallerid;
12884       tmp->hidecalleridname = conf->chan.hidecalleridname;
12885       tmp->callreturn = conf->chan.callreturn;
12886       tmp->echocancel = conf->chan.echocancel;
12887       tmp->echotraining = conf->chan.echotraining;
12888       tmp->pulse = conf->chan.pulse;
12889       if (tmp->echocancel.head.tap_length) {
12890          tmp->echocanbridged = conf->chan.echocanbridged;
12891       } else {
12892          if (conf->chan.echocanbridged)
12893             ast_log(LOG_NOTICE, "echocancelwhenbridged requires echocancel to be enabled; ignoring\n");
12894          tmp->echocanbridged = 0;
12895       }
12896       tmp->busydetect = conf->chan.busydetect;
12897       tmp->busycount = conf->chan.busycount;
12898       tmp->busy_tonelength = conf->chan.busy_tonelength;
12899       tmp->busy_quietlength = conf->chan.busy_quietlength;
12900       tmp->callprogress = conf->chan.callprogress;
12901       tmp->waitfordialtone = conf->chan.waitfordialtone;
12902       tmp->cancallforward = conf->chan.cancallforward;
12903       tmp->dtmfrelax = conf->chan.dtmfrelax;
12904       tmp->callwaiting = tmp->permcallwaiting;
12905       tmp->hidecallerid = tmp->permhidecallerid;
12906       tmp->channel = channel;
12907       tmp->stripmsd = conf->chan.stripmsd;
12908       tmp->use_callerid = conf->chan.use_callerid;
12909       tmp->cid_signalling = conf->chan.cid_signalling;
12910       tmp->cid_start = conf->chan.cid_start;
12911       tmp->dahditrcallerid = conf->chan.dahditrcallerid;
12912       tmp->restrictcid = conf->chan.restrictcid;
12913       tmp->use_callingpres = conf->chan.use_callingpres;
12914       if (tmp->usedistinctiveringdetection) {
12915          if (!tmp->use_callerid) {
12916             ast_log(LOG_NOTICE, "Distinctive Ring detect requires 'usecallerid' be on\n");
12917             tmp->use_callerid = 1;
12918          }
12919       }
12920 
12921       if (tmp->cid_signalling == CID_SIG_SMDI) {
12922          if (!tmp->use_smdi) {
12923             ast_log(LOG_WARNING, "SMDI callerid requires SMDI to be enabled, enabling...\n");
12924             tmp->use_smdi = 1;
12925          }
12926       }
12927       if (tmp->use_smdi) {
12928          tmp->smdi_iface = ast_smdi_interface_find(conf->smdi_port);
12929          if (!(tmp->smdi_iface)) {
12930             ast_log(LOG_ERROR, "Invalid SMDI port specfied, disabling SMDI support\n");
12931             tmp->use_smdi = 0;
12932          }
12933       }
12934 
12935       ast_copy_string(tmp->accountcode, conf->chan.accountcode, sizeof(tmp->accountcode));
12936       tmp->amaflags = conf->chan.amaflags;
12937       if (!here) {
12938          tmp->confno = -1;
12939          tmp->propconfno = -1;
12940       }
12941       tmp->canpark = conf->chan.canpark;
12942       tmp->transfer = conf->chan.transfer;
12943       ast_copy_string(tmp->defcontext,conf->chan.context,sizeof(tmp->defcontext));
12944       ast_copy_string(tmp->language, conf->chan.language, sizeof(tmp->language));
12945       ast_copy_string(tmp->mohinterpret, conf->chan.mohinterpret, sizeof(tmp->mohinterpret));
12946       ast_copy_string(tmp->mohsuggest, conf->chan.mohsuggest, sizeof(tmp->mohsuggest));
12947       ast_copy_string(tmp->context, conf->chan.context, sizeof(tmp->context));
12948       ast_copy_string(tmp->parkinglot, conf->chan.parkinglot, sizeof(tmp->parkinglot));
12949       tmp->cid_ton = 0;
12950       if (analog_lib_handles(tmp->sig, tmp->radio, tmp->oprmode)) {
12951          ast_copy_string(tmp->cid_num, conf->chan.cid_num, sizeof(tmp->cid_num));
12952          ast_copy_string(tmp->cid_name, conf->chan.cid_name, sizeof(tmp->cid_name));
12953       } else {
12954          tmp->cid_num[0] = '\0';
12955          tmp->cid_name[0] = '\0';
12956       }
12957 #if defined(HAVE_PRI)
12958       if (dahdi_sig_pri_lib_handles(tmp->sig)) {
12959          tmp->cid_tag[0] = '\0';
12960       } else
12961 #endif   /* defined(HAVE_PRI) */
12962       {
12963          ast_copy_string(tmp->cid_tag, conf->chan.cid_tag, sizeof(tmp->cid_tag));
12964       }
12965       tmp->cid_subaddr[0] = '\0';
12966       ast_copy_string(tmp->mailbox, conf->chan.mailbox, sizeof(tmp->mailbox));
12967       if (channel != CHAN_PSEUDO && !ast_strlen_zero(tmp->mailbox)) {
12968          char *mailbox, *context;
12969          mailbox = context = ast_strdupa(tmp->mailbox);
12970          strsep(&context, "@");
12971          if (ast_strlen_zero(context))
12972             context = "default";
12973          tmp->mwi_event_sub = ast_event_subscribe(AST_EVENT_MWI, mwi_event_cb, "Dahdi MWI subscription", NULL,
12974             AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
12975             AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
12976             AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS,
12977             AST_EVENT_IE_END);
12978       }
12979 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
12980       tmp->mwisend_setting = conf->chan.mwisend_setting;
12981       tmp->mwisend_fsk  = conf->chan.mwisend_fsk;
12982       tmp->mwisend_rpas = conf->chan.mwisend_rpas;
12983 #endif
12984 
12985       tmp->group = conf->chan.group;
12986       tmp->callgroup = conf->chan.callgroup;
12987       tmp->pickupgroup= conf->chan.pickupgroup;
12988       if (conf->chan.vars) {
12989          struct ast_variable *v, *tmpvar;
12990                    for (v = conf->chan.vars ; v ; v = v->next) {
12991                          if ((tmpvar = ast_variable_new(v->name, v->value, v->file))) {
12992                                   tmpvar->next = tmp->vars;
12993                                    tmp->vars = tmpvar;
12994                            }
12995                   }
12996       }
12997       tmp->cid_rxgain = conf->chan.cid_rxgain;
12998       tmp->rxgain = conf->chan.rxgain;
12999       tmp->txgain = conf->chan.txgain;
13000       tmp->txdrc = conf->chan.txdrc;
13001       tmp->rxdrc = conf->chan.rxdrc;
13002       tmp->tonezone = conf->chan.tonezone;
13003       if (tmp->subs[SUB_REAL].dfd > -1) {
13004          set_actual_gain(tmp->subs[SUB_REAL].dfd, tmp->rxgain, tmp->txgain, tmp->rxdrc, tmp->txdrc, tmp->law);
13005          if (tmp->dsp)
13006             ast_dsp_set_digitmode(tmp->dsp, DSP_DIGITMODE_DTMF | tmp->dtmfrelax);
13007          update_conf(tmp);
13008          if (!here) {
13009             switch (chan_sig) {
13010             case SIG_PRI_LIB_HANDLE_CASES:
13011             case SIG_SS7:
13012             case SIG_MFCR2:
13013                break;
13014             default:
13015                /* Hang it up to be sure it's good */
13016                dahdi_set_hook(tmp->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
13017                break;
13018             }
13019          }
13020          ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SETTONEZONE,&tmp->tonezone);
13021          if ((res = get_alarms(tmp)) != DAHDI_ALARM_NONE) {
13022             /* the dchannel is down so put the channel in alarm */
13023             switch (tmp->sig) {
13024 #ifdef HAVE_PRI
13025             case SIG_PRI_LIB_HANDLE_CASES:
13026                sig_pri_set_alarm(tmp->sig_pvt, 1);
13027                break;
13028 #endif
13029 #if defined(HAVE_SS7)
13030             case SIG_SS7:
13031                sig_ss7_set_alarm(tmp->sig_pvt, 1);
13032                break;
13033 #endif   /* defined(HAVE_SS7) */
13034             default:
13035                /* The only sig submodule left should be sig_analog. */
13036                analog_p = tmp->sig_pvt;
13037                if (analog_p) {
13038                   analog_p->inalarm = 1;
13039                }
13040                tmp->inalarm = 1;
13041                break;
13042             }
13043             handle_alarms(tmp, res);
13044          }
13045       }
13046 
13047       tmp->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
13048       tmp->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
13049       tmp->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
13050       tmp->sendcalleridafter = conf->chan.sendcalleridafter;
13051       ast_cc_copy_config_params(tmp->cc_params, conf->chan.cc_params);
13052 
13053       if (!here) {
13054          tmp->locallyblocked = 0;
13055          tmp->remotelyblocked = 0;
13056          switch (tmp->sig) {
13057 #if defined(HAVE_PRI)
13058          case SIG_PRI_LIB_HANDLE_CASES:
13059             tmp->inservice = 1;/* Inservice until actually implemented. */
13060 #if defined(HAVE_PRI_SERVICE_MESSAGES)
13061             ((struct sig_pri_chan *) tmp->sig_pvt)->service_status = 0;
13062             if (chan_sig == SIG_PRI) {
13063                char db_chan_name[20];
13064                char db_answer[5];
13065 
13066                /*
13067                 * Initialize the active out-of-service status
13068                 * and delete any record if the feature is not enabled.
13069                 */
13070                snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, tmp->span, tmp->channel);
13071                if (!ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) {
13072                   unsigned *why;
13073 
13074                   why = &((struct sig_pri_chan *) tmp->sig_pvt)->service_status;
13075                   if (tmp->pri->enable_service_message_support) {
13076                      char state;
13077 
13078                      sscanf(db_answer, "%1c:%30u", &state, why);
13079 
13080                      /* Ensure that only the implemented bits could be set.*/
13081                      *why &= (SRVST_NEAREND | SRVST_FAREND);
13082                   }
13083                   if (!*why) {
13084                      ast_db_del(db_chan_name, SRVST_DBKEY);
13085                   }
13086                }
13087             }
13088 #endif   /* defined(HAVE_PRI_SERVICE_MESSAGES) */
13089             break;
13090 #endif   /* defined(HAVE_PRI) */
13091 #if defined(HAVE_SS7)
13092          case SIG_SS7:
13093             tmp->inservice = 0;
13094             break;
13095 #endif   /* defined(HAVE_SS7) */
13096          default:
13097              /* We default to in service on protocols that don't have a reset */
13098             tmp->inservice = 1;
13099             break;
13100          }
13101       }
13102 
13103       switch (tmp->sig) {
13104 #if defined(HAVE_PRI)
13105       case SIG_PRI_LIB_HANDLE_CASES:
13106          if (pri_chan) {
13107             pri_chan->channel = tmp->channel;
13108             pri_chan->hidecallerid = tmp->hidecallerid;
13109             pri_chan->hidecalleridname = tmp->hidecalleridname;
13110             pri_chan->immediate = tmp->immediate;
13111             pri_chan->inalarm = tmp->inalarm;
13112             pri_chan->priexclusive = tmp->priexclusive;
13113             pri_chan->priindication_oob = tmp->priindication_oob;
13114             pri_chan->use_callerid = tmp->use_callerid;
13115             pri_chan->use_callingpres = tmp->use_callingpres;
13116             ast_copy_string(pri_chan->context, tmp->context,
13117                sizeof(pri_chan->context));
13118             ast_copy_string(pri_chan->mohinterpret, tmp->mohinterpret,
13119                sizeof(pri_chan->mohinterpret));
13120             pri_chan->stripmsd = tmp->stripmsd;
13121          }
13122          break;
13123 #endif   /* defined(HAVE_PRI) */
13124 #if defined(HAVE_SS7)
13125       case SIG_SS7:
13126          if (ss7_chan) {
13127             ss7_chan->inalarm = tmp->inalarm;
13128 
13129             ss7_chan->stripmsd = tmp->stripmsd;
13130             ss7_chan->hidecallerid = tmp->hidecallerid;
13131             ss7_chan->use_callerid = tmp->use_callerid;
13132             ss7_chan->use_callingpres = tmp->use_callingpres;
13133             ss7_chan->immediate = tmp->immediate;
13134             ss7_chan->locallyblocked = tmp->locallyblocked;
13135             ss7_chan->remotelyblocked = tmp->remotelyblocked;
13136             ast_copy_string(ss7_chan->context, tmp->context,
13137                sizeof(ss7_chan->context));
13138             ast_copy_string(ss7_chan->mohinterpret, tmp->mohinterpret,
13139                sizeof(ss7_chan->mohinterpret));
13140          }
13141          break;
13142 #endif   /* defined(HAVE_SS7) */
13143       default:
13144          /* The only sig submodule left should be sig_analog. */
13145          analog_p = tmp->sig_pvt;
13146          if (analog_p) {
13147             analog_p->channel = tmp->channel;
13148             analog_p->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
13149             analog_p->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
13150             analog_p->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
13151             analog_p->permcallwaiting = conf->chan.callwaiting; /* permcallwaiting possibly modified in analog_config_complete */
13152             analog_p->callreturn = conf->chan.callreturn;
13153             analog_p->cancallforward = conf->chan.cancallforward;
13154             analog_p->canpark = conf->chan.canpark;
13155             analog_p->dahditrcallerid = conf->chan.dahditrcallerid;
13156             analog_p->immediate = conf->chan.immediate;
13157             analog_p->permhidecallerid = conf->chan.permhidecallerid;
13158             analog_p->pulse = conf->chan.pulse;
13159             analog_p->threewaycalling = conf->chan.threewaycalling;
13160             analog_p->transfer = conf->chan.transfer;
13161             analog_p->transfertobusy = conf->chan.transfertobusy;
13162             analog_p->use_callerid = tmp->use_callerid;
13163             analog_p->use_smdi = tmp->use_smdi;
13164             analog_p->smdi_iface = tmp->smdi_iface;
13165             analog_p->outsigmod = ANALOG_SIG_NONE;
13166             analog_p->echotraining = conf->chan.echotraining;
13167             analog_p->cid_signalling = conf->chan.cid_signalling;
13168             analog_p->stripmsd = conf->chan.stripmsd;
13169             switch (conf->chan.cid_start) {
13170             case CID_START_POLARITY:
13171                analog_p->cid_start = ANALOG_CID_START_POLARITY;
13172                break;
13173             case CID_START_POLARITY_IN:
13174                analog_p->cid_start = ANALOG_CID_START_POLARITY_IN;
13175                break;
13176             case CID_START_DTMF_NOALERT:
13177                analog_p->cid_start = ANALOG_CID_START_DTMF_NOALERT;
13178                break;
13179             default:
13180                analog_p->cid_start = ANALOG_CID_START_RING;
13181                break;
13182             }
13183             analog_p->callwaitingcallerid = conf->chan.callwaitingcallerid;
13184             analog_p->ringt = conf->chan.ringt;
13185             analog_p->ringt_base = ringt_base;
13186             analog_p->onhooktime = time(NULL);
13187             if (chan_sig & __DAHDI_SIG_FXO) {
13188                memset(&p, 0, sizeof(p));
13189                res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
13190                if (!res) {
13191                   analog_p->fxsoffhookstate = p.rxisoffhook;
13192                }
13193 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
13194                res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_VMWI_CONFIG, &tmp->mwisend_setting);
13195 #endif
13196             }
13197             analog_p->msgstate = -1;
13198 
13199             ast_copy_string(analog_p->mohsuggest, conf->chan.mohsuggest, sizeof(analog_p->mohsuggest));
13200             ast_copy_string(analog_p->cid_num, conf->chan.cid_num, sizeof(analog_p->cid_num));
13201             ast_copy_string(analog_p->cid_name, conf->chan.cid_name, sizeof(analog_p->cid_name));
13202 
13203             analog_config_complete(analog_p);
13204          }
13205          break;
13206       }
13207 #if defined(HAVE_PRI)
13208       if (tmp->channel == CHAN_PSEUDO) {
13209          /*
13210           * Save off pseudo channel buffer policy values for dynamic creation of
13211           * no B channel interfaces.
13212           */
13213          dahdi_pseudo_parms.buf_no = tmp->buf_no;
13214          dahdi_pseudo_parms.buf_policy = tmp->buf_policy;
13215          dahdi_pseudo_parms.faxbuf_no = tmp->faxbuf_no;
13216          dahdi_pseudo_parms.faxbuf_policy = tmp->faxbuf_policy;
13217       }
13218 #endif   /* defined(HAVE_PRI) */
13219    }
13220    if (tmp && !here) {
13221       /* Add the new channel interface to the sorted channel interface list. */
13222       dahdi_iflist_insert(tmp);
13223    }
13224    return tmp;
13225 }
13226 
13227 static int is_group_or_channel_match(struct dahdi_pvt *p, int span, ast_group_t groupmatch, int *groupmatched, int channelmatch, int *channelmatched)
13228 {
13229 #if defined(HAVE_PRI)
13230    if (0 < span) {
13231       /* The channel must be on the specified PRI span. */
13232       if (!p->pri || p->pri->span != span) {
13233          return 0;
13234       }
13235       if (!groupmatch && channelmatch == -1) {
13236          /* Match any group since it only needs to be on the PRI span. */
13237          *groupmatched = 1;
13238          return 1;
13239       }
13240    }
13241 #endif   /* defined(HAVE_PRI) */
13242    /* check group matching */
13243    if (groupmatch) {
13244       if ((p->group & groupmatch) != groupmatch)
13245          /* Doesn't match the specified group, try the next one */
13246          return 0;
13247       *groupmatched = 1;
13248    }
13249    /* Check to see if we have a channel match */
13250    if (channelmatch != -1) {
13251       if (p->channel != channelmatch)
13252          /* Doesn't match the specified channel, try the next one */
13253          return 0;
13254       *channelmatched = 1;
13255    }
13256 
13257    return 1;
13258 }
13259 
13260 static int available(struct dahdi_pvt **pvt, int is_specific_channel)
13261 {
13262    struct dahdi_pvt *p = *pvt;
13263 
13264    if (p->inalarm)
13265       return 0;
13266 
13267    if (analog_lib_handles(p->sig, p->radio, p->oprmode))
13268       return analog_available(p->sig_pvt);
13269 
13270    switch (p->sig) {
13271 #if defined(HAVE_PRI)
13272    case SIG_PRI_LIB_HANDLE_CASES:
13273       {
13274          struct sig_pri_chan *pvt_chan;
13275          int res;
13276 
13277          pvt_chan = p->sig_pvt;
13278          res = sig_pri_available(&pvt_chan, is_specific_channel);
13279          *pvt = pvt_chan->chan_pvt;
13280          return res;
13281       }
13282 #endif   /* defined(HAVE_PRI) */
13283 #if defined(HAVE_SS7)
13284    case SIG_SS7:
13285       return sig_ss7_available(p->sig_pvt);
13286 #endif   /* defined(HAVE_SS7) */
13287    default:
13288       break;
13289    }
13290 
13291    if (p->locallyblocked || p->remotelyblocked) {
13292       return 0;
13293    }
13294 
13295    /* If no owner definitely available */
13296    if (!p->owner) {
13297 #ifdef HAVE_OPENR2
13298       /* Trust MFC/R2 */
13299       if (p->mfcr2) {
13300          if (p->mfcr2call) {
13301             return 0;
13302          } else {
13303             return 1;
13304          }
13305       }
13306 #endif
13307       return 1;
13308    }
13309 
13310    return 0;
13311 }
13312 
13313 #if defined(HAVE_PRI)
13314 #if defined(HAVE_PRI_CALL_WAITING)
13315 /*!
13316  * \internal
13317  * \brief Init the private channel configuration using the span controller.
13318  * \since 1.8
13319  *
13320  * \param priv Channel to init the configuration.
13321  * \param pri sig_pri PRI control structure.
13322  *
13323  * \note Assumes the pri->lock is already obtained.
13324  *
13325  * \return Nothing
13326  */
13327 static void my_pri_init_config(void *priv, struct sig_pri_span *pri)
13328 {
13329    struct dahdi_pvt *pvt = priv;
13330 
13331    pvt->stripmsd = pri->ch_cfg.stripmsd;
13332    pvt->hidecallerid = pri->ch_cfg.hidecallerid;
13333    pvt->hidecalleridname = pri->ch_cfg.hidecalleridname;
13334    pvt->immediate = pri->ch_cfg.immediate;
13335    pvt->priexclusive = pri->ch_cfg.priexclusive;
13336    pvt->priindication_oob = pri->ch_cfg.priindication_oob;
13337    pvt->use_callerid = pri->ch_cfg.use_callerid;
13338    pvt->use_callingpres = pri->ch_cfg.use_callingpres;
13339    ast_copy_string(pvt->context, pri->ch_cfg.context, sizeof(pvt->context));
13340    ast_copy_string(pvt->mohinterpret, pri->ch_cfg.mohinterpret, sizeof(pvt->mohinterpret));
13341 }
13342 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
13343 #endif   /* defined(HAVE_PRI) */
13344 
13345 #if defined(HAVE_PRI)
13346 /*!
13347  * \internal
13348  * \brief Create a no B channel interface.
13349  * \since 1.8
13350  *
13351  * \param pri sig_pri span controller to add interface.
13352  *
13353  * \note Assumes the pri->lock is already obtained.
13354  *
13355  * \retval array-index into private pointer array on success.
13356  * \retval -1 on error.
13357  */
13358 static int dahdi_new_pri_nobch_channel(struct sig_pri_span *pri)
13359 {
13360    int pvt_idx;
13361    int res;
13362    unsigned idx;
13363    struct dahdi_pvt *pvt;
13364    struct sig_pri_chan *chan;
13365    struct dahdi_bufferinfo bi;
13366 
13367    static int nobch_channel = CHAN_PSEUDO;
13368 
13369    /* Find spot in the private pointer array for new interface. */
13370    for (pvt_idx = 0; pvt_idx < pri->numchans; ++pvt_idx) {
13371       if (!pri->pvts[pvt_idx]) {
13372          break;
13373       }
13374    }
13375    if (pri->numchans == pvt_idx) {
13376       if (ARRAY_LEN(pri->pvts) <= pvt_idx) {
13377          ast_log(LOG_ERROR, "Unable to add a no-B-channel interface!\n");
13378          return -1;
13379       }
13380 
13381       /* Add new spot to the private pointer array. */
13382       pri->pvts[pvt_idx] = NULL;
13383       ++pri->numchans;
13384    }
13385 
13386    pvt = ast_calloc(1, sizeof(*pvt));
13387    if (!pvt) {
13388       return -1;
13389    }
13390    pvt->cc_params = ast_cc_config_params_init();
13391    if (!pvt->cc_params) {
13392       ast_free(pvt);
13393       return -1;
13394    }
13395    ast_mutex_init(&pvt->lock);
13396    for (idx = 0; idx < ARRAY_LEN(pvt->subs); ++idx) {
13397       pvt->subs[idx].dfd = -1;
13398    }
13399    pvt->buf_no = dahdi_pseudo_parms.buf_no;
13400    pvt->buf_policy = dahdi_pseudo_parms.buf_policy;
13401    pvt->faxbuf_no = dahdi_pseudo_parms.faxbuf_no;
13402    pvt->faxbuf_policy = dahdi_pseudo_parms.faxbuf_policy;
13403 
13404    chan = sig_pri_chan_new(pvt, &dahdi_pri_callbacks, pri, 0, 0, 0);
13405    if (!chan) {
13406       destroy_dahdi_pvt(pvt);
13407       return -1;
13408    }
13409    chan->no_b_channel = 1;
13410 
13411    /*
13412     * Pseudo channel companding law.
13413     * Needed for outgoing call waiting calls.
13414     * XXX May need to make this determined by switchtype or user option.
13415     */
13416    pvt->law_default = DAHDI_LAW_ALAW;
13417 
13418    pvt->sig = pri->sig;
13419    pvt->outsigmod = -1;
13420    pvt->pri = pri;
13421    pvt->sig_pvt = chan;
13422    pri->pvts[pvt_idx] = chan;
13423 
13424    pvt->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo");
13425    if (pvt->subs[SUB_REAL].dfd < 0) {
13426       ast_log(LOG_ERROR, "Unable to open no B channel interface pseudo channel: %s\n",
13427          strerror(errno));
13428       destroy_dahdi_pvt(pvt);
13429       return -1;
13430    }
13431    memset(&bi, 0, sizeof(bi));
13432    res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
13433    if (!res) {
13434       pvt->bufsize = bi.bufsize;
13435       bi.txbufpolicy = pvt->buf_policy;
13436       bi.rxbufpolicy = pvt->buf_policy;
13437       bi.numbufs = pvt->buf_no;
13438       res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
13439       if (res < 0) {
13440          ast_log(LOG_WARNING,
13441             "Unable to set buffer policy on no B channel interface: %s\n",
13442             strerror(errno));
13443       }
13444    } else
13445       ast_log(LOG_WARNING,
13446          "Unable to check buffer policy on no B channel interface: %s\n",
13447          strerror(errno));
13448 
13449    --nobch_channel;
13450    if (CHAN_PSEUDO < nobch_channel) {
13451       nobch_channel = CHAN_PSEUDO - 1;
13452    }
13453    pvt->channel = nobch_channel;
13454    pvt->span = pri->span;
13455    chan->channel = pvt->channel;
13456 
13457    dahdi_nobch_insert(pri, pvt);
13458 
13459    return pvt_idx;
13460 }
13461 #endif   /* defined(HAVE_PRI) */
13462 
13463 /* This function can *ONLY* be used for copying pseudo (CHAN_PSEUDO) private
13464    structures; it makes no attempt to safely copy regular channel private
13465    structures that might contain reference-counted object pointers and other
13466    scary bits
13467 */
13468 static struct dahdi_pvt *duplicate_pseudo(struct dahdi_pvt *src)
13469 {
13470    struct dahdi_pvt *p;
13471    struct dahdi_bufferinfo bi;
13472    int res;
13473 
13474    p = ast_malloc(sizeof(*p));
13475    if (!p) {
13476       return NULL;
13477    }
13478    *p = *src;
13479 
13480    /* Must deep copy the cc_params. */
13481    p->cc_params = ast_cc_config_params_init();
13482    if (!p->cc_params) {
13483       ast_free(p);
13484       return NULL;
13485    }
13486    ast_cc_copy_config_params(p->cc_params, src->cc_params);
13487 
13488    p->which_iflist = DAHDI_IFLIST_NONE;
13489    p->next = NULL;
13490    p->prev = NULL;
13491    ast_mutex_init(&p->lock);
13492    p->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo");
13493    if (p->subs[SUB_REAL].dfd < 0) {
13494       ast_log(LOG_ERROR, "Unable to dup channel: %s\n", strerror(errno));
13495       destroy_dahdi_pvt(p);
13496       return NULL;
13497    }
13498    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
13499    if (!res) {
13500       bi.txbufpolicy = src->buf_policy;
13501       bi.rxbufpolicy = src->buf_policy;
13502       bi.numbufs = src->buf_no;
13503       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
13504       if (res < 0) {
13505          ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel: %s\n", strerror(errno));
13506       }
13507    } else
13508       ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel: %s\n", strerror(errno));
13509    p->destroy = 1;
13510    dahdi_iflist_insert(p);
13511    return p;
13512 }
13513 
13514 struct dahdi_starting_point {
13515    /*! Group matching mask.  Zero if not specified. */
13516    ast_group_t groupmatch;
13517    /*! DAHDI channel to match with.  -1 if not specified. */
13518    int channelmatch;
13519    /*! Round robin saved search location index. (Valid if roundrobin TRUE) */
13520    int rr_starting_point;
13521    /*! ISDN span where channels can be picked (Zero if not specified) */
13522    int span;
13523    /*! Analog channel distinctive ring cadance index. */
13524    int cadance;
13525    /*! Dialing option. c/r/d if present and valid. */
13526    char opt;
13527    /*! TRUE if to search the channel list backwards. */
13528    char backwards;
13529    /*! TRUE if search is done with round robin sequence. */
13530    char roundrobin;
13531 };
13532 static struct dahdi_pvt *determine_starting_point(const char *data, struct dahdi_starting_point *param)
13533 {
13534    char *dest;
13535    char *s;
13536    int x;
13537    int res = 0;
13538    struct dahdi_pvt *p;
13539    char *subdir = NULL;
13540    AST_DECLARE_APP_ARGS(args,
13541       AST_APP_ARG(group);  /* channel/group token */
13542       //AST_APP_ARG(ext);  /* extension token */
13543       //AST_APP_ARG(opts); /* options token */
13544       AST_APP_ARG(other);  /* Any remining unused arguments */
13545    );
13546 
13547    /*
13548     * data is ---v
13549     * Dial(DAHDI/pseudo[/extension[/options]])
13550     * Dial(DAHDI/<channel#>[c|r<cadance#>|d][/extension[/options]])
13551     * Dial(DAHDI/<subdir>!<channel#>[c|r<cadance#>|d][/extension[/options]])
13552     * Dial(DAHDI/i<span>[/extension[/options]])
13553     * Dial(DAHDI/[i<span>-](g|G|r|R)<group#(0-63)>[c|r<cadance#>|d][/extension[/options]])
13554     *
13555     * i - ISDN span channel restriction.
13556     *     Used by CC to ensure that the CC recall goes out the same span.
13557     *     Also to make ISDN channel names dialable when the sequence number
13558     *     is stripped off.  (Used by DTMF attended transfer feature.)
13559     *
13560     * g - channel group allocation search forward
13561     * G - channel group allocation search backward
13562     * r - channel group allocation round robin search forward
13563     * R - channel group allocation round robin search backward
13564     *
13565     * c - Wait for DTMF digit to confirm answer
13566     * r<cadance#> - Set distintive ring cadance number
13567     * d - Force bearer capability for ISDN/SS7 call to digital.
13568     */
13569 
13570    if (data) {
13571       dest = ast_strdupa(data);
13572    } else {
13573       ast_log(LOG_WARNING, "Channel requested with no data\n");
13574       return NULL;
13575    }
13576    AST_NONSTANDARD_APP_ARGS(args, dest, '/');
13577    if (!args.argc || ast_strlen_zero(args.group)) {
13578       ast_log(LOG_WARNING, "No channel/group specified\n");
13579       return NULL;
13580    }
13581 
13582    /* Initialize the output parameters */
13583    memset(param, 0, sizeof(*param));
13584    param->channelmatch = -1;
13585 
13586    if (strchr(args.group, '!') != NULL) {
13587       char *prev = args.group;
13588       while ((s = strchr(prev, '!')) != NULL) {
13589          *s++ = '/';
13590          prev = s;
13591       }
13592       *(prev - 1) = '\0';
13593       subdir = args.group;
13594       args.group = prev;
13595    } else if (args.group[0] == 'i') {
13596       /* Extract the ISDN span channel restriction specifier. */
13597       res = sscanf(args.group + 1, "%30d", &x);
13598       if (res < 1) {
13599          ast_log(LOG_WARNING, "Unable to determine ISDN span for data %s\n", data);
13600          return NULL;
13601       }
13602       param->span = x;
13603 
13604       /* Remove the ISDN span channel restriction specifier. */
13605       s = strchr(args.group, '-');
13606       if (!s) {
13607          /* Search all groups since we are ISDN span restricted. */
13608          return iflist;
13609       }
13610       args.group = s + 1;
13611       res = 0;
13612    }
13613    if (toupper(args.group[0]) == 'G' || toupper(args.group[0])=='R') {
13614       /* Retrieve the group number */
13615       s = args.group + 1;
13616       res = sscanf(s, "%30d%1c%30d", &x, &param->opt, &param->cadance);
13617       if (res < 1) {
13618          ast_log(LOG_WARNING, "Unable to determine group for data %s\n", data);
13619          return NULL;
13620       }
13621       param->groupmatch = ((ast_group_t) 1 << x);
13622 
13623       if (toupper(args.group[0]) == 'G') {
13624          if (args.group[0] == 'G') {
13625             param->backwards = 1;
13626             p = ifend;
13627          } else
13628             p = iflist;
13629       } else {
13630          if (ARRAY_LEN(round_robin) <= x) {
13631             ast_log(LOG_WARNING, "Round robin index %d out of range for data %s\n",
13632                x, data);
13633             return NULL;
13634          }
13635          if (args.group[0] == 'R') {
13636             param->backwards = 1;
13637             p = round_robin[x] ? round_robin[x]->prev : ifend;
13638             if (!p)
13639                p = ifend;
13640          } else {
13641             p = round_robin[x] ? round_robin[x]->next : iflist;
13642             if (!p)
13643                p = iflist;
13644          }
13645          param->roundrobin = 1;
13646          param->rr_starting_point = x;
13647       }
13648    } else {
13649       s = args.group;
13650       if (!strcasecmp(s, "pseudo")) {
13651          /* Special case for pseudo */
13652          x = CHAN_PSEUDO;
13653          param->channelmatch = x;
13654       } else {
13655          res = sscanf(s, "%30d%1c%30d", &x, &param->opt, &param->cadance);
13656          if (res < 1) {
13657             ast_log(LOG_WARNING, "Unable to determine channel for data %s\n", data);
13658             return NULL;
13659          } else {
13660             param->channelmatch = x;
13661          }
13662       }
13663       if (subdir) {
13664          char path[PATH_MAX];
13665          struct stat stbuf;
13666 
13667          snprintf(path, sizeof(path), "/dev/dahdi/%s/%d",
13668                subdir, param->channelmatch);
13669          if (stat(path, &stbuf) < 0) {
13670             ast_log(LOG_WARNING, "stat(%s) failed: %s\n",
13671                   path, strerror(errno));
13672             return NULL;
13673          }
13674          if (!S_ISCHR(stbuf.st_mode)) {
13675             ast_log(LOG_ERROR, "%s: Not a character device file\n",
13676                   path);
13677             return NULL;
13678          }
13679          param->channelmatch = minor(stbuf.st_rdev);
13680       }
13681 
13682       p = iflist;
13683    }
13684 
13685    if (param->opt == 'r' && res < 3) {
13686       ast_log(LOG_WARNING, "Distinctive ring missing identifier in '%s'\n", data);
13687       param->opt = '\0';
13688    }
13689 
13690    return p;
13691 }
13692 
13693 static struct ast_channel *dahdi_request(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause)
13694 {
13695    int callwait = 0;
13696    struct dahdi_pvt *p;
13697    struct ast_channel *tmp = NULL;
13698    struct dahdi_pvt *exitpvt;
13699    int channelmatched = 0;
13700    int groupmatched = 0;
13701 #if defined(HAVE_PRI) || defined(HAVE_SS7)
13702    int transcapdigital = 0;
13703 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
13704    struct dahdi_starting_point start;
13705 
13706    ast_mutex_lock(&iflock);
13707    p = determine_starting_point(data, &start);
13708    if (!p) {
13709       /* We couldn't determine a starting point, which likely means badly-formatted channel name. Abort! */
13710       ast_mutex_unlock(&iflock);
13711       return NULL;
13712    }
13713 
13714    /* Search for an unowned channel */
13715    exitpvt = p;
13716    while (p && !tmp) {
13717       if (start.roundrobin)
13718          round_robin[start.rr_starting_point] = p;
13719 
13720       if (is_group_or_channel_match(p, start.span, start.groupmatch, &groupmatched, start.channelmatch, &channelmatched)
13721          && available(&p, channelmatched)) {
13722          ast_debug(1, "Using channel %d\n", p->channel);
13723 
13724          callwait = (p->owner != NULL);
13725 #ifdef HAVE_OPENR2
13726          if (p->mfcr2) {
13727             ast_mutex_lock(&p->lock);
13728             if (p->mfcr2call) {
13729                ast_mutex_unlock(&p->lock);
13730                ast_log(LOG_DEBUG, "Yay!, someone just beat us in the race for channel %d.\n", p->channel);
13731                goto next;
13732             }
13733             p->mfcr2call = 1;
13734             ast_mutex_unlock(&p->lock);
13735          }
13736 #endif
13737          if (p->channel == CHAN_PSEUDO) {
13738             p = duplicate_pseudo(p);
13739             if (!p) {
13740                break;
13741             }
13742          }
13743 
13744          p->distinctivering = 0;
13745          /* Make special notes */
13746          switch (start.opt) {
13747          case '\0':
13748             /* No option present. */
13749             break;
13750          case 'c':
13751             /* Confirm answer */
13752             p->confirmanswer = 1;
13753             break;
13754          case 'r':
13755             /* Distinctive ring */
13756             p->distinctivering = start.cadance;
13757             break;
13758          case 'd':
13759 #if defined(HAVE_PRI) || defined(HAVE_SS7)
13760             /* If this is an ISDN call, make it digital */
13761             transcapdigital = AST_TRANS_CAP_DIGITAL;
13762 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
13763             break;
13764          default:
13765             ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", start.opt, (char *)data);
13766             break;
13767          }
13768 
13769          p->outgoing = 1;
13770          if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
13771             tmp = analog_request(p->sig_pvt, &callwait, requestor);
13772 #ifdef HAVE_PRI
13773          } else if (dahdi_sig_pri_lib_handles(p->sig)) {
13774             /*
13775              * We already have the B channel reserved for this call.  We
13776              * just need to make sure that dahdi_hangup() has completed
13777              * cleaning up before continuing.
13778              */
13779             ast_mutex_lock(&p->lock);
13780             ast_mutex_unlock(&p->lock);
13781 
13782             sig_pri_extract_called_num_subaddr(p->sig_pvt, data, p->dnid,
13783                sizeof(p->dnid));
13784             tmp = sig_pri_request(p->sig_pvt, SIG_PRI_DEFLAW, requestor, transcapdigital);
13785 #endif
13786 #if defined(HAVE_SS7)
13787          } else if (p->sig == SIG_SS7) {
13788             tmp = sig_ss7_request(p->sig_pvt, SIG_SS7_DEFLAW, requestor, transcapdigital);
13789 #endif   /* defined(HAVE_SS7) */
13790          } else {
13791             tmp = dahdi_new(p, AST_STATE_RESERVED, 0, p->owner ? SUB_CALLWAIT : SUB_REAL, 0, requestor ? requestor->linkedid : "");
13792          }
13793          if (!tmp) {
13794             p->outgoing = 0;
13795 #if defined(HAVE_PRI)
13796             switch (p->sig) {
13797             case SIG_PRI_LIB_HANDLE_CASES:
13798 #if defined(HAVE_PRI_CALL_WAITING)
13799                if (((struct sig_pri_chan *) p->sig_pvt)->is_call_waiting) {
13800                   ((struct sig_pri_chan *) p->sig_pvt)->is_call_waiting = 0;
13801                   ast_atomic_fetchadd_int(&p->pri->num_call_waiting_calls, -1);
13802                }
13803 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
13804                /*
13805                 * This should be the last thing to clear when we are done with
13806                 * the channel.
13807                 */
13808                ((struct sig_pri_chan *) p->sig_pvt)->allocated = 0;
13809                break;
13810             default:
13811                break;
13812             }
13813 #endif   /* defined(HAVE_PRI) */
13814          } else {
13815             snprintf(p->dialstring, sizeof(p->dialstring), "DAHDI/%s", (char *) data);
13816          }
13817          break;
13818       }
13819 #ifdef HAVE_OPENR2
13820 next:
13821 #endif
13822       if (start.backwards) {
13823          p = p->prev;
13824          if (!p)
13825             p = ifend;
13826       } else {
13827          p = p->next;
13828          if (!p)
13829             p = iflist;
13830       }
13831       /* stop when you roll to the one that we started from */
13832       if (p == exitpvt)
13833          break;
13834    }
13835    ast_mutex_unlock(&iflock);
13836    restart_monitor();
13837    if (cause && !tmp) {
13838       if (callwait || channelmatched) {
13839          *cause = AST_CAUSE_BUSY;
13840       } else if (groupmatched) {
13841          *cause = AST_CAUSE_CONGESTION;
13842       } else {
13843          /*
13844           * We did not match any channel requested.
13845           * Dialplan error requesting non-existant channel?
13846           */
13847       }
13848    }
13849 
13850    return tmp;
13851 }
13852 
13853 /*!
13854  * \internal
13855  * \brief Determine the device state for a given DAHDI device if we can.
13856  * \since 1.8
13857  *
13858  * \param data DAHDI device name after "DAHDI/".
13859  *
13860  * \retval device_state enum ast_device_state value.
13861  * \retval AST_DEVICE_UNKNOWN if we could not determine the device's state.
13862  */
13863 static int dahdi_devicestate(void *data)
13864 {
13865 #if defined(HAVE_PRI)
13866    char *device;
13867    unsigned span;
13868    int res;
13869 
13870    device = data;
13871 
13872    if (*device != 'I') {
13873       /* The request is not for an ISDN span device. */
13874       return AST_DEVICE_UNKNOWN;
13875    }
13876    res = sscanf(device, "I%30u", &span);
13877    if (res != 1 || !span || NUM_SPANS < span) {
13878       /* Bad format for ISDN span device name. */
13879       return AST_DEVICE_UNKNOWN;
13880    }
13881    device = strchr(device, '/');
13882    if (!device) {
13883       /* Bad format for ISDN span device name. */
13884       return AST_DEVICE_UNKNOWN;
13885    }
13886 
13887    /*
13888     * Since there are currently no other span devstate's defined,
13889     * it must be congestion.
13890     */
13891 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
13892    ++device;
13893    if (!strcmp(device, "congestion"))
13894 #endif   /* defined(THRESHOLD_DEVSTATE_PLACEHOLDER) */
13895    {
13896       return pris[span - 1].pri.congestion_devstate;
13897    }
13898 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
13899    else if (!strcmp(device, "threshold")) {
13900       return pris[span - 1].pri.threshold_devstate;
13901    }
13902    return AST_DEVICE_UNKNOWN;
13903 #endif   /* defined(THRESHOLD_DEVSTATE_PLACEHOLDER) */
13904 #else
13905    return AST_DEVICE_UNKNOWN;
13906 #endif   /* defined(HAVE_PRI) */
13907 }
13908 
13909 /*!
13910  * \brief Callback made when dial failed to get a channel out of dahdi_request().
13911  * \since 1.8
13912  *
13913  * \param inbound Incoming asterisk channel.
13914  * \param dest Same dial string passed to dahdi_request().
13915  * \param callback Callback into CC core to announce a busy channel available for CC.
13916  *
13917  * \details
13918  * This callback acts like a forked dial with all prongs of the fork busy.
13919  * Essentially, for each channel that could have taken the call, indicate that
13920  * it is busy.
13921  *
13922  * \retval 0 on success.
13923  * \retval -1 on error.
13924  */
13925 static int dahdi_cc_callback(struct ast_channel *inbound, const char *dest, ast_cc_callback_fn callback)
13926 {
13927    struct dahdi_pvt *p;
13928    struct dahdi_pvt *exitpvt;
13929    struct dahdi_starting_point start;
13930    int groupmatched = 0;
13931    int channelmatched = 0;
13932 
13933    ast_mutex_lock(&iflock);
13934    p = determine_starting_point(dest, &start);
13935    if (!p) {
13936       ast_mutex_unlock(&iflock);
13937       return -1;
13938    }
13939    exitpvt = p;
13940    for (;;) {
13941       if (is_group_or_channel_match(p, start.span, start.groupmatch, &groupmatched, start.channelmatch, &channelmatched)) {
13942          /* We found a potential match. call the callback */
13943          struct ast_str *device_name;
13944          char *dash;
13945          const char *monitor_type;
13946          char dialstring[AST_CHANNEL_NAME];
13947          char full_device_name[AST_CHANNEL_NAME];
13948 
13949          switch (ast_get_cc_monitor_policy(p->cc_params)) {
13950          case AST_CC_MONITOR_NEVER:
13951             break;
13952          case AST_CC_MONITOR_NATIVE:
13953          case AST_CC_MONITOR_ALWAYS:
13954          case AST_CC_MONITOR_GENERIC:
13955 #if defined(HAVE_PRI)
13956             if (dahdi_sig_pri_lib_handles(p->sig)) {
13957                /*
13958                 * ISDN is in a trunk busy condition so we need to monitor
13959                 * the span congestion device state.
13960                 */
13961                snprintf(full_device_name, sizeof(full_device_name),
13962                   "DAHDI/I%d/congestion", p->pri->span);
13963             } else
13964 #endif   /* defined(HAVE_PRI) */
13965             {
13966 #if defined(HAVE_PRI)
13967                device_name = create_channel_name(p, 1, "");
13968 #else
13969                device_name = create_channel_name(p);
13970 #endif   /* defined(HAVE_PRI) */
13971                snprintf(full_device_name, sizeof(full_device_name), "DAHDI/%s",
13972                   device_name ? ast_str_buffer(device_name) : "");
13973                ast_free(device_name);
13974                /*
13975                 * The portion after the '-' in the channel name is either a random
13976                 * number, a sequence number, or a subchannel number. None are
13977                 * necessary so strip them off.
13978                 */
13979                dash = strrchr(full_device_name, '-');
13980                if (dash) {
13981                   *dash = '\0';
13982                }
13983             }
13984             snprintf(dialstring, sizeof(dialstring), "DAHDI/%s", dest);
13985 
13986             /*
13987              * Analog can only do generic monitoring.
13988              * ISDN is in a trunk busy condition and any "device" is going
13989              * to be busy until a B channel becomes available.  The generic
13990              * monitor can do this task.
13991              */
13992             monitor_type = AST_CC_GENERIC_MONITOR_TYPE;
13993             callback(inbound,
13994 #if defined(HAVE_PRI)
13995                p->pri ? p->pri->cc_params : p->cc_params,
13996 #else
13997                p->cc_params,
13998 #endif   /* defined(HAVE_PRI) */
13999                monitor_type, full_device_name, dialstring, NULL);
14000             break;
14001          }
14002       }
14003       p = start.backwards ? p->prev : p->next;
14004       if (!p) {
14005          p = start.backwards ? ifend : iflist;
14006       }
14007       if (p == exitpvt) {
14008          break;
14009       }
14010    }
14011    ast_mutex_unlock(&iflock);
14012    return 0;
14013 }
14014 
14015 #if defined(HAVE_SS7)
14016 static void dahdi_ss7_message(struct ss7 *ss7, char *s)
14017 {
14018    int i;
14019 
14020    if (ss7) {
14021       for (i = 0; i < NUM_SPANS; i++) {
14022          if (linksets[i].ss7.ss7 == ss7) {
14023             ast_verbose("[%d] %s", i + 1, s);
14024             return;
14025          }
14026       }
14027    }
14028    ast_verbose("%s", s);
14029 }
14030 #endif   /* defined(HAVE_SS7) */
14031 
14032 #if defined(HAVE_SS7)
14033 static void dahdi_ss7_error(struct ss7 *ss7, char *s)
14034 {
14035    int i;
14036 
14037    if (ss7) {
14038       for (i = 0; i < NUM_SPANS; i++) {
14039          if (linksets[i].ss7.ss7 == ss7) {
14040             ast_log(LOG_ERROR, "[%d] %s", i + 1, s);
14041             return;
14042          }
14043       }
14044    }
14045    ast_log(LOG_ERROR, "%s", s);
14046 }
14047 #endif   /* defined(HAVE_SS7) */
14048 
14049 #if defined(HAVE_OPENR2)
14050 static void *mfcr2_monitor(void *data)
14051 {
14052    struct dahdi_mfcr2 *mfcr2 = data;
14053    /* we should be using pthread_key_create
14054       and allocate pollers dynamically.
14055       I think do_monitor() could be leaking, since it
14056       could be cancelled at any time and is not
14057       using thread keys, why?, */
14058    struct pollfd pollers[ARRAY_LEN(mfcr2->pvts)];
14059    int res = 0;
14060    int i = 0;
14061    int oldstate = 0;
14062    int quit_loop = 0;
14063    int maxsleep = 20;
14064    int was_idle = 0;
14065    int pollsize = 0;
14066    /* now that we're ready to get calls, unblock our side and
14067       get current line state */
14068    for (i = 0; i < mfcr2->numchans; i++) {
14069       openr2_chan_set_idle(mfcr2->pvts[i]->r2chan);
14070       openr2_chan_handle_cas(mfcr2->pvts[i]->r2chan);
14071    }
14072    while (1) {
14073       /* we trust here that the mfcr2 channel list will not ever change once
14074          the module is loaded */
14075       pollsize = 0;
14076       for (i = 0; i < mfcr2->numchans; i++) {
14077          pollers[i].revents = 0;
14078          pollers[i].events = 0;
14079          if (mfcr2->pvts[i]->owner) {
14080             continue;
14081          }
14082          if (!mfcr2->pvts[i]->r2chan) {
14083             ast_log(LOG_DEBUG, "Wow, no r2chan on channel %d\n", mfcr2->pvts[i]->channel);
14084             quit_loop = 1;
14085             break;
14086          }
14087          openr2_chan_enable_read(mfcr2->pvts[i]->r2chan);
14088          pollers[i].events = POLLIN | POLLPRI;
14089          pollers[i].fd = mfcr2->pvts[i]->subs[SUB_REAL].dfd;
14090          pollsize++;
14091       }
14092       if (quit_loop) {
14093          break;
14094       }
14095       if (pollsize == 0) {
14096          if (!was_idle) {
14097             ast_log(LOG_DEBUG, "Monitor thread going idle since everybody has an owner\n");
14098             was_idle = 1;
14099          }
14100          poll(NULL, 0, maxsleep);
14101          continue;
14102       }
14103       was_idle = 0;
14104       /* probably poll() is a valid cancel point, lets just be on the safe side
14105          by calling pthread_testcancel */
14106       pthread_testcancel();
14107       res = poll(pollers, mfcr2->numchans, maxsleep);
14108       pthread_testcancel();
14109       if ((res < 0) && (errno != EINTR)) {
14110          ast_log(LOG_ERROR, "going out, poll failed: %s\n", strerror(errno));
14111          break;
14112       }
14113       /* do we want to allow to cancel while processing events? */
14114       pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate);
14115       for (i = 0; i < mfcr2->numchans; i++) {
14116          if (pollers[i].revents & POLLPRI || pollers[i].revents & POLLIN) {
14117             openr2_chan_process_event(mfcr2->pvts[i]->r2chan);
14118          }
14119       }
14120       pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
14121    }
14122    ast_log(LOG_NOTICE, "Quitting MFC/R2 monitor thread\n");
14123    return 0;
14124 }
14125 #endif /* HAVE_OPENR2 */
14126 
14127 #if defined(HAVE_PRI)
14128 static void dahdi_pri_message(struct pri *pri, char *s)
14129 {
14130    int x;
14131    int y;
14132    int dchan = -1;
14133    int span = -1;
14134    int dchancount = 0;
14135 
14136    if (pri) {
14137       for (x = 0; x < NUM_SPANS; x++) {
14138          for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
14139             if (pris[x].pri.dchans[y]) {
14140                dchancount++;
14141             }
14142 
14143             if (pris[x].pri.dchans[y] == pri) {
14144                dchan = y;
14145             }
14146          }
14147          if (dchan >= 0) {
14148             span = x;
14149             break;
14150          }
14151          dchancount = 0;
14152       }
14153       if (-1 < span) {
14154          if (1 < dchancount) {
14155             ast_verbose("[PRI Span: %d D-Channel: %d] %s", span + 1, dchan, s);
14156          } else {
14157             ast_verbose("PRI Span: %d %s", span + 1, s);
14158          }
14159       } else {
14160          ast_verbose("PRI Span: ? %s", s);
14161       }
14162    } else {
14163       ast_verbose("PRI Span: ? %s", s);
14164    }
14165 
14166    ast_mutex_lock(&pridebugfdlock);
14167 
14168    if (pridebugfd >= 0) {
14169       if (write(pridebugfd, s, strlen(s)) < 0) {
14170          ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
14171       }
14172    }
14173 
14174    ast_mutex_unlock(&pridebugfdlock);
14175 }
14176 #endif   /* defined(HAVE_PRI) */
14177 
14178 #if defined(HAVE_PRI)
14179 static void dahdi_pri_error(struct pri *pri, char *s)
14180 {
14181    int x;
14182    int y;
14183    int dchan = -1;
14184    int span = -1;
14185    int dchancount = 0;
14186 
14187    if (pri) {
14188       for (x = 0; x < NUM_SPANS; x++) {
14189          for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
14190             if (pris[x].pri.dchans[y]) {
14191                dchancount++;
14192             }
14193 
14194             if (pris[x].pri.dchans[y] == pri) {
14195                dchan = y;
14196             }
14197          }
14198          if (dchan >= 0) {
14199             span = x;
14200             break;
14201          }
14202          dchancount = 0;
14203       }
14204       if (-1 < span) {
14205          if (1 < dchancount) {
14206             ast_log(LOG_ERROR, "[PRI Span: %d D-Channel: %d] %s", span + 1, dchan, s);
14207          } else {
14208             ast_log(LOG_ERROR, "PRI Span: %d %s", span + 1, s);
14209          }
14210       } else {
14211          ast_log(LOG_ERROR, "PRI Span: ? %s", s);
14212       }
14213    } else {
14214       ast_log(LOG_ERROR, "PRI Span: ? %s", s);
14215    }
14216 
14217    ast_mutex_lock(&pridebugfdlock);
14218 
14219    if (pridebugfd >= 0) {
14220       if (write(pridebugfd, s, strlen(s)) < 0) {
14221          ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
14222       }
14223    }
14224 
14225    ast_mutex_unlock(&pridebugfdlock);
14226 }
14227 #endif   /* defined(HAVE_PRI) */
14228 
14229 #if defined(HAVE_PRI)
14230 static int prepare_pri(struct dahdi_pri *pri)
14231 {
14232    int i, res, x;
14233    struct dahdi_params p;
14234    struct dahdi_bufferinfo bi;
14235    struct dahdi_spaninfo si;
14236 
14237    pri->pri.calls = &dahdi_pri_callbacks;
14238 
14239    for (i = 0; i < SIG_PRI_NUM_DCHANS; i++) {
14240       if (!pri->dchannels[i])
14241          break;
14242       pri->pri.fds[i] = open("/dev/dahdi/channel", O_RDWR);
14243       x = pri->dchannels[i];
14244       if ((pri->pri.fds[i] < 0) || (ioctl(pri->pri.fds[i],DAHDI_SPECIFY,&x) == -1)) {
14245          ast_log(LOG_ERROR, "Unable to open D-channel %d (%s)\n", x, strerror(errno));
14246          return -1;
14247       }
14248       memset(&p, 0, sizeof(p));
14249       res = ioctl(pri->pri.fds[i], DAHDI_GET_PARAMS, &p);
14250       if (res) {
14251          dahdi_close_pri_fd(pri, i);
14252          ast_log(LOG_ERROR, "Unable to get parameters for D-channel %d (%s)\n", x, strerror(errno));
14253          return -1;
14254       }
14255       if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC)) {
14256          dahdi_close_pri_fd(pri, i);
14257          ast_log(LOG_ERROR, "D-channel %d is not in HDLC/FCS mode.\n", x);
14258          return -1;
14259       }
14260       memset(&si, 0, sizeof(si));
14261       res = ioctl(pri->pri.fds[i], DAHDI_SPANSTAT, &si);
14262       if (res) {
14263          dahdi_close_pri_fd(pri, i);
14264          ast_log(LOG_ERROR, "Unable to get span state for D-channel %d (%s)\n", x, strerror(errno));
14265       }
14266       if (!si.alarms) {
14267          pri_event_noalarm(&pri->pri, i, 1);
14268       } else {
14269          pri_event_alarm(&pri->pri, i, 1);
14270       }
14271       memset(&bi, 0, sizeof(bi));
14272       bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
14273       bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
14274       bi.numbufs = 32;
14275       bi.bufsize = 1024;
14276       if (ioctl(pri->pri.fds[i], DAHDI_SET_BUFINFO, &bi)) {
14277          ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", x, strerror(errno));
14278          dahdi_close_pri_fd(pri, i);
14279          return -1;
14280       }
14281       pri->pri.dchan_logical_span[i] = pris[p.spanno - 1].prilogicalspan;
14282    }
14283    return 0;
14284 }
14285 #endif   /* defined(HAVE_PRI) */
14286 
14287 #if defined(HAVE_PRI)
14288 static char *complete_span_helper(const char *line, const char *word, int pos, int state, int rpos)
14289 {
14290    int which, span;
14291    char *ret = NULL;
14292 
14293    if (pos != rpos)
14294       return ret;
14295 
14296    for (which = span = 0; span < NUM_SPANS; span++) {
14297       if (pris[span].pri.pri && ++which > state) {
14298          if (ast_asprintf(&ret, "%d", span + 1) < 0) {   /* user indexes start from 1 */
14299             ret = NULL;
14300          }
14301          break;
14302       }
14303    }
14304    return ret;
14305 }
14306 #endif   /* defined(HAVE_PRI) */
14307 
14308 #if defined(HAVE_PRI)
14309 static char *complete_span_4(const char *line, const char *word, int pos, int state)
14310 {
14311    return complete_span_helper(line,word,pos,state,3);
14312 }
14313 #endif   /* defined(HAVE_PRI) */
14314 
14315 #if defined(HAVE_PRI)
14316 static char *handle_pri_set_debug_file(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14317 {
14318    int myfd;
14319    switch (cmd) {
14320    case CLI_INIT:
14321       e->command = "pri set debug file";
14322       e->usage = "Usage: pri set debug file [output-file]\n"
14323          "       Sends PRI debug output to the specified output file\n";
14324       return NULL;
14325    case CLI_GENERATE:
14326       return NULL;
14327    }
14328    if (a->argc < 5)
14329       return CLI_SHOWUSAGE;
14330 
14331    if (ast_strlen_zero(a->argv[4]))
14332       return CLI_SHOWUSAGE;
14333 
14334    myfd = open(a->argv[4], O_CREAT|O_WRONLY, AST_FILE_MODE);
14335    if (myfd < 0) {
14336       ast_cli(a->fd, "Unable to open '%s' for writing\n", a->argv[4]);
14337       return CLI_SUCCESS;
14338    }
14339 
14340    ast_mutex_lock(&pridebugfdlock);
14341 
14342    if (pridebugfd >= 0)
14343       close(pridebugfd);
14344 
14345    pridebugfd = myfd;
14346    ast_copy_string(pridebugfilename,a->argv[4],sizeof(pridebugfilename));
14347    ast_mutex_unlock(&pridebugfdlock);
14348    ast_cli(a->fd, "PRI debug output will be sent to '%s'\n", a->argv[4]);
14349    return CLI_SUCCESS;
14350 }
14351 #endif   /* defined(HAVE_PRI) */
14352 
14353 #if defined(HAVE_PRI)
14354 static char *handle_pri_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14355 {
14356    int span;
14357    int x;
14358    int level = 0;
14359    switch (cmd) {
14360    case CLI_INIT:
14361       e->command = "pri set debug {on|off|0|1|2} span";
14362       e->usage =
14363          "Usage: pri set debug {<level>|on|off} span <span>\n"
14364          "       Enables debugging on a given PRI span\n";
14365       return NULL;
14366    case CLI_GENERATE:
14367       return complete_span_4(a->line, a->word, a->pos, a->n);
14368    }
14369    if (a->argc < 6) {
14370       return CLI_SHOWUSAGE;
14371    }
14372 
14373    if (!strcasecmp(a->argv[3], "on")) {
14374       level = 1;
14375    } else if (!strcasecmp(a->argv[3], "off")) {
14376       level = 0;
14377    } else {
14378       level = atoi(a->argv[3]);
14379    }
14380    span = atoi(a->argv[5]);
14381    if ((span < 1) || (span > NUM_SPANS)) {
14382       ast_cli(a->fd, "Invalid span %s.  Should be a number %d to %d\n", a->argv[5], 1, NUM_SPANS);
14383       return CLI_SUCCESS;
14384    }
14385    if (!pris[span-1].pri.pri) {
14386       ast_cli(a->fd, "No PRI running on span %d\n", span);
14387       return CLI_SUCCESS;
14388    }
14389 
14390    /* Set debug level in libpri */
14391    for (x = 0; x < SIG_PRI_NUM_DCHANS; x++) {
14392       if (pris[span - 1].pri.dchans[x]) {
14393          switch (level) {
14394          case 0:
14395             pri_set_debug(pris[span - 1].pri.dchans[x], 0);
14396             break;
14397          case 1:
14398             pri_set_debug(pris[span - 1].pri.dchans[x], SIG_PRI_DEBUG_NORMAL);
14399             break;
14400          default:
14401             pri_set_debug(pris[span - 1].pri.dchans[x], SIG_PRI_DEBUG_INTENSE);
14402             break;
14403          }
14404       }
14405    }
14406    if (level == 0) {
14407       /* Close the debugging file if it's set */
14408       ast_mutex_lock(&pridebugfdlock);
14409       if (0 <= pridebugfd) {
14410          close(pridebugfd);
14411          pridebugfd = -1;
14412          ast_cli(a->fd, "Disabled PRI debug output to file '%s'\n",
14413             pridebugfilename);
14414       }
14415       ast_mutex_unlock(&pridebugfdlock);
14416    }
14417    pris[span - 1].pri.debug = (level) ? 1 : 0;
14418    ast_cli(a->fd, "%s debugging on span %d\n", (level) ? "Enabled" : "Disabled", span);
14419    return CLI_SUCCESS;
14420 }
14421 #endif   /* defined(HAVE_PRI) */
14422 
14423 #if defined(HAVE_PRI)
14424 #if defined(HAVE_PRI_SERVICE_MESSAGES)
14425 static char *handle_pri_service_generic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a, int changestatus)
14426 {
14427    unsigned *why;
14428    int channel;
14429    int trunkgroup;
14430    int x, y, fd = a->fd;
14431    int interfaceid = 0;
14432    char db_chan_name[20], db_answer[5];
14433    struct dahdi_pvt *tmp;
14434    struct dahdi_pri *pri;
14435 
14436    if (a->argc < 5 || a->argc > 6)
14437       return CLI_SHOWUSAGE;
14438    if (strchr(a->argv[4], ':')) {
14439       if (sscanf(a->argv[4], "%30d:%30d", &trunkgroup, &channel) != 2)
14440          return CLI_SHOWUSAGE;
14441       if ((trunkgroup < 1) || (channel < 1))
14442          return CLI_SHOWUSAGE;
14443       pri = NULL;
14444       for (x=0;x<NUM_SPANS;x++) {
14445          if (pris[x].pri.trunkgroup == trunkgroup) {
14446             pri = pris + x;
14447             break;
14448          }
14449       }
14450       if (!pri) {
14451          ast_cli(fd, "No such trunk group %d\n", trunkgroup);
14452          return CLI_FAILURE;
14453       }
14454    } else
14455       channel = atoi(a->argv[4]);
14456 
14457    if (a->argc == 6)
14458       interfaceid = atoi(a->argv[5]);
14459 
14460    /* either servicing a D-Channel */
14461    for (x = 0; x < NUM_SPANS; x++) {
14462       for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
14463          if (pris[x].dchannels[y] == channel) {
14464             pri = pris + x;
14465             if (pri->pri.enable_service_message_support) {
14466                ast_mutex_lock(&pri->pri.lock);
14467                pri_maintenance_service(pri->pri.pri, interfaceid, -1, changestatus);
14468                ast_mutex_unlock(&pri->pri.lock);
14469             } else {
14470                ast_cli(fd,
14471                   "\n\tThis operation has not been enabled in chan_dahdi.conf, set 'service_message_support=yes' to use this operation.\n"
14472                   "\tNote only 4ESS, 5ESS, and NI2 switch types are supported.\n\n");
14473             }
14474             return CLI_SUCCESS;
14475          }
14476       }
14477    }
14478 
14479    /* or servicing a B-Channel */
14480    ast_mutex_lock(&iflock);
14481    for (tmp = iflist; tmp; tmp = tmp->next) {
14482       if (tmp->pri && tmp->channel == channel) {
14483          ast_mutex_unlock(&iflock);
14484          ast_mutex_lock(&tmp->pri->lock);
14485          if (!tmp->pri->enable_service_message_support) {
14486             ast_mutex_unlock(&tmp->pri->lock);
14487             ast_cli(fd,
14488                "\n\tThis operation has not been enabled in chan_dahdi.conf, set 'service_message_support=yes' to use this operation.\n"
14489                "\tNote only 4ESS, 5ESS, and NI2 switch types are supported.\n\n");
14490             return CLI_SUCCESS;
14491          }
14492          snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, tmp->span, channel);
14493          why = &((struct sig_pri_chan *) tmp->sig_pvt)->service_status;
14494          switch(changestatus) {
14495          case 0: /* enable */
14496             /* Near end wants to be in service now. */
14497             ast_db_del(db_chan_name, SRVST_DBKEY);
14498             *why &= ~SRVST_NEAREND;
14499             if (*why) {
14500                snprintf(db_answer, sizeof(db_answer), "%s:%u", SRVST_TYPE_OOS, *why);
14501                ast_db_put(db_chan_name, SRVST_DBKEY, db_answer);
14502             } else {
14503                dahdi_pri_update_span_devstate(tmp->pri);
14504             }
14505             break;
14506          /* case 1:  -- loop */
14507          case 2: /* disable */
14508             /* Near end wants to be out-of-service now. */
14509             ast_db_del(db_chan_name, SRVST_DBKEY);
14510             *why |= SRVST_NEAREND;
14511             snprintf(db_answer, sizeof(db_answer), "%s:%u", SRVST_TYPE_OOS, *why);
14512             ast_db_put(db_chan_name, SRVST_DBKEY, db_answer);
14513             dahdi_pri_update_span_devstate(tmp->pri);
14514             break;
14515          /* case 3:  -- continuity */
14516          /* case 4:  -- shutdown */
14517          default:
14518             ast_log(LOG_WARNING, "Unsupported changestatus: '%d'\n", changestatus);
14519             break;
14520          }
14521          pri_maintenance_bservice(tmp->pri->pri, tmp->sig_pvt, changestatus);
14522          ast_mutex_unlock(&tmp->pri->lock);
14523          return CLI_SUCCESS;
14524       }
14525    }
14526    ast_mutex_unlock(&iflock);
14527 
14528    ast_cli(fd, "Unable to find given channel %d, possibly not a PRI\n", channel);
14529    return CLI_FAILURE;
14530 }
14531 
14532 static char *handle_pri_service_enable_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14533 {
14534    switch (cmd) {
14535    case CLI_INIT:
14536       e->command = "pri service enable channel";
14537       e->usage =
14538          "Usage: pri service enable channel <channel> [<interface id>]\n"
14539          "       Send an AT&T / NFAS / CCS ANSI T1.607 maintenance message\n"
14540          "  to restore a channel to service, with optional interface id\n"
14541          "  as agreed upon with remote switch operator\n";
14542       return NULL;
14543    case CLI_GENERATE:
14544       return NULL;
14545    }
14546    return handle_pri_service_generic(e, cmd, a, 0);
14547 }
14548 
14549 static char *handle_pri_service_disable_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14550 {
14551    switch (cmd) {
14552    case CLI_INIT:
14553       e->command = "pri service disable channel";
14554       e->usage =
14555          "Usage: pri service disable channel <chan num> [<interface id>]\n"
14556          "  Send an AT&T / NFAS / CCS ANSI T1.607 maintenance message\n"
14557          "  to remove a channel from service, with optional interface id\n"
14558          "  as agreed upon with remote switch operator\n";
14559       return NULL;
14560    case CLI_GENERATE:
14561       return NULL;
14562    }
14563    return handle_pri_service_generic(e, cmd, a, 2);
14564 }
14565 #endif   /* defined(HAVE_PRI_SERVICE_MESSAGES) */
14566 #endif   /* defined(HAVE_PRI) */
14567 
14568 #if defined(HAVE_PRI)
14569 static char *handle_pri_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14570 {
14571    int span;
14572 
14573    switch (cmd) {
14574    case CLI_INIT:
14575       e->command = "pri show channels";
14576       e->usage =
14577          "Usage: pri show channels\n"
14578          "       Displays PRI channel information such as the current mapping\n"
14579          "       of DAHDI B channels to Asterisk channel names and which calls\n"
14580          "       are on hold or call-waiting.  Calls on hold or call-waiting\n"
14581          "       are not associated with any B channel.\n";
14582       return NULL;
14583    case CLI_GENERATE:
14584       return NULL;
14585    }
14586 
14587    if (a->argc != 3)
14588       return CLI_SHOWUSAGE;
14589 
14590    sig_pri_cli_show_channels_header(a->fd);
14591    for (span = 0; span < NUM_SPANS; ++span) {
14592       if (pris[span].pri.pri) {
14593          sig_pri_cli_show_channels(a->fd, &pris[span].pri);
14594       }
14595    }
14596    return CLI_SUCCESS;
14597 }
14598 #endif   /* defined(HAVE_PRI) */
14599 
14600 #if defined(HAVE_PRI)
14601 static char *handle_pri_show_spans(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14602 {
14603    int span;
14604 
14605    switch (cmd) {
14606    case CLI_INIT:
14607       e->command = "pri show spans";
14608       e->usage =
14609          "Usage: pri show spans\n"
14610          "       Displays PRI span information\n";
14611       return NULL;
14612    case CLI_GENERATE:
14613       return NULL;
14614    }
14615 
14616    if (a->argc != 3)
14617       return CLI_SHOWUSAGE;
14618 
14619    for (span = 0; span < NUM_SPANS; span++) {
14620       if (pris[span].pri.pri) {
14621          sig_pri_cli_show_spans(a->fd, span + 1, &pris[span].pri);
14622       }
14623    }
14624    return CLI_SUCCESS;
14625 }
14626 #endif   /* defined(HAVE_PRI) */
14627 
14628 #if defined(HAVE_PRI)
14629 #define container_of(ptr, type, member) \
14630    ((type *)((char *)(ptr) - offsetof(type, member)))
14631 /*!
14632  * \internal
14633  * \brief Destroy a D-Channel of a PRI span
14634  * \since 12
14635  *
14636  * \param pri the pri span
14637  *
14638  * \return TRUE if the span was valid and we attempted destroying.
14639  *
14640  * Shuts down a span and destroys its D-Channel. Further destruction
14641  * of the B-channels using dahdi_destroy_channel() would probably be required
14642  * for the B-Channels.
14643  */
14644 static int pri_destroy_dchan(struct sig_pri_span *pri)
14645 {
14646    int i;
14647    struct dahdi_pri* dahdi_pri;
14648 
14649    if (!pri->master || (pri->master == AST_PTHREADT_NULL)) {
14650       return 0;
14651    }
14652    pthread_cancel(pri->master);
14653    pthread_join(pri->master, NULL);
14654 
14655    /* The 'struct dahdi_pri' that contains our 'struct sig_pri_span' */
14656    dahdi_pri = container_of(pri, struct dahdi_pri, pri);
14657    for (i = 0; i < SIG_PRI_NUM_DCHANS; i++) {
14658       ast_debug(4, "closing pri_fd %d\n", i);
14659       dahdi_close_pri_fd(dahdi_pri, i);
14660    }
14661    pri->pri = NULL;
14662    ast_debug(1, "PRI span %d destroyed\n", pri->span);
14663    return 1;
14664 }
14665 
14666 static char *handle_pri_destroy_span(struct ast_cli_entry *e, int cmd,
14667       struct ast_cli_args *a)
14668 {
14669    int span;
14670    int i;
14671    int res;
14672 
14673    switch (cmd) {
14674    case CLI_INIT:
14675       e->command = "pri destroy span";
14676       e->usage =
14677          "Usage: pri destroy span <span>\n"
14678          "       Destorys D-channel of span and its B-channels.\n"
14679          "  DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n";
14680       return NULL;
14681    case CLI_GENERATE:
14682       return complete_span_4(a->line, a->word, a->pos, a->n);
14683    }
14684 
14685    if (a->argc < 4) {
14686       return CLI_SHOWUSAGE;
14687    }
14688    res = sscanf(a->argv[3], "%30d", &span);
14689    if ((res != 1) || span < 1 || span > NUM_SPANS) {
14690       ast_cli(a->fd,
14691          "Invalid span '%s'.  Should be a number from %d to %d\n",
14692          a->argv[3], 1, NUM_SPANS);
14693       return CLI_SUCCESS;
14694    }
14695    if (!pris[span - 1].pri.pri) {
14696       ast_cli(a->fd, "No PRI running on span %d\n", span);
14697       return CLI_SUCCESS;
14698    }
14699 
14700    for (i = 0; i < pris[span - 1].pri.numchans; i++) {
14701       int channel;
14702       struct sig_pri_chan *pvt = pris[span - 1].pri.pvts[i];
14703 
14704       if (!pvt) {
14705          continue;
14706       }
14707       channel = pvt->channel;
14708       ast_debug(2, "About to destroy B-channel %d.\n", channel);
14709       dahdi_destroy_channel_bynum(channel);
14710    }
14711    ast_debug(2, "About to destroy D-channel of span %d.\n", span);
14712    pri_destroy_dchan(&pris[span - 1].pri);
14713 
14714    return CLI_SUCCESS;
14715 }
14716 
14717 #endif   /* defined(HAVE_PRI) */
14718 
14719 #if defined(HAVE_PRI)
14720 static char *handle_pri_show_span(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14721 {
14722    int span;
14723 
14724    switch (cmd) {
14725    case CLI_INIT:
14726       e->command = "pri show span";
14727       e->usage =
14728          "Usage: pri show span <span>\n"
14729          "       Displays PRI Information on a given PRI span\n";
14730       return NULL;
14731    case CLI_GENERATE:
14732       return complete_span_4(a->line, a->word, a->pos, a->n);
14733    }
14734 
14735    if (a->argc < 4)
14736       return CLI_SHOWUSAGE;
14737    span = atoi(a->argv[3]);
14738    if ((span < 1) || (span > NUM_SPANS)) {
14739       ast_cli(a->fd, "Invalid span '%s'.  Should be a number from %d to %d\n", a->argv[3], 1, NUM_SPANS);
14740       return CLI_SUCCESS;
14741    }
14742    if (!pris[span-1].pri.pri) {
14743       ast_cli(a->fd, "No PRI running on span %d\n", span);
14744       return CLI_SUCCESS;
14745    }
14746 
14747    sig_pri_cli_show_span(a->fd, pris[span-1].dchannels, &pris[span-1].pri);
14748 
14749    return CLI_SUCCESS;
14750 }
14751 #endif   /* defined(HAVE_PRI) */
14752 
14753 #if defined(HAVE_PRI)
14754 static char *handle_pri_show_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14755 {
14756    int x;
14757    int span;
14758    int count=0;
14759    int debug;
14760 
14761    switch (cmd) {
14762    case CLI_INIT:
14763       e->command = "pri show debug";
14764       e->usage =
14765          "Usage: pri show debug\n"
14766          "  Show the debug state of pri spans\n";
14767       return NULL;
14768    case CLI_GENERATE:
14769       return NULL;
14770    }
14771 
14772    for (span = 0; span < NUM_SPANS; span++) {
14773       if (pris[span].pri.pri) {
14774          for (x = 0; x < SIG_PRI_NUM_DCHANS; x++) {
14775             if (pris[span].pri.dchans[x]) {
14776                debug = pri_get_debug(pris[span].pri.dchans[x]);
14777                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" );
14778                count++;
14779             }
14780          }
14781       }
14782 
14783    }
14784    ast_mutex_lock(&pridebugfdlock);
14785    if (pridebugfd >= 0)
14786       ast_cli(a->fd, "Logging PRI debug to file %s\n", pridebugfilename);
14787    ast_mutex_unlock(&pridebugfdlock);
14788 
14789    if (!count)
14790       ast_cli(a->fd, "No PRI running\n");
14791    return CLI_SUCCESS;
14792 }
14793 #endif   /* defined(HAVE_PRI) */
14794 
14795 #if defined(HAVE_PRI)
14796 static char *handle_pri_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14797 {
14798    switch (cmd) {
14799    case CLI_INIT:
14800       e->command = "pri show version";
14801       e->usage =
14802          "Usage: pri show version\n"
14803          "Show libpri version information\n";
14804       return NULL;
14805    case CLI_GENERATE:
14806       return NULL;
14807    }
14808 
14809    ast_cli(a->fd, "libpri version: %s\n", pri_get_version());
14810 
14811    return CLI_SUCCESS;
14812 }
14813 #endif   /* defined(HAVE_PRI) */
14814 
14815 #if defined(HAVE_PRI)
14816 static struct ast_cli_entry dahdi_pri_cli[] = {
14817    AST_CLI_DEFINE(handle_pri_debug, "Enables PRI debugging on a span"),
14818 #if defined(HAVE_PRI_SERVICE_MESSAGES)
14819    AST_CLI_DEFINE(handle_pri_service_enable_channel, "Return a channel to service"),
14820    AST_CLI_DEFINE(handle_pri_service_disable_channel, "Remove a channel from service"),
14821 #endif   /* defined(HAVE_PRI_SERVICE_MESSAGES) */
14822    AST_CLI_DEFINE(handle_pri_show_channels, "Displays PRI channel information"),
14823    AST_CLI_DEFINE(handle_pri_show_spans, "Displays PRI span information"),
14824    AST_CLI_DEFINE(handle_pri_show_span, "Displays PRI span information"),
14825    AST_CLI_DEFINE(handle_pri_destroy_span, "Destroy a PRI span"),
14826    AST_CLI_DEFINE(handle_pri_show_debug, "Displays current PRI debug settings"),
14827    AST_CLI_DEFINE(handle_pri_set_debug_file, "Sends PRI debug output to the specified file"),
14828    AST_CLI_DEFINE(handle_pri_version, "Displays libpri version"),
14829 };
14830 #endif   /* defined(HAVE_PRI) */
14831 
14832 #ifdef HAVE_OPENR2
14833 
14834 static char *handle_mfcr2_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14835 {
14836    switch (cmd) {
14837    case CLI_INIT:
14838       e->command = "mfcr2 show version";
14839       e->usage =
14840          "Usage: mfcr2 show version\n"
14841          "       Shows the version of the OpenR2 library being used.\n";
14842       return NULL;
14843    case CLI_GENERATE:
14844       return NULL;
14845    }
14846    ast_cli(a->fd, "OpenR2 version: %s, revision: %s\n", openr2_get_version(), openr2_get_revision());
14847    return CLI_SUCCESS;
14848 }
14849 
14850 static char *handle_mfcr2_show_variants(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14851 {
14852 #define FORMAT "%4s %40s\n"
14853    int i = 0;
14854    int numvariants = 0;
14855    const openr2_variant_entry_t *variants;
14856    switch (cmd) {
14857    case CLI_INIT:
14858       e->command = "mfcr2 show variants";
14859       e->usage =
14860          "Usage: mfcr2 show variants\n"
14861          "       Shows the list of MFC/R2 variants supported.\n";
14862       return NULL;
14863    case CLI_GENERATE:
14864       return NULL;
14865    }
14866    if (!(variants = openr2_proto_get_variant_list(&numvariants))) {
14867       ast_cli(a->fd, "Failed to get list of variants.\n");
14868       return CLI_FAILURE;
14869    }
14870    ast_cli(a->fd, FORMAT, "Variant Code", "Country");
14871    for (i = 0; i < numvariants; i++) {
14872       ast_cli(a->fd, FORMAT, variants[i].name, variants[i].country);
14873    }
14874    return CLI_SUCCESS;
14875 #undef FORMAT
14876 }
14877 
14878 static char *handle_mfcr2_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14879 {
14880 #define FORMAT "%4s %-7.7s %-7.7s %-8.8s %-9.9s %-16.16s %-8.8s %-8.8s\n"
14881    int filtertype = 0;
14882    int targetnum = 0;
14883    char channo[5];
14884    char anino[5];
14885    char dnisno[5];
14886    struct dahdi_pvt *p;
14887    openr2_context_t *r2context;
14888    openr2_variant_t r2variant;
14889    switch (cmd) {
14890    case CLI_INIT:
14891       e->command = "mfcr2 show channels [group|context]";
14892       e->usage =
14893          "Usage: mfcr2 show channels [group <group> | context <context>]\n"
14894          "       Shows the DAHDI channels configured with MFC/R2 signaling.\n";
14895       return NULL;
14896    case CLI_GENERATE:
14897       return NULL;
14898    }
14899    if (!((a->argc == 3) || (a->argc == 5))) {
14900       return CLI_SHOWUSAGE;
14901    }
14902    if (a->argc == 5) {
14903       if (!strcasecmp(a->argv[3], "group")) {
14904          targetnum = atoi(a->argv[4]);
14905          if ((targetnum < 0) || (targetnum > 63))
14906             return CLI_SHOWUSAGE;
14907          targetnum = 1 << targetnum;
14908          filtertype = 1;
14909       } else if (!strcasecmp(a->argv[3], "context")) {
14910          filtertype = 2;
14911       } else {
14912          return CLI_SHOWUSAGE;
14913       }
14914    }
14915    ast_cli(a->fd, FORMAT, "Chan", "Variant", "Max ANI", "Max DNIS", "ANI First", "Immediate Accept", "Tx CAS", "Rx CAS");
14916    ast_mutex_lock(&iflock);
14917    for (p = iflist; p; p = p->next) {
14918       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14919          continue;
14920       }
14921       if (filtertype) {
14922          switch(filtertype) {
14923          case 1: /* mfcr2 show channels group <group> */
14924             if (p->group != targetnum) {
14925                continue;
14926             }
14927             break;
14928          case 2: /* mfcr2 show channels context <context> */
14929             if (strcasecmp(p->context, a->argv[4])) {
14930                continue;
14931             }
14932             break;
14933          default:
14934             ;
14935          }
14936       }
14937       r2context = openr2_chan_get_context(p->r2chan);
14938       r2variant = openr2_context_get_variant(r2context);
14939       snprintf(channo, sizeof(channo), "%d", p->channel);
14940       snprintf(anino, sizeof(anino), "%d", openr2_context_get_max_ani(r2context));
14941       snprintf(dnisno, sizeof(dnisno), "%d", openr2_context_get_max_dnis(r2context));
14942       ast_cli(a->fd, FORMAT, channo, openr2_proto_get_variant_string(r2variant),
14943             anino, dnisno, openr2_context_get_ani_first(r2context) ? "Yes" : "No",
14944             openr2_context_get_immediate_accept(r2context) ? "Yes" : "No",
14945             openr2_chan_get_tx_cas_string(p->r2chan), openr2_chan_get_rx_cas_string(p->r2chan));
14946    }
14947    ast_mutex_unlock(&iflock);
14948    return CLI_SUCCESS;
14949 #undef FORMAT
14950 }
14951 
14952 static char *handle_mfcr2_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14953 {
14954    struct dahdi_pvt *p = NULL;
14955    int channo = 0;
14956    char *toklevel = NULL;
14957    char *saveptr = NULL;
14958    char *logval = NULL;
14959    openr2_log_level_t loglevel = OR2_LOG_NOTHING;
14960    openr2_log_level_t tmplevel = OR2_LOG_NOTHING;
14961    switch (cmd) {
14962    case CLI_INIT:
14963       e->command = "mfcr2 set debug";
14964       e->usage =
14965          "Usage: mfcr2 set debug <loglevel> <channel>\n"
14966          "       Set a new logging level for the specified channel.\n"
14967          "       If no channel is specified the logging level will be applied to all channels.\n";
14968       return NULL;
14969    case CLI_GENERATE:
14970       return NULL;
14971    }
14972    if (a->argc < 4) {
14973       return CLI_SHOWUSAGE;
14974    }
14975    channo = (a->argc == 5) ? atoi(a->argv[4]) : -1;
14976    logval = ast_strdupa(a->argv[3]);
14977    toklevel = strtok_r(logval, ",", &saveptr);
14978    if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
14979       ast_cli(a->fd, "Invalid MFC/R2 logging level '%s'.\n", a->argv[3]);
14980       return CLI_FAILURE;
14981    } else if (OR2_LOG_NOTHING == tmplevel) {
14982       loglevel = tmplevel;
14983    } else {
14984       loglevel |= tmplevel;
14985       while ((toklevel = strtok_r(NULL, ",", &saveptr))) {
14986          if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
14987             ast_cli(a->fd, "Ignoring invalid logging level: '%s'.\n", toklevel);
14988             continue;
14989          }
14990          loglevel |= tmplevel;
14991       }
14992    }
14993    ast_mutex_lock(&iflock);
14994    for (p = iflist; p; p = p->next) {
14995       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14996          continue;
14997       }
14998       if ((channo != -1) && (p->channel != channo )) {
14999          continue;
15000       }
15001       openr2_chan_set_log_level(p->r2chan, loglevel);
15002       if (channo != -1) {
15003          ast_cli(a->fd, "MFC/R2 debugging set to '%s' for channel %d.\n", a->argv[3], p->channel);
15004          break;
15005       }
15006    }
15007    if ((channo != -1) && !p) {
15008       ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
15009    }
15010    if (channo == -1) {
15011       ast_cli(a->fd, "MFC/R2 debugging set to '%s' for all channels.\n", a->argv[3]);
15012    }
15013    ast_mutex_unlock(&iflock);
15014    return CLI_SUCCESS;
15015 }
15016 
15017 static char *handle_mfcr2_call_files(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15018 {
15019    struct dahdi_pvt *p = NULL;
15020    int channo = 0;
15021    switch (cmd) {
15022    case CLI_INIT:
15023       e->command = "mfcr2 call files [on|off]";
15024       e->usage =
15025          "Usage: mfcr2 call files [on|off] <channel>\n"
15026          "       Enable call files creation on the specified channel.\n"
15027          "       If no channel is specified call files creation policy will be applied to all channels.\n";
15028       return NULL;
15029    case CLI_GENERATE:
15030       return NULL;
15031    }
15032    if (a->argc < 4) {
15033       return CLI_SHOWUSAGE;
15034    }
15035    channo = (a->argc == 5) ? atoi(a->argv[4]) : -1;
15036    ast_mutex_lock(&iflock);
15037    for (p = iflist; p; p = p->next) {
15038       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
15039          continue;
15040       }
15041       if ((channo != -1) && (p->channel != channo )) {
15042          continue;
15043       }
15044       if (ast_true(a->argv[3])) {
15045          openr2_chan_enable_call_files(p->r2chan);
15046       } else {
15047          openr2_chan_disable_call_files(p->r2chan);
15048       }
15049       if (channo != -1) {
15050          if (ast_true(a->argv[3])) {
15051             ast_cli(a->fd, "MFC/R2 call files enabled for channel %d.\n", p->channel);
15052          } else {
15053             ast_cli(a->fd, "MFC/R2 call files disabled for channel %d.\n", p->channel);
15054          }
15055          break;
15056       }
15057    }
15058    if ((channo != -1) && !p) {
15059       ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
15060    }
15061    if (channo == -1) {
15062       if (ast_true(a->argv[3])) {
15063          ast_cli(a->fd, "MFC/R2 Call files enabled for all channels.\n");
15064       } else {
15065          ast_cli(a->fd, "MFC/R2 Call files disabled for all channels.\n");
15066       }
15067    }
15068    ast_mutex_unlock(&iflock);
15069    return CLI_SUCCESS;
15070 }
15071 
15072 static char *handle_mfcr2_set_idle(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15073 {
15074    struct dahdi_pvt *p = NULL;
15075    int channo = 0;
15076    switch (cmd) {
15077    case CLI_INIT:
15078       e->command = "mfcr2 set idle";
15079       e->usage =
15080          "Usage: mfcr2 set idle <channel>\n"
15081          "       DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n"
15082          "       Force the given channel into IDLE state.\n"
15083          "       If no channel is specified, all channels will be set to IDLE.\n";
15084       return NULL;
15085    case CLI_GENERATE:
15086       return NULL;
15087    }
15088    channo = (a->argc == 4) ? atoi(a->argv[3]) : -1;
15089    ast_mutex_lock(&iflock);
15090    for (p = iflist; p; p = p->next) {
15091       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
15092          continue;
15093       }
15094       if ((channo != -1) && (p->channel != channo )) {
15095          continue;
15096       }
15097       openr2_chan_set_idle(p->r2chan);
15098       ast_mutex_lock(&p->lock);
15099       p->locallyblocked = 0;
15100       p->mfcr2call = 0;
15101       ast_mutex_unlock(&p->lock);
15102       if (channo != -1) {
15103          break;
15104       }
15105    }
15106    if ((channo != -1) && !p) {
15107       ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
15108    }
15109    ast_mutex_unlock(&iflock);
15110    return CLI_SUCCESS;
15111 }
15112 
15113 static char *handle_mfcr2_set_blocked(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15114 {
15115    struct dahdi_pvt *p = NULL;
15116    int channo = 0;
15117    switch (cmd) {
15118    case CLI_INIT:
15119       e->command = "mfcr2 set blocked";
15120       e->usage =
15121          "Usage: mfcr2 set blocked <channel>\n"
15122          "       DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n"
15123          "       Force the given channel into BLOCKED state.\n"
15124          "       If no channel is specified, all channels will be set to BLOCKED.\n";
15125       return NULL;
15126    case CLI_GENERATE:
15127       return NULL;
15128    }
15129    channo = (a->argc == 4) ? atoi(a->argv[3]) : -1;
15130    ast_mutex_lock(&iflock);
15131    for (p = iflist; p; p = p->next) {
15132       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
15133          continue;
15134       }
15135       if ((channo != -1) && (p->channel != channo )) {
15136          continue;
15137       }
15138       openr2_chan_set_blocked(p->r2chan);
15139       ast_mutex_lock(&p->lock);
15140       p->locallyblocked = 1;
15141       ast_mutex_unlock(&p->lock);
15142       if (channo != -1) {
15143          break;
15144       }
15145    }
15146    if ((channo != -1) && !p) {
15147       ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
15148    }
15149    ast_mutex_unlock(&iflock);
15150    return CLI_SUCCESS;
15151 }
15152 
15153 static struct ast_cli_entry dahdi_mfcr2_cli[] = {
15154    AST_CLI_DEFINE(handle_mfcr2_version, "Show OpenR2 library version"),
15155    AST_CLI_DEFINE(handle_mfcr2_show_variants, "Show supported MFC/R2 variants"),
15156    AST_CLI_DEFINE(handle_mfcr2_show_channels, "Show MFC/R2 channels"),
15157    AST_CLI_DEFINE(handle_mfcr2_set_debug, "Set MFC/R2 channel logging level"),
15158    AST_CLI_DEFINE(handle_mfcr2_call_files, "Enable/Disable MFC/R2 call files"),
15159    AST_CLI_DEFINE(handle_mfcr2_set_idle, "Reset MFC/R2 channel forcing it to IDLE"),
15160    AST_CLI_DEFINE(handle_mfcr2_set_blocked, "Reset MFC/R2 channel forcing it to BLOCKED"),
15161 };
15162 
15163 #endif /* HAVE_OPENR2 */
15164 
15165 static char *dahdi_destroy_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15166 {
15167    int channel;
15168    int ret;
15169    switch (cmd) {
15170    case CLI_INIT:
15171       e->command = "dahdi destroy channel";
15172       e->usage =
15173          "Usage: dahdi destroy channel <chan num>\n"
15174          "  DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.  Immediately removes a given channel, whether it is in use or not\n";
15175       return NULL;
15176    case CLI_GENERATE:
15177       return NULL;
15178    }
15179    if (a->argc != 4)
15180       return CLI_SHOWUSAGE;
15181 
15182    channel = atoi(a->argv[3]);
15183    ret = dahdi_destroy_channel_bynum(channel);
15184    return ( RESULT_SUCCESS == ret ) ? CLI_SUCCESS : CLI_FAILURE;
15185 }
15186 
15187 static void dahdi_softhangup_all(void)
15188 {
15189    struct dahdi_pvt *p;
15190 retry:
15191    ast_mutex_lock(&iflock);
15192    for (p = iflist; p; p = p->next) {
15193       ast_mutex_lock(&p->lock);
15194       if (p->owner && !p->restartpending) {
15195          if (ast_channel_trylock(p->owner)) {
15196             if (option_debug > 2)
15197                ast_verbose("Avoiding deadlock\n");
15198             /* Avoid deadlock since you're not supposed to lock iflock or pvt before a channel */
15199             ast_mutex_unlock(&p->lock);
15200             ast_mutex_unlock(&iflock);
15201             goto retry;
15202          }
15203          if (option_debug > 2)
15204             ast_verbose("Softhanging up on %s\n", p->owner->name);
15205          ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_EXPLICIT);
15206          p->restartpending = 1;
15207          num_restart_pending++;
15208          ast_channel_unlock(p->owner);
15209       }
15210       ast_mutex_unlock(&p->lock);
15211    }
15212    ast_mutex_unlock(&iflock);
15213 }
15214 
15215 static int setup_dahdi(int reload);
15216 static int dahdi_restart(void)
15217 {
15218 #if defined(HAVE_PRI) || defined(HAVE_SS7)
15219    int i, j;
15220 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
15221    int cancel_code;
15222    struct dahdi_pvt *p;
15223 
15224    ast_mutex_lock(&restart_lock);
15225    ast_verb(1, "Destroying channels and reloading DAHDI configuration.\n");
15226    dahdi_softhangup_all();
15227    ast_verb(4, "Initial softhangup of all DAHDI channels complete.\n");
15228 #ifdef HAVE_OPENR2
15229    dahdi_r2_destroy_links();
15230 #endif
15231 
15232 #if defined(HAVE_PRI)
15233    for (i = 0; i < NUM_SPANS; i++) {
15234       if (pris[i].pri.master && (pris[i].pri.master != AST_PTHREADT_NULL)) {
15235          cancel_code = pthread_cancel(pris[i].pri.master);
15236          pthread_kill(pris[i].pri.master, SIGURG);
15237          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);
15238          pthread_join(pris[i].pri.master, NULL);
15239          ast_debug(4, "Joined thread of span %d\n", i);
15240       }
15241    }
15242 #endif
15243 
15244 #if defined(HAVE_SS7)
15245    for (i = 0; i < NUM_SPANS; i++) {
15246       if (linksets[i].ss7.master && (linksets[i].ss7.master != AST_PTHREADT_NULL)) {
15247          cancel_code = pthread_cancel(linksets[i].ss7.master);
15248          pthread_kill(linksets[i].ss7.master, SIGURG);
15249          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);
15250          pthread_join(linksets[i].ss7.master, NULL);
15251          ast_debug(4, "Joined thread of span %d\n", i);
15252       }
15253    }
15254 #endif   /* defined(HAVE_SS7) */
15255 
15256    ast_mutex_lock(&monlock);
15257    if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
15258       cancel_code = pthread_cancel(monitor_thread);
15259       pthread_kill(monitor_thread, SIGURG);
15260       ast_debug(4, "Waiting to join monitor thread with pid=%p, cancel_code=%d\n", (void *) monitor_thread, cancel_code);
15261       pthread_join(monitor_thread, NULL);
15262       ast_debug(4, "Joined monitor thread\n");
15263    }
15264    monitor_thread = AST_PTHREADT_NULL; /* prepare to restart thread in setup_dahdi once channels are reconfigured */
15265 
15266    ast_mutex_lock(&ss_thread_lock);
15267    while (ss_thread_count > 0) { /* let ss_threads finish and run dahdi_hangup before dahvi_pvts are destroyed */
15268       int x = DAHDI_FLASH;
15269       ast_debug(3, "Waiting on %d analog_ss_thread(s) to finish\n", ss_thread_count);
15270 
15271       ast_mutex_lock(&iflock);
15272       for (p = iflist; p; p = p->next) {
15273          if (p->owner) {
15274             /* important to create an event for dahdi_wait_event to register so that all analog_ss_threads terminate */
15275             ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
15276          }
15277       }
15278       ast_mutex_unlock(&iflock);
15279       ast_cond_wait(&ss_thread_complete, &ss_thread_lock);
15280    }
15281 
15282    /* ensure any created channels before monitor threads were stopped are hungup */
15283    dahdi_softhangup_all();
15284    ast_verb(4, "Final softhangup of all DAHDI channels complete.\n");
15285    destroy_all_channels();
15286    memset(round_robin, 0, sizeof(round_robin));
15287    ast_debug(1, "Channels destroyed. Now re-reading config. %d active channels remaining.\n", ast_active_channels());
15288 
15289    ast_mutex_unlock(&monlock);
15290 
15291 #ifdef HAVE_PRI
15292    for (i = 0; i < NUM_SPANS; i++) {
15293       for (j = 0; j < SIG_PRI_NUM_DCHANS; j++)
15294          dahdi_close_pri_fd(&(pris[i]), j);
15295    }
15296 
15297    memset(pris, 0, sizeof(pris));
15298    for (i = 0; i < NUM_SPANS; i++) {
15299       sig_pri_init_pri(&pris[i].pri);
15300    }
15301    pri_set_error(dahdi_pri_error);
15302    pri_set_message(dahdi_pri_message);
15303 #endif
15304 #if defined(HAVE_SS7)
15305    for (i = 0; i < NUM_SPANS; i++) {
15306       for (j = 0; j < SIG_SS7_NUM_DCHANS; j++)
15307          dahdi_close_ss7_fd(&(linksets[i]), j);
15308    }
15309 
15310    memset(linksets, 0, sizeof(linksets));
15311    for (i = 0; i < NUM_SPANS; i++) {
15312       sig_ss7_init_linkset(&linksets[i].ss7);
15313    }
15314    ss7_set_error(dahdi_ss7_error);
15315    ss7_set_message(dahdi_ss7_message);
15316 #endif   /* defined(HAVE_SS7) */
15317 
15318    if (setup_dahdi(2) != 0) {
15319       ast_log(LOG_WARNING, "Reload channels from dahdi config failed!\n");
15320       ast_mutex_unlock(&ss_thread_lock);
15321       return 1;
15322    }
15323    ast_mutex_unlock(&ss_thread_lock);
15324    ast_mutex_unlock(&restart_lock);
15325    return 0;
15326 }
15327 
15328 static char *dahdi_restart_cmd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15329 {
15330    switch (cmd) {
15331    case CLI_INIT:
15332       e->command = "dahdi restart";
15333       e->usage =
15334          "Usage: dahdi restart\n"
15335          "  Restarts the DAHDI channels: destroys them all and then\n"
15336          "  re-reads them from chan_dahdi.conf.\n"
15337          "  Note that this will STOP any running CALL on DAHDI channels.\n"
15338          "";
15339       return NULL;
15340    case CLI_GENERATE:
15341       return NULL;
15342    }
15343    if (a->argc != 2)
15344       return CLI_SHOWUSAGE;
15345 
15346    if (dahdi_restart() != 0)
15347       return CLI_FAILURE;
15348    return CLI_SUCCESS;
15349 }
15350 
15351 static int action_dahdirestart(struct mansession *s, const struct message *m)
15352 {
15353    if (dahdi_restart() != 0) {
15354       astman_send_error(s, m, "Failed rereading DAHDI configuration");
15355       return 1;
15356    }
15357    astman_send_ack(s, m, "DAHDIRestart: Success");
15358    return 0;
15359 }
15360 
15361 static char *dahdi_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15362 {
15363 #define FORMAT "%7s %-15.15s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
15364 #define FORMAT2 "%7s %-15.15s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
15365    ast_group_t targetnum = 0;
15366    int filtertype = 0;
15367    struct dahdi_pvt *tmp = NULL;
15368    char tmps[20] = "";
15369    char statestr[20] = "";
15370    char blockstr[20] = "";
15371 
15372    switch (cmd) {
15373    case CLI_INIT:
15374       e->command = "dahdi show channels [group|context]";
15375       e->usage =
15376          "Usage: dahdi show channels [ group <group> | context <context> ]\n"
15377          "  Shows a list of available channels with optional filtering\n"
15378          "  <group> must be a number between 0 and 63\n";
15379       return NULL;
15380    case CLI_GENERATE:
15381       return NULL;
15382    }
15383 
15384    /* syntax: dahdi show channels [ group <group> | context <context> ] */
15385 
15386    if (!((a->argc == 3) || (a->argc == 5)))
15387       return CLI_SHOWUSAGE;
15388 
15389    if (a->argc == 5) {
15390       if (!strcasecmp(a->argv[3], "group")) {
15391          targetnum = atoi(a->argv[4]);
15392          if (63 < targetnum) {
15393             return CLI_SHOWUSAGE;
15394          }
15395          targetnum = ((ast_group_t) 1) << targetnum;
15396          filtertype = 1;
15397       } else if (!strcasecmp(a->argv[3], "context")) {
15398          filtertype = 2;
15399       }
15400    }
15401 
15402    ast_cli(a->fd, FORMAT2, "Chan", "Extension", "Context", "Language", "MOH Interpret", "Blocked", "State");
15403    ast_mutex_lock(&iflock);
15404    for (tmp = iflist; tmp; tmp = tmp->next) {
15405       if (filtertype) {
15406          switch(filtertype) {
15407          case 1: /* dahdi show channels group <group> */
15408             if (!(tmp->group & targetnum)) {
15409                continue;
15410             }
15411             break;
15412          case 2: /* dahdi show channels context <context> */
15413             if (strcasecmp(tmp->context, a->argv[4])) {
15414                continue;
15415             }
15416             break;
15417          default:
15418             break;
15419          }
15420       }
15421       if (tmp->channel > 0) {
15422          snprintf(tmps, sizeof(tmps), "%d", tmp->channel);
15423       } else
15424          ast_copy_string(tmps, "pseudo", sizeof(tmps));
15425 
15426       if (tmp->locallyblocked)
15427          blockstr[0] = 'L';
15428       else
15429          blockstr[0] = ' ';
15430 
15431       if (tmp->remotelyblocked)
15432          blockstr[1] = 'R';
15433       else
15434          blockstr[1] = ' ';
15435 
15436       blockstr[2] = '\0';
15437 
15438       snprintf(statestr, sizeof(statestr), "%s", "In Service");
15439 
15440       ast_cli(a->fd, FORMAT, tmps, tmp->exten, tmp->context, tmp->language, tmp->mohinterpret, blockstr, statestr);
15441    }
15442    ast_mutex_unlock(&iflock);
15443    return CLI_SUCCESS;
15444 #undef FORMAT
15445 #undef FORMAT2
15446 }
15447 
15448 static char *dahdi_show_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15449 {
15450    int channel;
15451    struct dahdi_pvt *tmp = NULL;
15452    struct dahdi_confinfo ci;
15453    struct dahdi_params ps;
15454    int x;
15455 
15456    switch (cmd) {
15457    case CLI_INIT:
15458       e->command = "dahdi show channel";
15459       e->usage =
15460          "Usage: dahdi show channel <chan num>\n"
15461          "  Detailed information about a given channel\n";
15462       return NULL;
15463    case CLI_GENERATE:
15464       return NULL;
15465    }
15466 
15467    if (a->argc != 4)
15468       return CLI_SHOWUSAGE;
15469 
15470    channel = atoi(a->argv[3]);
15471 
15472    ast_mutex_lock(&iflock);
15473    for (tmp = iflist; tmp; tmp = tmp->next) {
15474       if (tmp->channel == channel) {
15475          ast_cli(a->fd, "Channel: %d\n", tmp->channel);
15476          ast_cli(a->fd, "File Descriptor: %d\n", tmp->subs[SUB_REAL].dfd);
15477          ast_cli(a->fd, "Span: %d\n", tmp->span);
15478          ast_cli(a->fd, "Extension: %s\n", tmp->exten);
15479          ast_cli(a->fd, "Dialing: %s\n", tmp->dialing ? "yes" : "no");
15480          ast_cli(a->fd, "Context: %s\n", tmp->context);
15481          ast_cli(a->fd, "Caller ID: %s\n", tmp->cid_num);
15482          ast_cli(a->fd, "Calling TON: %d\n", tmp->cid_ton);
15483 #if defined(HAVE_PRI)
15484 #if defined(HAVE_PRI_SUBADDR)
15485          ast_cli(a->fd, "Caller ID subaddress: %s\n", tmp->cid_subaddr);
15486 #endif   /* defined(HAVE_PRI_SUBADDR) */
15487 #endif   /* defined(HAVE_PRI) */
15488          ast_cli(a->fd, "Caller ID name: %s\n", tmp->cid_name);
15489          ast_cli(a->fd, "Mailbox: %s\n", S_OR(tmp->mailbox, "none"));
15490          if (tmp->vars) {
15491             struct ast_variable *v;
15492             ast_cli(a->fd, "Variables:\n");
15493             for (v = tmp->vars ; v ; v = v->next)
15494                ast_cli(a->fd, "       %s = %s\n", v->name, v->value);
15495          }
15496          ast_cli(a->fd, "Destroy: %d\n", tmp->destroy);
15497          ast_cli(a->fd, "InAlarm: %d\n", tmp->inalarm);
15498          ast_cli(a->fd, "Signalling Type: %s\n", sig2str(tmp->sig));
15499          ast_cli(a->fd, "Radio: %d\n", tmp->radio);
15500          ast_cli(a->fd, "Owner: %s\n", tmp->owner ? tmp->owner->name : "<None>");
15501          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)" : "");
15502          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)" : "");
15503          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)" : "");
15504          ast_cli(a->fd, "Confno: %d\n", tmp->confno);
15505          ast_cli(a->fd, "Propagated Conference: %d\n", tmp->propconfno);
15506          ast_cli(a->fd, "Real in conference: %d\n", tmp->inconference);
15507          ast_cli(a->fd, "DSP: %s\n", tmp->dsp ? "yes" : "no");
15508          ast_cli(a->fd, "Busy Detection: %s\n", tmp->busydetect ? "yes" : "no");
15509          if (tmp->busydetect) {
15510 #if defined(BUSYDETECT_TONEONLY)
15511             ast_cli(a->fd, "    Busy Detector Helper: BUSYDETECT_TONEONLY\n");
15512 #elif defined(BUSYDETECT_COMPARE_TONE_AND_SILENCE)
15513             ast_cli(a->fd, "    Busy Detector Helper: BUSYDETECT_COMPARE_TONE_AND_SILENCE\n");
15514 #endif
15515 #ifdef BUSYDETECT_DEBUG
15516             ast_cli(a->fd, "    Busy Detector Debug: Enabled\n");
15517 #endif
15518             ast_cli(a->fd, "    Busy Count: %d\n", tmp->busycount);
15519             ast_cli(a->fd, "    Busy Pattern: %d,%d\n", tmp->busy_tonelength, tmp->busy_quietlength);
15520          }
15521          ast_cli(a->fd, "TDD: %s\n", tmp->tdd ? "yes" : "no");
15522          ast_cli(a->fd, "Relax DTMF: %s\n", tmp->dtmfrelax ? "yes" : "no");
15523          ast_cli(a->fd, "Dialing/CallwaitCAS: %d/%d\n", tmp->dialing, tmp->callwaitcas);
15524          ast_cli(a->fd, "Default law: %s\n", tmp->law_default == DAHDI_LAW_MULAW ? "ulaw" : tmp->law_default == DAHDI_LAW_ALAW ? "alaw" : "unknown");
15525          ast_cli(a->fd, "Fax Handled: %s\n", tmp->faxhandled ? "yes" : "no");
15526          ast_cli(a->fd, "Pulse phone: %s\n", tmp->pulsedial ? "yes" : "no");
15527          ast_cli(a->fd, "Gains (RX/TX): %.2f/%.2f\n", tmp->rxgain, tmp->txgain);
15528          ast_cli(a->fd, "Dynamic Range Compression (RX/TX): %.2f/%.2f\n", tmp->rxdrc, tmp->txdrc);
15529          ast_cli(a->fd, "DND: %s\n", dahdi_dnd(tmp, -1) ? "yes" : "no");
15530          ast_cli(a->fd, "Echo Cancellation:\n");
15531 
15532          if (tmp->echocancel.head.tap_length) {
15533             ast_cli(a->fd, "\t%u taps\n", tmp->echocancel.head.tap_length);
15534             for (x = 0; x < tmp->echocancel.head.param_count; x++) {
15535                ast_cli(a->fd, "\t\t%s: %dd\n", tmp->echocancel.params[x].name, tmp->echocancel.params[x].value);
15536             }
15537             ast_cli(a->fd, "\t%scurrently %s\n", tmp->echocanbridged ? "" : "(unless TDM bridged) ", tmp->echocanon ? "ON" : "OFF");
15538          } else {
15539             ast_cli(a->fd, "\tnone\n");
15540          }
15541          ast_cli(a->fd, "Wait for dialtone: %dms\n", tmp->waitfordialtone);
15542          if (tmp->master)
15543             ast_cli(a->fd, "Master Channel: %d\n", tmp->master->channel);
15544          for (x = 0; x < MAX_SLAVES; x++) {
15545             if (tmp->slaves[x])
15546                ast_cli(a->fd, "Slave Channel: %d\n", tmp->slaves[x]->channel);
15547          }
15548 #ifdef HAVE_OPENR2
15549          if (tmp->mfcr2) {
15550             char calldir[OR2_MAX_PATH];
15551             openr2_context_t *r2context = openr2_chan_get_context(tmp->r2chan);
15552             openr2_variant_t r2variant = openr2_context_get_variant(r2context);
15553             ast_cli(a->fd, "MFC/R2 MF State: %s\n", openr2_chan_get_mf_state_string(tmp->r2chan));
15554             ast_cli(a->fd, "MFC/R2 MF Group: %s\n", openr2_chan_get_mf_group_string(tmp->r2chan));
15555             ast_cli(a->fd, "MFC/R2 State: %s\n", openr2_chan_get_r2_state_string(tmp->r2chan));
15556             ast_cli(a->fd, "MFC/R2 Call State: %s\n", openr2_chan_get_call_state_string(tmp->r2chan));
15557             ast_cli(a->fd, "MFC/R2 Call Files Enabled: %s\n", openr2_chan_get_call_files_enabled(tmp->r2chan) ? "Yes" : "No");
15558             ast_cli(a->fd, "MFC/R2 Variant: %s\n", openr2_proto_get_variant_string(r2variant));
15559             ast_cli(a->fd, "MFC/R2 Max ANI: %d\n", openr2_context_get_max_ani(r2context));
15560             ast_cli(a->fd, "MFC/R2 Max DNIS: %d\n", openr2_context_get_max_dnis(r2context));
15561             ast_cli(a->fd, "MFC/R2 Get ANI First: %s\n", openr2_context_get_ani_first(r2context) ? "Yes" : "No");
15562 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
15563             ast_cli(a->fd, "MFC/R2 Skip Category Request: %s\n", openr2_context_get_skip_category_request(r2context) ? "Yes" : "No");
15564 #endif
15565             ast_cli(a->fd, "MFC/R2 Immediate Accept: %s\n", openr2_context_get_immediate_accept(r2context) ? "Yes" : "No");
15566             ast_cli(a->fd, "MFC/R2 Accept on Offer: %s\n", tmp->mfcr2_accept_on_offer ? "Yes" : "No");
15567             ast_cli(a->fd, "MFC/R2 Charge Calls: %s\n", tmp->mfcr2_charge_calls ? "Yes" : "No");
15568             ast_cli(a->fd, "MFC/R2 Allow Collect Calls: %s\n", tmp->mfcr2_allow_collect_calls ? "Yes" : "No");
15569             ast_cli(a->fd, "MFC/R2 Forced Release: %s\n", tmp->mfcr2_forced_release ? "Yes" : "No");
15570             ast_cli(a->fd, "MFC/R2 MF Back Timeout: %dms\n", openr2_context_get_mf_back_timeout(r2context));
15571             ast_cli(a->fd, "MFC/R2 R2 Metering Pulse Timeout: %dms\n", openr2_context_get_metering_pulse_timeout(r2context));
15572             ast_cli(a->fd, "MFC/R2 Rx CAS: %s\n", openr2_chan_get_rx_cas_string(tmp->r2chan));
15573             ast_cli(a->fd, "MFC/R2 Tx CAS: %s\n", openr2_chan_get_tx_cas_string(tmp->r2chan));
15574             ast_cli(a->fd, "MFC/R2 MF Tx Signal: %d\n", openr2_chan_get_tx_mf_signal(tmp->r2chan));
15575             ast_cli(a->fd, "MFC/R2 MF Rx Signal: %d\n", openr2_chan_get_rx_mf_signal(tmp->r2chan));
15576             ast_cli(a->fd, "MFC/R2 Call Files Directory: %s\n", openr2_context_get_log_directory(r2context, calldir, sizeof(calldir)));
15577          }
15578 #endif
15579 #if defined(HAVE_SS7)
15580          if (tmp->ss7) {
15581             struct sig_ss7_chan *chan = tmp->sig_pvt;
15582 
15583             ast_cli(a->fd, "CIC: %d\n", chan->cic);
15584          }
15585 #endif   /* defined(HAVE_SS7) */
15586 #ifdef HAVE_PRI
15587          if (tmp->pri) {
15588             struct sig_pri_chan *chan = tmp->sig_pvt;
15589 
15590             ast_cli(a->fd, "PRI Flags: ");
15591             if (chan->resetting != SIG_PRI_RESET_IDLE) {
15592                ast_cli(a->fd, "Resetting=%u ", chan->resetting);
15593             }
15594             if (chan->call)
15595                ast_cli(a->fd, "Call ");
15596             if (chan->allocated) {
15597                ast_cli(a->fd, "Allocated ");
15598             }
15599             ast_cli(a->fd, "\n");
15600             if (tmp->logicalspan)
15601                ast_cli(a->fd, "PRI Logical Span: %d\n", tmp->logicalspan);
15602             else
15603                ast_cli(a->fd, "PRI Logical Span: Implicit\n");
15604          }
15605 #endif
15606          memset(&ci, 0, sizeof(ci));
15607          ps.channo = tmp->channel;
15608          if (tmp->subs[SUB_REAL].dfd > -1) {
15609             memset(&ci, 0, sizeof(ci));
15610             if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
15611                ast_cli(a->fd, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci.confno, (unsigned)ci.confmode);
15612             }
15613             if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONFMUTE, &x)) {
15614                ast_cli(a->fd, "Actual Confmute: %s\n", x ? "Yes" : "No");
15615             }
15616             memset(&ps, 0, sizeof(ps));
15617             if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
15618                ast_log(LOG_WARNING, "Failed to get parameters on channel %d: %s\n", tmp->channel, strerror(errno));
15619             } else {
15620                ast_cli(a->fd, "Hookstate (FXS only): %s\n", ps.rxisoffhook ? "Offhook" : "Onhook");
15621             }
15622          }
15623          ast_mutex_unlock(&iflock);
15624          return CLI_SUCCESS;
15625       }
15626    }
15627    ast_mutex_unlock(&iflock);
15628 
15629    ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15630    return CLI_FAILURE;
15631 }
15632 
15633 static char *handle_dahdi_show_cadences(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15634 {
15635    int i, j;
15636    switch (cmd) {
15637    case CLI_INIT:
15638       e->command = "dahdi show cadences";
15639       e->usage =
15640          "Usage: dahdi show cadences\n"
15641          "       Shows all cadences currently defined\n";
15642       return NULL;
15643    case CLI_GENERATE:
15644       return NULL;
15645    }
15646    for (i = 0; i < num_cadence; i++) {
15647       char output[1024];
15648       char tmp[16], tmp2[64];
15649       snprintf(tmp, sizeof(tmp), "r%d: ", i + 1);
15650       term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output));
15651 
15652       for (j = 0; j < 16; j++) {
15653          if (cadences[i].ringcadence[j] == 0)
15654             break;
15655          snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]);
15656          if (cidrings[i] * 2 - 1 == j)
15657             term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1);
15658          else
15659             term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1);
15660          if (j != 0)
15661             strncat(output, ",", sizeof(output) - strlen(output) - 1);
15662          strncat(output, tmp2, sizeof(output) - strlen(output) - 1);
15663       }
15664       ast_cli(a->fd,"%s\n",output);
15665    }
15666    return CLI_SUCCESS;
15667 }
15668 
15669 /* Based on irqmiss.c */
15670 static char *dahdi_show_status(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15671 {
15672    #define FORMAT "%-40.40s %-7.7s %-6d %-6d %-6d %-3.3s %-4.4s %-8.8s %s\n"
15673    #define FORMAT2 "%-40.40s %-7.7s %-6.6s %-6.6s %-6.6s %-3.3s %-4.4s %-8.8s %s\n"
15674    int span;
15675    int res;
15676    char alarmstr[50];
15677 
15678    int ctl;
15679    struct dahdi_spaninfo s;
15680 
15681    switch (cmd) {
15682    case CLI_INIT:
15683       e->command = "dahdi show status";
15684       e->usage =
15685          "Usage: dahdi show status\n"
15686          "       Shows a list of DAHDI cards with status\n";
15687       return NULL;
15688    case CLI_GENERATE:
15689       return NULL;
15690    }
15691    ctl = open("/dev/dahdi/ctl", O_RDWR);
15692    if (ctl < 0) {
15693       ast_cli(a->fd, "No DAHDI found. Unable to open /dev/dahdi/ctl: %s\n", strerror(errno));
15694       return CLI_FAILURE;
15695    }
15696    ast_cli(a->fd, FORMAT2, "Description", "Alarms", "IRQ", "bpviol", "CRC", "Framing", "Coding", "Options", "LBO");
15697 
15698    for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
15699       s.spanno = span;
15700       res = ioctl(ctl, DAHDI_SPANSTAT, &s);
15701       if (res) {
15702          continue;
15703       }
15704       alarmstr[0] = '\0';
15705       if (s.alarms > 0) {
15706          if (s.alarms & DAHDI_ALARM_BLUE)
15707             strcat(alarmstr, "BLU/");
15708          if (s.alarms & DAHDI_ALARM_YELLOW)
15709             strcat(alarmstr, "YEL/");
15710          if (s.alarms & DAHDI_ALARM_RED)
15711             strcat(alarmstr, "RED/");
15712          if (s.alarms & DAHDI_ALARM_LOOPBACK)
15713             strcat(alarmstr, "LB/");
15714          if (s.alarms & DAHDI_ALARM_RECOVER)
15715             strcat(alarmstr, "REC/");
15716          if (s.alarms & DAHDI_ALARM_NOTOPEN)
15717             strcat(alarmstr, "NOP/");
15718          if (!strlen(alarmstr))
15719             strcat(alarmstr, "UUU/");
15720          if (strlen(alarmstr)) {
15721             /* Strip trailing / */
15722             alarmstr[strlen(alarmstr) - 1] = '\0';
15723          }
15724       } else {
15725          if (s.numchans)
15726             strcpy(alarmstr, "OK");
15727          else
15728             strcpy(alarmstr, "UNCONFIGURED");
15729       }
15730 
15731       ast_cli(a->fd, FORMAT, s.desc, alarmstr, s.irqmisses, s.bpvcount, s.crc4count,
15732          s.lineconfig & DAHDI_CONFIG_D4 ? "D4" :
15733          s.lineconfig & DAHDI_CONFIG_ESF ? "ESF" :
15734          s.lineconfig & DAHDI_CONFIG_CCS ? "CCS" :
15735          "CAS",
15736          s.lineconfig & DAHDI_CONFIG_B8ZS ? "B8ZS" :
15737          s.lineconfig & DAHDI_CONFIG_HDB3 ? "HDB3" :
15738          s.lineconfig & DAHDI_CONFIG_AMI ? "AMI" :
15739          "Unk",
15740          s.lineconfig & DAHDI_CONFIG_CRC4 ?
15741             s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" :
15742             s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "YEL" : "",
15743          lbostr[s.lbo]
15744          );
15745    }
15746    close(ctl);
15747 
15748    return CLI_SUCCESS;
15749 #undef FORMAT
15750 #undef FORMAT2
15751 }
15752 
15753 static char *dahdi_show_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15754 {
15755    int pseudo_fd = -1;
15756    struct dahdi_versioninfo vi;
15757 
15758    switch (cmd) {
15759    case CLI_INIT:
15760       e->command = "dahdi show version";
15761       e->usage =
15762          "Usage: dahdi show version\n"
15763          "       Shows the DAHDI version in use\n";
15764       return NULL;
15765    case CLI_GENERATE:
15766       return NULL;
15767    }
15768    if ((pseudo_fd = open("/dev/dahdi/ctl", O_RDONLY)) < 0) {
15769       ast_cli(a->fd, "Failed to open control file to get version.\n");
15770       return CLI_SUCCESS;
15771    }
15772 
15773    strcpy(vi.version, "Unknown");
15774    strcpy(vi.echo_canceller, "Unknown");
15775 
15776    if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi))
15777       ast_cli(a->fd, "Failed to get DAHDI version: %s\n", strerror(errno));
15778    else
15779       ast_cli(a->fd, "DAHDI Version: %s Echo Canceller: %s\n", vi.version, vi.echo_canceller);
15780 
15781    close(pseudo_fd);
15782 
15783    return CLI_SUCCESS;
15784 }
15785 
15786 static char *dahdi_set_hwgain(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15787 {
15788    int channel;
15789    int gain;
15790    int tx;
15791    struct dahdi_hwgain hwgain;
15792    struct dahdi_pvt *tmp = NULL;
15793 
15794    switch (cmd) {
15795    case CLI_INIT:
15796       e->command = "dahdi set hwgain {rx|tx}";
15797       e->usage =
15798          "Usage: dahdi set hwgain <rx|tx> <chan#> <gain>\n"
15799          "   Sets the hardware gain on a given channel.  Changes take effect\n"
15800          "   immediately whether the channel is in use or not.\n"
15801          "\n"
15802          "   <rx|tx> which direction do you want to change (relative to our module)\n"
15803          "   <chan num> is the channel number relative to the device\n"
15804          "   <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n"
15805          "\n"
15806          "   Please note:\n"
15807          "   * This is currently the only way to set hwgain by the channel driver.\n"
15808          "   * hwgain is only supportable by hardware with analog ports because\n"
15809          "     hwgain works on the analog side of an analog-digital conversion.\n";
15810       return NULL;
15811    case CLI_GENERATE:
15812       return NULL;
15813    }
15814 
15815    if (a->argc != 6)
15816       return CLI_SHOWUSAGE;
15817 
15818    if (!strcasecmp("rx", a->argv[3]))
15819       tx = 0; /* rx */
15820    else if (!strcasecmp("tx", a->argv[3]))
15821       tx = 1; /* tx */
15822    else
15823       return CLI_SHOWUSAGE;
15824 
15825    channel = atoi(a->argv[4]);
15826    gain = atof(a->argv[5])*10.0;
15827 
15828    ast_mutex_lock(&iflock);
15829 
15830    for (tmp = iflist; tmp; tmp = tmp->next) {
15831 
15832       if (tmp->channel != channel)
15833          continue;
15834 
15835       if (tmp->subs[SUB_REAL].dfd == -1)
15836          break;
15837 
15838       hwgain.newgain = gain;
15839       hwgain.tx = tx;
15840       if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_HWGAIN, &hwgain) < 0) {
15841          ast_cli(a->fd, "Unable to set the hardware gain for channel %d: %s\n", channel, strerror(errno));
15842          ast_mutex_unlock(&iflock);
15843          return CLI_FAILURE;
15844       }
15845       ast_cli(a->fd, "hardware %s gain set to %d (%.1f dB) on channel %d\n",
15846          tx ? "tx" : "rx", gain, (float)gain/10.0, channel);
15847       break;
15848    }
15849 
15850    ast_mutex_unlock(&iflock);
15851 
15852    if (tmp)
15853       return CLI_SUCCESS;
15854 
15855    ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15856    return CLI_FAILURE;
15857 
15858 }
15859 
15860 static char *dahdi_set_swgain(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15861 {
15862    int channel;
15863    float gain;
15864    int tx;
15865    int res;
15866    struct dahdi_pvt *tmp = NULL;
15867 
15868    switch (cmd) {
15869    case CLI_INIT:
15870       e->command = "dahdi set swgain {rx|tx}";
15871       e->usage =
15872          "Usage: dahdi set swgain <rx|tx> <chan#> <gain>\n"
15873          "   Sets the software gain on a given channel and overrides the\n"
15874          "   value provided at module loadtime.  Changes take effect\n"
15875          "   immediately whether the channel is in use or not.\n"
15876          "\n"
15877          "   <rx|tx> which direction do you want to change (relative to our module)\n"
15878          "   <chan num> is the channel number relative to the device\n"
15879          "   <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
15880       return NULL;
15881    case CLI_GENERATE:
15882       return NULL;
15883    }
15884 
15885    if (a->argc != 6)
15886       return CLI_SHOWUSAGE;
15887 
15888    if (!strcasecmp("rx", a->argv[3]))
15889       tx = 0; /* rx */
15890    else if (!strcasecmp("tx", a->argv[3]))
15891       tx = 1; /* tx */
15892    else
15893       return CLI_SHOWUSAGE;
15894 
15895    channel = atoi(a->argv[4]);
15896    gain = atof(a->argv[5]);
15897 
15898    ast_mutex_lock(&iflock);
15899    for (tmp = iflist; tmp; tmp = tmp->next) {
15900 
15901       if (tmp->channel != channel)
15902          continue;
15903 
15904       if (tmp->subs[SUB_REAL].dfd == -1)
15905          break;
15906 
15907       if (tx)
15908          res = set_actual_txgain(tmp->subs[SUB_REAL].dfd, gain, tmp->txdrc, tmp->law);
15909       else
15910          res = set_actual_rxgain(tmp->subs[SUB_REAL].dfd, gain, tmp->rxdrc, tmp->law);
15911 
15912       if (res) {
15913          ast_cli(a->fd, "Unable to set the software gain for channel %d\n", channel);
15914          ast_mutex_unlock(&iflock);
15915          return CLI_FAILURE;
15916       }
15917 
15918       ast_cli(a->fd, "software %s gain set to %.1f on channel %d\n",
15919          tx ? "tx" : "rx", gain, channel);
15920 
15921       if (tx) {
15922          tmp->txgain = gain;
15923       } else {
15924          tmp->rxgain = gain;
15925       }
15926       break;
15927    }
15928    ast_mutex_unlock(&iflock);
15929 
15930    if (tmp)
15931       return CLI_SUCCESS;
15932 
15933    ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15934    return CLI_FAILURE;
15935 
15936 }
15937 
15938 static char *dahdi_set_dnd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15939 {
15940    int channel;
15941    int on;
15942    struct dahdi_pvt *dahdi_chan = NULL;
15943 
15944    switch (cmd) {
15945    case CLI_INIT:
15946       e->command = "dahdi set dnd";
15947       e->usage =
15948          "Usage: dahdi set dnd <chan#> <on|off>\n"
15949          "  Sets/resets DND (Do Not Disturb) mode on a channel.\n"
15950          "  Changes take effect immediately.\n"
15951          "  <chan num> is the channel number\n"
15952          "  <on|off> Enable or disable DND mode?\n"
15953          ;
15954       return NULL;
15955    case CLI_GENERATE:
15956       return NULL;
15957    }
15958 
15959    if (a->argc != 5)
15960       return CLI_SHOWUSAGE;
15961 
15962    if ((channel = atoi(a->argv[3])) <= 0) {
15963       ast_cli(a->fd, "Expected channel number, got '%s'\n", a->argv[3]);
15964       return CLI_SHOWUSAGE;
15965    }
15966 
15967    if (ast_true(a->argv[4]))
15968       on = 1;
15969    else if (ast_false(a->argv[4]))
15970       on = 0;
15971    else {
15972       ast_cli(a->fd, "Expected 'on' or 'off', got '%s'\n", a->argv[4]);
15973       return CLI_SHOWUSAGE;
15974    }
15975 
15976    ast_mutex_lock(&iflock);
15977    for (dahdi_chan = iflist; dahdi_chan; dahdi_chan = dahdi_chan->next) {
15978       if (dahdi_chan->channel != channel)
15979          continue;
15980 
15981       /* Found the channel. Actually set it */
15982       dahdi_dnd(dahdi_chan, on);
15983       break;
15984    }
15985    ast_mutex_unlock(&iflock);
15986 
15987    if (!dahdi_chan) {
15988       ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15989       return CLI_FAILURE;
15990    }
15991 
15992    return CLI_SUCCESS;
15993 }
15994 
15995 static struct ast_cli_entry dahdi_cli[] = {
15996    AST_CLI_DEFINE(handle_dahdi_show_cadences, "List cadences"),
15997    AST_CLI_DEFINE(dahdi_show_channels, "Show active DAHDI channels"),
15998    AST_CLI_DEFINE(dahdi_show_channel, "Show information on a channel"),
15999    AST_CLI_DEFINE(dahdi_destroy_channel, "Destroy a channel"),
16000    AST_CLI_DEFINE(dahdi_restart_cmd, "Fully restart DAHDI channels"),
16001    AST_CLI_DEFINE(dahdi_show_status, "Show all DAHDI cards status"),
16002    AST_CLI_DEFINE(dahdi_show_version, "Show the DAHDI version in use"),
16003    AST_CLI_DEFINE(dahdi_set_hwgain, "Set hardware gain on a channel"),
16004    AST_CLI_DEFINE(dahdi_set_swgain, "Set software gain on a channel"),
16005    AST_CLI_DEFINE(dahdi_set_dnd, "Sets/resets DND (Do Not Disturb) mode on a channel"),
16006 };
16007 
16008 #define TRANSFER  0
16009 #define HANGUP    1
16010 
16011 static int dahdi_fake_event(struct dahdi_pvt *p, int mode)
16012 {
16013    if (p) {
16014       switch (mode) {
16015       case TRANSFER:
16016          p->fake_event = DAHDI_EVENT_WINKFLASH;
16017          break;
16018       case HANGUP:
16019          p->fake_event = DAHDI_EVENT_ONHOOK;
16020          break;
16021       default:
16022          ast_log(LOG_WARNING, "I don't know how to handle transfer event with this: %d on channel %s\n",mode, p->owner->name);
16023       }
16024    }
16025    return 0;
16026 }
16027 static struct dahdi_pvt *find_channel(int channel)
16028 {
16029    struct dahdi_pvt *p;
16030 
16031    ast_mutex_lock(&iflock);
16032    for (p = iflist; p; p = p->next) {
16033       if (p->channel == channel) {
16034          break;
16035       }
16036    }
16037    ast_mutex_unlock(&iflock);
16038    return p;
16039 }
16040 
16041 /*!
16042  * \internal
16043  * \brief Get private struct using given numeric channel string.
16044  *
16045  * \param channel Numeric channel number string get private struct.
16046  *
16047  * \retval pvt on success.
16048  * \retval NULL on error.
16049  */
16050 static struct dahdi_pvt *find_channel_from_str(const char *channel)
16051 {
16052    int chan_num;
16053 
16054    if (sscanf(channel, "%30d", &chan_num) != 1) {
16055       /* Not numeric string. */
16056       return NULL;
16057    }
16058 
16059    return find_channel(chan_num);
16060 }
16061 
16062 static int action_dahdidndon(struct mansession *s, const struct message *m)
16063 {
16064    struct dahdi_pvt *p;
16065    const char *channel = astman_get_header(m, "DAHDIChannel");
16066 
16067    if (ast_strlen_zero(channel)) {
16068       astman_send_error(s, m, "No channel specified");
16069       return 0;
16070    }
16071    p = find_channel_from_str(channel);
16072    if (!p) {
16073       astman_send_error(s, m, "No such channel");
16074       return 0;
16075    }
16076    dahdi_dnd(p, 1);
16077    astman_send_ack(s, m, "DND Enabled");
16078    return 0;
16079 }
16080 
16081 static int action_dahdidndoff(struct mansession *s, const struct message *m)
16082 {
16083    struct dahdi_pvt *p;
16084    const char *channel = astman_get_header(m, "DAHDIChannel");
16085 
16086    if (ast_strlen_zero(channel)) {
16087       astman_send_error(s, m, "No channel specified");
16088       return 0;
16089    }
16090    p = find_channel_from_str(channel);
16091    if (!p) {
16092       astman_send_error(s, m, "No such channel");
16093       return 0;
16094    }
16095    dahdi_dnd(p, 0);
16096    astman_send_ack(s, m, "DND Disabled");
16097    return 0;
16098 }
16099 
16100 static int action_transfer(struct mansession *s, const struct message *m)
16101 {
16102    struct dahdi_pvt *p;
16103    const char *channel = astman_get_header(m, "DAHDIChannel");
16104 
16105    if (ast_strlen_zero(channel)) {
16106       astman_send_error(s, m, "No channel specified");
16107       return 0;
16108    }
16109    p = find_channel_from_str(channel);
16110    if (!p) {
16111       astman_send_error(s, m, "No such channel");
16112       return 0;
16113    }
16114    if (!analog_lib_handles(p->sig, 0, 0)) {
16115       astman_send_error(s, m, "Channel signaling is not analog");
16116       return 0;
16117    }
16118    dahdi_fake_event(p,TRANSFER);
16119    astman_send_ack(s, m, "DAHDITransfer");
16120    return 0;
16121 }
16122 
16123 static int action_transferhangup(struct mansession *s, const struct message *m)
16124 {
16125    struct dahdi_pvt *p;
16126    const char *channel = astman_get_header(m, "DAHDIChannel");
16127 
16128    if (ast_strlen_zero(channel)) {
16129       astman_send_error(s, m, "No channel specified");
16130       return 0;
16131    }
16132    p = find_channel_from_str(channel);
16133    if (!p) {
16134       astman_send_error(s, m, "No such channel");
16135       return 0;
16136    }
16137    if (!analog_lib_handles(p->sig, 0, 0)) {
16138       astman_send_error(s, m, "Channel signaling is not analog");
16139       return 0;
16140    }
16141    dahdi_fake_event(p,HANGUP);
16142    astman_send_ack(s, m, "DAHDIHangup");
16143    return 0;
16144 }
16145 
16146 static int action_dahdidialoffhook(struct mansession *s, const struct message *m)
16147 {
16148    struct dahdi_pvt *p;
16149    const char *channel = astman_get_header(m, "DAHDIChannel");
16150    const char *number = astman_get_header(m, "Number");
16151    int i;
16152 
16153    if (ast_strlen_zero(channel)) {
16154       astman_send_error(s, m, "No channel specified");
16155       return 0;
16156    }
16157    if (ast_strlen_zero(number)) {
16158       astman_send_error(s, m, "No number specified");
16159       return 0;
16160    }
16161    p = find_channel_from_str(channel);
16162    if (!p) {
16163       astman_send_error(s, m, "No such channel");
16164       return 0;
16165    }
16166    if (!p->owner) {
16167       astman_send_error(s, m, "Channel does not have it's owner");
16168       return 0;
16169    }
16170    for (i = 0; i < strlen(number); i++) {
16171       struct ast_frame f = { AST_FRAME_DTMF, .subclass.integer = number[i] };
16172       dahdi_queue_frame(p, &f);
16173    }
16174    astman_send_ack(s, m, "DAHDIDialOffhook");
16175    return 0;
16176 }
16177 
16178 static int action_dahdishowchannels(struct mansession *s, const struct message *m)
16179 {
16180    struct dahdi_pvt *tmp = NULL;
16181    const char *id = astman_get_header(m, "ActionID");
16182    const char *dahdichannel = astman_get_header(m, "DAHDIChannel");
16183    char idText[256] = "";
16184    int channels = 0;
16185    int dahdichanquery;
16186 
16187    if (!dahdichannel || sscanf(dahdichannel, "%30d", &dahdichanquery) != 1) {
16188       /* Not numeric string. */
16189       dahdichanquery = -1;
16190    }
16191 
16192    astman_send_ack(s, m, "DAHDI channel status will follow");
16193    if (!ast_strlen_zero(id))
16194       snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
16195 
16196    ast_mutex_lock(&iflock);
16197 
16198    for (tmp = iflist; tmp; tmp = tmp->next) {
16199       if (tmp->channel > 0) {
16200          int alm;
16201 
16202          /* If a specific channel is queried for, only deliver status for that channel */
16203          if (dahdichanquery > 0 && tmp->channel != dahdichanquery)
16204             continue;
16205 
16206          alm = get_alarms(tmp);
16207          channels++;
16208          if (tmp->owner) {
16209             /* Add data if we have a current call */
16210             astman_append(s,
16211                "Event: DAHDIShowChannels\r\n"
16212                "DAHDIChannel: %d\r\n"
16213                "Channel: %s\r\n"
16214                "Uniqueid: %s\r\n"
16215                "AccountCode: %s\r\n"
16216                "Signalling: %s\r\n"
16217                "SignallingCode: %d\r\n"
16218                "Context: %s\r\n"
16219                "DND: %s\r\n"
16220                "Alarm: %s\r\n"
16221                "%s"
16222                "\r\n",
16223                tmp->channel,
16224                tmp->owner->name,
16225                tmp->owner->uniqueid,
16226                tmp->owner->accountcode,
16227                sig2str(tmp->sig),
16228                tmp->sig,
16229                tmp->context,
16230                dahdi_dnd(tmp, -1) ? "Enabled" : "Disabled",
16231                alarm2str(alm), idText);
16232          } else {
16233             astman_append(s,
16234                "Event: DAHDIShowChannels\r\n"
16235                "DAHDIChannel: %d\r\n"
16236                "Signalling: %s\r\n"
16237                "SignallingCode: %d\r\n"
16238                "Context: %s\r\n"
16239                "DND: %s\r\n"
16240                "Alarm: %s\r\n"
16241                "%s"
16242                "\r\n",
16243                tmp->channel, sig2str(tmp->sig), tmp->sig,
16244                tmp->context,
16245                dahdi_dnd(tmp, -1) ? "Enabled" : "Disabled",
16246                alarm2str(alm), idText);
16247          }
16248       }
16249    }
16250 
16251    ast_mutex_unlock(&iflock);
16252 
16253    astman_append(s,
16254       "Event: DAHDIShowChannelsComplete\r\n"
16255       "%s"
16256       "Items: %d\r\n"
16257       "\r\n",
16258       idText,
16259       channels);
16260    return 0;
16261 }
16262 
16263 #if defined(HAVE_SS7)
16264 static int linkset_addsigchan(int sigchan)
16265 {
16266    struct dahdi_ss7 *link;
16267    int res;
16268    int curfd;
16269    struct dahdi_params params;
16270    struct dahdi_bufferinfo bi;
16271    struct dahdi_spaninfo si;
16272 
16273    if (sigchan < 0) {
16274       ast_log(LOG_ERROR, "Invalid sigchan!\n");
16275       return -1;
16276    }
16277    if (cur_ss7type < 0) {
16278       ast_log(LOG_ERROR, "Unspecified or invalid ss7type\n");
16279       return -1;
16280    }
16281    if (cur_pointcode < 0) {
16282       ast_log(LOG_ERROR, "Unspecified pointcode!\n");
16283       return -1;
16284    }
16285    if (cur_adjpointcode < 0) {
16286       ast_log(LOG_ERROR, "Unspecified adjpointcode!\n");
16287       return -1;
16288    }
16289    if (cur_defaultdpc < 0) {
16290       ast_log(LOG_ERROR, "Unspecified defaultdpc!\n");
16291       return -1;
16292    }
16293    if (cur_networkindicator < 0) {
16294       ast_log(LOG_ERROR, "Invalid networkindicator!\n");
16295       return -1;
16296    }
16297    link = ss7_resolve_linkset(cur_linkset);
16298    if (!link) {
16299       ast_log(LOG_ERROR, "Invalid linkset number.  Must be between 1 and %d\n", NUM_SPANS + 1);
16300       return -1;
16301    }
16302    if (link->ss7.numsigchans >= SIG_SS7_NUM_DCHANS) {
16303       ast_log(LOG_ERROR, "Too many sigchans on linkset %d\n", cur_linkset);
16304       return -1;
16305    }
16306 
16307    curfd = link->ss7.numsigchans;
16308 
16309    /* Open signaling channel */
16310    link->ss7.fds[curfd] = open("/dev/dahdi/channel", O_RDWR, 0600);
16311    if (link->ss7.fds[curfd] < 0) {
16312       ast_log(LOG_ERROR, "Unable to open SS7 sigchan %d (%s)\n", sigchan,
16313          strerror(errno));
16314       return -1;
16315    }
16316    if (ioctl(link->ss7.fds[curfd], DAHDI_SPECIFY, &sigchan) == -1) {
16317       dahdi_close_ss7_fd(link, curfd);
16318       ast_log(LOG_ERROR, "Unable to specify SS7 sigchan %d (%s)\n", sigchan,
16319          strerror(errno));
16320       return -1;
16321    }
16322 
16323    /* Get signaling channel parameters */
16324    memset(&params, 0, sizeof(params));
16325    res = ioctl(link->ss7.fds[curfd], DAHDI_GET_PARAMS, &params);
16326    if (res) {
16327       dahdi_close_ss7_fd(link, curfd);
16328       ast_log(LOG_ERROR, "Unable to get parameters for sigchan %d (%s)\n", sigchan,
16329          strerror(errno));
16330       return -1;
16331    }
16332    if (params.sigtype != DAHDI_SIG_HDLCFCS
16333       && params.sigtype != DAHDI_SIG_HARDHDLC
16334       && params.sigtype != DAHDI_SIG_MTP2) {
16335       dahdi_close_ss7_fd(link, curfd);
16336       ast_log(LOG_ERROR, "sigchan %d is not in HDLC/FCS mode.\n", sigchan);
16337       return -1;
16338    }
16339 
16340    /* Set signaling channel buffer policy. */
16341    memset(&bi, 0, sizeof(bi));
16342    bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
16343    bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
16344    bi.numbufs = 32;
16345    bi.bufsize = 512;
16346    if (ioctl(link->ss7.fds[curfd], DAHDI_SET_BUFINFO, &bi)) {
16347       ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n",
16348          sigchan, strerror(errno));
16349       dahdi_close_ss7_fd(link, curfd);
16350       return -1;
16351    }
16352 
16353    /* Get current signaling channel alarm status. */
16354    memset(&si, 0, sizeof(si));
16355    res = ioctl(link->ss7.fds[curfd], DAHDI_SPANSTAT, &si);
16356    if (res) {
16357       dahdi_close_ss7_fd(link, curfd);
16358       ast_log(LOG_ERROR, "Unable to get span state for sigchan %d (%s)\n", sigchan,
16359          strerror(errno));
16360    }
16361 
16362    res = sig_ss7_add_sigchan(&link->ss7, curfd, cur_ss7type,
16363       (params.sigtype == DAHDI_SIG_MTP2)
16364          ? SS7_TRANSPORT_DAHDIMTP2
16365          : SS7_TRANSPORT_DAHDIDCHAN,
16366       si.alarms, cur_networkindicator, cur_pointcode, cur_adjpointcode);
16367    if (res) {
16368       dahdi_close_ss7_fd(link, curfd);
16369       return -1;
16370    }
16371 
16372    ++link->ss7.numsigchans;
16373 
16374    return 0;
16375 }
16376 #endif   /* defined(HAVE_SS7) */
16377 
16378 #if defined(HAVE_SS7)
16379 static char *handle_ss7_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16380 {
16381    int span;
16382    switch (cmd) {
16383    case CLI_INIT:
16384       e->command = "ss7 set debug {on|off} linkset";
16385       e->usage =
16386          "Usage: ss7 set debug {on|off} linkset <linkset>\n"
16387          "       Enables debugging on a given SS7 linkset\n";
16388       return NULL;
16389    case CLI_GENERATE:
16390       return NULL;
16391    }
16392    if (a->argc < 6)
16393       return CLI_SHOWUSAGE;
16394    span = atoi(a->argv[5]);
16395    if ((span < 1) || (span > NUM_SPANS)) {
16396       ast_cli(a->fd, "Invalid linkset %s.  Should be a number from %d to %d\n", a->argv[5], 1, NUM_SPANS);
16397       return CLI_SUCCESS;
16398    }
16399    if (!linksets[span-1].ss7.ss7) {
16400       ast_cli(a->fd, "No SS7 running on linkset %d\n", span);
16401    } else {
16402       if (!strcasecmp(a->argv[3], "on")) {
16403          linksets[span - 1].ss7.debug = 1;
16404          ss7_set_debug(linksets[span-1].ss7.ss7, SIG_SS7_DEBUG);
16405          ast_cli(a->fd, "Enabled debugging on linkset %d\n", span);
16406       } else {
16407          linksets[span - 1].ss7.debug = 0;
16408          ss7_set_debug(linksets[span-1].ss7.ss7, 0);
16409          ast_cli(a->fd, "Disabled debugging on linkset %d\n", span);
16410       }
16411    }
16412 
16413    return CLI_SUCCESS;
16414 }
16415 #endif   /* defined(HAVE_SS7) */
16416 
16417 #if defined(HAVE_SS7)
16418 static char *handle_ss7_block_cic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16419 {
16420    int linkset, cic;
16421    int blocked = -1, i;
16422    switch (cmd) {
16423    case CLI_INIT:
16424       e->command = "ss7 block cic";
16425       e->usage =
16426          "Usage: ss7 block cic <linkset> <CIC>\n"
16427          "       Sends a remote blocking request for the given CIC on the specified linkset\n";
16428       return NULL;
16429    case CLI_GENERATE:
16430       return NULL;
16431    }
16432    if (a->argc == 5)
16433       linkset = atoi(a->argv[3]);
16434    else
16435       return CLI_SHOWUSAGE;
16436 
16437    if ((linkset < 1) || (linkset > NUM_SPANS)) {
16438       ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16439       return CLI_SUCCESS;
16440    }
16441 
16442    if (!linksets[linkset-1].ss7.ss7) {
16443       ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16444       return CLI_SUCCESS;
16445    }
16446 
16447    cic = atoi(a->argv[4]);
16448 
16449    if (cic < 1) {
16450       ast_cli(a->fd, "Invalid CIC specified!\n");
16451       return CLI_SUCCESS;
16452    }
16453 
16454    for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
16455       if (linksets[linkset-1].ss7.pvts[i]->cic == cic) {
16456          blocked = linksets[linkset-1].ss7.pvts[i]->locallyblocked;
16457          if (!blocked) {
16458             ast_mutex_lock(&linksets[linkset-1].ss7.lock);
16459             isup_blo(linksets[linkset-1].ss7.ss7, cic, linksets[linkset-1].ss7.pvts[i]->dpc);
16460             ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
16461          }
16462       }
16463    }
16464 
16465    if (blocked < 0) {
16466       ast_cli(a->fd, "Invalid CIC specified!\n");
16467       return CLI_SUCCESS;
16468    }
16469 
16470    if (!blocked)
16471       ast_cli(a->fd, "Sent blocking request for linkset %d on CIC %d\n", linkset, cic);
16472    else
16473       ast_cli(a->fd, "CIC %d already locally blocked\n", cic);
16474 
16475    /* Break poll on the linkset so it sends our messages */
16476    pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
16477 
16478    return CLI_SUCCESS;
16479 }
16480 #endif   /* defined(HAVE_SS7) */
16481 
16482 #if defined(HAVE_SS7)
16483 static char *handle_ss7_block_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16484 {
16485    int linkset;
16486    int i;
16487    switch (cmd) {
16488    case CLI_INIT:
16489       e->command = "ss7 block linkset";
16490       e->usage =
16491          "Usage: ss7 block linkset <linkset number>\n"
16492          "       Sends a remote blocking request for all CICs on the given linkset\n";
16493       return NULL;
16494    case CLI_GENERATE:
16495       return NULL;
16496    }
16497    if (a->argc == 4)
16498       linkset = atoi(a->argv[3]);
16499    else
16500       return CLI_SHOWUSAGE;
16501 
16502    if ((linkset < 1) || (linkset > NUM_SPANS)) {
16503       ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16504       return CLI_SUCCESS;
16505    }
16506 
16507    if (!linksets[linkset-1].ss7.ss7) {
16508       ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16509       return CLI_SUCCESS;
16510    }
16511 
16512    for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
16513       ast_cli(a->fd, "Sending remote blocking request on CIC %d\n", linksets[linkset-1].ss7.pvts[i]->cic);
16514       ast_mutex_lock(&linksets[linkset-1].ss7.lock);
16515       isup_blo(linksets[linkset-1].ss7.ss7, linksets[linkset-1].ss7.pvts[i]->cic, linksets[linkset-1].ss7.pvts[i]->dpc);
16516       ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
16517    }
16518 
16519    /* Break poll on the linkset so it sends our messages */
16520    pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
16521 
16522    return CLI_SUCCESS;
16523 }
16524 #endif   /* defined(HAVE_SS7) */
16525 
16526 #if defined(HAVE_SS7)
16527 static char *handle_ss7_unblock_cic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16528 {
16529    int linkset, cic;
16530    int i, blocked = -1;
16531    switch (cmd) {
16532    case CLI_INIT:
16533       e->command = "ss7 unblock cic";
16534       e->usage =
16535          "Usage: ss7 unblock cic <linkset> <CIC>\n"
16536          "       Sends a remote unblocking request for the given CIC on the specified linkset\n";
16537       return NULL;
16538    case CLI_GENERATE:
16539       return NULL;
16540    }
16541 
16542    if (a->argc == 5)
16543       linkset = atoi(a->argv[3]);
16544    else
16545       return CLI_SHOWUSAGE;
16546 
16547    if ((linkset < 1) || (linkset > NUM_SPANS)) {
16548       ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16549       return CLI_SUCCESS;
16550    }
16551 
16552    if (!linksets[linkset-1].ss7.ss7) {
16553       ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16554       return CLI_SUCCESS;
16555    }
16556 
16557    cic = atoi(a->argv[4]);
16558 
16559    if (cic < 1) {
16560       ast_cli(a->fd, "Invalid CIC specified!\n");
16561       return CLI_SUCCESS;
16562    }
16563 
16564    for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
16565       if (linksets[linkset-1].ss7.pvts[i]->cic == cic) {
16566          blocked = linksets[linkset-1].ss7.pvts[i]->locallyblocked;
16567          if (blocked) {
16568             ast_mutex_lock(&linksets[linkset-1].ss7.lock);
16569             isup_ubl(linksets[linkset-1].ss7.ss7, cic, linksets[linkset-1].ss7.pvts[i]->dpc);
16570             ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
16571          }
16572       }
16573    }
16574 
16575    if (blocked > 0)
16576       ast_cli(a->fd, "Sent unblocking request for linkset %d on CIC %d\n", linkset, cic);
16577 
16578    /* Break poll on the linkset so it sends our messages */
16579    pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
16580 
16581    return CLI_SUCCESS;
16582 }
16583 #endif   /* defined(HAVE_SS7) */
16584 
16585 #if defined(HAVE_SS7)
16586 static char *handle_ss7_unblock_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16587 {
16588    int linkset;
16589    int i;
16590    switch (cmd) {
16591    case CLI_INIT:
16592       e->command = "ss7 unblock linkset";
16593       e->usage =
16594          "Usage: ss7 unblock linkset <linkset number>\n"
16595          "       Sends a remote unblocking request for all CICs on the specified linkset\n";
16596       return NULL;
16597    case CLI_GENERATE:
16598       return NULL;
16599    }
16600 
16601    if (a->argc == 4)
16602       linkset = atoi(a->argv[3]);
16603    else
16604       return CLI_SHOWUSAGE;
16605 
16606    if ((linkset < 1) || (linkset > NUM_SPANS)) {
16607       ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16608       return CLI_SUCCESS;
16609    }
16610 
16611    if (!linksets[linkset-1].ss7.ss7) {
16612       ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16613       return CLI_SUCCESS;
16614    }
16615 
16616    for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
16617       ast_cli(a->fd, "Sending remote unblock request on CIC %d\n", linksets[linkset-1].ss7.pvts[i]->cic);
16618       ast_mutex_lock(&linksets[linkset-1].ss7.lock);
16619       isup_ubl(linksets[linkset-1].ss7.ss7, linksets[linkset-1].ss7.pvts[i]->cic, linksets[linkset-1].ss7.pvts[i]->dpc);
16620       ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
16621    }
16622 
16623    /* Break poll on the linkset so it sends our messages */
16624    pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
16625 
16626    return CLI_SUCCESS;
16627 }
16628 #endif   /* defined(HAVE_SS7) */
16629 
16630 #if defined(HAVE_SS7)
16631 static char *handle_ss7_show_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16632 {
16633    int linkset;
16634    struct sig_ss7_linkset *ss7;
16635    switch (cmd) {
16636    case CLI_INIT:
16637       e->command = "ss7 show linkset";
16638       e->usage =
16639          "Usage: ss7 show linkset <span>\n"
16640          "       Shows the status of an SS7 linkset.\n";
16641       return NULL;
16642    case CLI_GENERATE:
16643       return NULL;
16644    }
16645 
16646    if (a->argc < 4)
16647       return CLI_SHOWUSAGE;
16648    linkset = atoi(a->argv[3]);
16649    if ((linkset < 1) || (linkset > NUM_SPANS)) {
16650       ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16651       return CLI_SUCCESS;
16652    }
16653    ss7 = &linksets[linkset - 1].ss7;
16654    if (!ss7->ss7) {
16655       ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16656       return CLI_SUCCESS;
16657    }
16658 
16659    ast_cli(a->fd, "SS7 linkset %d status: %s\n", linkset, (ss7->state == LINKSET_STATE_UP) ? "Up" : "Down");
16660 
16661    return CLI_SUCCESS;
16662 }
16663 #endif   /* defined(HAVE_SS7) */
16664 
16665 #if defined(HAVE_SS7)
16666 static char *handle_ss7_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16667 {
16668    int linkset;
16669 
16670    switch (cmd) {
16671    case CLI_INIT:
16672       e->command = "ss7 show channels";
16673       e->usage =
16674          "Usage: ss7 show channels\n"
16675          "       Displays SS7 channel information at a glance.\n";
16676       return NULL;
16677    case CLI_GENERATE:
16678       return NULL;
16679    }
16680 
16681    if (a->argc != 3)
16682       return CLI_SHOWUSAGE;
16683 
16684    sig_ss7_cli_show_channels_header(a->fd);
16685    for (linkset = 0; linkset < NUM_SPANS; ++linkset) {
16686       if (linksets[linkset].ss7.ss7) {
16687          sig_ss7_cli_show_channels(a->fd, &linksets[linkset].ss7);
16688       }
16689    }
16690    return CLI_SUCCESS;
16691 }
16692 #endif   /* defined(HAVE_SS7) */
16693 
16694 #if defined(HAVE_SS7)
16695 static char *handle_ss7_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16696 {
16697    switch (cmd) {
16698    case CLI_INIT:
16699       e->command = "ss7 show version";
16700       e->usage =
16701          "Usage: ss7 show version\n"
16702          "  Show the libss7 version\n";
16703       return NULL;
16704    case CLI_GENERATE:
16705       return NULL;
16706    }
16707 
16708    ast_cli(a->fd, "libss7 version: %s\n", ss7_get_version());
16709 
16710    return CLI_SUCCESS;
16711 }
16712 #endif   /* defined(HAVE_SS7) */
16713 
16714 #if defined(HAVE_SS7)
16715 static struct ast_cli_entry dahdi_ss7_cli[] = {
16716    AST_CLI_DEFINE(handle_ss7_debug, "Enables SS7 debugging on a linkset"),
16717    AST_CLI_DEFINE(handle_ss7_block_cic, "Blocks the given CIC"),
16718    AST_CLI_DEFINE(handle_ss7_unblock_cic, "Unblocks the given CIC"),
16719    AST_CLI_DEFINE(handle_ss7_block_linkset, "Blocks all CICs on a linkset"),
16720    AST_CLI_DEFINE(handle_ss7_unblock_linkset, "Unblocks all CICs on a linkset"),
16721    AST_CLI_DEFINE(handle_ss7_show_linkset, "Shows the status of a linkset"),
16722    AST_CLI_DEFINE(handle_ss7_show_channels, "Displays SS7 channel information"),
16723    AST_CLI_DEFINE(handle_ss7_version, "Displays libss7 version"),
16724 };
16725 #endif   /* defined(HAVE_SS7) */
16726 
16727 #if defined(HAVE_PRI)
16728 #if defined(HAVE_PRI_CCSS)
16729 /*!
16730  * \internal
16731  * \brief CC agent initialization.
16732  * \since 1.8
16733  *
16734  * \param agent CC core agent control.
16735  * \param chan Original channel the agent will attempt to recall.
16736  *
16737  * \details
16738  * This callback is called when the CC core is initialized.  Agents should allocate
16739  * any private data necessary for the call and assign it to the private_data
16740  * on the agent.  Additionally, if any ast_cc_agent_flags are pertinent to the
16741  * specific agent type, they should be set in this function as well.
16742  *
16743  * \retval 0 on success.
16744  * \retval -1 on error.
16745  */
16746 static int dahdi_pri_cc_agent_init(struct ast_cc_agent *agent, struct ast_channel *chan)
16747 {
16748    struct dahdi_pvt *pvt;
16749    struct sig_pri_chan *pvt_chan;
16750    int res;
16751 
16752    ast_assert(!strcmp(chan->tech->type, "DAHDI"));
16753 
16754    pvt = chan->tech_pvt;
16755    if (dahdi_sig_pri_lib_handles(pvt->sig)) {
16756       pvt_chan = pvt->sig_pvt;
16757    } else {
16758       pvt_chan = NULL;
16759    }
16760    if (!pvt_chan) {
16761       return -1;
16762    }
16763 
16764    ast_module_ref(ast_module_info->self);
16765 
16766    res = sig_pri_cc_agent_init(agent, pvt_chan);
16767    if (res) {
16768       ast_module_unref(ast_module_info->self);
16769    }
16770    return res;
16771 }
16772 #endif   /* defined(HAVE_PRI_CCSS) */
16773 #endif   /* defined(HAVE_PRI) */
16774 
16775 #if defined(HAVE_PRI)
16776 #if defined(HAVE_PRI_CCSS)
16777 /*!
16778  * \internal
16779  * \brief Destroy private data on the agent.
16780  * \since 1.8
16781  *
16782  * \param agent CC core agent control.
16783  *
16784  * \details
16785  * The core will call this function upon completion
16786  * or failure of CC.
16787  *
16788  * \return Nothing
16789  */
16790 static void dahdi_pri_cc_agent_destructor(struct ast_cc_agent *agent)
16791 {
16792    sig_pri_cc_agent_destructor(agent);
16793 
16794    ast_module_unref(ast_module_info->self);
16795 }
16796 #endif   /* defined(HAVE_PRI_CCSS) */
16797 #endif   /* defined(HAVE_PRI) */
16798 
16799 #if defined(HAVE_PRI)
16800 #if defined(HAVE_PRI_CCSS)
16801 static struct ast_cc_agent_callbacks dahdi_pri_cc_agent_callbacks = {
16802    .type = dahdi_pri_cc_type,
16803    .init = dahdi_pri_cc_agent_init,
16804    .start_offer_timer = sig_pri_cc_agent_start_offer_timer,
16805    .stop_offer_timer = sig_pri_cc_agent_stop_offer_timer,
16806    .respond = sig_pri_cc_agent_req_rsp,
16807    .status_request = sig_pri_cc_agent_status_req,
16808    .stop_ringing = sig_pri_cc_agent_stop_ringing,
16809    .party_b_free = sig_pri_cc_agent_party_b_free,
16810    .start_monitoring = sig_pri_cc_agent_start_monitoring,
16811    .callee_available = sig_pri_cc_agent_callee_available,
16812    .destructor = dahdi_pri_cc_agent_destructor,
16813 };
16814 #endif   /* defined(HAVE_PRI_CCSS) */
16815 #endif   /* defined(HAVE_PRI) */
16816 
16817 #if defined(HAVE_PRI)
16818 #if defined(HAVE_PRI_CCSS)
16819 static struct ast_cc_monitor_callbacks dahdi_pri_cc_monitor_callbacks = {
16820    .type = dahdi_pri_cc_type,
16821    .request_cc = sig_pri_cc_monitor_req_cc,
16822    .suspend = sig_pri_cc_monitor_suspend,
16823    .unsuspend = sig_pri_cc_monitor_unsuspend,
16824    .status_response = sig_pri_cc_monitor_status_rsp,
16825    .cancel_available_timer = sig_pri_cc_monitor_cancel_available_timer,
16826    .destructor = sig_pri_cc_monitor_destructor,
16827 };
16828 #endif   /* defined(HAVE_PRI_CCSS) */
16829 #endif   /* defined(HAVE_PRI) */
16830 
16831 static int __unload_module(void)
16832 {
16833    struct dahdi_pvt *p;
16834 #if defined(HAVE_PRI) || defined(HAVE_SS7)
16835    int i, j;
16836 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
16837 
16838 #ifdef HAVE_PRI
16839    for (i = 0; i < NUM_SPANS; i++) {
16840       if (pris[i].pri.master != AST_PTHREADT_NULL) {
16841          pthread_cancel(pris[i].pri.master);
16842          pthread_kill(pris[i].pri.master, SIGURG);
16843       }
16844    }
16845    ast_cli_unregister_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
16846    ast_unregister_application(dahdi_send_keypad_facility_app);
16847 #ifdef HAVE_PRI_PROG_W_CAUSE
16848    ast_unregister_application(dahdi_send_callrerouting_facility_app);
16849 #endif
16850 #endif
16851 #if defined(HAVE_SS7)
16852    for (i = 0; i < NUM_SPANS; i++) {
16853       if (linksets[i].ss7.master != AST_PTHREADT_NULL) {
16854          pthread_cancel(linksets[i].ss7.master);
16855          pthread_kill(linksets[i].ss7.master, SIGURG);
16856       }
16857    }
16858    ast_cli_unregister_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
16859 #endif   /* defined(HAVE_SS7) */
16860 #if defined(HAVE_OPENR2)
16861    dahdi_r2_destroy_links();
16862    ast_cli_unregister_multiple(dahdi_mfcr2_cli, ARRAY_LEN(dahdi_mfcr2_cli));
16863    ast_unregister_application(dahdi_accept_r2_call_app);
16864 #endif
16865 
16866    ast_cli_unregister_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli));
16867    ast_manager_unregister("DAHDIDialOffhook");
16868    ast_manager_unregister("DAHDIHangup");
16869    ast_manager_unregister("DAHDITransfer");
16870    ast_manager_unregister("DAHDIDNDoff");
16871    ast_manager_unregister("DAHDIDNDon");
16872    ast_manager_unregister("DAHDIShowChannels");
16873    ast_manager_unregister("DAHDIRestart");
16874    ast_data_unregister(NULL);
16875    ast_channel_unregister(&dahdi_tech);
16876 
16877    /* Hangup all interfaces if they have an owner */
16878    ast_mutex_lock(&iflock);
16879    for (p = iflist; p; p = p->next) {
16880       if (p->owner)
16881          ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
16882    }
16883    ast_mutex_unlock(&iflock);
16884 
16885    ast_mutex_lock(&monlock);
16886    if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
16887       pthread_cancel(monitor_thread);
16888       pthread_kill(monitor_thread, SIGURG);
16889       pthread_join(monitor_thread, NULL);
16890    }
16891    monitor_thread = AST_PTHREADT_STOP;
16892    ast_mutex_unlock(&monlock);
16893 
16894    destroy_all_channels();
16895 
16896 #if defined(HAVE_PRI)
16897    for (i = 0; i < NUM_SPANS; i++) {
16898       if (pris[i].pri.master && (pris[i].pri.master != AST_PTHREADT_NULL)) {
16899          pthread_join(pris[i].pri.master, NULL);
16900       }
16901       for (j = 0; j < SIG_PRI_NUM_DCHANS; j++) {
16902          dahdi_close_pri_fd(&(pris[i]), j);
16903       }
16904       sig_pri_stop_pri(&pris[i].pri);
16905    }
16906 #if defined(HAVE_PRI_CCSS)
16907    ast_cc_agent_unregister(&dahdi_pri_cc_agent_callbacks);
16908    ast_cc_monitor_unregister(&dahdi_pri_cc_monitor_callbacks);
16909 #endif   /* defined(HAVE_PRI_CCSS) */
16910    sig_pri_unload();
16911 #endif
16912 
16913 #if defined(HAVE_SS7)
16914    for (i = 0; i < NUM_SPANS; i++) {
16915       if (linksets[i].ss7.master && (linksets[i].ss7.master != AST_PTHREADT_NULL)) {
16916          pthread_join(linksets[i].ss7.master, NULL);
16917       }
16918       for (j = 0; j < SIG_SS7_NUM_DCHANS; j++) {
16919          dahdi_close_ss7_fd(&(linksets[i]), j);
16920       }
16921    }
16922 #endif   /* defined(HAVE_SS7) */
16923    ast_cond_destroy(&ss_thread_complete);
16924    return 0;
16925 }
16926 
16927 static int unload_module(void)
16928 {
16929 #if defined(HAVE_PRI) || defined(HAVE_SS7)
16930    int y;
16931 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
16932 #ifdef HAVE_PRI
16933    for (y = 0; y < NUM_SPANS; y++)
16934       ast_mutex_destroy(&pris[y].pri.lock);
16935 #endif
16936 #if defined(HAVE_SS7)
16937    for (y = 0; y < NUM_SPANS; y++)
16938       ast_mutex_destroy(&linksets[y].ss7.lock);
16939 #endif   /* defined(HAVE_SS7) */
16940    return __unload_module();
16941 }
16942 
16943 static void string_replace(char *str, int char1, int char2)
16944 {
16945    for (; *str; str++) {
16946       if (*str == char1) {
16947          *str = char2;
16948       }
16949    }
16950 }
16951 
16952 static char *parse_spanchan(char *chanstr, char **subdir)
16953 {
16954    char *p;
16955 
16956    if ((p = strrchr(chanstr, '!')) == NULL) {
16957       *subdir = NULL;
16958       return chanstr;
16959    }
16960    *p++ = '\0';
16961    string_replace(chanstr, '!', '/');
16962    *subdir = chanstr;
16963    return p;
16964 }
16965 
16966 static int build_channels(struct dahdi_chan_conf *conf, const char *value, int reload, int lineno, int *found_pseudo)
16967 {
16968    char *c, *chan;
16969    char *subdir;
16970    int x, start, finish;
16971    struct dahdi_pvt *tmp;
16972 
16973    if ((reload == 0) && (conf->chan.sig < 0) && !conf->is_sig_auto) {
16974       ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n");
16975       return -1;
16976    }
16977 
16978    c = ast_strdupa(value);
16979    c = parse_spanchan(c, &subdir);
16980 
16981    while ((chan = strsep(&c, ","))) {
16982       if (sscanf(chan, "%30d-%30d", &start, &finish) == 2) {
16983          /* Range */
16984       } else if (sscanf(chan, "%30d", &start)) {
16985          /* Just one */
16986          finish = start;
16987       } else if (!strcasecmp(chan, "pseudo")) {
16988          finish = start = CHAN_PSEUDO;
16989          if (found_pseudo)
16990             *found_pseudo = 1;
16991       } else {
16992          ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan);
16993          return -1;
16994       }
16995       if (finish < start) {
16996          ast_log(LOG_WARNING, "Sillyness: %d < %d\n", start, finish);
16997          x = finish;
16998          finish = start;
16999          start = x;
17000       }
17001 
17002       for (x = start; x <= finish; x++) {
17003          char fn[PATH_MAX];
17004          int real_channel = x;
17005 
17006          if (!ast_strlen_zero(subdir)) {
17007             real_channel = device2chan(subdir, x, fn, sizeof(fn));
17008             if (real_channel < 0) {
17009                if (conf->ignore_failed_channels) {
17010                   ast_log(LOG_WARNING, "Failed configuring %s!%d, (got %d). But moving on to others.\n",
17011                         subdir, x, real_channel);
17012                   continue;
17013                } else {
17014                   ast_log(LOG_ERROR, "Failed configuring %s!%d, (got %d).\n",
17015                         subdir, x, real_channel);
17016                   return -1;
17017                }
17018             }
17019          }
17020          tmp = mkintf(real_channel, conf, reload);
17021 
17022          if (tmp) {
17023             ast_verb(3, "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", real_channel, sig2str(tmp->sig));
17024          } else {
17025             ast_log(LOG_ERROR, "Unable to %s channel '%s'\n",
17026                   (reload == 1) ? "reconfigure" : "register", value);
17027             return -1;
17028          }
17029       }
17030    }
17031 
17032    return 0;
17033 }
17034 
17035 /** The length of the parameters list of 'dahdichan'.
17036  * \todo Move definition of MAX_CHANLIST_LEN to a proper place. */
17037 #define MAX_CHANLIST_LEN 80
17038 
17039 static void process_echocancel(struct dahdi_chan_conf *confp, const char *data, unsigned int line)
17040 {
17041    char *parse = ast_strdupa(data);
17042    char *params[DAHDI_MAX_ECHOCANPARAMS + 1];
17043    unsigned int param_count;
17044    unsigned int x;
17045 
17046    if (!(param_count = ast_app_separate_args(parse, ',', params, ARRAY_LEN(params))))
17047       return;
17048 
17049    memset(&confp->chan.echocancel, 0, sizeof(confp->chan.echocancel));
17050 
17051    /* first parameter is tap length, process it here */
17052 
17053    x = ast_strlen_zero(params[0]) ? 0 : atoi(params[0]);
17054 
17055    if ((x == 32) || (x == 64) || (x == 128) || (x == 256) || (x == 512) || (x == 1024))
17056       confp->chan.echocancel.head.tap_length = x;
17057    else if ((confp->chan.echocancel.head.tap_length = ast_true(params[0])))
17058       confp->chan.echocancel.head.tap_length = 128;
17059 
17060    /* now process any remaining parameters */
17061 
17062    for (x = 1; x < param_count; x++) {
17063       struct {
17064          char *name;
17065          char *value;
17066       } param;
17067 
17068       if (ast_app_separate_args(params[x], '=', (char **) &param, 2) < 1) {
17069          ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %u: '%s'\n", line, params[x]);
17070          continue;
17071       }
17072 
17073       if (ast_strlen_zero(param.name) || (strlen(param.name) > sizeof(confp->chan.echocancel.params[0].name)-1)) {
17074          ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %u: '%s'\n", line, param.name);
17075          continue;
17076       }
17077 
17078       strcpy(confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].name, param.name);
17079 
17080       if (param.value) {
17081          if (sscanf(param.value, "%30d", &confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].value) != 1) {
17082             ast_log(LOG_WARNING, "Invalid echocancel parameter value supplied at line %u: '%s'\n", line, param.value);
17083             continue;
17084          }
17085       }
17086       confp->chan.echocancel.head.param_count++;
17087    }
17088 }
17089 
17090 /*! process_dahdi() - ignore keyword 'channel' and similar */
17091 #define PROC_DAHDI_OPT_NOCHAN  (1 << 0)
17092 /*! process_dahdi() - No warnings on non-existing cofiguration keywords */
17093 #define PROC_DAHDI_OPT_NOWARN  (1 << 1)
17094 
17095 static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct ast_variable *v, int reload, int options)
17096 {
17097    struct dahdi_pvt *tmp;
17098    int y;
17099    int found_pseudo = 0;
17100    struct ast_variable *dahdichan = NULL;
17101 
17102    for (; v; v = v->next) {
17103       if (!ast_jb_read_conf(&global_jbconf, v->name, v->value))
17104          continue;
17105 
17106       /* Create the interface list */
17107       if (!strcasecmp(v->name, "channel") || !strcasecmp(v->name, "channels")) {
17108          if (options & PROC_DAHDI_OPT_NOCHAN) {
17109             ast_log(LOG_WARNING, "Channel '%s' ignored.\n", v->value);
17110             continue;
17111          }
17112          if (build_channels(confp, v->value, reload, v->lineno, &found_pseudo)) {
17113             if (confp->ignore_failed_channels) {
17114                ast_log(LOG_WARNING, "Channel '%s' failure ignored: ignore_failed_channels.\n", v->value);
17115                continue;
17116             } else {
17117                return -1;
17118             }
17119          }
17120          ast_log(LOG_DEBUG, "Channel '%s' configured.\n", v->value);
17121       } else if (!strcasecmp(v->name, "ignore_failed_channels")) {
17122          confp->ignore_failed_channels = ast_true(v->value);
17123       } else if (!strcasecmp(v->name, "buffers")) {
17124          if (parse_buffers_policy(v->value, &confp->chan.buf_no, &confp->chan.buf_policy)) {
17125             ast_log(LOG_WARNING, "Using default buffer policy.\n");
17126             confp->chan.buf_no = numbufs;
17127             confp->chan.buf_policy = DAHDI_POLICY_IMMEDIATE;
17128          }
17129       } else if (!strcasecmp(v->name, "faxbuffers")) {
17130          if (!parse_buffers_policy(v->value, &confp->chan.faxbuf_no, &confp->chan.faxbuf_policy)) {
17131             confp->chan.usefaxbuffers = 1;
17132          }
17133       } else if (!strcasecmp(v->name, "dahdichan")) {
17134          /* Only process the last dahdichan value. */
17135          dahdichan = v;
17136       } else if (!strcasecmp(v->name, "usedistinctiveringdetection")) {
17137          usedistinctiveringdetection = ast_true(v->value);
17138       } else if (!strcasecmp(v->name, "distinctiveringaftercid")) {
17139          distinctiveringaftercid = ast_true(v->value);
17140       } else if (!strcasecmp(v->name, "dring1context")) {
17141          ast_copy_string(confp->chan.drings.ringContext[0].contextData,v->value,sizeof(confp->chan.drings.ringContext[0].contextData));
17142       } else if (!strcasecmp(v->name, "dring2context")) {
17143          ast_copy_string(confp->chan.drings.ringContext[1].contextData,v->value,sizeof(confp->chan.drings.ringContext[1].contextData));
17144       } else if (!strcasecmp(v->name, "dring3context")) {
17145          ast_copy_string(confp->chan.drings.ringContext[2].contextData,v->value,sizeof(confp->chan.drings.ringContext[2].contextData));
17146       } else if (!strcasecmp(v->name, "dring1range")) {
17147          confp->chan.drings.ringnum[0].range = atoi(v->value);
17148       } else if (!strcasecmp(v->name, "dring2range")) {
17149          confp->chan.drings.ringnum[1].range = atoi(v->value);
17150       } else if (!strcasecmp(v->name, "dring3range")) {
17151          confp->chan.drings.ringnum[2].range = atoi(v->value);
17152       } else if (!strcasecmp(v->name, "dring1")) {
17153          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]);
17154       } else if (!strcasecmp(v->name, "dring2")) {
17155          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]);
17156       } else if (!strcasecmp(v->name, "dring3")) {
17157          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]);
17158       } else if (!strcasecmp(v->name, "usecallerid")) {
17159          confp->chan.use_callerid = ast_true(v->value);
17160       } else if (!strcasecmp(v->name, "cidsignalling")) {
17161          if (!strcasecmp(v->value, "bell"))
17162             confp->chan.cid_signalling = CID_SIG_BELL;
17163          else if (!strcasecmp(v->value, "v23"))
17164             confp->chan.cid_signalling = CID_SIG_V23;
17165          else if (!strcasecmp(v->value, "dtmf"))
17166             confp->chan.cid_signalling = CID_SIG_DTMF;
17167          else if (!strcasecmp(v->value, "smdi"))
17168             confp->chan.cid_signalling = CID_SIG_SMDI;
17169          else if (!strcasecmp(v->value, "v23_jp"))
17170             confp->chan.cid_signalling = CID_SIG_V23_JP;
17171          else if (ast_true(v->value))
17172             confp->chan.cid_signalling = CID_SIG_BELL;
17173       } else if (!strcasecmp(v->name, "cidstart")) {
17174          if (!strcasecmp(v->value, "ring"))
17175             confp->chan.cid_start = CID_START_RING;
17176          else if (!strcasecmp(v->value, "polarity_in"))
17177             confp->chan.cid_start = CID_START_POLARITY_IN;
17178          else if (!strcasecmp(v->value, "polarity"))
17179             confp->chan.cid_start = CID_START_POLARITY;
17180          else if (!strcasecmp(v->value, "dtmf"))
17181             confp->chan.cid_start = CID_START_DTMF_NOALERT;
17182          else if (ast_true(v->value))
17183             confp->chan.cid_start = CID_START_RING;
17184       } else if (!strcasecmp(v->name, "threewaycalling")) {
17185          confp->chan.threewaycalling = ast_true(v->value);
17186       } else if (!strcasecmp(v->name, "cancallforward")) {
17187          confp->chan.cancallforward = ast_true(v->value);
17188       } else if (!strcasecmp(v->name, "relaxdtmf")) {
17189          if (ast_true(v->value))
17190             confp->chan.dtmfrelax = DSP_DIGITMODE_RELAXDTMF;
17191          else
17192             confp->chan.dtmfrelax = 0;
17193       } else if (!strcasecmp(v->name, "mailbox")) {
17194          ast_copy_string(confp->chan.mailbox, v->value, sizeof(confp->chan.mailbox));
17195       } else if (!strcasecmp(v->name, "hasvoicemail")) {
17196          if (ast_true(v->value) && ast_strlen_zero(confp->chan.mailbox)) {
17197             ast_copy_string(confp->chan.mailbox, cat, sizeof(confp->chan.mailbox));
17198          }
17199       } else if (!strcasecmp(v->name, "adsi")) {
17200          confp->chan.adsi = ast_true(v->value);
17201       } else if (!strcasecmp(v->name, "usesmdi")) {
17202          confp->chan.use_smdi = ast_true(v->value);
17203       } else if (!strcasecmp(v->name, "smdiport")) {
17204          ast_copy_string(confp->smdi_port, v->value, sizeof(confp->smdi_port));
17205       } else if (!strcasecmp(v->name, "transfer")) {
17206          confp->chan.transfer = ast_true(v->value);
17207       } else if (!strcasecmp(v->name, "canpark")) {
17208          confp->chan.canpark = ast_true(v->value);
17209       } else if (!strcasecmp(v->name, "echocancelwhenbridged")) {
17210          confp->chan.echocanbridged = ast_true(v->value);
17211       } else if (!strcasecmp(v->name, "busydetect")) {
17212          confp->chan.busydetect = ast_true(v->value);
17213       } else if (!strcasecmp(v->name, "busycount")) {
17214          confp->chan.busycount = atoi(v->value);
17215       } else if (!strcasecmp(v->name, "busypattern")) {
17216          if (sscanf(v->value, "%30d,%30d", &confp->chan.busy_tonelength, &confp->chan.busy_quietlength) != 2) {
17217             ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength,quietlength at line %d.\n", v->lineno);
17218          }
17219       } else if (!strcasecmp(v->name, "callprogress")) {
17220          confp->chan.callprogress &= ~CALLPROGRESS_PROGRESS;
17221          if (ast_true(v->value))
17222             confp->chan.callprogress |= CALLPROGRESS_PROGRESS;
17223       } else if (!strcasecmp(v->name, "waitfordialtone")) {
17224          confp->chan.waitfordialtone = atoi(v->value);
17225       } else if (!strcasecmp(v->name, "faxdetect")) {
17226          confp->chan.callprogress &= ~CALLPROGRESS_FAX;
17227          if (!strcasecmp(v->value, "incoming")) {
17228             confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING;
17229          } else if (!strcasecmp(v->value, "outgoing")) {
17230             confp->chan.callprogress |= CALLPROGRESS_FAX_OUTGOING;
17231          } else if (!strcasecmp(v->value, "both") || ast_true(v->value))
17232             confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING;
17233       } else if (!strcasecmp(v->name, "echocancel")) {
17234          process_echocancel(confp, v->value, v->lineno);
17235       } else if (!strcasecmp(v->name, "echotraining")) {
17236          if (sscanf(v->value, "%30d", &y) == 1) {
17237             if ((y < 10) || (y > 4000)) {
17238                ast_log(LOG_WARNING, "Echo training time must be within the range of 10 to 4000 ms at line %d.\n", v->lineno);
17239             } else {
17240                confp->chan.echotraining = y;
17241             }
17242          } else if (ast_true(v->value)) {
17243             confp->chan.echotraining = 400;
17244          } else
17245             confp->chan.echotraining = 0;
17246       } else if (!strcasecmp(v->name, "hidecallerid")) {
17247          confp->chan.hidecallerid = ast_true(v->value);
17248       } else if (!strcasecmp(v->name, "hidecalleridname")) {
17249          confp->chan.hidecalleridname = ast_true(v->value);
17250       } else if (!strcasecmp(v->name, "pulsedial")) {
17251          confp->chan.pulse = ast_true(v->value);
17252       } else if (!strcasecmp(v->name, "callreturn")) {
17253          confp->chan.callreturn = ast_true(v->value);
17254       } else if (!strcasecmp(v->name, "callwaiting")) {
17255          confp->chan.callwaiting = ast_true(v->value);
17256       } else if (!strcasecmp(v->name, "callwaitingcallerid")) {
17257          confp->chan.callwaitingcallerid = ast_true(v->value);
17258       } else if (!strcasecmp(v->name, "context")) {
17259          ast_copy_string(confp->chan.context, v->value, sizeof(confp->chan.context));
17260       } else if (!strcasecmp(v->name, "language")) {
17261          ast_copy_string(confp->chan.language, v->value, sizeof(confp->chan.language));
17262       } else if (!strcasecmp(v->name, "progzone")) {
17263          ast_copy_string(progzone, v->value, sizeof(progzone));
17264       } else if (!strcasecmp(v->name, "mohinterpret")
17265          ||!strcasecmp(v->name, "musiconhold") || !strcasecmp(v->name, "musicclass")) {
17266          ast_copy_string(confp->chan.mohinterpret, v->value, sizeof(confp->chan.mohinterpret));
17267       } else if (!strcasecmp(v->name, "mohsuggest")) {
17268          ast_copy_string(confp->chan.mohsuggest, v->value, sizeof(confp->chan.mohsuggest));
17269       } else if (!strcasecmp(v->name, "parkinglot")) {
17270          ast_copy_string(confp->chan.parkinglot, v->value, sizeof(confp->chan.parkinglot));
17271       } else if (!strcasecmp(v->name, "stripmsd")) {
17272          ast_log(LOG_NOTICE, "Configuration option \"%s\" has been deprecated. Please use dialplan instead\n", v->name);
17273          confp->chan.stripmsd = atoi(v->value);
17274       } else if (!strcasecmp(v->name, "jitterbuffers")) {
17275          numbufs = atoi(v->value);
17276       } else if (!strcasecmp(v->name, "group")) {
17277          confp->chan.group = ast_get_group(v->value);
17278       } else if (!strcasecmp(v->name, "callgroup")) {
17279          if (!strcasecmp(v->value, "none"))
17280             confp->chan.callgroup = 0;
17281          else
17282             confp->chan.callgroup = ast_get_group(v->value);
17283       } else if (!strcasecmp(v->name, "pickupgroup")) {
17284          if (!strcasecmp(v->value, "none"))
17285             confp->chan.pickupgroup = 0;
17286          else
17287             confp->chan.pickupgroup = ast_get_group(v->value);
17288       } else if (!strcasecmp(v->name, "setvar")) {
17289          char *varname = ast_strdupa(v->value), *varval = NULL;
17290          struct ast_variable *tmpvar;
17291          if (varname && (varval = strchr(varname, '='))) {
17292             *varval++ = '\0';
17293             if ((tmpvar = ast_variable_new(varname, varval, ""))) {
17294                tmpvar->next = confp->chan.vars;
17295                confp->chan.vars = tmpvar;
17296             }
17297          }
17298       } else if (!strcasecmp(v->name, "immediate")) {
17299          confp->chan.immediate = ast_true(v->value);
17300       } else if (!strcasecmp(v->name, "transfertobusy")) {
17301          confp->chan.transfertobusy = ast_true(v->value);
17302       } else if (!strcasecmp(v->name, "mwimonitor")) {
17303          confp->chan.mwimonitor_neon = 0;
17304          confp->chan.mwimonitor_fsk = 0;
17305          confp->chan.mwimonitor_rpas = 0;
17306          if (strcasestr(v->value, "fsk")) {
17307             confp->chan.mwimonitor_fsk = 1;
17308          }
17309          if (strcasestr(v->value, "rpas")) {
17310             confp->chan.mwimonitor_rpas = 1;
17311          }
17312          if (strcasestr(v->value, "neon")) {
17313             confp->chan.mwimonitor_neon = 1;
17314          }
17315          /* If set to true or yes, assume that simple fsk is desired */
17316          if (ast_true(v->value)) {
17317             confp->chan.mwimonitor_fsk = 1;
17318          }
17319       } else if (!strcasecmp(v->name, "cid_rxgain")) {
17320          if (sscanf(v->value, "%30f", &confp->chan.cid_rxgain) != 1) {
17321             ast_log(LOG_WARNING, "Invalid cid_rxgain: %s at line %d.\n", v->value, v->lineno);
17322          }
17323       } else if (!strcasecmp(v->name, "rxgain")) {
17324          if (sscanf(v->value, "%30f", &confp->chan.rxgain) != 1) {
17325             ast_log(LOG_WARNING, "Invalid rxgain: %s at line %d.\n", v->value, v->lineno);
17326          }
17327       } else if (!strcasecmp(v->name, "txgain")) {
17328          if (sscanf(v->value, "%30f", &confp->chan.txgain) != 1) {
17329             ast_log(LOG_WARNING, "Invalid txgain: %s at line %d.\n", v->value, v->lineno);
17330          }
17331       } else if (!strcasecmp(v->name, "txdrc")) {
17332          if (sscanf(v->value, "%f", &confp->chan.txdrc) != 1) {
17333             ast_log(LOG_WARNING, "Invalid txdrc: %s\n", v->value);
17334          }
17335       } else if (!strcasecmp(v->name, "rxdrc")) {
17336          if (sscanf(v->value, "%f", &confp->chan.rxdrc) != 1) {
17337             ast_log(LOG_WARNING, "Invalid rxdrc: %s\n", v->value);
17338          }
17339       } else if (!strcasecmp(v->name, "tonezone")) {
17340          if (sscanf(v->value, "%30d", &confp->chan.tonezone) != 1) {
17341             ast_log(LOG_WARNING, "Invalid tonezone: %s at line %d.\n", v->value, v->lineno);
17342          }
17343       } else if (!strcasecmp(v->name, "callerid")) {
17344          if (!strcasecmp(v->value, "asreceived")) {
17345             confp->chan.cid_num[0] = '\0';
17346             confp->chan.cid_name[0] = '\0';
17347          } else {
17348             ast_callerid_split(v->value, confp->chan.cid_name, sizeof(confp->chan.cid_name), confp->chan.cid_num, sizeof(confp->chan.cid_num));
17349          }
17350       } else if (!strcasecmp(v->name, "fullname")) {
17351          ast_copy_string(confp->chan.cid_name, v->value, sizeof(confp->chan.cid_name));
17352       } else if (!strcasecmp(v->name, "cid_number")) {
17353          ast_copy_string(confp->chan.cid_num, v->value, sizeof(confp->chan.cid_num));
17354       } else if (!strcasecmp(v->name, "cid_tag")) {
17355          ast_copy_string(confp->chan.cid_tag, v->value, sizeof(confp->chan.cid_tag));
17356       } else if (!strcasecmp(v->name, "useincomingcalleridondahditransfer")) {
17357          confp->chan.dahditrcallerid = ast_true(v->value);
17358       } else if (!strcasecmp(v->name, "restrictcid")) {
17359          confp->chan.restrictcid = ast_true(v->value);
17360       } else if (!strcasecmp(v->name, "usecallingpres")) {
17361          confp->chan.use_callingpres = ast_true(v->value);
17362       } else if (!strcasecmp(v->name, "accountcode")) {
17363          ast_copy_string(confp->chan.accountcode, v->value, sizeof(confp->chan.accountcode));
17364       } else if (!strcasecmp(v->name, "amaflags")) {
17365          y = ast_cdr_amaflags2int(v->value);
17366          if (y < 0)
17367             ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d.\n", v->value, v->lineno);
17368          else
17369             confp->chan.amaflags = y;
17370       } else if (!strcasecmp(v->name, "polarityonanswerdelay")) {
17371          confp->chan.polarityonanswerdelay = atoi(v->value);
17372       } else if (!strcasecmp(v->name, "answeronpolarityswitch")) {
17373          confp->chan.answeronpolarityswitch = ast_true(v->value);
17374       } else if (!strcasecmp(v->name, "hanguponpolarityswitch")) {
17375          confp->chan.hanguponpolarityswitch = ast_true(v->value);
17376       } else if (!strcasecmp(v->name, "sendcalleridafter")) {
17377          confp->chan.sendcalleridafter = atoi(v->value);
17378       } else if (!strcasecmp(v->name, "mwimonitornotify")) {
17379          ast_copy_string(mwimonitornotify, v->value, sizeof(mwimonitornotify));
17380       } else if (ast_cc_is_config_param(v->name)) {
17381          ast_cc_set_param(confp->chan.cc_params, v->name, v->value);
17382       } else if (!strcasecmp(v->name, "mwisendtype")) {
17383 #ifndef HAVE_DAHDI_LINEREVERSE_VMWI  /* backward compatibility for older dahdi VMWI implementation */
17384          if (!strcasecmp(v->value, "rpas")) { /* Ring Pulse Alert Signal */
17385             mwisend_rpas = 1;
17386          } else {
17387             mwisend_rpas = 0;
17388          }
17389 #else
17390          /* Default is fsk, to turn it off you must specify nofsk */
17391          memset(&confp->chan.mwisend_setting, 0, sizeof(confp->chan.mwisend_setting));
17392          if (strcasestr(v->value, "nofsk")) {      /* NoFSK */
17393             confp->chan.mwisend_fsk = 0;
17394          } else {             /* Default FSK */
17395             confp->chan.mwisend_fsk = 1;
17396          }
17397          if (strcasestr(v->value, "rpas")) {       /* Ring Pulse Alert Signal, normally followed by FSK */
17398             confp->chan.mwisend_rpas = 1;
17399          } else {
17400             confp->chan.mwisend_rpas = 0;
17401          }
17402          if (strcasestr(v->value, "lrev")) {       /* Line Reversal */
17403             confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_LREV;
17404          }
17405          if (strcasestr(v->value, "hvdc")) {       /* HV 90VDC */
17406             confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_HVDC;
17407          }
17408          if ( (strcasestr(v->value, "neon")) || (strcasestr(v->value, "hvac")) ){   /* 90V DC pulses */
17409             confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_HVAC;
17410          }
17411 #endif
17412       } else if (reload != 1) {
17413           if (!strcasecmp(v->name, "signalling") || !strcasecmp(v->name, "signaling")) {
17414             int orig_radio = confp->chan.radio;
17415             int orig_outsigmod = confp->chan.outsigmod;
17416             int orig_auto = confp->is_sig_auto;
17417 
17418             confp->chan.radio = 0;
17419             confp->chan.outsigmod = -1;
17420             confp->is_sig_auto = 0;
17421             if (!strcasecmp(v->value, "em")) {
17422                confp->chan.sig = SIG_EM;
17423             } else if (!strcasecmp(v->value, "em_e1")) {
17424                confp->chan.sig = SIG_EM_E1;
17425             } else if (!strcasecmp(v->value, "em_w")) {
17426                confp->chan.sig = SIG_EMWINK;
17427             } else if (!strcasecmp(v->value, "fxs_ls")) {
17428                confp->chan.sig = SIG_FXSLS;
17429             } else if (!strcasecmp(v->value, "fxs_gs")) {
17430                confp->chan.sig = SIG_FXSGS;
17431             } else if (!strcasecmp(v->value, "fxs_ks")) {
17432                confp->chan.sig = SIG_FXSKS;
17433             } else if (!strcasecmp(v->value, "fxo_ls")) {
17434                confp->chan.sig = SIG_FXOLS;
17435             } else if (!strcasecmp(v->value, "fxo_gs")) {
17436                confp->chan.sig = SIG_FXOGS;
17437             } else if (!strcasecmp(v->value, "fxo_ks")) {
17438                confp->chan.sig = SIG_FXOKS;
17439             } else if (!strcasecmp(v->value, "fxs_rx")) {
17440                confp->chan.sig = SIG_FXSKS;
17441                confp->chan.radio = 1;
17442             } else if (!strcasecmp(v->value, "fxo_rx")) {
17443                confp->chan.sig = SIG_FXOLS;
17444                confp->chan.radio = 1;
17445             } else if (!strcasecmp(v->value, "fxs_tx")) {
17446                confp->chan.sig = SIG_FXSLS;
17447                confp->chan.radio = 1;
17448             } else if (!strcasecmp(v->value, "fxo_tx")) {
17449                confp->chan.sig = SIG_FXOGS;
17450                confp->chan.radio = 1;
17451             } else if (!strcasecmp(v->value, "em_rx")) {
17452                confp->chan.sig = SIG_EM;
17453                confp->chan.radio = 1;
17454             } else if (!strcasecmp(v->value, "em_tx")) {
17455                confp->chan.sig = SIG_EM;
17456                confp->chan.radio = 1;
17457             } else if (!strcasecmp(v->value, "em_rxtx")) {
17458                confp->chan.sig = SIG_EM;
17459                confp->chan.radio = 2;
17460             } else if (!strcasecmp(v->value, "em_txrx")) {
17461                confp->chan.sig = SIG_EM;
17462                confp->chan.radio = 2;
17463             } else if (!strcasecmp(v->value, "sf")) {
17464                confp->chan.sig = SIG_SF;
17465             } else if (!strcasecmp(v->value, "sf_w")) {
17466                confp->chan.sig = SIG_SFWINK;
17467             } else if (!strcasecmp(v->value, "sf_featd")) {
17468                confp->chan.sig = SIG_FEATD;
17469             } else if (!strcasecmp(v->value, "sf_featdmf")) {
17470                confp->chan.sig = SIG_FEATDMF;
17471             } else if (!strcasecmp(v->value, "sf_featb")) {
17472                confp->chan.sig = SIG_SF_FEATB;
17473             } else if (!strcasecmp(v->value, "sf")) {
17474                confp->chan.sig = SIG_SF;
17475             } else if (!strcasecmp(v->value, "sf_rx")) {
17476                confp->chan.sig = SIG_SF;
17477                confp->chan.radio = 1;
17478             } else if (!strcasecmp(v->value, "sf_tx")) {
17479                confp->chan.sig = SIG_SF;
17480                confp->chan.radio = 1;
17481             } else if (!strcasecmp(v->value, "sf_rxtx")) {
17482                confp->chan.sig = SIG_SF;
17483                confp->chan.radio = 2;
17484             } else if (!strcasecmp(v->value, "sf_txrx")) {
17485                confp->chan.sig = SIG_SF;
17486                confp->chan.radio = 2;
17487             } else if (!strcasecmp(v->value, "featd")) {
17488                confp->chan.sig = SIG_FEATD;
17489             } else if (!strcasecmp(v->value, "featdmf")) {
17490                confp->chan.sig = SIG_FEATDMF;
17491             } else if (!strcasecmp(v->value, "featdmf_ta")) {
17492                confp->chan.sig = SIG_FEATDMF_TA;
17493             } else if (!strcasecmp(v->value, "e911")) {
17494                confp->chan.sig = SIG_E911;
17495             } else if (!strcasecmp(v->value, "fgccama")) {
17496                confp->chan.sig = SIG_FGC_CAMA;
17497             } else if (!strcasecmp(v->value, "fgccamamf")) {
17498                confp->chan.sig = SIG_FGC_CAMAMF;
17499             } else if (!strcasecmp(v->value, "featb")) {
17500                confp->chan.sig = SIG_FEATB;
17501 #ifdef HAVE_PRI
17502             } else if (!strcasecmp(v->value, "pri_net")) {
17503                confp->chan.sig = SIG_PRI;
17504                confp->pri.pri.nodetype = PRI_NETWORK;
17505             } else if (!strcasecmp(v->value, "pri_cpe")) {
17506                confp->chan.sig = SIG_PRI;
17507                confp->pri.pri.nodetype = PRI_CPE;
17508             } else if (!strcasecmp(v->value, "bri_cpe")) {
17509                confp->chan.sig = SIG_BRI;
17510                confp->pri.pri.nodetype = PRI_CPE;
17511             } else if (!strcasecmp(v->value, "bri_net")) {
17512                confp->chan.sig = SIG_BRI;
17513                confp->pri.pri.nodetype = PRI_NETWORK;
17514             } else if (!strcasecmp(v->value, "bri_cpe_ptmp")) {
17515                confp->chan.sig = SIG_BRI_PTMP;
17516                confp->pri.pri.nodetype = PRI_CPE;
17517             } else if (!strcasecmp(v->value, "bri_net_ptmp")) {
17518 #if defined(HAVE_PRI_CALL_HOLD)
17519                confp->chan.sig = SIG_BRI_PTMP;
17520                confp->pri.pri.nodetype = PRI_NETWORK;
17521 #else
17522                ast_log(LOG_WARNING, "How cool would it be if someone implemented this mode!  For now, sucks for you. (line %d)\n", v->lineno);
17523 #endif   /* !defined(HAVE_PRI_CALL_HOLD) */
17524 #endif
17525 #if defined(HAVE_SS7)
17526             } else if (!strcasecmp(v->value, "ss7")) {
17527                confp->chan.sig = SIG_SS7;
17528 #endif   /* defined(HAVE_SS7) */
17529 #ifdef HAVE_OPENR2
17530             } else if (!strcasecmp(v->value, "mfcr2")) {
17531                confp->chan.sig = SIG_MFCR2;
17532 #endif
17533             } else if (!strcasecmp(v->value, "auto")) {
17534                confp->is_sig_auto = 1;
17535             } else {
17536                confp->chan.outsigmod = orig_outsigmod;
17537                confp->chan.radio = orig_radio;
17538                confp->is_sig_auto = orig_auto;
17539                ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
17540             }
17541           } else if (!strcasecmp(v->name, "outsignalling") || !strcasecmp(v->name, "outsignaling")) {
17542             if (!strcasecmp(v->value, "em")) {
17543                confp->chan.outsigmod = SIG_EM;
17544             } else if (!strcasecmp(v->value, "em_e1")) {
17545                confp->chan.outsigmod = SIG_EM_E1;
17546             } else if (!strcasecmp(v->value, "em_w")) {
17547                confp->chan.outsigmod = SIG_EMWINK;
17548             } else if (!strcasecmp(v->value, "sf")) {
17549                confp->chan.outsigmod = SIG_SF;
17550             } else if (!strcasecmp(v->value, "sf_w")) {
17551                confp->chan.outsigmod = SIG_SFWINK;
17552             } else if (!strcasecmp(v->value, "sf_featd")) {
17553                confp->chan.outsigmod = SIG_FEATD;
17554             } else if (!strcasecmp(v->value, "sf_featdmf")) {
17555                confp->chan.outsigmod = SIG_FEATDMF;
17556             } else if (!strcasecmp(v->value, "sf_featb")) {
17557                confp->chan.outsigmod = SIG_SF_FEATB;
17558             } else if (!strcasecmp(v->value, "sf")) {
17559                confp->chan.outsigmod = SIG_SF;
17560             } else if (!strcasecmp(v->value, "featd")) {
17561                confp->chan.outsigmod = SIG_FEATD;
17562             } else if (!strcasecmp(v->value, "featdmf")) {
17563                confp->chan.outsigmod = SIG_FEATDMF;
17564             } else if (!strcasecmp(v->value, "featdmf_ta")) {
17565                confp->chan.outsigmod = SIG_FEATDMF_TA;
17566             } else if (!strcasecmp(v->value, "e911")) {
17567                confp->chan.outsigmod = SIG_E911;
17568             } else if (!strcasecmp(v->value, "fgccama")) {
17569                confp->chan.outsigmod = SIG_FGC_CAMA;
17570             } else if (!strcasecmp(v->value, "fgccamamf")) {
17571                confp->chan.outsigmod = SIG_FGC_CAMAMF;
17572             } else if (!strcasecmp(v->value, "featb")) {
17573                confp->chan.outsigmod = SIG_FEATB;
17574             } else {
17575                ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
17576             }
17577 #ifdef HAVE_PRI
17578          } else if (!strcasecmp(v->name, "pridialplan")) {
17579             if (!strcasecmp(v->value, "national")) {
17580                confp->pri.pri.dialplan = PRI_NATIONAL_ISDN + 1;
17581             } else if (!strcasecmp(v->value, "unknown")) {
17582                confp->pri.pri.dialplan = PRI_UNKNOWN + 1;
17583             } else if (!strcasecmp(v->value, "private")) {
17584                confp->pri.pri.dialplan = PRI_PRIVATE + 1;
17585             } else if (!strcasecmp(v->value, "international")) {
17586                confp->pri.pri.dialplan = PRI_INTERNATIONAL_ISDN + 1;
17587             } else if (!strcasecmp(v->value, "local")) {
17588                confp->pri.pri.dialplan = PRI_LOCAL_ISDN + 1;
17589             } else if (!strcasecmp(v->value, "dynamic")) {
17590                confp->pri.pri.dialplan = -1;
17591             } else if (!strcasecmp(v->value, "redundant")) {
17592                confp->pri.pri.dialplan = -2;
17593             } else {
17594                ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno);
17595             }
17596          } else if (!strcasecmp(v->name, "prilocaldialplan")) {
17597             if (!strcasecmp(v->value, "national")) {
17598                confp->pri.pri.localdialplan = PRI_NATIONAL_ISDN + 1;
17599             } else if (!strcasecmp(v->value, "unknown")) {
17600                confp->pri.pri.localdialplan = PRI_UNKNOWN + 1;
17601             } else if (!strcasecmp(v->value, "private")) {
17602                confp->pri.pri.localdialplan = PRI_PRIVATE + 1;
17603             } else if (!strcasecmp(v->value, "international")) {
17604                confp->pri.pri.localdialplan = PRI_INTERNATIONAL_ISDN + 1;
17605             } else if (!strcasecmp(v->value, "local")) {
17606                confp->pri.pri.localdialplan = PRI_LOCAL_ISDN + 1;
17607             } else if (!strcasecmp(v->value, "dynamic")) {
17608                confp->pri.pri.localdialplan = -1;
17609             } else if (!strcasecmp(v->value, "redundant")) {
17610                confp->pri.pri.localdialplan = -2;
17611             } else {
17612                ast_log(LOG_WARNING, "Unknown PRI localdialplan '%s' at line %d.\n", v->value, v->lineno);
17613             }
17614          } else if (!strcasecmp(v->name, "switchtype")) {
17615             if (!strcasecmp(v->value, "national"))
17616                confp->pri.pri.switchtype = PRI_SWITCH_NI2;
17617             else if (!strcasecmp(v->value, "ni1"))
17618                confp->pri.pri.switchtype = PRI_SWITCH_NI1;
17619             else if (!strcasecmp(v->value, "dms100"))
17620                confp->pri.pri.switchtype = PRI_SWITCH_DMS100;
17621             else if (!strcasecmp(v->value, "4ess"))
17622                confp->pri.pri.switchtype = PRI_SWITCH_ATT4ESS;
17623             else if (!strcasecmp(v->value, "5ess"))
17624                confp->pri.pri.switchtype = PRI_SWITCH_LUCENT5E;
17625             else if (!strcasecmp(v->value, "euroisdn"))
17626                confp->pri.pri.switchtype = PRI_SWITCH_EUROISDN_E1;
17627             else if (!strcasecmp(v->value, "qsig"))
17628                confp->pri.pri.switchtype = PRI_SWITCH_QSIG;
17629             else {
17630                ast_log(LOG_ERROR, "Unknown switchtype '%s' at line %d.\n", v->value, v->lineno);
17631                return -1;
17632             }
17633          } else if (!strcasecmp(v->name, "msn")) {
17634             ast_copy_string(confp->pri.pri.msn_list, v->value,
17635                sizeof(confp->pri.pri.msn_list));
17636          } else if (!strcasecmp(v->name, "nsf")) {
17637             if (!strcasecmp(v->value, "sdn"))
17638                confp->pri.pri.nsf = PRI_NSF_SDN;
17639             else if (!strcasecmp(v->value, "megacom"))
17640                confp->pri.pri.nsf = PRI_NSF_MEGACOM;
17641             else if (!strcasecmp(v->value, "tollfreemegacom"))
17642                confp->pri.pri.nsf = PRI_NSF_TOLL_FREE_MEGACOM;
17643             else if (!strcasecmp(v->value, "accunet"))
17644                confp->pri.pri.nsf = PRI_NSF_ACCUNET;
17645             else if (!strcasecmp(v->value, "none"))
17646                confp->pri.pri.nsf = PRI_NSF_NONE;
17647             else {
17648                ast_log(LOG_WARNING, "Unknown network-specific facility '%s' at line %d.\n", v->value, v->lineno);
17649                confp->pri.pri.nsf = PRI_NSF_NONE;
17650             }
17651          } else if (!strcasecmp(v->name, "priindication")) {
17652             if (!strcasecmp(v->value, "outofband"))
17653                confp->chan.priindication_oob = 1;
17654             else if (!strcasecmp(v->value, "inband"))
17655                confp->chan.priindication_oob = 0;
17656             else
17657                ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d.\n",
17658                   v->value, v->lineno);
17659          } else if (!strcasecmp(v->name, "priexclusive")) {
17660             confp->chan.priexclusive = ast_true(v->value);
17661          } else if (!strcasecmp(v->name, "internationalprefix")) {
17662             ast_copy_string(confp->pri.pri.internationalprefix, v->value, sizeof(confp->pri.pri.internationalprefix));
17663          } else if (!strcasecmp(v->name, "nationalprefix")) {
17664             ast_copy_string(confp->pri.pri.nationalprefix, v->value, sizeof(confp->pri.pri.nationalprefix));
17665          } else if (!strcasecmp(v->name, "localprefix")) {
17666             ast_copy_string(confp->pri.pri.localprefix, v->value, sizeof(confp->pri.pri.localprefix));
17667          } else if (!strcasecmp(v->name, "privateprefix")) {
17668             ast_copy_string(confp->pri.pri.privateprefix, v->value, sizeof(confp->pri.pri.privateprefix));
17669          } else if (!strcasecmp(v->name, "unknownprefix")) {
17670             ast_copy_string(confp->pri.pri.unknownprefix, v->value, sizeof(confp->pri.pri.unknownprefix));
17671          } else if (!strcasecmp(v->name, "resetinterval")) {
17672             if (!strcasecmp(v->value, "never"))
17673                confp->pri.pri.resetinterval = -1;
17674             else if (atoi(v->value) >= 60)
17675                confp->pri.pri.resetinterval = atoi(v->value);
17676             else
17677                ast_log(LOG_WARNING, "'%s' is not a valid reset interval, should be >= 60 seconds or 'never' at line %d.\n",
17678                   v->value, v->lineno);
17679          } else if (!strcasecmp(v->name, "minunused")) {
17680             confp->pri.pri.minunused = atoi(v->value);
17681          } else if (!strcasecmp(v->name, "minidle")) {
17682             confp->pri.pri.minidle = atoi(v->value);
17683          } else if (!strcasecmp(v->name, "idleext")) {
17684             ast_copy_string(confp->pri.pri.idleext, v->value, sizeof(confp->pri.pri.idleext));
17685          } else if (!strcasecmp(v->name, "idledial")) {
17686             ast_copy_string(confp->pri.pri.idledial, v->value, sizeof(confp->pri.pri.idledial));
17687          } else if (!strcasecmp(v->name, "overlapdial")) {
17688             if (ast_true(v->value)) {
17689                confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
17690             } else if (!strcasecmp(v->value, "incoming")) {
17691                confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_INCOMING;
17692             } else if (!strcasecmp(v->value, "outgoing")) {
17693                confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_OUTGOING;
17694             } else if (!strcasecmp(v->value, "both") || ast_true(v->value)) {
17695                confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
17696             } else {
17697                confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_NONE;
17698             }
17699 #ifdef HAVE_PRI_PROG_W_CAUSE
17700          } else if (!strcasecmp(v->name, "qsigchannelmapping")) {
17701             if (!strcasecmp(v->value, "logical")) {
17702                confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_LOGICAL;
17703             } else if (!strcasecmp(v->value, "physical")) {
17704                confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL;
17705             } else {
17706                confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL;
17707             }
17708 #endif
17709          } else if (!strcasecmp(v->name, "discardremoteholdretrieval")) {
17710             confp->pri.pri.discardremoteholdretrieval = ast_true(v->value);
17711 #if defined(HAVE_PRI_SERVICE_MESSAGES)
17712          } else if (!strcasecmp(v->name, "service_message_support")) {
17713             /* assuming switchtype for this channel group has been configured already */
17714             if ((confp->pri.pri.switchtype == PRI_SWITCH_ATT4ESS 
17715                || confp->pri.pri.switchtype == PRI_SWITCH_LUCENT5E
17716                || confp->pri.pri.switchtype == PRI_SWITCH_NI2) && ast_true(v->value)) {
17717                confp->pri.pri.enable_service_message_support = 1;
17718             } else {
17719                confp->pri.pri.enable_service_message_support = 0;
17720             }
17721 #endif   /* defined(HAVE_PRI_SERVICE_MESSAGES) */
17722 #ifdef HAVE_PRI_INBANDDISCONNECT
17723          } else if (!strcasecmp(v->name, "inbanddisconnect")) {
17724             confp->pri.pri.inbanddisconnect = ast_true(v->value);
17725 #endif
17726          } else if (!strcasecmp(v->name, "pritimer")) {
17727 #ifdef PRI_GETSET_TIMERS
17728             char tmp[20];
17729             char *timerc;
17730             char *c;
17731             int timer;
17732             int timeridx;
17733 
17734             ast_copy_string(tmp, v->value, sizeof(tmp));
17735             c = tmp;
17736             timerc = strsep(&c, ",");
17737             if (!ast_strlen_zero(timerc) && !ast_strlen_zero(c)) {
17738                timeridx = pri_timer2idx(timerc);
17739                timer = atoi(c);
17740                if (timeridx < 0 || PRI_MAX_TIMERS <= timeridx) {
17741                   ast_log(LOG_WARNING,
17742                      "'%s' is not a valid ISDN timer at line %d.\n", timerc,
17743                      v->lineno);
17744                } else if (!timer) {
17745                   ast_log(LOG_WARNING,
17746                      "'%s' is not a valid value for ISDN timer '%s' at line %d.\n",
17747                      c, timerc, v->lineno);
17748                } else {
17749                   confp->pri.pri.pritimers[timeridx] = timer;
17750                }
17751             } else {
17752                ast_log(LOG_WARNING,
17753                   "'%s' is not a valid ISDN timer configuration string at line %d.\n",
17754                   v->value, v->lineno);
17755             }
17756 #endif /* PRI_GETSET_TIMERS */
17757          } else if (!strcasecmp(v->name, "facilityenable")) {
17758             confp->pri.pri.facilityenable = ast_true(v->value);
17759 #if defined(HAVE_PRI_AOC_EVENTS)
17760          } else if (!strcasecmp(v->name, "aoc_enable")) {
17761             confp->pri.pri.aoc_passthrough_flag = 0;
17762             if (strchr(v->value, 's') || strchr(v->value, 'S')) {
17763                confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_S;
17764             }
17765             if (strchr(v->value, 'd') || strchr(v->value, 'D')) {
17766                confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_D;
17767             }
17768             if (strchr(v->value, 'e') || strchr(v->value, 'E')) {
17769                confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_E;
17770             }
17771          } else if (!strcasecmp(v->name, "aoce_delayhangup")) {
17772             confp->pri.pri.aoce_delayhangup = ast_true(v->value);
17773 #endif   /* defined(HAVE_PRI_AOC_EVENTS) */
17774 #if defined(HAVE_PRI_CALL_HOLD)
17775          } else if (!strcasecmp(v->name, "hold_disconnect_transfer")) {
17776             confp->pri.pri.hold_disconnect_transfer = ast_true(v->value);
17777 #endif   /* defined(HAVE_PRI_CALL_HOLD) */
17778 #if defined(HAVE_PRI_CCSS)
17779          } else if (!strcasecmp(v->name, "cc_ptmp_recall_mode")) {
17780             if (!strcasecmp(v->value, "global")) {
17781                confp->pri.pri.cc_ptmp_recall_mode = 0;/* globalRecall */
17782             } else if (!strcasecmp(v->value, "specific")) {
17783                confp->pri.pri.cc_ptmp_recall_mode = 1;/* specificRecall */
17784             } else {
17785                confp->pri.pri.cc_ptmp_recall_mode = 1;/* specificRecall */
17786             }
17787          } else if (!strcasecmp(v->name, "cc_qsig_signaling_link_req")) {
17788             if (!strcasecmp(v->value, "release")) {
17789                confp->pri.pri.cc_qsig_signaling_link_req = 0;/* release */
17790             } else if (!strcasecmp(v->value, "retain")) {
17791                confp->pri.pri.cc_qsig_signaling_link_req = 1;/* retain */
17792             } else if (!strcasecmp(v->value, "do_not_care")) {
17793                confp->pri.pri.cc_qsig_signaling_link_req = 2;/* do-not-care */
17794             } else {
17795                confp->pri.pri.cc_qsig_signaling_link_req = 1;/* retain */
17796             }
17797          } else if (!strcasecmp(v->name, "cc_qsig_signaling_link_rsp")) {
17798             if (!strcasecmp(v->value, "release")) {
17799                confp->pri.pri.cc_qsig_signaling_link_rsp = 0;/* release */
17800             } else if (!strcasecmp(v->value, "retain")) {
17801                confp->pri.pri.cc_qsig_signaling_link_rsp = 1;/* retain */
17802             } else {
17803                confp->pri.pri.cc_qsig_signaling_link_rsp = 1;/* retain */
17804             }
17805 #endif   /* defined(HAVE_PRI_CCSS) */
17806 #if defined(HAVE_PRI_CALL_WAITING)
17807          } else if (!strcasecmp(v->name, "max_call_waiting_calls")) {
17808             confp->pri.pri.max_call_waiting_calls = atoi(v->value);
17809             if (confp->pri.pri.max_call_waiting_calls < 0) {
17810                /* Negative values are not allowed. */
17811                confp->pri.pri.max_call_waiting_calls = 0;
17812             }
17813          } else if (!strcasecmp(v->name, "allow_call_waiting_calls")) {
17814             confp->pri.pri.allow_call_waiting_calls = ast_true(v->value);
17815 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
17816 #if defined(HAVE_PRI_MWI)
17817          } else if (!strcasecmp(v->name, "mwi_mailboxes")) {
17818             ast_copy_string(confp->pri.pri.mwi_mailboxes, v->value,
17819                sizeof(confp->pri.pri.mwi_mailboxes));
17820 #endif   /* defined(HAVE_PRI_MWI) */
17821          } else if (!strcasecmp(v->name, "append_msn_to_cid_tag")) {
17822             confp->pri.pri.append_msn_to_user_tag = ast_true(v->value);
17823          } else if (!strcasecmp(v->name, "inband_on_setup_ack")) {
17824             confp->pri.pri.inband_on_setup_ack = ast_true(v->value);
17825          } else if (!strcasecmp(v->name, "inband_on_proceeding")) {
17826             confp->pri.pri.inband_on_proceeding = ast_true(v->value);
17827          } else if (!strcasecmp(v->name, "layer1_presence")) {
17828             if (!strcasecmp(v->value, "required")) {
17829                confp->pri.pri.layer1_ignored = 0;
17830             } else if (!strcasecmp(v->value, "ignore")) {
17831                confp->pri.pri.layer1_ignored = 1;
17832             } else {
17833                /* Default */
17834                confp->pri.pri.layer1_ignored = 0;
17835             }
17836 #if defined(HAVE_PRI_L2_PERSISTENCE)
17837          } else if (!strcasecmp(v->name, "layer2_persistence")) {
17838             if (!strcasecmp(v->value, "keep_up")) {
17839                confp->pri.pri.l2_persistence = PRI_L2_PERSISTENCE_KEEP_UP;
17840             } else if (!strcasecmp(v->value, "leave_down")) {
17841                confp->pri.pri.l2_persistence = PRI_L2_PERSISTENCE_LEAVE_DOWN;
17842             } else {
17843                confp->pri.pri.l2_persistence = PRI_L2_PERSISTENCE_DEFAULT;
17844             }
17845 #endif   /* defined(HAVE_PRI_L2_PERSISTENCE) */
17846 #endif /* HAVE_PRI */
17847 #if defined(HAVE_SS7)
17848          } else if (!strcasecmp(v->name, "ss7type")) {
17849             if (!strcasecmp(v->value, "itu")) {
17850                cur_ss7type = SS7_ITU;
17851             } else if (!strcasecmp(v->value, "ansi")) {
17852                cur_ss7type = SS7_ANSI;
17853             } else
17854                ast_log(LOG_WARNING, "'%s' is an unknown ss7 switch type at line %d.!\n", v->value, v->lineno);
17855          } else if (!strcasecmp(v->name, "linkset")) {
17856             cur_linkset = atoi(v->value);
17857          } else if (!strcasecmp(v->name, "pointcode")) {
17858             cur_pointcode = parse_pointcode(v->value);
17859          } else if (!strcasecmp(v->name, "adjpointcode")) {
17860             cur_adjpointcode = parse_pointcode(v->value);
17861          } else if (!strcasecmp(v->name, "defaultdpc")) {
17862             cur_defaultdpc = parse_pointcode(v->value);
17863          } else if (!strcasecmp(v->name, "cicbeginswith")) {
17864             cur_cicbeginswith = atoi(v->value);
17865          } else if (!strcasecmp(v->name, "networkindicator")) {
17866             if (!strcasecmp(v->value, "national"))
17867                cur_networkindicator = SS7_NI_NAT;
17868             else if (!strcasecmp(v->value, "national_spare"))
17869                cur_networkindicator = SS7_NI_NAT_SPARE;
17870             else if (!strcasecmp(v->value, "international"))
17871                cur_networkindicator = SS7_NI_INT;
17872             else if (!strcasecmp(v->value, "international_spare"))
17873                cur_networkindicator = SS7_NI_INT_SPARE;
17874             else
17875                cur_networkindicator = -1;
17876          } else if (!strcasecmp(v->name, "ss7_internationalprefix")) {
17877             ast_copy_string(confp->ss7.ss7.internationalprefix, v->value, sizeof(confp->ss7.ss7.internationalprefix));
17878          } else if (!strcasecmp(v->name, "ss7_nationalprefix")) {
17879             ast_copy_string(confp->ss7.ss7.nationalprefix, v->value, sizeof(confp->ss7.ss7.nationalprefix));
17880          } else if (!strcasecmp(v->name, "ss7_subscriberprefix")) {
17881             ast_copy_string(confp->ss7.ss7.subscriberprefix, v->value, sizeof(confp->ss7.ss7.subscriberprefix));
17882          } else if (!strcasecmp(v->name, "ss7_unknownprefix")) {
17883             ast_copy_string(confp->ss7.ss7.unknownprefix, v->value, sizeof(confp->ss7.ss7.unknownprefix));
17884          } else if (!strcasecmp(v->name, "ss7_called_nai")) {
17885             if (!strcasecmp(v->value, "national")) {
17886                confp->ss7.ss7.called_nai = SS7_NAI_NATIONAL;
17887             } else if (!strcasecmp(v->value, "international")) {
17888                confp->ss7.ss7.called_nai = SS7_NAI_INTERNATIONAL;
17889             } else if (!strcasecmp(v->value, "subscriber")) {
17890                confp->ss7.ss7.called_nai = SS7_NAI_SUBSCRIBER;
17891             } else if (!strcasecmp(v->value, "unknown")) {
17892                confp->ss7.ss7.called_nai = SS7_NAI_UNKNOWN;
17893             } else if (!strcasecmp(v->value, "dynamic")) {
17894                confp->ss7.ss7.called_nai = SS7_NAI_DYNAMIC;
17895             } else {
17896                ast_log(LOG_WARNING, "Unknown SS7 called_nai '%s' at line %d.\n", v->value, v->lineno);
17897             }
17898          } else if (!strcasecmp(v->name, "ss7_calling_nai")) {
17899             if (!strcasecmp(v->value, "national")) {
17900                confp->ss7.ss7.calling_nai = SS7_NAI_NATIONAL;
17901             } else if (!strcasecmp(v->value, "international")) {
17902                confp->ss7.ss7.calling_nai = SS7_NAI_INTERNATIONAL;
17903             } else if (!strcasecmp(v->value, "subscriber")) {
17904                confp->ss7.ss7.calling_nai = SS7_NAI_SUBSCRIBER;
17905             } else if (!strcasecmp(v->value, "unknown")) {
17906                confp->ss7.ss7.calling_nai = SS7_NAI_UNKNOWN;
17907             } else if (!strcasecmp(v->value, "dynamic")) {
17908                confp->ss7.ss7.calling_nai = SS7_NAI_DYNAMIC;
17909             } else {
17910                ast_log(LOG_WARNING, "Unknown SS7 calling_nai '%s' at line %d.\n", v->value, v->lineno);
17911             }
17912          } else if (!strcasecmp(v->name, "sigchan")) {
17913             int sigchan, res;
17914             sigchan = atoi(v->value);
17915             res = linkset_addsigchan(sigchan);
17916             if (res < 0)
17917                return -1;
17918 
17919          } else if (!strcasecmp(v->name, "ss7_explicitacm")) {
17920             struct dahdi_ss7 *link;
17921             link = ss7_resolve_linkset(cur_linkset);
17922             if (!link) {
17923                ast_log(LOG_ERROR, "Invalid linkset number.  Must be between 1 and %d\n", NUM_SPANS + 1);
17924                return -1;
17925             }
17926             if (ast_true(v->value))
17927                link->ss7.flags |= LINKSET_FLAG_EXPLICITACM;
17928 #endif   /* defined(HAVE_SS7) */
17929 #ifdef HAVE_OPENR2
17930          } else if (!strcasecmp(v->name, "mfcr2_advanced_protocol_file")) {
17931             ast_copy_string(confp->mfcr2.r2proto_file, v->value, sizeof(confp->mfcr2.r2proto_file));
17932             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);
17933          } else if (!strcasecmp(v->name, "mfcr2_logdir")) {
17934             ast_copy_string(confp->mfcr2.logdir, v->value, sizeof(confp->mfcr2.logdir));
17935          } else if (!strcasecmp(v->name, "mfcr2_variant")) {
17936             confp->mfcr2.variant = openr2_proto_get_variant(v->value);
17937             if (OR2_VAR_UNKNOWN == confp->mfcr2.variant) {
17938                ast_log(LOG_WARNING, "Unknown MFC/R2 variant '%s' at line %d, defaulting to ITU.\n", v->value, v->lineno);
17939                confp->mfcr2.variant = OR2_VAR_ITU;
17940             }
17941          } else if (!strcasecmp(v->name, "mfcr2_mfback_timeout")) {
17942             confp->mfcr2.mfback_timeout = atoi(v->value);
17943             if (!confp->mfcr2.mfback_timeout) {
17944                ast_log(LOG_WARNING, "MF timeout of 0? hum, I will protect you from your ignorance. Setting default.\n");
17945                confp->mfcr2.mfback_timeout = -1;
17946             } else if (confp->mfcr2.mfback_timeout > 0 && confp->mfcr2.mfback_timeout < 500) {
17947                ast_log(LOG_WARNING, "MF timeout less than 500ms is not recommended, you have been warned!\n");
17948             }
17949          } else if (!strcasecmp(v->name, "mfcr2_metering_pulse_timeout")) {
17950             confp->mfcr2.metering_pulse_timeout = atoi(v->value);
17951             if (confp->mfcr2.metering_pulse_timeout > 500) {
17952                ast_log(LOG_WARNING, "Metering pulse timeout greater than 500ms is not recommended, you have been warned!\n");
17953             }
17954          } else if (!strcasecmp(v->name, "mfcr2_get_ani_first")) {
17955             confp->mfcr2.get_ani_first = ast_true(v->value) ? 1 : 0;
17956          } else if (!strcasecmp(v->name, "mfcr2_double_answer")) {
17957             confp->mfcr2.double_answer = ast_true(v->value) ? 1 : 0;
17958          } else if (!strcasecmp(v->name, "mfcr2_charge_calls")) {
17959             confp->mfcr2.charge_calls = ast_true(v->value) ? 1 : 0;
17960          } else if (!strcasecmp(v->name, "mfcr2_accept_on_offer")) {
17961             confp->mfcr2.accept_on_offer = ast_true(v->value) ? 1 : 0;
17962          } else if (!strcasecmp(v->name, "mfcr2_allow_collect_calls")) {
17963             confp->mfcr2.allow_collect_calls = ast_true(v->value) ? 1 : 0;
17964          } else if (!strcasecmp(v->name, "mfcr2_forced_release")) {
17965             confp->mfcr2.forced_release = ast_true(v->value) ? 1 : 0;
17966          } else if (!strcasecmp(v->name, "mfcr2_immediate_accept")) {
17967             confp->mfcr2.immediate_accept = ast_true(v->value) ? 1 : 0;
17968 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
17969          } else if (!strcasecmp(v->name, "mfcr2_skip_category")) {
17970             confp->mfcr2.skip_category_request = ast_true(v->value) ? 1 : 0;
17971 #endif
17972          } else if (!strcasecmp(v->name, "mfcr2_call_files")) {
17973             confp->mfcr2.call_files = ast_true(v->value) ? 1 : 0;
17974          } else if (!strcasecmp(v->name, "mfcr2_max_ani")) {
17975             confp->mfcr2.max_ani = atoi(v->value);
17976             if (confp->mfcr2.max_ani >= AST_MAX_EXTENSION){
17977                confp->mfcr2.max_ani = AST_MAX_EXTENSION - 1;
17978             }
17979          } else if (!strcasecmp(v->name, "mfcr2_max_dnis")) {
17980             confp->mfcr2.max_dnis = atoi(v->value);
17981             if (confp->mfcr2.max_dnis >= AST_MAX_EXTENSION){
17982                confp->mfcr2.max_dnis = AST_MAX_EXTENSION - 1;
17983             }
17984          } else if (!strcasecmp(v->name, "mfcr2_category")) {
17985             confp->mfcr2.category = openr2_proto_get_category(v->value);
17986             if (OR2_CALLING_PARTY_CATEGORY_UNKNOWN == confp->mfcr2.category) {
17987                confp->mfcr2.category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER;
17988                ast_log(LOG_WARNING, "Invalid MFC/R2 caller category '%s' at line %d. Using national subscriber as default.\n",
17989                      v->value, v->lineno);
17990             }
17991          } else if (!strcasecmp(v->name, "mfcr2_logging")) {
17992             openr2_log_level_t tmplevel;
17993             char *clevel;
17994             char *logval = ast_strdupa(v->value);
17995             while (logval) {
17996                clevel = strsep(&logval,",");
17997                if (-1 == (tmplevel = openr2_log_get_level(clevel))) {
17998                   ast_log(LOG_WARNING, "Ignoring invalid logging level: '%s' at line %d.\n", clevel, v->lineno);
17999                   continue;
18000                }
18001                confp->mfcr2.loglevel |= tmplevel;
18002             }
18003 #endif /* HAVE_OPENR2 */
18004          } else if (!strcasecmp(v->name, "cadence")) {
18005             /* setup to scan our argument */
18006             int element_count, c[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
18007             int i;
18008             struct dahdi_ring_cadence new_cadence;
18009             int cid_location = -1;
18010             int firstcadencepos = 0;
18011             char original_args[80];
18012             int cadence_is_ok = 1;
18013 
18014             ast_copy_string(original_args, v->value, sizeof(original_args));
18015             /* 16 cadences allowed (8 pairs) */
18016             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]);
18017 
18018             /* Cadence must be even (on/off) */
18019             if (element_count % 2 == 1) {
18020                ast_log(LOG_ERROR, "Must be a silence duration for each ring duration: %s at line %d.\n", original_args, v->lineno);
18021                cadence_is_ok = 0;
18022             }
18023 
18024             /* Ring cadences cannot be negative */
18025             for (i = 0; i < element_count; i++) {
18026                if (c[i] == 0) {
18027                   ast_log(LOG_ERROR, "Ring or silence duration cannot be zero: %s at line %d.\n", original_args, v->lineno);
18028                   cadence_is_ok = 0;
18029                   break;
18030                } else if (c[i] < 0) {
18031                   if (i % 2 == 1) {
18032                      /* Silence duration, negative possibly okay */
18033                      if (cid_location == -1) {
18034                         cid_location = i;
18035                         c[i] *= -1;
18036                      } else {
18037                         ast_log(LOG_ERROR, "CID location specified twice: %s at line %d.\n", original_args, v->lineno);
18038                         cadence_is_ok = 0;
18039                         break;
18040                      }
18041                   } else {
18042                      if (firstcadencepos == 0) {
18043                         firstcadencepos = i; /* only recorded to avoid duplicate specification */
18044                                  /* duration will be passed negative to the DAHDI driver */
18045                      } else {
18046                          ast_log(LOG_ERROR, "First cadence position specified twice: %s at line %d.\n", original_args, v->lineno);
18047                         cadence_is_ok = 0;
18048                         break;
18049                      }
18050                   }
18051                }
18052             }
18053 
18054             /* Substitute our scanned cadence */
18055             for (i = 0; i < 16; i++) {
18056                new_cadence.ringcadence[i] = c[i];
18057             }
18058 
18059             if (cadence_is_ok) {
18060                /* ---we scanned it without getting annoyed; now some sanity checks--- */
18061                if (element_count < 2) {
18062                   ast_log(LOG_ERROR, "Minimum cadence is ring,pause: %s at line %d.\n", original_args, v->lineno);
18063                } else {
18064                   if (cid_location == -1) {
18065                      /* user didn't say; default to first pause */
18066                      cid_location = 1;
18067                   } else {
18068                      /* convert element_index to cidrings value */
18069                      cid_location = (cid_location + 1) / 2;
18070                   }
18071                   /* ---we like their cadence; try to install it--- */
18072                   if (!user_has_defined_cadences++)
18073                      /* this is the first user-defined cadence; clear the default user cadences */
18074                      num_cadence = 0;
18075                   if ((num_cadence+1) >= NUM_CADENCE_MAX)
18076                      ast_log(LOG_ERROR, "Already %d cadences; can't add another: %s at line %d.\n", NUM_CADENCE_MAX, original_args, v->lineno);
18077                   else {
18078                      cadences[num_cadence] = new_cadence;
18079                      cidrings[num_cadence++] = cid_location;
18080                      ast_verb(3, "cadence 'r%d' added: %s\n",num_cadence,original_args);
18081                   }
18082                }
18083             }
18084          } else if (!strcasecmp(v->name, "ringtimeout")) {
18085             ringt_base = (atoi(v->value) * 8) / READ_SIZE;
18086          } else if (!strcasecmp(v->name, "prewink")) {
18087             confp->timing.prewinktime = atoi(v->value);
18088          } else if (!strcasecmp(v->name, "preflash")) {
18089             confp->timing.preflashtime = atoi(v->value);
18090          } else if (!strcasecmp(v->name, "wink")) {
18091             confp->timing.winktime = atoi(v->value);
18092          } else if (!strcasecmp(v->name, "flash")) {
18093             confp->timing.flashtime = atoi(v->value);
18094          } else if (!strcasecmp(v->name, "start")) {
18095             confp->timing.starttime = atoi(v->value);
18096          } else if (!strcasecmp(v->name, "rxwink")) {
18097             confp->timing.rxwinktime = atoi(v->value);
18098          } else if (!strcasecmp(v->name, "rxflash")) {
18099             confp->timing.rxflashtime = atoi(v->value);
18100          } else if (!strcasecmp(v->name, "debounce")) {
18101             confp->timing.debouncetime = atoi(v->value);
18102          } else if (!strcasecmp(v->name, "toneduration")) {
18103             int toneduration;
18104             int ctlfd;
18105             int res;
18106             struct dahdi_dialparams dps;
18107 
18108             ctlfd = open("/dev/dahdi/ctl", O_RDWR);
18109             if (ctlfd == -1) {
18110                ast_log(LOG_ERROR, "Unable to open /dev/dahdi/ctl to set toneduration at line %d.\n", v->lineno);
18111                return -1;
18112             }
18113 
18114             toneduration = atoi(v->value);
18115             if (toneduration > -1) {
18116                memset(&dps, 0, sizeof(dps));
18117 
18118                dps.dtmf_tonelen = dps.mfv1_tonelen = toneduration;
18119                res = ioctl(ctlfd, DAHDI_SET_DIALPARAMS, &dps);
18120                if (res < 0) {
18121                   ast_log(LOG_ERROR, "Invalid tone duration: %d ms at line %d: %s\n", toneduration, v->lineno, strerror(errno));
18122                   close(ctlfd);
18123                   return -1;
18124                }
18125             }
18126             close(ctlfd);
18127          } else if (!strcasecmp(v->name, "defaultcic")) {
18128             ast_copy_string(defaultcic, v->value, sizeof(defaultcic));
18129          } else if (!strcasecmp(v->name, "defaultozz")) {
18130             ast_copy_string(defaultozz, v->value, sizeof(defaultozz));
18131          } else if (!strcasecmp(v->name, "mwilevel")) {
18132             mwilevel = atoi(v->value);
18133          } else if (!strcasecmp(v->name, "dtmfcidlevel")) {
18134             dtmfcid_level = atoi(v->value);
18135          } else if (!strcasecmp(v->name, "reportalarms")) {
18136             if (!strcasecmp(v->value, "all"))
18137                report_alarms = REPORT_CHANNEL_ALARMS | REPORT_SPAN_ALARMS;
18138             if (!strcasecmp(v->value, "none"))
18139                report_alarms = 0;
18140             else if (!strcasecmp(v->value, "channels"))
18141                report_alarms = REPORT_CHANNEL_ALARMS;
18142             else if (!strcasecmp(v->value, "spans"))
18143                report_alarms = REPORT_SPAN_ALARMS;
18144           }
18145       } else if (!(options & PROC_DAHDI_OPT_NOWARN) )
18146          ast_log(LOG_WARNING, "Ignoring any changes to '%s' (on reload) at line %d.\n", v->name, v->lineno);
18147    }
18148 
18149    /* Since confp has already filled invidual dahdi_pvt objects with channels at this point, clear the variables in confp's pvt. */
18150    if (confp->chan.vars) {
18151       ast_variables_destroy(confp->chan.vars);
18152       confp->chan.vars = NULL;
18153    }
18154 
18155    if (dahdichan) {
18156       /* Process the deferred dahdichan value. */
18157       if (build_channels(confp, dahdichan->value, reload, dahdichan->lineno,
18158          &found_pseudo)) {
18159          if (confp->ignore_failed_channels) {
18160             ast_log(LOG_WARNING,
18161                "Dahdichan '%s' failure ignored: ignore_failed_channels.\n",
18162                dahdichan->value);
18163          } else {
18164             return -1;
18165          }
18166       }
18167    }
18168 
18169    /* mark the first channels of each DAHDI span to watch for their span alarms */
18170    for (tmp = iflist, y=-1; tmp; tmp = tmp->next) {
18171       if (!tmp->destroy && tmp->span != y) {
18172          tmp->manages_span_alarms = 1;
18173          y = tmp->span; 
18174       } else {
18175          tmp->manages_span_alarms = 0;
18176       }
18177    }
18178 
18179    /*< \todo why check for the pseudo in the per-channel section.
18180     * Any actual use for manual setup of the pseudo channel? */
18181    if (!found_pseudo && reload != 1 && !(options & PROC_DAHDI_OPT_NOCHAN)) {
18182       /* use the default configuration for a channel, so
18183          that any settings from real configured channels
18184          don't "leak" into the pseudo channel config
18185       */
18186       struct dahdi_chan_conf conf = dahdi_chan_conf_default();
18187 
18188       if (conf.chan.cc_params) {
18189          tmp = mkintf(CHAN_PSEUDO, &conf, reload);
18190       } else {
18191          tmp = NULL;
18192       }
18193       if (tmp) {
18194          ast_verb(3, "Automatically generated pseudo channel\n");
18195       } else {
18196          ast_log(LOG_WARNING, "Unable to register pseudo channel!\n");
18197       }
18198       ast_cc_config_params_destroy(conf.chan.cc_params);
18199    }
18200    return 0;
18201 }
18202 
18203 /*!
18204  * \internal
18205  * \brief Deep copy struct dahdi_chan_conf.
18206  * \since 1.8
18207  *
18208  * \param dest Destination.
18209  * \param src Source.
18210  *
18211  * \return Nothing
18212  */
18213 static void deep_copy_dahdi_chan_conf(struct dahdi_chan_conf *dest, const struct dahdi_chan_conf *src)
18214 {
18215    struct ast_cc_config_params *cc_params;
18216 
18217    cc_params = dest->chan.cc_params;
18218    *dest = *src;
18219    dest->chan.cc_params = cc_params;
18220    ast_cc_copy_config_params(dest->chan.cc_params, src->chan.cc_params);
18221 }
18222 
18223 /*!
18224  * \internal
18225  * \brief Setup DAHDI channel driver.
18226  *
18227  * \param reload enum: load_module(0), reload(1), restart(2).
18228  * \param default_conf Default config parameters.  So cc_params can be properly destroyed.
18229  * \param base_conf Default config parameters per section.  So cc_params can be properly destroyed.
18230  * \param conf Local config parameters.  So cc_params can be properly destroyed.
18231  *
18232  * \retval 0 on success.
18233  * \retval -1 on error.
18234  */
18235 static int setup_dahdi_int(int reload, struct dahdi_chan_conf *default_conf, struct dahdi_chan_conf *base_conf, struct dahdi_chan_conf *conf)
18236 {
18237    struct ast_config *cfg;
18238    struct ast_config *ucfg;
18239    struct ast_variable *v;
18240    struct ast_flags config_flags = { reload == 1 ? CONFIG_FLAG_FILEUNCHANGED : 0 };
18241    const char *chans;
18242    const char *cat;
18243    int res;
18244 
18245 #ifdef HAVE_PRI
18246    char *c;
18247    int spanno;
18248    int i;
18249    int logicalspan;
18250    int trunkgroup;
18251    int dchannels[SIG_PRI_NUM_DCHANS];
18252 #endif
18253    int have_cfg_now;
18254    static int had_cfg_before = 1;/* So initial load will complain if we don't have cfg. */
18255 
18256    cfg = ast_config_load(config, config_flags);
18257    have_cfg_now = !!cfg;
18258    if (!cfg) {
18259       /* Error if we have no config file */
18260       if (had_cfg_before) {
18261          ast_log(LOG_ERROR, "Unable to load config %s\n", config);
18262          ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
18263       }
18264       cfg = ast_config_new();/* Dummy config */
18265       if (!cfg) {
18266          return 0;
18267       }
18268       ucfg = ast_config_load("users.conf", config_flags);
18269       if (ucfg == CONFIG_STATUS_FILEUNCHANGED) {
18270          ast_config_destroy(cfg);
18271          return 0;
18272       }
18273       if (ucfg == CONFIG_STATUS_FILEINVALID) {
18274          ast_log(LOG_ERROR, "File users.conf cannot be parsed.  Aborting.\n");
18275          ast_config_destroy(cfg);
18276          return 0;
18277       }
18278    } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
18279       ucfg = ast_config_load("users.conf", config_flags);
18280       if (ucfg == CONFIG_STATUS_FILEUNCHANGED) {
18281          return 0;
18282       }
18283       if (ucfg == CONFIG_STATUS_FILEINVALID) {
18284          ast_log(LOG_ERROR, "File users.conf cannot be parsed.  Aborting.\n");
18285          return 0;
18286       }
18287       ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
18288       cfg = ast_config_load(config, config_flags);
18289       have_cfg_now = !!cfg;
18290       if (!cfg) {
18291          if (had_cfg_before) {
18292             /* We should have been able to load the config. */
18293             ast_log(LOG_ERROR, "Bad. Unable to load config %s\n", config);
18294             ast_config_destroy(ucfg);
18295             return 0;
18296          }
18297          cfg = ast_config_new();/* Dummy config */
18298          if (!cfg) {
18299             ast_config_destroy(ucfg);
18300             return 0;
18301          }
18302       } else if (cfg == CONFIG_STATUS_FILEINVALID) {
18303          ast_log(LOG_ERROR, "File %s cannot be parsed.  Aborting.\n", config);
18304          ast_config_destroy(ucfg);
18305          return 0;
18306       }
18307    } else if (cfg == CONFIG_STATUS_FILEINVALID) {
18308       ast_log(LOG_ERROR, "File %s cannot be parsed.  Aborting.\n", config);
18309       return 0;
18310    } else {
18311       ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
18312       ucfg = ast_config_load("users.conf", config_flags);
18313       if (ucfg == CONFIG_STATUS_FILEINVALID) {
18314          ast_log(LOG_ERROR, "File users.conf cannot be parsed.  Aborting.\n");
18315          ast_config_destroy(cfg);
18316          return 0;
18317       }
18318    }
18319    had_cfg_before = have_cfg_now;
18320 
18321    /* It's a little silly to lock it, but we might as well just to be sure */
18322    ast_mutex_lock(&iflock);
18323 #ifdef HAVE_PRI
18324    if (reload != 1) {
18325       /* Process trunkgroups first */
18326       v = ast_variable_browse(cfg, "trunkgroups");
18327       while (v) {
18328          if (!strcasecmp(v->name, "trunkgroup")) {
18329             trunkgroup = atoi(v->value);
18330             if (trunkgroup > 0) {
18331                if ((c = strchr(v->value, ','))) {
18332                   i = 0;
18333                   memset(dchannels, 0, sizeof(dchannels));
18334                   while (c && (i < SIG_PRI_NUM_DCHANS)) {
18335                      dchannels[i] = atoi(c + 1);
18336                      if (dchannels[i] < 0) {
18337                         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);
18338                      } else
18339                         i++;
18340                      c = strchr(c + 1, ',');
18341                   }
18342                   if (i) {
18343                      if (pri_create_trunkgroup(trunkgroup, dchannels)) {
18344                         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);
18345                   } else
18346                         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");
18347                   } else
18348                      ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
18349                } else
18350                   ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
18351             } else
18352                ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of chan_dahdi.conf\n", v->lineno);
18353          } else if (!strcasecmp(v->name, "spanmap")) {
18354             spanno = atoi(v->value);
18355             if (spanno > 0) {
18356                if ((c = strchr(v->value, ','))) {
18357                   trunkgroup = atoi(c + 1);
18358                   if (trunkgroup > 0) {
18359                      if ((c = strchr(c + 1, ',')))
18360                         logicalspan = atoi(c + 1);
18361                      else
18362                         logicalspan = 0;
18363                      if (logicalspan >= 0) {
18364                         if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) {
18365                            ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
18366                      } else
18367                            ast_verb(2, "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
18368                      } else
18369                         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);
18370                   } else
18371                      ast_log(LOG_WARNING, "Trunk group must be a postive number at line %d of chan_dahdi.conf\n", v->lineno);
18372                } else
18373                   ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of chan_dahdi.conf\n", v->lineno);
18374             } else
18375                ast_log(LOG_WARNING, "Span number must be a postive integer at line %d of chan_dahdi.conf\n", v->lineno);
18376          } else {
18377             ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name);
18378          }
18379          v = v->next;
18380       }
18381    }
18382 #endif
18383 
18384    /* Copy the default jb config over global_jbconf */
18385    memcpy(&global_jbconf, &default_jbconf, sizeof(global_jbconf));
18386 
18387    mwimonitornotify[0] = '\0';
18388 
18389    v = ast_variable_browse(cfg, "channels");
18390    if ((res = process_dahdi(base_conf,
18391       "" /* Must be empty for the channels category.  Silly voicemail mailbox. */,
18392       v, reload, 0))) {
18393       ast_mutex_unlock(&iflock);
18394       ast_config_destroy(cfg);
18395       if (ucfg) {
18396          ast_config_destroy(ucfg);
18397       }
18398       return res;
18399    }
18400 
18401    /* Now get configuration from all normal sections in chan_dahdi.conf: */
18402    for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) {
18403       /* [channels] and [trunkgroups] are used. Let's also reserve
18404        * [globals] and [general] for future use
18405        */
18406       if (!strcasecmp(cat, "general") ||
18407          !strcasecmp(cat, "trunkgroups") ||
18408          !strcasecmp(cat, "globals") ||
18409          !strcasecmp(cat, "channels")) {
18410          continue;
18411       }
18412 
18413       chans = ast_variable_retrieve(cfg, cat, "dahdichan");
18414       if (ast_strlen_zero(chans)) {
18415          /* Section is useless without a dahdichan value present. */
18416          continue;
18417       }
18418 
18419       /* Copy base_conf to conf. */
18420       deep_copy_dahdi_chan_conf(conf, base_conf);
18421 
18422       if ((res = process_dahdi(conf, cat, ast_variable_browse(cfg, cat), reload, PROC_DAHDI_OPT_NOCHAN))) {
18423          ast_mutex_unlock(&iflock);
18424          ast_config_destroy(cfg);
18425          if (ucfg) {
18426             ast_config_destroy(ucfg);
18427          }
18428          return res;
18429       }
18430    }
18431 
18432    ast_config_destroy(cfg);
18433 
18434    if (ucfg) {
18435       /* Reset base_conf, so things don't leak from chan_dahdi.conf */
18436       deep_copy_dahdi_chan_conf(base_conf, default_conf);
18437       process_dahdi(base_conf,
18438          "" /* Must be empty for the general category.  Silly voicemail mailbox. */,
18439          ast_variable_browse(ucfg, "general"), 1, 0);
18440 
18441       for (cat = ast_category_browse(ucfg, NULL); cat ; cat = ast_category_browse(ucfg, cat)) {
18442          if (!strcasecmp(cat, "general")) {
18443             continue;
18444          }
18445 
18446          chans = ast_variable_retrieve(ucfg, cat, "dahdichan");
18447          if (ast_strlen_zero(chans)) {
18448             /* Section is useless without a dahdichan value present. */
18449             continue;
18450          }
18451 
18452          /* Copy base_conf to conf. */
18453          deep_copy_dahdi_chan_conf(conf, base_conf);
18454 
18455          if ((res = process_dahdi(conf, cat, ast_variable_browse(ucfg, cat), reload, PROC_DAHDI_OPT_NOCHAN | PROC_DAHDI_OPT_NOWARN))) {
18456             ast_config_destroy(ucfg);
18457             ast_mutex_unlock(&iflock);
18458             return res;
18459          }
18460       }
18461       ast_config_destroy(ucfg);
18462    }
18463    ast_mutex_unlock(&iflock);
18464 
18465 #ifdef HAVE_PRI
18466    if (reload != 1) {
18467       int x;
18468       for (x = 0; x < NUM_SPANS; x++) {
18469          if (pris[x].pri.pvts[0]) {
18470             prepare_pri(pris + x);
18471             if (sig_pri_start_pri(&pris[x].pri)) {
18472                ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1);
18473                return -1;
18474             } else
18475                ast_verb(2, "Starting D-Channel on span %d\n", x + 1);
18476          }
18477       }
18478    }
18479 #endif
18480 #if defined(HAVE_SS7)
18481    if (reload != 1) {
18482       int x;
18483       for (x = 0; x < NUM_SPANS; x++) {
18484          if (linksets[x].ss7.ss7) {
18485             linksets[x].ss7.calls = &dahdi_ss7_callbacks;
18486             if (ast_pthread_create(&linksets[x].ss7.master, NULL, ss7_linkset, &linksets[x].ss7)) {
18487                ast_log(LOG_ERROR, "Unable to start SS7 linkset on span %d\n", x + 1);
18488                return -1;
18489             } else
18490                ast_verb(2, "Starting SS7 linkset on span %d\n", x + 1);
18491          }
18492       }
18493    }
18494 #endif   /* defined(HAVE_SS7) */
18495 #ifdef HAVE_OPENR2
18496    if (reload != 1) {
18497       int x;
18498       for (x = 0; x < r2links_count; x++) {
18499          if (ast_pthread_create(&r2links[x]->r2master, NULL, mfcr2_monitor, r2links[x])) {
18500             ast_log(LOG_ERROR, "Unable to start R2 monitor on channel group %d\n", x + 1);
18501             return -1;
18502          } else {
18503             ast_verb(2, "Starting R2 monitor on channel group %d\n", x + 1);
18504          }
18505       }
18506    }
18507 #endif
18508    /* And start the monitor for the first time */
18509    restart_monitor();
18510    return 0;
18511 }
18512 
18513 /*!
18514  * \internal
18515  * \brief Setup DAHDI channel driver.
18516  *
18517  * \param reload enum: load_module(0), reload(1), restart(2).
18518  *
18519  * \retval 0 on success.
18520  * \retval -1 on error.
18521  */
18522 static int setup_dahdi(int reload)
18523 {
18524    int res;
18525    struct dahdi_chan_conf default_conf = dahdi_chan_conf_default();
18526    struct dahdi_chan_conf base_conf = dahdi_chan_conf_default();
18527    struct dahdi_chan_conf conf = dahdi_chan_conf_default();
18528 
18529    if (default_conf.chan.cc_params && base_conf.chan.cc_params && conf.chan.cc_params) {
18530       res = setup_dahdi_int(reload, &default_conf, &base_conf, &conf);
18531    } else {
18532       res = -1;
18533    }
18534    ast_cc_config_params_destroy(default_conf.chan.cc_params);
18535    ast_cc_config_params_destroy(base_conf.chan.cc_params);
18536    ast_cc_config_params_destroy(conf.chan.cc_params);
18537 
18538    return res;
18539 }
18540 
18541 /*!
18542  * \internal
18543  * \brief Callback used to generate the dahdi status tree.
18544  * \param[in] search The search pattern tree.
18545  * \retval NULL on error.
18546  * \retval non-NULL The generated tree.
18547  */
18548 static int dahdi_status_data_provider_get(const struct ast_data_search *search,
18549       struct ast_data *data_root)
18550 {
18551    int ctl, res, span;
18552    struct ast_data *data_span, *data_alarms;
18553    struct dahdi_spaninfo s;
18554 
18555    ctl = open("/dev/dahdi/ctl", O_RDWR);
18556    if (ctl < 0) {
18557       ast_log(LOG_ERROR, "No DAHDI found. Unable to open /dev/dahdi/ctl: %s\n", strerror(errno));
18558       return -1;
18559    }
18560    for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
18561       s.spanno = span;
18562       res = ioctl(ctl, DAHDI_SPANSTAT, &s);
18563       if (res) {
18564          continue;
18565       }
18566 
18567       data_span = ast_data_add_node(data_root, "span");
18568       if (!data_span) {
18569          continue;
18570       }
18571       ast_data_add_str(data_span, "description", s.desc);
18572 
18573       /* insert the alarms status */
18574       data_alarms = ast_data_add_node(data_span, "alarms");
18575       if (!data_alarms) {
18576          continue;
18577       }
18578 
18579       ast_data_add_bool(data_alarms, "BLUE", s.alarms & DAHDI_ALARM_BLUE);
18580       ast_data_add_bool(data_alarms, "YELLOW", s.alarms & DAHDI_ALARM_YELLOW);
18581       ast_data_add_bool(data_alarms, "RED", s.alarms & DAHDI_ALARM_RED);
18582       ast_data_add_bool(data_alarms, "LOOPBACK", s.alarms & DAHDI_ALARM_LOOPBACK);
18583       ast_data_add_bool(data_alarms, "RECOVER", s.alarms & DAHDI_ALARM_RECOVER);
18584       ast_data_add_bool(data_alarms, "NOTOPEN", s.alarms & DAHDI_ALARM_NOTOPEN);
18585 
18586       ast_data_add_int(data_span, "irqmisses", s.irqmisses);
18587       ast_data_add_int(data_span, "bpviol", s.bpvcount);
18588       ast_data_add_int(data_span, "crc4", s.crc4count);
18589       ast_data_add_str(data_span, "framing", s.lineconfig & DAHDI_CONFIG_D4 ? "D4" :
18590                      s.lineconfig & DAHDI_CONFIG_ESF ? "ESF" :
18591                      s.lineconfig & DAHDI_CONFIG_CCS ? "CCS" :
18592                      "CAS");
18593       ast_data_add_str(data_span, "coding",  s.lineconfig & DAHDI_CONFIG_B8ZS ? "B8ZS" :
18594                      s.lineconfig & DAHDI_CONFIG_HDB3 ? "HDB3" :
18595                      s.lineconfig & DAHDI_CONFIG_AMI ? "AMI" :
18596                      "Unknown");
18597       ast_data_add_str(data_span, "options", s.lineconfig & DAHDI_CONFIG_CRC4 ?
18598                      s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" :
18599                      s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "YEL" : "");
18600       ast_data_add_str(data_span, "lbo", lbostr[s.lbo]);
18601 
18602       /* if this span doesn't match remove it. */
18603       if (!ast_data_search_match(search, data_span)) {
18604          ast_data_remove_node(data_root, data_span);
18605       }
18606    }
18607    close(ctl);
18608 
18609    return 0;
18610 }
18611 
18612 /*!
18613  * \internal
18614  * \brief Callback used to generate the dahdi channels tree.
18615  * \param[in] search The search pattern tree.
18616  * \retval NULL on error.
18617  * \retval non-NULL The generated tree.
18618  */
18619 static int dahdi_channels_data_provider_get(const struct ast_data_search *search,
18620       struct ast_data *data_root)
18621 {
18622    struct dahdi_pvt *tmp;
18623    struct ast_data *data_channel;
18624 
18625    ast_mutex_lock(&iflock);
18626    for (tmp = iflist; tmp; tmp = tmp->next) {
18627       data_channel = ast_data_add_node(data_root, "channel");
18628       if (!data_channel) {
18629          continue;
18630       }
18631 
18632       ast_data_add_structure(dahdi_pvt, data_channel, tmp);
18633 
18634       /* if this channel doesn't match remove it. */
18635       if (!ast_data_search_match(search, data_channel)) {
18636          ast_data_remove_node(data_root, data_channel);
18637       }
18638    }
18639    ast_mutex_unlock(&iflock);
18640 
18641    return 0;
18642 }
18643 
18644 /*!
18645  * \internal
18646  * \brief Callback used to generate the dahdi channels tree.
18647  * \param[in] search The search pattern tree.
18648  * \retval NULL on error.
18649  * \retval non-NULL The generated tree.
18650  */
18651 static int dahdi_version_data_provider_get(const struct ast_data_search *search,
18652       struct ast_data *data_root)
18653 {
18654    int pseudo_fd = -1;
18655    struct dahdi_versioninfo vi = {
18656       .version = "Unknown",
18657       .echo_canceller = "Unknown"
18658    };
18659 
18660    if ((pseudo_fd = open("/dev/dahdi/ctl", O_RDONLY)) < 0) {
18661       ast_log(LOG_ERROR, "Failed to open control file to get version.\n");
18662       return -1;
18663    }
18664 
18665    if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi)) {
18666       ast_log(LOG_ERROR, "Failed to get DAHDI version: %s\n", strerror(errno));
18667    }
18668 
18669    close(pseudo_fd);
18670 
18671    ast_data_add_str(data_root, "value", vi.version);
18672    ast_data_add_str(data_root, "echocanceller", vi.echo_canceller);
18673 
18674    return 0;
18675 }
18676 
18677 static const struct ast_data_handler dahdi_status_data_provider = {
18678    .version = AST_DATA_HANDLER_VERSION,
18679    .get = dahdi_status_data_provider_get
18680 };
18681 
18682 static const struct ast_data_handler dahdi_channels_data_provider = {
18683    .version = AST_DATA_HANDLER_VERSION,
18684    .get = dahdi_channels_data_provider_get
18685 };
18686 
18687 static const struct ast_data_handler dahdi_version_data_provider = {
18688    .version = AST_DATA_HANDLER_VERSION,
18689    .get = dahdi_version_data_provider_get
18690 };
18691 
18692 static const struct ast_data_entry dahdi_data_providers[] = {
18693    AST_DATA_ENTRY("asterisk/channel/dahdi/status", &dahdi_status_data_provider),
18694    AST_DATA_ENTRY("asterisk/channel/dahdi/channels", &dahdi_channels_data_provider),
18695    AST_DATA_ENTRY("asterisk/channel/dahdi/version", &dahdi_version_data_provider)
18696 };
18697 
18698 static int load_module(void)
18699 {
18700    int res;
18701 #if defined(HAVE_PRI) || defined(HAVE_SS7)
18702    int y;
18703 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
18704 
18705 #ifdef HAVE_PRI
18706    memset(pris, 0, sizeof(pris));
18707    for (y = 0; y < NUM_SPANS; y++) {
18708       sig_pri_init_pri(&pris[y].pri);
18709    }
18710    pri_set_error(dahdi_pri_error);
18711    pri_set_message(dahdi_pri_message);
18712    ast_register_application_xml(dahdi_send_keypad_facility_app, dahdi_send_keypad_facility_exec);
18713 #ifdef HAVE_PRI_PROG_W_CAUSE
18714    ast_register_application_xml(dahdi_send_callrerouting_facility_app, dahdi_send_callrerouting_facility_exec);
18715 #endif
18716 #if defined(HAVE_PRI_CCSS)
18717    if (ast_cc_agent_register(&dahdi_pri_cc_agent_callbacks)
18718       || ast_cc_monitor_register(&dahdi_pri_cc_monitor_callbacks)) {
18719       __unload_module();
18720       return AST_MODULE_LOAD_FAILURE;
18721    }
18722 #endif   /* defined(HAVE_PRI_CCSS) */
18723    if (sig_pri_load(
18724 #if defined(HAVE_PRI_CCSS)
18725       dahdi_pri_cc_type
18726 #else
18727       NULL
18728 #endif   /* defined(HAVE_PRI_CCSS) */
18729       )) {
18730       __unload_module();
18731       return AST_MODULE_LOAD_FAILURE;
18732    }
18733 #endif
18734 #if defined(HAVE_SS7)
18735    memset(linksets, 0, sizeof(linksets));
18736    for (y = 0; y < NUM_SPANS; y++) {
18737       sig_ss7_init_linkset(&linksets[y].ss7);
18738    }
18739    ss7_set_error(dahdi_ss7_error);
18740    ss7_set_message(dahdi_ss7_message);
18741 #endif   /* defined(HAVE_SS7) */
18742    res = setup_dahdi(0);
18743    /* Make sure we can register our DAHDI channel type */
18744    if (res)
18745       return AST_MODULE_LOAD_DECLINE;
18746    if (ast_channel_register(&dahdi_tech)) {
18747       ast_log(LOG_ERROR, "Unable to register channel class 'DAHDI'\n");
18748       __unload_module();
18749       return AST_MODULE_LOAD_FAILURE;
18750    }
18751 #ifdef HAVE_PRI
18752    ast_cli_register_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
18753 #endif
18754 #if defined(HAVE_SS7)
18755    ast_cli_register_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
18756 #endif   /* defined(HAVE_SS7) */
18757 #ifdef HAVE_OPENR2
18758    ast_cli_register_multiple(dahdi_mfcr2_cli, ARRAY_LEN(dahdi_mfcr2_cli));
18759    ast_register_application_xml(dahdi_accept_r2_call_app, dahdi_accept_r2_call_exec);
18760 #endif
18761 
18762    ast_cli_register_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli));
18763    /* register all the data providers */
18764    ast_data_register_multiple(dahdi_data_providers, ARRAY_LEN(dahdi_data_providers));
18765    memset(round_robin, 0, sizeof(round_robin));
18766    ast_manager_register_xml("DAHDITransfer", 0, action_transfer);
18767    ast_manager_register_xml("DAHDIHangup", 0, action_transferhangup);
18768    ast_manager_register_xml("DAHDIDialOffhook", 0, action_dahdidialoffhook);
18769    ast_manager_register_xml("DAHDIDNDon", 0, action_dahdidndon);
18770    ast_manager_register_xml("DAHDIDNDoff", 0, action_dahdidndoff);
18771    ast_manager_register_xml("DAHDIShowChannels", 0, action_dahdishowchannels);
18772    ast_manager_register_xml("DAHDIRestart", 0, action_dahdirestart);
18773 
18774    ast_cond_init(&ss_thread_complete, NULL);
18775 
18776    return res;
18777 }
18778 
18779 static int dahdi_sendtext(struct ast_channel *c, const char *text)
18780 {
18781 #define  END_SILENCE_LEN 400
18782 #define  HEADER_MS 50
18783 #define  TRAILER_MS 5
18784 #define  HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8)
18785 #define  ASCII_BYTES_PER_CHAR 80
18786 
18787    unsigned char *buf,*mybuf;
18788    struct dahdi_pvt *p = c->tech_pvt;
18789    struct pollfd fds[1];
18790    int size,res,fd,len,x;
18791    int bytes=0;
18792    /* Initial carrier (imaginary) */
18793    float cr = 1.0;
18794    float ci = 0.0;
18795    float scont = 0.0;
18796    int idx;
18797 
18798    idx = dahdi_get_index(c, p, 0);
18799    if (idx < 0) {
18800       ast_log(LOG_WARNING, "Huh?  I don't exist?\n");
18801       return -1;
18802    }
18803    if (!text[0]) return(0); /* if nothing to send, don't */
18804    if ((!p->tdd) && (!p->mate)) return(0);  /* if not in TDD mode, just return */
18805    if (p->mate)
18806       buf = ast_malloc(((strlen(text) + 1) * ASCII_BYTES_PER_CHAR) + END_SILENCE_LEN + HEADER_LEN);
18807    else
18808       buf = ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN);
18809    if (!buf)
18810       return -1;
18811    mybuf = buf;
18812    if (p->mate) {
18813       int codec = AST_LAW(p);
18814       for (x = 0; x < HEADER_MS; x++) {   /* 50 ms of Mark */
18815          PUT_CLID_MARKMS;
18816       }
18817       /* Put actual message */
18818       for (x = 0; text[x]; x++) {
18819          PUT_CLID(text[x]);
18820       }
18821       for (x = 0; x < TRAILER_MS; x++) {  /* 5 ms of Mark */
18822          PUT_CLID_MARKMS;
18823       }
18824       len = bytes;
18825       buf = mybuf;
18826    } else {
18827       len = tdd_generate(p->tdd, buf, text);
18828       if (len < 1) {
18829          ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text));
18830          ast_free(mybuf);
18831          return -1;
18832       }
18833    }
18834    memset(buf + len, 0x7f, END_SILENCE_LEN);
18835    len += END_SILENCE_LEN;
18836    fd = p->subs[idx].dfd;
18837    while (len) {
18838       if (ast_check_hangup(c)) {
18839          ast_free(mybuf);
18840          return -1;
18841       }
18842       size = len;
18843       if (size > READ_SIZE)
18844          size = READ_SIZE;
18845       fds[0].fd = fd;
18846       fds[0].events = POLLOUT | POLLPRI;
18847       fds[0].revents = 0;
18848       res = poll(fds, 1, -1);
18849       if (!res) {
18850          ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
18851          continue;
18852       }
18853       /* if got exception */
18854       if (fds[0].revents & POLLPRI) {
18855          ast_free(mybuf);
18856          return -1;
18857       }
18858       if (!(fds[0].revents & POLLOUT)) {
18859          ast_debug(1, "write fd not ready on channel %d\n", p->channel);
18860          continue;
18861       }
18862       res = write(fd, buf, size);
18863       if (res != size) {
18864          if (res == -1) {
18865             ast_free(mybuf);
18866             return -1;
18867          }
18868          ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
18869          break;
18870       }
18871       len -= size;
18872       buf += size;
18873    }
18874    ast_free(mybuf);
18875    return(0);
18876 }
18877 
18878 
18879 static int reload(void)
18880 {
18881    int res = 0;
18882 
18883    res = setup_dahdi(1);
18884    if (res) {
18885       ast_log(LOG_WARNING, "Reload of chan_dahdi.so is unsuccessful!\n");
18886       return -1;
18887    }
18888    return 0;
18889 }
18890 
18891 /* This is a workaround so that menuselect displays a proper description
18892  * AST_MODULE_INFO(, , "DAHDI Telephony"
18893  */
18894 
18895 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, tdesc,
18896    .load = load_module,
18897    .unload = unload_module,
18898    .reload = reload,
18899    .load_pri = AST_MODPRI_CHANNEL_DRIVER,
18900       .nonoptreq = "res_smdi",
18901    );

Generated on 15 Apr 2016 for Asterisk - The Open Source Telephony Project by  doxygen 1.6.1