Mon Apr 28 2014 10:05:37

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: 407817 $")
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_proceeding = 1,
01370 
01371 #if defined(HAVE_PRI_CCSS)
01372          .cc_ptmp_recall_mode = 1,/* specificRecall */
01373          .cc_qsig_signaling_link_req = 1,/* retain */
01374          .cc_qsig_signaling_link_rsp = 1,/* retain */
01375 #endif   /* defined(HAVE_PRI_CCSS) */
01376 
01377          .minunused = 2,
01378          .idleext = "",
01379          .idledial = "",
01380          .internationalprefix = "",
01381          .nationalprefix = "",
01382          .localprefix = "",
01383          .privateprefix = "",
01384          .unknownprefix = "",
01385          .resetinterval = -1,
01386       },
01387 #endif
01388 #if defined(HAVE_SS7)
01389       .ss7.ss7 = {
01390          .called_nai = SS7_NAI_NATIONAL,
01391          .calling_nai = SS7_NAI_NATIONAL,
01392          .internationalprefix = "",
01393          .nationalprefix = "",
01394          .subscriberprefix = "",
01395          .unknownprefix = ""
01396       },
01397 #endif   /* defined(HAVE_SS7) */
01398 #ifdef HAVE_OPENR2
01399       .mfcr2 = {
01400          .variant = OR2_VAR_ITU,
01401          .mfback_timeout = -1,
01402          .metering_pulse_timeout = -1,
01403          .max_ani = 10,
01404          .max_dnis = 4,
01405          .get_ani_first = -1,
01406 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
01407          .skip_category_request = -1,
01408 #endif
01409          .call_files = 0,
01410          .allow_collect_calls = 0,
01411          .charge_calls = 1,
01412          .accept_on_offer = 1,
01413          .forced_release = 0,
01414          .double_answer = 0,
01415          .immediate_accept = -1,
01416          .logdir = "",
01417          .r2proto_file = "",
01418          .loglevel = OR2_LOG_ERROR | OR2_LOG_WARNING,
01419          .category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER
01420       },
01421 #endif
01422       .chan = {
01423          .context = "default",
01424          .cid_num = "",
01425          .cid_name = "",
01426          .cid_tag = "",
01427          .mohinterpret = "default",
01428          .mohsuggest = "",
01429          .parkinglot = "",
01430          .transfertobusy = 1,
01431 
01432          .cid_signalling = CID_SIG_BELL,
01433          .cid_start = CID_START_RING,
01434          .dahditrcallerid = 0,
01435          .use_callerid = 1,
01436          .sig = -1,
01437          .outsigmod = -1,
01438 
01439          .cid_rxgain = +5.0,
01440 
01441          .tonezone = -1,
01442 
01443          .echocancel.head.tap_length = 1,
01444 
01445          .busycount = 3,
01446 
01447          .accountcode = "",
01448 
01449          .mailbox = "",
01450 
01451 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
01452          .mwisend_fsk = 1,
01453 #endif
01454          .polarityonanswerdelay = 600,
01455 
01456          .sendcalleridafter = DEFAULT_CIDRINGS,
01457 
01458          .buf_policy = DAHDI_POLICY_IMMEDIATE,
01459          .buf_no = numbufs,
01460          .usefaxbuffers = 0,
01461          .cc_params = ast_cc_config_params_init(),
01462       },
01463       .timing = {
01464          .prewinktime = -1,
01465          .preflashtime = -1,
01466          .winktime = -1,
01467          .flashtime = -1,
01468          .starttime = -1,
01469          .rxwinktime = -1,
01470          .rxflashtime = -1,
01471          .debouncetime = -1
01472       },
01473       .is_sig_auto = 1,
01474       .smdi_port = "/dev/ttyS0",
01475    };
01476 
01477    return conf;
01478 }
01479 
01480 
01481 static struct ast_channel *dahdi_request(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause);
01482 static int dahdi_digit_begin(struct ast_channel *ast, char digit);
01483 static int dahdi_digit_end(struct ast_channel *ast, char digit, unsigned int duration);
01484 static int dahdi_sendtext(struct ast_channel *c, const char *text);
01485 static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout);
01486 static int dahdi_hangup(struct ast_channel *ast);
01487 static int dahdi_answer(struct ast_channel *ast);
01488 static struct ast_frame *dahdi_read(struct ast_channel *ast);
01489 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame);
01490 static struct ast_frame *dahdi_exception(struct ast_channel *ast);
01491 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen);
01492 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
01493 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen);
01494 static int dahdi_queryoption(struct ast_channel *chan, int option, void *data, int *datalen);
01495 static int dahdi_func_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len);
01496 static int dahdi_func_write(struct ast_channel *chan, const char *function, char *data, const char *value);
01497 static int dahdi_devicestate(void *data);
01498 static int dahdi_cc_callback(struct ast_channel *inbound, const char *dest, ast_cc_callback_fn callback);
01499 
01500 static const struct ast_channel_tech dahdi_tech = {
01501    .type = "DAHDI",
01502    .description = tdesc,
01503    .capabilities = AST_FORMAT_SLINEAR | AST_FORMAT_ULAW | AST_FORMAT_ALAW,
01504    .requester = dahdi_request,
01505    .send_digit_begin = dahdi_digit_begin,
01506    .send_digit_end = dahdi_digit_end,
01507    .send_text = dahdi_sendtext,
01508    .call = dahdi_call,
01509    .hangup = dahdi_hangup,
01510    .answer = dahdi_answer,
01511    .read = dahdi_read,
01512    .write = dahdi_write,
01513    .bridge = dahdi_bridge,
01514    .exception = dahdi_exception,
01515    .indicate = dahdi_indicate,
01516    .fixup = dahdi_fixup,
01517    .setoption = dahdi_setoption,
01518    .queryoption = dahdi_queryoption,
01519    .func_channel_read = dahdi_func_read,
01520    .func_channel_write = dahdi_func_write,
01521    .devicestate = dahdi_devicestate,
01522    .cc_callback = dahdi_cc_callback,
01523 };
01524 
01525 #define GET_CHANNEL(p) ((p)->channel)
01526 
01527 #define SIG_PRI_LIB_HANDLE_CASES \
01528    SIG_PRI:                \
01529    case SIG_BRI:              \
01530    case SIG_BRI_PTMP
01531 
01532 /*!
01533  * \internal
01534  * \brief Determine if sig_pri handles the signaling.
01535  * \since 1.8
01536  *
01537  * \param signaling Signaling to determine if is for sig_pri.
01538  *
01539  * \return TRUE if the signaling is for sig_pri.
01540  */
01541 static inline int dahdi_sig_pri_lib_handles(int signaling)
01542 {
01543    int handles;
01544 
01545    switch (signaling) {
01546    case SIG_PRI_LIB_HANDLE_CASES:
01547       handles = 1;
01548       break;
01549    default:
01550       handles = 0;
01551       break;
01552    }
01553 
01554    return handles;
01555 }
01556 
01557 static int analog_lib_handles(int signalling, int radio, int oprmode)
01558 {
01559    switch (signalling) {
01560    case SIG_FXOLS:
01561    case SIG_FXOGS:
01562    case SIG_FXOKS:
01563    case SIG_FXSLS:
01564    case SIG_FXSGS:
01565    case SIG_FXSKS:
01566    case SIG_EMWINK:
01567    case SIG_EM:
01568    case SIG_EM_E1:
01569    case SIG_FEATD:
01570    case SIG_FEATDMF:
01571    case SIG_E911:
01572    case SIG_FGC_CAMA:
01573    case SIG_FGC_CAMAMF:
01574    case SIG_FEATB:
01575    case SIG_SFWINK:
01576    case SIG_SF:
01577    case SIG_SF_FEATD:
01578    case SIG_SF_FEATDMF:
01579    case SIG_FEATDMF_TA:
01580    case SIG_SF_FEATB:
01581       break;
01582    default:
01583       /* The rest of the function should cover the remainder of signalling types */
01584       return 0;
01585    }
01586 
01587    if (radio) {
01588       return 0;
01589    }
01590 
01591    if (oprmode) {
01592       return 0;
01593    }
01594 
01595    return 1;
01596 }
01597 
01598 static enum analog_sigtype dahdisig_to_analogsig(int sig)
01599 {
01600    switch (sig) {
01601    case SIG_FXOLS:
01602       return ANALOG_SIG_FXOLS;
01603    case SIG_FXOGS:
01604       return ANALOG_SIG_FXOGS;
01605    case SIG_FXOKS:
01606       return ANALOG_SIG_FXOKS;
01607    case SIG_FXSLS:
01608       return ANALOG_SIG_FXSLS;
01609    case SIG_FXSGS:
01610       return ANALOG_SIG_FXSGS;
01611    case SIG_FXSKS:
01612       return ANALOG_SIG_FXSKS;
01613    case SIG_EMWINK:
01614       return ANALOG_SIG_EMWINK;
01615    case SIG_EM:
01616       return ANALOG_SIG_EM;
01617    case SIG_EM_E1:
01618       return ANALOG_SIG_EM_E1;
01619    case SIG_FEATD:
01620       return ANALOG_SIG_FEATD;
01621    case SIG_FEATDMF:
01622       return ANALOG_SIG_FEATDMF;
01623    case SIG_E911:
01624       return SIG_E911;
01625    case SIG_FGC_CAMA:
01626       return ANALOG_SIG_FGC_CAMA;
01627    case SIG_FGC_CAMAMF:
01628       return ANALOG_SIG_FGC_CAMAMF;
01629    case SIG_FEATB:
01630       return ANALOG_SIG_FEATB;
01631    case SIG_SFWINK:
01632       return ANALOG_SIG_SFWINK;
01633    case SIG_SF:
01634       return ANALOG_SIG_SF;
01635    case SIG_SF_FEATD:
01636       return ANALOG_SIG_SF_FEATD;
01637    case SIG_SF_FEATDMF:
01638       return ANALOG_SIG_SF_FEATDMF;
01639    case SIG_FEATDMF_TA:
01640       return ANALOG_SIG_FEATDMF_TA;
01641    case SIG_SF_FEATB:
01642       return ANALOG_SIG_FEATB;
01643    default:
01644       return -1;
01645    }
01646 }
01647 
01648 
01649 static int analog_tone_to_dahditone(enum analog_tone tone)
01650 {
01651    switch (tone) {
01652    case ANALOG_TONE_RINGTONE:
01653       return DAHDI_TONE_RINGTONE;
01654    case ANALOG_TONE_STUTTER:
01655       return DAHDI_TONE_STUTTER;
01656    case ANALOG_TONE_CONGESTION:
01657       return DAHDI_TONE_CONGESTION;
01658    case ANALOG_TONE_DIALTONE:
01659       return DAHDI_TONE_DIALTONE;
01660    case ANALOG_TONE_DIALRECALL:
01661       return DAHDI_TONE_DIALRECALL;
01662    case ANALOG_TONE_INFO:
01663       return DAHDI_TONE_INFO;
01664    default:
01665       return -1;
01666    }
01667 }
01668 
01669 static int analogsub_to_dahdisub(enum analog_sub analogsub)
01670 {
01671    int index;
01672 
01673    switch (analogsub) {
01674    case ANALOG_SUB_REAL:
01675       index = SUB_REAL;
01676       break;
01677    case ANALOG_SUB_CALLWAIT:
01678       index = SUB_CALLWAIT;
01679       break;
01680    case ANALOG_SUB_THREEWAY:
01681       index = SUB_THREEWAY;
01682       break;
01683    default:
01684       ast_log(LOG_ERROR, "Unidentified sub!\n");
01685       index = SUB_REAL;
01686    }
01687 
01688    return index;
01689 }
01690 
01691 static enum analog_event dahdievent_to_analogevent(int event);
01692 static int bump_gains(struct dahdi_pvt *p);
01693 static int dahdi_setlinear(int dfd, int linear);
01694 
01695 static int my_start_cid_detect(void *pvt, int cid_signalling)
01696 {
01697    struct dahdi_pvt *p = pvt;
01698    int index = SUB_REAL;
01699    p->cs = callerid_new(cid_signalling);
01700    if (!p->cs) {
01701       ast_log(LOG_ERROR, "Unable to alloc callerid\n");
01702       return -1;
01703    }
01704    bump_gains(p);
01705    dahdi_setlinear(p->subs[index].dfd, 0);
01706 
01707    return 0;
01708 }
01709 
01710 static int my_stop_cid_detect(void *pvt)
01711 {
01712    struct dahdi_pvt *p = pvt;
01713    int index = SUB_REAL;
01714    if (p->cs)
01715       callerid_free(p->cs);
01716    dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
01717    return 0;
01718 }
01719 
01720 static int my_get_callerid(void *pvt, char *namebuf, char *numbuf, enum analog_event *ev, size_t timeout)
01721 {
01722    struct dahdi_pvt *p = pvt;
01723    struct analog_pvt *analog_p = p->sig_pvt;
01724    struct pollfd poller;
01725    char *name, *num;
01726    int index = SUB_REAL;
01727    int res;
01728    unsigned char buf[256];
01729    int flags;
01730 
01731    poller.fd = p->subs[SUB_REAL].dfd;
01732    poller.events = POLLPRI | POLLIN;
01733    poller.revents = 0;
01734 
01735    res = poll(&poller, 1, timeout);
01736 
01737    if (poller.revents & POLLPRI) {
01738       *ev = dahdievent_to_analogevent(dahdi_get_event(p->subs[SUB_REAL].dfd));
01739       return 1;
01740    }
01741 
01742    if (poller.revents & POLLIN) {
01743       /*** NOTES ***/
01744       /* Change API: remove cid_signalling from get_callerid, add a new start_cid_detect and stop_cid_detect function
01745        * to enable slin mode and allocate cid detector. get_callerid should be able to be called any number of times until
01746        * either a timeout occurs or CID is detected (returns 0). returning 1 should be event received, and -1 should be
01747        * a failure and die, and returning 2 means no event was received. */
01748       res = read(p->subs[index].dfd, buf, sizeof(buf));
01749       if (res < 0) {
01750          ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
01751          return -1;
01752       }
01753 
01754       if (analog_p->ringt > 0) {
01755          if (!(--analog_p->ringt)) {
01756             /* only return if we timeout from a ring event */
01757             return -1;
01758          }
01759       }
01760 
01761       if (p->cid_signalling == CID_SIG_V23_JP) {
01762          res = callerid_feed_jp(p->cs, buf, res, AST_LAW(p));
01763       } else {
01764          res = callerid_feed(p->cs, buf, res, AST_LAW(p));
01765       }
01766       if (res < 0) {
01767          /*
01768           * The previous diagnostic message output likely
01769           * explains why it failed.
01770           */
01771          ast_log(LOG_WARNING, "Failed to decode CallerID\n");
01772          return -1;
01773       }
01774 
01775       if (res == 1) {
01776          callerid_get(p->cs, &name, &num, &flags);
01777          if (name)
01778             ast_copy_string(namebuf, name, ANALOG_MAX_CID);
01779          if (num)
01780             ast_copy_string(numbuf, num, ANALOG_MAX_CID);
01781 
01782          ast_debug(1, "CallerID number: %s, name: %s, flags=%d\n", num, name, flags);
01783          return 0;
01784       }
01785    }
01786 
01787    *ev = ANALOG_EVENT_NONE;
01788    return 2;
01789 }
01790 
01791 static const char *event2str(int event);
01792 static int restore_gains(struct dahdi_pvt *p);
01793 
01794 static int my_distinctive_ring(struct ast_channel *chan, void *pvt, int idx, int *ringdata)
01795 {
01796    unsigned char buf[256];
01797    int distMatches;
01798    int curRingData[RING_PATTERNS];
01799    int receivedRingT;
01800    int counter1;
01801    int counter;
01802    int i;
01803    int res;
01804    int checkaftercid = 0;
01805 
01806    struct dahdi_pvt *p = pvt;
01807    struct analog_pvt *analog_p = p->sig_pvt;
01808 
01809    if (ringdata == NULL) {
01810       ringdata = curRingData;
01811    } else {
01812       checkaftercid = 1;
01813    }
01814 
01815    /* We must have a ring by now, so, if configured, lets try to listen for
01816     * distinctive ringing */
01817    if ((checkaftercid && distinctiveringaftercid) || !checkaftercid) {
01818       /* Clear the current ring data array so we don't have old data in it. */
01819       for (receivedRingT = 0; receivedRingT < RING_PATTERNS; receivedRingT++)
01820          ringdata[receivedRingT] = 0;
01821       receivedRingT = 0;
01822       if (checkaftercid && distinctiveringaftercid)
01823          ast_verb(3, "Detecting post-CID distinctive ring\n");
01824       /* Check to see if context is what it should be, if not set to be. */
01825       else if (strcmp(p->context,p->defcontext) != 0) {
01826          ast_copy_string(p->context, p->defcontext, sizeof(p->context));
01827          ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
01828       }
01829 
01830       for (;;) {
01831          i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
01832          if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
01833             ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
01834             ast_hangup(chan);
01835             return 1;
01836          }
01837          if (i & DAHDI_IOMUX_SIGEVENT) {
01838             res = dahdi_get_event(p->subs[idx].dfd);
01839             if (res == DAHDI_EVENT_NOALARM) {
01840                p->inalarm = 0;
01841                analog_p->inalarm = 0;
01842             }
01843             ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
01844             res = 0;
01845             /* Let us detect distinctive ring */
01846 
01847             ringdata[receivedRingT] = analog_p->ringt;
01848 
01849             if (analog_p->ringt < analog_p->ringt_base/2)
01850                break;
01851             /* Increment the ringT counter so we can match it against
01852                values in chan_dahdi.conf for distinctive ring */
01853             if (++receivedRingT == RING_PATTERNS)
01854                break;
01855          } else if (i & DAHDI_IOMUX_READ) {
01856             res = read(p->subs[idx].dfd, buf, sizeof(buf));
01857             if (res < 0) {
01858                if (errno != ELAST) {
01859                   ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
01860                   ast_hangup(chan);
01861                   return 1;
01862                }
01863                break;
01864             }
01865             if (analog_p->ringt > 0) {
01866                if (!(--analog_p->ringt)) {
01867                   res = -1;
01868                   break;
01869                }
01870             }
01871          }
01872       }
01873    }
01874    if ((checkaftercid && usedistinctiveringdetection) || !checkaftercid) {
01875       /* this only shows up if you have n of the dring patterns filled in */
01876       ast_verb(3, "Detected ring pattern: %d,%d,%d\n",ringdata[0],ringdata[1],ringdata[2]);
01877       for (counter = 0; counter < 3; counter++) {
01878       /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this channel */
01879          distMatches = 0;
01880          /* this only shows up if you have n of the dring patterns filled in */
01881          ast_verb(3, "Checking %d,%d,%d\n",
01882                p->drings.ringnum[counter].ring[0],
01883                p->drings.ringnum[counter].ring[1],
01884                p->drings.ringnum[counter].ring[2]);
01885          for (counter1 = 0; counter1 < 3; counter1++) {
01886             ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
01887             if (p->drings.ringnum[counter].ring[counter1] == -1) {
01888                ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
01889                ringdata[counter1]);
01890                distMatches++;
01891             } else if (ringdata[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
01892                               ringdata[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
01893                ast_verb(3, "Ring pattern matched in range: %d to %d\n",
01894                (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
01895                (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
01896                distMatches++;
01897             }
01898          }
01899 
01900          if (distMatches == 3) {
01901             /* The ring matches, set the context to whatever is for distinctive ring.. */
01902             ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context));
01903             ast_copy_string(chan->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(chan->context));
01904             ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
01905             break;
01906          }
01907       }
01908    }
01909    /* Restore linear mode (if appropriate) for Caller*ID processing */
01910    dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
01911    restore_gains(p);
01912 
01913    return 0;
01914 }
01915 
01916 static int my_stop_callwait(void *pvt)
01917 {
01918    struct dahdi_pvt *p = pvt;
01919    p->callwaitingrepeat = 0;
01920    p->cidcwexpire = 0;
01921    p->cid_suppress_expire = 0;
01922 
01923    return 0;
01924 }
01925 
01926 static int send_callerid(struct dahdi_pvt *p);
01927 static int save_conference(struct dahdi_pvt *p);
01928 static int restore_conference(struct dahdi_pvt *p);
01929 
01930 static int my_callwait(void *pvt)
01931 {
01932    struct dahdi_pvt *p = pvt;
01933    p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
01934    if (p->cidspill) {
01935       ast_log(LOG_WARNING, "Spill already exists?!?\n");
01936       ast_free(p->cidspill);
01937    }
01938 
01939    /*
01940     * SAS: Subscriber Alert Signal, 440Hz for 300ms
01941     * CAS: CPE Alert Signal, 2130Hz * 2750Hz sine waves
01942     */
01943    if (!(p->cidspill = ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE * 4)))
01944       return -1;
01945    save_conference(p);
01946    /* Silence */
01947    memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
01948    if (!p->callwaitrings && p->callwaitingcallerid) {
01949       ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
01950       p->callwaitcas = 1;
01951       p->cidlen = 2400 + 680 + READ_SIZE * 4;
01952    } else {
01953       ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
01954       p->callwaitcas = 0;
01955       p->cidlen = 2400 + READ_SIZE * 4;
01956    }
01957    p->cidpos = 0;
01958    send_callerid(p);
01959 
01960    return 0;
01961 }
01962 
01963 static int my_send_callerid(void *pvt, int cwcid, struct ast_party_caller *caller)
01964 {
01965    struct dahdi_pvt *p = pvt;
01966 
01967    ast_debug(2, "Starting cid spill\n");
01968 
01969    if (p->cidspill) {
01970       ast_log(LOG_WARNING, "cidspill already exists??\n");
01971       ast_free(p->cidspill);
01972    }
01973 
01974    if ((p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) {
01975       if (cwcid == 0) {
01976          p->cidlen = ast_callerid_generate(p->cidspill,
01977             caller->id.name.str,
01978             caller->id.number.str,
01979             AST_LAW(p));
01980       } else {
01981          ast_verb(3, "CPE supports Call Waiting Caller*ID.  Sending '%s/%s'\n",
01982             caller->id.name.str, caller->id.number.str);
01983          p->callwaitcas = 0;
01984          p->cidcwexpire = 0;
01985          p->cidlen = ast_callerid_callwaiting_generate(p->cidspill,
01986             caller->id.name.str,
01987             caller->id.number.str,
01988             AST_LAW(p));
01989          p->cidlen += READ_SIZE * 4;
01990       }
01991       p->cidpos = 0;
01992       p->cid_suppress_expire = 0;
01993       send_callerid(p);
01994    }
01995    return 0;
01996 }
01997 
01998 static int my_dsp_reset_and_flush_digits(void *pvt)
01999 {
02000    struct dahdi_pvt *p = pvt;
02001    if (p->dsp)
02002       ast_dsp_digitreset(p->dsp);
02003 
02004    return 0;
02005 }
02006 
02007 static int my_dsp_set_digitmode(void *pvt, enum analog_dsp_digitmode mode)
02008 {
02009    struct dahdi_pvt *p = pvt;
02010 
02011    if (p->channel == CHAN_PSEUDO)
02012       ast_log(LOG_ERROR, "You have assumed incorrectly sir!\n");
02013 
02014    if (mode == ANALOG_DIGITMODE_DTMF) {
02015       /* If we do hardware dtmf, no need for a DSP */
02016       if (p->hardwaredtmf) {
02017          if (p->dsp) {
02018             ast_dsp_free(p->dsp);
02019             p->dsp = NULL;
02020          }
02021          return 0;
02022       }
02023 
02024       if (!p->dsp) {
02025          p->dsp = ast_dsp_new();
02026          if (!p->dsp) {
02027             ast_log(LOG_ERROR, "Unable to allocate DSP\n");
02028             return -1;
02029          }
02030       }
02031 
02032       ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
02033    } else if (mode == ANALOG_DIGITMODE_MF) {
02034       if (!p->dsp) {
02035          p->dsp = ast_dsp_new();
02036          if (!p->dsp) {
02037             ast_log(LOG_ERROR, "Unable to allocate DSP\n");
02038             return -1;
02039          }
02040       }
02041       ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
02042    }
02043    return 0;
02044 }
02045 
02046 static int dahdi_wink(struct dahdi_pvt *p, int index);
02047 
02048 static int my_wink(void *pvt, enum analog_sub sub)
02049 {
02050    struct dahdi_pvt *p = pvt;
02051    int index = analogsub_to_dahdisub(sub);
02052    if (index != SUB_REAL) {
02053       ast_log(LOG_ERROR, "We used a sub other than SUB_REAL (incorrect assumption sir)\n");
02054    }
02055    return dahdi_wink(p, index);
02056 }
02057 
02058 static void wakeup_sub(struct dahdi_pvt *p, int a);
02059 
02060 static int reset_conf(struct dahdi_pvt *p);
02061 
02062 static inline int dahdi_confmute(struct dahdi_pvt *p, int muted);
02063 
02064 static void my_handle_dtmf(void *pvt, struct ast_channel *ast, enum analog_sub analog_index, struct ast_frame **dest)
02065 {
02066    struct ast_frame *f = *dest;
02067    struct dahdi_pvt *p = pvt;
02068    int idx = analogsub_to_dahdisub(analog_index);
02069 
02070    ast_debug(1, "%s DTMF digit: 0x%02X '%c' on %s\n",
02071       f->frametype == AST_FRAME_DTMF_BEGIN ? "Begin" : "End",
02072       f->subclass.integer, f->subclass.integer, ast->name);
02073 
02074    if (f->subclass.integer == 'f') {
02075       if (f->frametype == AST_FRAME_DTMF_END) {
02076          /* Fax tone -- Handle and return NULL */
02077          if ((p->callprogress & CALLPROGRESS_FAX) && !p->faxhandled) {
02078             /* If faxbuffers are configured, use them for the fax transmission */
02079             if (p->usefaxbuffers && !p->bufferoverrideinuse) {
02080                struct dahdi_bufferinfo bi = {
02081                   .txbufpolicy = p->faxbuf_policy,
02082                   .bufsize = p->bufsize,
02083                   .numbufs = p->faxbuf_no
02084                };
02085                int res;
02086 
02087                if ((res = ioctl(p->subs[idx].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
02088                   ast_log(LOG_WARNING, "Channel '%s' unable to set buffer policy, reason: %s\n", ast->name, strerror(errno));
02089                } else {
02090                   p->bufferoverrideinuse = 1;
02091                }
02092             }
02093             p->faxhandled = 1;
02094             if (p->dsp) {
02095                p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
02096                ast_dsp_set_features(p->dsp, p->dsp_features);
02097                ast_debug(1, "Disabling FAX tone detection on %s after tone received\n", ast->name);
02098             }
02099             if (strcmp(ast->exten, "fax")) {
02100                const char *target_context = S_OR(ast->macrocontext, ast->context);
02101 
02102                /* We need to unlock 'ast' here because ast_exists_extension has the
02103                 * potential to start autoservice on the channel. Such action is prone
02104                 * to deadlock.
02105                 */
02106                ast_mutex_unlock(&p->lock);
02107                ast_channel_unlock(ast);
02108                if (ast_exists_extension(ast, target_context, "fax", 1,
02109                   S_COR(ast->caller.id.number.valid, ast->caller.id.number.str, NULL))) {
02110                   ast_channel_lock(ast);
02111                   ast_mutex_lock(&p->lock);
02112                   ast_verb(3, "Redirecting %s to fax extension\n", ast->name);
02113                   /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
02114                   pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten);
02115                   if (ast_async_goto(ast, target_context, "fax", 1))
02116                      ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context);
02117                } else {
02118                   ast_channel_lock(ast);
02119                   ast_mutex_lock(&p->lock);
02120                   ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
02121                }
02122             } else {
02123                ast_debug(1, "Already in a fax extension, not redirecting\n");
02124             }
02125          } else {
02126             ast_debug(1, "Fax already handled\n");
02127          }
02128          dahdi_confmute(p, 0);
02129       }
02130       p->subs[idx].f.frametype = AST_FRAME_NULL;
02131       p->subs[idx].f.subclass.integer = 0;
02132       *dest = &p->subs[idx].f;
02133    }
02134 }
02135 
02136 static void my_lock_private(void *pvt)
02137 {
02138    struct dahdi_pvt *p = pvt;
02139    ast_mutex_lock(&p->lock);
02140 }
02141 
02142 static void my_unlock_private(void *pvt)
02143 {
02144    struct dahdi_pvt *p = pvt;
02145    ast_mutex_unlock(&p->lock);
02146 }
02147 
02148 static void my_deadlock_avoidance_private(void *pvt)
02149 {
02150    struct dahdi_pvt *p = pvt;
02151 
02152    DEADLOCK_AVOIDANCE(&p->lock);
02153 }
02154 
02155 /*!
02156  * \internal
02157  * \brief Post an AMI DAHDI channel association event.
02158  * \since 1.8
02159  *
02160  * \param p DAHDI private pointer
02161  * \param chan Channel associated with the private pointer
02162  *
02163  * \return Nothing
02164  */
02165 static void dahdi_ami_channel_event(struct dahdi_pvt *p, struct ast_channel *chan)
02166 {
02167    char ch_name[20];
02168 
02169    if (p->channel < CHAN_PSEUDO) {
02170       /* No B channel */
02171       snprintf(ch_name, sizeof(ch_name), "no-media (%d)", p->channel);
02172    } else if (p->channel == CHAN_PSEUDO) {
02173       /* Pseudo channel */
02174       strcpy(ch_name, "pseudo");
02175    } else {
02176       /* Real channel */
02177       snprintf(ch_name, sizeof(ch_name), "%d", p->channel);
02178    }
02179    ast_manager_event(chan, EVENT_FLAG_CALL, "DAHDIChannel",
02180       "Channel: %s\r\n"
02181       "Uniqueid: %s\r\n"
02182       "DAHDISpan: %d\r\n"
02183       "DAHDIChannel: %s\r\n",
02184       chan->name,
02185       chan->uniqueid,
02186       p->span,
02187       ch_name);
02188 }
02189 
02190 #ifdef HAVE_PRI
02191 /*!
02192  * \internal
02193  * \brief Post an AMI DAHDI channel association event.
02194  * \since 1.8
02195  *
02196  * \param pvt DAHDI private pointer
02197  * \param chan Channel associated with the private pointer
02198  *
02199  * \return Nothing
02200  */
02201 static void my_ami_channel_event(void *pvt, struct ast_channel *chan)
02202 {
02203    struct dahdi_pvt *p = pvt;
02204 
02205    dahdi_ami_channel_event(p, chan);
02206 }
02207 #endif
02208 
02209 /* linear_mode = 0 - turn linear mode off, >0 - turn linear mode on
02210 *  returns the last value of the linear setting 
02211 */ 
02212 static int my_set_linear_mode(void *pvt, enum analog_sub sub, int linear_mode)
02213 {
02214    struct dahdi_pvt *p = pvt;
02215    int oldval;
02216    int idx = analogsub_to_dahdisub(sub);
02217    
02218    dahdi_setlinear(p->subs[idx].dfd, linear_mode);
02219    oldval = p->subs[idx].linear;
02220    p->subs[idx].linear = linear_mode ? 1 : 0;
02221    return oldval;
02222 }
02223 
02224 static void my_set_inthreeway(void *pvt, enum analog_sub sub, int inthreeway)
02225 {
02226    struct dahdi_pvt *p = pvt;
02227    int idx = analogsub_to_dahdisub(sub);
02228 
02229    p->subs[idx].inthreeway = inthreeway;
02230 }
02231 
02232 static int get_alarms(struct dahdi_pvt *p);
02233 static void handle_alarms(struct dahdi_pvt *p, int alms);
02234 static void my_get_and_handle_alarms(void *pvt)
02235 {
02236    int res;
02237    struct dahdi_pvt *p = pvt;
02238 
02239    res = get_alarms(p);
02240    handle_alarms(p, res);
02241 }
02242 
02243 static void *my_get_sigpvt_bridged_channel(struct ast_channel *chan)
02244 {
02245    struct ast_channel *bridged = ast_bridged_channel(chan);
02246 
02247    if (bridged && bridged->tech == &dahdi_tech) {
02248       struct dahdi_pvt *p = bridged->tech_pvt;
02249 
02250       if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
02251          return p->sig_pvt;
02252       }
02253    }
02254    return NULL;
02255 }
02256 
02257 static int my_get_sub_fd(void *pvt, enum analog_sub sub)
02258 {
02259    struct dahdi_pvt *p = pvt;
02260    int dahdi_sub = analogsub_to_dahdisub(sub);
02261    return p->subs[dahdi_sub].dfd;
02262 }
02263 
02264 static void my_set_cadence(void *pvt, int *cid_rings, struct ast_channel *ast)
02265 {
02266    struct dahdi_pvt *p = pvt;
02267 
02268    /* Choose proper cadence */
02269    if ((p->distinctivering > 0) && (p->distinctivering <= num_cadence)) {
02270       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &cadences[p->distinctivering - 1]))
02271          ast_log(LOG_WARNING, "Unable to set distinctive ring cadence %d on '%s': %s\n", p->distinctivering, ast->name, strerror(errno));
02272       *cid_rings = cidrings[p->distinctivering - 1];
02273    } else {
02274       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, NULL))
02275          ast_log(LOG_WARNING, "Unable to reset default ring on '%s': %s\n", ast->name, strerror(errno));
02276       *cid_rings = p->sendcalleridafter;
02277    }
02278 }
02279 
02280 static void my_set_alarm(void *pvt, int in_alarm)
02281 {
02282    struct dahdi_pvt *p = pvt;
02283 
02284    p->inalarm = in_alarm;
02285 }
02286 
02287 static void my_set_dialing(void *pvt, int is_dialing)
02288 {
02289    struct dahdi_pvt *p = pvt;
02290 
02291    p->dialing = is_dialing;
02292 }
02293 
02294 static void my_set_outgoing(void *pvt, int is_outgoing)
02295 {
02296    struct dahdi_pvt *p = pvt;
02297 
02298    p->outgoing = is_outgoing;
02299 }
02300 
02301 #if defined(HAVE_PRI) || defined(HAVE_SS7)
02302 static void my_set_digital(void *pvt, int is_digital)
02303 {
02304    struct dahdi_pvt *p = pvt;
02305 
02306    p->digital = is_digital;
02307 }
02308 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
02309 
02310 #if defined(HAVE_SS7)
02311 static void my_set_inservice(void *pvt, int is_inservice)
02312 {
02313    struct dahdi_pvt *p = pvt;
02314 
02315    p->inservice = is_inservice;
02316 }
02317 #endif   /* defined(HAVE_SS7) */
02318 
02319 #if defined(HAVE_SS7)
02320 static void my_set_locallyblocked(void *pvt, int is_blocked)
02321 {
02322    struct dahdi_pvt *p = pvt;
02323 
02324    p->locallyblocked = is_blocked;
02325 }
02326 #endif   /* defined(HAVE_SS7) */
02327 
02328 #if defined(HAVE_SS7)
02329 static void my_set_remotelyblocked(void *pvt, int is_blocked)
02330 {
02331    struct dahdi_pvt *p = pvt;
02332 
02333    p->remotelyblocked = is_blocked;
02334 }
02335 #endif   /* defined(HAVE_SS7) */
02336 
02337 static void my_set_ringtimeout(void *pvt, int ringt)
02338 {
02339    struct dahdi_pvt *p = pvt;
02340    p->ringt = ringt;
02341 }
02342 
02343 static void my_set_waitingfordt(void *pvt, struct ast_channel *ast)
02344 {
02345    struct dahdi_pvt *p = pvt;
02346 
02347    if (p->waitfordialtone && CANPROGRESSDETECT(p) && p->dsp) {
02348       ast_log(LOG_DEBUG, "Defer dialing for %dms or dialtone\n", p->waitfordialtone);
02349       gettimeofday(&p->waitingfordt, NULL);
02350       ast_setstate(ast, AST_STATE_OFFHOOK);
02351    }
02352 }
02353 
02354 static int my_check_waitingfordt(void *pvt)
02355 {
02356    struct dahdi_pvt *p = pvt;
02357 
02358    if (p->waitingfordt.tv_usec) {
02359       return 1;
02360    }
02361 
02362    return 0;
02363 }
02364 
02365 static void my_set_confirmanswer(void *pvt, int flag)
02366 {
02367    struct dahdi_pvt *p = pvt;
02368    p->confirmanswer = flag;
02369 }
02370 
02371 static int my_check_confirmanswer(void *pvt)
02372 {
02373    struct dahdi_pvt *p = pvt;
02374    if (p->confirmanswer) {
02375       return 1;
02376    }
02377 
02378    return 0;
02379 }
02380 
02381 static void my_set_callwaiting(void *pvt, int callwaiting_enable)
02382 {
02383    struct dahdi_pvt *p = pvt;
02384 
02385    p->callwaiting = callwaiting_enable;
02386 }
02387 
02388 static void my_cancel_cidspill(void *pvt)
02389 {
02390    struct dahdi_pvt *p = pvt;
02391 
02392    ast_free(p->cidspill);
02393    p->cidspill = NULL;
02394    restore_conference(p);
02395 }
02396 
02397 static int my_confmute(void *pvt, int mute)
02398 {
02399    struct dahdi_pvt *p = pvt;
02400    return dahdi_confmute(p, mute);
02401 }
02402 
02403 static void my_set_pulsedial(void *pvt, int flag)
02404 {
02405    struct dahdi_pvt *p = pvt;
02406    p->pulsedial = flag;
02407 }
02408 
02409 static void my_set_new_owner(void *pvt, struct ast_channel *new_owner)
02410 {
02411    struct dahdi_pvt *p = pvt;
02412 
02413    p->owner = new_owner;
02414 }
02415 
02416 static const char *my_get_orig_dialstring(void *pvt)
02417 {
02418    struct dahdi_pvt *p = pvt;
02419 
02420    return p->dialstring;
02421 }
02422 
02423 static void my_increase_ss_count(void)
02424 {
02425    ast_mutex_lock(&ss_thread_lock);
02426    ss_thread_count++;
02427    ast_mutex_unlock(&ss_thread_lock);
02428 }
02429 
02430 static void my_decrease_ss_count(void)
02431 {
02432    ast_mutex_lock(&ss_thread_lock);
02433    ss_thread_count--;
02434    ast_cond_signal(&ss_thread_complete);
02435    ast_mutex_unlock(&ss_thread_lock);
02436 }
02437 
02438 static void my_all_subchannels_hungup(void *pvt)
02439 {
02440    struct dahdi_pvt *p = pvt;
02441    int res, law;
02442 
02443    p->faxhandled = 0;
02444    p->didtdd = 0;
02445 
02446    if (p->dsp) {
02447       ast_dsp_free(p->dsp);
02448       p->dsp = NULL;
02449    }
02450 
02451    p->law = p->law_default;
02452    law = p->law_default;
02453    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
02454    if (res < 0)
02455       ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
02456 
02457    dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
02458 
02459 #if 1
02460    {
02461    int i;
02462    p->owner = NULL;
02463    /* Cleanup owners here */
02464    for (i = 0; i < 3; i++) {
02465       p->subs[i].owner = NULL;
02466    }
02467    }
02468 #endif
02469 
02470    reset_conf(p);
02471    if (num_restart_pending == 0) {
02472       restart_monitor();
02473    }
02474 }
02475 
02476 static int conf_del(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index);
02477 
02478 static int my_conf_del(void *pvt, enum analog_sub sub)
02479 {
02480    struct dahdi_pvt *p = pvt;
02481    int x = analogsub_to_dahdisub(sub);
02482 
02483    return conf_del(p, &p->subs[x], x);
02484 }
02485 
02486 static int conf_add(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index, int slavechannel);
02487 
02488 static int my_conf_add(void *pvt, enum analog_sub sub)
02489 {
02490    struct dahdi_pvt *p = pvt;
02491    int x = analogsub_to_dahdisub(sub);
02492 
02493    return conf_add(p, &p->subs[x], x, 0);
02494 }
02495 
02496 static int isslavenative(struct dahdi_pvt *p, struct dahdi_pvt **out);
02497 
02498 static int my_complete_conference_update(void *pvt, int needconference)
02499 {
02500    struct dahdi_pvt *p = pvt;
02501    int needconf = needconference;
02502    int x;
02503    int useslavenative;
02504    struct dahdi_pvt *slave = NULL;
02505 
02506    useslavenative = isslavenative(p, &slave);
02507 
02508    /* If we have a slave, add him to our conference now. or DAX
02509       if this is slave native */
02510    for (x = 0; x < MAX_SLAVES; x++) {
02511       if (p->slaves[x]) {
02512          if (useslavenative)
02513             conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
02514          else {
02515             conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
02516             needconf++;
02517          }
02518       }
02519    }
02520    /* If we're supposed to be in there, do so now */
02521    if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
02522       if (useslavenative)
02523          conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
02524       else {
02525          conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
02526          needconf++;
02527       }
02528    }
02529    /* If we have a master, add ourselves to his conference */
02530    if (p->master) {
02531       if (isslavenative(p->master, NULL)) {
02532          conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
02533       } else {
02534          conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
02535       }
02536    }
02537    if (!needconf) {
02538       /* Nobody is left (or should be left) in our conference.
02539          Kill it. */
02540       p->confno = -1;
02541    }
02542 
02543    return 0;
02544 }
02545 
02546 static int check_for_conference(struct dahdi_pvt *p);
02547 
02548 static int my_check_for_conference(void *pvt)
02549 {
02550    struct dahdi_pvt *p = pvt;
02551    return check_for_conference(p);
02552 }
02553 
02554 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)
02555 {
02556    struct dahdi_pvt *p = pvt;
02557    int da, db;
02558    int tchan;
02559    int tinthreeway;
02560 
02561    da = analogsub_to_dahdisub(a);
02562    db = analogsub_to_dahdisub(b);
02563 
02564    tchan = p->subs[da].chan;
02565    p->subs[da].chan = p->subs[db].chan;
02566    p->subs[db].chan = tchan;
02567 
02568    tinthreeway = p->subs[da].inthreeway;
02569    p->subs[da].inthreeway = p->subs[db].inthreeway;
02570    p->subs[db].inthreeway = tinthreeway;
02571 
02572    p->subs[da].owner = ast_a;
02573    p->subs[db].owner = ast_b;
02574 
02575    if (ast_a)
02576       ast_channel_set_fd(ast_a, 0, p->subs[da].dfd);
02577    if (ast_b)
02578       ast_channel_set_fd(ast_b, 0, p->subs[db].dfd);
02579 
02580    wakeup_sub(p, a);
02581    wakeup_sub(p, b);
02582 
02583    return;
02584 }
02585 
02586 static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpbx, int idx, int law, const char *linkedid);
02587 
02588 static struct ast_channel *my_new_analog_ast_channel(void *pvt, int state, int startpbx, enum analog_sub sub, const struct ast_channel *requestor)
02589 {
02590    struct dahdi_pvt *p = pvt;
02591    int dsub = analogsub_to_dahdisub(sub);
02592 
02593    return dahdi_new(p, state, startpbx, dsub, 0, requestor ? requestor->linkedid : "");
02594 }
02595 
02596 #if defined(HAVE_PRI) || defined(HAVE_SS7)
02597 static int dahdi_setlaw(int dfd, int law)
02598 {
02599    int res;
02600    res = ioctl(dfd, DAHDI_SETLAW, &law);
02601    if (res)
02602       return res;
02603    return 0;
02604 }
02605 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
02606 
02607 #if defined(HAVE_PRI)
02608 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)
02609 {
02610    struct dahdi_pvt *p = pvt;
02611    int audio;
02612    int newlaw = -1;
02613 
02614    switch (p->sig) {
02615    case SIG_PRI_LIB_HANDLE_CASES:
02616       if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
02617          /* PRI nobch pseudo channel.  Does not handle ioctl(DAHDI_AUDIOMODE) */
02618          break;
02619       }
02620       /* Fall through */
02621    default:
02622       /* Set to audio mode at this point */
02623       audio = 1;
02624       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &audio) == -1) {
02625          ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n",
02626             p->channel, audio, strerror(errno));
02627       }
02628       break;
02629    }
02630 
02631    if (law != SIG_PRI_DEFLAW) {
02632       dahdi_setlaw(p->subs[SUB_REAL].dfd, (law == SIG_PRI_ULAW) ? DAHDI_LAW_MULAW : DAHDI_LAW_ALAW);
02633    }
02634 
02635    ast_copy_string(p->exten, exten, sizeof(p->exten));
02636 
02637    switch (law) {
02638       case SIG_PRI_DEFLAW:
02639          newlaw = 0;
02640          break;
02641       case SIG_PRI_ALAW:
02642          newlaw = DAHDI_LAW_ALAW;
02643          break;
02644       case SIG_PRI_ULAW:
02645          newlaw = DAHDI_LAW_MULAW;
02646          break;
02647    }
02648    return dahdi_new(p, state, 0, SUB_REAL, newlaw, requestor ? requestor->linkedid : "");
02649 }
02650 #endif   /* defined(HAVE_PRI) */
02651 
02652 static int set_actual_gain(int fd, float rxgain, float txgain, float rxdrc, float txdrc, int law);
02653 
02654 #if defined(HAVE_PRI) || defined(HAVE_SS7)
02655 /*!
02656  * \internal
02657  * \brief Open the PRI/SS7 channel media path.
02658  * \since 1.8
02659  *
02660  * \param p Channel private control structure.
02661  *
02662  * \return Nothing
02663  */
02664 static void my_pri_ss7_open_media(void *p)
02665 {
02666    struct dahdi_pvt *pvt = p;
02667    int res;
02668    int dfd;
02669    int set_val;
02670 
02671    dfd = pvt->subs[SUB_REAL].dfd;
02672 
02673    /* Open the media path. */
02674    set_val = 1;
02675    res = ioctl(dfd, DAHDI_AUDIOMODE, &set_val);
02676    if (res < 0) {
02677       ast_log(LOG_WARNING, "Unable to enable audio mode on channel %d (%s)\n",
02678          pvt->channel, strerror(errno));
02679    }
02680 
02681    /* Set correct companding law for this call. */
02682    res = dahdi_setlaw(dfd, pvt->law);
02683    if (res < 0) {
02684       ast_log(LOG_WARNING, "Unable to set law on channel %d\n", pvt->channel);
02685    }
02686 
02687    /* Set correct gain for this call. */
02688    if (pvt->digital) {
02689       res = set_actual_gain(dfd, 0, 0, pvt->rxdrc, pvt->txdrc, pvt->law);
02690    } else {
02691       res = set_actual_gain(dfd, pvt->rxgain, pvt->txgain, pvt->rxdrc, pvt->txdrc,
02692          pvt->law);
02693    }
02694    if (res < 0) {
02695       ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", pvt->channel);
02696    }
02697 
02698    if (pvt->dsp_features && pvt->dsp) {
02699       ast_dsp_set_features(pvt->dsp, pvt->dsp_features);
02700       pvt->dsp_features = 0;
02701    }
02702 }
02703 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
02704 
02705 #if defined(HAVE_PRI)
02706 /*!
02707  * \internal
02708  * \brief Ask DAHDI to dial the given dial string.
02709  * \since 1.8.11
02710  *
02711  * \param p Channel private control structure.
02712  * \param dial_string String to pass to DAHDI to dial.
02713  *
02714  * \note The channel private lock needs to be held when calling.
02715  *
02716  * \return Nothing
02717  */
02718 static void my_pri_dial_digits(void *p, const char *dial_string)
02719 {
02720    struct dahdi_dialoperation zo = {
02721       .op = DAHDI_DIAL_OP_APPEND,
02722    };
02723    struct dahdi_pvt *pvt = p;
02724    int res;
02725 
02726    snprintf(zo.dialstr, sizeof(zo.dialstr), "T%s", dial_string);
02727    ast_debug(1, "Channel %d: Sending '%s' to DAHDI_DIAL.\n", pvt->channel, zo.dialstr);
02728    res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo);
02729    if (res) {
02730       ast_log(LOG_WARNING, "Channel %d: Couldn't dial '%s': %s\n",
02731          pvt->channel, dial_string, strerror(errno));
02732    } else {
02733       pvt->dialing = 1;
02734    }
02735 }
02736 #endif   /* defined(HAVE_PRI) */
02737 
02738 static int unalloc_sub(struct dahdi_pvt *p, int x);
02739 
02740 static int my_unallocate_sub(void *pvt, enum analog_sub analogsub)
02741 {
02742    struct dahdi_pvt *p = pvt;
02743 
02744    return unalloc_sub(p, analogsub_to_dahdisub(analogsub));
02745 }
02746 
02747 static int alloc_sub(struct dahdi_pvt *p, int x);
02748 
02749 static int my_allocate_sub(void *pvt, enum analog_sub analogsub)
02750 {
02751    struct dahdi_pvt *p = pvt;
02752 
02753    return alloc_sub(p, analogsub_to_dahdisub(analogsub));
02754 }
02755 
02756 static int has_voicemail(struct dahdi_pvt *p);
02757 
02758 static int my_has_voicemail(void *pvt)
02759 {
02760    struct dahdi_pvt *p = pvt;
02761 
02762    return has_voicemail(p);
02763 }
02764 
02765 static int my_play_tone(void *pvt, enum analog_sub sub, enum analog_tone tone)
02766 {
02767    struct dahdi_pvt *p = pvt;
02768    int index;
02769 
02770    index = analogsub_to_dahdisub(sub);
02771 
02772    return tone_zone_play_tone(p->subs[index].dfd, analog_tone_to_dahditone(tone));
02773 }
02774 
02775 static enum analog_event dahdievent_to_analogevent(int event)
02776 {
02777    enum analog_event res;
02778 
02779    switch (event) {
02780    case DAHDI_EVENT_ONHOOK:
02781       res = ANALOG_EVENT_ONHOOK;
02782       break;
02783    case DAHDI_EVENT_RINGOFFHOOK:
02784       res = ANALOG_EVENT_RINGOFFHOOK;
02785       break;
02786    case DAHDI_EVENT_WINKFLASH:
02787       res = ANALOG_EVENT_WINKFLASH;
02788       break;
02789    case DAHDI_EVENT_ALARM:
02790       res = ANALOG_EVENT_ALARM;
02791       break;
02792    case DAHDI_EVENT_NOALARM:
02793       res = ANALOG_EVENT_NOALARM;
02794       break;
02795    case DAHDI_EVENT_DIALCOMPLETE:
02796       res = ANALOG_EVENT_DIALCOMPLETE;
02797       break;
02798    case DAHDI_EVENT_RINGERON:
02799       res = ANALOG_EVENT_RINGERON;
02800       break;
02801    case DAHDI_EVENT_RINGEROFF:
02802       res = ANALOG_EVENT_RINGEROFF;
02803       break;
02804    case DAHDI_EVENT_HOOKCOMPLETE:
02805       res = ANALOG_EVENT_HOOKCOMPLETE;
02806       break;
02807    case DAHDI_EVENT_PULSE_START:
02808       res = ANALOG_EVENT_PULSE_START;
02809       break;
02810    case DAHDI_EVENT_POLARITY:
02811       res = ANALOG_EVENT_POLARITY;
02812       break;
02813    case DAHDI_EVENT_RINGBEGIN:
02814       res = ANALOG_EVENT_RINGBEGIN;
02815       break;
02816    case DAHDI_EVENT_EC_DISABLED:
02817       res = ANALOG_EVENT_EC_DISABLED;
02818       break;
02819    case DAHDI_EVENT_REMOVED:
02820       res = ANALOG_EVENT_REMOVED;
02821       break;
02822    case DAHDI_EVENT_NEONMWI_ACTIVE:
02823       res = ANALOG_EVENT_NEONMWI_ACTIVE;
02824       break;
02825    case DAHDI_EVENT_NEONMWI_INACTIVE:
02826       res = ANALOG_EVENT_NEONMWI_INACTIVE;
02827       break;
02828 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
02829    case DAHDI_EVENT_TX_CED_DETECTED:
02830       res = ANALOG_EVENT_TX_CED_DETECTED;
02831       break;
02832    case DAHDI_EVENT_RX_CED_DETECTED:
02833       res = ANALOG_EVENT_RX_CED_DETECTED;
02834       break;
02835    case DAHDI_EVENT_EC_NLP_DISABLED:
02836       res = ANALOG_EVENT_EC_NLP_DISABLED;
02837       break;
02838    case DAHDI_EVENT_EC_NLP_ENABLED:
02839       res = ANALOG_EVENT_EC_NLP_ENABLED;
02840       break;
02841 #endif
02842    case DAHDI_EVENT_PULSEDIGIT:
02843       res = ANALOG_EVENT_PULSEDIGIT;
02844       break;
02845    case DAHDI_EVENT_DTMFDOWN:
02846       res = ANALOG_EVENT_DTMFDOWN;
02847       break;
02848    case DAHDI_EVENT_DTMFUP:
02849       res = ANALOG_EVENT_DTMFUP;
02850       break;
02851    default:
02852       switch(event & 0xFFFF0000) {
02853       case DAHDI_EVENT_PULSEDIGIT:
02854       case DAHDI_EVENT_DTMFDOWN:
02855       case DAHDI_EVENT_DTMFUP:
02856          /* The event includes a digit number in the low word.
02857           * Converting it to a 'enum analog_event' would remove
02858           * that information. Thus it is returned as-is.
02859           */
02860          return event;
02861       }
02862 
02863       res = ANALOG_EVENT_ERROR;
02864       break;
02865    }
02866 
02867    return res;
02868 }
02869 
02870 static inline int dahdi_wait_event(int fd);
02871 
02872 static int my_wait_event(void *pvt)
02873 {
02874    struct dahdi_pvt *p = pvt;
02875 
02876    return dahdi_wait_event(p->subs[SUB_REAL].dfd);
02877 }
02878 
02879 static int my_get_event(void *pvt)
02880 {
02881    struct dahdi_pvt *p = pvt;
02882    int res;
02883 
02884    if (p->fake_event) {
02885       res = p->fake_event;
02886       p->fake_event = 0;
02887    } else
02888       res = dahdi_get_event(p->subs[SUB_REAL].dfd);
02889 
02890    return dahdievent_to_analogevent(res);
02891 }
02892 
02893 static int my_is_off_hook(void *pvt)
02894 {
02895    struct dahdi_pvt *p = pvt;
02896    int res;
02897    struct dahdi_params par;
02898 
02899    memset(&par, 0, sizeof(par));
02900 
02901    if (p->subs[SUB_REAL].dfd > -1)
02902       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
02903    else {
02904       /* Assume not off hook on CVRS */
02905       res = 0;
02906       par.rxisoffhook = 0;
02907    }
02908    if (res) {
02909       ast_log(LOG_WARNING, "Unable to check hook state on channel %d: %s\n", p->channel, strerror(errno));
02910    }
02911 
02912    if ((p->sig == SIG_FXSKS) || (p->sig == SIG_FXSGS)) {
02913       /* When "onhook" that means no battery on the line, and thus
02914       it is out of service..., if it's on a TDM card... If it's a channel
02915       bank, there is no telling... */
02916       return (par.rxbits > -1) || par.rxisoffhook;
02917    }
02918 
02919    return par.rxisoffhook;
02920 }
02921 
02922 static void dahdi_enable_ec(struct dahdi_pvt *p);
02923 static void dahdi_disable_ec(struct dahdi_pvt *p);
02924 
02925 static int my_set_echocanceller(void *pvt, int enable)
02926 {
02927    struct dahdi_pvt *p = pvt;
02928 
02929    if (enable)
02930       dahdi_enable_ec(p);
02931    else
02932       dahdi_disable_ec(p);
02933 
02934    return 0;
02935 }
02936 
02937 static int dahdi_ring_phone(struct dahdi_pvt *p);
02938 
02939 static int my_ring(void *pvt)
02940 {
02941    struct dahdi_pvt *p = pvt;
02942 
02943    return dahdi_ring_phone(p);
02944 }
02945 
02946 static int my_flash(void *pvt)
02947 {
02948    struct dahdi_pvt *p = pvt;
02949    int func = DAHDI_FLASH;
02950    return ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &func);
02951 }
02952 
02953 static inline int dahdi_set_hook(int fd, int hs);
02954 
02955 static int my_off_hook(void *pvt)
02956 {
02957    struct dahdi_pvt *p = pvt;
02958    return dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
02959 }
02960 
02961 static void my_set_needringing(void *pvt, int value)
02962 {
02963    struct dahdi_pvt *p = pvt;
02964    p->subs[SUB_REAL].needringing = value;
02965 }
02966 
02967 static void my_set_polarity(void *pvt, int value)
02968 {
02969    struct dahdi_pvt *p = pvt;
02970 
02971    if (p->channel == CHAN_PSEUDO) {
02972       return;
02973    }
02974    p->polarity = value;
02975    ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETPOLARITY, &value);
02976 }
02977 
02978 static void my_start_polarityswitch(void *pvt)
02979 {
02980    struct dahdi_pvt *p = pvt;
02981 
02982    if (p->answeronpolarityswitch || p->hanguponpolarityswitch) {
02983       my_set_polarity(pvt, 0);
02984    }
02985 }
02986 
02987 static void my_answer_polarityswitch(void *pvt)
02988 {
02989    struct dahdi_pvt *p = pvt;
02990 
02991    if (!p->answeronpolarityswitch) {
02992       return;
02993    }
02994 
02995    my_set_polarity(pvt, 1);
02996 }
02997 
02998 static void my_hangup_polarityswitch(void *pvt)
02999 {
03000    struct dahdi_pvt *p = pvt;
03001 
03002    if (!p->hanguponpolarityswitch) {
03003       return;
03004    }
03005 
03006    if (p->answeronpolarityswitch) {
03007       my_set_polarity(pvt, 0);
03008    } else {
03009       my_set_polarity(pvt, 1);
03010    }
03011 }
03012 
03013 static int my_start(void *pvt)
03014 {
03015    struct dahdi_pvt *p = pvt;
03016    int x = DAHDI_START;
03017 
03018    return ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
03019 }
03020 
03021 static int my_dial_digits(void *pvt, enum analog_sub sub, struct analog_dialoperation *dop)
03022 {
03023    int index = analogsub_to_dahdisub(sub);
03024    int res;
03025    struct dahdi_pvt *p = pvt;
03026    struct dahdi_dialoperation ddop;
03027 
03028    if (dop->op != ANALOG_DIAL_OP_REPLACE) {
03029       ast_log(LOG_ERROR, "Fix the dial_digits callback!\n");
03030       return -1;
03031    }
03032 
03033    if (sub != ANALOG_SUB_REAL) {
03034       ast_log(LOG_ERROR, "Trying to dial_digits '%s' on channel %d subchannel %d\n",
03035          dop->dialstr, p->channel, sub);
03036       return -1;
03037    }
03038 
03039    ddop.op = DAHDI_DIAL_OP_REPLACE;
03040    ast_copy_string(ddop.dialstr, dop->dialstr, sizeof(ddop.dialstr));
03041 
03042    ast_debug(1, "Channel %d: Sending '%s' to DAHDI_DIAL.\n", p->channel, ddop.dialstr);
03043 
03044    res = ioctl(p->subs[index].dfd, DAHDI_DIAL, &ddop);
03045    if (res == -1) {
03046       ast_debug(1, "DAHDI_DIAL ioctl failed on %s: %s\n", p->owner->name, strerror(errno));
03047    }
03048 
03049    return res;
03050 }
03051 
03052 static void dahdi_train_ec(struct dahdi_pvt *p);
03053 
03054 static int my_train_echocanceller(void *pvt)
03055 {
03056    struct dahdi_pvt *p = pvt;
03057 
03058    dahdi_train_ec(p);
03059 
03060    return 0;
03061 }
03062 
03063 static int my_is_dialing(void *pvt, enum analog_sub sub)
03064 {
03065    struct dahdi_pvt *p = pvt;
03066    int index;
03067    int x;
03068 
03069    index = analogsub_to_dahdisub(sub);
03070 
03071    if (ioctl(p->subs[index].dfd, DAHDI_DIALING, &x)) {
03072       ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed!\n");
03073       return -1;
03074    }
03075 
03076    return x;
03077 }
03078 
03079 static int my_on_hook(void *pvt)
03080 {
03081    struct dahdi_pvt *p = pvt;
03082    return dahdi_set_hook(p->subs[ANALOG_SUB_REAL].dfd, DAHDI_ONHOOK);
03083 }
03084 
03085 #if defined(HAVE_PRI)
03086 static void my_pri_fixup_chans(void *chan_old, void *chan_new)
03087 {
03088    struct dahdi_pvt *old_chan = chan_old;
03089    struct dahdi_pvt *new_chan = chan_new;
03090 
03091    new_chan->owner = old_chan->owner;
03092    old_chan->owner = NULL;
03093    if (new_chan->owner) {
03094       new_chan->owner->tech_pvt = new_chan;
03095       new_chan->owner->fds[0] = new_chan->subs[SUB_REAL].dfd;
03096       new_chan->subs[SUB_REAL].owner = old_chan->subs[SUB_REAL].owner;
03097       old_chan->subs[SUB_REAL].owner = NULL;
03098    }
03099    /* Copy any DSP that may be present */
03100    new_chan->dsp = old_chan->dsp;
03101    new_chan->dsp_features = old_chan->dsp_features;
03102    old_chan->dsp = NULL;
03103    old_chan->dsp_features = 0;
03104 
03105    /* Transfer flags from the old channel. */
03106    new_chan->dialing = old_chan->dialing;
03107    new_chan->digital = old_chan->digital;
03108    new_chan->outgoing = old_chan->outgoing;
03109    old_chan->dialing = 0;
03110    old_chan->digital = 0;
03111    old_chan->outgoing = 0;
03112 
03113    /* More stuff to transfer to the new channel. */
03114    new_chan->law = old_chan->law;
03115    strcpy(new_chan->dialstring, old_chan->dialstring);
03116 }
03117 #endif   /* defined(HAVE_PRI) */
03118 
03119 #if defined(HAVE_PRI)
03120 static int sig_pri_tone_to_dahditone(enum sig_pri_tone tone)
03121 {
03122    switch (tone) {
03123    case SIG_PRI_TONE_RINGTONE:
03124       return DAHDI_TONE_RINGTONE;
03125    case SIG_PRI_TONE_STUTTER:
03126       return DAHDI_TONE_STUTTER;
03127    case SIG_PRI_TONE_CONGESTION:
03128       return DAHDI_TONE_CONGESTION;
03129    case SIG_PRI_TONE_DIALTONE:
03130       return DAHDI_TONE_DIALTONE;
03131    case SIG_PRI_TONE_DIALRECALL:
03132       return DAHDI_TONE_DIALRECALL;
03133    case SIG_PRI_TONE_INFO:
03134       return DAHDI_TONE_INFO;
03135    case SIG_PRI_TONE_BUSY:
03136       return DAHDI_TONE_BUSY;
03137    default:
03138       return -1;
03139    }
03140 }
03141 #endif   /* defined(HAVE_PRI) */
03142 
03143 #if defined(HAVE_PRI)
03144 static int pri_destroy_dchan(struct sig_pri_span *pri);
03145 
03146 static void my_handle_dchan_exception(struct sig_pri_span *pri, int index)
03147 {
03148    int x;
03149 
03150    ioctl(pri->fds[index], DAHDI_GETEVENT, &x);
03151    switch (x) {
03152    case DAHDI_EVENT_NONE:
03153       break;
03154    case DAHDI_EVENT_ALARM:
03155    case DAHDI_EVENT_NOALARM:
03156       if (sig_pri_is_alarm_ignored(pri)) {
03157          break;
03158       }
03159       /* Fall through */
03160    default:
03161       ast_log(LOG_NOTICE, "PRI got event: %s (%d) on D-channel of span %d\n",
03162          event2str(x), x, pri->span);
03163       break;
03164    }
03165    /* Keep track of alarm state */
03166    switch (x) {
03167    case DAHDI_EVENT_ALARM:
03168       pri_event_alarm(pri, index, 0);
03169       break;
03170    case DAHDI_EVENT_NOALARM:
03171       pri_event_noalarm(pri, index, 0);
03172       break;
03173    case DAHDI_EVENT_REMOVED:
03174       pri_destroy_dchan(pri);
03175       break;
03176    default:
03177       break;
03178    }
03179 }
03180 #endif   /* defined(HAVE_PRI) */
03181 
03182 #if defined(HAVE_PRI)
03183 static int my_pri_play_tone(void *pvt, enum sig_pri_tone tone)
03184 {
03185    struct dahdi_pvt *p = pvt;
03186 
03187    return tone_zone_play_tone(p->subs[SUB_REAL].dfd, sig_pri_tone_to_dahditone(tone));
03188 }
03189 #endif   /* defined(HAVE_PRI) */
03190 
03191 #if defined(HAVE_PRI) || defined(HAVE_SS7)
03192 /*!
03193  * \internal
03194  * \brief Set the caller id information.
03195  * \since 1.8
03196  *
03197  * \param pvt DAHDI private structure
03198  * \param caller Caller-id information to set.
03199  *
03200  * \return Nothing
03201  */
03202 static void my_set_callerid(void *pvt, const struct ast_party_caller *caller)
03203 {
03204    struct dahdi_pvt *p = pvt;
03205 
03206    ast_copy_string(p->cid_num,
03207       S_COR(caller->id.number.valid, caller->id.number.str, ""),
03208       sizeof(p->cid_num));
03209    ast_copy_string(p->cid_name,
03210       S_COR(caller->id.name.valid, caller->id.name.str, ""),
03211       sizeof(p->cid_name));
03212    ast_copy_string(p->cid_subaddr,
03213       S_COR(caller->id.subaddress.valid, caller->id.subaddress.str, ""),
03214       sizeof(p->cid_subaddr));
03215    p->cid_ton = caller->id.number.plan;
03216    p->callingpres = ast_party_id_presentation(&caller->id);
03217    if (caller->id.tag) {
03218       ast_copy_string(p->cid_tag, caller->id.tag, sizeof(p->cid_tag));
03219    }
03220    ast_copy_string(p->cid_ani,
03221       S_COR(caller->ani.number.valid, caller->ani.number.str, ""),
03222       sizeof(p->cid_ani));
03223    p->cid_ani2 = caller->ani2;
03224 }
03225 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
03226 
03227 #if defined(HAVE_PRI) || defined(HAVE_SS7)
03228 /*!
03229  * \internal
03230  * \brief Set the Dialed Number Identifier.
03231  * \since 1.8
03232  *
03233  * \param pvt DAHDI private structure
03234  * \param dnid Dialed Number Identifier string.
03235  *
03236  * \return Nothing
03237  */
03238 static void my_set_dnid(void *pvt, const char *dnid)
03239 {
03240    struct dahdi_pvt *p = pvt;
03241 
03242    ast_copy_string(p->dnid, dnid, sizeof(p->dnid));
03243 }
03244 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
03245 
03246 #if defined(HAVE_PRI)
03247 /*!
03248  * \internal
03249  * \brief Set the Redirecting Directory Number Information Service (RDNIS).
03250  * \since 1.8
03251  *
03252  * \param pvt DAHDI private structure
03253  * \param rdnis Redirecting Directory Number Information Service (RDNIS) string.
03254  *
03255  * \return Nothing
03256  */
03257 static void my_set_rdnis(void *pvt, const char *rdnis)
03258 {
03259    struct dahdi_pvt *p = pvt;
03260 
03261    ast_copy_string(p->rdnis, rdnis, sizeof(p->rdnis));
03262 }
03263 #endif   /* defined(HAVE_PRI) */
03264 
03265 #if defined(HAVE_PRI)
03266 /*!
03267  * \internal
03268  * \brief Make a dialstring for native ISDN CC to recall properly.
03269  * \since 1.8
03270  *
03271  * \param priv Channel private control structure.
03272  * \param buf Where to put the modified dialstring.
03273  * \param buf_size Size of modified dialstring buffer.
03274  *
03275  * \details
03276  * original dialstring:
03277  * DAHDI/[i<span>-](g|G|r|R)<group#(0-63)>[c|r<cadance#>|d][/extension[/options]]
03278  *
03279  * The modified dialstring will have prefixed the channel-group section
03280  * with the ISDN channel restriction.
03281  *
03282  * buf:
03283  * DAHDI/i<span>-(g|G|r|R)<group#(0-63)>[c|r<cadance#>|d][/extension[/options]]
03284  *
03285  * The routine will check to see if the ISDN channel restriction is already
03286  * in the original dialstring.
03287  *
03288  * \return Nothing
03289  */
03290 static void my_pri_make_cc_dialstring(void *priv, char *buf, size_t buf_size)
03291 {
03292    char *dial;
03293    struct dahdi_pvt *pvt;
03294    AST_DECLARE_APP_ARGS(args,
03295       AST_APP_ARG(tech);   /* channel technology token */
03296       AST_APP_ARG(group);  /* channel/group token */
03297       //AST_APP_ARG(ext);  /* extension token */
03298       //AST_APP_ARG(opts); /* options token */
03299       //AST_APP_ARG(other);   /* Any remining unused arguments */
03300    );
03301 
03302    pvt = priv;
03303    dial = ast_strdupa(pvt->dialstring);
03304    AST_NONSTANDARD_APP_ARGS(args, dial, '/');
03305    if (!args.tech) {
03306       ast_copy_string(buf, pvt->dialstring, buf_size);
03307       return;
03308    }
03309    if (!args.group) {
03310       /* Append the ISDN span channel restriction to the dialstring. */
03311       snprintf(buf, buf_size, "%s/i%d-", args.tech, pvt->pri->span);
03312       return;
03313    }
03314    if (isdigit(args.group[0]) || args.group[0] == 'i' || strchr(args.group, '!')) {
03315       /* The ISDN span channel restriction is not needed or already
03316        * in the dialstring. */
03317       ast_copy_string(buf, pvt->dialstring, buf_size);
03318       return;
03319    }
03320    /* Insert the ISDN span channel restriction into the dialstring. */
03321    snprintf(buf, buf_size, "%s/i%d-%s", args.tech, pvt->pri->span, args.group);
03322 }
03323 #endif   /* defined(HAVE_PRI) */
03324 
03325 #if defined(HAVE_PRI)
03326 /*!
03327  * \internal
03328  * \brief Reevaluate the PRI span device state.
03329  * \since 1.8
03330  *
03331  * \param pri Asterisk D channel control structure.
03332  *
03333  * \return Nothing
03334  *
03335  * \note Assumes the pri->lock is already obtained.
03336  */
03337 static void dahdi_pri_update_span_devstate(struct sig_pri_span *pri)
03338 {
03339    unsigned idx;
03340    unsigned num_b_chans;   /* Number of B channels provisioned on the span. */
03341    unsigned in_use;     /* Number of B channels in use on the span. */
03342    unsigned in_alarm;      /* TRUE if the span is in alarm condition. */
03343    enum ast_device_state new_state;
03344 
03345    /* Count the number of B channels and the number of B channels in use. */
03346    num_b_chans = 0;
03347    in_use = 0;
03348    in_alarm = 1;
03349    for (idx = pri->numchans; idx--;) {
03350       if (pri->pvts[idx] && !pri->pvts[idx]->no_b_channel) {
03351          /* This is a B channel interface. */
03352          ++num_b_chans;
03353          if (!sig_pri_is_chan_available(pri->pvts[idx])) {
03354             ++in_use;
03355          }
03356          if (!pri->pvts[idx]->inalarm) {
03357             /* There is a channel that is not in alarm. */
03358             in_alarm = 0;
03359          }
03360       }
03361    }
03362 
03363    /* Update the span congestion device state and report any change. */
03364    if (in_alarm) {
03365       new_state = AST_DEVICE_UNAVAILABLE;
03366    } else {
03367       new_state = num_b_chans == in_use ? AST_DEVICE_BUSY : AST_DEVICE_NOT_INUSE;
03368    }
03369    if (pri->congestion_devstate != new_state) {
03370       pri->congestion_devstate = new_state;
03371       ast_devstate_changed(AST_DEVICE_UNKNOWN, AST_DEVSTATE_NOT_CACHABLE, "DAHDI/I%d/congestion", pri->span);
03372    }
03373 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
03374    /* Update the span threshold device state and report any change. */
03375    if (in_alarm) {
03376       new_state = AST_DEVICE_UNAVAILABLE;
03377    } else if (!in_use) {
03378       new_state = AST_DEVICE_NOT_INUSE;
03379    } else if (!pri->user_busy_threshold) {
03380       new_state = in_use < num_b_chans ? AST_DEVICE_INUSE : AST_DEVICE_BUSY;
03381    } else {
03382       new_state = in_use < pri->user_busy_threshold ? AST_DEVICE_INUSE
03383          : AST_DEVICE_BUSY;
03384    }
03385    if (pri->threshold_devstate != new_state) {
03386       pri->threshold_devstate = new_state;
03387       ast_devstate_changed(AST_DEVICE_UNKNOWN, AST_DEVSTATE_NOT_CACHABLE, "DAHDI/I%d/threshold", pri->span);
03388    }
03389 #endif   /* defined(THRESHOLD_DEVSTATE_PLACEHOLDER) */
03390 }
03391 #endif   /* defined(HAVE_PRI) */
03392 
03393 #if defined(HAVE_PRI)
03394 /*!
03395  * \internal
03396  * \brief Reference this module.
03397  * \since 1.8
03398  *
03399  * \return Nothing
03400  */
03401 static void my_module_ref(void)
03402 {
03403    ast_module_ref(ast_module_info->self);
03404 }
03405 #endif   /* defined(HAVE_PRI) */
03406 
03407 #if defined(HAVE_PRI)
03408 /*!
03409  * \internal
03410  * \brief Unreference this module.
03411  * \since 1.8
03412  *
03413  * \return Nothing
03414  */
03415 static void my_module_unref(void)
03416 {
03417    ast_module_unref(ast_module_info->self);
03418 }
03419 #endif   /* defined(HAVE_PRI) */
03420 
03421 #if defined(HAVE_PRI)
03422 #if defined(HAVE_PRI_CALL_WAITING)
03423 static void my_pri_init_config(void *priv, struct sig_pri_span *pri);
03424 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
03425 static int dahdi_new_pri_nobch_channel(struct sig_pri_span *pri);
03426 
03427 static struct sig_pri_callback dahdi_pri_callbacks =
03428 {
03429    .handle_dchan_exception = my_handle_dchan_exception,
03430    .play_tone = my_pri_play_tone,
03431    .set_echocanceller = my_set_echocanceller,
03432    .dsp_reset_and_flush_digits = my_dsp_reset_and_flush_digits,
03433    .lock_private = my_lock_private,
03434    .unlock_private = my_unlock_private,
03435    .new_ast_channel = my_new_pri_ast_channel,
03436    .fixup_chans = my_pri_fixup_chans,
03437    .set_alarm = my_set_alarm,
03438    .set_dialing = my_set_dialing,
03439    .set_outgoing = my_set_outgoing,
03440    .set_digital = my_set_digital,
03441    .set_callerid = my_set_callerid,
03442    .set_dnid = my_set_dnid,
03443    .set_rdnis = my_set_rdnis,
03444    .new_nobch_intf = dahdi_new_pri_nobch_channel,
03445 #if defined(HAVE_PRI_CALL_WAITING)
03446    .init_config = my_pri_init_config,
03447 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
03448    .get_orig_dialstring = my_get_orig_dialstring,
03449    .make_cc_dialstring = my_pri_make_cc_dialstring,
03450    .update_span_devstate = dahdi_pri_update_span_devstate,
03451    .module_ref = my_module_ref,
03452    .module_unref = my_module_unref,
03453    .dial_digits = my_pri_dial_digits,
03454    .open_media = my_pri_ss7_open_media,
03455    .ami_channel_event = my_ami_channel_event,
03456 };
03457 #endif   /* defined(HAVE_PRI) */
03458 
03459 #if defined(HAVE_SS7)
03460 /*!
03461  * \internal
03462  * \brief Handle the SS7 link exception.
03463  * \since 1.8
03464  *
03465  * \param linkset Controlling linkset for the channel.
03466  * \param which Link index of the signaling channel.
03467  *
03468  * \return Nothing
03469  */
03470 static void my_handle_link_exception(struct sig_ss7_linkset *linkset, int which)
03471 {
03472    int event;
03473 
03474    if (ioctl(linkset->fds[which], DAHDI_GETEVENT, &event)) {
03475       ast_log(LOG_ERROR, "SS7: Error in exception retrieval on span %d/%d!\n",
03476          linkset->span, which);
03477       return;
03478    }
03479    switch (event) {
03480    case DAHDI_EVENT_NONE:
03481       break;
03482    case DAHDI_EVENT_ALARM:
03483       ast_log(LOG_ERROR, "SS7 got event: %s(%d) on span %d/%d\n",
03484          event2str(event), event, linkset->span, which);
03485       sig_ss7_link_alarm(linkset, which);
03486       break;
03487    case DAHDI_EVENT_NOALARM:
03488       ast_log(LOG_ERROR, "SS7 got event: %s(%d) on span %d/%d\n",
03489          event2str(event), event, linkset->span, which);
03490       sig_ss7_link_noalarm(linkset, which);
03491       break;
03492    default:
03493       ast_log(LOG_NOTICE, "SS7 got event: %s(%d) on span %d/%d\n",
03494          event2str(event), event, linkset->span, which);
03495       break;
03496    }
03497 }
03498 #endif   /* defined(HAVE_SS7) */
03499 
03500 #if defined(HAVE_SS7)
03501 static void my_ss7_set_loopback(void *pvt, int enable)
03502 {
03503    struct dahdi_pvt *p = pvt;
03504 
03505    if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_LOOPBACK, &enable)) {
03506       ast_log(LOG_WARNING, "Unable to set loopback on channel %d: %s\n", p->channel,
03507          strerror(errno));
03508    }
03509 }
03510 #endif   /* defined(HAVE_SS7) */
03511 
03512 #if defined(HAVE_SS7)
03513 /*!
03514  * \internal
03515  * \brief Create a new asterisk channel structure for SS7.
03516  * \since 1.8
03517  *
03518  * \param pvt Private channel structure.
03519  * \param state Initial state of new channel.
03520  * \param law Combanding law to use.
03521  * \param exten Dialplan extension for incoming call.
03522  * \param requestor Channel requesting this new channel.
03523  *
03524  * \retval ast_channel on success.
03525  * \retval NULL on error.
03526  */
03527 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)
03528 {
03529    struct dahdi_pvt *p = pvt;
03530    int audio;
03531    int newlaw;
03532 
03533    /* Set to audio mode at this point */
03534    audio = 1;
03535    if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &audio) == -1)
03536       ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n",
03537          p->channel, audio, strerror(errno));
03538 
03539    if (law != SIG_SS7_DEFLAW) {
03540       dahdi_setlaw(p->subs[SUB_REAL].dfd,
03541          (law == SIG_SS7_ULAW) ? DAHDI_LAW_MULAW : DAHDI_LAW_ALAW);
03542    }
03543 
03544    ast_copy_string(p->exten, exten, sizeof(p->exten));
03545 
03546    newlaw = -1;
03547    switch (law) {
03548    case SIG_SS7_DEFLAW:
03549       newlaw = 0;
03550       break;
03551    case SIG_SS7_ALAW:
03552       newlaw = DAHDI_LAW_ALAW;
03553       break;
03554    case SIG_SS7_ULAW:
03555       newlaw = DAHDI_LAW_MULAW;
03556       break;
03557    }
03558    return dahdi_new(p, state, 0, SUB_REAL, newlaw, requestor ? requestor->linkedid : "");
03559 }
03560 #endif   /* defined(HAVE_SS7) */
03561 
03562 #if defined(HAVE_SS7)
03563 static int sig_ss7_tone_to_dahditone(enum sig_ss7_tone tone)
03564 {
03565    switch (tone) {
03566    case SIG_SS7_TONE_RINGTONE:
03567       return DAHDI_TONE_RINGTONE;
03568    case SIG_SS7_TONE_STUTTER:
03569       return DAHDI_TONE_STUTTER;
03570    case SIG_SS7_TONE_CONGESTION:
03571       return DAHDI_TONE_CONGESTION;
03572    case SIG_SS7_TONE_DIALTONE:
03573       return DAHDI_TONE_DIALTONE;
03574    case SIG_SS7_TONE_DIALRECALL:
03575       return DAHDI_TONE_DIALRECALL;
03576    case SIG_SS7_TONE_INFO:
03577       return DAHDI_TONE_INFO;
03578    case SIG_SS7_TONE_BUSY:
03579       return DAHDI_TONE_BUSY;
03580    default:
03581       return -1;
03582    }
03583 }
03584 #endif   /* defined(HAVE_SS7) */
03585 
03586 #if defined(HAVE_SS7)
03587 static int my_ss7_play_tone(void *pvt, enum sig_ss7_tone tone)
03588 {
03589    struct dahdi_pvt *p = pvt;
03590 
03591    return tone_zone_play_tone(p->subs[SUB_REAL].dfd, sig_ss7_tone_to_dahditone(tone));
03592 }
03593 #endif   /* defined(HAVE_SS7) */
03594 
03595 #if defined(HAVE_SS7)
03596 static struct sig_ss7_callback dahdi_ss7_callbacks =
03597 {
03598    .lock_private = my_lock_private,
03599    .unlock_private = my_unlock_private,
03600 
03601    .set_echocanceller = my_set_echocanceller,
03602    .set_loopback = my_ss7_set_loopback,
03603 
03604    .new_ast_channel = my_new_ss7_ast_channel,
03605    .play_tone = my_ss7_play_tone,
03606 
03607    .handle_link_exception = my_handle_link_exception,
03608    .set_alarm = my_set_alarm,
03609    .set_dialing = my_set_dialing,
03610    .set_outgoing = my_set_outgoing,
03611    .set_digital = my_set_digital,
03612    .set_inservice = my_set_inservice,
03613    .set_locallyblocked = my_set_locallyblocked,
03614    .set_remotelyblocked = my_set_remotelyblocked,
03615    .set_callerid = my_set_callerid,
03616    .set_dnid = my_set_dnid,
03617    .open_media = my_pri_ss7_open_media,
03618 };
03619 #endif   /* defined(HAVE_SS7) */
03620 
03621 /*!
03622  * \brief Send MWI state change
03623  *
03624  * \arg mailbox_full This is the mailbox associated with the FXO line that the
03625  *      MWI state has changed on.
03626  * \arg thereornot This argument should simply be set to 1 or 0, to indicate
03627  *      whether there are messages waiting or not.
03628  *
03629  *  \return nothing
03630  *
03631  * This function does two things:
03632  *
03633  * 1) It generates an internal Asterisk event notifying any other module that
03634  *    cares about MWI that the state of a mailbox has changed.
03635  *
03636  * 2) It runs the script specified by the mwimonitornotify option to allow
03637  *    some custom handling of the state change.
03638  */
03639 static void notify_message(char *mailbox_full, int thereornot)
03640 {
03641    char s[sizeof(mwimonitornotify) + 80];
03642    struct ast_event *event;
03643    char *mailbox, *context;
03644 
03645    /* Strip off @default */
03646    context = mailbox = ast_strdupa(mailbox_full);
03647    strsep(&context, "@");
03648    if (ast_strlen_zero(context))
03649       context = "default";
03650 
03651    if (!(event = ast_event_new(AST_EVENT_MWI,
03652          AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
03653          AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
03654          AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot,
03655          AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot,
03656          AST_EVENT_IE_END))) {
03657       return;
03658    }
03659 
03660    ast_event_queue_and_cache(event);
03661 
03662    if (!ast_strlen_zero(mailbox) && !ast_strlen_zero(mwimonitornotify)) {
03663       snprintf(s, sizeof(s), "%s %s %d", mwimonitornotify, mailbox, thereornot);
03664       ast_safe_system(s);
03665    }
03666 }
03667 
03668 static void my_handle_notify_message(struct ast_channel *chan, void *pvt, int cid_flags, int neon_mwievent)
03669 {
03670    struct dahdi_pvt *p = pvt;
03671 
03672    if (neon_mwievent > -1 && !p->mwimonitor_neon)
03673       return;
03674 
03675    if (neon_mwievent == ANALOG_EVENT_NEONMWI_ACTIVE || cid_flags & CID_MSGWAITING) {
03676       ast_log(LOG_NOTICE, "MWI: Channel %d message waiting, mailbox %s\n", p->channel, p->mailbox);
03677       notify_message(p->mailbox, 1);
03678    } else if (neon_mwievent == ANALOG_EVENT_NEONMWI_INACTIVE || cid_flags & CID_NOMSGWAITING) {
03679       ast_log(LOG_NOTICE, "MWI: Channel %d no message waiting, mailbox %s\n", p->channel, p->mailbox);
03680       notify_message(p->mailbox, 0);
03681    }
03682    /* If the CID had Message waiting payload, assume that this for MWI only and hangup the call */
03683    /* If generated using Ring Pulse Alert, then ring has been answered as a call and needs to be hungup */
03684    if (neon_mwievent == -1 && p->mwimonitor_rpas) {
03685       ast_hangup(chan);
03686       return;
03687    }
03688 }
03689 
03690 static int my_have_progressdetect(void *pvt)
03691 {
03692    struct dahdi_pvt *p = pvt;
03693 
03694    if ((p->callprogress & CALLPROGRESS_PROGRESS)
03695       && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
03696       return 1;
03697    } else {
03698       /* Don't have progress detection. */
03699       return 0;
03700    }
03701 }
03702 
03703 static struct analog_callback dahdi_analog_callbacks =
03704 {
03705    .play_tone = my_play_tone,
03706    .get_event = my_get_event,
03707    .wait_event = my_wait_event,
03708    .is_off_hook = my_is_off_hook,
03709    .set_echocanceller = my_set_echocanceller,
03710    .ring = my_ring,
03711    .flash = my_flash,
03712    .off_hook = my_off_hook,
03713    .dial_digits = my_dial_digits,
03714    .train_echocanceller = my_train_echocanceller,
03715    .on_hook = my_on_hook,
03716    .is_dialing = my_is_dialing,
03717    .allocate_sub = my_allocate_sub,
03718    .unallocate_sub = my_unallocate_sub,
03719    .swap_subs = my_swap_subchannels,
03720    .has_voicemail = my_has_voicemail,
03721    .check_for_conference = my_check_for_conference,
03722    .conf_add = my_conf_add,
03723    .conf_del = my_conf_del,
03724    .complete_conference_update = my_complete_conference_update,
03725    .start = my_start,
03726    .all_subchannels_hungup = my_all_subchannels_hungup,
03727    .lock_private = my_lock_private,
03728    .unlock_private = my_unlock_private,
03729    .deadlock_avoidance_private = my_deadlock_avoidance_private,
03730    .handle_dtmf = my_handle_dtmf,
03731    .wink = my_wink,
03732    .new_ast_channel = my_new_analog_ast_channel,
03733    .dsp_set_digitmode = my_dsp_set_digitmode,
03734    .dsp_reset_and_flush_digits = my_dsp_reset_and_flush_digits,
03735    .send_callerid = my_send_callerid,
03736    .callwait = my_callwait,
03737    .stop_callwait = my_stop_callwait,
03738    .get_callerid = my_get_callerid,
03739    .start_cid_detect = my_start_cid_detect,
03740    .stop_cid_detect = my_stop_cid_detect,
03741    .handle_notify_message = my_handle_notify_message,
03742    .increase_ss_count = my_increase_ss_count,
03743    .decrease_ss_count = my_decrease_ss_count,
03744    .distinctive_ring = my_distinctive_ring,
03745    .set_linear_mode = my_set_linear_mode,
03746    .set_inthreeway = my_set_inthreeway,
03747    .get_and_handle_alarms = my_get_and_handle_alarms,
03748    .get_sigpvt_bridged_channel = my_get_sigpvt_bridged_channel,
03749    .get_sub_fd = my_get_sub_fd,
03750    .set_cadence = my_set_cadence,
03751    .set_alarm = my_set_alarm,
03752    .set_dialing = my_set_dialing,
03753    .set_outgoing = my_set_outgoing,
03754    .set_ringtimeout = my_set_ringtimeout,
03755    .set_waitingfordt = my_set_waitingfordt,
03756    .check_waitingfordt = my_check_waitingfordt,
03757    .set_confirmanswer = my_set_confirmanswer,
03758    .check_confirmanswer = my_check_confirmanswer,
03759    .set_callwaiting = my_set_callwaiting,
03760    .cancel_cidspill = my_cancel_cidspill,
03761    .confmute = my_confmute,
03762    .set_pulsedial = my_set_pulsedial,
03763    .set_new_owner = my_set_new_owner,
03764    .get_orig_dialstring = my_get_orig_dialstring,
03765    .set_needringing = my_set_needringing,
03766    .set_polarity = my_set_polarity,
03767    .start_polarityswitch = my_start_polarityswitch,
03768    .answer_polarityswitch = my_answer_polarityswitch,
03769    .hangup_polarityswitch = my_hangup_polarityswitch,
03770    .have_progressdetect = my_have_progressdetect,
03771 };
03772 
03773 /*! Round robin search locations. */
03774 static struct dahdi_pvt *round_robin[32];
03775 
03776 #define dahdi_get_index(ast, p, nullok)   _dahdi_get_index(ast, p, nullok, __PRETTY_FUNCTION__, __LINE__)
03777 static int _dahdi_get_index(struct ast_channel *ast, struct dahdi_pvt *p, int nullok, const char *fname, unsigned long line)
03778 {
03779    int res;
03780    if (p->subs[SUB_REAL].owner == ast)
03781       res = 0;
03782    else if (p->subs[SUB_CALLWAIT].owner == ast)
03783       res = 1;
03784    else if (p->subs[SUB_THREEWAY].owner == ast)
03785       res = 2;
03786    else {
03787       res = -1;
03788       if (!nullok)
03789          ast_log(LOG_WARNING,
03790             "Unable to get index for '%s' on channel %d (%s(), line %lu)\n",
03791             ast ? ast->name : "", p->channel, fname, line);
03792    }
03793    return res;
03794 }
03795 
03796 /*!
03797  * \internal
03798  * \brief Obtain the specified subchannel owner lock if the owner exists.
03799  *
03800  * \param pvt Channel private struct.
03801  * \param sub_idx Subchannel owner to lock.
03802  *
03803  * \note Assumes the pvt->lock is already obtained.
03804  *
03805  * \note
03806  * Because deadlock avoidance may have been necessary, you need to confirm
03807  * the state of things before continuing.
03808  *
03809  * \return Nothing
03810  */
03811 static void dahdi_lock_sub_owner(struct dahdi_pvt *pvt, int sub_idx)
03812 {
03813    for (;;) {
03814       if (!pvt->subs[sub_idx].owner) {
03815          /* No subchannel owner pointer */
03816          break;
03817       }
03818       if (!ast_channel_trylock(pvt->subs[sub_idx].owner)) {
03819          /* Got subchannel owner lock */
03820          break;
03821       }
03822       /* We must unlock the private to avoid the possibility of a deadlock */
03823       DEADLOCK_AVOIDANCE(&pvt->lock);
03824    }
03825 }
03826 
03827 static void wakeup_sub(struct dahdi_pvt *p, int a)
03828 {
03829    dahdi_lock_sub_owner(p, a);
03830    if (p->subs[a].owner) {
03831       ast_queue_frame(p->subs[a].owner, &ast_null_frame);
03832       ast_channel_unlock(p->subs[a].owner);
03833    }
03834 }
03835 
03836 static void dahdi_queue_frame(struct dahdi_pvt *p, struct ast_frame *f)
03837 {
03838    for (;;) {
03839       if (p->owner) {
03840          if (ast_channel_trylock(p->owner)) {
03841             DEADLOCK_AVOIDANCE(&p->lock);
03842          } else {
03843             ast_queue_frame(p->owner, f);
03844             ast_channel_unlock(p->owner);
03845             break;
03846          }
03847       } else
03848          break;
03849    }
03850 }
03851 
03852 static void handle_clear_alarms(struct dahdi_pvt *p)
03853 {
03854 #if defined(HAVE_PRI)
03855    if (dahdi_sig_pri_lib_handles(p->sig) && sig_pri_is_alarm_ignored(p->pri)) {
03856       return;
03857    }
03858 #endif   /* defined(HAVE_PRI) */
03859 
03860    if (report_alarms & REPORT_CHANNEL_ALARMS) {
03861       ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel);
03862       manager_event(EVENT_FLAG_SYSTEM, "AlarmClear", "Channel: %d\r\n", p->channel);
03863    }
03864    if (report_alarms & REPORT_SPAN_ALARMS && p->manages_span_alarms) {
03865       ast_log(LOG_NOTICE, "Alarm cleared on span %d\n", p->span);
03866       manager_event(EVENT_FLAG_SYSTEM, "SpanAlarmClear", "Span: %d\r\n", p->span);
03867    }
03868 }
03869 
03870 #ifdef HAVE_OPENR2
03871 
03872 static int dahdi_r2_answer(struct dahdi_pvt *p)
03873 {
03874    int res = 0;
03875    /* openr2 1.1.0 and older does not even define OR2_LIB_INTERFACE
03876    * and does not has support for openr2_chan_answer_call_with_mode
03877    *  */
03878 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
03879    const char *double_answer = pbx_builtin_getvar_helper(p->owner, "MFCR2_DOUBLE_ANSWER");
03880    int wants_double_answer = ast_true(double_answer) ? 1 : 0;
03881    if (!double_answer) {
03882       /* this still can result in double answer if the channel context
03883       * was configured that way */
03884       res = openr2_chan_answer_call(p->r2chan);
03885    } else if (wants_double_answer) {
03886       res = openr2_chan_answer_call_with_mode(p->r2chan, OR2_ANSWER_DOUBLE);
03887    } else {
03888       res = openr2_chan_answer_call_with_mode(p->r2chan, OR2_ANSWER_SIMPLE);
03889    }
03890 #else
03891    res = openr2_chan_answer_call(p->r2chan);
03892 #endif
03893    return res;
03894 }
03895 
03896 
03897 
03898 /* should be called with the ast_channel locked */
03899 static openr2_calling_party_category_t dahdi_r2_get_channel_category(struct ast_channel *c)
03900 {
03901    openr2_calling_party_category_t cat;
03902    const char *catstr = pbx_builtin_getvar_helper(c, "MFCR2_CATEGORY");
03903    struct dahdi_pvt *p = c->tech_pvt;
03904    if (ast_strlen_zero(catstr)) {
03905       ast_debug(1, "No MFC/R2 category specified for chan %s, using default %s\n",
03906             c->name, openr2_proto_get_category_string(p->mfcr2_category));
03907       return p->mfcr2_category;
03908    }
03909    if ((cat = openr2_proto_get_category(catstr)) == OR2_CALLING_PARTY_CATEGORY_UNKNOWN) {
03910       ast_log(LOG_WARNING, "Invalid category specified '%s' for chan %s, using default %s\n",
03911             catstr, c->name, openr2_proto_get_category_string(p->mfcr2_category));
03912       return p->mfcr2_category;
03913    }
03914    ast_debug(1, "Using category %s\n", catstr);
03915    return cat;
03916 }
03917 
03918 static void dahdi_r2_on_call_init(openr2_chan_t *r2chan)
03919 {
03920    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
03921    ast_mutex_lock(&p->lock);
03922    if (p->mfcr2call) {
03923       ast_mutex_unlock(&p->lock);
03924       /* TODO: This can happen when some other thread just finished dahdi_request requesting this very same
03925          interface but has not yet seized the line (dahdi_call), and the far end wins and seize the line,
03926          can we avoid this somehow?, at this point when dahdi_call send the seize, it is likely that since
03927          the other end will see our seize as a forced release and drop the call, we will see an invalid
03928          pattern that will be seen and treated as protocol error. */
03929       ast_log(LOG_ERROR, "Collision of calls on chan %d detected!.\n", openr2_chan_get_number(r2chan));
03930       return;
03931    }
03932    p->mfcr2call = 1;
03933    /* better safe than sorry ... */
03934    p->cid_name[0] = '\0';
03935    p->cid_num[0] = '\0';
03936    p->cid_subaddr[0] = '\0';
03937    p->rdnis[0] = '\0';
03938    p->exten[0] = '\0';
03939    p->mfcr2_ani_index = '\0';
03940    p->mfcr2_dnis_index = '\0';
03941    p->mfcr2_dnis_matched = 0;
03942    p->mfcr2_answer_pending = 0;
03943    p->mfcr2_call_accepted = 0;
03944    ast_mutex_unlock(&p->lock);
03945    ast_verbose("New MFC/R2 call detected on chan %d.\n", openr2_chan_get_number(r2chan));
03946 }
03947 
03948 static void dahdi_r2_on_hardware_alarm(openr2_chan_t *r2chan, int alarm)
03949 {
03950    int res;
03951    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
03952    ast_mutex_lock(&p->lock);
03953    p->inalarm = alarm ? 1 : 0;
03954    if (p->inalarm) {
03955       res = get_alarms(p);
03956       handle_alarms(p, res);
03957    } else {
03958       handle_clear_alarms(p);
03959    }
03960    ast_mutex_unlock(&p->lock);
03961 }
03962 
03963 static void dahdi_r2_on_os_error(openr2_chan_t *r2chan, int errorcode)
03964 {
03965    ast_log(LOG_ERROR, "OS error on chan %d: %s\n", openr2_chan_get_number(r2chan), strerror(errorcode));
03966 }
03967 
03968 static void dahdi_r2_on_protocol_error(openr2_chan_t *r2chan, openr2_protocol_error_t reason)
03969 {
03970    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
03971    ast_log(LOG_ERROR, "MFC/R2 protocol error on chan %d: %s\n", openr2_chan_get_number(r2chan), openr2_proto_get_error(reason));
03972    if (p->owner) {
03973       p->owner->hangupcause = AST_CAUSE_PROTOCOL_ERROR;
03974       p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
03975    }
03976    ast_mutex_lock(&p->lock);
03977    p->mfcr2call = 0;
03978    ast_mutex_unlock(&p->lock);
03979 }
03980 
03981 static void dahdi_r2_disconnect_call(struct dahdi_pvt *p, openr2_call_disconnect_cause_t cause)
03982 {
03983    if (openr2_chan_disconnect_call(p->r2chan, cause)) {
03984       ast_log(LOG_NOTICE, "Bad! failed to disconnect call on channel %d with reason %s, hope for the best!\n",
03985          p->channel, openr2_proto_get_disconnect_string(cause));
03986       /* force the chan to idle and release the call flag now since we will not see a clean on_call_end */
03987       openr2_chan_set_idle(p->r2chan);
03988       ast_mutex_lock(&p->lock);
03989       p->mfcr2call = 0;
03990       ast_mutex_unlock(&p->lock);
03991    }
03992 }
03993 
03994 static void dahdi_r2_on_call_offered(openr2_chan_t *r2chan, const char *ani, const char *dnis, openr2_calling_party_category_t category)
03995 {
03996    struct dahdi_pvt *p;
03997    struct ast_channel *c;
03998    ast_verbose("MFC/R2 call offered on chan %d. ANI = %s, DNIS = %s, Category = %s\n",
03999          openr2_chan_get_number(r2chan), ani ? ani : "(restricted)", dnis,
04000          openr2_proto_get_category_string(category));
04001    p = openr2_chan_get_client_data(r2chan);
04002    /* if collect calls are not allowed and this is a collect call, reject it! */
04003    if (!p->mfcr2_allow_collect_calls && category == OR2_CALLING_PARTY_CATEGORY_COLLECT_CALL) {
04004       ast_log(LOG_NOTICE, "Rejecting MFC/R2 collect call\n");
04005       dahdi_r2_disconnect_call(p, OR2_CAUSE_COLLECT_CALL_REJECTED);
04006       return;
04007    }
04008    ast_mutex_lock(&p->lock);
04009    p->mfcr2_recvd_category = category;
04010    /* if we're not supposed to use CID, clear whatever we have */
04011    if (!p->use_callerid) {
04012       ast_log(LOG_DEBUG, "No CID allowed in configuration, CID is being cleared!\n");
04013       p->cid_num[0] = 0;
04014       p->cid_name[0] = 0;
04015    }
04016    /* if we're supposed to answer immediately, clear DNIS and set 's' exten */
04017    if (p->immediate || !openr2_context_get_max_dnis(openr2_chan_get_context(r2chan))) {
04018       ast_log(LOG_DEBUG, "Setting exten => s because of immediate or 0 DNIS configured\n");
04019       p->exten[0] = 's';
04020       p->exten[1] = 0;
04021    }
04022    ast_mutex_unlock(&p->lock);
04023    if (!ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
04024       ast_log(LOG_NOTICE, "MFC/R2 call on channel %d requested non-existent extension '%s' in context '%s'. Rejecting call.\n",
04025             p->channel, p->exten, p->context);
04026       dahdi_r2_disconnect_call(p, OR2_CAUSE_UNALLOCATED_NUMBER);
04027       return;
04028    }
04029    if (!p->mfcr2_accept_on_offer) {
04030       /* The user wants us to start the PBX thread right away without accepting the call first */
04031       c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, NULL);
04032       if (c) {
04033          /* Done here, don't disable reading now since we still need to generate MF tones to accept
04034             the call or reject it and detect the tone off condition of the other end, all of this
04035             will be done in the PBX thread now */
04036          return;
04037       }
04038       ast_log(LOG_WARNING, "Unable to create PBX channel in DAHDI channel %d\n", p->channel);
04039       dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER);
04040    } else if (p->mfcr2_charge_calls) {
04041       ast_log(LOG_DEBUG, "Accepting MFC/R2 call with charge on chan %d\n", p->channel);
04042       openr2_chan_accept_call(r2chan, OR2_CALL_WITH_CHARGE);
04043    } else {
04044       ast_log(LOG_DEBUG, "Accepting MFC/R2 call with no charge on chan %d\n", p->channel);
04045       openr2_chan_accept_call(r2chan, OR2_CALL_NO_CHARGE);
04046    }
04047 }
04048 
04049 static void dahdi_r2_on_call_end(openr2_chan_t *r2chan)
04050 {
04051    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04052    ast_verbose("MFC/R2 call end on channel %d\n", p->channel);
04053    ast_mutex_lock(&p->lock);
04054    p->mfcr2call = 0;
04055    ast_mutex_unlock(&p->lock);
04056 }
04057 
04058 static void dahdi_enable_ec(struct dahdi_pvt *p);
04059 static void dahdi_r2_on_call_accepted(openr2_chan_t *r2chan, openr2_call_mode_t mode)
04060 {
04061    struct dahdi_pvt *p = NULL;
04062    struct ast_channel *c = NULL;
04063    p = openr2_chan_get_client_data(r2chan);
04064    dahdi_enable_ec(p);
04065    p->mfcr2_call_accepted = 1;
04066    /* if it's an incoming call ... */
04067    if (OR2_DIR_BACKWARD == openr2_chan_get_direction(r2chan)) {
04068       ast_verbose("MFC/R2 call has been accepted on backward channel %d\n", openr2_chan_get_number(r2chan));
04069       /* If accept on offer is not set, it means at this point the PBX thread is already
04070          launched (was launched in the 'on call offered' handler) and therefore this callback
04071          is being executed already in the PBX thread rather than the monitor thread, don't launch
04072          any other thread, just disable the openr2 reading and answer the call if needed */
04073       if (!p->mfcr2_accept_on_offer) {
04074          openr2_chan_disable_read(r2chan);
04075          if (p->mfcr2_answer_pending) {
04076             ast_log(LOG_DEBUG, "Answering MFC/R2 call after accepting it on chan %d\n", openr2_chan_get_number(r2chan));
04077             dahdi_r2_answer(p);
04078          }
04079          return;
04080       }
04081       c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, NULL);
04082       if (c) {
04083          /* chan_dahdi will take care of reading from now on in the PBX thread, tell the
04084             library to forget about it */
04085          openr2_chan_disable_read(r2chan);
04086          return;
04087       }
04088       ast_log(LOG_WARNING, "Unable to create PBX channel in DAHDI channel %d\n", p->channel);
04089       /* failed to create the channel, bail out and report it as an out of order line */
04090       dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER);
04091       return;
04092    }
04093    /* this is an outgoing call, no need to launch the PBX thread, most likely we're in one already */
04094    ast_verbose("MFC/R2 call has been accepted on forward channel %d\n", p->channel);
04095    p->subs[SUB_REAL].needringing = 1;
04096    p->dialing = 0;
04097    /* chan_dahdi will take care of reading from now on in the PBX thread, tell the library to forget about it */
04098    openr2_chan_disable_read(r2chan);
04099 }
04100 
04101 static void dahdi_r2_on_call_answered(openr2_chan_t *r2chan)
04102 {
04103    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04104    ast_verbose("MFC/R2 call has been answered on channel %d\n", openr2_chan_get_number(r2chan));
04105    p->subs[SUB_REAL].needanswer = 1;
04106 }
04107 
04108 static void dahdi_r2_on_call_read(openr2_chan_t *r2chan, const unsigned char *buf, int buflen)
04109 {
04110    /*ast_log(LOG_DEBUG, "Read data from dahdi channel %d\n", openr2_chan_get_number(r2chan));*/
04111 }
04112 
04113 static int dahdi_r2_cause_to_ast_cause(openr2_call_disconnect_cause_t cause)
04114 {
04115    switch (cause) {
04116    case OR2_CAUSE_BUSY_NUMBER:
04117       return AST_CAUSE_BUSY;
04118    case OR2_CAUSE_NETWORK_CONGESTION:
04119       return AST_CAUSE_CONGESTION;
04120    case OR2_CAUSE_OUT_OF_ORDER:
04121       return AST_CAUSE_DESTINATION_OUT_OF_ORDER;
04122    case OR2_CAUSE_UNALLOCATED_NUMBER:
04123       return AST_CAUSE_UNREGISTERED;
04124    case OR2_CAUSE_NO_ANSWER:
04125       return AST_CAUSE_NO_ANSWER;
04126    case OR2_CAUSE_NORMAL_CLEARING:
04127       return AST_CAUSE_NORMAL_CLEARING;
04128    case OR2_CAUSE_UNSPECIFIED:
04129    default:
04130       return AST_CAUSE_NOTDEFINED;
04131    }
04132 }
04133 
04134 static void dahdi_r2_on_call_disconnect(openr2_chan_t *r2chan, openr2_call_disconnect_cause_t cause)
04135 {
04136    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04137    ast_verbose("MFC/R2 call disconnected on channel %d\n", openr2_chan_get_number(r2chan));
04138    ast_mutex_lock(&p->lock);
04139    if (!p->owner) {
04140       ast_mutex_unlock(&p->lock);
04141       /* no owner, therefore we can't use dahdi_hangup to disconnect, do it right now */
04142       dahdi_r2_disconnect_call(p, OR2_CAUSE_NORMAL_CLEARING);
04143       return;
04144    }
04145    /* when we have an owner we don't call dahdi_r2_disconnect_call here, that will
04146       be done in dahdi_hangup */
04147    if (p->owner->_state == AST_STATE_UP) {
04148       p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
04149       ast_mutex_unlock(&p->lock);
04150    } else if (openr2_chan_get_direction(r2chan) == OR2_DIR_FORWARD) {
04151       /* being the forward side we must report what happened to the call to whoever requested it */
04152       switch (cause) {
04153       case OR2_CAUSE_BUSY_NUMBER:
04154          p->subs[SUB_REAL].needbusy = 1;
04155          break;
04156       case OR2_CAUSE_NETWORK_CONGESTION:
04157       case OR2_CAUSE_OUT_OF_ORDER:
04158       case OR2_CAUSE_UNALLOCATED_NUMBER:
04159       case OR2_CAUSE_NO_ANSWER:
04160       case OR2_CAUSE_UNSPECIFIED:
04161       case OR2_CAUSE_NORMAL_CLEARING:
04162          p->subs[SUB_REAL].needcongestion = 1;
04163          break;
04164       default:
04165          p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
04166       }
04167       ast_mutex_unlock(&p->lock);
04168    } else {
04169       ast_mutex_unlock(&p->lock);
04170       /* being the backward side and not UP yet, we only need to request hangup */
04171       /* TODO: what about doing this same thing when were AST_STATE_UP? */
04172       ast_queue_hangup_with_cause(p->owner, dahdi_r2_cause_to_ast_cause(cause));
04173    }
04174 }
04175 
04176 static void dahdi_r2_write_log(openr2_log_level_t level, char *logmessage)
04177 {
04178    switch (level) {
04179    case OR2_LOG_NOTICE:
04180       ast_verbose("%s", logmessage);
04181       break;
04182    case OR2_LOG_WARNING:
04183       ast_log(LOG_WARNING, "%s", logmessage);
04184       break;
04185    case OR2_LOG_ERROR:
04186       ast_log(LOG_ERROR, "%s", logmessage);
04187       break;
04188    case OR2_LOG_STACK_TRACE:
04189    case OR2_LOG_MF_TRACE:
04190    case OR2_LOG_CAS_TRACE:
04191    case OR2_LOG_DEBUG:
04192    case OR2_LOG_EX_DEBUG:
04193       ast_log(LOG_DEBUG, "%s", logmessage);
04194       break;
04195    default:
04196       ast_log(LOG_WARNING, "We should handle logging level %d here.\n", level);
04197       ast_log(LOG_DEBUG, "%s", logmessage);
04198       break;
04199    }
04200 }
04201 
04202 static void dahdi_r2_on_line_blocked(openr2_chan_t *r2chan)
04203 {
04204    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04205    ast_mutex_lock(&p->lock);
04206    p->remotelyblocked = 1;
04207    ast_mutex_unlock(&p->lock);
04208    ast_log(LOG_NOTICE, "Far end blocked on chan %d\n", openr2_chan_get_number(r2chan));
04209 }
04210 
04211 static void dahdi_r2_on_line_idle(openr2_chan_t *r2chan)
04212 {
04213    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04214    ast_mutex_lock(&p->lock);
04215    p->remotelyblocked = 0;
04216    ast_mutex_unlock(&p->lock);
04217    ast_log(LOG_NOTICE, "Far end unblocked on chan %d\n", openr2_chan_get_number(r2chan));
04218 }
04219 
04220 static void dahdi_r2_on_context_log(openr2_context_t *r2context, openr2_log_level_t level, const char *fmt, va_list ap)
04221    __attribute__((format (printf, 3, 0)));
04222 static void dahdi_r2_on_context_log(openr2_context_t *r2context, openr2_log_level_t level, const char *fmt, va_list ap)
04223 {
04224 #define CONTEXT_TAG "Context - "
04225    char logmsg[256];
04226    char completemsg[sizeof(logmsg) + sizeof(CONTEXT_TAG) - 1];
04227    vsnprintf(logmsg, sizeof(logmsg), fmt, ap);
04228    snprintf(completemsg, sizeof(completemsg), CONTEXT_TAG "%s", logmsg);
04229    dahdi_r2_write_log(level, completemsg);
04230 #undef CONTEXT_TAG
04231 }
04232 
04233 static void dahdi_r2_on_chan_log(openr2_chan_t *r2chan, openr2_log_level_t level, const char *fmt, va_list ap)
04234    __attribute__((format (printf, 3, 0)));
04235 static void dahdi_r2_on_chan_log(openr2_chan_t *r2chan, openr2_log_level_t level, const char *fmt, va_list ap)
04236 {
04237 #define CHAN_TAG "Chan "
04238    char logmsg[256];
04239    char completemsg[sizeof(logmsg) + sizeof(CHAN_TAG) - 1];
04240    vsnprintf(logmsg, sizeof(logmsg), fmt, ap);
04241    snprintf(completemsg, sizeof(completemsg), CHAN_TAG "%d - %s", openr2_chan_get_number(r2chan), logmsg);
04242    dahdi_r2_write_log(level, completemsg);
04243 }
04244 
04245 static int dahdi_r2_on_dnis_digit_received(openr2_chan_t *r2chan, char digit)
04246 {
04247    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04248    /* if 'immediate' is set, let's stop requesting DNIS */
04249    if (p->immediate) {
04250       return 0;
04251    }
04252    p->exten[p->mfcr2_dnis_index] = digit;
04253    p->rdnis[p->mfcr2_dnis_index] = digit;
04254    p->mfcr2_dnis_index++;
04255    p->exten[p->mfcr2_dnis_index] = 0;
04256    p->rdnis[p->mfcr2_dnis_index] = 0;
04257    /* if the DNIS is a match and cannot match more, stop requesting DNIS */
04258    if ((p->mfcr2_dnis_matched ||
04259        (ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num) && (p->mfcr2_dnis_matched = 1))) &&
04260        !ast_matchmore_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
04261       return 0;
04262    }
04263    /* otherwise keep going */
04264    return 1;
04265 }
04266 
04267 static void dahdi_r2_on_ani_digit_received(openr2_chan_t *r2chan, char digit)
04268 {
04269    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04270    p->cid_num[p->mfcr2_ani_index] = digit;
04271    p->cid_name[p->mfcr2_ani_index] = digit;
04272    p->mfcr2_ani_index++;
04273    p->cid_num[p->mfcr2_ani_index] = 0;
04274    p->cid_name[p->mfcr2_ani_index] = 0;
04275 }
04276 
04277 static void dahdi_r2_on_billing_pulse_received(openr2_chan_t *r2chan)
04278 {
04279    ast_verbose("MFC/R2 billing pulse received on channel %d\n", openr2_chan_get_number(r2chan));
04280 }
04281 
04282 static openr2_event_interface_t dahdi_r2_event_iface = {
04283    .on_call_init = dahdi_r2_on_call_init,
04284    .on_call_offered = dahdi_r2_on_call_offered,
04285    .on_call_accepted = dahdi_r2_on_call_accepted,
04286    .on_call_answered = dahdi_r2_on_call_answered,
04287    .on_call_disconnect = dahdi_r2_on_call_disconnect,
04288    .on_call_end = dahdi_r2_on_call_end,
04289    .on_call_read = dahdi_r2_on_call_read,
04290    .on_hardware_alarm = dahdi_r2_on_hardware_alarm,
04291    .on_os_error = dahdi_r2_on_os_error,
04292    .on_protocol_error = dahdi_r2_on_protocol_error,
04293    .on_line_blocked = dahdi_r2_on_line_blocked,
04294    .on_line_idle = dahdi_r2_on_line_idle,
04295    /* cast seems to be needed to get rid of the annoying warning regarding format attribute  */
04296    .on_context_log = (openr2_handle_context_logging_func)dahdi_r2_on_context_log,
04297    .on_dnis_digit_received = dahdi_r2_on_dnis_digit_received,
04298    .on_ani_digit_received = dahdi_r2_on_ani_digit_received,
04299    /* so far we do nothing with billing pulses */
04300    .on_billing_pulse_received = dahdi_r2_on_billing_pulse_received
04301 };
04302 
04303 static inline int16_t dahdi_r2_alaw_to_linear(uint8_t sample)
04304 {
04305    return AST_ALAW(sample);
04306 }
04307 
04308 static inline uint8_t dahdi_r2_linear_to_alaw(int sample)
04309 {
04310    return AST_LIN2A(sample);
04311 }
04312 
04313 static openr2_transcoder_interface_t dahdi_r2_transcode_iface = {
04314    dahdi_r2_alaw_to_linear,
04315    dahdi_r2_linear_to_alaw
04316 };
04317 
04318 #endif /* HAVE_OPENR2 */
04319 
04320 static void swap_subs(struct dahdi_pvt *p, int a, int b)
04321 {
04322    int tchan;
04323    int tinthreeway;
04324    struct ast_channel *towner;
04325 
04326    ast_debug(1, "Swapping %d and %d\n", a, b);
04327 
04328    tchan = p->subs[a].chan;
04329    towner = p->subs[a].owner;
04330    tinthreeway = p->subs[a].inthreeway;
04331 
04332    p->subs[a].chan = p->subs[b].chan;
04333    p->subs[a].owner = p->subs[b].owner;
04334    p->subs[a].inthreeway = p->subs[b].inthreeway;
04335 
04336    p->subs[b].chan = tchan;
04337    p->subs[b].owner = towner;
04338    p->subs[b].inthreeway = tinthreeway;
04339 
04340    if (p->subs[a].owner)
04341       ast_channel_set_fd(p->subs[a].owner, 0, p->subs[a].dfd);
04342    if (p->subs[b].owner)
04343       ast_channel_set_fd(p->subs[b].owner, 0, p->subs[b].dfd);
04344    wakeup_sub(p, a);
04345    wakeup_sub(p, b);
04346 }
04347 
04348 static int dahdi_open(char *fn)
04349 {
04350    int fd;
04351    int isnum;
04352    int chan = 0;
04353    int bs;
04354    int x;
04355    isnum = 1;
04356    for (x = 0; x < strlen(fn); x++) {
04357       if (!isdigit(fn[x])) {
04358          isnum = 0;
04359          break;
04360       }
04361    }
04362    if (isnum) {
04363       chan = atoi(fn);
04364       if (chan < 1) {
04365          ast_log(LOG_WARNING, "Invalid channel number '%s'\n", fn);
04366          return -1;
04367       }
04368       fn = "/dev/dahdi/channel";
04369    }
04370    fd = open(fn, O_RDWR | O_NONBLOCK);
04371    if (fd < 0) {
04372       ast_log(LOG_WARNING, "Unable to open '%s': %s\n", fn, strerror(errno));
04373       return -1;
04374    }
04375    if (chan) {
04376       if (ioctl(fd, DAHDI_SPECIFY, &chan)) {
04377          x = errno;
04378          close(fd);
04379          errno = x;
04380          ast_log(LOG_WARNING, "Unable to specify channel %d: %s\n", chan, strerror(errno));
04381          return -1;
04382       }
04383    }
04384    bs = READ_SIZE;
04385    if (ioctl(fd, DAHDI_SET_BLOCKSIZE, &bs) == -1) {
04386       ast_log(LOG_WARNING, "Unable to set blocksize '%d': %s\n", bs,  strerror(errno));
04387       x = errno;
04388       close(fd);
04389       errno = x;
04390       return -1;
04391    }
04392    return fd;
04393 }
04394 
04395 static void dahdi_close(int fd)
04396 {
04397    if (fd > 0)
04398       close(fd);
04399 }
04400 
04401 static void dahdi_close_sub(struct dahdi_pvt *chan_pvt, int sub_num)
04402 {
04403    dahdi_close(chan_pvt->subs[sub_num].dfd);
04404    chan_pvt->subs[sub_num].dfd = -1;
04405 }
04406 
04407 #if defined(HAVE_PRI)
04408 static void dahdi_close_pri_fd(struct dahdi_pri *pri, int fd_num)
04409 {
04410    dahdi_close(pri->pri.fds[fd_num]);
04411    pri->pri.fds[fd_num] = -1;
04412 }
04413 #endif   /* defined(HAVE_PRI) */
04414 
04415 #if defined(HAVE_SS7)
04416 static void dahdi_close_ss7_fd(struct dahdi_ss7 *ss7, int fd_num)
04417 {
04418    dahdi_close(ss7->ss7.fds[fd_num]);
04419    ss7->ss7.fds[fd_num] = -1;
04420 }
04421 #endif   /* defined(HAVE_SS7) */
04422 
04423 static int dahdi_setlinear(int dfd, int linear)
04424 {
04425    return ioctl(dfd, DAHDI_SETLINEAR, &linear);
04426 }
04427 
04428 
04429 static int alloc_sub(struct dahdi_pvt *p, int x)
04430 {
04431    struct dahdi_bufferinfo bi;
04432    int res;
04433    if (p->subs[x].dfd >= 0) {
04434       ast_log(LOG_WARNING, "%s subchannel of %d already in use\n", subnames[x], p->channel);
04435       return -1;
04436    }
04437 
04438    p->subs[x].dfd = dahdi_open("/dev/dahdi/pseudo");
04439    if (p->subs[x].dfd <= -1) {
04440       ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno));
04441       return -1;
04442    }
04443 
04444    res = ioctl(p->subs[x].dfd, DAHDI_GET_BUFINFO, &bi);
04445    if (!res) {
04446       bi.txbufpolicy = p->buf_policy;
04447       bi.rxbufpolicy = p->buf_policy;
04448       bi.numbufs = p->buf_no;
04449       res = ioctl(p->subs[x].dfd, DAHDI_SET_BUFINFO, &bi);
04450       if (res < 0) {
04451          ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", x, strerror(errno));
04452       }
04453    } else
04454       ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", x, strerror(errno));
04455 
04456    if (ioctl(p->subs[x].dfd, DAHDI_CHANNO, &p->subs[x].chan) == 1) {
04457       ast_log(LOG_WARNING, "Unable to get channel number for pseudo channel on FD %d: %s\n", p->subs[x].dfd, strerror(errno));
04458       dahdi_close_sub(p, x);
04459       p->subs[x].dfd = -1;
04460       return -1;
04461    }
04462    ast_debug(1, "Allocated %s subchannel on FD %d channel %d\n", subnames[x], p->subs[x].dfd, p->subs[x].chan);
04463    return 0;
04464 }
04465 
04466 static int unalloc_sub(struct dahdi_pvt *p, int x)
04467 {
04468    if (!x) {
04469       ast_log(LOG_WARNING, "Trying to unalloc the real channel %d?!?\n", p->channel);
04470       return -1;
04471    }
04472    ast_debug(1, "Released sub %d of channel %d\n", x, p->channel);
04473    dahdi_close_sub(p, x);
04474    p->subs[x].linear = 0;
04475    p->subs[x].chan = 0;
04476    p->subs[x].owner = NULL;
04477    p->subs[x].inthreeway = 0;
04478    p->polarity = POLARITY_IDLE;
04479    memset(&p->subs[x].curconf, 0, sizeof(p->subs[x].curconf));
04480    return 0;
04481 }
04482 
04483 static int digit_to_dtmfindex(char digit)
04484 {
04485    if (isdigit(digit))
04486       return DAHDI_TONE_DTMF_BASE + (digit - '0');
04487    else if (digit >= 'A' && digit <= 'D')
04488       return DAHDI_TONE_DTMF_A + (digit - 'A');
04489    else if (digit >= 'a' && digit <= 'd')
04490       return DAHDI_TONE_DTMF_A + (digit - 'a');
04491    else if (digit == '*')
04492       return DAHDI_TONE_DTMF_s;
04493    else if (digit == '#')
04494       return DAHDI_TONE_DTMF_p;
04495    else
04496       return -1;
04497 }
04498 
04499 static int dahdi_digit_begin(struct ast_channel *chan, char digit)
04500 {
04501    struct dahdi_pvt *pvt;
04502    int idx;
04503    int dtmf = -1;
04504    int res;
04505 
04506    pvt = chan->tech_pvt;
04507 
04508    ast_mutex_lock(&pvt->lock);
04509 
04510    idx = dahdi_get_index(chan, pvt, 0);
04511 
04512    if ((idx != SUB_REAL) || !pvt->owner)
04513       goto out;
04514 
04515 #ifdef HAVE_PRI
04516    switch (pvt->sig) {
04517    case SIG_PRI_LIB_HANDLE_CASES:
04518       res = sig_pri_digit_begin(pvt->sig_pvt, chan, digit);
04519       if (!res)
04520          goto out;
04521       break;
04522    default:
04523       break;
04524    }
04525 #endif
04526    if ((dtmf = digit_to_dtmfindex(digit)) == -1)
04527       goto out;
04528 
04529    if (pvt->pulse || ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &dtmf)) {
04530       struct dahdi_dialoperation zo = {
04531          .op = DAHDI_DIAL_OP_APPEND,
04532       };
04533 
04534       zo.dialstr[0] = 'T';
04535       zo.dialstr[1] = digit;
04536       zo.dialstr[2] = '\0';
04537       if ((res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo)))
04538          ast_log(LOG_WARNING, "Channel %s couldn't dial digit %c: %s\n",
04539             chan->name, digit, strerror(errno));
04540       else
04541          pvt->dialing = 1;
04542    } else {
04543       ast_debug(1, "Channel %s started VLDTMF digit '%c'\n",
04544          chan->name, digit);
04545       pvt->dialing = 1;
04546       pvt->begindigit = digit;
04547    }
04548 
04549 out:
04550    ast_mutex_unlock(&pvt->lock);
04551 
04552    return 0;
04553 }
04554 
04555 static int dahdi_digit_end(struct ast_channel *chan, char digit, unsigned int duration)
04556 {
04557    struct dahdi_pvt *pvt;
04558    int res = 0;
04559    int idx;
04560    int x;
04561 
04562    pvt = chan->tech_pvt;
04563 
04564    ast_mutex_lock(&pvt->lock);
04565 
04566    idx = dahdi_get_index(chan, pvt, 0);
04567 
04568    if ((idx != SUB_REAL) || !pvt->owner || pvt->pulse)
04569       goto out;
04570 
04571 #ifdef HAVE_PRI
04572    /* This means that the digit was already sent via PRI signalling */
04573    if (dahdi_sig_pri_lib_handles(pvt->sig) && !pvt->begindigit) {
04574       goto out;
04575    }
04576 #endif
04577 
04578    if (pvt->begindigit) {
04579       x = -1;
04580       ast_debug(1, "Channel %s ending VLDTMF digit '%c'\n",
04581          chan->name, digit);
04582       res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &x);
04583       pvt->dialing = 0;
04584       pvt->begindigit = 0;
04585    }
04586 
04587 out:
04588    ast_mutex_unlock(&pvt->lock);
04589 
04590    return res;
04591 }
04592 
04593 static const char * const events[] = {
04594    "No event",
04595    "On hook",
04596    "Ring/Answered",
04597    "Wink/Flash",
04598    "Alarm",
04599    "No more alarm",
04600    "HDLC Abort",
04601    "HDLC Overrun",
04602    "HDLC Bad FCS",
04603    "Dial Complete",
04604    "Ringer On",
04605    "Ringer Off",
04606    "Hook Transition Complete",
04607    "Bits Changed",
04608    "Pulse Start",
04609    "Timer Expired",
04610    "Timer Ping",
04611    "Polarity Reversal",
04612    "Ring Begin",
04613 };
04614 
04615 static struct {
04616    int alarm;
04617    char *name;
04618 } alarms[] = {
04619    { DAHDI_ALARM_RED, "Red Alarm" },
04620    { DAHDI_ALARM_YELLOW, "Yellow Alarm" },
04621    { DAHDI_ALARM_BLUE, "Blue Alarm" },
04622    { DAHDI_ALARM_RECOVER, "Recovering" },
04623    { DAHDI_ALARM_LOOPBACK, "Loopback" },
04624    { DAHDI_ALARM_NOTOPEN, "Not Open" },
04625    { DAHDI_ALARM_NONE, "None" },
04626 };
04627 
04628 static char *alarm2str(int alm)
04629 {
04630    int x;
04631    for (x = 0; x < ARRAY_LEN(alarms); x++) {
04632       if (alarms[x].alarm & alm)
04633          return alarms[x].name;
04634    }
04635    return alm ? "Unknown Alarm" : "No Alarm";
04636 }
04637 
04638 static const char *event2str(int event)
04639 {
04640    static char buf[256];
04641    if ((event < (ARRAY_LEN(events))) && (event > -1))
04642       return events[event];
04643    sprintf(buf, "Event %d", event); /* safe */
04644    return buf;
04645 }
04646 
04647 static char *dahdi_sig2str(int sig)
04648 {
04649    static char buf[256];
04650    switch (sig) {
04651    case SIG_EM:
04652       return "E & M Immediate";
04653    case SIG_EMWINK:
04654       return "E & M Wink";
04655    case SIG_EM_E1:
04656       return "E & M E1";
04657    case SIG_FEATD:
04658       return "Feature Group D (DTMF)";
04659    case SIG_FEATDMF:
04660       return "Feature Group D (MF)";
04661    case SIG_FEATDMF_TA:
04662       return "Feature Groud D (MF) Tandem Access";
04663    case SIG_FEATB:
04664       return "Feature Group B (MF)";
04665    case SIG_E911:
04666       return "E911 (MF)";
04667    case SIG_FGC_CAMA:
04668       return "FGC/CAMA (Dialpulse)";
04669    case SIG_FGC_CAMAMF:
04670       return "FGC/CAMA (MF)";
04671    case SIG_FXSLS:
04672       return "FXS Loopstart";
04673    case SIG_FXSGS:
04674       return "FXS Groundstart";
04675    case SIG_FXSKS:
04676       return "FXS Kewlstart";
04677    case SIG_FXOLS:
04678       return "FXO Loopstart";
04679    case SIG_FXOGS:
04680       return "FXO Groundstart";
04681    case SIG_FXOKS:
04682       return "FXO Kewlstart";
04683    case SIG_PRI:
04684       return "ISDN PRI";
04685    case SIG_BRI:
04686       return "ISDN BRI Point to Point";
04687    case SIG_BRI_PTMP:
04688       return "ISDN BRI Point to MultiPoint";
04689    case SIG_SS7:
04690       return "SS7";
04691    case SIG_MFCR2:
04692       return "MFC/R2";
04693    case SIG_SF:
04694       return "SF (Tone) Immediate";
04695    case SIG_SFWINK:
04696       return "SF (Tone) Wink";
04697    case SIG_SF_FEATD:
04698       return "SF (Tone) with Feature Group D (DTMF)";
04699    case SIG_SF_FEATDMF:
04700       return "SF (Tone) with Feature Group D (MF)";
04701    case SIG_SF_FEATB:
04702       return "SF (Tone) with Feature Group B (MF)";
04703    case 0:
04704       return "Pseudo";
04705    default:
04706       snprintf(buf, sizeof(buf), "Unknown signalling %d", sig);
04707       return buf;
04708    }
04709 }
04710 
04711 #define sig2str dahdi_sig2str
04712 
04713 static int conf_add(struct dahdi_pvt *p, struct dahdi_subchannel *c, int idx, int slavechannel)
04714 {
04715    /* If the conference already exists, and we're already in it
04716       don't bother doing anything */
04717    struct dahdi_confinfo zi;
04718 
04719    memset(&zi, 0, sizeof(zi));
04720    zi.chan = 0;
04721 
04722    if (slavechannel > 0) {
04723       /* If we have only one slave, do a digital mon */
04724       zi.confmode = DAHDI_CONF_DIGITALMON;
04725       zi.confno = slavechannel;
04726    } else {
04727       if (!idx) {
04728          /* Real-side and pseudo-side both participate in conference */
04729          zi.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER |
04730             DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER;
04731       } else
04732          zi.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER;
04733       zi.confno = p->confno;
04734    }
04735    if ((zi.confno == c->curconf.confno) && (zi.confmode == c->curconf.confmode))
04736       return 0;
04737    if (c->dfd < 0)
04738       return 0;
04739    if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
04740       ast_log(LOG_WARNING, "Failed to add %d to conference %d/%d: %s\n", c->dfd, zi.confmode, zi.confno, strerror(errno));
04741       return -1;
04742    }
04743    if (slavechannel < 1) {
04744       p->confno = zi.confno;
04745    }
04746    c->curconf = zi;
04747    ast_debug(1, "Added %d to conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
04748    return 0;
04749 }
04750 
04751 static int isourconf(struct dahdi_pvt *p, struct dahdi_subchannel *c)
04752 {
04753    /* If they're listening to our channel, they're ours */
04754    if ((p->channel == c->curconf.confno) && (c->curconf.confmode == DAHDI_CONF_DIGITALMON))
04755       return 1;
04756    /* If they're a talker on our (allocated) conference, they're ours */
04757    if ((p->confno > 0) && (p->confno == c->curconf.confno) && (c->curconf.confmode & DAHDI_CONF_TALKER))
04758       return 1;
04759    return 0;
04760 }
04761 
04762 static int conf_del(struct dahdi_pvt *p, struct dahdi_subchannel *c, int idx)
04763 {
04764    struct dahdi_confinfo zi;
04765    if (/* Can't delete if there's no dfd */
04766       (c->dfd < 0) ||
04767       /* Don't delete from the conference if it's not our conference */
04768       !isourconf(p, c)
04769       /* Don't delete if we don't think it's conferenced at all (implied) */
04770       ) return 0;
04771    memset(&zi, 0, sizeof(zi));
04772    if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
04773       ast_log(LOG_WARNING, "Failed to drop %d from conference %d/%d: %s\n", c->dfd, c->curconf.confmode, c->curconf.confno, strerror(errno));
04774       return -1;
04775    }
04776    ast_debug(1, "Removed %d from conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
04777    memcpy(&c->curconf, &zi, sizeof(c->curconf));
04778    return 0;
04779 }
04780 
04781 static int isslavenative(struct dahdi_pvt *p, struct dahdi_pvt **out)
04782 {
04783    int x;
04784    int useslavenative;
04785    struct dahdi_pvt *slave = NULL;
04786    /* Start out optimistic */
04787    useslavenative = 1;
04788    /* Update conference state in a stateless fashion */
04789    for (x = 0; x < 3; x++) {
04790       /* Any three-way calling makes slave native mode *definitely* out
04791          of the question */
04792       if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway)
04793          useslavenative = 0;
04794    }
04795    /* If we don't have any 3-way calls, check to see if we have
04796       precisely one slave */
04797    if (useslavenative) {
04798       for (x = 0; x < MAX_SLAVES; x++) {
04799          if (p->slaves[x]) {
04800             if (slave) {
04801                /* Whoops already have a slave!  No
04802                   slave native and stop right away */
04803                slave = NULL;
04804                useslavenative = 0;
04805                break;
04806             } else {
04807                /* We have one slave so far */
04808                slave = p->slaves[x];
04809             }
04810          }
04811       }
04812    }
04813    /* If no slave, slave native definitely out */
04814    if (!slave)
04815       useslavenative = 0;
04816    else if (slave->law != p->law) {
04817       useslavenative = 0;
04818       slave = NULL;
04819    }
04820    if (out)
04821       *out = slave;
04822    return useslavenative;
04823 }
04824 
04825 static int reset_conf(struct dahdi_pvt *p)
04826 {
04827    p->confno = -1;
04828    memset(&p->subs[SUB_REAL].curconf, 0, sizeof(p->subs[SUB_REAL].curconf));
04829    if (p->subs[SUB_REAL].dfd > -1) {
04830       struct dahdi_confinfo zi;
04831 
04832       memset(&zi, 0, sizeof(zi));
04833       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &zi))
04834          ast_log(LOG_WARNING, "Failed to reset conferencing on channel %d: %s\n", p->channel, strerror(errno));
04835    }
04836    return 0;
04837 }
04838 
04839 static int update_conf(struct dahdi_pvt *p)
04840 {
04841    int needconf = 0;
04842    int x;
04843    int useslavenative;
04844    struct dahdi_pvt *slave = NULL;
04845 
04846    useslavenative = isslavenative(p, &slave);
04847    /* Start with the obvious, general stuff */
04848    for (x = 0; x < 3; x++) {
04849       /* Look for three way calls */
04850       if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) {
04851          conf_add(p, &p->subs[x], x, 0);
04852          needconf++;
04853       } else {
04854          conf_del(p, &p->subs[x], x);
04855       }
04856    }
04857    /* If we have a slave, add him to our conference now. or DAX
04858       if this is slave native */
04859    for (x = 0; x < MAX_SLAVES; x++) {
04860       if (p->slaves[x]) {
04861          if (useslavenative)
04862             conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
04863          else {
04864             conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
04865             needconf++;
04866          }
04867       }
04868    }
04869    /* If we're supposed to be in there, do so now */
04870    if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
04871       if (useslavenative)
04872          conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
04873       else {
04874          conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
04875          needconf++;
04876       }
04877    }
04878    /* If we have a master, add ourselves to his conference */
04879    if (p->master) {
04880       if (isslavenative(p->master, NULL)) {
04881          conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
04882       } else {
04883          conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
04884       }
04885    }
04886    if (!needconf) {
04887       /* Nobody is left (or should be left) in our conference.
04888          Kill it. */
04889       p->confno = -1;
04890    }
04891    ast_debug(1, "Updated conferencing on %d, with %d conference users\n", p->channel, needconf);
04892    return 0;
04893 }
04894 
04895 static void dahdi_enable_ec(struct dahdi_pvt *p)
04896 {
04897    int res;
04898    if (!p)
04899       return;
04900    if (p->echocanon) {
04901       ast_debug(1, "Echo cancellation already on\n");
04902       return;
04903    }
04904    if (p->digital) {
04905       ast_debug(1, "Echo cancellation isn't required on digital connection\n");
04906       return;
04907    }
04908    if (p->echocancel.head.tap_length) {
04909 #if defined(HAVE_PRI) || defined(HAVE_SS7)
04910       switch (p->sig) {
04911 #if defined(HAVE_PRI)
04912       case SIG_PRI_LIB_HANDLE_CASES:
04913          if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
04914             /*
04915              * PRI nobch pseudo channel.  Does not need ec anyway.
04916              * Does not handle ioctl(DAHDI_AUDIOMODE)
04917              */
04918             return;
04919          }
04920          /* Fall through */
04921 #endif   /* defined(HAVE_PRI) */
04922 #if defined(HAVE_SS7)
04923       case SIG_SS7:
04924 #endif   /* defined(HAVE_SS7) */
04925          {
04926             int x = 1;
04927 
04928             res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x);
04929             if (res)
04930                ast_log(LOG_WARNING,
04931                   "Unable to enable audio mode on channel %d (%s)\n",
04932                   p->channel, strerror(errno));
04933          }
04934          break;
04935       default:
04936          break;
04937       }
04938 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
04939       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &p->echocancel);
04940       if (res) {
04941          ast_log(LOG_WARNING, "Unable to enable echo cancellation on channel %d (%s)\n", p->channel, strerror(errno));
04942       } else {
04943          p->echocanon = 1;
04944          ast_debug(1, "Enabled echo cancellation on channel %d\n", p->channel);
04945       }
04946    } else
04947       ast_debug(1, "No echo cancellation requested\n");
04948 }
04949 
04950 static void dahdi_train_ec(struct dahdi_pvt *p)
04951 {
04952    int x;
04953    int res;
04954 
04955    if (p && p->echocanon && p->echotraining) {
04956       x = p->echotraining;
04957       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOTRAIN, &x);
04958       if (res)
04959          ast_log(LOG_WARNING, "Unable to request echo training on channel %d: %s\n", p->channel, strerror(errno));
04960       else
04961          ast_debug(1, "Engaged echo training on channel %d\n", p->channel);
04962    } else {
04963       ast_debug(1, "No echo training requested\n");
04964    }
04965 }
04966 
04967 static void dahdi_disable_ec(struct dahdi_pvt *p)
04968 {
04969    int res;
04970 
04971    if (p->echocanon) {
04972       struct dahdi_echocanparams ecp = { .tap_length = 0 };
04973 
04974       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &ecp);
04975 
04976       if (res)
04977          ast_log(LOG_WARNING, "Unable to disable echo cancellation on channel %d: %s\n", p->channel, strerror(errno));
04978       else
04979          ast_debug(1, "Disabled echo cancellation on channel %d\n", p->channel);
04980    }
04981 
04982    p->echocanon = 0;
04983 }
04984 
04985 /* perform a dynamic range compression transform on the given sample */
04986 static int drc_sample(int sample, float drc)
04987 {
04988    float neg;
04989    float shallow, steep;
04990    float max = SHRT_MAX;
04991    
04992    neg = (sample < 0 ? -1 : 1);
04993    steep = drc*sample;
04994    shallow = neg*(max-max/drc)+(float)sample/drc;
04995    if (abs(steep) < abs(shallow)) {
04996       sample = steep;
04997    }
04998    else {
04999       sample = shallow;
05000    }
05001 
05002    return sample;
05003 }
05004 
05005 
05006 static void fill_txgain(struct dahdi_gains *g, float gain, float drc, int law)
05007 {
05008    int j;
05009    int k;
05010 
05011    float linear_gain = pow(10.0, gain / 20.0);
05012 
05013    switch (law) {
05014    case DAHDI_LAW_ALAW:
05015       for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
05016          if (gain || drc) {
05017             k = AST_ALAW(j);
05018             if (drc) {
05019                k = drc_sample(k, drc);
05020             }
05021             k = (float)k * linear_gain;
05022             if (k > 32767) {
05023                k = 32767;
05024             } else if (k < -32768) {
05025                k = -32768;
05026             }
05027             g->txgain[j] = AST_LIN2A(k);
05028          } else {
05029             g->txgain[j] = j;
05030          }
05031       }
05032       break;
05033    case DAHDI_LAW_MULAW:
05034       for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
05035          if (gain || drc) {
05036             k = AST_MULAW(j);
05037             if (drc) {
05038                k = drc_sample(k, drc);
05039             }
05040             k = (float)k * linear_gain;
05041             if (k > 32767) {
05042                k = 32767;
05043             } else if (k < -32768) {
05044                k = -32768;
05045             }
05046             g->txgain[j] = AST_LIN2MU(k);
05047 
05048          } else {
05049             g->txgain[j] = j;
05050          }
05051       }
05052       break;
05053    }
05054 }
05055 
05056 static void fill_rxgain(struct dahdi_gains *g, float gain, float drc, int law)
05057 {
05058    int j;
05059    int k;
05060    float linear_gain = pow(10.0, gain / 20.0);
05061 
05062    switch (law) {
05063    case DAHDI_LAW_ALAW:
05064       for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
05065          if (gain || drc) {
05066             k = AST_ALAW(j);
05067             if (drc) {
05068                k = drc_sample(k, drc);
05069             }
05070             k = (float)k * linear_gain;
05071             if (k > 32767) {
05072                k = 32767;
05073             } else if (k < -32768) {
05074                k = -32768;
05075             }
05076             g->rxgain[j] = AST_LIN2A(k);
05077          } else {
05078             g->rxgain[j] = j;
05079          }
05080       }
05081       break;
05082    case DAHDI_LAW_MULAW:
05083       for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
05084          if (gain || drc) {
05085             k = AST_MULAW(j);
05086             if (drc) {
05087                k = drc_sample(k, drc);
05088             }
05089             k = (float)k * linear_gain;
05090             if (k > 32767) {
05091                k = 32767;
05092             } else if (k < -32768) {
05093                k = -32768;
05094             }
05095             g->rxgain[j] = AST_LIN2MU(k);
05096          } else {
05097             g->rxgain[j] = j;
05098          }
05099       }
05100       break;
05101    }
05102 }
05103 
05104 static int set_actual_txgain(int fd, float gain, float drc, int law)
05105 {
05106    struct dahdi_gains g;
05107    int res;
05108 
05109    memset(&g, 0, sizeof(g));
05110    res = ioctl(fd, DAHDI_GETGAINS, &g);
05111    if (res) {
05112       ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
05113       return res;
05114    }
05115 
05116    fill_txgain(&g, gain, drc, law);
05117 
05118    return ioctl(fd, DAHDI_SETGAINS, &g);
05119 }
05120 
05121 static int set_actual_rxgain(int fd, float gain, float drc, int law)
05122 {
05123    struct dahdi_gains g;
05124    int res;
05125 
05126    memset(&g, 0, sizeof(g));
05127    res = ioctl(fd, DAHDI_GETGAINS, &g);
05128    if (res) {
05129       ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
05130       return res;
05131    }
05132 
05133    fill_rxgain(&g, gain, drc, law);
05134 
05135    return ioctl(fd, DAHDI_SETGAINS, &g);
05136 }
05137 
05138 static int set_actual_gain(int fd, float rxgain, float txgain, float rxdrc, float txdrc, int law)
05139 {
05140    return set_actual_txgain(fd, txgain, txdrc, law) | set_actual_rxgain(fd, rxgain, rxdrc, law);
05141 }
05142 
05143 static int bump_gains(struct dahdi_pvt *p)
05144 {
05145    int res;
05146 
05147    /* Bump receive gain by value stored in cid_rxgain */
05148    res = set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain + p->cid_rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
05149    if (res) {
05150       ast_log(LOG_WARNING, "Unable to bump gain: %s\n", strerror(errno));
05151       return -1;
05152    }
05153 
05154    return 0;
05155 }
05156 
05157 static int restore_gains(struct dahdi_pvt *p)
05158 {
05159    int res;
05160 
05161    res = set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
05162    if (res) {
05163       ast_log(LOG_WARNING, "Unable to restore gains: %s\n", strerror(errno));
05164       return -1;
05165    }
05166 
05167    return 0;
05168 }
05169 
05170 static inline int dahdi_set_hook(int fd, int hs)
05171 {
05172    int x, res;
05173 
05174    x = hs;
05175    res = ioctl(fd, DAHDI_HOOK, &x);
05176 
05177    if (res < 0) {
05178       if (errno == EINPROGRESS)
05179          return 0;
05180       ast_log(LOG_WARNING, "DAHDI hook failed returned %d (trying %d): %s\n", res, hs, strerror(errno));
05181       /* will expectedly fail if phone is off hook during operation, such as during a restart */
05182    }
05183 
05184    return res;
05185 }
05186 
05187 static inline int dahdi_confmute(struct dahdi_pvt *p, int muted)
05188 {
05189    int x, res;
05190 
05191    x = muted;
05192 #if defined(HAVE_PRI) || defined(HAVE_SS7)
05193    switch (p->sig) {
05194 #if defined(HAVE_PRI)
05195    case SIG_PRI_LIB_HANDLE_CASES:
05196       if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
05197          /* PRI nobch pseudo channel.  Does not handle ioctl(DAHDI_AUDIOMODE) */
05198          break;
05199       }
05200       /* Fall through */
05201 #endif   /* defined(HAVE_PRI) */
05202 #if defined(HAVE_SS7)
05203    case SIG_SS7:
05204 #endif   /* defined(HAVE_SS7) */
05205       {
05206          int y = 1;
05207 
05208          res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &y);
05209          if (res)
05210             ast_log(LOG_WARNING, "Unable to set audio mode on %d: %s\n",
05211                p->channel, strerror(errno));
05212       }
05213       break;
05214    default:
05215       break;
05216    }
05217 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
05218    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_CONFMUTE, &x);
05219    if (res < 0)
05220       ast_log(LOG_WARNING, "DAHDI confmute(%d) failed on channel %d: %s\n", muted, p->channel, strerror(errno));
05221    return res;
05222 }
05223 
05224 static int save_conference(struct dahdi_pvt *p)
05225 {
05226    struct dahdi_confinfo c;
05227    int res;
05228    if (p->saveconf.confmode) {
05229       ast_log(LOG_WARNING, "Can't save conference -- already in use\n");
05230       return -1;
05231    }
05232    p->saveconf.chan = 0;
05233    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &p->saveconf);
05234    if (res) {
05235       ast_log(LOG_WARNING, "Unable to get conference info: %s\n", strerror(errno));
05236       p->saveconf.confmode = 0;
05237       return -1;
05238    }
05239    memset(&c, 0, sizeof(c));
05240    c.confmode = DAHDI_CONF_NORMAL;
05241    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &c);
05242    if (res) {
05243       ast_log(LOG_WARNING, "Unable to set conference info: %s\n", strerror(errno));
05244       return -1;
05245    }
05246    ast_debug(1, "Disabled conferencing\n");
05247    return 0;
05248 }
05249 
05250 static int restore_conference(struct dahdi_pvt *p)
05251 {
05252    int res;
05253    if (p->saveconf.confmode) {
05254       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &p->saveconf);
05255       p->saveconf.confmode = 0;
05256       if (res) {
05257          ast_log(LOG_WARNING, "Unable to restore conference info: %s\n", strerror(errno));
05258          return -1;
05259       }
05260       ast_debug(1, "Restored conferencing\n");
05261    }
05262    return 0;
05263 }
05264 
05265 static int send_cwcidspill(struct dahdi_pvt *p)
05266 {
05267    p->callwaitcas = 0;
05268    p->cidcwexpire = 0;
05269    p->cid_suppress_expire = 0;
05270    if (!(p->cidspill = ast_malloc(MAX_CALLERID_SIZE)))
05271       return -1;
05272    p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, p->callwait_name, p->callwait_num, AST_LAW(p));
05273    /* Make sure we account for the end */
05274    p->cidlen += READ_SIZE * 4;
05275    p->cidpos = 0;
05276    send_callerid(p);
05277    ast_verb(3, "CPE supports Call Waiting Caller*ID.  Sending '%s/%s'\n", p->callwait_name, p->callwait_num);
05278    return 0;
05279 }
05280 
05281 static int has_voicemail(struct dahdi_pvt *p)
05282 {
05283    int new_msgs;
05284    struct ast_event *event;
05285    char *mailbox, *context;
05286 
05287    mailbox = context = ast_strdupa(p->mailbox);
05288    strsep(&context, "@");
05289    if (ast_strlen_zero(context))
05290       context = "default";
05291 
05292    event = ast_event_get_cached(AST_EVENT_MWI,
05293       AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
05294       AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
05295       AST_EVENT_IE_END);
05296 
05297    if (event) {
05298       new_msgs = ast_event_get_ie_uint(event, AST_EVENT_IE_NEWMSGS);
05299       ast_event_destroy(event);
05300    } else
05301       new_msgs = ast_app_has_voicemail(p->mailbox, NULL);
05302 
05303    return new_msgs;
05304 }
05305 
05306 
05307 
05308 static int send_callerid(struct dahdi_pvt *p)
05309 {
05310    /* Assumes spill in p->cidspill, p->cidlen in length and we're p->cidpos into it */
05311    int res;
05312    /* Take out of linear mode if necessary */
05313    if (p->subs[SUB_REAL].linear) {
05314       p->subs[SUB_REAL].linear = 0;
05315       dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
05316    }
05317    while (p->cidpos < p->cidlen) {
05318       res = write(p->subs[SUB_REAL].dfd, p->cidspill + p->cidpos, p->cidlen - p->cidpos);
05319       ast_debug(4, "writing callerid at pos %d of %d, res = %d\n", p->cidpos, p->cidlen, res);
05320       if (res < 0) {
05321          if (errno == EAGAIN)
05322             return 0;
05323          else {
05324             ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
05325             return -1;
05326          }
05327       }
05328       if (!res)
05329          return 0;
05330       p->cidpos += res;
05331    }
05332    p->cid_suppress_expire = CALLWAITING_SUPPRESS_SAMPLES;
05333    ast_free(p->cidspill);
05334    p->cidspill = NULL;
05335    if (p->callwaitcas) {
05336       /* Wait for CID/CW to expire */
05337       p->cidcwexpire = CIDCW_EXPIRE_SAMPLES;
05338       p->cid_suppress_expire = p->cidcwexpire;
05339    } else
05340       restore_conference(p);
05341    return 0;
05342 }
05343 
05344 static int dahdi_callwait(struct ast_channel *ast)
05345 {
05346    struct dahdi_pvt *p = ast->tech_pvt;
05347    p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
05348    if (p->cidspill) {
05349       ast_log(LOG_WARNING, "Spill already exists?!?\n");
05350       ast_free(p->cidspill);
05351    }
05352 
05353    /*
05354     * SAS: Subscriber Alert Signal, 440Hz for 300ms
05355     * CAS: CPE Alert Signal, 2130Hz * 2750Hz sine waves
05356     */
05357    if (!(p->cidspill = ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE * 4)))
05358       return -1;
05359    save_conference(p);
05360    /* Silence */
05361    memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
05362    if (!p->callwaitrings && p->callwaitingcallerid) {
05363       ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
05364       p->callwaitcas = 1;
05365       p->cidlen = 2400 + 680 + READ_SIZE * 4;
05366    } else {
05367       ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
05368       p->callwaitcas = 0;
05369       p->cidlen = 2400 + READ_SIZE * 4;
05370    }
05371    p->cidpos = 0;
05372    send_callerid(p);
05373 
05374    return 0;
05375 }
05376 
05377 static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout)
05378 {
05379    struct dahdi_pvt *p = ast->tech_pvt;
05380    int x, res, mysig;
05381    char dest[256]; /* must be same length as p->dialdest */
05382 
05383    ast_mutex_lock(&p->lock);
05384    ast_copy_string(dest, rdest, sizeof(dest));
05385    ast_copy_string(p->dialdest, rdest, sizeof(p->dialdest));
05386    if ((ast->_state == AST_STATE_BUSY)) {
05387       p->subs[SUB_REAL].needbusy = 1;
05388       ast_mutex_unlock(&p->lock);
05389       return 0;
05390    }
05391    if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
05392       ast_log(LOG_WARNING, "dahdi_call called on %s, neither down nor reserved\n", ast->name);
05393       ast_mutex_unlock(&p->lock);
05394       return -1;
05395    }
05396    p->waitingfordt.tv_sec = 0;
05397    p->dialednone = 0;
05398    if ((p->radio || (p->oprmode < 0)))  /* if a radio channel, up immediately */
05399    {
05400       /* Special pseudo -- automatically up */
05401       ast_setstate(ast, AST_STATE_UP);
05402       ast_mutex_unlock(&p->lock);
05403       return 0;
05404    }
05405    x = DAHDI_FLUSH_READ | DAHDI_FLUSH_WRITE;
05406    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
05407    if (res)
05408       ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", p->channel, strerror(errno));
05409    p->outgoing = 1;
05410 
05411    if (IS_DIGITAL(ast->transfercapability)){
05412       set_actual_gain(p->subs[SUB_REAL].dfd, 0, 0, p->rxdrc, p->txdrc, p->law);
05413    } else {
05414       set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
05415    }  
05416 
05417 #ifdef HAVE_PRI
05418    if (dahdi_sig_pri_lib_handles(p->sig)) {
05419       res = sig_pri_call(p->sig_pvt, ast, rdest, timeout,
05420          (p->law == DAHDI_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW);
05421       ast_mutex_unlock(&p->lock);
05422       return res;
05423    }
05424 #endif
05425 
05426 #if defined(HAVE_SS7)
05427    if (p->sig == SIG_SS7) {
05428       res = sig_ss7_call(p->sig_pvt, ast, rdest);
05429       ast_mutex_unlock(&p->lock);
05430       return res;
05431    }
05432 #endif   /* defined(HAVE_SS7) */
05433 
05434    /* If this is analog signalling we can exit here */
05435    if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
05436       p->callwaitrings = 0;
05437       res = analog_call(p->sig_pvt, ast, rdest, timeout);
05438       ast_mutex_unlock(&p->lock);
05439       return res;
05440    }
05441 
05442    mysig = p->outsigmod > -1 ? p->outsigmod : p->sig;
05443    switch (mysig) {
05444    case 0:
05445       /* Special pseudo -- automatically up*/
05446       ast_setstate(ast, AST_STATE_UP);
05447       break;
05448    case SIG_MFCR2:
05449       break;
05450    default:
05451       ast_debug(1, "not yet implemented\n");
05452       ast_mutex_unlock(&p->lock);
05453       return -1;
05454    }
05455 
05456 #ifdef HAVE_OPENR2
05457    if (p->mfcr2) {
05458       openr2_calling_party_category_t chancat;
05459       int callres = 0;
05460       char *c, *l;
05461 
05462       /* We'll get it in a moment -- but use dialdest to store pre-setup_ack digits */
05463       p->dialdest[0] = '\0';
05464 
05465       c = strchr(dest, '/');
05466       if (c) {
05467          c++;
05468       } else {
05469          c = "";
05470       }
05471       if (!p->hidecallerid) {
05472          l = ast->connected.id.number.valid ? ast->connected.id.number.str : NULL;
05473       } else {
05474          l = NULL;
05475       }
05476       if (strlen(c) < p->stripmsd) {
05477          ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
05478          ast_mutex_unlock(&p->lock);
05479          return -1;
05480       }
05481       p->dialing = 1;
05482       chancat = dahdi_r2_get_channel_category(ast);
05483       callres = openr2_chan_make_call(p->r2chan, l, (c + p->stripmsd), chancat);
05484       if (-1 == callres) {
05485          ast_mutex_unlock(&p->lock);
05486          ast_log(LOG_ERROR, "unable to make new MFC/R2 call!\n");
05487          return -1;
05488       }
05489       p->mfcr2_call_accepted = 0;
05490       p->mfcr2_progress = 0;
05491       ast_setstate(ast, AST_STATE_DIALING);
05492    }
05493 #endif /* HAVE_OPENR2 */
05494    ast_mutex_unlock(&p->lock);
05495    return 0;
05496 }
05497 
05498 /*!
05499  * \internal
05500  * \brief Insert the given chan_dahdi interface structure into the interface list.
05501  * \since 1.8
05502  *
05503  * \param pvt chan_dahdi private interface structure to insert.
05504  *
05505  * \details
05506  * The interface list is a doubly linked list sorted by the chan_dahdi channel number.
05507  * Any duplicates are inserted after the existing entries.
05508  *
05509  * \note The new interface must not already be in the list.
05510  *
05511  * \return Nothing
05512  */
05513 static void dahdi_iflist_insert(struct dahdi_pvt *pvt)
05514 {
05515    struct dahdi_pvt *cur;
05516 
05517    pvt->which_iflist = DAHDI_IFLIST_MAIN;
05518 
05519    /* Find place in middle of list for the new interface. */
05520    for (cur = iflist; cur; cur = cur->next) {
05521       if (pvt->channel < cur->channel) {
05522          /* New interface goes before the current interface. */
05523          pvt->prev = cur->prev;
05524          pvt->next = cur;
05525          if (cur->prev) {
05526             /* Insert into the middle of the list. */
05527             cur->prev->next = pvt;
05528          } else {
05529             /* Insert at head of list. */
05530             iflist = pvt;
05531          }
05532          cur->prev = pvt;
05533          return;
05534       }
05535    }
05536 
05537    /* New interface goes onto the end of the list */
05538    pvt->prev = ifend;
05539    pvt->next = NULL;
05540    if (ifend) {
05541       ifend->next = pvt;
05542    }
05543    ifend = pvt;
05544    if (!iflist) {
05545       /* List was empty */
05546       iflist = pvt;
05547    }
05548 }
05549 
05550 /*!
05551  * \internal
05552  * \brief Extract the given chan_dahdi interface structure from the interface list.
05553  * \since 1.8
05554  *
05555  * \param pvt chan_dahdi private interface structure to extract.
05556  *
05557  * \note
05558  * The given interface structure can be either in the interface list or a stand alone
05559  * structure that has not been put in the list if the next and prev pointers are NULL.
05560  *
05561  * \return Nothing
05562  */
05563 static void dahdi_iflist_extract(struct dahdi_pvt *pvt)
05564 {
05565    /* Extract from the forward chain. */
05566    if (pvt->prev) {
05567       pvt->prev->next = pvt->next;
05568    } else if (iflist == pvt) {
05569       /* Node is at the head of the list. */
05570       iflist = pvt->next;
05571    }
05572 
05573    /* Extract from the reverse chain. */
05574    if (pvt->next) {
05575       pvt->next->prev = pvt->prev;
05576    } else if (ifend == pvt) {
05577       /* Node is at the end of the list. */
05578       ifend = pvt->prev;
05579    }
05580 
05581    /* Node is no longer in the list. */
05582    pvt->which_iflist = DAHDI_IFLIST_NONE;
05583    pvt->prev = NULL;
05584    pvt->next = NULL;
05585 }
05586 
05587 #if defined(HAVE_PRI)
05588 /*!
05589  * \internal
05590  * \brief Insert the given chan_dahdi interface structure into the no B channel list.
05591  * \since 1.8
05592  *
05593  * \param pri sig_pri span control structure holding no B channel list.
05594  * \param pvt chan_dahdi private interface structure to insert.
05595  *
05596  * \details
05597  * The interface list is a doubly linked list sorted by the chan_dahdi channel number.
05598  * Any duplicates are inserted after the existing entries.
05599  *
05600  * \note The new interface must not already be in the list.
05601  *
05602  * \return Nothing
05603  */
05604 static void dahdi_nobch_insert(struct sig_pri_span *pri, struct dahdi_pvt *pvt)
05605 {
05606    struct dahdi_pvt *cur;
05607 
05608    pvt->which_iflist = DAHDI_IFLIST_NO_B_CHAN;
05609 
05610    /* Find place in middle of list for the new interface. */
05611    for (cur = pri->no_b_chan_iflist; cur; cur = cur->next) {
05612       if (pvt->channel < cur->channel) {
05613          /* New interface goes before the current interface. */
05614          pvt->prev = cur->prev;
05615          pvt->next = cur;
05616          if (cur->prev) {
05617             /* Insert into the middle of the list. */
05618             cur->prev->next = pvt;
05619          } else {
05620             /* Insert at head of list. */
05621             pri->no_b_chan_iflist = pvt;
05622          }
05623          cur->prev = pvt;
05624          return;
05625       }
05626    }
05627 
05628    /* New interface goes onto the end of the list */
05629    pvt->prev = pri->no_b_chan_end;
05630    pvt->next = NULL;
05631    if (pri->no_b_chan_end) {
05632       ((struct dahdi_pvt *) pri->no_b_chan_end)->next = pvt;
05633    }
05634    pri->no_b_chan_end = pvt;
05635    if (!pri->no_b_chan_iflist) {
05636       /* List was empty */
05637       pri->no_b_chan_iflist = pvt;
05638    }
05639 }
05640 #endif   /* defined(HAVE_PRI) */
05641 
05642 #if defined(HAVE_PRI)
05643 /*!
05644  * \internal
05645  * \brief Extract the given chan_dahdi interface structure from the no B channel list.
05646  * \since 1.8
05647  *
05648  * \param pri sig_pri span control structure holding no B channel list.
05649  * \param pvt chan_dahdi private interface structure to extract.
05650  *
05651  * \note
05652  * The given interface structure can be either in the interface list or a stand alone
05653  * structure that has not been put in the list if the next and prev pointers are NULL.
05654  *
05655  * \return Nothing
05656  */
05657 static void dahdi_nobch_extract(struct sig_pri_span *pri, struct dahdi_pvt *pvt)
05658 {
05659    /* Extract from the forward chain. */
05660    if (pvt->prev) {
05661       pvt->prev->next = pvt->next;
05662    } else if (pri->no_b_chan_iflist == pvt) {
05663       /* Node is at the head of the list. */
05664       pri->no_b_chan_iflist = pvt->next;
05665    }
05666 
05667    /* Extract from the reverse chain. */
05668    if (pvt->next) {
05669       pvt->next->prev = pvt->prev;
05670    } else if (pri->no_b_chan_end == pvt) {
05671       /* Node is at the end of the list. */
05672       pri->no_b_chan_end = pvt->prev;
05673    }
05674 
05675    /* Node is no longer in the list. */
05676    pvt->which_iflist = DAHDI_IFLIST_NONE;
05677    pvt->prev = NULL;
05678    pvt->next = NULL;
05679 }
05680 #endif   /* defined(HAVE_PRI) */
05681 
05682 #if defined(HAVE_PRI)
05683 /*!
05684  * \internal
05685  * \brief Unlink the channel interface from the PRI private pointer array.
05686  * \since 1.8
05687  *
05688  * \param pvt chan_dahdi private interface structure to unlink.
05689  *
05690  * \return Nothing
05691  */
05692 static void dahdi_unlink_pri_pvt(struct dahdi_pvt *pvt)
05693 {
05694    unsigned idx;
05695    struct sig_pri_span *pri;
05696 
05697    pri = pvt->pri;
05698    if (!pri) {
05699       /* Not PRI signaling so cannot be in a PRI private pointer array. */
05700       return;
05701    }
05702    ast_mutex_lock(&pri->lock);
05703    for (idx = 0; idx < pri->numchans; ++idx) {
05704       if (pri->pvts[idx] == pvt->sig_pvt) {
05705          pri->pvts[idx] = NULL;
05706          ast_mutex_unlock(&pri->lock);
05707          return;
05708       }
05709    }
05710    ast_mutex_unlock(&pri->lock);
05711 }
05712 #endif   /* defined(HAVE_PRI) */
05713 
05714 #if defined(HAVE_SS7)
05715 /*!
05716  * \internal
05717  * \brief Unlink the channel interface from the SS7 private pointer array.
05718  * \since 1.8
05719  *
05720  * \param pvt chan_dahdi private interface structure to unlink.
05721  *
05722  * \return Nothing
05723  */
05724 static void dahdi_unlink_ss7_pvt(struct dahdi_pvt *pvt)
05725 {
05726    unsigned idx;
05727    struct sig_ss7_linkset *ss7;
05728 
05729    ss7 = pvt->ss7;
05730    if (!ss7) {
05731       /* Not SS7 signaling so cannot be in a SS7 private pointer array. */
05732       return;
05733    }
05734    ast_mutex_lock(&ss7->lock);
05735    for (idx = 0; idx < ss7->numchans; ++idx) {
05736       if (ss7->pvts[idx] == pvt->sig_pvt) {
05737          ss7->pvts[idx] = NULL;
05738          ast_mutex_unlock(&ss7->lock);
05739          return;
05740       }
05741    }
05742    ast_mutex_unlock(&ss7->lock);
05743 }
05744 #endif   /* defined(HAVE_SS7) */
05745 
05746 static struct dahdi_pvt *find_next_iface_in_span(struct dahdi_pvt *cur)
05747 {
05748    if (cur->next && cur->next->span == cur->span) {
05749       return cur->next;
05750    } else if (cur->prev && cur->prev->span == cur->span) {
05751       return cur->prev;
05752    }
05753 
05754    return NULL;
05755 }
05756 
05757 static void destroy_dahdi_pvt(struct dahdi_pvt *pvt)
05758 {
05759    struct dahdi_pvt *p = pvt;
05760 
05761    if (p->manages_span_alarms) {
05762       struct dahdi_pvt *next = find_next_iface_in_span(p);
05763       if (next) {
05764          next->manages_span_alarms = 1;
05765       }
05766    }
05767 
05768    /* Remove channel from the list */
05769 #if defined(HAVE_PRI)
05770    dahdi_unlink_pri_pvt(p);
05771 #endif   /* defined(HAVE_PRI) */
05772 #if defined(HAVE_SS7)
05773    dahdi_unlink_ss7_pvt(p);
05774 #endif   /* defined(HAVE_SS7) */
05775    switch (pvt->which_iflist) {
05776    case DAHDI_IFLIST_NONE:
05777       break;
05778    case DAHDI_IFLIST_MAIN:
05779       dahdi_iflist_extract(p);
05780       break;
05781 #if defined(HAVE_PRI)
05782    case DAHDI_IFLIST_NO_B_CHAN:
05783       if (p->pri) {
05784          dahdi_nobch_extract(p->pri, p);
05785       }
05786       break;
05787 #endif   /* defined(HAVE_PRI) */
05788    }
05789 
05790    if (p->sig_pvt) {
05791       if (analog_lib_handles(p->sig, 0, 0)) {
05792          analog_delete(p->sig_pvt);
05793       }
05794       switch (p->sig) {
05795 #if defined(HAVE_PRI)
05796       case SIG_PRI_LIB_HANDLE_CASES:
05797          sig_pri_chan_delete(p->sig_pvt);
05798          break;
05799 #endif   /* defined(HAVE_PRI) */
05800 #if defined(HAVE_SS7)
05801       case SIG_SS7:
05802          sig_ss7_chan_delete(p->sig_pvt);
05803          break;
05804 #endif   /* defined(HAVE_SS7) */
05805       default:
05806          break;
05807       }
05808    }
05809    ast_free(p->cidspill);
05810    if (p->use_smdi)
05811       ast_smdi_interface_unref(p->smdi_iface);
05812    if (p->mwi_event_sub)
05813       ast_event_unsubscribe(p->mwi_event_sub);
05814    if (p->vars) {
05815       ast_variables_destroy(p->vars);
05816    }
05817    if (p->cc_params) {
05818       ast_cc_config_params_destroy(p->cc_params);
05819    }
05820    ast_mutex_destroy(&p->lock);
05821    dahdi_close_sub(p, SUB_REAL);
05822    if (p->owner)
05823       p->owner->tech_pvt = NULL;
05824    ast_free(p);
05825 }
05826 
05827 static void destroy_channel(struct dahdi_pvt *cur, int now)
05828 {
05829    int i;
05830 
05831    if (!now) {
05832       /* Do not destroy the channel now if it is owned by someone. */
05833       if (cur->owner) {
05834          return;
05835       }
05836       for (i = 0; i < 3; i++) {
05837          if (cur->subs[i].owner) {
05838             return;
05839          }
05840       }
05841    }
05842    destroy_dahdi_pvt(cur);
05843 }
05844 
05845 static void destroy_all_channels(void)
05846 {
05847    int chan;
05848 #if defined(HAVE_PRI)
05849    unsigned span;
05850    struct sig_pri_span *pri;
05851 #endif   /* defined(HAVE_PRI) */
05852    struct dahdi_pvt *p;
05853 
05854    while (num_restart_pending) {
05855       usleep(1);
05856    }
05857 
05858    ast_mutex_lock(&iflock);
05859    /* Destroy all the interfaces and free their memory */
05860    while (iflist) {
05861       p = iflist;
05862 
05863       chan = p->channel;
05864 #if defined(HAVE_PRI_SERVICE_MESSAGES)
05865       {
05866          char db_chan_name[20];
05867          char db_answer[5];
05868          char state;
05869          int why = -1;
05870 
05871          snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, p->span, chan);
05872          if (!ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) {
05873             sscanf(db_answer, "%1c:%30d", &state, &why);
05874          }
05875          if (!why) {
05876             /* SRVST persistence is not required */
05877             ast_db_del(db_chan_name, SRVST_DBKEY);
05878          }
05879       }
05880 #endif   /* defined(HAVE_PRI_SERVICE_MESSAGES) */
05881       /* Free associated memory */
05882       destroy_dahdi_pvt(p);
05883       ast_verb(3, "Unregistered channel %d\n", chan);
05884    }
05885    ifcount = 0;
05886    ast_mutex_unlock(&iflock);
05887 
05888 #if defined(HAVE_PRI)
05889    /* Destroy all of the no B channel interface lists */
05890    for (span = 0; span < NUM_SPANS; ++span) {
05891       if (!pris[span].dchannels[0]) {
05892          break;
05893       }
05894       pri = &pris[span].pri;
05895       ast_mutex_lock(&pri->lock);
05896       while (pri->no_b_chan_iflist) {
05897          p = pri->no_b_chan_iflist;
05898 
05899          /* Free associated memory */
05900          destroy_dahdi_pvt(p);
05901       }
05902       ast_mutex_unlock(&pri->lock);
05903    }
05904 #endif   /* defined(HAVE_PRI) */
05905 }
05906 
05907 #if defined(HAVE_PRI)
05908 static char *dahdi_send_keypad_facility_app = "DAHDISendKeypadFacility";
05909 
05910 static int dahdi_send_keypad_facility_exec(struct ast_channel *chan, const char *digits)
05911 {
05912    /* Data will be our digit string */
05913    struct dahdi_pvt *p;
05914 
05915    if (ast_strlen_zero(digits)) {
05916       ast_debug(1, "No digit string sent to application!\n");
05917       return -1;
05918    }
05919 
05920    p = (struct dahdi_pvt *)chan->tech_pvt;
05921 
05922    if (!p) {
05923       ast_debug(1, "Unable to find technology private\n");
05924       return -1;
05925    }
05926 
05927    pri_send_keypad_facility_exec(p->sig_pvt, digits);
05928 
05929    return 0;
05930 }
05931 #endif   /* defined(HAVE_PRI) */
05932 
05933 #if defined(HAVE_PRI)
05934 #if defined(HAVE_PRI_PROG_W_CAUSE)
05935 static char *dahdi_send_callrerouting_facility_app = "DAHDISendCallreroutingFacility";
05936 
05937 static int dahdi_send_callrerouting_facility_exec(struct ast_channel *chan, const char *data)
05938 {
05939    /* Data will be our digit string */
05940    struct dahdi_pvt *pvt;
05941    char *parse;
05942    int res;
05943    AST_DECLARE_APP_ARGS(args,
05944       AST_APP_ARG(destination);
05945       AST_APP_ARG(original);
05946       AST_APP_ARG(reason);
05947    );
05948 
05949    if (ast_strlen_zero(data)) {
05950       ast_log(LOG_DEBUG, "No data sent to application!\n");
05951       return -1;
05952    }
05953    if (chan->tech != &dahdi_tech) {
05954       ast_log(LOG_DEBUG, "Only DAHDI technology accepted!\n");
05955       return -1;
05956    }
05957    pvt = (struct dahdi_pvt *) chan->tech_pvt;
05958    if (!pvt) {
05959       ast_log(LOG_DEBUG, "Unable to find technology private\n");
05960       return -1;
05961    }
05962    switch (pvt->sig) {
05963    case SIG_PRI_LIB_HANDLE_CASES:
05964       break;
05965    default:
05966       ast_log(LOG_DEBUG, "callrerouting attempted on non-ISDN channel %s\n",
05967          chan->name);
05968       return -1;
05969    }
05970 
05971    parse = ast_strdupa(data);
05972    AST_STANDARD_APP_ARGS(args, parse);
05973 
05974    if (ast_strlen_zero(args.destination)) {
05975       ast_log(LOG_WARNING, "callrerouting facility requires at least destination number argument\n");
05976       return -1;
05977    }
05978 
05979    if (ast_strlen_zero(args.original)) {
05980       ast_log(LOG_WARNING, "Callrerouting Facility without original called number argument\n");
05981       args.original = NULL;
05982    }
05983 
05984    if (ast_strlen_zero(args.reason)) {
05985       ast_log(LOG_NOTICE, "Callrerouting Facility without diversion reason argument, defaulting to unknown\n");
05986       args.reason = NULL;
05987    }
05988 
05989    res = pri_send_callrerouting_facility_exec(pvt->sig_pvt, chan->_state,
05990       args.destination, args.original, args.reason);
05991    if (!res) {
05992       /*
05993        * Wait up to 5 seconds for a reply before hanging up this call
05994        * leg if the peer does not disconnect first.
05995        */
05996       ast_safe_sleep(chan, 5000);
05997    }
05998 
05999    return -1;
06000 }
06001 #endif   /* defined(HAVE_PRI_PROG_W_CAUSE) */
06002 #endif   /* defined(HAVE_PRI) */
06003 
06004 #if defined(HAVE_OPENR2)
06005 static const char * const dahdi_accept_r2_call_app = "DAHDIAcceptR2Call";
06006 
06007 static int dahdi_accept_r2_call_exec(struct ast_channel *chan, const char *data)
06008 {
06009    /* data is whether to accept with charge or no charge */
06010    openr2_call_mode_t accept_mode;
06011    int res, timeout, maxloops;
06012    struct ast_frame *f;
06013    struct dahdi_pvt *p;
06014    char *parse;
06015    AST_DECLARE_APP_ARGS(args,
06016          AST_APP_ARG(charge);
06017    );
06018 
06019    if (ast_strlen_zero(data)) {
06020       ast_log(LOG_DEBUG, "No data sent to application!\n");
06021       return -1;
06022    }
06023 
06024    if (chan->tech != &dahdi_tech) {
06025       ast_log(LOG_DEBUG, "Only DAHDI technology accepted!\n");
06026       return -1;
06027    }
06028 
06029    p = (struct dahdi_pvt *)chan->tech_pvt;
06030    if (!p) {
06031       ast_log(LOG_DEBUG, "Unable to find technology private!\n");
06032       return -1;
06033    }
06034 
06035    parse = ast_strdupa(data);
06036    AST_STANDARD_APP_ARGS(args, parse);
06037 
06038    if (ast_strlen_zero(args.charge)) {
06039       ast_log(LOG_WARNING, "DAHDIAcceptR2Call requires 'yes' or 'no' for the charge parameter\n");
06040       return -1;
06041    }
06042 
06043    ast_mutex_lock(&p->lock);
06044    if (!p->mfcr2 || !p->mfcr2call) {
06045       ast_mutex_unlock(&p->lock);
06046       ast_log(LOG_DEBUG, "Channel %s does not seems to be an R2 active channel!\n", chan->name);
06047       return -1;
06048    }
06049 
06050    if (p->mfcr2_call_accepted) {
06051       ast_mutex_unlock(&p->lock);
06052       ast_log(LOG_DEBUG, "MFC/R2 call already accepted on channel %s!\n", chan->name);
06053       return 0;
06054    }
06055    accept_mode = ast_true(args.charge) ? OR2_CALL_WITH_CHARGE : OR2_CALL_NO_CHARGE;
06056    if (openr2_chan_accept_call(p->r2chan, accept_mode)) {
06057       ast_mutex_unlock(&p->lock);
06058       ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n");
06059       return -1;
06060    }
06061    ast_mutex_unlock(&p->lock);
06062 
06063    res = 0;
06064    timeout = 100;
06065    maxloops = 50; /* wait up to 5 seconds */
06066    /* we need to read() until the call is accepted */
06067    while (maxloops > 0) {
06068       maxloops--;
06069       if (ast_check_hangup(chan)) {
06070          break;
06071       }
06072       res = ast_waitfor(chan, timeout);
06073       if (res < 0) {
06074          ast_log(LOG_DEBUG, "ast_waitfor failed on channel %s, going out ...\n", chan->name);
06075          res = -1;
06076          break;
06077       }
06078       if (res == 0) {
06079          continue;
06080       }
06081       res = 0;
06082       f = ast_read(chan);
06083       if (!f) {
06084          ast_log(LOG_DEBUG, "No frame read on channel %s, going out ...\n", chan->name);
06085          res = -1;
06086          break;
06087       }
06088       if (f->frametype == AST_FRAME_CONTROL && f->subclass.integer == AST_CONTROL_HANGUP) {
06089          ast_log(LOG_DEBUG, "Got HANGUP frame on channel %s, going out ...\n", chan->name);
06090          ast_frfree(f);
06091          res = -1;
06092          break;
06093       }
06094       ast_frfree(f);
06095       ast_mutex_lock(&p->lock);
06096       if (p->mfcr2_call_accepted) {
06097          ast_mutex_unlock(&p->lock);
06098          ast_log(LOG_DEBUG, "Accepted MFC/R2 call!\n");
06099          break;
06100       }
06101       ast_mutex_unlock(&p->lock);
06102    }
06103    if (res == -1) {
06104       ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n");
06105    }
06106    return res;
06107 }
06108 
06109 static openr2_call_disconnect_cause_t dahdi_ast_cause_to_r2_cause(int cause)
06110 {
06111    openr2_call_disconnect_cause_t r2cause = OR2_CAUSE_NORMAL_CLEARING;
06112    switch (cause) {
06113    case AST_CAUSE_USER_BUSY:
06114    case AST_CAUSE_CALL_REJECTED:
06115    case AST_CAUSE_INTERWORKING: /* I don't know wtf is this but is used sometimes when ekiga rejects a call */
06116       r2cause = OR2_CAUSE_BUSY_NUMBER;
06117       break;
06118 
06119    case AST_CAUSE_NORMAL_CIRCUIT_CONGESTION:
06120    case AST_CAUSE_SWITCH_CONGESTION:
06121       r2cause = OR2_CAUSE_NETWORK_CONGESTION;
06122       break;
06123 
06124    case AST_CAUSE_UNALLOCATED:
06125       r2cause = OR2_CAUSE_UNALLOCATED_NUMBER;
06126       break;
06127 
06128    case AST_CAUSE_NETWORK_OUT_OF_ORDER:
06129    case AST_CAUSE_DESTINATION_OUT_OF_ORDER:
06130       r2cause = OR2_CAUSE_OUT_OF_ORDER;
06131       break;
06132 
06133    case AST_CAUSE_NO_ANSWER:
06134    case AST_CAUSE_NO_USER_RESPONSE:
06135       r2cause = OR2_CAUSE_NO_ANSWER;
06136       break;
06137 
06138    default:
06139       r2cause = OR2_CAUSE_NORMAL_CLEARING;
06140       break;
06141    }
06142    ast_log(LOG_DEBUG, "ast cause %d resulted in openr2 cause %d/%s\n",
06143          cause, r2cause, openr2_proto_get_disconnect_string(r2cause));
06144    return r2cause;
06145 }
06146 #endif
06147 
06148 static int revert_fax_buffers(struct dahdi_pvt *p, struct ast_channel *ast)
06149 {
06150    if (p->bufferoverrideinuse) {
06151       /* faxbuffers are in use, revert them */
06152       struct dahdi_bufferinfo bi = {
06153          .txbufpolicy = p->buf_policy,
06154          .rxbufpolicy = p->buf_policy,
06155          .bufsize = p->bufsize,
06156          .numbufs = p->buf_no
06157       };
06158       int bpres;
06159 
06160       if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
06161          ast_log(LOG_WARNING, "Channel '%s' unable to revert buffer policy: %s\n", ast->name, strerror(errno));
06162       }
06163       p->bufferoverrideinuse = 0;
06164       return bpres;
06165    }
06166 
06167    return -1;
06168 }
06169 
06170 static int dahdi_hangup(struct ast_channel *ast)
06171 {
06172    int res = 0;
06173    int idx,x;
06174    int law;
06175    /*static int restore_gains(struct dahdi_pvt *p);*/
06176    struct dahdi_pvt *p = ast->tech_pvt;
06177    struct dahdi_params par;
06178 
06179    ast_debug(1, "dahdi_hangup(%s)\n", ast->name);
06180    if (!ast->tech_pvt) {
06181       ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
06182       return 0;
06183    }
06184 
06185    ast_mutex_lock(&p->lock);
06186    p->exten[0] = '\0';
06187    if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
06188       dahdi_confmute(p, 0);
06189       restore_gains(p);
06190       p->ignoredtmf = 0;
06191       p->waitingfordt.tv_sec = 0;
06192 
06193       res = analog_hangup(p->sig_pvt, ast);
06194       revert_fax_buffers(p, ast);
06195 
06196       goto hangup_out;
06197    } else {
06198       p->cid_num[0] = '\0';
06199       p->cid_name[0] = '\0';
06200       p->cid_subaddr[0] = '\0';
06201    }
06202 
06203 #if defined(HAVE_PRI)
06204    if (dahdi_sig_pri_lib_handles(p->sig)) {
06205       x = 1;
06206       ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
06207 
06208       dahdi_confmute(p, 0);
06209       p->muting = 0;
06210       restore_gains(p);
06211       if (p->dsp) {
06212          ast_dsp_free(p->dsp);
06213          p->dsp = NULL;
06214       }
06215       p->ignoredtmf = 0;
06216 
06217       /* Real channel, do some fixup */
06218       p->subs[SUB_REAL].owner = NULL;
06219       p->subs[SUB_REAL].needbusy = 0;
06220       dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
06221 
06222       p->owner = NULL;
06223       p->cid_tag[0] = '\0';
06224       p->ringt = 0;/* Probably not used in this mode.  Reset anyway. */
06225       p->distinctivering = 0;/* Probably not used in this mode. Reset anyway. */
06226       p->confirmanswer = 0;/* Probably not used in this mode. Reset anyway. */
06227       p->outgoing = 0;
06228       p->digital = 0;
06229       p->faxhandled = 0;
06230       p->pulsedial = 0;/* Probably not used in this mode. Reset anyway. */
06231 
06232       revert_fax_buffers(p, ast);
06233 
06234       p->law = p->law_default;
06235       law = p->law_default;
06236       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
06237       if (res < 0) {
06238          ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n",
06239             p->channel, strerror(errno));
06240       }
06241 
06242       sig_pri_hangup(p->sig_pvt, ast);
06243 
06244       tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06245       dahdi_disable_ec(p);
06246 
06247       x = 0;
06248       ast_channel_setoption(ast, AST_OPTION_TDD, &x, sizeof(char), 0);
06249       p->didtdd = 0;/* Probably not used in this mode. Reset anyway. */
06250 
06251       p->rdnis[0] = '\0';
06252       update_conf(p);
06253       reset_conf(p);
06254 
06255       /* Restore data mode */
06256       x = 0;
06257       ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
06258 
06259       if (num_restart_pending == 0) {
06260          restart_monitor();
06261       }
06262       goto hangup_out;
06263    }
06264 #endif   /* defined(HAVE_PRI) */
06265 
06266 #if defined(HAVE_SS7)
06267    if (p->sig == SIG_SS7) {
06268       x = 1;
06269       ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
06270 
06271       dahdi_confmute(p, 0);
06272       p->muting = 0;
06273       restore_gains(p);
06274       if (p->dsp) {
06275          ast_dsp_free(p->dsp);
06276          p->dsp = NULL;
06277       }
06278       p->ignoredtmf = 0;
06279 
06280       /* Real channel, do some fixup */
06281       p->subs[SUB_REAL].owner = NULL;
06282       p->subs[SUB_REAL].needbusy = 0;
06283       dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
06284 
06285       p->owner = NULL;
06286       p->ringt = 0;/* Probably not used in this mode.  Reset anyway. */
06287       p->distinctivering = 0;/* Probably not used in this mode. Reset anyway. */
06288       p->confirmanswer = 0;/* Probably not used in this mode. Reset anyway. */
06289       p->outgoing = 0;
06290       p->digital = 0;
06291       p->faxhandled = 0;
06292       p->pulsedial = 0;/* Probably not used in this mode. Reset anyway. */
06293 
06294       revert_fax_buffers(p, ast);
06295 
06296       p->law = p->law_default;
06297       law = p->law_default;
06298       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
06299       if (res < 0) {
06300          ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n",
06301             p->channel, strerror(errno));
06302       }
06303 
06304       sig_ss7_hangup(p->sig_pvt, ast);
06305 
06306       tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06307       dahdi_disable_ec(p);
06308 
06309       x = 0;
06310       ast_channel_setoption(ast, AST_OPTION_TDD, &x, sizeof(char), 0);
06311       p->didtdd = 0;/* Probably not used in this mode. Reset anyway. */
06312 
06313       update_conf(p);
06314       reset_conf(p);
06315 
06316       /* Restore data mode */
06317       x = 0;
06318       ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
06319 
06320       if (num_restart_pending == 0) {
06321          restart_monitor();
06322       }
06323       goto hangup_out;
06324    }
06325 #endif   /* defined(HAVE_SS7) */
06326 
06327    idx = dahdi_get_index(ast, p, 1);
06328 
06329    dahdi_confmute(p, 0);
06330    p->muting = 0;
06331    restore_gains(p);
06332    if (p->origcid_num) {
06333       ast_copy_string(p->cid_num, p->origcid_num, sizeof(p->cid_num));
06334       ast_free(p->origcid_num);
06335       p->origcid_num = NULL;
06336    }
06337    if (p->origcid_name) {
06338       ast_copy_string(p->cid_name, p->origcid_name, sizeof(p->cid_name));
06339       ast_free(p->origcid_name);
06340       p->origcid_name = NULL;
06341    }
06342    if (p->dsp)
06343       ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
06344 
06345    ast_debug(1, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n",
06346       p->channel, idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
06347    p->ignoredtmf = 0;
06348 
06349    if (idx > -1) {
06350       /* Real channel, do some fixup */
06351       p->subs[idx].owner = NULL;
06352       p->subs[idx].needanswer = 0;
06353       p->subs[idx].needflash = 0;
06354       p->subs[idx].needringing = 0;
06355       p->subs[idx].needbusy = 0;
06356       p->subs[idx].needcongestion = 0;
06357       p->subs[idx].linear = 0;
06358       p->polarity = POLARITY_IDLE;
06359       dahdi_setlinear(p->subs[idx].dfd, 0);
06360       if (idx == SUB_REAL) {
06361          if ((p->subs[SUB_CALLWAIT].dfd > -1) && (p->subs[SUB_THREEWAY].dfd > -1)) {
06362             ast_debug(1, "Normal call hung up with both three way call and a call waiting call in place?\n");
06363             if (p->subs[SUB_CALLWAIT].inthreeway) {
06364                /* We had flipped over to answer a callwait and now it's gone */
06365                ast_debug(1, "We were flipped over to the callwait, moving back and unowning.\n");
06366                /* Move to the call-wait, but un-own us until they flip back. */
06367                swap_subs(p, SUB_CALLWAIT, SUB_REAL);
06368                unalloc_sub(p, SUB_CALLWAIT);
06369                p->owner = NULL;
06370             } else {
06371                /* The three way hung up, but we still have a call wait */
06372                ast_debug(1, "We were in the threeway and have a callwait still.  Ditching the threeway.\n");
06373                swap_subs(p, SUB_THREEWAY, SUB_REAL);
06374                unalloc_sub(p, SUB_THREEWAY);
06375                if (p->subs[SUB_REAL].inthreeway) {
06376                   /* This was part of a three way call.  Immediately make way for
06377                      another call */
06378                   ast_debug(1, "Call was complete, setting owner to former third call\n");
06379                   p->owner = p->subs[SUB_REAL].owner;
06380                } else {
06381                   /* This call hasn't been completed yet...  Set owner to NULL */
06382                   ast_debug(1, "Call was incomplete, setting owner to NULL\n");
06383                   p->owner = NULL;
06384                }
06385                p->subs[SUB_REAL].inthreeway = 0;
06386             }
06387          } else if (p->subs[SUB_CALLWAIT].dfd > -1) {
06388             /* Move to the call-wait and switch back to them. */
06389             swap_subs(p, SUB_CALLWAIT, SUB_REAL);
06390             unalloc_sub(p, SUB_CALLWAIT);
06391             p->owner = p->subs[SUB_REAL].owner;
06392             if (p->owner->_state != AST_STATE_UP)
06393                p->subs[SUB_REAL].needanswer = 1;
06394             if (ast_bridged_channel(p->subs[SUB_REAL].owner))
06395                ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
06396          } else if (p->subs[SUB_THREEWAY].dfd > -1) {
06397             swap_subs(p, SUB_THREEWAY, SUB_REAL);
06398             unalloc_sub(p, SUB_THREEWAY);
06399             if (p->subs[SUB_REAL].inthreeway) {
06400                /* This was part of a three way call.  Immediately make way for
06401                   another call */
06402                ast_debug(1, "Call was complete, setting owner to former third call\n");
06403                p->owner = p->subs[SUB_REAL].owner;
06404             } else {
06405                /* This call hasn't been completed yet...  Set owner to NULL */
06406                ast_debug(1, "Call was incomplete, setting owner to NULL\n");
06407                p->owner = NULL;
06408             }
06409             p->subs[SUB_REAL].inthreeway = 0;
06410          }
06411       } else if (idx == SUB_CALLWAIT) {
06412          /* Ditch the holding callwait call, and immediately make it availabe */
06413          if (p->subs[SUB_CALLWAIT].inthreeway) {
06414             /* This is actually part of a three way, placed on hold.  Place the third part
06415                on music on hold now */
06416             if (p->subs[SUB_THREEWAY].owner && ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
06417                ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
06418                   S_OR(p->mohsuggest, NULL),
06419                   !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
06420             }
06421             p->subs[SUB_THREEWAY].inthreeway = 0;
06422             /* Make it the call wait now */
06423             swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
06424             unalloc_sub(p, SUB_THREEWAY);
06425          } else
06426             unalloc_sub(p, SUB_CALLWAIT);
06427       } else if (idx == SUB_THREEWAY) {
06428          if (p->subs[SUB_CALLWAIT].inthreeway) {
06429             /* The other party of the three way call is currently in a call-wait state.
06430                Start music on hold for them, and take the main guy out of the third call */
06431             if (p->subs[SUB_CALLWAIT].owner && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
06432                ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
06433                   S_OR(p->mohsuggest, NULL),
06434                   !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
06435             }
06436             p->subs[SUB_CALLWAIT].inthreeway = 0;
06437          }
06438          p->subs[SUB_REAL].inthreeway = 0;
06439          /* If this was part of a three way call index, let us make
06440             another three way call */
06441          unalloc_sub(p, SUB_THREEWAY);
06442       } else {
06443          /* This wasn't any sort of call, but how are we an index? */
06444          ast_log(LOG_WARNING, "Index found but not any type of call?\n");
06445       }
06446    }
06447 
06448    if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) {
06449       p->owner = NULL;
06450       p->ringt = 0;
06451       p->distinctivering = 0;
06452       p->confirmanswer = 0;
06453       p->outgoing = 0;
06454       p->digital = 0;
06455       p->faxhandled = 0;
06456       p->pulsedial = 0;
06457       if (p->dsp) {
06458          ast_dsp_free(p->dsp);
06459          p->dsp = NULL;
06460       }
06461 
06462       revert_fax_buffers(p, ast);
06463 
06464       p->law = p->law_default;
06465       law = p->law_default;
06466       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
06467       if (res < 0)
06468          ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
06469       /* Perform low level hangup if no owner left */
06470 #ifdef HAVE_OPENR2
06471       if (p->mfcr2 && p->mfcr2call && openr2_chan_get_direction(p->r2chan) != OR2_DIR_STOPPED) {
06472          ast_log(LOG_DEBUG, "disconnecting MFC/R2 call on chan %d\n", p->channel);
06473          /* If it's an incoming call, check the mfcr2_forced_release setting */
06474          if (openr2_chan_get_direction(p->r2chan) == OR2_DIR_BACKWARD && p->mfcr2_forced_release) {
06475             dahdi_r2_disconnect_call(p, OR2_CAUSE_FORCED_RELEASE);
06476          } else {
06477             const char *r2causestr = pbx_builtin_getvar_helper(ast, "MFCR2_CAUSE");
06478             int r2cause_user = r2causestr ? atoi(r2causestr) : 0;
06479             openr2_call_disconnect_cause_t r2cause = r2cause_user ? dahdi_ast_cause_to_r2_cause(r2cause_user)
06480                                                              : dahdi_ast_cause_to_r2_cause(ast->hangupcause);
06481             dahdi_r2_disconnect_call(p, r2cause);
06482          }
06483       } else if (p->mfcr2call) {
06484          ast_log(LOG_DEBUG, "Clearing call request on channel %d\n", p->channel);
06485          /* since ast_request() was called but not ast_call() we have not yet dialed
06486          and the openr2 stack will not call on_call_end callback, we need to unset
06487          the mfcr2call flag and bump the monitor count so the monitor thread can take
06488          care of this channel events from now on */
06489          p->mfcr2call = 0;
06490       }
06491 #endif
06492       switch (p->sig) {
06493       case SIG_SS7:
06494       case SIG_MFCR2:
06495       case SIG_PRI_LIB_HANDLE_CASES:
06496       case 0:
06497          break;
06498       default:
06499          res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
06500          break;
06501       }
06502       if (res < 0) {
06503          ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast->name);
06504       }
06505       switch (p->sig) {
06506       case SIG_FXOGS:
06507       case SIG_FXOLS:
06508       case SIG_FXOKS:
06509          memset(&par, 0, sizeof(par));
06510          res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
06511          if (!res) {
06512             struct analog_pvt *analog_p = p->sig_pvt;
06513 #if 0
06514             ast_debug(1, "Hanging up channel %d, offhook = %d\n", p->channel, par.rxisoffhook);
06515 #endif
06516             /* If they're off hook, try playing congestion */
06517             if ((par.rxisoffhook) && (!(p->radio || (p->oprmode < 0))))
06518                tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
06519             else
06520                tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06521             analog_p->fxsoffhookstate = par.rxisoffhook;
06522          }
06523          break;
06524       case SIG_FXSGS:
06525       case SIG_FXSLS:
06526       case SIG_FXSKS:
06527          /* Make sure we're not made available for at least two seconds assuming
06528          we were actually used for an inbound or outbound call. */
06529          if (ast->_state != AST_STATE_RESERVED) {
06530             time(&p->guardtime);
06531             p->guardtime += 2;
06532          }
06533          break;
06534       default:
06535          tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06536          break;
06537       }
06538       if (p->sig)
06539          dahdi_disable_ec(p);
06540       x = 0;
06541       ast_channel_setoption(ast,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0);
06542       ast_channel_setoption(ast,AST_OPTION_TDD,&x,sizeof(char),0);
06543       p->didtdd = 0;
06544       p->callwaitcas = 0;
06545       p->callwaiting = p->permcallwaiting;
06546       p->hidecallerid = p->permhidecallerid;
06547       p->waitingfordt.tv_sec = 0;
06548       p->dialing = 0;
06549       p->rdnis[0] = '\0';
06550       update_conf(p);
06551       reset_conf(p);
06552       /* Restore data mode */
06553       switch (p->sig) {
06554       case SIG_PRI_LIB_HANDLE_CASES:
06555       case SIG_SS7:
06556          x = 0;
06557          ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
06558          break;
06559       default:
06560          break;
06561       }
06562       if (num_restart_pending == 0)
06563          restart_monitor();
06564    }
06565 
06566    p->callwaitingrepeat = 0;
06567    p->cidcwexpire = 0;
06568    p->cid_suppress_expire = 0;
06569    p->oprmode = 0;
06570 hangup_out:
06571    ast->tech_pvt = NULL;
06572    ast_free(p->cidspill);
06573    p->cidspill = NULL;
06574 
06575    ast_mutex_unlock(&p->lock);
06576    ast_verb(3, "Hungup '%s'\n", ast->name);
06577 
06578    ast_mutex_lock(&iflock);
06579    if (p->restartpending) {
06580       num_restart_pending--;
06581    }
06582 
06583    if (p->destroy) {
06584       destroy_channel(p, 0);
06585    }
06586    ast_mutex_unlock(&iflock);
06587 
06588    ast_module_unref(ast_module_info->self);
06589    return 0;
06590 }
06591 
06592 static int dahdi_answer(struct ast_channel *ast)
06593 {
06594    struct dahdi_pvt *p = ast->tech_pvt;
06595    int res = 0;
06596    int idx;
06597    ast_setstate(ast, AST_STATE_UP);/*! \todo XXX this is redundantly set by the analog and PRI submodules! */
06598    ast_mutex_lock(&p->lock);
06599    idx = dahdi_get_index(ast, p, 0);
06600    if (idx < 0)
06601       idx = SUB_REAL;
06602    /* nothing to do if a radio channel */
06603    if ((p->radio || (p->oprmode < 0))) {
06604       ast_mutex_unlock(&p->lock);
06605       return 0;
06606    }
06607 
06608    if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
06609       res = analog_answer(p->sig_pvt, ast);
06610       ast_mutex_unlock(&p->lock);
06611       return res;
06612    }
06613 
06614    switch (p->sig) {
06615 #if defined(HAVE_PRI)
06616    case SIG_PRI_LIB_HANDLE_CASES:
06617       res = sig_pri_answer(p->sig_pvt, ast);
06618       break;
06619 #endif   /* defined(HAVE_PRI) */
06620 #if defined(HAVE_SS7)
06621    case SIG_SS7:
06622       res = sig_ss7_answer(p->sig_pvt, ast);
06623       break;
06624 #endif   /* defined(HAVE_SS7) */
06625 #ifdef HAVE_OPENR2
06626    case SIG_MFCR2:
06627       if (!p->mfcr2_call_accepted) {
06628          /* The call was not accepted on offer nor the user, so it must be accepted now before answering,
06629             openr2_chan_answer_call will be called when the callback on_call_accepted is executed */
06630          p->mfcr2_answer_pending = 1;
06631          if (p->mfcr2_charge_calls) {
06632             ast_log(LOG_DEBUG, "Accepting MFC/R2 call with charge before answering on chan %d\n", p->channel);
06633             openr2_chan_accept_call(p->r2chan, OR2_CALL_WITH_CHARGE);
06634          } else {
06635             ast_log(LOG_DEBUG, "Accepting MFC/R2 call with no charge before answering on chan %d\n", p->channel);
06636             openr2_chan_accept_call(p->r2chan, OR2_CALL_NO_CHARGE);
06637          }
06638       } else {
06639          ast_log(LOG_DEBUG, "Answering MFC/R2 call on chan %d\n", p->channel);
06640          dahdi_r2_answer(p);
06641       }
06642       break;
06643 #endif
06644    case 0:
06645       ast_mutex_unlock(&p->lock);
06646       return 0;
06647    default:
06648       ast_log(LOG_WARNING, "Don't know how to answer signalling %d (channel %d)\n", p->sig, p->channel);
06649       res = -1;
06650       break;
06651    }
06652    ast_mutex_unlock(&p->lock);
06653    return res;
06654 }
06655 
06656 static void disable_dtmf_detect(struct dahdi_pvt *p)
06657 {
06658    int val = 0;
06659 
06660    p->ignoredtmf = 1;
06661 
06662    ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
06663 
06664    if (!p->hardwaredtmf && p->dsp) {
06665       p->dsp_features &= ~DSP_FEATURE_DIGIT_DETECT;
06666       ast_dsp_set_features(p->dsp, p->dsp_features);
06667    }
06668 }
06669 
06670 static void enable_dtmf_detect(struct dahdi_pvt *p)
06671 {
06672    int val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
06673 
06674    if (p->channel == CHAN_PSEUDO)
06675       return;
06676 
06677    p->ignoredtmf = 0;
06678 
06679    ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
06680 
06681    if (!p->hardwaredtmf && p->dsp) {
06682       p->dsp_features |= DSP_FEATURE_DIGIT_DETECT;
06683       ast_dsp_set_features(p->dsp, p->dsp_features);
06684    }
06685 }
06686 
06687 static int dahdi_queryoption(struct ast_channel *chan, int option, void *data, int *datalen)
06688 {
06689    char *cp;
06690    struct dahdi_pvt *p = chan->tech_pvt;
06691 
06692    /* all supported options require data */
06693    if (!p || !data || (*datalen < 1)) {
06694       errno = EINVAL;
06695       return -1;
06696    }
06697 
06698    switch (option) {
06699    case AST_OPTION_DIGIT_DETECT:
06700       cp = (char *) data;
06701       *cp = p->ignoredtmf ? 0 : 1;
06702       ast_debug(1, "Reporting digit detection %sabled on %s\n", *cp ? "en" : "dis", chan->name);
06703       break;
06704    case AST_OPTION_FAX_DETECT:
06705       cp = (char *) data;
06706       *cp = (p->dsp_features & DSP_FEATURE_FAX_DETECT) ? 0 : 1;
06707       ast_debug(1, "Reporting fax tone detection %sabled on %s\n", *cp ? "en" : "dis", chan->name);
06708       break;
06709    case AST_OPTION_CC_AGENT_TYPE:
06710 #if defined(HAVE_PRI)
06711 #if defined(HAVE_PRI_CCSS)
06712       if (dahdi_sig_pri_lib_handles(p->sig)) {
06713          ast_copy_string((char *) data, dahdi_pri_cc_type, *datalen);
06714          break;
06715       }
06716 #endif   /* defined(HAVE_PRI_CCSS) */
06717 #endif   /* defined(HAVE_PRI) */
06718       return -1;
06719    default:
06720       return -1;
06721    }
06722 
06723    errno = 0;
06724 
06725    return 0;
06726 }
06727 
06728 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen)
06729 {
06730    char *cp;
06731    signed char *scp;
06732    int x;
06733    int idx;
06734    struct dahdi_pvt *p = chan->tech_pvt, *pp;
06735    struct oprmode *oprmode;
06736 
06737 
06738    /* all supported options require data */
06739    if (!p || !data || (datalen < 1)) {
06740       errno = EINVAL;
06741       return -1;
06742    }
06743 
06744    switch (option) {
06745    case AST_OPTION_TXGAIN:
06746       scp = (signed char *) data;
06747       idx = dahdi_get_index(chan, p, 0);
06748       if (idx < 0) {
06749          ast_log(LOG_WARNING, "No index in TXGAIN?\n");
06750          return -1;
06751       }
06752       ast_debug(1, "Setting actual tx gain on %s to %f\n", chan->name, p->txgain + (float) *scp);
06753       return set_actual_txgain(p->subs[idx].dfd, p->txgain + (float) *scp, p->txdrc, p->law);
06754    case AST_OPTION_RXGAIN:
06755       scp = (signed char *) data;
06756       idx = dahdi_get_index(chan, p, 0);
06757       if (idx < 0) {
06758          ast_log(LOG_WARNING, "No index in RXGAIN?\n");
06759          return -1;
06760       }
06761       ast_debug(1, "Setting actual rx gain on %s to %f\n", chan->name, p->rxgain + (float) *scp);
06762       return set_actual_rxgain(p->subs[idx].dfd, p->rxgain + (float) *scp, p->rxdrc, p->law);
06763    case AST_OPTION_TONE_VERIFY:
06764       if (!p->dsp)
06765          break;
06766       cp = (char *) data;
06767       switch (*cp) {
06768       case 1:
06769          ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",chan->name);
06770          ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | p->dtmfrelax);  /* set mute mode if desired */
06771          break;
06772       case 2:
06773          ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",chan->name);
06774          ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX | p->dtmfrelax);  /* set mute mode if desired */
06775          break;
06776       default:
06777          ast_debug(1, "Set option TONE VERIFY, mode: OFF(0) on %s\n",chan->name);
06778          ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);  /* set mute mode if desired */
06779          break;
06780       }
06781       break;
06782    case AST_OPTION_TDD:
06783       /* turn on or off TDD */
06784       cp = (char *) data;
06785       p->mate = 0;
06786       if (!*cp) { /* turn it off */
06787          ast_debug(1, "Set option TDD MODE, value: OFF(0) on %s\n",chan->name);
06788          if (p->tdd)
06789             tdd_free(p->tdd);
06790          p->tdd = 0;
06791          break;
06792       }
06793       ast_debug(1, "Set option TDD MODE, value: %s(%d) on %s\n",
06794          (*cp == 2) ? "MATE" : "ON", (int) *cp, chan->name);
06795       dahdi_disable_ec(p);
06796       /* otherwise, turn it on */
06797       if (!p->didtdd) { /* if havent done it yet */
06798          unsigned char mybuf[41000];/*! \todo XXX This is an abuse of the stack!! */
06799          unsigned char *buf;
06800          int size, res, fd, len;
06801          struct pollfd fds[1];
06802 
06803          buf = mybuf;
06804          memset(buf, 0x7f, sizeof(mybuf)); /* set to silence */
06805          ast_tdd_gen_ecdisa(buf + 16000, 16000);  /* put in tone */
06806          len = 40000;
06807          idx = dahdi_get_index(chan, p, 0);
06808          if (idx < 0) {
06809             ast_log(LOG_WARNING, "No index in TDD?\n");
06810             return -1;
06811          }
06812          fd = p->subs[idx].dfd;
06813          while (len) {
06814             if (ast_check_hangup(chan))
06815                return -1;
06816             size = len;
06817             if (size > READ_SIZE)
06818                size = READ_SIZE;
06819             fds[0].fd = fd;
06820             fds[0].events = POLLPRI | POLLOUT;
06821             fds[0].revents = 0;
06822             res = poll(fds, 1, -1);
06823             if (!res) {
06824                ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
06825                continue;
06826             }
06827             /* if got exception */
06828             if (fds[0].revents & POLLPRI)
06829                return -1;
06830             if (!(fds[0].revents & POLLOUT)) {
06831                ast_debug(1, "write fd not ready on channel %d\n", p->channel);
06832                continue;
06833             }
06834             res = write(fd, buf, size);
06835             if (res != size) {
06836                if (res == -1) return -1;
06837                ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
06838                break;
06839             }
06840             len -= size;
06841             buf += size;
06842          }
06843          p->didtdd = 1; /* set to have done it now */
06844       }
06845       if (*cp == 2) { /* Mate mode */
06846          if (p->tdd)
06847             tdd_free(p->tdd);
06848          p->tdd = 0;
06849          p->mate = 1;
06850          break;
06851       }
06852       if (!p->tdd) { /* if we don't have one yet */
06853          p->tdd = tdd_new(); /* allocate one */
06854       }
06855       break;
06856    case AST_OPTION_RELAXDTMF:  /* Relax DTMF decoding (or not) */
06857       if (!p->dsp)
06858          break;
06859       cp = (char *) data;
06860       ast_debug(1, "Set option RELAX DTMF, value: %s(%d) on %s\n",
06861          *cp ? "ON" : "OFF", (int) *cp, chan->name);
06862       ast_dsp_set_digitmode(p->dsp, ((*cp) ? DSP_DIGITMODE_RELAXDTMF : DSP_DIGITMODE_DTMF) | p->dtmfrelax);
06863       break;
06864    case AST_OPTION_AUDIO_MODE:  /* Set AUDIO mode (or not) */
06865 #if defined(HAVE_PRI)
06866       if (dahdi_sig_pri_lib_handles(p->sig)
06867          && ((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
06868          /* PRI nobch pseudo channel.  Does not handle ioctl(DAHDI_AUDIOMODE) */
06869          break;
06870       }
06871 #endif   /* defined(HAVE_PRI) */
06872 
06873       cp = (char *) data;
06874       if (!*cp) {
06875          ast_debug(1, "Set option AUDIO MODE, value: OFF(0) on %s\n", chan->name);
06876          x = 0;
06877          dahdi_disable_ec(p);
06878       } else {
06879          ast_debug(1, "Set option AUDIO MODE, value: ON(1) on %s\n", chan->name);
06880          x = 1;
06881       }
06882       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x) == -1)
06883          ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, x, strerror(errno));
06884       break;
06885    case AST_OPTION_OPRMODE:  /* Operator services mode */
06886       oprmode = (struct oprmode *) data;
06887       /* We don't support operator mode across technologies */
06888       if (strcasecmp(chan->tech->type, oprmode->peer->tech->type)) {
06889          ast_log(LOG_NOTICE, "Operator mode not supported on %s to %s calls.\n",
06890                chan->tech->type, oprmode->peer->tech->type);
06891          errno = EINVAL;
06892          return -1;
06893       }
06894       pp = oprmode->peer->tech_pvt;
06895       p->oprmode = pp->oprmode = 0;
06896       /* setup peers */
06897       p->oprpeer = pp;
06898       pp->oprpeer = p;
06899       /* setup modes, if any */
06900       if (oprmode->mode)
06901       {
06902          pp->oprmode = oprmode->mode;
06903          p->oprmode = -oprmode->mode;
06904       }
06905       ast_debug(1, "Set Operator Services mode, value: %d on %s/%s\n",
06906          oprmode->mode, chan->name,oprmode->peer->name);
06907       break;
06908    case AST_OPTION_ECHOCAN:
06909       cp = (char *) data;
06910       if (*cp) {
06911          ast_debug(1, "Enabling echo cancellation on %s\n", chan->name);
06912          dahdi_enable_ec(p);
06913       } else {
06914          ast_debug(1, "Disabling echo cancellation on %s\n", chan->name);
06915          dahdi_disable_ec(p);
06916       }
06917       break;
06918    case AST_OPTION_DIGIT_DETECT:
06919       cp = (char *) data;
06920       ast_debug(1, "%sabling digit detection on %s\n", *cp ? "En" : "Dis", chan->name);
06921       if (*cp) {
06922          enable_dtmf_detect(p);
06923       } else {
06924          disable_dtmf_detect(p);
06925       }
06926       break;
06927    case AST_OPTION_FAX_DETECT:
06928       cp = (char *) data;
06929       if (p->dsp) {
06930          ast_debug(1, "%sabling fax tone detection on %s\n", *cp ? "En" : "Dis", chan->name);
06931          if (*cp) {
06932             p->dsp_features |= DSP_FEATURE_FAX_DETECT;
06933          } else {
06934             p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
06935          }
06936          ast_dsp_set_features(p->dsp, p->dsp_features);
06937       }
06938       break;
06939    default:
06940       return -1;
06941    }
06942    errno = 0;
06943 
06944    return 0;
06945 }
06946 
06947 static int dahdi_func_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len)
06948 {
06949    struct dahdi_pvt *p = chan->tech_pvt;
06950    int res = 0;
06951 
06952    if (!p) {
06953       /* No private structure! */
06954       *buf = '\0';
06955       return -1;
06956    }
06957 
06958    if (!strcasecmp(data, "rxgain")) {
06959       ast_mutex_lock(&p->lock);
06960       snprintf(buf, len, "%f", p->rxgain);
06961       ast_mutex_unlock(&p->lock);
06962    } else if (!strcasecmp(data, "txgain")) {
06963       ast_mutex_lock(&p->lock);
06964       snprintf(buf, len, "%f", p->txgain);
06965       ast_mutex_unlock(&p->lock);
06966    } else if (!strcasecmp(data, "dahdi_channel")) {
06967       ast_mutex_lock(&p->lock);
06968       snprintf(buf, len, "%d", p->channel);
06969       ast_mutex_unlock(&p->lock);
06970    } else if (!strcasecmp(data, "dahdi_span")) {
06971       ast_mutex_lock(&p->lock);
06972       snprintf(buf, len, "%d", p->span);
06973       ast_mutex_unlock(&p->lock);
06974    } else if (!strcasecmp(data, "dahdi_type")) {
06975       ast_mutex_lock(&p->lock);
06976       switch (p->sig) {
06977 #if defined(HAVE_OPENR2)
06978       case SIG_MFCR2:
06979          ast_copy_string(buf, "mfc/r2", len);
06980          break;
06981 #endif   /* defined(HAVE_OPENR2) */
06982 #if defined(HAVE_PRI)
06983       case SIG_PRI_LIB_HANDLE_CASES:
06984          ast_copy_string(buf, "pri", len);
06985          break;
06986 #endif   /* defined(HAVE_PRI) */
06987       case 0:
06988          ast_copy_string(buf, "pseudo", len);
06989          break;
06990 #if defined(HAVE_SS7)
06991       case SIG_SS7:
06992          ast_copy_string(buf, "ss7", len);
06993          break;
06994 #endif   /* defined(HAVE_SS7) */
06995       default:
06996          /* The only thing left is analog ports. */
06997          ast_copy_string(buf, "analog", len);
06998          break;
06999       }
07000       ast_mutex_unlock(&p->lock);
07001 #if defined(HAVE_PRI)
07002 #if defined(HAVE_PRI_REVERSE_CHARGE)
07003    } else if (!strcasecmp(data, "reversecharge")) {
07004       ast_mutex_lock(&p->lock);
07005       switch (p->sig) {
07006       case SIG_PRI_LIB_HANDLE_CASES:
07007          snprintf(buf, len, "%d", ((struct sig_pri_chan *) p->sig_pvt)->reverse_charging_indication);
07008          break;
07009       default:
07010          *buf = '\0';
07011          res = -1;
07012          break;
07013       }
07014       ast_mutex_unlock(&p->lock);
07015 #endif
07016 #if defined(HAVE_PRI_SETUP_KEYPAD)
07017    } else if (!strcasecmp(data, "keypad_digits")) {
07018       ast_mutex_lock(&p->lock);
07019       switch (p->sig) {
07020       case SIG_PRI_LIB_HANDLE_CASES:
07021          ast_copy_string(buf, ((struct sig_pri_chan *) p->sig_pvt)->keypad_digits,
07022             len);
07023          break;
07024       default:
07025          *buf = '\0';
07026          res = -1;
07027          break;
07028       }
07029       ast_mutex_unlock(&p->lock);
07030 #endif   /* defined(HAVE_PRI_SETUP_KEYPAD) */
07031    } else if (!strcasecmp(data, "no_media_path")) {
07032       ast_mutex_lock(&p->lock);
07033       switch (p->sig) {
07034       case SIG_PRI_LIB_HANDLE_CASES:
07035          /*
07036           * TRUE if the call is on hold or is call waiting because
07037           * there is no media path available.
07038           */
07039          snprintf(buf, len, "%d", ((struct sig_pri_chan *) p->sig_pvt)->no_b_channel);
07040          break;
07041       default:
07042          *buf = '\0';
07043          res = -1;
07044          break;
07045       }
07046       ast_mutex_unlock(&p->lock);
07047 #endif   /* defined(HAVE_PRI) */
07048    } else {
07049       *buf = '\0';
07050       res = -1;
07051    }
07052 
07053    return res;
07054 }
07055 
07056 
07057 static int parse_buffers_policy(const char *parse, int *num_buffers, int *policy)
07058 {
07059    int res;
07060    char policy_str[21] = "";
07061 
07062    if ((res = sscanf(parse, "%30d,%20s", num_buffers, policy_str)) != 2) {
07063       ast_log(LOG_WARNING, "Parsing buffer string '%s' failed.\n", parse);
07064       return 1;
07065    }
07066    if (*num_buffers < 0) {
07067       ast_log(LOG_WARNING, "Invalid buffer count given '%d'.\n", *num_buffers);
07068       return -1;
07069    }
07070    if (!strcasecmp(policy_str, "full")) {
07071       *policy = DAHDI_POLICY_WHEN_FULL;
07072    } else if (!strcasecmp(policy_str, "immediate")) {
07073       *policy = DAHDI_POLICY_IMMEDIATE;
07074 #if defined(HAVE_DAHDI_HALF_FULL)
07075    } else if (!strcasecmp(policy_str, "half")) {
07076       *policy = DAHDI_POLICY_HALF_FULL;
07077 #endif
07078    } else {
07079       ast_log(LOG_WARNING, "Invalid policy name given '%s'.\n", policy_str);
07080       return -1;
07081    }
07082 
07083    return 0;
07084 }
07085 
07086 static int dahdi_func_write(struct ast_channel *chan, const char *function, char *data, const char *value)
07087 {
07088    struct dahdi_pvt *p = chan->tech_pvt;
07089    int res = 0;
07090 
07091    if (!p) {
07092       /* No private structure! */
07093       return -1;
07094    }
07095 
07096    if (!strcasecmp(data, "buffers")) {
07097       int num_bufs, policy;
07098 
07099       if (!(parse_buffers_policy(value, &num_bufs, &policy))) {
07100          struct dahdi_bufferinfo bi = {
07101             .txbufpolicy = policy,
07102             .rxbufpolicy = policy,
07103             .bufsize = p->bufsize,
07104             .numbufs = num_bufs,
07105          };
07106          int bpres;
07107 
07108          if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
07109             ast_log(LOG_WARNING, "Channel '%d' unable to override buffer policy: %s\n", p->channel, strerror(errno));
07110          } else {
07111             p->bufferoverrideinuse = 1;
07112          }
07113       } else {
07114          res = -1;
07115       }
07116    } else if (!strcasecmp(data, "echocan_mode")) {
07117       if (!strcasecmp(value, "on")) {
07118          ast_mutex_lock(&p->lock);
07119          dahdi_enable_ec(p);
07120          ast_mutex_unlock(&p->lock);
07121       } else if (!strcasecmp(value, "off")) {
07122          ast_mutex_lock(&p->lock);
07123          dahdi_disable_ec(p);
07124          ast_mutex_unlock(&p->lock);
07125 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
07126       } else if (!strcasecmp(value, "fax")) {
07127          int blah = 1;
07128 
07129          ast_mutex_lock(&p->lock);
07130          if (!p->echocanon) {
07131             dahdi_enable_ec(p);
07132          }
07133          if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_FAX_MODE, &blah)) {
07134             ast_log(LOG_WARNING, "Unable to place echocan into fax mode on channel %d: %s\n", p->channel, strerror(errno));
07135          }
07136          ast_mutex_unlock(&p->lock);
07137       } else if (!strcasecmp(value, "voice")) {
07138          int blah = 0;
07139 
07140          ast_mutex_lock(&p->lock);
07141          if (!p->echocanon) {
07142             dahdi_enable_ec(p);
07143          }
07144          if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_FAX_MODE, &blah)) {
07145             ast_log(LOG_WARNING, "Unable to place echocan into voice mode on channel %d: %s\n", p->channel, strerror(errno));
07146          }
07147          ast_mutex_unlock(&p->lock);
07148 #endif
07149       } else {
07150          ast_log(LOG_WARNING, "Unsupported value '%s' provided for '%s' item.\n", value, data);
07151          res = -1;
07152       }
07153    } else {
07154       res = -1;
07155    }
07156 
07157    return res;
07158 }
07159 
07160 static void dahdi_unlink(struct dahdi_pvt *slave, struct dahdi_pvt *master, int needlock)
07161 {
07162    /* Unlink a specific slave or all slaves/masters from a given master */
07163    int x;
07164    int hasslaves;
07165    if (!master)
07166       return;
07167    if (needlock) {
07168       ast_mutex_lock(&master->lock);
07169       if (slave) {
07170          while (ast_mutex_trylock(&slave->lock)) {
07171             DEADLOCK_AVOIDANCE(&master->lock);
07172          }
07173       }
07174    }
07175    hasslaves = 0;
07176    for (x = 0; x < MAX_SLAVES; x++) {
07177       if (master->slaves[x]) {
07178          if (!slave || (master->slaves[x] == slave)) {
07179             /* Take slave out of the conference */
07180             ast_debug(1, "Unlinking slave %d from %d\n", master->slaves[x]->channel, master->channel);
07181             conf_del(master, &master->slaves[x]->subs[SUB_REAL], SUB_REAL);
07182             conf_del(master->slaves[x], &master->subs[SUB_REAL], SUB_REAL);
07183             master->slaves[x]->master = NULL;
07184             master->slaves[x] = NULL;
07185          } else
07186             hasslaves = 1;
07187       }
07188       if (!hasslaves)
07189          master->inconference = 0;
07190    }
07191    if (!slave) {
07192       if (master->master) {
07193          /* Take master out of the conference */
07194          conf_del(master->master, &master->subs[SUB_REAL], SUB_REAL);
07195          conf_del(master, &master->master->subs[SUB_REAL], SUB_REAL);
07196          hasslaves = 0;
07197          for (x = 0; x < MAX_SLAVES; x++) {
07198             if (master->master->slaves[x] == master)
07199                master->master->slaves[x] = NULL;
07200             else if (master->master->slaves[x])
07201                hasslaves = 1;
07202          }
07203          if (!hasslaves)
07204             master->master->inconference = 0;
07205       }
07206       master->master = NULL;
07207    }
07208    update_conf(master);
07209    if (needlock) {
07210       if (slave)
07211          ast_mutex_unlock(&slave->lock);
07212       ast_mutex_unlock(&master->lock);
07213    }
07214 }
07215 
07216 static void dahdi_link(struct dahdi_pvt *slave, struct dahdi_pvt *master) {
07217    int x;
07218    if (!slave || !master) {
07219       ast_log(LOG_WARNING, "Tried to link to/from NULL??\n");
07220       return;
07221    }
07222    for (x = 0; x < MAX_SLAVES; x++) {
07223       if (!master->slaves[x]) {
07224          master->slaves[x] = slave;
07225          break;
07226       }
07227    }
07228    if (x >= MAX_SLAVES) {
07229       ast_log(LOG_WARNING, "Replacing slave %d with new slave, %d\n", master->slaves[MAX_SLAVES - 1]->channel, slave->channel);
07230       master->slaves[MAX_SLAVES - 1] = slave;
07231    }
07232    if (slave->master)
07233       ast_log(LOG_WARNING, "Replacing master %d with new master, %d\n", slave->master->channel, master->channel);
07234    slave->master = master;
07235 
07236    ast_debug(1, "Making %d slave to master %d at %d\n", slave->channel, master->channel, x);
07237 }
07238 
07239 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)
07240 {
07241    struct ast_channel *who;
07242    struct dahdi_pvt *p0, *p1, *op0, *op1;
07243    struct dahdi_pvt *master = NULL, *slave = NULL;
07244    struct ast_frame *f;
07245    int inconf = 0;
07246    int nothingok = 1;
07247    int ofd0, ofd1;
07248    int oi0, oi1, i0 = -1, i1 = -1, t0, t1;
07249    int os0 = -1, os1 = -1;
07250    int priority = 0;
07251    struct ast_channel *oc0, *oc1;
07252    enum ast_bridge_result res;
07253    struct timeval start = ast_tvnow();
07254 #ifdef PRI_2BCT
07255    int triedtopribridge = 0;
07256    q931_call *q931c0;
07257    q931_call *q931c1;
07258 #endif
07259 
07260    /* For now, don't attempt to native bridge if either channel needs DTMF detection.
07261       There is code below to handle it properly until DTMF is actually seen,
07262       but due to currently unresolved issues it's ignored...
07263    */
07264 
07265    if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1))
07266       return AST_BRIDGE_FAILED_NOWARN;
07267 
07268    ast_channel_lock(c0);
07269    while (ast_channel_trylock(c1)) {
07270       CHANNEL_DEADLOCK_AVOIDANCE(c0);
07271    }
07272 
07273    p0 = c0->tech_pvt;
07274    p1 = c1->tech_pvt;
07275    /* cant do pseudo-channels here */
07276    if (!p0 || (!p0->sig) || !p1 || (!p1->sig)) {
07277       ast_channel_unlock(c0);
07278       ast_channel_unlock(c1);
07279       return AST_BRIDGE_FAILED_NOWARN;
07280    }
07281 
07282    oi0 = dahdi_get_index(c0, p0, 0);
07283    oi1 = dahdi_get_index(c1, p1, 0);
07284    if ((oi0 < 0) || (oi1 < 0)) {
07285       ast_channel_unlock(c0);
07286       ast_channel_unlock(c1);
07287       return AST_BRIDGE_FAILED;
07288    }
07289 
07290    op0 = p0 = c0->tech_pvt;
07291    op1 = p1 = c1->tech_pvt;
07292    ofd0 = c0->fds[0];
07293    ofd1 = c1->fds[0];
07294    oc0 = p0->owner;
07295    oc1 = p1->owner;
07296 
07297    if (ast_mutex_trylock(&p0->lock)) {
07298       /* Don't block, due to potential for deadlock */
07299       ast_channel_unlock(c0);
07300       ast_channel_unlock(c1);
07301       ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
07302       return AST_BRIDGE_RETRY;
07303    }
07304    if (ast_mutex_trylock(&p1->lock)) {
07305       /* Don't block, due to potential for deadlock */
07306       ast_mutex_unlock(&p0->lock);
07307       ast_channel_unlock(c0);
07308       ast_channel_unlock(c1);
07309       ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
07310       return AST_BRIDGE_RETRY;
07311    }
07312 
07313    if ((p0->callwaiting && p0->callwaitingcallerid)
07314       || (p1->callwaiting && p1->callwaitingcallerid)) {
07315       /*
07316        * Call Waiting Caller ID requires DTMF detection to know if it
07317        * can send the CID spill.
07318        *
07319        * For now, don't attempt to native bridge if either channel
07320        * needs DTMF detection.  There is code below to handle it
07321        * properly until DTMF is actually seen, but due to currently
07322        * unresolved issues it's ignored...
07323        */
07324       ast_mutex_unlock(&p0->lock);
07325       ast_mutex_unlock(&p1->lock);
07326       ast_channel_unlock(c0);
07327       ast_channel_unlock(c1);
07328       return AST_BRIDGE_FAILED_NOWARN;
07329    }
07330 
07331 #if defined(HAVE_PRI)
07332    if ((dahdi_sig_pri_lib_handles(p0->sig)
07333          && ((struct sig_pri_chan *) p0->sig_pvt)->no_b_channel)
07334       || (dahdi_sig_pri_lib_handles(p1->sig)
07335          && ((struct sig_pri_chan *) p1->sig_pvt)->no_b_channel)) {
07336       /*
07337        * PRI nobch channels (hold and call waiting) are equivalent to
07338        * pseudo channels and cannot be done here.
07339        */
07340       ast_mutex_unlock(&p0->lock);
07341       ast_mutex_unlock(&p1->lock);
07342       ast_channel_unlock(c0);
07343       ast_channel_unlock(c1);
07344       return AST_BRIDGE_FAILED_NOWARN;
07345    }
07346 #endif   /* defined(HAVE_PRI) */
07347 
07348    if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
07349       if (p0->owner && p1->owner) {
07350          /* If we don't have a call-wait in a 3-way, and we aren't in a 3-way, we can be master */
07351          if (!p0->subs[SUB_CALLWAIT].inthreeway && !p1->subs[SUB_REAL].inthreeway) {
07352             master = p0;
07353             slave = p1;
07354             inconf = 1;
07355          } else if (!p1->subs[SUB_CALLWAIT].inthreeway && !p0->subs[SUB_REAL].inthreeway) {
07356             master = p1;
07357             slave = p0;
07358             inconf = 1;
07359          } else {
07360             ast_log(LOG_WARNING, "Huh?  Both calls are callwaits or 3-ways?  That's clever...?\n");
07361             ast_log(LOG_WARNING, "p0: chan %d/%d/CW%d/3W%d, p1: chan %d/%d/CW%d/3W%d\n",
07362                p0->channel,
07363                oi0, (p0->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
07364                p0->subs[SUB_REAL].inthreeway, p0->channel,
07365                oi0, (p1->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
07366                p1->subs[SUB_REAL].inthreeway);
07367          }
07368          nothingok = 0;
07369       }
07370    } else if ((oi0 == SUB_REAL) && (oi1 == SUB_THREEWAY)) {
07371       if (p1->subs[SUB_THREEWAY].inthreeway) {
07372          master = p1;
07373          slave = p0;
07374          nothingok = 0;
07375       }
07376    } else if ((oi0 == SUB_THREEWAY) && (oi1 == SUB_REAL)) {
07377       if (p0->subs[SUB_THREEWAY].inthreeway) {
07378          master = p0;
07379          slave = p1;
07380          nothingok = 0;
07381       }
07382    } else if ((oi0 == SUB_REAL) && (oi1 == SUB_CALLWAIT)) {
07383       /* We have a real and a call wait.  If we're in a three way call, put us in it, otherwise,
07384          don't put us in anything */
07385       if (p1->subs[SUB_CALLWAIT].inthreeway) {
07386          master = p1;
07387          slave = p0;
07388          nothingok = 0;
07389       }
07390    } else if ((oi0 == SUB_CALLWAIT) && (oi1 == SUB_REAL)) {
07391       /* Same as previous */
07392       if (p0->subs[SUB_CALLWAIT].inthreeway) {
07393          master = p0;
07394          slave = p1;
07395          nothingok = 0;
07396       }
07397    }
07398    ast_debug(1, "master: %d, slave: %d, nothingok: %d\n",
07399       master ? master->channel : 0, slave ? slave->channel : 0, nothingok);
07400    if (master && slave) {
07401       /* Stop any tones, or play ringtone as appropriate.  If they're bridged
07402          in an active threeway call with a channel that is ringing, we should
07403          indicate ringing. */
07404       if ((oi1 == SUB_THREEWAY) &&
07405          p1->subs[SUB_THREEWAY].inthreeway &&
07406          p1->subs[SUB_REAL].owner &&
07407          p1->subs[SUB_REAL].inthreeway &&
07408          (p1->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
07409          ast_debug(1,
07410             "Playing ringback on %d/%d(%s) since %d/%d(%s) is in a ringing three-way\n",
07411             p0->channel, oi0, c0->name, p1->channel, oi1, c1->name);
07412          tone_zone_play_tone(p0->subs[oi0].dfd, DAHDI_TONE_RINGTONE);
07413          os1 = p1->subs[SUB_REAL].owner->_state;
07414       } else {
07415          ast_debug(1, "Stopping tones on %d/%d(%s) talking to %d/%d(%s)\n",
07416             p0->channel, oi0, c0->name, p1->channel, oi1, c1->name);
07417          tone_zone_play_tone(p0->subs[oi0].dfd, -1);
07418       }
07419       if ((oi0 == SUB_THREEWAY) &&
07420          p0->subs[SUB_THREEWAY].inthreeway &&
07421          p0->subs[SUB_REAL].owner &&
07422          p0->subs[SUB_REAL].inthreeway &&
07423          (p0->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
07424          ast_debug(1,
07425             "Playing ringback on %d/%d(%s) since %d/%d(%s) is in a ringing three-way\n",
07426             p1->channel, oi1, c1->name, p0->channel, oi0, c0->name);
07427          tone_zone_play_tone(p1->subs[oi1].dfd, DAHDI_TONE_RINGTONE);
07428          os0 = p0->subs[SUB_REAL].owner->_state;
07429       } else {
07430          ast_debug(1, "Stopping tones on %d/%d(%s) talking to %d/%d(%s)\n",
07431             p1->channel, oi1, c1->name, p0->channel, oi0, c0->name);
07432          tone_zone_play_tone(p1->subs[oi1].dfd, -1);
07433       }
07434       if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
07435          if (!p0->echocanbridged || !p1->echocanbridged) {
07436             /* Disable echo cancellation if appropriate */
07437             dahdi_disable_ec(p0);
07438             dahdi_disable_ec(p1);
07439          }
07440       }
07441       dahdi_link(slave, master);
07442       master->inconference = inconf;
07443    } else if (!nothingok)
07444       ast_log(LOG_WARNING, "Can't link %d/%s with %d/%s\n", p0->channel, subnames[oi0], p1->channel, subnames[oi1]);
07445 
07446    update_conf(p0);
07447    update_conf(p1);
07448    t0 = p0->subs[SUB_REAL].inthreeway;
07449    t1 = p1->subs[SUB_REAL].inthreeway;
07450 
07451    ast_mutex_unlock(&p0->lock);
07452    ast_mutex_unlock(&p1->lock);
07453 
07454    ast_channel_unlock(c0);
07455    ast_channel_unlock(c1);
07456 
07457    /* Native bridge failed */
07458    if ((!master || !slave) && !nothingok) {
07459       dahdi_enable_ec(p0);
07460       dahdi_enable_ec(p1);
07461       return AST_BRIDGE_FAILED;
07462    }
07463 
07464    ast_verb(3, "Native bridging %s and %s\n", c0->name, c1->name);
07465 
07466    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
07467       disable_dtmf_detect(op0);
07468 
07469    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
07470       disable_dtmf_detect(op1);
07471 
07472    for (;;) {
07473       struct ast_channel *c0_priority[2] = {c0, c1};
07474       struct ast_channel *c1_priority[2] = {c1, c0};
07475       int ms;
07476 
07477       /* Here's our main loop...  Start by locking things, looking for private parts,
07478          and then balking if anything is wrong */
07479 
07480       ast_channel_lock(c0);
07481       while (ast_channel_trylock(c1)) {
07482          CHANNEL_DEADLOCK_AVOIDANCE(c0);
07483       }
07484 
07485       p0 = c0->tech_pvt;
07486       p1 = c1->tech_pvt;
07487 
07488       if (op0 == p0)
07489          i0 = dahdi_get_index(c0, p0, 1);
07490       if (op1 == p1)
07491          i1 = dahdi_get_index(c1, p1, 1);
07492 
07493       ast_channel_unlock(c0);
07494       ast_channel_unlock(c1);
07495       ms = ast_remaining_ms(start, timeoutms);
07496       if (!ms ||
07497          (op0 != p0) ||
07498          (op1 != p1) ||
07499          (ofd0 != c0->fds[0]) ||
07500          (ofd1 != c1->fds[0]) ||
07501          (p0->subs[SUB_REAL].owner && (os0 > -1) && (os0 != p0->subs[SUB_REAL].owner->_state)) ||
07502          (p1->subs[SUB_REAL].owner && (os1 > -1) && (os1 != p1->subs[SUB_REAL].owner->_state)) ||
07503          (oc0 != p0->owner) ||
07504          (oc1 != p1->owner) ||
07505          (t0 != p0->subs[SUB_REAL].inthreeway) ||
07506          (t1 != p1->subs[SUB_REAL].inthreeway) ||
07507          (oi0 != i0) ||
07508          (oi1 != i1)) {
07509          ast_debug(1, "Something changed out on %d/%d to %d/%d, returning -3 to restart\n",
07510             op0->channel, oi0, op1->channel, oi1);
07511          res = AST_BRIDGE_RETRY;
07512          goto return_from_bridge;
07513       }
07514 
07515 #ifdef PRI_2BCT
07516       if (!triedtopribridge) {
07517          triedtopribridge = 1;
07518          if (p0->pri && p0->pri == p1->pri && p0->pri->transfer) {
07519             ast_mutex_lock(&p0->pri->lock);
07520             switch (p0->sig) {
07521             case SIG_PRI_LIB_HANDLE_CASES:
07522                q931c0 = ((struct sig_pri_chan *) (p0->sig_pvt))->call;
07523                break;
07524             default:
07525                q931c0 = NULL;
07526                break;
07527             }
07528             switch (p1->sig) {
07529             case SIG_PRI_LIB_HANDLE_CASES:
07530                q931c1 = ((struct sig_pri_chan *) (p1->sig_pvt))->call;
07531                break;
07532             default:
07533                q931c1 = NULL;
07534                break;
07535             }
07536             if (q931c0 && q931c1) {
07537                pri_channel_bridge(q931c0, q931c1);
07538             }
07539             ast_mutex_unlock(&p0->pri->lock);
07540          }
07541       }
07542 #endif
07543 
07544       who = ast_waitfor_n(priority ? c0_priority : c1_priority, 2, &ms);
07545       if (!who) {
07546          ast_debug(1, "Ooh, empty read...\n");
07547          continue;
07548       }
07549       f = ast_read(who);
07550       if (!f || (f->frametype == AST_FRAME_CONTROL)) {
07551          *fo = f;
07552          *rc = who;
07553          res = AST_BRIDGE_COMPLETE;
07554          goto return_from_bridge;
07555       }
07556       if (f->frametype == AST_FRAME_DTMF) {
07557          if ((who == c0) && p0->pulsedial) {
07558             ast_write(c1, f);
07559          } else if ((who == c1) && p1->pulsedial) {
07560             ast_write(c0, f);
07561          } else {
07562             *fo = f;
07563             *rc = who;
07564             res = AST_BRIDGE_COMPLETE;
07565             goto return_from_bridge;
07566          }
07567       }
07568       ast_frfree(f);
07569 
07570       /* Swap who gets priority */
07571       priority = !priority;
07572    }
07573 
07574 return_from_bridge:
07575    if (op0 == p0)
07576       dahdi_enable_ec(p0);
07577 
07578    if (op1 == p1)
07579       dahdi_enable_ec(p1);
07580 
07581    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
07582       enable_dtmf_detect(op0);
07583 
07584    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
07585       enable_dtmf_detect(op1);
07586 
07587    dahdi_unlink(slave, master, 1);
07588 
07589    return res;
07590 }
07591 
07592 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
07593 {
07594    struct dahdi_pvt *p = newchan->tech_pvt;
07595    int x;
07596 
07597    ast_mutex_lock(&p->lock);
07598 
07599    ast_debug(1, "New owner for channel %d is %s\n", p->channel, newchan->name);
07600    if (p->owner == oldchan) {
07601       p->owner = newchan;
07602    }
07603    for (x = 0; x < 3; x++) {
07604       if (p->subs[x].owner == oldchan) {
07605          if (!x) {
07606             dahdi_unlink(NULL, p, 0);
07607          }
07608          p->subs[x].owner = newchan;
07609       }
07610    }
07611    if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
07612       analog_fixup(oldchan, newchan, p->sig_pvt);
07613 #if defined(HAVE_PRI)
07614    } else if (dahdi_sig_pri_lib_handles(p->sig)) {
07615       sig_pri_fixup(oldchan, newchan, p->sig_pvt);
07616 #endif   /* defined(HAVE_PRI) */
07617 #if defined(HAVE_SS7)
07618    } else if (p->sig == SIG_SS7) {
07619       sig_ss7_fixup(oldchan, newchan, p->sig_pvt);
07620 #endif   /* defined(HAVE_SS7) */
07621    }
07622    update_conf(p);
07623 
07624    ast_mutex_unlock(&p->lock);
07625 
07626    if (newchan->_state == AST_STATE_RINGING) {
07627       dahdi_indicate(newchan, AST_CONTROL_RINGING, NULL, 0);
07628    }
07629    return 0;
07630 }
07631 
07632 static int dahdi_ring_phone(struct dahdi_pvt *p)
07633 {
07634    int x;
07635    int res;
07636    /* Make sure our transmit state is on hook */
07637    x = 0;
07638    x = DAHDI_ONHOOK;
07639    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
07640    do {
07641       x = DAHDI_RING;
07642       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
07643       if (res) {
07644          switch (errno) {
07645          case EBUSY:
07646          case EINTR:
07647             /* Wait just in case */
07648             usleep(10000);
07649             continue;
07650          case EINPROGRESS:
07651             res = 0;
07652             break;
07653          default:
07654             ast_log(LOG_WARNING, "Couldn't ring the phone: %s\n", strerror(errno));
07655             res = 0;
07656          }
07657       }
07658    } while (res);
07659    return res;
07660 }
07661 
07662 static void *analog_ss_thread(void *data);
07663 
07664 static int attempt_transfer(struct dahdi_pvt *p)
07665 {
07666    /* In order to transfer, we need at least one of the channels to
07667       actually be in a call bridge.  We can't conference two applications
07668       together (but then, why would we want to?) */
07669    if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
07670       /* The three-way person we're about to transfer to could still be in MOH, so
07671          stop if now if appropriate */
07672       if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner))
07673          ast_queue_control(p->subs[SUB_THREEWAY].owner, AST_CONTROL_UNHOLD);
07674       if (p->subs[SUB_REAL].owner->_state == AST_STATE_RINGING) {
07675          ast_indicate(ast_bridged_channel(p->subs[SUB_REAL].owner), AST_CONTROL_RINGING);
07676       }
07677       if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RING) {
07678          tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE);
07679       }
07680        if (ast_channel_masquerade(p->subs[SUB_THREEWAY].owner, ast_bridged_channel(p->subs[SUB_REAL].owner))) {
07681          ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
07682                ast_bridged_channel(p->subs[SUB_REAL].owner)->name, p->subs[SUB_THREEWAY].owner->name);
07683          return -1;
07684       }
07685       /* Orphan the channel after releasing the lock */
07686       ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
07687       unalloc_sub(p, SUB_THREEWAY);
07688    } else if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
07689       ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
07690       if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RINGING) {
07691          ast_indicate(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), AST_CONTROL_RINGING);
07692       }
07693       if (p->subs[SUB_REAL].owner->_state == AST_STATE_RING) {
07694          tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
07695       }
07696       if (ast_channel_masquerade(p->subs[SUB_REAL].owner, ast_bridged_channel(p->subs[SUB_THREEWAY].owner))) {
07697          ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
07698                ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->name, p->subs[SUB_REAL].owner->name);
07699          return -1;
07700       }
07701       /* Three-way is now the REAL */
07702       swap_subs(p, SUB_THREEWAY, SUB_REAL);
07703       ast_channel_unlock(p->subs[SUB_REAL].owner);
07704       unalloc_sub(p, SUB_THREEWAY);
07705       /* Tell the caller not to hangup */
07706       return 1;
07707    } else {
07708       ast_debug(1, "Neither %s nor %s are in a bridge, nothing to transfer\n",
07709          p->subs[SUB_REAL].owner->name, p->subs[SUB_THREEWAY].owner->name);
07710       p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
07711       return -1;
07712    }
07713    return 0;
07714 }
07715 
07716 static int check_for_conference(struct dahdi_pvt *p)
07717 {
07718    struct dahdi_confinfo ci;
07719    /* Fine if we already have a master, etc */
07720    if (p->master || (p->confno > -1))
07721       return 0;
07722    memset(&ci, 0, sizeof(ci));
07723    if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
07724       ast_log(LOG_WARNING, "Failed to get conference info on channel %d: %s\n", p->channel, strerror(errno));
07725       return 0;
07726    }
07727    /* If we have no master and don't have a confno, then
07728       if we're in a conference, it's probably a MeetMe room or
07729       some such, so don't let us 3-way out! */
07730    if ((p->subs[SUB_REAL].curconf.confno != ci.confno) || (p->subs[SUB_REAL].curconf.confmode != ci.confmode)) {
07731       ast_verb(3, "Avoiding 3-way call when in an external conference\n");
07732       return 1;
07733    }
07734    return 0;
07735 }
07736 
07737 /*! Checks channel for alarms
07738  * \param p a channel to check for alarms.
07739  * \returns the alarms on the span to which the channel belongs, or alarms on
07740  *          the channel if no span alarms.
07741  */
07742 static int get_alarms(struct dahdi_pvt *p)
07743 {
07744    int res;
07745    struct dahdi_spaninfo zi;
07746    struct dahdi_params params;
07747 
07748    memset(&zi, 0, sizeof(zi));
07749    zi.spanno = p->span;
07750 
07751    if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SPANSTAT, &zi)) >= 0) {
07752       if (zi.alarms != DAHDI_ALARM_NONE)
07753          return zi.alarms;
07754    } else {
07755       ast_log(LOG_WARNING, "Unable to determine alarm on channel %d: %s\n", p->channel, strerror(errno));
07756       return 0;
07757    }
07758 
07759    /* No alarms on the span. Check for channel alarms. */
07760    memset(&params, 0, sizeof(params));
07761    if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &params)) >= 0)
07762       return params.chan_alarms;
07763 
07764    ast_log(LOG_WARNING, "Unable to determine alarm on channel %d\n", p->channel);
07765 
07766    return DAHDI_ALARM_NONE;
07767 }
07768 
07769 static void dahdi_handle_dtmf(struct ast_channel *ast, int idx, struct ast_frame **dest)
07770 {
07771    struct dahdi_pvt *p = ast->tech_pvt;
07772    struct ast_frame *f = *dest;
07773 
07774    ast_debug(1, "%s DTMF digit: 0x%02X '%c' on %s\n",
07775       f->frametype == AST_FRAME_DTMF_BEGIN ? "Begin" : "End",
07776       f->subclass.integer, f->subclass.integer, ast->name);
07777 
07778    if (p->confirmanswer) {
07779       if (f->frametype == AST_FRAME_DTMF_END) {
07780          ast_debug(1, "Confirm answer on %s!\n", ast->name);
07781          /* Upon receiving a DTMF digit, consider this an answer confirmation instead
07782             of a DTMF digit */
07783          p->subs[idx].f.frametype = AST_FRAME_CONTROL;
07784          p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
07785          /* Reset confirmanswer so DTMF's will behave properly for the duration of the call */
07786          p->confirmanswer = 0;
07787       } else {
07788          p->subs[idx].f.frametype = AST_FRAME_NULL;
07789          p->subs[idx].f.subclass.integer = 0;
07790       }
07791       *dest = &p->subs[idx].f;
07792    } else if (p->callwaitcas) {
07793       if (f->frametype == AST_FRAME_DTMF_END) {
07794          if ((f->subclass.integer == 'A') || (f->subclass.integer == 'D')) {
07795             ast_debug(1, "Got some DTMF, but it's for the CAS\n");
07796             ast_free(p->cidspill);
07797             p->cidspill = NULL;
07798             send_cwcidspill(p);
07799          }
07800          p->callwaitcas = 0;
07801       }
07802       p->subs[idx].f.frametype = AST_FRAME_NULL;
07803       p->subs[idx].f.subclass.integer = 0;
07804       *dest = &p->subs[idx].f;
07805    } else if (f->subclass.integer == 'f') {
07806       if (f->frametype == AST_FRAME_DTMF_END) {
07807          /* Fax tone -- Handle and return NULL */
07808          if ((p->callprogress & CALLPROGRESS_FAX) && !p->faxhandled) {
07809             /* If faxbuffers are configured, use them for the fax transmission */
07810             if (p->usefaxbuffers && !p->bufferoverrideinuse) {
07811                struct dahdi_bufferinfo bi = {
07812                   .txbufpolicy = p->faxbuf_policy,
07813                   .bufsize = p->bufsize,
07814                   .numbufs = p->faxbuf_no
07815                };
07816                int res;
07817 
07818                if ((res = ioctl(p->subs[idx].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
07819                   ast_log(LOG_WARNING, "Channel '%s' unable to set buffer policy, reason: %s\n", ast->name, strerror(errno));
07820                } else {
07821                   p->bufferoverrideinuse = 1;
07822                }
07823             }
07824             p->faxhandled = 1;
07825             if (p->dsp) {
07826                p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
07827                ast_dsp_set_features(p->dsp, p->dsp_features);
07828                ast_debug(1, "Disabling FAX tone detection on %s after tone received\n", ast->name);
07829             }
07830             if (strcmp(ast->exten, "fax")) {
07831                const char *target_context = S_OR(ast->macrocontext, ast->context);
07832 
07833                /* We need to unlock 'ast' here because ast_exists_extension has the
07834                 * potential to start autoservice on the channel. Such action is prone
07835                 * to deadlock.
07836                 */
07837                ast_mutex_unlock(&p->lock);
07838                ast_channel_unlock(ast);
07839                if (ast_exists_extension(ast, target_context, "fax", 1,
07840                   S_COR(ast->caller.id.number.valid, ast->caller.id.number.str, NULL))) {
07841                   ast_channel_lock(ast);
07842                   ast_mutex_lock(&p->lock);
07843                   ast_verb(3, "Redirecting %s to fax extension\n", ast->name);
07844                   /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
07845                   pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten);
07846                   if (ast_async_goto(ast, target_context, "fax", 1))
07847                      ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context);
07848                } else {
07849                   ast_channel_lock(ast);
07850                   ast_mutex_lock(&p->lock);
07851                   ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
07852                }
07853             } else {
07854                ast_debug(1, "Already in a fax extension, not redirecting\n");
07855             }
07856          } else {
07857             ast_debug(1, "Fax already handled\n");
07858          }
07859          dahdi_confmute(p, 0);
07860       }
07861       p->subs[idx].f.frametype = AST_FRAME_NULL;
07862       p->subs[idx].f.subclass.integer = 0;
07863       *dest = &p->subs[idx].f;
07864    }
07865 }
07866 
07867 static void handle_alarms(struct dahdi_pvt *p, int alms)
07868 {
07869    const char *alarm_str;
07870 
07871 #if defined(HAVE_PRI)
07872    if (dahdi_sig_pri_lib_handles(p->sig) && sig_pri_is_alarm_ignored(p->pri)) {
07873       return;
07874    }
07875 #endif   /* defined(HAVE_PRI) */
07876 
07877    alarm_str = alarm2str(alms);
07878    if (report_alarms & REPORT_CHANNEL_ALARMS) {
07879       ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", p->channel, alarm_str);
07880       manager_event(EVENT_FLAG_SYSTEM, "Alarm",
07881                  "Alarm: %s\r\n"
07882                  "Channel: %d\r\n",
07883                  alarm_str, p->channel);
07884    }
07885 
07886    if (report_alarms & REPORT_SPAN_ALARMS && p->manages_span_alarms) {
07887       ast_log(LOG_WARNING, "Detected alarm on span %d: %s\n", p->span, alarm_str);
07888       manager_event(EVENT_FLAG_SYSTEM, "SpanAlarm",
07889                  "Alarm: %s\r\n"
07890                  "Span: %d\r\n",
07891                  alarm_str, p->span);
07892    }
07893 }
07894 
07895 static struct ast_frame *dahdi_handle_event(struct ast_channel *ast)
07896 {
07897    int res, x;
07898    int idx, mysig;
07899    char *c;
07900    struct dahdi_pvt *p = ast->tech_pvt;
07901    pthread_t threadid;
07902    struct ast_channel *chan;
07903    struct ast_frame *f;
07904 
07905    idx = dahdi_get_index(ast, p, 0);
07906    if (idx < 0) {
07907       return &ast_null_frame;
07908    }
07909    mysig = p->sig;
07910    if (p->outsigmod > -1)
07911       mysig = p->outsigmod;
07912    p->subs[idx].f.frametype = AST_FRAME_NULL;
07913    p->subs[idx].f.subclass.integer = 0;
07914    p->subs[idx].f.datalen = 0;
07915    p->subs[idx].f.samples = 0;
07916    p->subs[idx].f.mallocd = 0;
07917    p->subs[idx].f.offset = 0;
07918    p->subs[idx].f.src = "dahdi_handle_event";
07919    p->subs[idx].f.data.ptr = NULL;
07920    f = &p->subs[idx].f;
07921 
07922    if (p->fake_event) {
07923       res = p->fake_event;
07924       p->fake_event = 0;
07925    } else
07926       res = dahdi_get_event(p->subs[idx].dfd);
07927 
07928    ast_debug(1, "Got event %s(%d) on channel %d (index %d)\n", event2str(res), res, p->channel, idx);
07929 
07930    if (res & (DAHDI_EVENT_PULSEDIGIT | DAHDI_EVENT_DTMFUP)) {
07931       p->pulsedial = (res & DAHDI_EVENT_PULSEDIGIT) ? 1 : 0;
07932       ast_debug(1, "Detected %sdigit '%c'\n", p->pulsedial ? "pulse ": "", res & 0xff);
07933 #if defined(HAVE_PRI)
07934       if (dahdi_sig_pri_lib_handles(p->sig)
07935          && ((struct sig_pri_chan *) p->sig_pvt)->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING
07936          && p->pri
07937          && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
07938          /* absorb event */
07939       } else
07940 #endif   /* defined(HAVE_PRI) */
07941       {
07942          /* Unmute conference */
07943          dahdi_confmute(p, 0);
07944          p->subs[idx].f.frametype = AST_FRAME_DTMF_END;
07945          p->subs[idx].f.subclass.integer = res & 0xff;
07946          dahdi_handle_dtmf(ast, idx, &f);
07947       }
07948       return f;
07949    }
07950 
07951    if (res & DAHDI_EVENT_DTMFDOWN) {
07952       ast_debug(1, "DTMF Down '%c'\n", res & 0xff);
07953 #if defined(HAVE_PRI)
07954       if (dahdi_sig_pri_lib_handles(p->sig)
07955          && ((struct sig_pri_chan *) p->sig_pvt)->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING
07956          && p->pri
07957          && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
07958          /* absorb event */
07959       } else
07960 #endif   /* defined(HAVE_PRI) */
07961       {
07962          /* Mute conference */
07963          dahdi_confmute(p, 1);
07964          p->subs[idx].f.frametype = AST_FRAME_DTMF_BEGIN;
07965          p->subs[idx].f.subclass.integer = res & 0xff;
07966          dahdi_handle_dtmf(ast, idx, &f);
07967       }
07968       return &p->subs[idx].f;
07969    }
07970 
07971    switch (res) {
07972    case DAHDI_EVENT_EC_DISABLED:
07973       ast_verb(3, "Channel %d echo canceler disabled.\n", p->channel);
07974       p->echocanon = 0;
07975       break;
07976 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
07977    case DAHDI_EVENT_TX_CED_DETECTED:
07978       ast_verb(3, "Channel %d detected a CED tone towards the network.\n", p->channel);
07979       break;
07980    case DAHDI_EVENT_RX_CED_DETECTED:
07981       ast_verb(3, "Channel %d detected a CED tone from the network.\n", p->channel);
07982       break;
07983    case DAHDI_EVENT_EC_NLP_DISABLED:
07984       ast_verb(3, "Channel %d echo canceler disabled its NLP.\n", p->channel);
07985       break;
07986    case DAHDI_EVENT_EC_NLP_ENABLED:
07987       ast_verb(3, "Channel %d echo canceler enabled its NLP.\n", p->channel);
07988       break;
07989 #endif
07990    case DAHDI_EVENT_BITSCHANGED:
07991 #ifdef HAVE_OPENR2
07992       if (p->sig != SIG_MFCR2) {
07993          ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig));
07994       } else {
07995          ast_log(LOG_DEBUG, "bits changed in chan %d\n", p->channel);
07996          openr2_chan_handle_cas(p->r2chan);
07997       }
07998 #else
07999       ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig));
08000 #endif
08001       break;
08002    case DAHDI_EVENT_PULSE_START:
08003       /* Stop tone if there's a pulse start and the PBX isn't started */
08004       if (!ast->pbx)
08005          tone_zone_play_tone(p->subs[idx].dfd, -1);
08006       break;
08007    case DAHDI_EVENT_DIALCOMPLETE:
08008       /* DAHDI has completed dialing all digits sent using DAHDI_DIAL. */
08009 #if defined(HAVE_PRI)
08010       if (dahdi_sig_pri_lib_handles(p->sig)) {
08011          if (p->inalarm) {
08012             break;
08013          }
08014          if (ioctl(p->subs[idx].dfd, DAHDI_DIALING, &x) == -1) {
08015             ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed on %s: %s\n", ast->name,
08016                strerror(errno));
08017             return NULL;
08018          }
08019          if (x) {
08020             /* Still dialing in DAHDI driver */
08021             break;
08022          }
08023          /*
08024           * The ast channel is locked and the private may be locked more
08025           * than once.
08026           */
08027          sig_pri_dial_complete(p->sig_pvt, ast);
08028          break;
08029       }
08030 #endif   /* defined(HAVE_PRI) */
08031 #ifdef HAVE_OPENR2
08032       if ((p->sig & SIG_MFCR2) && p->r2chan && ast->_state != AST_STATE_UP) {
08033          /* we don't need to do anything for this event for R2 signaling
08034             if the call is being setup */
08035          break;
08036       }
08037 #endif
08038       if (p->inalarm) break;
08039       if ((p->radio || (p->oprmode < 0))) break;
08040       if (ioctl(p->subs[idx].dfd,DAHDI_DIALING,&x) == -1) {
08041          ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed on %s: %s\n",ast->name, strerror(errno));
08042          return NULL;
08043       }
08044       if (!x) { /* if not still dialing in driver */
08045          dahdi_enable_ec(p);
08046          if (p->echobreak) {
08047             dahdi_train_ec(p);
08048             ast_copy_string(p->dop.dialstr, p->echorest, sizeof(p->dop.dialstr));
08049             p->dop.op = DAHDI_DIAL_OP_REPLACE;
08050             res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
08051             p->echobreak = 0;
08052          } else {
08053             p->dialing = 0;
08054             if ((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) {
08055                /* if thru with dialing after offhook */
08056                if (ast->_state == AST_STATE_DIALING_OFFHOOK) {
08057                   ast_setstate(ast, AST_STATE_UP);
08058                   p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08059                   p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
08060                   break;
08061                } else { /* if to state wait for offhook to dial rest */
08062                   /* we now wait for off hook */
08063                   ast_setstate(ast,AST_STATE_DIALING_OFFHOOK);
08064                }
08065             }
08066             if (ast->_state == AST_STATE_DIALING) {
08067                if ((p->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
08068                   ast_debug(1, "Done dialing, but waiting for progress detection before doing more...\n");
08069                } else if (p->confirmanswer || (!p->dialednone
08070                   && ((mysig == SIG_EM) || (mysig == SIG_EM_E1)
08071                      || (mysig == SIG_EMWINK) || (mysig == SIG_FEATD)
08072                      || (mysig == SIG_FEATDMF_TA) || (mysig == SIG_FEATDMF)
08073                      || (mysig == SIG_E911) || (mysig == SIG_FGC_CAMA)
08074                      || (mysig == SIG_FGC_CAMAMF) || (mysig == SIG_FEATB)
08075                      || (mysig == SIG_SF) || (mysig == SIG_SFWINK)
08076                      || (mysig == SIG_SF_FEATD) || (mysig == SIG_SF_FEATDMF)
08077                      || (mysig == SIG_SF_FEATB)))) {
08078                   ast_setstate(ast, AST_STATE_RINGING);
08079                } else if (!p->answeronpolarityswitch) {
08080                   ast_setstate(ast, AST_STATE_UP);
08081                   p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08082                   p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
08083                   /* If aops=0 and hops=1, this is necessary */
08084                   p->polarity = POLARITY_REV;
08085                } else {
08086                   /* Start clean, so we can catch the change to REV polarity when party answers */
08087                   p->polarity = POLARITY_IDLE;
08088                }
08089             }
08090          }
08091       }
08092       break;
08093    case DAHDI_EVENT_ALARM:
08094       switch (p->sig) {
08095 #if defined(HAVE_PRI)
08096       case SIG_PRI_LIB_HANDLE_CASES:
08097          sig_pri_chan_alarm_notify(p->sig_pvt, 0);
08098          break;
08099 #endif   /* defined(HAVE_PRI) */
08100 #if defined(HAVE_SS7)
08101       case SIG_SS7:
08102          sig_ss7_set_alarm(p->sig_pvt, 1);
08103          break;
08104 #endif   /* defined(HAVE_SS7) */
08105       default:
08106          p->inalarm = 1;
08107          break;
08108       }
08109       res = get_alarms(p);
08110       handle_alarms(p, res);
08111 #ifdef HAVE_PRI
08112       if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
08113          /* fall through intentionally */
08114       } else {
08115          break;
08116       }
08117 #endif
08118 #if defined(HAVE_SS7)
08119       if (p->sig == SIG_SS7)
08120          break;
08121 #endif   /* defined(HAVE_SS7) */
08122 #ifdef HAVE_OPENR2
08123       if (p->sig == SIG_MFCR2)
08124          break;
08125 #endif
08126    case DAHDI_EVENT_ONHOOK:
08127       if (p->radio) {
08128          p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08129          p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_UNKEY;
08130          break;
08131       }
08132       if (p->oprmode < 0)
08133       {
08134          if (p->oprmode != -1) break;
08135          if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
08136          {
08137             /* Make sure it starts ringing */
08138             dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
08139             dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RING);
08140             save_conference(p->oprpeer);
08141             tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
08142          }
08143          break;
08144       }
08145       switch (p->sig) {
08146       case SIG_FXOLS:
08147       case SIG_FXOGS:
08148       case SIG_FXOKS:
08149          /* Check for some special conditions regarding call waiting */
08150          if (idx == SUB_REAL) {
08151             /* The normal line was hung up */
08152             if (p->subs[SUB_CALLWAIT].owner) {
08153                /* There's a call waiting call, so ring the phone, but make it unowned in the mean time */
08154                swap_subs(p, SUB_CALLWAIT, SUB_REAL);
08155                ast_verb(3, "Channel %d still has (callwait) call, ringing phone\n", p->channel);
08156                unalloc_sub(p, SUB_CALLWAIT);
08157 #if 0
08158                p->subs[idx].needanswer = 0;
08159                p->subs[idx].needringing = 0;
08160 #endif
08161                p->callwaitingrepeat = 0;
08162                p->cidcwexpire = 0;
08163                p->cid_suppress_expire = 0;
08164                p->owner = NULL;
08165                /* Don't start streaming audio yet if the incoming call isn't up yet */
08166                if (p->subs[SUB_REAL].owner->_state != AST_STATE_UP)
08167                   p->dialing = 1;
08168                dahdi_ring_phone(p);
08169             } else if (p->subs[SUB_THREEWAY].owner) {
08170                unsigned int mssinceflash;
08171                /* Here we have to retain the lock on both the main channel, the 3-way channel, and
08172                   the private structure -- not especially easy or clean */
08173                while (p->subs[SUB_THREEWAY].owner && ast_channel_trylock(p->subs[SUB_THREEWAY].owner)) {
08174                   /* Yuck, didn't get the lock on the 3-way, gotta release everything and re-grab! */
08175                   DLA_UNLOCK(&p->lock);
08176                   CHANNEL_DEADLOCK_AVOIDANCE(ast);
08177                   /* We can grab ast and p in that order, without worry.  We should make sure
08178                      nothing seriously bad has happened though like some sort of bizarre double
08179                      masquerade! */
08180                   DLA_LOCK(&p->lock);
08181                   if (p->owner != ast) {
08182                      ast_log(LOG_WARNING, "This isn't good...\n");
08183                      return NULL;
08184                   }
08185                }
08186                if (!p->subs[SUB_THREEWAY].owner) {
08187                   ast_log(LOG_NOTICE, "Whoa, threeway disappeared kinda randomly.\n");
08188                   return NULL;
08189                }
08190                mssinceflash = ast_tvdiff_ms(ast_tvnow(), p->flashtime);
08191                ast_debug(1, "Last flash was %d ms ago\n", mssinceflash);
08192                if (mssinceflash < MIN_MS_SINCE_FLASH) {
08193                   /* It hasn't been long enough since the last flashook.  This is probably a bounce on
08194                      hanging up.  Hangup both channels now */
08195                   if (p->subs[SUB_THREEWAY].owner)
08196                      ast_queue_hangup_with_cause(p->subs[SUB_THREEWAY].owner, AST_CAUSE_NO_ANSWER);
08197                   p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08198                   ast_debug(1, "Looks like a bounced flash, hanging up both calls on %d\n", p->channel);
08199                   ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08200                } else if ((ast->pbx) || (ast->_state == AST_STATE_UP)) {
08201                   if (p->transfer) {
08202                      /* In any case this isn't a threeway call anymore */
08203                      p->subs[SUB_REAL].inthreeway = 0;
08204                      p->subs[SUB_THREEWAY].inthreeway = 0;
08205                      /* Only attempt transfer if the phone is ringing; why transfer to busy tone eh? */
08206                      if (!p->transfertobusy && ast->_state == AST_STATE_BUSY) {
08207                         ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08208                         /* Swap subs and dis-own channel */
08209                         swap_subs(p, SUB_THREEWAY, SUB_REAL);
08210                         p->owner = NULL;
08211                         /* Ring the phone */
08212                         dahdi_ring_phone(p);
08213                      } else {
08214                         if ((res = attempt_transfer(p)) < 0) {
08215                            p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08216                            if (p->subs[SUB_THREEWAY].owner)
08217                               ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08218                         } else if (res) {
08219                            /* Don't actually hang up at this point */
08220                            if (p->subs[SUB_THREEWAY].owner)
08221                               ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08222                            break;
08223                         }
08224                      }
08225                   } else {
08226                      p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08227                      if (p->subs[SUB_THREEWAY].owner)
08228                         ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08229                   }
08230                } else {
08231                   ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08232                   /* Swap subs and dis-own channel */
08233                   swap_subs(p, SUB_THREEWAY, SUB_REAL);
08234                   p->owner = NULL;
08235                   /* Ring the phone */
08236                   dahdi_ring_phone(p);
08237                }
08238             }
08239          } else {
08240             ast_log(LOG_WARNING, "Got a hangup and my index is %d?\n", idx);
08241          }
08242          /* Fall through */
08243       default:
08244          dahdi_disable_ec(p);
08245          return NULL;
08246       }
08247       break;
08248    case DAHDI_EVENT_RINGOFFHOOK:
08249       if (p->inalarm) break;
08250       if (p->oprmode < 0)
08251       {
08252          if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
08253          {
08254             /* Make sure it stops ringing */
08255             dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
08256             tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, -1);
08257             restore_conference(p->oprpeer);
08258          }
08259          break;
08260       }
08261       if (p->radio)
08262       {
08263          p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08264          p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_KEY;
08265          break;
08266       }
08267       /* for E911, its supposed to wait for offhook then dial
08268          the second half of the dial string */
08269       if (((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) && (ast->_state == AST_STATE_DIALING_OFFHOOK)) {
08270          c = strchr(p->dialdest, '/');
08271          if (c)
08272             c++;
08273          else
08274             c = p->dialdest;
08275          if (*c) snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*0%s#", c);
08276          else ast_copy_string(p->dop.dialstr,"M*2#", sizeof(p->dop.dialstr));
08277          if (strlen(p->dop.dialstr) > 4) {
08278             memset(p->echorest, 'w', sizeof(p->echorest) - 1);
08279             strcpy(p->echorest + (p->echotraining / 401) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
08280             p->echorest[sizeof(p->echorest) - 1] = '\0';
08281             p->echobreak = 1;
08282             p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
08283          } else
08284             p->echobreak = 0;
08285          if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
08286             int saveerr = errno;
08287 
08288             x = DAHDI_ONHOOK;
08289             ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
08290             ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
08291             return NULL;
08292             }
08293          p->dialing = 1;
08294          return &p->subs[idx].f;
08295       }
08296       switch (p->sig) {
08297       case SIG_FXOLS:
08298       case SIG_FXOGS:
08299       case SIG_FXOKS:
08300          switch (ast->_state) {
08301          case AST_STATE_RINGING:
08302             dahdi_enable_ec(p);
08303             dahdi_train_ec(p);
08304             p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08305             p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
08306             /* Make sure it stops ringing */
08307             p->subs[SUB_REAL].needringing = 0;
08308             dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
08309             ast_debug(1, "channel %d answered\n", p->channel);
08310 
08311             /* Cancel any running CallerID spill */
08312             ast_free(p->cidspill);
08313             p->cidspill = NULL;
08314             restore_conference(p);
08315 
08316             p->dialing = 0;
08317             p->callwaitcas = 0;
08318             if (p->confirmanswer) {
08319                /* Ignore answer if "confirm answer" is enabled */
08320                p->subs[idx].f.frametype = AST_FRAME_NULL;
08321                p->subs[idx].f.subclass.integer = 0;
08322             } else if (!ast_strlen_zero(p->dop.dialstr)) {
08323                /* nick@dccinc.com 4/3/03 - fxo should be able to do deferred dialing */
08324                res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
08325                if (res < 0) {
08326                   ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
08327                   p->dop.dialstr[0] = '\0';
08328                   return NULL;
08329                } else {
08330                   ast_debug(1, "Sent FXO deferred digit string: %s\n", p->dop.dialstr);
08331                   p->subs[idx].f.frametype = AST_FRAME_NULL;
08332                   p->subs[idx].f.subclass.integer = 0;
08333                   p->dialing = 1;
08334                }
08335                p->dop.dialstr[0] = '\0';
08336                ast_setstate(ast, AST_STATE_DIALING);
08337             } else
08338                ast_setstate(ast, AST_STATE_UP);
08339             return &p->subs[idx].f;
08340          case AST_STATE_DOWN:
08341             ast_setstate(ast, AST_STATE_RING);
08342             ast->rings = 1;
08343             p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08344             p->subs[idx].f.subclass.integer = AST_CONTROL_OFFHOOK;
08345             ast_debug(1, "channel %d picked up\n", p->channel);
08346             return &p->subs[idx].f;
08347          case AST_STATE_UP:
08348             /* Make sure it stops ringing */
08349             dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
08350             /* Okay -- probably call waiting*/
08351             if (ast_bridged_channel(p->owner))
08352                ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
08353             p->subs[idx].needunhold = 1;
08354             break;
08355          case AST_STATE_RESERVED:
08356             /* Start up dialtone */
08357             if (has_voicemail(p))
08358                res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
08359             else
08360                res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
08361             break;
08362          default:
08363             ast_log(LOG_WARNING, "FXO phone off hook in weird state %d??\n", ast->_state);
08364          }
08365          break;
08366       case SIG_FXSLS:
08367       case SIG_FXSGS:
08368       case SIG_FXSKS:
08369          if (ast->_state == AST_STATE_RING) {
08370             p->ringt = p->ringt_base;
08371          }
08372 
08373          /* If we get a ring then we cannot be in
08374           * reversed polarity. So we reset to idle */
08375          ast_debug(1, "Setting IDLE polarity due "
08376             "to ring. Old polarity was %d\n",
08377             p->polarity);
08378          p->polarity = POLARITY_IDLE;
08379 
08380          /* Fall through */
08381       case SIG_EM:
08382       case SIG_EM_E1:
08383       case SIG_EMWINK:
08384       case SIG_FEATD:
08385       case SIG_FEATDMF:
08386       case SIG_FEATDMF_TA:
08387       case SIG_E911:
08388       case SIG_FGC_CAMA:
08389       case SIG_FGC_CAMAMF:
08390       case SIG_FEATB:
08391       case SIG_SF:
08392       case SIG_SFWINK:
08393       case SIG_SF_FEATD:
08394       case SIG_SF_FEATDMF:
08395       case SIG_SF_FEATB:
08396          if (ast->_state == AST_STATE_PRERING)
08397             ast_setstate(ast, AST_STATE_RING);
08398          if ((ast->_state == AST_STATE_DOWN) || (ast->_state == AST_STATE_RING)) {
08399             ast_debug(1, "Ring detected\n");
08400             p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08401             p->subs[idx].f.subclass.integer = AST_CONTROL_RING;
08402          } else if (p->outgoing && ((ast->_state == AST_STATE_RINGING) || (ast->_state == AST_STATE_DIALING))) {
08403             ast_debug(1, "Line answered\n");
08404             if (p->confirmanswer) {
08405                p->subs[idx].f.frametype = AST_FRAME_NULL;
08406                p->subs[idx].f.subclass.integer = 0;
08407             } else {
08408                p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08409                p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
08410                ast_setstate(ast, AST_STATE_UP);
08411             }
08412          } else if (ast->_state != AST_STATE_RING)
08413             ast_log(LOG_WARNING, "Ring/Off-hook in strange state %d on channel %d\n", ast->_state, p->channel);
08414          break;
08415       default:
08416          ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
08417       }
08418       break;
08419    case DAHDI_EVENT_RINGBEGIN:
08420       switch (p->sig) {
08421       case SIG_FXSLS:
08422       case SIG_FXSGS:
08423       case SIG_FXSKS:
08424          if (ast->_state == AST_STATE_RING) {
08425             p->ringt = p->ringt_base;
08426          }
08427          break;
08428       }
08429       break;
08430    case DAHDI_EVENT_RINGERON:
08431       break;
08432    case DAHDI_EVENT_NOALARM:
08433       switch (p->sig) {
08434 #if defined(HAVE_PRI)
08435       case SIG_PRI_LIB_HANDLE_CASES:
08436          sig_pri_chan_alarm_notify(p->sig_pvt, 1);
08437          break;
08438 #endif   /* defined(HAVE_PRI) */
08439 #if defined(HAVE_SS7)
08440       case SIG_SS7:
08441          sig_ss7_set_alarm(p->sig_pvt, 0);
08442          break;
08443 #endif   /* defined(HAVE_SS7) */
08444       default:
08445          p->inalarm = 0;
08446          break;
08447       }
08448       handle_clear_alarms(p);
08449       break;
08450    case DAHDI_EVENT_WINKFLASH:
08451       if (p->inalarm) break;
08452       if (p->radio) break;
08453       if (p->oprmode < 0) break;
08454       if (p->oprmode > 1)
08455       {
08456          struct dahdi_params par;
08457 
08458          memset(&par, 0, sizeof(par));
08459          if (ioctl(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par) != -1)
08460          {
08461             if (!par.rxisoffhook)
08462             {
08463                /* Make sure it stops ringing */
08464                dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
08465                dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RING);
08466                save_conference(p);
08467                tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
08468             }
08469          }
08470          break;
08471       }
08472       /* Remember last time we got a flash-hook */
08473       p->flashtime = ast_tvnow();
08474       switch (mysig) {
08475       case SIG_FXOLS:
08476       case SIG_FXOGS:
08477       case SIG_FXOKS:
08478          ast_debug(1, "Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n",
08479             idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
08480 
08481          /* Cancel any running CallerID spill */
08482          ast_free(p->cidspill);
08483          p->cidspill = NULL;
08484          restore_conference(p);
08485          p->callwaitcas = 0;
08486 
08487          if (idx != SUB_REAL) {
08488             ast_log(LOG_WARNING, "Got flash hook with index %d on channel %d?!?\n", idx, p->channel);
08489             goto winkflashdone;
08490          }
08491 
08492          if (p->subs[SUB_CALLWAIT].owner) {
08493             /* Swap to call-wait */
08494             swap_subs(p, SUB_REAL, SUB_CALLWAIT);
08495             tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
08496             p->owner = p->subs[SUB_REAL].owner;
08497             ast_debug(1, "Making %s the new owner\n", p->owner->name);
08498             if (p->owner->_state == AST_STATE_RINGING) {
08499                ast_setstate(p->owner, AST_STATE_UP);
08500                p->subs[SUB_REAL].needanswer = 1;
08501             }
08502             p->callwaitingrepeat = 0;
08503             p->cidcwexpire = 0;
08504             p->cid_suppress_expire = 0;
08505             /* Start music on hold if appropriate */
08506             if (!p->subs[SUB_CALLWAIT].inthreeway && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
08507                ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
08508                   S_OR(p->mohsuggest, NULL),
08509                   !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
08510             }
08511             p->subs[SUB_CALLWAIT].needhold = 1;
08512             if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
08513                ast_queue_control_data(p->subs[SUB_REAL].owner, AST_CONTROL_HOLD,
08514                   S_OR(p->mohsuggest, NULL),
08515                   !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
08516             }
08517             p->subs[SUB_REAL].needunhold = 1;
08518          } else if (!p->subs[SUB_THREEWAY].owner) {
08519             if (!p->threewaycalling) {
08520                /* Just send a flash if no 3-way calling */
08521                p->subs[SUB_REAL].needflash = 1;
08522                goto winkflashdone;
08523             } else if (!check_for_conference(p)) {
08524                char cid_num[256];
08525                char cid_name[256];
08526 
08527                cid_num[0] = 0;
08528                cid_name[0] = 0;
08529                if (p->dahditrcallerid && p->owner) {
08530                   if (p->owner->caller.id.number.valid
08531                      && p->owner->caller.id.number.str) {
08532                      ast_copy_string(cid_num, p->owner->caller.id.number.str,
08533                         sizeof(cid_num));
08534                   }
08535                   if (p->owner->caller.id.name.valid
08536                      && p->owner->caller.id.name.str) {
08537                      ast_copy_string(cid_name, p->owner->caller.id.name.str,
08538                         sizeof(cid_name));
08539                   }
08540                }
08541                /* XXX This section needs much more error checking!!! XXX */
08542                /* Start a 3-way call if feasible */
08543                if (!((ast->pbx) ||
08544                   (ast->_state == AST_STATE_UP) ||
08545                   (ast->_state == AST_STATE_RING))) {
08546                   ast_debug(1, "Flash when call not up or ringing\n");
08547                   goto winkflashdone;
08548                }
08549                if (alloc_sub(p, SUB_THREEWAY)) {
08550                   ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n");
08551                   goto winkflashdone;
08552                }
08553 
08554                /*
08555                 * Make new channel
08556                 *
08557                 * We cannot hold the p or ast locks while creating a new
08558                 * channel.
08559                 */
08560                ast_mutex_unlock(&p->lock);
08561                ast_channel_unlock(ast);
08562                chan = dahdi_new(p, AST_STATE_RESERVED, 0, SUB_THREEWAY, 0, NULL);
08563                ast_channel_lock(ast);
08564                ast_mutex_lock(&p->lock);
08565                if (p->dahditrcallerid) {
08566                   if (!p->origcid_num)
08567                      p->origcid_num = ast_strdup(p->cid_num);
08568                   if (!p->origcid_name)
08569                      p->origcid_name = ast_strdup(p->cid_name);
08570                   ast_copy_string(p->cid_num, cid_num, sizeof(p->cid_num));
08571                   ast_copy_string(p->cid_name, cid_name, sizeof(p->cid_name));
08572                }
08573                /* Swap things around between the three-way and real call */
08574                swap_subs(p, SUB_THREEWAY, SUB_REAL);
08575                /* Disable echo canceller for better dialing */
08576                dahdi_disable_ec(p);
08577                res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALRECALL);
08578                if (res)
08579                   ast_log(LOG_WARNING, "Unable to start dial recall tone on channel %d\n", p->channel);
08580                p->owner = chan;
08581                if (!chan) {
08582                   ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", p->channel);
08583                } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
08584                   ast_log(LOG_WARNING, "Unable to start simple switch on channel %d\n", p->channel);
08585                   res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
08586                   dahdi_enable_ec(p);
08587                   ast_hangup(chan);
08588                } else {
08589                   ast_verb(3, "Started three way call on channel %d\n", p->channel);
08590 
08591                   /* Start music on hold if appropriate */
08592                   if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
08593                      ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
08594                         S_OR(p->mohsuggest, NULL),
08595                         !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
08596                   }
08597                   p->subs[SUB_THREEWAY].needhold = 1;
08598                }
08599             }
08600          } else {
08601             /* Already have a 3 way call */
08602             if (p->subs[SUB_THREEWAY].inthreeway) {
08603                /* Call is already up, drop the last person */
08604                ast_debug(1, "Got flash with three way call up, dropping last call on %d\n", p->channel);
08605                /* If the primary call isn't answered yet, use it */
08606                if ((p->subs[SUB_REAL].owner->_state != AST_STATE_UP) && (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_UP)) {
08607                   /* Swap back -- we're dropping the real 3-way that isn't finished yet*/
08608                   swap_subs(p, SUB_THREEWAY, SUB_REAL);
08609                   p->owner = p->subs[SUB_REAL].owner;
08610                }
08611                /* Drop the last call and stop the conference */
08612                ast_verb(3, "Dropping three-way call on %s\n", p->subs[SUB_THREEWAY].owner->name);
08613                p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08614                p->subs[SUB_REAL].inthreeway = 0;
08615                p->subs[SUB_THREEWAY].inthreeway = 0;
08616             } else {
08617                /* Lets see what we're up to */
08618                if (((ast->pbx) || (ast->_state == AST_STATE_UP)) &&
08619                   (p->transfertobusy || (ast->_state != AST_STATE_BUSY))) {
08620                   int otherindex = SUB_THREEWAY;
08621 
08622                   ast_verb(3, "Building conference call with %s and %s\n",
08623                      p->subs[SUB_THREEWAY].owner->name,
08624                      p->subs[SUB_REAL].owner->name);
08625                   /* Put them in the threeway, and flip */
08626                   p->subs[SUB_THREEWAY].inthreeway = 1;
08627                   p->subs[SUB_REAL].inthreeway = 1;
08628                   if (ast->_state == AST_STATE_UP) {
08629                      swap_subs(p, SUB_THREEWAY, SUB_REAL);
08630                      otherindex = SUB_REAL;
08631                   }
08632                   if (p->subs[otherindex].owner && ast_bridged_channel(p->subs[otherindex].owner))
08633                      ast_queue_control(p->subs[otherindex].owner, AST_CONTROL_UNHOLD);
08634                   p->subs[otherindex].needunhold = 1;
08635                   p->owner = p->subs[SUB_REAL].owner;
08636                } else {
08637                   ast_verb(3, "Dumping incomplete call on on %s\n", p->subs[SUB_THREEWAY].owner->name);
08638                   swap_subs(p, SUB_THREEWAY, SUB_REAL);
08639                   p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08640                   p->owner = p->subs[SUB_REAL].owner;
08641                   if (p->subs[SUB_REAL].owner && ast_bridged_channel(p->subs[SUB_REAL].owner))
08642                      ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
08643                   p->subs[SUB_REAL].needunhold = 1;
08644                   dahdi_enable_ec(p);
08645                }
08646             }
08647          }
08648 winkflashdone:
08649          update_conf(p);
08650          break;
08651       case SIG_EM:
08652       case SIG_EM_E1:
08653       case SIG_FEATD:
08654       case SIG_SF:
08655       case SIG_SFWINK:
08656       case SIG_SF_FEATD:
08657       case SIG_FXSLS:
08658       case SIG_FXSGS:
08659          if (p->dialing)
08660             ast_debug(1, "Ignoring wink on channel %d\n", p->channel);
08661          else
08662             ast_debug(1, "Got wink in weird state %d on channel %d\n", ast->_state, p->channel);
08663          break;
08664       case SIG_FEATDMF_TA:
08665          switch (p->whichwink) {
08666          case 0:
08667             ast_debug(1, "ANI2 set to '%d' and ANI is '%s'\n", p->owner->caller.ani2,
08668                S_COR(p->owner->caller.ani.number.valid,
08669                   p->owner->caller.ani.number.str, ""));
08670             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%d%s#",
08671                p->owner->caller.ani2,
08672                S_COR(p->owner->caller.ani.number.valid,
08673                   p->owner->caller.ani.number.str, ""));
08674             break;
08675          case 1:
08676             ast_copy_string(p->dop.dialstr, p->finaldial, sizeof(p->dop.dialstr));
08677             break;
08678          case 2:
08679             ast_log(LOG_WARNING, "Received unexpected wink on channel of type SIG_FEATDMF_TA\n");
08680             return NULL;
08681          }
08682          p->whichwink++;
08683          /* Fall through */
08684       case SIG_FEATDMF:
08685       case SIG_E911:
08686       case SIG_FGC_CAMAMF:
08687       case SIG_FGC_CAMA:
08688       case SIG_FEATB:
08689       case SIG_SF_FEATDMF:
08690       case SIG_SF_FEATB:
08691       case SIG_EMWINK:
08692          /* FGD MF and EMWINK *Must* wait for wink */
08693          if (!ast_strlen_zero(p->dop.dialstr)) {
08694             res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
08695             if (res < 0) {
08696                ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
08697                p->dop.dialstr[0] = '\0';
08698                return NULL;
08699             } else
08700                ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
08701          }
08702          p->dop.dialstr[0] = '\0';
08703          break;
08704       default:
08705          ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
08706       }
08707       break;
08708    case DAHDI_EVENT_HOOKCOMPLETE:
08709       if (p->inalarm) break;
08710       if ((p->radio || (p->oprmode < 0))) break;
08711       if (p->waitingfordt.tv_sec) break;
08712       switch (mysig) {
08713       case SIG_FXSLS:  /* only interesting for FXS */
08714       case SIG_FXSGS:
08715       case SIG_FXSKS:
08716       case SIG_EM:
08717       case SIG_EM_E1:
08718       case SIG_EMWINK:
08719       case SIG_FEATD:
08720       case SIG_SF:
08721       case SIG_SFWINK:
08722       case SIG_SF_FEATD:
08723          if (!ast_strlen_zero(p->dop.dialstr)) {
08724             res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
08725             if (res < 0) {
08726                ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
08727                p->dop.dialstr[0] = '\0';
08728                return NULL;
08729             } else
08730                ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
08731          }
08732          p->dop.dialstr[0] = '\0';
08733          p->dop.op = DAHDI_DIAL_OP_REPLACE;
08734          break;
08735       case SIG_FEATDMF:
08736       case SIG_FEATDMF_TA:
08737       case SIG_E911:
08738       case SIG_FGC_CAMA:
08739       case SIG_FGC_CAMAMF:
08740       case SIG_FEATB:
08741       case SIG_SF_FEATDMF:
08742       case SIG_SF_FEATB:
08743          ast_debug(1, "Got hook complete in MF FGD, waiting for wink now on channel %d\n",p->channel);
08744          break;
08745       default:
08746          break;
08747       }
08748       break;
08749    case DAHDI_EVENT_POLARITY:
08750       /*
08751        * If we get a Polarity Switch event, check to see
08752        * if we should change the polarity state and
08753        * mark the channel as UP or if this is an indication
08754        * of remote end disconnect.
08755        */
08756       if (p->polarity == POLARITY_IDLE) {
08757          p->polarity = POLARITY_REV;
08758          if (p->answeronpolarityswitch &&
08759             ((ast->_state == AST_STATE_DIALING) ||
08760             (ast->_state == AST_STATE_RINGING))) {
08761             ast_debug(1, "Answering on polarity switch!\n");
08762             ast_setstate(p->owner, AST_STATE_UP);
08763             if (p->hanguponpolarityswitch) {
08764                p->polaritydelaytv = ast_tvnow();
08765             }
08766          } else
08767             ast_debug(1, "Ignore switch to REVERSED Polarity on channel %d, state %d\n", p->channel, ast->_state);
08768       }
08769       /* Removed else statement from here as it was preventing hangups from ever happening*/
08770       /* Added AST_STATE_RING in if statement below to deal with calling party hangups that take place when ringing */
08771       if (p->hanguponpolarityswitch &&
08772          (p->polarityonanswerdelay > 0) &&
08773          (p->polarity == POLARITY_REV) &&
08774          ((ast->_state == AST_STATE_UP) || (ast->_state == AST_STATE_RING)) ) {
08775          /* Added log_debug information below to provide a better indication of what is going on */
08776          ast_debug(1, "Polarity Reversal event occured - DEBUG 1: channel %d, state %d, pol= %d, aonp= %d, honp= %d, pdelay= %d, tv= %" PRIi64 "\n", p->channel, ast->_state, p->polarity, p->answeronpolarityswitch, p->hanguponpolarityswitch, p->polarityonanswerdelay, ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) );
08777 
08778          if (ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) > p->polarityonanswerdelay) {
08779             ast_debug(1, "Polarity Reversal detected and now Hanging up on channel %d\n", p->channel);
08780             ast_softhangup(p->owner, AST_SOFTHANGUP_EXPLICIT);
08781             p->polarity = POLARITY_IDLE;
08782          } else
08783             ast_debug(1, "Polarity Reversal detected but NOT hanging up (too close to answer event) on channel %d, state %d\n", p->channel, ast->_state);
08784 
08785       } else {
08786          p->polarity = POLARITY_IDLE;
08787          ast_debug(1, "Ignoring Polarity switch to IDLE on channel %d, state %d\n", p->channel, ast->_state);
08788       }
08789       /* Added more log_debug information below to provide a better indication of what is going on */
08790       ast_debug(1, "Polarity Reversal event occured - DEBUG 2: channel %d, state %d, pol= %d, aonp= %d, honp= %d, pdelay= %d, tv= %" PRIi64 "\n", p->channel, ast->_state, p->polarity, p->answeronpolarityswitch, p->hanguponpolarityswitch, p->polarityonanswerdelay, ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) );
08791       break;
08792    default:
08793       ast_debug(1, "Dunno what to do with event %d on channel %d\n", res, p->channel);
08794    }
08795    return &p->subs[idx].f;
08796 }
08797 
08798 static struct ast_frame *__dahdi_exception(struct ast_channel *ast)
08799 {
08800    int res;
08801    int idx;
08802    struct ast_frame *f;
08803    int usedindex = -1;
08804    struct dahdi_pvt *p = ast->tech_pvt;
08805 
08806    if ((idx = dahdi_get_index(ast, p, 0)) < 0) {
08807       idx = SUB_REAL;
08808    }
08809 
08810    p->subs[idx].f.frametype = AST_FRAME_NULL;
08811    p->subs[idx].f.datalen = 0;
08812    p->subs[idx].f.samples = 0;
08813    p->subs[idx].f.mallocd = 0;
08814    p->subs[idx].f.offset = 0;
08815    p->subs[idx].f.subclass.integer = 0;
08816    p->subs[idx].f.delivery = ast_tv(0,0);
08817    p->subs[idx].f.src = "dahdi_exception";
08818    p->subs[idx].f.data.ptr = NULL;
08819 
08820 
08821    if ((!p->owner) && (!(p->radio || (p->oprmode < 0)))) {
08822       /* If nobody owns us, absorb the event appropriately, otherwise
08823          we loop indefinitely.  This occurs when, during call waiting, the
08824          other end hangs up our channel so that it no longer exists, but we
08825          have neither FLASH'd nor ONHOOK'd to signify our desire to
08826          change to the other channel. */
08827       if (p->fake_event) {
08828          res = p->fake_event;
08829          p->fake_event = 0;
08830       } else
08831          res = dahdi_get_event(p->subs[SUB_REAL].dfd);
08832       /* Switch to real if there is one and this isn't something really silly... */
08833       if ((res != DAHDI_EVENT_RINGEROFF) && (res != DAHDI_EVENT_RINGERON) &&
08834          (res != DAHDI_EVENT_HOOKCOMPLETE)) {
08835          ast_debug(1, "Restoring owner of channel %d on event %d\n", p->channel, res);
08836          p->owner = p->subs[SUB_REAL].owner;
08837          if (p->owner && ast_bridged_channel(p->owner))
08838             ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
08839          p->subs[SUB_REAL].needunhold = 1;
08840       }
08841       switch (res) {
08842       case DAHDI_EVENT_ONHOOK:
08843          dahdi_disable_ec(p);
08844          if (p->owner) {
08845             ast_verb(3, "Channel %s still has call, ringing phone\n", p->owner->name);
08846             dahdi_ring_phone(p);
08847             p->callwaitingrepeat = 0;
08848             p->cidcwexpire = 0;
08849             p->cid_suppress_expire = 0;
08850          } else
08851             ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
08852          update_conf(p);
08853          break;
08854       case DAHDI_EVENT_RINGOFFHOOK:
08855          dahdi_enable_ec(p);
08856          dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
08857          if (p->owner && (p->owner->_state == AST_STATE_RINGING)) {
08858             p->subs[SUB_REAL].needanswer = 1;
08859             p->dialing = 0;
08860          }
08861          break;
08862       case DAHDI_EVENT_HOOKCOMPLETE:
08863       case DAHDI_EVENT_RINGERON:
08864       case DAHDI_EVENT_RINGEROFF:
08865          /* Do nothing */
08866          break;
08867       case DAHDI_EVENT_WINKFLASH:
08868          p->flashtime = ast_tvnow();
08869          if (p->owner) {
08870             ast_verb(3, "Channel %d flashed to other channel %s\n", p->channel, p->owner->name);
08871             if (p->owner->_state != AST_STATE_UP) {
08872                /* Answer if necessary */
08873                usedindex = dahdi_get_index(p->owner, p, 0);
08874                if (usedindex > -1) {
08875                   p->subs[usedindex].needanswer = 1;
08876                }
08877                ast_setstate(p->owner, AST_STATE_UP);
08878             }
08879             p->callwaitingrepeat = 0;
08880             p->cidcwexpire = 0;
08881             p->cid_suppress_expire = 0;
08882             if (ast_bridged_channel(p->owner))
08883                ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
08884             p->subs[SUB_REAL].needunhold = 1;
08885          } else
08886             ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
08887          update_conf(p);
08888          break;
08889       default:
08890          ast_log(LOG_WARNING, "Don't know how to absorb event %s\n", event2str(res));
08891       }
08892       f = &p->subs[idx].f;
08893       return f;
08894    }
08895    if (!(p->radio || (p->oprmode < 0)))
08896       ast_debug(1, "Exception on %d, channel %d\n", ast->fds[0],p->channel);
08897    /* If it's not us, return NULL immediately */
08898    if (ast != p->owner) {
08899       if (p->owner) {
08900          ast_log(LOG_WARNING, "We're %s, not %s\n", ast->name, p->owner->name);
08901       }
08902       f = &p->subs[idx].f;
08903       return f;
08904    }
08905 
08906    f = dahdi_handle_event(ast);
08907    if (!f) {
08908       const char *name = ast_strdupa(ast->name);
08909 
08910       /* Tell the CDR this DAHDI device hung up */
08911       ast_mutex_unlock(&p->lock);
08912       ast_channel_unlock(ast);
08913       ast_set_hangupsource(ast, name, 0);
08914       ast_channel_lock(ast);
08915       ast_mutex_lock(&p->lock);
08916    }
08917    return f;
08918 }
08919 
08920 static struct ast_frame *dahdi_exception(struct ast_channel *ast)
08921 {
08922    struct dahdi_pvt *p = ast->tech_pvt;
08923    struct ast_frame *f;
08924    ast_mutex_lock(&p->lock);
08925    if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
08926       struct analog_pvt *analog_p = p->sig_pvt;
08927       f = analog_exception(analog_p, ast);
08928    } else {
08929       f = __dahdi_exception(ast);
08930    }
08931    ast_mutex_unlock(&p->lock);
08932    return f;
08933 }
08934 
08935 static struct ast_frame *dahdi_read(struct ast_channel *ast)
08936 {
08937    struct dahdi_pvt *p;
08938    int res;
08939    int idx;
08940    void *readbuf;
08941    struct ast_frame *f;
08942 
08943    /*
08944     * For analog channels, we must do deadlock avoidance because
08945     * analog ports can have more than one Asterisk channel using
08946     * the same private structure.
08947     */
08948    p = ast->tech_pvt;
08949    while (ast_mutex_trylock(&p->lock)) {
08950       CHANNEL_DEADLOCK_AVOIDANCE(ast);
08951 
08952       /*
08953        * Check to see if the channel is still associated with the same
08954        * private structure.  While the Asterisk channel was unlocked
08955        * the following events may have occured:
08956        *
08957        * 1) A masquerade may have associated the channel with another
08958        * technology or private structure.
08959        *
08960        * 2) For PRI calls, call signaling could change the channel
08961        * association to another B channel (private structure).
08962        */
08963       if (ast->tech_pvt != p) {
08964          /* The channel is no longer associated.  Quit gracefully. */
08965          return &ast_null_frame;
08966       }
08967    }
08968 
08969    idx = dahdi_get_index(ast, p, 0);
08970 
08971    /* Hang up if we don't really exist */
08972    if (idx < 0)   {
08973       ast_log(LOG_WARNING, "We don't exist?\n");
08974       ast_mutex_unlock(&p->lock);
08975       return NULL;
08976    }
08977 
08978    if ((p->radio || (p->oprmode < 0)) && p->inalarm) {
08979       ast_mutex_unlock(&p->lock);
08980       return NULL;
08981    }
08982 
08983    p->subs[idx].f.frametype = AST_FRAME_NULL;
08984    p->subs[idx].f.datalen = 0;
08985    p->subs[idx].f.samples = 0;
08986    p->subs[idx].f.mallocd = 0;
08987    p->subs[idx].f.offset = 0;
08988    p->subs[idx].f.subclass.integer = 0;
08989    p->subs[idx].f.delivery = ast_tv(0,0);
08990    p->subs[idx].f.src = "dahdi_read";
08991    p->subs[idx].f.data.ptr = NULL;
08992 
08993    /* make sure it sends initial key state as first frame */
08994    if ((p->radio || (p->oprmode < 0)) && (!p->firstradio))
08995    {
08996       struct dahdi_params ps;
08997 
08998       memset(&ps, 0, sizeof(ps));
08999       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
09000          ast_mutex_unlock(&p->lock);
09001          return NULL;
09002       }
09003       p->firstradio = 1;
09004       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09005       if (ps.rxisoffhook)
09006       {
09007          p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_KEY;
09008       }
09009       else
09010       {
09011          p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_UNKEY;
09012       }
09013       ast_mutex_unlock(&p->lock);
09014       return &p->subs[idx].f;
09015    }
09016    if (p->ringt > 0) {
09017       if (!(--p->ringt)) {
09018          ast_mutex_unlock(&p->lock);
09019          return NULL;
09020       }
09021    }
09022 
09023 #ifdef HAVE_OPENR2
09024    if (p->mfcr2) {
09025       openr2_chan_process_event(p->r2chan);
09026       if (OR2_DIR_FORWARD == openr2_chan_get_direction(p->r2chan)) {
09027          struct ast_frame f = { AST_FRAME_CONTROL, { AST_CONTROL_PROGRESS }, };
09028          /* if the call is already accepted and we already delivered AST_CONTROL_RINGING
09029           * now enqueue a progress frame to bridge the media up */
09030          if (p->mfcr2_call_accepted &&
09031              !p->mfcr2_progress && 
09032              ast->_state == AST_STATE_RINGING) {
09033             ast_log(LOG_DEBUG, "Enqueuing progress frame after R2 accept in chan %d\n", p->channel);
09034             ast_queue_frame(p->owner, &f);
09035             p->mfcr2_progress = 1;
09036          }
09037       }
09038    }
09039 #endif
09040 
09041    if (p->subs[idx].needringing) {
09042       /* Send ringing frame if requested */
09043       p->subs[idx].needringing = 0;
09044       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09045       p->subs[idx].f.subclass.integer = AST_CONTROL_RINGING;
09046       ast_setstate(ast, AST_STATE_RINGING);
09047       ast_mutex_unlock(&p->lock);
09048       return &p->subs[idx].f;
09049    }
09050 
09051    if (p->subs[idx].needbusy) {
09052       /* Send busy frame if requested */
09053       p->subs[idx].needbusy = 0;
09054       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09055       p->subs[idx].f.subclass.integer = AST_CONTROL_BUSY;
09056       ast_mutex_unlock(&p->lock);
09057       return &p->subs[idx].f;
09058    }
09059 
09060    if (p->subs[idx].needcongestion) {
09061       /* Send congestion frame if requested */
09062       p->subs[idx].needcongestion = 0;
09063       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09064       p->subs[idx].f.subclass.integer = AST_CONTROL_CONGESTION;
09065       ast_mutex_unlock(&p->lock);
09066       return &p->subs[idx].f;
09067    }
09068 
09069    if (p->subs[idx].needanswer) {
09070       /* Send answer frame if requested */
09071       p->subs[idx].needanswer = 0;
09072       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09073       p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
09074       ast_mutex_unlock(&p->lock);
09075       return &p->subs[idx].f;
09076    }
09077 #ifdef HAVE_OPENR2
09078    if (p->mfcr2 && openr2_chan_get_read_enabled(p->r2chan)) {
09079       /* openr2 took care of reading and handling any event
09080         (needanswer, needbusy etc), if we continue we will read()
09081         twice, lets just return a null frame. This should only
09082         happen when openr2 is dialing out */
09083       ast_mutex_unlock(&p->lock);
09084       return &ast_null_frame;
09085    }
09086 #endif
09087 
09088    if (p->subs[idx].needflash) {
09089       /* Send answer frame if requested */
09090       p->subs[idx].needflash = 0;
09091       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09092       p->subs[idx].f.subclass.integer = AST_CONTROL_FLASH;
09093       ast_mutex_unlock(&p->lock);
09094       return &p->subs[idx].f;
09095    }
09096 
09097    if (p->subs[idx].needhold) {
09098       /* Send answer frame if requested */
09099       p->subs[idx].needhold = 0;
09100       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09101       p->subs[idx].f.subclass.integer = AST_CONTROL_HOLD;
09102       ast_mutex_unlock(&p->lock);
09103       ast_debug(1, "Sending hold on '%s'\n", ast->name);
09104       return &p->subs[idx].f;
09105    }
09106 
09107    if (p->subs[idx].needunhold) {
09108       /* Send answer frame if requested */
09109       p->subs[idx].needunhold = 0;
09110       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09111       p->subs[idx].f.subclass.integer = AST_CONTROL_UNHOLD;
09112       ast_mutex_unlock(&p->lock);
09113       ast_debug(1, "Sending unhold on '%s'\n", ast->name);
09114       return &p->subs[idx].f;
09115    }
09116 
09117    /*
09118     * If we have a fake_event, fake an exception to handle it only
09119     * if this channel owns the private.
09120     */
09121    if (p->fake_event && p->owner == ast) {
09122       if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
09123          struct analog_pvt *analog_p = p->sig_pvt;
09124 
09125          f = analog_exception(analog_p, ast);
09126       } else {
09127          f = __dahdi_exception(ast);
09128       }
09129       ast_mutex_unlock(&p->lock);
09130       return f;
09131    }
09132 
09133    if (ast->rawreadformat == AST_FORMAT_SLINEAR) {
09134       if (!p->subs[idx].linear) {
09135          p->subs[idx].linear = 1;
09136          res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09137          if (res)
09138             ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to linear mode.\n", p->channel, idx);
09139       }
09140    } else if ((ast->rawreadformat == AST_FORMAT_ULAW) ||
09141       (ast->rawreadformat == AST_FORMAT_ALAW)) {
09142       if (p->subs[idx].linear) {
09143          p->subs[idx].linear = 0;
09144          res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09145          if (res)
09146             ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to companded mode.\n", p->channel, idx);
09147       }
09148    } else {
09149       ast_log(LOG_WARNING, "Don't know how to read frames in format %s\n", ast_getformatname(ast->rawreadformat));
09150       ast_mutex_unlock(&p->lock);
09151       return NULL;
09152    }
09153    readbuf = ((unsigned char *)p->subs[idx].buffer) + AST_FRIENDLY_OFFSET;
09154    CHECK_BLOCKING(ast);
09155    res = read(p->subs[idx].dfd, readbuf, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
09156    ast_clear_flag(ast, AST_FLAG_BLOCKING);
09157    /* Check for hangup */
09158    if (res < 0) {
09159       f = NULL;
09160       if (res == -1) {
09161          if (errno == EAGAIN) {
09162             /* Return "NULL" frame if there is nobody there */
09163             ast_mutex_unlock(&p->lock);
09164             return &p->subs[idx].f;
09165          } else if (errno == ELAST) {
09166             if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
09167                struct analog_pvt *analog_p = p->sig_pvt;
09168                f = analog_exception(analog_p, ast);
09169             } else {
09170                f = __dahdi_exception(ast);
09171             }
09172          } else
09173             ast_log(LOG_WARNING, "dahdi_rec: %s\n", strerror(errno));
09174       }
09175       ast_mutex_unlock(&p->lock);
09176       return f;
09177    }
09178    if (res != (p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE)) {
09179       ast_debug(1, "Short read (%d/%d), must be an event...\n", res, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
09180       if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
09181          struct analog_pvt *analog_p = p->sig_pvt;
09182          f = analog_exception(analog_p, ast);
09183       } else {
09184          f = __dahdi_exception(ast);
09185       }
09186       ast_mutex_unlock(&p->lock);
09187       return f;
09188    }
09189    if (p->tdd) { /* if in TDD mode, see if we receive that */
09190       int c;
09191 
09192       c = tdd_feed(p->tdd,readbuf,READ_SIZE);
09193       if (c < 0) {
09194          ast_debug(1,"tdd_feed failed\n");
09195          ast_mutex_unlock(&p->lock);
09196          return NULL;
09197       }
09198       if (c) { /* if a char to return */
09199          p->subs[idx].f.subclass.integer = 0;
09200          p->subs[idx].f.frametype = AST_FRAME_TEXT;
09201          p->subs[idx].f.mallocd = 0;
09202          p->subs[idx].f.offset = AST_FRIENDLY_OFFSET;
09203          p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET;
09204          p->subs[idx].f.datalen = 1;
09205          *((char *) p->subs[idx].f.data.ptr) = c;
09206          ast_mutex_unlock(&p->lock);
09207          return &p->subs[idx].f;
09208       }
09209    }
09210    if (idx == SUB_REAL) {
09211       /* Ensure the CW timers decrement only on a single subchannel */
09212       if (p->cidcwexpire) {
09213          if (!--p->cidcwexpire) {
09214             /* Expired CID/CW */
09215             ast_verb(3, "CPE does not support Call Waiting Caller*ID.\n");
09216             restore_conference(p);
09217          }
09218       }
09219       if (p->cid_suppress_expire) {
09220          --p->cid_suppress_expire;
09221       }
09222       if (p->callwaitingrepeat) {
09223          if (!--p->callwaitingrepeat) {
09224             /* Expired, Repeat callwaiting tone */
09225             ++p->callwaitrings;
09226             dahdi_callwait(ast);
09227          }
09228       }
09229    }
09230    if (p->subs[idx].linear) {
09231       p->subs[idx].f.datalen = READ_SIZE * 2;
09232    } else
09233       p->subs[idx].f.datalen = READ_SIZE;
09234 
09235    /* Handle CallerID Transmission */
09236    if ((p->owner == ast) && p->cidspill) {
09237       send_callerid(p);
09238    }
09239 
09240    p->subs[idx].f.frametype = AST_FRAME_VOICE;
09241    p->subs[idx].f.subclass.codec = ast->rawreadformat;
09242    p->subs[idx].f.samples = READ_SIZE;
09243    p->subs[idx].f.mallocd = 0;
09244    p->subs[idx].f.offset = AST_FRIENDLY_OFFSET;
09245    p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET / sizeof(p->subs[idx].buffer[0]);
09246 #if 0
09247    ast_debug(1, "Read %d of voice on %s\n", p->subs[idx].f.datalen, ast->name);
09248 #endif
09249    if (p->dialing ||  p->radio || /* Transmitting something */
09250       (idx && (ast->_state != AST_STATE_UP)) || /* Three-way or callwait that isn't up */
09251       ((idx == SUB_CALLWAIT) && !p->subs[SUB_CALLWAIT].inthreeway) /* Inactive and non-confed call-wait */
09252       ) {
09253       /* Whoops, we're still dialing, or in a state where we shouldn't transmit....
09254          don't send anything */
09255       p->subs[idx].f.frametype = AST_FRAME_NULL;
09256       p->subs[idx].f.subclass.integer = 0;
09257       p->subs[idx].f.samples = 0;
09258       p->subs[idx].f.mallocd = 0;
09259       p->subs[idx].f.offset = 0;
09260       p->subs[idx].f.data.ptr = NULL;
09261       p->subs[idx].f.datalen= 0;
09262    }
09263    if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect || p->callprogress || p->waitingfordt.tv_sec) && !idx) {
09264       /* Perform busy detection etc on the dahdi line */
09265       int mute;
09266 
09267       f = ast_dsp_process(ast, p->dsp, &p->subs[idx].f);
09268 
09269       /* Check if DSP code thinks we should be muting this frame and mute the conference if so */
09270       mute = ast_dsp_was_muted(p->dsp);
09271       if (p->muting != mute) {
09272          p->muting = mute;
09273          dahdi_confmute(p, mute);
09274       }
09275 
09276       if (f) {
09277          if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass.integer == AST_CONTROL_BUSY)) {
09278             if ((ast->_state == AST_STATE_UP) && !p->outgoing) {
09279                /* Treat this as a "hangup" instead of a "busy" on the assumption that
09280                   a busy */
09281                ast_frfree(f);
09282                f = NULL;
09283             }
09284          } else if (f->frametype == AST_FRAME_DTMF_BEGIN
09285             || f->frametype == AST_FRAME_DTMF_END) {
09286 #ifdef HAVE_PRI
09287             if (dahdi_sig_pri_lib_handles(p->sig)
09288                && ((struct sig_pri_chan *) p->sig_pvt)->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING
09289                && p->pri
09290                && ((!p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING))
09291                   || (p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)))) {
09292                /* Don't accept in-band DTMF when in overlap dial mode */
09293                ast_debug(1, "Absorbing inband %s DTMF digit: 0x%02X '%c' on %s\n",
09294                   f->frametype == AST_FRAME_DTMF_BEGIN ? "begin" : "end",
09295                   f->subclass.integer, f->subclass.integer, ast->name);
09296 
09297                f->frametype = AST_FRAME_NULL;
09298                f->subclass.integer = 0;
09299             }
09300 #endif
09301             /* DSP clears us of being pulse */
09302             p->pulsedial = 0;
09303          } else if (p->waitingfordt.tv_sec) {
09304             if (ast_tvdiff_ms(ast_tvnow(), p->waitingfordt) >= p->waitfordialtone ) {
09305                p->waitingfordt.tv_sec = 0;
09306                ast_log(LOG_WARNING, "Never saw dialtone on channel %d\n", p->channel);
09307                ast_frfree(f);
09308                f = NULL;
09309             } else if (f->frametype == AST_FRAME_VOICE) {
09310                f->frametype = AST_FRAME_NULL;
09311                f->subclass.integer = 0;
09312                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) {
09313                   p->waitingfordt.tv_sec = 0;
09314                   p->dsp_features &= ~DSP_FEATURE_WAITDIALTONE;
09315                   ast_dsp_set_features(p->dsp, p->dsp_features);
09316                   ast_log(LOG_DEBUG, "Got 10 samples of dialtone!\n");
09317                   if (!ast_strlen_zero(p->dop.dialstr)) { /* Dial deferred digits */
09318                      res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
09319                      if (res < 0) {
09320                         ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d\n", p->channel);
09321                         p->dop.dialstr[0] = '\0';
09322                         ast_mutex_unlock(&p->lock);
09323                         ast_frfree(f);
09324                         return NULL;
09325                      } else {
09326                         ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", p->dop.dialstr);
09327                         p->dialing = 1;
09328                         p->dop.dialstr[0] = '\0';
09329                         p->dop.op = DAHDI_DIAL_OP_REPLACE;
09330                         ast_setstate(ast, AST_STATE_DIALING);
09331                      }
09332                   }
09333                }
09334             }
09335          }
09336       }
09337    } else
09338       f = &p->subs[idx].f;
09339 
09340    if (f) {
09341       switch (f->frametype) {
09342       case AST_FRAME_DTMF_BEGIN:
09343       case AST_FRAME_DTMF_END:
09344          if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
09345             analog_handle_dtmf(p->sig_pvt, ast, idx, &f);
09346          } else {
09347             dahdi_handle_dtmf(ast, idx, &f);
09348          }
09349          break;
09350       case AST_FRAME_VOICE:
09351          if (p->cidspill || p->cid_suppress_expire) {
09352             /* We are/were sending a caller id spill.  Suppress any echo. */
09353             p->subs[idx].f.frametype = AST_FRAME_NULL;
09354             p->subs[idx].f.subclass.integer = 0;
09355             p->subs[idx].f.samples = 0;
09356             p->subs[idx].f.mallocd = 0;
09357             p->subs[idx].f.offset = 0;
09358             p->subs[idx].f.data.ptr = NULL;
09359             p->subs[idx].f.datalen= 0;
09360          }
09361          break;
09362       default:
09363          break;
09364       }
09365    }
09366 
09367    ast_mutex_unlock(&p->lock);
09368    return f;
09369 }
09370 
09371 static int my_dahdi_write(struct dahdi_pvt *p, unsigned char *buf, int len, int idx, int linear)
09372 {
09373    int sent=0;
09374    int size;
09375    int res;
09376    int fd;
09377    fd = p->subs[idx].dfd;
09378    while (len) {
09379       size = len;
09380       if (size > (linear ? READ_SIZE * 2 : READ_SIZE))
09381          size = (linear ? READ_SIZE * 2 : READ_SIZE);
09382       res = write(fd, buf, size);
09383       if (res != size) {
09384          ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
09385          return sent;
09386       }
09387       len -= size;
09388       buf += size;
09389    }
09390    return sent;
09391 }
09392 
09393 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame)
09394 {
09395    struct dahdi_pvt *p = ast->tech_pvt;
09396    int res;
09397    int idx;
09398    idx = dahdi_get_index(ast, p, 0);
09399    if (idx < 0) {
09400       ast_log(LOG_WARNING, "%s doesn't really exist?\n", ast->name);
09401       return -1;
09402    }
09403 
09404    /* Write a frame of (presumably voice) data */
09405    if (frame->frametype != AST_FRAME_VOICE) {
09406       if (frame->frametype != AST_FRAME_IMAGE)
09407          ast_log(LOG_WARNING, "Don't know what to do with frame type '%d'\n", frame->frametype);
09408       return 0;
09409    }
09410    if ((frame->subclass.codec != AST_FORMAT_SLINEAR) &&
09411       (frame->subclass.codec != AST_FORMAT_ULAW) &&
09412       (frame->subclass.codec != AST_FORMAT_ALAW)) {
09413       ast_log(LOG_WARNING, "Cannot handle frames in %s format\n", ast_getformatname(frame->subclass.codec));
09414       return -1;
09415    }
09416    if (p->dialing) {
09417       ast_debug(1, "Dropping frame since I'm still dialing on %s...\n",ast->name);
09418       return 0;
09419    }
09420    if (!p->owner) {
09421       ast_debug(1, "Dropping frame since there is no active owner on %s...\n",ast->name);
09422       return 0;
09423    }
09424    if (p->cidspill) {
09425       ast_debug(1, "Dropping frame since I've still got a callerid spill on %s...\n",
09426          ast->name);
09427       return 0;
09428    }
09429    /* Return if it's not valid data */
09430    if (!frame->data.ptr || !frame->datalen)
09431       return 0;
09432 
09433    if (frame->subclass.codec == AST_FORMAT_SLINEAR) {
09434       if (!p->subs[idx].linear) {
09435          p->subs[idx].linear = 1;
09436          res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09437          if (res)
09438             ast_log(LOG_WARNING, "Unable to set linear mode on channel %d\n", p->channel);
09439       }
09440       res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 1);
09441    } else {
09442       /* x-law already */
09443       if (p->subs[idx].linear) {
09444          p->subs[idx].linear = 0;
09445          res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09446          if (res)
09447             ast_log(LOG_WARNING, "Unable to set companded mode on channel %d\n", p->channel);
09448       }
09449       res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 0);
09450    }
09451    if (res < 0) {
09452       ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
09453       return -1;
09454    }
09455    return 0;
09456 }
09457 
09458 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen)
09459 {
09460    struct dahdi_pvt *p = chan->tech_pvt;
09461    int res=-1;
09462    int idx;
09463    int func = DAHDI_FLASH;
09464 
09465    ast_mutex_lock(&p->lock);
09466    ast_debug(1, "Requested indication %d on channel %s\n", condition, chan->name);
09467    switch (p->sig) {
09468 #if defined(HAVE_PRI)
09469    case SIG_PRI_LIB_HANDLE_CASES:
09470       res = sig_pri_indicate(p->sig_pvt, chan, condition, data, datalen);
09471       ast_mutex_unlock(&p->lock);
09472       return res;
09473 #endif   /* defined(HAVE_PRI) */
09474 #if defined(HAVE_SS7)
09475    case SIG_SS7:
09476       res = sig_ss7_indicate(p->sig_pvt, chan, condition, data, datalen);
09477       ast_mutex_unlock(&p->lock);
09478       return res;
09479 #endif   /* defined(HAVE_SS7) */
09480    default:
09481       break;
09482    }
09483 #ifdef HAVE_OPENR2
09484    if (p->mfcr2 && !p->mfcr2_call_accepted) {
09485       ast_mutex_unlock(&p->lock);
09486       /* if this is an R2 call and the call is not yet accepted, we don't want the
09487          tone indications to mess up with the MF tones */
09488       return 0;
09489    }
09490 #endif
09491    idx = dahdi_get_index(chan, p, 0);
09492    if (idx == SUB_REAL) {
09493       switch (condition) {
09494       case AST_CONTROL_BUSY:
09495          res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_BUSY);
09496          break;
09497       case AST_CONTROL_RINGING:
09498          res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_RINGTONE);
09499 
09500          if (chan->_state != AST_STATE_UP) {
09501             if ((chan->_state != AST_STATE_RING) ||
09502                ((p->sig != SIG_FXSKS) &&
09503              (p->sig != SIG_FXSLS) &&
09504              (p->sig != SIG_FXSGS)))
09505             ast_setstate(chan, AST_STATE_RINGING);
09506          }
09507          break;
09508       case AST_CONTROL_INCOMPLETE:
09509          ast_debug(1, "Received AST_CONTROL_INCOMPLETE on %s\n", chan->name);
09510          /* act as a progress or proceeding, allowing the caller to enter additional numbers */
09511          res = 0;
09512          break;
09513       case AST_CONTROL_PROCEEDING:
09514          ast_debug(1, "Received AST_CONTROL_PROCEEDING on %s\n", chan->name);
09515          /* don't continue in ast_indicate */
09516          res = 0;
09517          break;
09518       case AST_CONTROL_PROGRESS:
09519          ast_debug(1, "Received AST_CONTROL_PROGRESS on %s\n", chan->name);
09520          /* don't continue in ast_indicate */
09521          res = 0;
09522          break;
09523       case AST_CONTROL_CONGESTION:
09524          /* There are many cause codes that generate an AST_CONTROL_CONGESTION. */
09525          switch (chan->hangupcause) {
09526          case AST_CAUSE_USER_BUSY:
09527          case AST_CAUSE_NORMAL_CLEARING:
09528          case 0:/* Cause has not been set. */
09529             /* Supply a more appropriate cause. */
09530             chan->hangupcause = AST_CAUSE_CONGESTION;
09531             break;
09532          default:
09533             break;
09534          }
09535          break;
09536       case AST_CONTROL_HOLD:
09537          ast_moh_start(chan, data, p->mohinterpret);
09538          break;
09539       case AST_CONTROL_UNHOLD:
09540          ast_moh_stop(chan);
09541          break;
09542       case AST_CONTROL_RADIO_KEY:
09543          if (p->radio)
09544             res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
09545          res = 0;
09546          break;
09547       case AST_CONTROL_RADIO_UNKEY:
09548          if (p->radio)
09549             res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_RINGOFF);
09550          res = 0;
09551          break;
09552       case AST_CONTROL_FLASH:
09553          /* flash hookswitch */
09554          if (ISTRUNK(p) && (p->sig != SIG_PRI)) {
09555             /* Clear out the dial buffer */
09556             p->dop.dialstr[0] = '\0';
09557             if ((ioctl(p->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
09558                ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
09559                   chan->name, strerror(errno));
09560             } else
09561                res = 0;
09562          } else
09563             res = 0;
09564          break;
09565       case AST_CONTROL_SRCUPDATE:
09566          res = 0;
09567          break;
09568       case -1:
09569          res = tone_zone_play_tone(p->subs[idx].dfd, -1);
09570          break;
09571       }
09572    } else {
09573       res = 0;
09574    }
09575    ast_mutex_unlock(&p->lock);
09576    return res;
09577 }
09578 
09579 #if defined(HAVE_PRI)
09580 static struct ast_str *create_channel_name(struct dahdi_pvt *i, int is_outgoing, char *address)
09581 #else
09582 static struct ast_str *create_channel_name(struct dahdi_pvt *i)
09583 #endif   /* defined(HAVE_PRI) */
09584 {
09585    struct ast_str *chan_name;
09586    int x, y;
09587 
09588    /* Create the new channel name tail. */
09589    if (!(chan_name = ast_str_create(32))) {
09590       return NULL;
09591    }
09592    if (i->channel == CHAN_PSEUDO) {
09593       ast_str_set(&chan_name, 0, "pseudo-%ld", ast_random());
09594 #if defined(HAVE_PRI)
09595    } else if (i->pri) {
09596       ast_mutex_lock(&i->pri->lock);
09597       y = ++i->pri->new_chan_seq;
09598       if (is_outgoing) {
09599          ast_str_set(&chan_name, 0, "i%d/%s-%x", i->pri->span, address, y);
09600          address[0] = '\0';
09601       } else if (ast_strlen_zero(i->cid_subaddr)) {
09602          /* Put in caller-id number only since there is no subaddress. */
09603          ast_str_set(&chan_name, 0, "i%d/%s-%x", i->pri->span, i->cid_num, y);
09604       } else {
09605          /* Put in caller-id number and subaddress. */
09606          ast_str_set(&chan_name, 0, "i%d/%s:%s-%x", i->pri->span, i->cid_num,
09607             i->cid_subaddr, y);
09608       }
09609       ast_mutex_unlock(&i->pri->lock);
09610 #endif   /* defined(HAVE_PRI) */
09611    } else {
09612       y = 1;
09613       do {
09614          ast_str_set(&chan_name, 0, "%d-%d", i->channel, y);
09615          for (x = 0; x < 3; ++x) {
09616             if (i->subs[x].owner && !strcasecmp(ast_str_buffer(chan_name),
09617                i->subs[x].owner->name + 6)) {
09618                break;
09619             }
09620          }
09621          ++y;
09622       } while (x < 3);
09623    }
09624    return chan_name;
09625 }
09626 
09627 static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpbx, int idx, int law, const char *linkedid)
09628 {
09629    struct ast_channel *tmp;
09630    format_t deflaw;
09631    int x;
09632    int features;
09633    struct ast_str *chan_name;
09634    struct ast_variable *v;
09635    char *dashptr;
09636    char device_name[AST_CHANNEL_NAME];
09637 
09638    if (i->subs[idx].owner) {
09639       ast_log(LOG_WARNING, "Channel %d already has a %s call\n", i->channel,subnames[idx]);
09640       return NULL;
09641    }
09642 
09643 #if defined(HAVE_PRI)
09644    /*
09645     * The dnid has been stuffed with the called-number[:subaddress]
09646     * by dahdi_request() for outgoing calls.
09647     */
09648    chan_name = create_channel_name(i, i->outgoing, i->dnid);
09649 #else
09650    chan_name = create_channel_name(i);
09651 #endif   /* defined(HAVE_PRI) */
09652    if (!chan_name) {
09653       return NULL;
09654    }
09655 
09656    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));
09657    ast_free(chan_name);
09658    if (!tmp)
09659       return NULL;
09660    tmp->tech = &dahdi_tech;
09661 #if defined(HAVE_PRI)
09662    if (i->pri) {
09663       ast_cc_copy_config_params(i->cc_params, i->pri->cc_params);
09664    }
09665 #endif   /* defined(HAVE_PRI) */
09666    ast_channel_cc_params_init(tmp, i->cc_params);
09667    if (law) {
09668       i->law = law;
09669       if (law == DAHDI_LAW_ALAW) {
09670          deflaw = AST_FORMAT_ALAW;
09671       } else {
09672          deflaw = AST_FORMAT_ULAW;
09673       }
09674    } else {
09675       switch (i->sig) {
09676       case SIG_PRI_LIB_HANDLE_CASES:
09677          /* Make sure companding law is known. */
09678          i->law = (i->law_default == DAHDI_LAW_ALAW)
09679             ? DAHDI_LAW_ALAW : DAHDI_LAW_MULAW;
09680          break;
09681       default:
09682          i->law = i->law_default;
09683          break;
09684       }
09685       if (i->law_default == DAHDI_LAW_ALAW) {
09686          deflaw = AST_FORMAT_ALAW;
09687       } else {
09688          deflaw = AST_FORMAT_ULAW;
09689       }
09690    }
09691    ast_channel_set_fd(tmp, 0, i->subs[idx].dfd);
09692    tmp->nativeformats = deflaw;
09693    /* Start out assuming ulaw since it's smaller :) */
09694    tmp->rawreadformat = deflaw;
09695    tmp->readformat = deflaw;
09696    tmp->rawwriteformat = deflaw;
09697    tmp->writeformat = deflaw;
09698    i->subs[idx].linear = 0;
09699    dahdi_setlinear(i->subs[idx].dfd, i->subs[idx].linear);
09700    features = 0;
09701    if (idx == SUB_REAL) {
09702       if (i->busydetect && CANBUSYDETECT(i))
09703          features |= DSP_FEATURE_BUSY_DETECT;
09704       if ((i->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(i))
09705          features |= DSP_FEATURE_CALL_PROGRESS;
09706       if ((i->waitfordialtone) && CANPROGRESSDETECT(i))
09707          features |= DSP_FEATURE_WAITDIALTONE;
09708       if ((!i->outgoing && (i->callprogress & CALLPROGRESS_FAX_INCOMING)) ||
09709          (i->outgoing && (i->callprogress & CALLPROGRESS_FAX_OUTGOING))) {
09710          features |= DSP_FEATURE_FAX_DETECT;
09711       }
09712       x = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
09713       if (ioctl(i->subs[idx].dfd, DAHDI_TONEDETECT, &x)) {
09714          i->hardwaredtmf = 0;
09715          features |= DSP_FEATURE_DIGIT_DETECT;
09716       } else if (NEED_MFDETECT(i)) {
09717          i->hardwaredtmf = 1;
09718          features |= DSP_FEATURE_DIGIT_DETECT;
09719       }
09720    }
09721    if (features) {
09722       if (i->dsp) {
09723          ast_debug(1, "Already have a dsp on %s?\n", tmp->name);
09724       } else {
09725          if (i->channel != CHAN_PSEUDO)
09726             i->dsp = ast_dsp_new();
09727          else
09728             i->dsp = NULL;
09729          if (i->dsp) {
09730             i->dsp_features = features;
09731 #if defined(HAVE_PRI) || defined(HAVE_SS7)
09732             /* We cannot do progress detection until receive PROGRESS message */
09733             if (i->outgoing && (dahdi_sig_pri_lib_handles(i->sig) || (i->sig == SIG_SS7))) {
09734                /* Remember requested DSP features, don't treat
09735                   talking as ANSWER */
09736                i->dsp_features = features & ~DSP_PROGRESS_TALK;
09737                features = 0;
09738             }
09739 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
09740             ast_dsp_set_features(i->dsp, features);
09741             ast_dsp_set_digitmode(i->dsp, DSP_DIGITMODE_DTMF | i->dtmfrelax);
09742             if (!ast_strlen_zero(progzone))
09743                ast_dsp_set_call_progress_zone(i->dsp, progzone);
09744             if (i->busydetect && CANBUSYDETECT(i)) {
09745                ast_dsp_set_busy_count(i->dsp, i->busycount);
09746                ast_dsp_set_busy_pattern(i->dsp, i->busy_tonelength, i->busy_quietlength);
09747             }
09748          }
09749       }
09750    }
09751 
09752    if (state == AST_STATE_RING)
09753       tmp->rings = 1;
09754    tmp->tech_pvt = i;
09755    if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) {
09756       /* Only FXO signalled stuff can be picked up */
09757       tmp->callgroup = i->callgroup;
09758       tmp->pickupgroup = i->pickupgroup;
09759    }
09760    if (!ast_strlen_zero(i->parkinglot))
09761       ast_string_field_set(tmp, parkinglot, i->parkinglot);
09762    if (!ast_strlen_zero(i->language))
09763       ast_string_field_set(tmp, language, i->language);
09764    if (!i->owner)
09765       i->owner = tmp;
09766    if (!ast_strlen_zero(i->accountcode))
09767       ast_string_field_set(tmp, accountcode, i->accountcode);
09768    if (i->amaflags)
09769       tmp->amaflags = i->amaflags;
09770    i->subs[idx].owner = tmp;
09771    ast_copy_string(tmp->context, i->context, sizeof(tmp->context));
09772    if (!analog_lib_handles(i->sig, i->radio, i->oprmode)) {
09773       ast_string_field_set(tmp, call_forward, i->call_forward);
09774    }
09775    /* If we've been told "no ADSI" then enforce it */
09776    if (!i->adsi)
09777       tmp->adsicpe = AST_ADSI_UNAVAILABLE;
09778    if (!ast_strlen_zero(i->exten))
09779       ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten));
09780    if (!ast_strlen_zero(i->rdnis)) {
09781       tmp->redirecting.from.number.valid = 1;
09782       tmp->redirecting.from.number.str = ast_strdup(i->rdnis);
09783    }
09784    if (!ast_strlen_zero(i->dnid)) {
09785       tmp->dialed.number.str = ast_strdup(i->dnid);
09786    }
09787 
09788    /* Don't use ast_set_callerid() here because it will
09789     * generate a needless NewCallerID event */
09790 #if defined(HAVE_PRI) || defined(HAVE_SS7)
09791    if (!ast_strlen_zero(i->cid_ani)) {
09792       tmp->caller.ani.number.valid = 1;
09793       tmp->caller.ani.number.str = ast_strdup(i->cid_ani);
09794    } else if (!ast_strlen_zero(i->cid_num)) {
09795       tmp->caller.ani.number.valid = 1;
09796       tmp->caller.ani.number.str = ast_strdup(i->cid_num);
09797    }
09798 #else
09799    if (!ast_strlen_zero(i->cid_num)) {
09800       tmp->caller.ani.number.valid = 1;
09801       tmp->caller.ani.number.str = ast_strdup(i->cid_num);
09802    }
09803 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
09804    tmp->caller.id.name.presentation = i->callingpres;
09805    tmp->caller.id.number.presentation = i->callingpres;
09806    tmp->caller.id.number.plan = i->cid_ton;
09807    tmp->caller.ani2 = i->cid_ani2;
09808    tmp->caller.id.tag = ast_strdup(i->cid_tag);
09809    /* clear the fake event in case we posted one before we had ast_channel */
09810    i->fake_event = 0;
09811    /* Assure there is no confmute on this channel */
09812    dahdi_confmute(i, 0);
09813    i->muting = 0;
09814    /* Configure the new channel jb */
09815    ast_jb_configure(tmp, &global_jbconf);
09816 
09817    /* Set initial device state */
09818    ast_copy_string(device_name, tmp->name, sizeof(device_name));
09819    dashptr = strrchr(device_name, '-');
09820    if (dashptr) {
09821       *dashptr = '\0';
09822    }
09823    tmp->flags |= AST_FLAG_DISABLE_DEVSTATE_CACHE;
09824    ast_devstate_changed_literal(AST_DEVICE_UNKNOWN, AST_DEVSTATE_NOT_CACHABLE, device_name);
09825 
09826    for (v = i->vars ; v ; v = v->next)
09827       pbx_builtin_setvar_helper(tmp, v->name, v->value);
09828 
09829    ast_module_ref(ast_module_info->self);
09830 
09831    dahdi_ami_channel_event(i, tmp);
09832    if (startpbx) {
09833 #ifdef HAVE_OPENR2
09834       if (i->mfcr2call) {
09835          pbx_builtin_setvar_helper(tmp, "MFCR2_CATEGORY", openr2_proto_get_category_string(i->mfcr2_recvd_category));
09836       }
09837 #endif
09838       if (ast_pbx_start(tmp)) {
09839          ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
09840          ast_hangup(tmp);
09841          return NULL;
09842       }
09843    }
09844    return tmp;
09845 }
09846 
09847 
09848 static int my_getsigstr(struct ast_channel *chan, char *str, const char *term, int ms)
09849 {
09850    char c;
09851 
09852    *str = 0; /* start with empty output buffer */
09853    for (;;)
09854    {
09855       /* Wait for the first digit (up to specified ms). */
09856       c = ast_waitfordigit(chan, ms);
09857       /* if timeout, hangup or error, return as such */
09858       if (c < 1)
09859          return c;
09860       *str++ = c;
09861       *str = 0;
09862       if (strchr(term, c))
09863          return 1;
09864    }
09865 }
09866 
09867 static int dahdi_wink(struct dahdi_pvt *p, int idx)
09868 {
09869    int j;
09870    dahdi_set_hook(p->subs[idx].dfd, DAHDI_WINK);
09871    for (;;)
09872    {
09873       /* set bits of interest */
09874       j = DAHDI_IOMUX_SIGEVENT;
09875       /* wait for some happening */
09876       if (ioctl(p->subs[idx].dfd,DAHDI_IOMUX,&j) == -1) return(-1);
09877       /* exit loop if we have it */
09878       if (j & DAHDI_IOMUX_SIGEVENT) break;
09879    }
09880    /* get the event info */
09881    if (ioctl(p->subs[idx].dfd,DAHDI_GETEVENT,&j) == -1) return(-1);
09882    return 0;
09883 }
09884 
09885 /*! \brief enable or disable the chan_dahdi Do-Not-Disturb mode for a DAHDI channel
09886  * \param dahdichan "Physical" DAHDI channel (e.g: DAHDI/5)
09887  * \param flag on 1 to enable, 0 to disable, -1 return dnd value
09888  *
09889  * chan_dahdi has a DND (Do Not Disturb) mode for each dahdichan (physical
09890  * DAHDI channel). Use this to enable or disable it.
09891  *
09892  * \bug the use of the word "channel" for those dahdichans is really confusing.
09893  */
09894 static int dahdi_dnd(struct dahdi_pvt *dahdichan, int flag)
09895 {
09896    if (analog_lib_handles(dahdichan->sig, dahdichan->radio, dahdichan->oprmode)) {
09897       return analog_dnd(dahdichan->sig_pvt, flag);
09898    }
09899 
09900    if (flag == -1) {
09901       return dahdichan->dnd;
09902    }
09903 
09904    /* Do not disturb */
09905    dahdichan->dnd = flag;
09906    ast_verb(3, "%s DND on channel %d\n",
09907          flag? "Enabled" : "Disabled",
09908          dahdichan->channel);
09909    manager_event(EVENT_FLAG_SYSTEM, "DNDState",
09910          "Channel: DAHDI/%d\r\n"
09911          "Status: %s\r\n", dahdichan->channel,
09912          flag? "enabled" : "disabled");
09913 
09914    return 0;
09915 }
09916 
09917 static int canmatch_featurecode(const char *exten)
09918 {
09919    int extlen = strlen(exten);
09920    const char *pickup_ext;
09921    if (!extlen) {
09922       return 1;
09923    }
09924    pickup_ext = ast_pickup_ext();
09925    if (extlen < strlen(pickup_ext) && !strncmp(pickup_ext, exten, extlen)) {
09926       return 1;
09927    }
09928    /* hardcoded features are *60, *67, *69, *70, *72, *73, *78, *79, *82, *0 */
09929    if (exten[0] == '*' && extlen < 3) {
09930       if (extlen == 1) {
09931          return 1;
09932       }
09933       /* "*0" should be processed before it gets here */
09934       switch (exten[1]) {
09935       case '6':
09936       case '7':
09937       case '8':
09938          return 1;
09939       }
09940    }
09941    return 0;
09942 }
09943 
09944 static void *analog_ss_thread(void *data)
09945 {
09946    struct ast_channel *chan = data;
09947    struct dahdi_pvt *p = chan->tech_pvt;
09948    char exten[AST_MAX_EXTENSION] = "";
09949    char exten2[AST_MAX_EXTENSION] = "";
09950    unsigned char buf[256];
09951    char dtmfcid[300];
09952    char dtmfbuf[300];
09953    struct callerid_state *cs = NULL;
09954    char *name = NULL, *number = NULL;
09955    int distMatches;
09956    int curRingData[3];
09957    int receivedRingT;
09958    int counter1;
09959    int counter;
09960    int samples = 0;
09961    struct ast_smdi_md_message *smdi_msg = NULL;
09962    int flags = 0;
09963    int i;
09964    int timeout;
09965    int getforward = 0;
09966    char *s1, *s2;
09967    int len = 0;
09968    int res;
09969    int idx;
09970 
09971    ast_mutex_lock(&ss_thread_lock);
09972    ss_thread_count++;
09973    ast_mutex_unlock(&ss_thread_lock);
09974    /* in the bizarre case where the channel has become a zombie before we
09975       even get started here, abort safely
09976    */
09977    if (!p) {
09978       ast_log(LOG_WARNING, "Channel became a zombie before simple switch could be started (%s)\n", chan->name);
09979       ast_hangup(chan);
09980       goto quit;
09981    }
09982    ast_verb(3, "Starting simple switch on '%s'\n", chan->name);
09983    idx = dahdi_get_index(chan, p, 1);
09984    if (idx < 0) {
09985       ast_log(LOG_WARNING, "Huh?\n");
09986       ast_hangup(chan);
09987       goto quit;
09988    }
09989    if (p->dsp)
09990       ast_dsp_digitreset(p->dsp);
09991    switch (p->sig) {
09992    case SIG_FEATD:
09993    case SIG_FEATDMF:
09994    case SIG_FEATDMF_TA:
09995    case SIG_E911:
09996    case SIG_FGC_CAMAMF:
09997    case SIG_FEATB:
09998    case SIG_EMWINK:
09999    case SIG_SF_FEATD:
10000    case SIG_SF_FEATDMF:
10001    case SIG_SF_FEATB:
10002    case SIG_SFWINK:
10003       if (dahdi_wink(p, idx))
10004          goto quit;
10005       /* Fall through */
10006    case SIG_EM:
10007    case SIG_EM_E1:
10008    case SIG_SF:
10009    case SIG_FGC_CAMA:
10010       res = tone_zone_play_tone(p->subs[idx].dfd, -1);
10011       if (p->dsp)
10012          ast_dsp_digitreset(p->dsp);
10013       /* set digit mode appropriately */
10014       if (p->dsp) {
10015          if (NEED_MFDETECT(p))
10016             ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
10017          else
10018             ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
10019       }
10020       memset(dtmfbuf, 0, sizeof(dtmfbuf));
10021       /* Wait for the first digit only if immediate=no */
10022       if (!p->immediate)
10023          /* Wait for the first digit (up to 5 seconds). */
10024          res = ast_waitfordigit(chan, 5000);
10025       else
10026          res = 0;
10027       if (res > 0) {
10028          /* save first char */
10029          dtmfbuf[0] = res;
10030          switch (p->sig) {
10031          case SIG_FEATD:
10032          case SIG_SF_FEATD:
10033             res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
10034             if (res > 0)
10035                res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
10036             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
10037             break;
10038          case SIG_FEATDMF_TA:
10039             res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
10040             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
10041             if (dahdi_wink(p, idx)) goto quit;
10042             dtmfbuf[0] = 0;
10043             /* Wait for the first digit (up to 5 seconds). */
10044             res = ast_waitfordigit(chan, 5000);
10045             if (res <= 0) break;
10046             dtmfbuf[0] = res;
10047             /* fall through intentionally */
10048          case SIG_FEATDMF:
10049          case SIG_E911:
10050          case SIG_FGC_CAMAMF:
10051          case SIG_SF_FEATDMF:
10052             res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
10053             /* if international caca, do it again to get real ANO */
10054             if ((p->sig == SIG_FEATDMF) && (dtmfbuf[1] != '0') && (strlen(dtmfbuf) != 14))
10055             {
10056                if (dahdi_wink(p, idx)) goto quit;
10057                dtmfbuf[0] = 0;
10058                /* Wait for the first digit (up to 5 seconds). */
10059                res = ast_waitfordigit(chan, 5000);
10060                if (res <= 0) break;
10061                dtmfbuf[0] = res;
10062                res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
10063             }
10064             if (res > 0) {
10065                /* if E911, take off hook */
10066                if (p->sig == SIG_E911)
10067                   dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
10068                res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "#", 3000);
10069             }
10070             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
10071             break;
10072          case SIG_FEATB:
10073          case SIG_SF_FEATB:
10074             res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
10075             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
10076             break;
10077          case SIG_EMWINK:
10078             /* if we received a '*', we are actually receiving Feature Group D
10079                dial syntax, so use that mode; otherwise, fall through to normal
10080                mode
10081             */
10082             if (res == '*') {
10083                res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
10084                if (res > 0)
10085                   res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
10086                if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
10087                break;
10088             }
10089          default:
10090             /* If we got the first digit, get the rest */
10091             len = 1;
10092             dtmfbuf[len] = '\0';
10093             while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
10094                if (ast_exists_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
10095                   timeout = matchdigittimeout;
10096                } else {
10097                   timeout = gendigittimeout;
10098                }
10099                res = ast_waitfordigit(chan, timeout);
10100                if (res < 0) {
10101                   ast_debug(1, "waitfordigit returned < 0...\n");
10102                   ast_hangup(chan);
10103                   goto quit;
10104                } else if (res) {
10105                   dtmfbuf[len++] = res;
10106                   dtmfbuf[len] = '\0';
10107                } else {
10108                   break;
10109                }
10110             }
10111             break;
10112          }
10113       }
10114       if (res == -1) {
10115          ast_log(LOG_WARNING, "getdtmf on channel %d: %s\n", p->channel, strerror(errno));
10116          ast_hangup(chan);
10117          goto quit;
10118       } else if (res < 0) {
10119          ast_debug(1, "Got hung up before digits finished\n");
10120          ast_hangup(chan);
10121          goto quit;
10122       }
10123 
10124       if (p->sig == SIG_FGC_CAMA) {
10125          char anibuf[100];
10126 
10127          if (ast_safe_sleep(chan,1000) == -1) {
10128             ast_hangup(chan);
10129             goto quit;
10130          }
10131          dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
10132          ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
10133          res = my_getsigstr(chan, anibuf, "#", 10000);
10134          if ((res > 0) && (strlen(anibuf) > 2)) {
10135             if (anibuf[strlen(anibuf) - 1] == '#')
10136                anibuf[strlen(anibuf) - 1] = 0;
10137             ast_set_callerid(chan, anibuf + 2, NULL, anibuf + 2);
10138          }
10139          ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
10140       }
10141 
10142       ast_copy_string(exten, dtmfbuf, sizeof(exten));
10143       if (ast_strlen_zero(exten))
10144          ast_copy_string(exten, "s", sizeof(exten));
10145       if (p->sig == SIG_FEATD || p->sig == SIG_EMWINK) {
10146          /* Look for Feature Group D on all E&M Wink and Feature Group D trunks */
10147          if (exten[0] == '*') {
10148             char *stringp=NULL;
10149             ast_copy_string(exten2, exten, sizeof(exten2));
10150             /* Parse out extension and callerid */
10151             stringp=exten2 +1;
10152             s1 = strsep(&stringp, "*");
10153             s2 = strsep(&stringp, "*");
10154             if (s2) {
10155                if (!ast_strlen_zero(p->cid_num))
10156                   ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
10157                else
10158                   ast_set_callerid(chan, s1, NULL, s1);
10159                ast_copy_string(exten, s2, sizeof(exten));
10160             } else
10161                ast_copy_string(exten, s1, sizeof(exten));
10162          } else if (p->sig == SIG_FEATD)
10163             ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d.  Assuming E&M Wink instead\n", p->channel);
10164       }
10165       if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
10166          if (exten[0] == '*') {
10167             char *stringp=NULL;
10168             ast_copy_string(exten2, exten, sizeof(exten2));
10169             /* Parse out extension and callerid */
10170             stringp=exten2 +1;
10171             s1 = strsep(&stringp, "#");
10172             s2 = strsep(&stringp, "#");
10173             if (s2) {
10174                if (!ast_strlen_zero(p->cid_num))
10175                   ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
10176                else
10177                   if (*(s1 + 2))
10178                      ast_set_callerid(chan, s1 + 2, NULL, s1 + 2);
10179                ast_copy_string(exten, s2 + 1, sizeof(exten));
10180             } else
10181                ast_copy_string(exten, s1 + 2, sizeof(exten));
10182          } else
10183             ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d.  Assuming E&M Wink instead\n", p->channel);
10184       }
10185       if ((p->sig == SIG_E911) || (p->sig == SIG_FGC_CAMAMF)) {
10186          if (exten[0] == '*') {
10187             char *stringp=NULL;
10188             ast_copy_string(exten2, exten, sizeof(exten2));
10189             /* Parse out extension and callerid */
10190             stringp=exten2 +1;
10191             s1 = strsep(&stringp, "#");
10192             s2 = strsep(&stringp, "#");
10193             if (s2 && (*(s2 + 1) == '0')) {
10194                if (*(s2 + 2))
10195                   ast_set_callerid(chan, s2 + 2, NULL, s2 + 2);
10196             }
10197             if (s1)  ast_copy_string(exten, s1, sizeof(exten));
10198             else ast_copy_string(exten, "911", sizeof(exten));
10199          } else
10200             ast_log(LOG_WARNING, "Got a non-E911/FGC CAMA input on channel %d.  Assuming E&M Wink instead\n", p->channel);
10201       }
10202       if (p->sig == SIG_FEATB) {
10203          if (exten[0] == '*') {
10204             char *stringp=NULL;
10205             ast_copy_string(exten2, exten, sizeof(exten2));
10206             /* Parse out extension and callerid */
10207             stringp=exten2 +1;
10208             s1 = strsep(&stringp, "#");
10209             ast_copy_string(exten, exten2 + 1, sizeof(exten));
10210          } else
10211             ast_log(LOG_WARNING, "Got a non-Feature Group B input on channel %d.  Assuming E&M Wink instead\n", p->channel);
10212       }
10213       if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
10214          dahdi_wink(p, idx);
10215          /* some switches require a minimum guard time between
10216             the last FGD wink and something that answers
10217             immediately. This ensures it */
10218          if (ast_safe_sleep(chan, 100)) {
10219             ast_hangup(chan);
10220             goto quit;
10221          }
10222       }
10223       dahdi_enable_ec(p);
10224       if (NEED_MFDETECT(p)) {
10225          if (p->dsp) {
10226             if (!p->hardwaredtmf)
10227                ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
10228             else {
10229                ast_dsp_free(p->dsp);
10230                p->dsp = NULL;
10231             }
10232          }
10233       }
10234 
10235       if (ast_exists_extension(chan, chan->context, exten, 1,
10236          S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
10237          ast_copy_string(chan->exten, exten, sizeof(chan->exten));
10238          if (p->dsp) ast_dsp_digitreset(p->dsp);
10239          res = ast_pbx_run(chan);
10240          if (res) {
10241             ast_log(LOG_WARNING, "PBX exited non-zero\n");
10242             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10243          }
10244          goto quit;
10245       } else {
10246          ast_verb(2, "Unknown extension '%s' in context '%s' requested\n", exten, chan->context);
10247          sleep(2);
10248          res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_INFO);
10249          if (res < 0)
10250             ast_log(LOG_WARNING, "Unable to start special tone on %d\n", p->channel);
10251          else
10252             sleep(1);
10253          res = ast_streamfile(chan, "ss-noservice", chan->language);
10254          if (res >= 0)
10255             ast_waitstream(chan, "");
10256          res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10257          ast_hangup(chan);
10258          goto quit;
10259       }
10260       break;
10261    case SIG_FXOLS:
10262    case SIG_FXOGS:
10263    case SIG_FXOKS:
10264       /* Read the first digit */
10265       timeout = firstdigittimeout;
10266       /* If starting a threeway call, never timeout on the first digit so someone
10267          can use flash-hook as a "hold" feature */
10268       if (p->subs[SUB_THREEWAY].owner)
10269          timeout = 999999;
10270       while (len < AST_MAX_EXTENSION-1) {
10271          /* Read digit unless it's supposed to be immediate, in which case the
10272             only answer is 's' */
10273          if (p->immediate)
10274             res = 's';
10275          else
10276             res = ast_waitfordigit(chan, timeout);
10277          timeout = 0;
10278          if (res < 0) {
10279             ast_debug(1, "waitfordigit returned < 0...\n");
10280             res = tone_zone_play_tone(p->subs[idx].dfd, -1);
10281             ast_hangup(chan);
10282             goto quit;
10283          } else if (res) {
10284             ast_debug(1,"waitfordigit returned '%c' (%d), timeout = %d\n", res, res, timeout);
10285             exten[len++]=res;
10286             exten[len] = '\0';
10287          }
10288          if (!ast_ignore_pattern(chan->context, exten))
10289             tone_zone_play_tone(p->subs[idx].dfd, -1);
10290          else
10291             tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
10292          if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num) && !ast_parking_ext_valid(exten, chan, chan->context)) {
10293             if (!res || !ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
10294                if (getforward) {
10295                   /* Record this as the forwarding extension */
10296                   ast_copy_string(p->call_forward, exten, sizeof(p->call_forward));
10297                   ast_verb(3, "Setting call forward to '%s' on channel %d\n", p->call_forward, p->channel);
10298                   res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10299                   if (res)
10300                      break;
10301                   usleep(500000);
10302                   res = tone_zone_play_tone(p->subs[idx].dfd, -1);
10303                   sleep(1);
10304                   memset(exten, 0, sizeof(exten));
10305                   res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
10306                   len = 0;
10307                   getforward = 0;
10308                } else {
10309                   res = tone_zone_play_tone(p->subs[idx].dfd, -1);
10310                   ast_copy_string(chan->exten, exten, sizeof(chan->exten));
10311                   if (!ast_strlen_zero(p->cid_num)) {
10312                      if (!p->hidecallerid)
10313                         ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
10314                      else
10315                         ast_set_callerid(chan, NULL, NULL, p->cid_num);
10316                   }
10317                   if (!ast_strlen_zero(p->cid_name)) {
10318                      if (!p->hidecallerid)
10319                         ast_set_callerid(chan, NULL, p->cid_name, NULL);
10320                   }
10321                   ast_setstate(chan, AST_STATE_RING);
10322                   dahdi_enable_ec(p);
10323                   res = ast_pbx_run(chan);
10324                   if (res) {
10325                      ast_log(LOG_WARNING, "PBX exited non-zero\n");
10326                      res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10327                   }
10328                   goto quit;
10329                }
10330             } else {
10331                /* It's a match, but they just typed a digit, and there is an ambiguous match,
10332                   so just set the timeout to matchdigittimeout and wait some more */
10333                timeout = matchdigittimeout;
10334             }
10335          } else if (res == 0) {
10336             ast_debug(1, "not enough digits (and no ambiguous match)...\n");
10337             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10338             dahdi_wait_event(p->subs[idx].dfd);
10339             ast_hangup(chan);
10340             goto quit;
10341          } else if (p->callwaiting && !strcmp(exten, "*70")) {
10342             ast_verb(3, "Disabling call waiting on %s\n", chan->name);
10343             /* Disable call waiting if enabled */
10344             p->callwaiting = 0;
10345             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10346             if (res) {
10347                ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
10348                   chan->name, strerror(errno));
10349             }
10350             len = 0;
10351             ioctl(p->subs[idx].dfd,DAHDI_CONFDIAG,&len);
10352             memset(exten, 0, sizeof(exten));
10353             timeout = firstdigittimeout;
10354 
10355          } else if (!strcmp(exten,ast_pickup_ext())) {
10356             /* Scan all channels and see if there are any
10357              * ringing channels that have call groups
10358              * that equal this channels pickup group
10359              */
10360             if (idx == SUB_REAL) {
10361                /* Switch us from Third call to Call Wait */
10362                if (p->subs[SUB_THREEWAY].owner) {
10363                   /* If you make a threeway call and the *8# a call, it should actually
10364                      look like a callwait */
10365                   alloc_sub(p, SUB_CALLWAIT);
10366                   swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
10367                   unalloc_sub(p, SUB_THREEWAY);
10368                }
10369                dahdi_enable_ec(p);
10370                if (ast_pickup_call(chan)) {
10371                   ast_debug(1, "No call pickup possible...\n");
10372                   res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10373                   dahdi_wait_event(p->subs[idx].dfd);
10374                }
10375                ast_hangup(chan);
10376                goto quit;
10377             } else {
10378                ast_log(LOG_WARNING, "Huh?  Got *8# on call not on real\n");
10379                ast_hangup(chan);
10380                goto quit;
10381             }
10382 
10383          } else if (!p->hidecallerid && !strcmp(exten, "*67")) {
10384             ast_verb(3, "Disabling Caller*ID on %s\n", chan->name);
10385             /* Disable Caller*ID if enabled */
10386             p->hidecallerid = 1;
10387             ast_party_number_free(&chan->caller.id.number);
10388             ast_party_number_init(&chan->caller.id.number);
10389             ast_party_name_free(&chan->caller.id.name);
10390             ast_party_name_init(&chan->caller.id.name);
10391             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10392             if (res) {
10393                ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
10394                   chan->name, strerror(errno));
10395             }
10396             len = 0;
10397             memset(exten, 0, sizeof(exten));
10398             timeout = firstdigittimeout;
10399          } else if (p->callreturn && !strcmp(exten, "*69")) {
10400             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10401             break;
10402          } else if (!strcmp(exten, "*78")) {
10403             dahdi_dnd(p, 1);
10404             /* Do not disturb */
10405             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10406             getforward = 0;
10407             memset(exten, 0, sizeof(exten));
10408             len = 0;
10409          } else if (!strcmp(exten, "*79")) {
10410             dahdi_dnd(p, 0);
10411             /* Do not disturb */
10412             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10413             getforward = 0;
10414             memset(exten, 0, sizeof(exten));
10415             len = 0;
10416          } else if (p->cancallforward && !strcmp(exten, "*72")) {
10417             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10418             getforward = 1;
10419             memset(exten, 0, sizeof(exten));
10420             len = 0;
10421          } else if (p->cancallforward && !strcmp(exten, "*73")) {
10422             ast_verb(3, "Cancelling call forwarding on channel %d\n", p->channel);
10423             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10424             memset(p->call_forward, 0, sizeof(p->call_forward));
10425             getforward = 0;
10426             memset(exten, 0, sizeof(exten));
10427             len = 0;
10428          } else if ((p->transfer || p->canpark) && ast_parking_ext_valid(exten, chan, chan->context) &&
10429                   p->subs[SUB_THREEWAY].owner &&
10430                   ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
10431             /* This is a three way call, the main call being a real channel,
10432                and we're parking the first call. */
10433             ast_masq_park_call_exten(ast_bridged_channel(p->subs[SUB_THREEWAY].owner),
10434                chan, exten, chan->context, 0, NULL);
10435             ast_verb(3, "Parking call to '%s'\n", chan->name);
10436             break;
10437          } else if (p->hidecallerid && !strcmp(exten, "*82")) {
10438             ast_verb(3, "Enabling Caller*ID on %s\n", chan->name);
10439             /* Enable Caller*ID if enabled */
10440             p->hidecallerid = 0;
10441             ast_set_callerid(chan, p->cid_num, p->cid_name, NULL);
10442             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10443             if (res) {
10444                ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
10445                   chan->name, strerror(errno));
10446             }
10447             len = 0;
10448             memset(exten, 0, sizeof(exten));
10449             timeout = firstdigittimeout;
10450          } else if (!strcmp(exten, "*0")) {
10451             struct ast_channel *nbridge =
10452                p->subs[SUB_THREEWAY].owner;
10453             struct dahdi_pvt *pbridge = NULL;
10454             /* set up the private struct of the bridged one, if any */
10455             if (nbridge && ast_bridged_channel(nbridge))
10456                pbridge = ast_bridged_channel(nbridge)->tech_pvt;
10457             if (nbridge && pbridge &&
10458                (nbridge->tech == &dahdi_tech) &&
10459                (ast_bridged_channel(nbridge)->tech == &dahdi_tech) &&
10460                ISTRUNK(pbridge)) {
10461                int func = DAHDI_FLASH;
10462                /* Clear out the dial buffer */
10463                p->dop.dialstr[0] = '\0';
10464                /* flash hookswitch */
10465                if ((ioctl(pbridge->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
10466                   ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
10467                      nbridge->name, strerror(errno));
10468                }
10469                swap_subs(p, SUB_REAL, SUB_THREEWAY);
10470                unalloc_sub(p, SUB_THREEWAY);
10471                p->owner = p->subs[SUB_REAL].owner;
10472                if (ast_bridged_channel(p->subs[SUB_REAL].owner))
10473                   ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
10474                ast_hangup(chan);
10475                goto quit;
10476             } else {
10477                tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10478                dahdi_wait_event(p->subs[idx].dfd);
10479                tone_zone_play_tone(p->subs[idx].dfd, -1);
10480                swap_subs(p, SUB_REAL, SUB_THREEWAY);
10481                unalloc_sub(p, SUB_THREEWAY);
10482                p->owner = p->subs[SUB_REAL].owner;
10483                ast_hangup(chan);
10484                goto quit;
10485             }
10486          } else if (!ast_canmatch_extension(chan, chan->context, exten, 1,
10487             S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))
10488             && !canmatch_featurecode(exten)) {
10489             ast_debug(1, "Can't match %s from '%s' in context %s\n", exten,
10490                S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, "<Unknown Caller>"),
10491                chan->context);
10492             break;
10493          }
10494          if (!timeout)
10495             timeout = gendigittimeout;
10496          if (len && !ast_ignore_pattern(chan->context, exten))
10497             tone_zone_play_tone(p->subs[idx].dfd, -1);
10498       }
10499       break;
10500    case SIG_FXSLS:
10501    case SIG_FXSGS:
10502    case SIG_FXSKS:
10503       /* check for SMDI messages */
10504       if (p->use_smdi && p->smdi_iface) {
10505          smdi_msg = ast_smdi_md_message_wait(p->smdi_iface, SMDI_MD_WAIT_TIMEOUT);
10506 
10507          if (smdi_msg != NULL) {
10508             ast_copy_string(chan->exten, smdi_msg->fwd_st, sizeof(chan->exten));
10509 
10510             if (smdi_msg->type == 'B')
10511                pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "b");
10512             else if (smdi_msg->type == 'N')
10513                pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "u");
10514 
10515             ast_debug(1, "Received SMDI message on %s\n", chan->name);
10516          } else {
10517             ast_log(LOG_WARNING, "SMDI enabled but no SMDI message present\n");
10518          }
10519       }
10520 
10521       if (p->use_callerid && (p->cid_signalling == CID_SIG_SMDI && smdi_msg)) {
10522          number = smdi_msg->calling_st;
10523 
10524       /* If we want caller id, we're in a prering state due to a polarity reversal
10525        * and we're set to use a polarity reversal to trigger the start of caller id,
10526        * grab the caller id and wait for ringing to start... */
10527       } else if (p->use_callerid && (chan->_state == AST_STATE_PRERING &&
10528                    (p->cid_start == CID_START_POLARITY || p->cid_start == CID_START_POLARITY_IN || p->cid_start == CID_START_DTMF_NOALERT))) {
10529          /* If set to use DTMF CID signalling, listen for DTMF */
10530          if (p->cid_signalling == CID_SIG_DTMF) {
10531             int k = 0;
10532             int off_ms;
10533             struct timeval start = ast_tvnow();
10534             int ms;
10535             cs = NULL;
10536             ast_debug(1, "Receiving DTMF cid on channel %s\n", chan->name);
10537             dahdi_setlinear(p->subs[idx].dfd, 0);
10538             /*
10539              * We are the only party interested in the Rx stream since
10540              * we have not answered yet.  We don't need or even want DTMF
10541              * emulation.  The DTMF digits can come so fast that emulation
10542              * can drop some of them.
10543              */
10544             ast_set_flag(chan, AST_FLAG_END_DTMF_ONLY);
10545             off_ms = 4000;/* This is a typical OFF time between rings. */
10546             for (;;) {
10547                struct ast_frame *f;
10548 
10549                ms = ast_remaining_ms(start, off_ms);
10550                res = ast_waitfor(chan, ms);
10551                if (res <= 0) {
10552                   /*
10553                    * We do not need to restore the dahdi_setlinear()
10554                    * or AST_FLAG_END_DTMF_ONLY flag settings since we
10555                    * are hanging up the channel.
10556                    */
10557                   ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
10558                      "Exiting simple switch\n");
10559                   ast_hangup(chan);
10560                   goto quit;
10561                }
10562                f = ast_read(chan);
10563                if (!f)
10564                   break;
10565                if (f->frametype == AST_FRAME_DTMF) {
10566                   if (k < ARRAY_LEN(dtmfbuf) - 1) {
10567                      dtmfbuf[k++] = f->subclass.integer;
10568                   }
10569                   ast_debug(1, "CID got digit '%c'\n", f->subclass.integer);
10570                   start = ast_tvnow();
10571                }
10572                ast_frfree(f);
10573                if (chan->_state == AST_STATE_RING ||
10574                   chan->_state == AST_STATE_RINGING)
10575                   break; /* Got ring */
10576             }
10577             ast_clear_flag(chan, AST_FLAG_END_DTMF_ONLY);
10578             dtmfbuf[k] = '\0';
10579             dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10580             /* Got cid and ring. */
10581             ast_debug(1, "CID got string '%s'\n", dtmfbuf);
10582             callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
10583             ast_debug(1, "CID is '%s', flags %d\n", dtmfcid, flags);
10584             /* If first byte is NULL, we have no cid */
10585             if (!ast_strlen_zero(dtmfcid))
10586                number = dtmfcid;
10587             else
10588                number = NULL;
10589          /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */
10590          } else if ((p->cid_signalling == CID_SIG_V23) || (p->cid_signalling == CID_SIG_V23_JP)) {
10591             cs = callerid_new(p->cid_signalling);
10592             if (cs) {
10593                int off_ms;
10594                struct timeval start;
10595                int ms;
10596                samples = 0;
10597 #if 1
10598                bump_gains(p);
10599 #endif
10600                /* Take out of linear mode for Caller*ID processing */
10601                dahdi_setlinear(p->subs[idx].dfd, 0);
10602 
10603                /* First we wait and listen for the Caller*ID */
10604                for (;;) {
10605                   i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10606                   if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10607                      ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10608                      callerid_free(cs);
10609                      ast_hangup(chan);
10610                      goto quit;
10611                   }
10612                   if (i & DAHDI_IOMUX_SIGEVENT) {
10613                      res = dahdi_get_event(p->subs[idx].dfd);
10614                      ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10615                      if (res == DAHDI_EVENT_NOALARM) {
10616                         p->inalarm = 0;
10617                      }
10618 
10619                      if (p->cid_signalling == CID_SIG_V23_JP) {
10620                         if (res == DAHDI_EVENT_RINGBEGIN) {
10621                            res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
10622                            usleep(1);
10623                         }
10624                      } else {
10625                         res = 0;
10626                         break;
10627                      }
10628                   } else if (i & DAHDI_IOMUX_READ) {
10629                      res = read(p->subs[idx].dfd, buf, sizeof(buf));
10630                      if (res < 0) {
10631                         if (errno != ELAST) {
10632                            ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10633                            callerid_free(cs);
10634                            ast_hangup(chan);
10635                            goto quit;
10636                         }
10637                         break;
10638                      }
10639                      samples += res;
10640 
10641                      if (p->cid_signalling == CID_SIG_V23_JP) {
10642                         res = callerid_feed_jp(cs, buf, res, AST_LAW(p));
10643                      } else {
10644                         res = callerid_feed(cs, buf, res, AST_LAW(p));
10645                      }
10646                      if (res < 0) {
10647                         /*
10648                          * The previous diagnostic message output likely
10649                          * explains why it failed.
10650                          */
10651                         ast_log(LOG_WARNING,
10652                            "Failed to decode CallerID on channel '%s'\n",
10653                            chan->name);
10654                         break;
10655                      } else if (res)
10656                         break;
10657                      else if (samples > (8000 * 10))
10658                         break;
10659                   }
10660                }
10661                if (res == 1) {
10662                   callerid_get(cs, &name, &number, &flags);
10663                   ast_log(LOG_NOTICE, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
10664                }
10665 
10666                if (p->cid_signalling == CID_SIG_V23_JP) {
10667                   res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
10668                   usleep(1);
10669                }
10670 
10671                /* Finished with Caller*ID, now wait for a ring to make sure there really is a call coming */
10672                start = ast_tvnow();
10673                off_ms = 4000;/* This is a typical OFF time between rings. */
10674                for (;;) {
10675                   struct ast_frame *f;
10676 
10677                   ms = ast_remaining_ms(start, off_ms);
10678                   res = ast_waitfor(chan, ms);
10679                   if (res <= 0) {
10680                      ast_log(LOG_WARNING, "CID timed out waiting for ring. "
10681                         "Exiting simple switch\n");
10682                      ast_hangup(chan);
10683                      goto quit;
10684                   }
10685                   if (!(f = ast_read(chan))) {
10686                      ast_log(LOG_WARNING, "Hangup received waiting for ring. Exiting simple switch\n");
10687                      ast_hangup(chan);
10688                      goto quit;
10689                   }
10690                   ast_frfree(f);
10691                   if (chan->_state == AST_STATE_RING ||
10692                      chan->_state == AST_STATE_RINGING)
10693                      break; /* Got ring */
10694                }
10695 
10696                /* We must have a ring by now, so, if configured, lets try to listen for
10697                 * distinctive ringing */
10698                if (p->usedistinctiveringdetection) {
10699                   len = 0;
10700                   distMatches = 0;
10701                   /* Clear the current ring data array so we don't have old data in it. */
10702                   for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
10703                      curRingData[receivedRingT] = 0;
10704                   receivedRingT = 0;
10705                   counter = 0;
10706                   counter1 = 0;
10707                   /* Check to see if context is what it should be, if not set to be. */
10708                   if (strcmp(p->context,p->defcontext) != 0) {
10709                      ast_copy_string(p->context, p->defcontext, sizeof(p->context));
10710                      ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
10711                   }
10712 
10713                   for (;;) {
10714                      i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10715                      if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10716                         ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10717                         callerid_free(cs);
10718                         ast_hangup(chan);
10719                         goto quit;
10720                      }
10721                      if (i & DAHDI_IOMUX_SIGEVENT) {
10722                         res = dahdi_get_event(p->subs[idx].dfd);
10723                         ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10724                         if (res == DAHDI_EVENT_NOALARM) {
10725                            p->inalarm = 0;
10726                         }
10727                         res = 0;
10728                         /* Let us detect distinctive ring */
10729 
10730                         curRingData[receivedRingT] = p->ringt;
10731 
10732                         if (p->ringt < p->ringt_base/2)
10733                            break;
10734                         /* Increment the ringT counter so we can match it against
10735                            values in chan_dahdi.conf for distinctive ring */
10736                         if (++receivedRingT == ARRAY_LEN(curRingData))
10737                            break;
10738                      } else if (i & DAHDI_IOMUX_READ) {
10739                         res = read(p->subs[idx].dfd, buf, sizeof(buf));
10740                         if (res < 0) {
10741                            if (errno != ELAST) {
10742                               ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10743                               callerid_free(cs);
10744                               ast_hangup(chan);
10745                               goto quit;
10746                            }
10747                            break;
10748                         }
10749                         if (p->ringt > 0) {
10750                            if (!(--p->ringt)) {
10751                               res = -1;
10752                               break;
10753                            }
10754                         }
10755                      }
10756                   }
10757                      /* this only shows up if you have n of the dring patterns filled in */
10758                   ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
10759                   for (counter = 0; counter < 3; counter++) {
10760                      /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this
10761                      channel */
10762                      distMatches = 0;
10763                      for (counter1 = 0; counter1 < 3; counter1++) {
10764                         ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
10765                         if (p->drings.ringnum[counter].ring[counter1] == -1) {
10766                            ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
10767                            curRingData[counter1]);
10768                            distMatches++;
10769                         } else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
10770                               curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
10771                            ast_verb(3, "Ring pattern matched in range: %d to %d\n",
10772                            (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
10773                            (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
10774                            distMatches++;
10775                         }
10776                      }
10777 
10778                      if (distMatches == 3) {
10779                         /* The ring matches, set the context to whatever is for distinctive ring.. */
10780                         ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context));
10781                         ast_copy_string(chan->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(chan->context));
10782                         ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
10783                         break;
10784                      }
10785                   }
10786                }
10787                /* Restore linear mode (if appropriate) for Caller*ID processing */
10788                dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10789 #if 1
10790                restore_gains(p);
10791 #endif
10792             } else
10793                ast_log(LOG_WARNING, "Unable to get caller ID space\n");
10794          } else {
10795             ast_log(LOG_WARNING, "Channel %s in prering "
10796                "state, but I have nothing to do. "
10797                "Terminating simple switch, should be "
10798                "restarted by the actual ring.\n",
10799                chan->name);
10800             ast_hangup(chan);
10801             goto quit;
10802          }
10803       } else if (p->use_callerid && p->cid_start == CID_START_RING) {
10804          if (p->cid_signalling == CID_SIG_DTMF) {
10805             int k = 0;
10806             int off_ms;
10807             struct timeval start;
10808             int ms;
10809             cs = NULL;
10810             dahdi_setlinear(p->subs[idx].dfd, 0);
10811             off_ms = 2000;
10812             start = ast_tvnow();
10813             for (;;) {
10814                struct ast_frame *f;
10815 
10816                ms = ast_remaining_ms(start, off_ms);
10817                res = ast_waitfor(chan, ms);
10818                if (res <= 0) {
10819                   ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
10820                      "Exiting simple switch\n");
10821                   ast_hangup(chan);
10822                   goto quit;
10823                }
10824                f = ast_read(chan);
10825                if (!f) {
10826                   /* Hangup received waiting for DTMFCID. Exiting simple switch. */
10827                   ast_hangup(chan);
10828                   goto quit;
10829                }
10830                if (f->frametype == AST_FRAME_DTMF) {
10831                   dtmfbuf[k++] = f->subclass.integer;
10832                   ast_log(LOG_DEBUG, "CID got digit '%c'\n", f->subclass.integer);
10833                   start = ast_tvnow();
10834                }
10835                ast_frfree(f);
10836 
10837                if (p->ringt_base == p->ringt)
10838                   break;
10839             }
10840             dtmfbuf[k] = '\0';
10841             dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10842             /* Got cid and ring. */
10843             callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
10844             ast_log(LOG_DEBUG, "CID is '%s', flags %d\n",
10845                dtmfcid, flags);
10846             /* If first byte is NULL, we have no cid */
10847             if (!ast_strlen_zero(dtmfcid))
10848                number = dtmfcid;
10849             else
10850                number = NULL;
10851             /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */
10852          } else {
10853             /* FSK Bell202 callerID */
10854             cs = callerid_new(p->cid_signalling);
10855             if (cs) {
10856 #if 1
10857                bump_gains(p);
10858 #endif
10859                samples = 0;
10860                len = 0;
10861                distMatches = 0;
10862                /* Clear the current ring data array so we don't have old data in it. */
10863                for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
10864                   curRingData[receivedRingT] = 0;
10865                receivedRingT = 0;
10866                counter = 0;
10867                counter1 = 0;
10868                /* Check to see if context is what it should be, if not set to be. */
10869                if (strcmp(p->context,p->defcontext) != 0) {
10870                   ast_copy_string(p->context, p->defcontext, sizeof(p->context));
10871                   ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
10872                }
10873 
10874                /* Take out of linear mode for Caller*ID processing */
10875                dahdi_setlinear(p->subs[idx].dfd, 0);
10876                for (;;) {
10877                   i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10878                   if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10879                      ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10880                      callerid_free(cs);
10881                      ast_hangup(chan);
10882                      goto quit;
10883                   }
10884                   if (i & DAHDI_IOMUX_SIGEVENT) {
10885                      res = dahdi_get_event(p->subs[idx].dfd);
10886                      ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10887                      if (res == DAHDI_EVENT_NOALARM) {
10888                         p->inalarm = 0;
10889                      }
10890                      /* If we get a PR event, they hung up while processing calerid */
10891                      if ( res == DAHDI_EVENT_POLARITY && p->hanguponpolarityswitch && p->polarity == POLARITY_REV) {
10892                         ast_log(LOG_DEBUG, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p->channel);
10893                         p->polarity = POLARITY_IDLE;
10894                         callerid_free(cs);
10895                         ast_hangup(chan);
10896                         goto quit;
10897                      }
10898                      res = 0;
10899                      /* Let us detect callerid when the telco uses distinctive ring */
10900 
10901                      curRingData[receivedRingT] = p->ringt;
10902 
10903                      if (p->ringt < p->ringt_base/2)
10904                         break;
10905                      /* Increment the ringT counter so we can match it against
10906                         values in chan_dahdi.conf for distinctive ring */
10907                      if (++receivedRingT == ARRAY_LEN(curRingData))
10908                         break;
10909                   } else if (i & DAHDI_IOMUX_READ) {
10910                      res = read(p->subs[idx].dfd, buf, sizeof(buf));
10911                      if (res < 0) {
10912                         if (errno != ELAST) {
10913                            ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10914                            callerid_free(cs);
10915                            ast_hangup(chan);
10916                            goto quit;
10917                         }
10918                         break;
10919                      }
10920                      if (p->ringt > 0) {
10921                         if (!(--p->ringt)) {
10922                            res = -1;
10923                            break;
10924                         }
10925                      }
10926                      samples += res;
10927                      res = callerid_feed(cs, buf, res, AST_LAW(p));
10928                      if (res < 0) {
10929                         /*
10930                          * The previous diagnostic message output likely
10931                          * explains why it failed.
10932                          */
10933                         ast_log(LOG_WARNING,
10934                            "Failed to decode CallerID on channel '%s'\n",
10935                            chan->name);
10936                         break;
10937                      } else if (res)
10938                         break;
10939                      else if (samples > (8000 * 10))
10940                         break;
10941                   }
10942                }
10943                if (res == 1) {
10944                   callerid_get(cs, &name, &number, &flags);
10945                   ast_debug(1, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
10946                }
10947                if (distinctiveringaftercid == 1) {
10948                   /* Clear the current ring data array so we don't have old data in it. */
10949                   for (receivedRingT = 0; receivedRingT < 3; receivedRingT++) {
10950                      curRingData[receivedRingT] = 0;
10951                   }
10952                   receivedRingT = 0;
10953                   ast_verb(3, "Detecting post-CID distinctive ring\n");
10954                   for (;;) {
10955                      i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10956                      if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10957                         ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10958                         callerid_free(cs);
10959                         ast_hangup(chan);
10960                         goto quit;
10961                      }
10962                      if (i & DAHDI_IOMUX_SIGEVENT) {
10963                         res = dahdi_get_event(p->subs[idx].dfd);
10964                         ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10965                         if (res == DAHDI_EVENT_NOALARM) {
10966                            p->inalarm = 0;
10967                         }
10968                         res = 0;
10969                         /* Let us detect callerid when the telco uses distinctive ring */
10970 
10971                         curRingData[receivedRingT] = p->ringt;
10972 
10973                         if (p->ringt < p->ringt_base/2)
10974                            break;
10975                         /* Increment the ringT counter so we can match it against
10976                            values in chan_dahdi.conf for distinctive ring */
10977                         if (++receivedRingT == ARRAY_LEN(curRingData))
10978                            break;
10979                      } else if (i & DAHDI_IOMUX_READ) {
10980                         res = read(p->subs[idx].dfd, buf, sizeof(buf));
10981                         if (res < 0) {
10982                            if (errno != ELAST) {
10983                               ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10984                               callerid_free(cs);
10985                               ast_hangup(chan);
10986                               goto quit;
10987                            }
10988                            break;
10989                         }
10990                         if (p->ringt > 0) {
10991                            if (!(--p->ringt)) {
10992                               res = -1;
10993                               break;
10994                            }
10995                         }
10996                      }
10997                   }
10998                }
10999                if (p->usedistinctiveringdetection) {
11000                   /* this only shows up if you have n of the dring patterns filled in */
11001                   ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
11002 
11003                   for (counter = 0; counter < 3; counter++) {
11004                      /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this
11005                      channel */
11006                      /* this only shows up if you have n of the dring patterns filled in */
11007                      ast_verb(3, "Checking %d,%d,%d\n",
11008                            p->drings.ringnum[counter].ring[0],
11009                            p->drings.ringnum[counter].ring[1],
11010                            p->drings.ringnum[counter].ring[2]);
11011                      distMatches = 0;
11012                      for (counter1 = 0; counter1 < 3; counter1++) {
11013                         ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
11014                         if (p->drings.ringnum[counter].ring[counter1] == -1) {
11015                            ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
11016                            curRingData[counter1]);
11017                            distMatches++;
11018                         }
11019                         else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
11020                            curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
11021                            ast_verb(3, "Ring pattern matched in range: %d to %d\n",
11022                            (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
11023                            (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
11024                            distMatches++;
11025                         }
11026                      }
11027                      if (distMatches == 3) {
11028                         /* The ring matches, set the context to whatever is for distinctive ring.. */
11029                         ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context));
11030                         ast_copy_string(chan->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(chan->context));
11031                         ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
11032                         break;
11033                      }
11034                   }
11035                }
11036                /* Restore linear mode (if appropriate) for Caller*ID processing */
11037                dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
11038 #if 1
11039                restore_gains(p);
11040 #endif
11041                if (res < 0) {
11042                   ast_log(LOG_WARNING, "CallerID returned with error on channel '%s'\n", chan->name);
11043                }
11044             } else
11045                ast_log(LOG_WARNING, "Unable to get caller ID space\n");
11046          }
11047       } else
11048          cs = NULL;
11049 
11050       if (number)
11051          ast_shrink_phone_number(number);
11052       ast_set_callerid(chan, number, name, number);
11053 
11054       if (smdi_msg)
11055          ASTOBJ_UNREF(smdi_msg, ast_smdi_md_message_destroy);
11056 
11057       if (cs)
11058          callerid_free(cs);
11059 
11060       my_handle_notify_message(chan, p, flags, -1);
11061 
11062       ast_setstate(chan, AST_STATE_RING);
11063       chan->rings = 1;
11064       p->ringt = p->ringt_base;
11065       res = ast_pbx_run(chan);
11066       if (res) {
11067          ast_hangup(chan);
11068          ast_log(LOG_WARNING, "PBX exited non-zero\n");
11069       }
11070       goto quit;
11071    default:
11072       ast_log(LOG_WARNING, "Don't know how to handle simple switch with signalling %s on channel %d\n", sig2str(p->sig), p->channel);
11073       res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
11074       if (res < 0)
11075             ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
11076    }
11077    res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
11078    if (res < 0)
11079          ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
11080    ast_hangup(chan);
11081 quit:
11082    ast_mutex_lock(&ss_thread_lock);
11083    ss_thread_count--;
11084    ast_cond_signal(&ss_thread_complete);
11085    ast_mutex_unlock(&ss_thread_lock);
11086    return NULL;
11087 }
11088 
11089 struct mwi_thread_data {
11090    struct dahdi_pvt *pvt;
11091    unsigned char buf[READ_SIZE];
11092    size_t len;
11093 };
11094 
11095 static int calc_energy(const unsigned char *buf, int len, format_t law)
11096 {
11097    int x;
11098    int sum = 0;
11099 
11100    if (!len)
11101       return 0;
11102 
11103    for (x = 0; x < len; x++)
11104       sum += abs(law == AST_FORMAT_ULAW ? AST_MULAW(buf[x]) : AST_ALAW(buf[x]));
11105 
11106    return sum / len;
11107 }
11108 
11109 static void *mwi_thread(void *data)
11110 {
11111    struct mwi_thread_data *mtd = data;
11112    struct callerid_state *cs;
11113    pthread_t threadid;
11114    int samples = 0;
11115    char *name, *number;
11116    int flags;
11117    int i, res;
11118    unsigned int spill_done = 0;
11119    int spill_result = -1;
11120 
11121    if (!(cs = callerid_new(mtd->pvt->cid_signalling))) {
11122       goto quit_no_clean;
11123    }
11124 
11125    callerid_feed(cs, mtd->buf, mtd->len, AST_LAW(mtd->pvt));
11126 
11127    bump_gains(mtd->pvt);
11128 
11129    for (;;) {
11130       i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
11131       if ((res = ioctl(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_IOMUX, &i))) {
11132          ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
11133          goto quit;
11134       }
11135 
11136       if (i & DAHDI_IOMUX_SIGEVENT) {
11137          struct ast_channel *chan;
11138 
11139          /* If we get an event, screen out events that we do not act on.
11140           * Otherwise, cancel and go to the simple switch to let it deal with it.
11141           */
11142          res = dahdi_get_event(mtd->pvt->subs[SUB_REAL].dfd);
11143 
11144          switch (res) {
11145          case DAHDI_EVENT_NEONMWI_ACTIVE:
11146          case DAHDI_EVENT_NEONMWI_INACTIVE:
11147          case DAHDI_EVENT_NONE:
11148          case DAHDI_EVENT_BITSCHANGED:
11149             break;
11150          case DAHDI_EVENT_NOALARM:
11151             if (analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) {
11152                struct analog_pvt *analog_p = mtd->pvt->sig_pvt;
11153 
11154                analog_p->inalarm = 0;
11155             }
11156             mtd->pvt->inalarm = 0;
11157             handle_clear_alarms(mtd->pvt);
11158             break;
11159          case DAHDI_EVENT_ALARM:
11160             if (analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) {
11161                struct analog_pvt *analog_p = mtd->pvt->sig_pvt;
11162 
11163                analog_p->inalarm = 1;
11164             }
11165             mtd->pvt->inalarm = 1;
11166             res = get_alarms(mtd->pvt);
11167             handle_alarms(mtd->pvt, res);
11168             break; /* What to do on channel alarm ???? -- fall thru intentionally?? */
11169          default:
11170             ast_log(LOG_NOTICE, "Got event %d (%s)...  Passing along to analog_ss_thread\n", res, event2str(res));
11171             callerid_free(cs);
11172 
11173             restore_gains(mtd->pvt);
11174             mtd->pvt->ringt = mtd->pvt->ringt_base;
11175 
11176             if ((chan = dahdi_new(mtd->pvt, AST_STATE_RING, 0, SUB_REAL, 0, NULL))) {
11177                int result;
11178 
11179                if (analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) {
11180                   result = analog_ss_thread_start(mtd->pvt->sig_pvt, chan);
11181                } else {
11182                   result = ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan);
11183                }
11184                if (result) {
11185                   ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", mtd->pvt->channel);
11186                   res = tone_zone_play_tone(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11187                   if (res < 0)
11188                      ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", mtd->pvt->channel);
11189                   ast_hangup(chan);
11190                }
11191             } else {
11192                ast_log(LOG_WARNING, "Could not create channel to handle call\n");
11193             }
11194             goto quit_no_clean;
11195          }
11196       } else if (i & DAHDI_IOMUX_READ) {
11197          if ((res = read(mtd->pvt->subs[SUB_REAL].dfd, mtd->buf, sizeof(mtd->buf))) < 0) {
11198             if (errno != ELAST) {
11199                ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
11200                goto quit;
11201             }
11202             break;
11203          }
11204          samples += res;
11205          if (!spill_done) {
11206             if ((spill_result = callerid_feed(cs, mtd->buf, res, AST_LAW(mtd->pvt))) < 0) {
11207                /*
11208                 * The previous diagnostic message output likely
11209                 * explains why it failed.
11210                 */
11211                ast_log(LOG_WARNING, "Failed to decode CallerID\n");
11212                break;
11213             } else if (spill_result) {
11214                spill_done = 1;
11215             }
11216          } else {
11217             /* keep reading data until the energy level drops below the threshold
11218                so we don't get another 'trigger' on the remaining carrier signal
11219             */
11220             if (calc_energy(mtd->buf, res, AST_LAW(mtd->pvt)) <= mwilevel)
11221                break;
11222          }
11223          if (samples > (8000 * 4)) /*Termination case - time to give up*/
11224             break;
11225       }
11226    }
11227 
11228    if (spill_result == 1) {
11229       callerid_get(cs, &name, &number, &flags);
11230       if (flags & CID_MSGWAITING) {
11231          ast_log(LOG_NOTICE, "mwi: Have Messages on channel %d\n", mtd->pvt->channel);
11232          notify_message(mtd->pvt->mailbox, 1);
11233       } else if (flags & CID_NOMSGWAITING) {
11234          ast_log(LOG_NOTICE, "mwi: No Messages on channel %d\n", mtd->pvt->channel);
11235          notify_message(mtd->pvt->mailbox, 0);
11236       } else {
11237          ast_log(LOG_NOTICE, "mwi: Status unknown on channel %d\n", mtd->pvt->channel);
11238       }
11239    }
11240 
11241 
11242 quit:
11243    callerid_free(cs);
11244 
11245    restore_gains(mtd->pvt);
11246 
11247 quit_no_clean:
11248    mtd->pvt->mwimonitoractive = 0;
11249    ast_free(mtd);
11250 
11251    return NULL;
11252 }
11253 
11254 /*
11255 * The following three functions (mwi_send_init, mwi_send_process_buffer,
11256 * mwi_send_process_event) work with the do_monitor thread to generate mwi spills
11257 * that are sent out via FXS port on voicemail state change.  The execution of
11258 * the mwi send is state driven and can either generate a ring pulse prior to
11259 * sending the fsk spill or simply send an fsk spill.
11260 */
11261 static int mwi_send_init(struct dahdi_pvt * pvt)
11262 {
11263    int x;
11264 
11265 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11266    /* Determine how this spill is to be sent */
11267    if (pvt->mwisend_rpas) {
11268       pvt->mwisend_data.mwisend_current = MWI_SEND_SA;
11269       pvt->mwisendactive = 1;
11270    } else if (pvt->mwisend_fsk) {
11271       pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
11272       pvt->mwisendactive = 1;
11273    } else {
11274       pvt->mwisendactive = 0;
11275       return 0;
11276    }
11277 #else
11278    if (mwisend_rpas) {
11279       pvt->mwisend_data.mwisend_current = MWI_SEND_SA;
11280    } else {
11281       pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
11282    }
11283    pvt->mwisendactive = 1;
11284 #endif
11285 
11286    if (pvt->cidspill) {
11287       ast_log(LOG_WARNING, "cidspill already exists when trying to send FSK MWI\n");
11288       ast_free(pvt->cidspill);
11289       pvt->cidspill = NULL;
11290       pvt->cidpos = 0;
11291       pvt->cidlen = 0;
11292    }
11293    pvt->cidspill = ast_calloc(1, MAX_CALLERID_SIZE);
11294    if (!pvt->cidspill) {
11295       pvt->mwisendactive = 0;
11296       return -1;
11297    }
11298    x = DAHDI_FLUSH_BOTH;
11299    ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
11300    x = 3000;
11301    ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_ONHOOKTRANSFER, &x);
11302 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11303    if (pvt->mwisend_fsk) {
11304 #endif
11305       pvt->cidlen = ast_callerid_vmwi_generate(pvt->cidspill, has_voicemail(pvt), CID_MWI_TYPE_MDMF_FULL,
11306                       AST_LAW(pvt), pvt->cid_name, pvt->cid_num, 0);
11307       pvt->cidpos = 0;
11308 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11309    }
11310 #endif
11311    return 0;
11312 }
11313 
11314 static int mwi_send_process_buffer(struct dahdi_pvt * pvt, int num_read)
11315 {
11316    struct timeval    now;
11317    int         res;
11318 
11319    /* sanity check to catch if this had been interrupted previously
11320    *  i.e. state says there is more to do but there is no spill allocated
11321    */
11322    if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current && !pvt->cidspill) {
11323       pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11324    } else if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current) {
11325       /* Normal processing -- Perform mwi send action */
11326       switch ( pvt->mwisend_data.mwisend_current) {
11327       case MWI_SEND_SA:
11328          /* Send the Ring Pulse Signal Alert */
11329          res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &AS_RP_cadence);
11330          if (res) {
11331             ast_log(LOG_WARNING, "Unable to set RP-AS ring cadence: %s\n", strerror(errno));
11332             goto quit;
11333          }
11334          res = dahdi_set_hook(pvt->subs[SUB_REAL].dfd, DAHDI_RING);
11335          pvt->mwisend_data.mwisend_current = MWI_SEND_SA_WAIT;
11336          break;
11337       case MWI_SEND_SA_WAIT:  /* do nothing until I get RINGEROFF event */
11338          break;
11339       case MWI_SEND_PAUSE:  /* Wait between alert and spill - min of 500 mS*/
11340 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11341          if (pvt->mwisend_fsk) {
11342 #endif
11343             gettimeofday(&now, NULL);
11344             if ((int)(now.tv_sec - pvt->mwisend_data.pause.tv_sec) * 1000000 + (int)now.tv_usec - (int)pvt->mwisend_data.pause.tv_usec > 500000) {
11345                pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
11346             }
11347 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11348          } else { /* support for mwisendtype=nofsk */
11349             pvt->mwisend_data.mwisend_current = MWI_SEND_CLEANUP;
11350          }
11351 #endif
11352          break;
11353       case MWI_SEND_SPILL:
11354          /* We read some number of bytes.  Write an equal amount of data */
11355          if(0 < num_read) {
11356             if (num_read > pvt->cidlen - pvt->cidpos)
11357                num_read = pvt->cidlen - pvt->cidpos;
11358             res = write(pvt->subs[SUB_REAL].dfd, pvt->cidspill + pvt->cidpos, num_read);
11359             if (res > 0) {
11360                pvt->cidpos += res;
11361                if (pvt->cidpos >= pvt->cidlen) {
11362                   pvt->mwisend_data.mwisend_current = MWI_SEND_CLEANUP;
11363                }
11364             } else {
11365                ast_log(LOG_WARNING, "MWI FSK Send Write failed: %s\n", strerror(errno));
11366                goto quit;
11367             }
11368          }
11369          break;
11370       case MWI_SEND_CLEANUP:
11371          /* For now, do nothing */
11372          pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11373          break;
11374       default:
11375          /* Should not get here, punt*/
11376          goto quit;
11377       }
11378    }
11379 
11380    if (MWI_SEND_DONE == pvt->mwisend_data.mwisend_current) {
11381       if (pvt->cidspill) {
11382          ast_free(pvt->cidspill);
11383          pvt->cidspill = NULL;
11384          pvt->cidpos = 0;
11385          pvt->cidlen = 0;
11386       }
11387       pvt->mwisendactive = 0;
11388    }
11389    return 0;
11390 quit:
11391    if (pvt->cidspill) {
11392       ast_free(pvt->cidspill);
11393       pvt->cidspill = NULL;
11394       pvt->cidpos = 0;
11395       pvt->cidlen = 0;
11396    }
11397    pvt->mwisendactive = 0;
11398    return -1;
11399 }
11400 
11401 static int mwi_send_process_event(struct dahdi_pvt * pvt, int event)
11402 {
11403    int handled = 0;
11404 
11405    if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current) {
11406       switch (event) {
11407       case DAHDI_EVENT_RINGEROFF:
11408          if(pvt->mwisend_data.mwisend_current == MWI_SEND_SA_WAIT) {
11409             handled = 1;
11410 
11411             if (dahdi_set_hook(pvt->subs[SUB_REAL].dfd, DAHDI_RINGOFF) ) {
11412                ast_log(LOG_WARNING, "Unable to finish RP-AS: %s mwi send aborted\n", strerror(errno));
11413                ast_free(pvt->cidspill);
11414                pvt->cidspill = NULL;
11415                pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11416                pvt->mwisendactive = 0;
11417             } else {
11418                pvt->mwisend_data.mwisend_current = MWI_SEND_PAUSE;
11419                gettimeofday(&pvt->mwisend_data.pause, NULL);
11420             }
11421          }
11422          break;
11423       /* Going off hook, I need to punt this spill */
11424       case DAHDI_EVENT_RINGOFFHOOK:
11425          if (pvt->cidspill) {
11426             ast_free(pvt->cidspill);
11427             pvt->cidspill = NULL;
11428             pvt->cidpos = 0;
11429             pvt->cidlen = 0;
11430          }
11431          pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11432          pvt->mwisendactive = 0;
11433          break;
11434       case DAHDI_EVENT_RINGERON:
11435       case DAHDI_EVENT_HOOKCOMPLETE:
11436          break;
11437       default:
11438          break;
11439       }
11440    }
11441    return handled;
11442 }
11443 
11444 /* destroy a DAHDI channel, identified by its number */
11445 static int dahdi_destroy_channel_bynum(int channel)
11446 {
11447    struct dahdi_pvt *cur;
11448 
11449    ast_mutex_lock(&iflock);
11450    for (cur = iflist; cur; cur = cur->next) {
11451       if (cur->channel == channel) {
11452          int x = DAHDI_FLASH;
11453 
11454          /* important to create an event for dahdi_wait_event to register so that all analog_ss_threads terminate */
11455          ioctl(cur->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
11456 
11457          destroy_channel(cur, 1);
11458          ast_mutex_unlock(&iflock);
11459          ast_module_unref(ast_module_info->self);
11460          return RESULT_SUCCESS;
11461       }
11462    }
11463    ast_mutex_unlock(&iflock);
11464    return RESULT_FAILURE;
11465 }
11466 
11467 static struct dahdi_pvt *handle_init_event(struct dahdi_pvt *i, int event)
11468 {
11469    int res;
11470    pthread_t threadid;
11471    struct ast_channel *chan;
11472 
11473    /* Handle an event on a given channel for the monitor thread. */
11474 
11475    switch (event) {
11476    case DAHDI_EVENT_NONE:
11477    case DAHDI_EVENT_BITSCHANGED:
11478       break;
11479    case DAHDI_EVENT_WINKFLASH:
11480    case DAHDI_EVENT_RINGOFFHOOK:
11481       if (i->inalarm) break;
11482       if (i->radio) break;
11483       /* Got a ring/answer.  What kind of channel are we? */
11484       switch (i->sig) {
11485       case SIG_FXOLS:
11486       case SIG_FXOGS:
11487       case SIG_FXOKS:
11488          res = dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
11489          if (res && (errno == EBUSY))
11490             break;
11491 
11492          /* Cancel VMWI spill */
11493          ast_free(i->cidspill);
11494          i->cidspill = NULL;
11495          restore_conference(i);
11496 
11497          if (i->immediate) {
11498             dahdi_enable_ec(i);
11499             /* The channel is immediately up.  Start right away */
11500             res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
11501             chan = dahdi_new(i, AST_STATE_RING, 1, SUB_REAL, 0, NULL);
11502             if (!chan) {
11503                ast_log(LOG_WARNING, "Unable to start PBX on channel %d\n", i->channel);
11504                res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11505                if (res < 0)
11506                   ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11507             }
11508          } else {
11509             /* Check for callerid, digits, etc */
11510             chan = dahdi_new(i, AST_STATE_RESERVED, 0, SUB_REAL, 0, NULL);
11511             if (chan) {
11512                if (has_voicemail(i))
11513                   res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
11514                else
11515                   res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
11516                if (res < 0)
11517                   ast_log(LOG_WARNING, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i->channel);
11518                if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
11519                   ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11520                   res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11521                   if (res < 0)
11522                      ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11523                   ast_hangup(chan);
11524                }
11525             } else
11526                ast_log(LOG_WARNING, "Unable to create channel\n");
11527          }
11528          break;
11529       case SIG_FXSLS:
11530       case SIG_FXSGS:
11531       case SIG_FXSKS:
11532             i->ringt = i->ringt_base;
11533             /* Fall through */
11534       case SIG_EMWINK:
11535       case SIG_FEATD:
11536       case SIG_FEATDMF:
11537       case SIG_FEATDMF_TA:
11538       case SIG_E911:
11539       case SIG_FGC_CAMA:
11540       case SIG_FGC_CAMAMF:
11541       case SIG_FEATB:
11542       case SIG_EM:
11543       case SIG_EM_E1:
11544       case SIG_SFWINK:
11545       case SIG_SF_FEATD:
11546       case SIG_SF_FEATDMF:
11547       case SIG_SF_FEATB:
11548       case SIG_SF:
11549          /* Check for callerid, digits, etc */
11550          if (i->cid_start == CID_START_POLARITY_IN) {
11551             chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL);
11552          } else {
11553             chan = dahdi_new(i, AST_STATE_RING, 0, SUB_REAL, 0, NULL);
11554          }
11555 
11556          if (!chan) {
11557             ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
11558          } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
11559             ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11560             res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11561             if (res < 0) {
11562                ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11563             }
11564             ast_hangup(chan);
11565          }
11566          break;
11567       default:
11568          ast_log(LOG_WARNING, "Don't know how to handle ring/answer with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
11569          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11570          if (res < 0)
11571             ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11572          return NULL;
11573       }
11574       break;
11575    case DAHDI_EVENT_NOALARM:
11576       switch (i->sig) {
11577 #if defined(HAVE_PRI)
11578       case SIG_PRI_LIB_HANDLE_CASES:
11579          ast_mutex_lock(&i->lock);
11580          sig_pri_chan_alarm_notify(i->sig_pvt, 1);
11581          ast_mutex_unlock(&i->lock);
11582          break;
11583 #endif   /* defined(HAVE_PRI) */
11584 #if defined(HAVE_SS7)
11585       case SIG_SS7:
11586          sig_ss7_set_alarm(i->sig_pvt, 0);
11587          break;
11588 #endif   /* defined(HAVE_SS7) */
11589       default:
11590          i->inalarm = 0;
11591          break;
11592       }
11593       handle_clear_alarms(i);
11594       break;
11595    case DAHDI_EVENT_ALARM:
11596       switch (i->sig) {
11597 #if defined(HAVE_PRI)
11598       case SIG_PRI_LIB_HANDLE_CASES:
11599          ast_mutex_lock(&i->lock);
11600          sig_pri_chan_alarm_notify(i->sig_pvt, 0);
11601          ast_mutex_unlock(&i->lock);
11602          break;
11603 #endif   /* defined(HAVE_PRI) */
11604 #if defined(HAVE_SS7)
11605       case SIG_SS7:
11606          sig_ss7_set_alarm(i->sig_pvt, 1);
11607          break;
11608 #endif   /* defined(HAVE_SS7) */
11609       default:
11610          i->inalarm = 1;
11611          break;
11612       }
11613       res = get_alarms(i);
11614       handle_alarms(i, res);
11615       /* fall thru intentionally */
11616    case DAHDI_EVENT_ONHOOK:
11617       if (i->radio)
11618          break;
11619       /* Back on hook.  Hang up. */
11620       switch (i->sig) {
11621       case SIG_FXOLS:
11622       case SIG_FXOGS:
11623       case SIG_FEATD:
11624       case SIG_FEATDMF:
11625       case SIG_FEATDMF_TA:
11626       case SIG_E911:
11627       case SIG_FGC_CAMA:
11628       case SIG_FGC_CAMAMF:
11629       case SIG_FEATB:
11630       case SIG_EM:
11631       case SIG_EM_E1:
11632       case SIG_EMWINK:
11633       case SIG_SF_FEATD:
11634       case SIG_SF_FEATDMF:
11635       case SIG_SF_FEATB:
11636       case SIG_SF:
11637       case SIG_SFWINK:
11638       case SIG_FXSLS:
11639       case SIG_FXSGS:
11640       case SIG_FXSKS:
11641       case SIG_FXOKS:
11642          dahdi_disable_ec(i);
11643          /* Diddle the battery for the zhone */
11644 #ifdef ZHONE_HACK
11645          dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
11646          usleep(1);
11647 #endif
11648          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
11649          dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
11650          break;
11651       case SIG_SS7:
11652       case SIG_PRI_LIB_HANDLE_CASES:
11653          dahdi_disable_ec(i);
11654          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
11655          break;
11656       default:
11657          ast_log(LOG_WARNING, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
11658          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
11659          return NULL;
11660       }
11661       break;
11662    case DAHDI_EVENT_POLARITY:
11663       switch (i->sig) {
11664       case SIG_FXSLS:
11665       case SIG_FXSKS:
11666       case SIG_FXSGS:
11667          /* We have already got a PR before the channel was
11668             created, but it wasn't handled. We need polarity
11669             to be REV for remote hangup detection to work.
11670             At least in Spain */
11671          if (i->hanguponpolarityswitch)
11672             i->polarity = POLARITY_REV;
11673          if (i->cid_start == CID_START_POLARITY || i->cid_start == CID_START_POLARITY_IN) {
11674             i->polarity = POLARITY_REV;
11675             ast_verb(2, "Starting post polarity "
11676                "CID detection on channel %d\n",
11677                i->channel);
11678             chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL);
11679             if (!chan) {
11680                ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
11681             } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
11682                ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11683                ast_hangup(chan);
11684             }
11685          }
11686          break;
11687       default:
11688          ast_log(LOG_WARNING, "handle_init_event detected "
11689             "polarity reversal on non-FXO (SIG_FXS) "
11690             "interface %d\n", i->channel);
11691       }
11692       break;
11693    case DAHDI_EVENT_REMOVED: /* destroy channel, will actually do so in do_monitor */
11694       ast_log(LOG_NOTICE,
11695             "Got DAHDI_EVENT_REMOVED. Destroying channel %d\n",
11696             i->channel);
11697       return i;
11698    case DAHDI_EVENT_NEONMWI_ACTIVE:
11699       if (i->mwimonitor_neon) {
11700          notify_message(i->mailbox, 1);
11701          ast_log(LOG_NOTICE, "NEON MWI set for channel %d, mailbox %s \n", i->channel, i->mailbox);
11702       }
11703       break;
11704    case DAHDI_EVENT_NEONMWI_INACTIVE:
11705       if (i->mwimonitor_neon) {
11706          notify_message(i->mailbox, 0);
11707          ast_log(LOG_NOTICE, "NEON MWI cleared for channel %d, mailbox %s\n", i->channel, i->mailbox);
11708       }
11709       break;
11710    }
11711    return NULL;
11712 }
11713 
11714 static void monitor_pfds_clean(void *arg) {
11715    struct pollfd **pfds = arg;
11716    ast_free(*pfds);
11717 }
11718 
11719 static void *do_monitor(void *data)
11720 {
11721    int count, res, res2, spoint, pollres=0;
11722    struct dahdi_pvt *i;
11723    struct dahdi_pvt *last = NULL;
11724    struct dahdi_pvt *doomed;
11725    time_t thispass = 0, lastpass = 0;
11726    int found;
11727    char buf[1024];
11728    struct pollfd *pfds=NULL;
11729    int lastalloc = -1;
11730    /* This thread monitors all the frame relay interfaces which are not yet in use
11731       (and thus do not have a separate thread) indefinitely */
11732    /* From here on out, we die whenever asked */
11733 #if 0
11734    if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) {
11735       ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n");
11736       return NULL;
11737    }
11738    ast_debug(1, "Monitor starting...\n");
11739 #endif
11740    pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
11741 
11742    pthread_cleanup_push(monitor_pfds_clean, &pfds);
11743    for (;;) {
11744       /* Lock the interface list */
11745       ast_mutex_lock(&iflock);
11746       if (!pfds || (lastalloc != ifcount)) {
11747          if (pfds) {
11748             ast_free(pfds);
11749             pfds = NULL;
11750          }
11751          if (ifcount) {
11752             if (!(pfds = ast_calloc(1, ifcount * sizeof(*pfds)))) {
11753                ast_mutex_unlock(&iflock);
11754                return NULL;
11755             }
11756          }
11757          lastalloc = ifcount;
11758       }
11759       /* Build the stuff we're going to poll on, that is the socket of every
11760          dahdi_pvt that does not have an associated owner channel */
11761       count = 0;
11762       for (i = iflist; i; i = i->next) {
11763          ast_mutex_lock(&i->lock);
11764          if (pfds && (i->subs[SUB_REAL].dfd > -1) && i->sig && (!i->radio) && !(i->sig & SIG_MFCR2)) {
11765             if (analog_lib_handles(i->sig, i->radio, i->oprmode)) {
11766                struct analog_pvt *p = i->sig_pvt;
11767 
11768                if (!p) {
11769                   ast_log(LOG_ERROR, "No sig_pvt?\n");
11770                } else if (!p->owner && !p->subs[SUB_REAL].owner) {
11771                   /* This needs to be watched, as it lacks an owner */
11772                   pfds[count].fd = i->subs[SUB_REAL].dfd;
11773                   pfds[count].events = POLLPRI;
11774                   pfds[count].revents = 0;
11775                   /* Message waiting or r2 channels also get watched for reading */
11776                   if (i->cidspill || i->mwisendactive || i->mwimonitor_fsk || 
11777                      (i->cid_start == CID_START_DTMF_NOALERT && (i->sig == SIG_FXSLS || i->sig == SIG_FXSGS || i->sig == SIG_FXSKS))) {
11778                      pfds[count].events |= POLLIN;
11779                   }
11780                   count++;
11781                }
11782             } else {
11783                if (!i->owner && !i->subs[SUB_REAL].owner && !i->mwimonitoractive ) {
11784                   /* This needs to be watched, as it lacks an owner */
11785                   pfds[count].fd = i->subs[SUB_REAL].dfd;
11786                   pfds[count].events = POLLPRI;
11787                   pfds[count].revents = 0;
11788                   /* If we are monitoring for VMWI or sending CID, we need to
11789                      read from the channel as well */
11790                   if (i->cidspill || i->mwisendactive || i->mwimonitor_fsk ||
11791                      (i->cid_start == CID_START_DTMF_NOALERT && (i->sig == SIG_FXSLS || i->sig == SIG_FXSGS || i->sig == SIG_FXSKS))) {
11792                      pfds[count].events |= POLLIN;
11793                   }
11794                   count++;
11795                }
11796             }
11797          }
11798          ast_mutex_unlock(&i->lock);
11799       }
11800       /* Okay, now that we know what to do, release the interface lock */
11801       ast_mutex_unlock(&iflock);
11802 
11803       pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
11804       pthread_testcancel();
11805       /* Wait at least a second for something to happen */
11806       res = poll(pfds, count, 1000);
11807       pthread_testcancel();
11808       pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
11809 
11810       /* Okay, poll has finished.  Let's see what happened.  */
11811       if (res < 0) {
11812          if ((errno != EAGAIN) && (errno != EINTR))
11813             ast_log(LOG_WARNING, "poll return %d: %s\n", res, strerror(errno));
11814          continue;
11815       }
11816       /* Alright, lock the interface list again, and let's look and see what has
11817          happened */
11818       ast_mutex_lock(&iflock);
11819       found = 0;
11820       spoint = 0;
11821       lastpass = thispass;
11822       thispass = time(NULL);
11823       doomed = NULL;
11824       for (i = iflist;; i = i->next) {
11825          if (doomed) {
11826             int res;
11827             res = dahdi_destroy_channel_bynum(doomed->channel);
11828             if (res != RESULT_SUCCESS) {
11829                ast_log(LOG_WARNING, "Couldn't find channel to destroy, hopefully another destroy operation just happened.\n");
11830             }
11831             doomed = NULL;
11832          }
11833          if (!i) {
11834             break;
11835          }
11836 
11837          if (thispass != lastpass) {
11838             if (!found && ((i == last) || ((i == iflist) && !last))) {
11839                last = i;
11840                if (last) {
11841                   struct analog_pvt *analog_p = last->sig_pvt;
11842                   /* Only allow MWI to be initiated on a quiescent fxs port */
11843                   if (analog_p
11844                      && !last->mwisendactive
11845                      && (last->sig & __DAHDI_SIG_FXO)
11846                      && !analog_p->fxsoffhookstate
11847                      && !last->owner
11848                      && !ast_strlen_zero(last->mailbox)
11849                      && (thispass - analog_p->onhooktime > 3)) {
11850                      res = has_voicemail(last);
11851                      if (analog_p->msgstate != res) {
11852                         /* Set driver resources for signalling VMWI */
11853                         res2 = ioctl(last->subs[SUB_REAL].dfd, DAHDI_VMWI, &res);
11854                         if (res2) {
11855                            /* TODO: This message will ALWAYS be generated on some cards; any way to restrict it to those cards where it is interesting? */
11856                            ast_debug(3, "Unable to control message waiting led on channel %d: %s\n", last->channel, strerror(errno));
11857                         }
11858                         /* If enabled for FSK spill then initiate it */
11859                         if (mwi_send_init(last)) {
11860                            ast_log(LOG_WARNING, "Unable to initiate mwi send sequence on channel %d\n", last->channel);
11861                         }
11862                         analog_p->msgstate = res;
11863                         found ++;
11864                      }
11865                   }
11866                   last = last->next;
11867                }
11868             }
11869          }
11870          if ((i->subs[SUB_REAL].dfd > -1) && i->sig) {
11871             if (i->radio && !i->owner)
11872             {
11873                res = dahdi_get_event(i->subs[SUB_REAL].dfd);
11874                if (res)
11875                {
11876                   ast_debug(1, "Monitor doohicky got event %s on radio channel %d\n", event2str(res), i->channel);
11877                   /* Don't hold iflock while handling init events */
11878                   ast_mutex_unlock(&iflock);
11879                   if (analog_lib_handles(i->sig, i->radio, i->oprmode))
11880                      doomed = (struct dahdi_pvt *) analog_handle_init_event(i->sig_pvt, dahdievent_to_analogevent(res));
11881                   else
11882                      doomed = handle_init_event(i, res);
11883                   ast_mutex_lock(&iflock);
11884                }
11885                continue;
11886             }
11887             pollres = ast_fdisset(pfds, i->subs[SUB_REAL].dfd, count, &spoint);
11888             if (pollres & POLLIN) {
11889                if (i->owner || i->subs[SUB_REAL].owner) {
11890 #ifdef HAVE_PRI
11891                   if (!i->pri)
11892 #endif
11893                      ast_log(LOG_WARNING, "Whoa....  I'm owned but found (%d) in read...\n", i->subs[SUB_REAL].dfd);
11894                   continue;
11895                }
11896                if (!i->mwimonitor_fsk && !i->mwisendactive  && i->cid_start != CID_START_DTMF_NOALERT) {
11897                   ast_log(LOG_WARNING, "Whoa....  I'm not looking for MWI or sending MWI but am reading (%d)...\n", i->subs[SUB_REAL].dfd);
11898                   continue;
11899                }
11900                res = read(i->subs[SUB_REAL].dfd, buf, sizeof(buf));
11901                if (res > 0) {
11902                   if (i->mwimonitor_fsk) {
11903                      if (calc_energy((unsigned char *) buf, res, AST_LAW(i)) > mwilevel) {
11904                         pthread_attr_t attr;
11905                         pthread_t threadid;
11906                         struct mwi_thread_data *mtd;
11907 
11908                         pthread_attr_init(&attr);
11909                         pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
11910 
11911                         ast_log(LOG_DEBUG, "Maybe some MWI on port %d!\n", i->channel);
11912                         if ((mtd = ast_calloc(1, sizeof(*mtd)))) {
11913                            mtd->pvt = i;
11914                            memcpy(mtd->buf, buf, res);
11915                            mtd->len = res;
11916                            i->mwimonitoractive = 1;
11917                            if (ast_pthread_create_background(&threadid, &attr, mwi_thread, mtd)) {
11918                               ast_log(LOG_WARNING, "Unable to start mwi thread on channel %d\n", i->channel);
11919                               i->mwimonitoractive = 0;
11920                               ast_free(mtd);
11921                            }
11922                         }
11923                      }
11924                   /* If configured to check for a DTMF CID spill that comes without alert (e.g no polarity reversal) */
11925                   } else if (i->cid_start == CID_START_DTMF_NOALERT) {
11926                      int energy;
11927                      struct timeval now;
11928                      /* State machine dtmfcid_holdoff_state allows for the line to settle
11929                       * before checking agin for dtmf energy.  Presently waits for 500 mS before checking again 
11930                      */
11931                      if (1 == i->dtmfcid_holdoff_state) {
11932                         gettimeofday(&i->dtmfcid_delay, NULL);
11933                         i->dtmfcid_holdoff_state = 2;
11934                      } else if (2 == i->dtmfcid_holdoff_state) {
11935                         gettimeofday(&now, NULL);
11936                         if ((int)(now.tv_sec - i->dtmfcid_delay.tv_sec) * 1000000 + (int)now.tv_usec - (int)i->dtmfcid_delay.tv_usec > 500000) {
11937                            i->dtmfcid_holdoff_state = 0;
11938                         }
11939                      } else {
11940                         energy = calc_energy((unsigned char *) buf, res, AST_LAW(i));
11941                         if (!i->mwisendactive && energy > dtmfcid_level) {
11942                            pthread_t threadid;
11943                            struct ast_channel *chan;
11944                            ast_mutex_unlock(&iflock);
11945                            if (analog_lib_handles(i->sig, i->radio, i->oprmode)) {
11946                               /* just in case this event changes or somehow destroys a channel, set doomed here too */
11947                               doomed = analog_handle_init_event(i->sig_pvt, ANALOG_EVENT_DTMFCID);  
11948                               i->dtmfcid_holdoff_state = 1;
11949                            } else {
11950                               chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL);
11951                               if (!chan) {
11952                                  ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
11953                               } else {
11954                                  res = ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan);
11955                                  if (res) {
11956                                     ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11957                                     ast_hangup(chan);
11958                                  } else {
11959                                     i->dtmfcid_holdoff_state = 1;
11960                                  }
11961                               }
11962                            }
11963                            ast_mutex_lock(&iflock);
11964                         }
11965                      }
11966                   }
11967                   if (i->mwisendactive) {
11968                      mwi_send_process_buffer(i, res);
11969                   }
11970                } else {
11971                   ast_log(LOG_WARNING, "Read failed with %d: %s\n", res, strerror(errno));
11972                }
11973             }
11974             if (pollres & POLLPRI) {
11975                if (i->owner || i->subs[SUB_REAL].owner) {
11976 #ifdef HAVE_PRI
11977                   if (!i->pri)
11978 #endif
11979                      ast_log(LOG_WARNING, "Whoa....  I'm owned but found (%d)...\n", i->subs[SUB_REAL].dfd);
11980                   continue;
11981                }
11982                res = dahdi_get_event(i->subs[SUB_REAL].dfd);
11983                ast_debug(1, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel);
11984                /* Don't hold iflock while handling init events */
11985                ast_mutex_unlock(&iflock);
11986                if (0 == i->mwisendactive || 0 == mwi_send_process_event(i, res)) {
11987                   if (analog_lib_handles(i->sig, i->radio, i->oprmode))
11988                      doomed = (struct dahdi_pvt *) analog_handle_init_event(i->sig_pvt, dahdievent_to_analogevent(res));
11989                   else
11990                      doomed = handle_init_event(i, res);
11991                }
11992                ast_mutex_lock(&iflock);
11993             }
11994          }
11995       }
11996       ast_mutex_unlock(&iflock);
11997    }
11998    /* Never reached */
11999    pthread_cleanup_pop(1);
12000    return NULL;
12001 
12002 }
12003 
12004 static int restart_monitor(void)
12005 {
12006    /* If we're supposed to be stopped -- stay stopped */
12007    if (monitor_thread == AST_PTHREADT_STOP)
12008       return 0;
12009    ast_mutex_lock(&monlock);
12010    if (monitor_thread == pthread_self()) {
12011       ast_mutex_unlock(&monlock);
12012       ast_log(LOG_WARNING, "Cannot kill myself\n");
12013       return -1;
12014    }
12015    if (monitor_thread != AST_PTHREADT_NULL) {
12016       /* Wake up the thread */
12017       pthread_kill(monitor_thread, SIGURG);
12018    } else {
12019       /* Start a new monitor */
12020       if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) {
12021          ast_mutex_unlock(&monlock);
12022          ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
12023          return -1;
12024       }
12025    }
12026    ast_mutex_unlock(&monlock);
12027    return 0;
12028 }
12029 
12030 #if defined(HAVE_PRI)
12031 static int pri_resolve_span(int *span, int channel, int offset, struct dahdi_spaninfo *si)
12032 {
12033    int x;
12034    int trunkgroup;
12035    /* Get appropriate trunk group if there is one */
12036    trunkgroup = pris[*span].mastertrunkgroup;
12037    if (trunkgroup) {
12038       /* Select a specific trunk group */
12039       for (x = 0; x < NUM_SPANS; x++) {
12040          if (pris[x].pri.trunkgroup == trunkgroup) {
12041             *span = x;
12042             return 0;
12043          }
12044       }
12045       ast_log(LOG_WARNING, "Channel %d on span %d configured to use nonexistent trunk group %d\n", channel, *span, trunkgroup);
12046       *span = -1;
12047    } else {
12048       if (pris[*span].pri.trunkgroup) {
12049          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);
12050          *span = -1;
12051       } else if (pris[*span].mastertrunkgroup) {
12052          ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is already part of trunk group %d\n", *span, pris[*span].mastertrunkgroup);
12053          *span = -1;
12054       } else {
12055          if (si->totalchans == 31) {
12056             /* E1 */
12057             pris[*span].dchannels[0] = 16 + offset;
12058          } else if (si->totalchans == 24) {
12059             /* T1 or J1 */
12060             pris[*span].dchannels[0] = 24 + offset;
12061          } else if (si->totalchans == 3) {
12062             /* BRI */
12063             pris[*span].dchannels[0] = 3 + offset;
12064          } else {
12065             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);
12066             *span = -1;
12067             return 0;
12068          }
12069          pris[*span].pri.span = *span + 1;
12070       }
12071    }
12072    return 0;
12073 }
12074 #endif   /* defined(HAVE_PRI) */
12075 
12076 #if defined(HAVE_PRI)
12077 static int pri_create_trunkgroup(int trunkgroup, int *channels)
12078 {
12079    struct dahdi_spaninfo si;
12080    struct dahdi_params p;
12081    int fd;
12082    int span;
12083    int ospan=0;
12084    int x,y;
12085    for (x = 0; x < NUM_SPANS; x++) {
12086       if (pris[x].pri.trunkgroup == trunkgroup) {
12087          ast_log(LOG_WARNING, "Trunk group %d already exists on span %d, Primary d-channel %d\n", trunkgroup, x + 1, pris[x].dchannels[0]);
12088          return -1;
12089       }
12090    }
12091    for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
12092       if (!channels[y])
12093          break;
12094       memset(&si, 0, sizeof(si));
12095       memset(&p, 0, sizeof(p));
12096       fd = open("/dev/dahdi/channel", O_RDWR);
12097       if (fd < 0) {
12098          ast_log(LOG_WARNING, "Failed to open channel: %s\n", strerror(errno));
12099          return -1;
12100       }
12101       x = channels[y];
12102       if (ioctl(fd, DAHDI_SPECIFY, &x)) {
12103          ast_log(LOG_WARNING, "Failed to specify channel %d: %s\n", channels[y], strerror(errno));
12104          close(fd);
12105          return -1;
12106       }
12107       if (ioctl(fd, DAHDI_GET_PARAMS, &p)) {
12108          ast_log(LOG_WARNING, "Failed to get channel parameters for channel %d: %s\n", channels[y], strerror(errno));
12109          return -1;
12110       }
12111       if (ioctl(fd, DAHDI_SPANSTAT, &si)) {
12112          ast_log(LOG_WARNING, "Failed go get span information on channel %d (span %d): %s\n", channels[y], p.spanno, strerror(errno));
12113          close(fd);
12114          return -1;
12115       }
12116       span = p.spanno - 1;
12117       if (pris[span].pri.trunkgroup) {
12118          ast_log(LOG_WARNING, "Span %d is already provisioned for trunk group %d\n", span + 1, pris[span].pri.trunkgroup);
12119          close(fd);
12120          return -1;
12121       }
12122       if (pris[span].pri.pvts[0]) {
12123          ast_log(LOG_WARNING, "Span %d is already provisioned with channels (implicit PRI maybe?)\n", span + 1);
12124          close(fd);
12125          return -1;
12126       }
12127       if (!y) {
12128          pris[span].pri.trunkgroup = trunkgroup;
12129          ospan = span;
12130       }
12131       pris[ospan].dchannels[y] = channels[y];
12132       pris[span].pri.span = span + 1;
12133       close(fd);
12134    }
12135    return 0;
12136 }
12137 #endif   /* defined(HAVE_PRI) */
12138 
12139 #if defined(HAVE_PRI)
12140 static int pri_create_spanmap(int span, int trunkgroup, int logicalspan)
12141 {
12142    if (pris[span].mastertrunkgroup) {
12143       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);
12144       return -1;
12145    }
12146    pris[span].mastertrunkgroup = trunkgroup;
12147    pris[span].prilogicalspan = logicalspan;
12148    return 0;
12149 }
12150 #endif   /* defined(HAVE_PRI) */
12151 
12152 #if defined(HAVE_SS7)
12153 static unsigned int parse_pointcode(const char *pcstring)
12154 {
12155    unsigned int code1, code2, code3;
12156    int numvals;
12157 
12158    numvals = sscanf(pcstring, "%30d-%30d-%30d", &code1, &code2, &code3);
12159    if (numvals == 1)
12160       return code1;
12161    if (numvals == 3)
12162       return (code1 << 16) | (code2 << 8) | code3;
12163 
12164    return 0;
12165 }
12166 #endif   /* defined(HAVE_SS7) */
12167 
12168 #if defined(HAVE_SS7)
12169 static struct dahdi_ss7 * ss7_resolve_linkset(int linkset)
12170 {
12171    if ((linkset < 0) || (linkset >= NUM_SPANS))
12172       return NULL;
12173    else
12174       return &linksets[linkset - 1];
12175 }
12176 #endif   /* defined(HAVE_SS7) */
12177 
12178 #ifdef HAVE_OPENR2
12179 static void dahdi_r2_destroy_links(void)
12180 {
12181    int i = 0;
12182    if (!r2links) {
12183       return;
12184    }
12185    for (; i < r2links_count; i++) {
12186       if (r2links[i]->r2master != AST_PTHREADT_NULL) {
12187          pthread_cancel(r2links[i]->r2master);
12188          pthread_join(r2links[i]->r2master, NULL);
12189          openr2_context_delete(r2links[i]->protocol_context);
12190       }
12191       ast_free(r2links[i]);
12192    }
12193    ast_free(r2links);
12194    r2links = NULL;
12195    r2links_count = 0;
12196 }
12197 
12198 /* This is an artificial convenient capacity, to keep at most a full E1 of channels in a single thread */
12199 #define R2_LINK_CAPACITY 30
12200 static struct dahdi_mfcr2 *dahdi_r2_get_link(const struct dahdi_chan_conf *conf)
12201 {
12202    struct dahdi_mfcr2 *new_r2link = NULL;
12203    struct dahdi_mfcr2 **new_r2links = NULL;
12204 
12205    /* Only create a new R2 link if 
12206       1. This is the first link requested
12207       2. Configuration changed 
12208       3. We got more channels than supported per link */
12209    if (!r2links_count ||
12210        memcmp(&conf->mfcr2, &r2links[r2links_count - 1]->conf, sizeof(conf->mfcr2)) ||
12211       (r2links[r2links_count - 1]->numchans == R2_LINK_CAPACITY)) {
12212       new_r2link = ast_calloc(1, sizeof(**r2links));
12213       if (!new_r2link) {
12214          ast_log(LOG_ERROR, "Cannot allocate R2 link!\n");
12215          return NULL;
12216       }
12217       new_r2links = ast_realloc(r2links, ((r2links_count + 1) * sizeof(*r2links)));
12218       if (!new_r2links) {
12219          ast_log(LOG_ERROR, "Cannot allocate R2 link!\n");
12220          ast_free(new_r2link);
12221          return NULL;
12222       }
12223       r2links = new_r2links;
12224       new_r2link->r2master = AST_PTHREADT_NULL;
12225       r2links[r2links_count] = new_r2link;
12226       r2links_count++;
12227       ast_log(LOG_DEBUG, "Created new R2 link!\n");
12228    }
12229    return r2links[r2links_count - 1];
12230 }
12231 
12232 static int dahdi_r2_set_context(struct dahdi_mfcr2 *r2_link, const struct dahdi_chan_conf *conf)
12233 {
12234    char tmplogdir[] = "/tmp";
12235    char logdir[OR2_MAX_PATH];
12236    int threshold = 0;
12237    int snres = 0;
12238    r2_link->protocol_context = openr2_context_new(NULL, &dahdi_r2_event_iface,
12239          &dahdi_r2_transcode_iface, conf->mfcr2.variant, conf->mfcr2.max_ani,
12240          conf->mfcr2.max_dnis);
12241    if (!r2_link->protocol_context) {
12242       return -1;
12243    }
12244    openr2_context_set_log_level(r2_link->protocol_context, conf->mfcr2.loglevel);
12245    openr2_context_set_ani_first(r2_link->protocol_context, conf->mfcr2.get_ani_first);
12246 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
12247    openr2_context_set_skip_category_request(r2_link->protocol_context, conf->mfcr2.skip_category_request);
12248 #endif
12249    openr2_context_set_mf_threshold(r2_link->protocol_context, threshold);
12250    openr2_context_set_mf_back_timeout(r2_link->protocol_context, conf->mfcr2.mfback_timeout);
12251    openr2_context_set_metering_pulse_timeout(r2_link->protocol_context, conf->mfcr2.metering_pulse_timeout);
12252    openr2_context_set_double_answer(r2_link->protocol_context, conf->mfcr2.double_answer);
12253    openr2_context_set_immediate_accept(r2_link->protocol_context, conf->mfcr2.immediate_accept);
12254    if (ast_strlen_zero(conf->mfcr2.logdir)) {
12255       if (openr2_context_set_log_directory(r2_link->protocol_context, tmplogdir)) {
12256          ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir);
12257       }
12258    } else {
12259       snres = snprintf(logdir, sizeof(logdir), "%s/%s/%s", ast_config_AST_LOG_DIR, "mfcr2", conf->mfcr2.logdir);
12260       if (snres >= sizeof(logdir)) {
12261          ast_log(LOG_ERROR, "MFC/R2 logging directory truncated, using %s\n", tmplogdir);
12262          if (openr2_context_set_log_directory(r2_link->protocol_context, tmplogdir)) {
12263             ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir);
12264          }
12265       } else {
12266          if (openr2_context_set_log_directory(r2_link->protocol_context, logdir)) {
12267             ast_log(LOG_ERROR, "Failed setting MFC/R2 log directory %s\n", logdir);
12268          }
12269       }
12270    }
12271    if (!ast_strlen_zero(conf->mfcr2.r2proto_file)) {
12272       if (openr2_context_configure_from_advanced_file(r2_link->protocol_context, conf->mfcr2.r2proto_file)) {
12273          ast_log(LOG_ERROR, "Failed to configure r2context from advanced configuration file %s\n", conf->mfcr2.r2proto_file);
12274       }
12275    }
12276    /* Save the configuration used to setup this link */
12277    memcpy(&r2_link->conf, conf, sizeof(r2_link->conf));
12278    return 0;
12279 }
12280 #endif
12281 
12282 /* converts a DAHDI sigtype to signalling as can be configured from
12283  * chan_dahdi.conf.
12284  * While both have basically the same values, this will later be the
12285  * place to add filters and sanity checks
12286  */
12287 static int sigtype_to_signalling(int sigtype)
12288 {
12289    return sigtype;
12290 }
12291 
12292 /*!
12293  * \internal
12294  * \brief Get file name and channel number from (subdir,number)
12295  *
12296  * \param subdir name of the subdirectory under /dev/dahdi/
12297  * \param channel name of device file under /dev/dahdi/<subdir>/
12298  * \param path buffer to put file name in
12299  * \param pathlen maximal length of path
12300  *
12301  * \retval minor number of dahdi channel.
12302  * \retval -errno on error.
12303  */
12304 static int device2chan(const char *subdir, int channel, char *path, int pathlen)
12305 {
12306    struct stat stbuf;
12307    int      num;
12308 
12309    snprintf(path, pathlen, "/dev/dahdi/%s/%d", subdir, channel);
12310    if (stat(path, &stbuf) < 0) {
12311       ast_log(LOG_ERROR, "stat(%s) failed: %s\n", path, strerror(errno));
12312       return -errno;
12313    }
12314    if (!S_ISCHR(stbuf.st_mode)) {
12315       ast_log(LOG_ERROR, "%s: Not a character device file\n", path);
12316       return -EINVAL;
12317    }
12318    num = minor(stbuf.st_rdev);
12319    ast_log(LOG_DEBUG, "%s -> %d\n", path, num);
12320    return num;
12321 
12322 }
12323 
12324 /*!
12325  * \internal
12326  * \brief Initialize/create a channel interface.
12327  *
12328  * \param channel Channel interface number to initialize/create.
12329  * \param conf Configuration parameters to initialize interface with.
12330  * \param reloading What we are doing now:
12331  * 0 - initial module load,
12332  * 1 - module reload,
12333  * 2 - module restart
12334  *
12335  * \retval Interface-pointer initialized/created
12336  * \retval NULL if error
12337  */
12338 static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf, int reloading)
12339 {
12340    /* Make a dahdi_pvt structure for this interface */
12341    struct dahdi_pvt *tmp;/*!< Current channel structure initializing */
12342    char fn[80];
12343    struct dahdi_bufferinfo bi;
12344 
12345    int res;
12346 #if defined(HAVE_PRI)
12347    int span = 0;
12348 #endif   /* defined(HAVE_PRI) */
12349    int here = 0;/*!< TRUE if the channel interface already exists. */
12350    int x;
12351    struct analog_pvt *analog_p = NULL;
12352    struct dahdi_params p;
12353 #if defined(HAVE_PRI)
12354    struct dahdi_spaninfo si;
12355    struct sig_pri_chan *pri_chan = NULL;
12356 #endif   /* defined(HAVE_PRI) */
12357 #if defined(HAVE_SS7)
12358    struct sig_ss7_chan *ss7_chan = NULL;
12359 #endif   /* defined(HAVE_SS7) */
12360 
12361    /* Search channel interface list to see if it already exists. */
12362    for (tmp = iflist; tmp; tmp = tmp->next) {
12363       if (!tmp->destroy) {
12364          if (tmp->channel == channel) {
12365             /* The channel interface already exists. */
12366             here = 1;
12367             break;
12368          }
12369          if (tmp->channel > channel) {
12370             /* No way it can be in the sorted list. */
12371             tmp = NULL;
12372             break;
12373          }
12374       }
12375    }
12376 
12377    if (!here && reloading != 1) {
12378       tmp = ast_calloc(1, sizeof(*tmp));
12379       if (!tmp) {
12380          return NULL;
12381       }
12382       tmp->cc_params = ast_cc_config_params_init();
12383       if (!tmp->cc_params) {
12384          ast_free(tmp);
12385          return NULL;
12386       }
12387       ast_mutex_init(&tmp->lock);
12388       ifcount++;
12389       for (x = 0; x < 3; x++)
12390          tmp->subs[x].dfd = -1;
12391       tmp->channel = channel;
12392       tmp->priindication_oob = conf->chan.priindication_oob;
12393    }
12394 
12395    if (tmp) {
12396       int chan_sig = conf->chan.sig;
12397 
12398       /* If there are variables in tmp before it is updated to match the new config, clear them */
12399       if (reloading && tmp->vars) {
12400          ast_variables_destroy(tmp->vars);
12401          tmp->vars = NULL;
12402       }
12403 
12404 
12405       if (!here) {
12406          /* Can only get here if this is a new channel interface being created. */
12407          if ((channel != CHAN_PSEUDO)) {
12408             int count = 0;
12409 
12410             snprintf(fn, sizeof(fn), "%d", channel);
12411             /* Open non-blocking */
12412             tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
12413             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 */
12414                usleep(1);
12415                tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
12416                count++;
12417             }
12418             /* Allocate a DAHDI structure */
12419             if (tmp->subs[SUB_REAL].dfd < 0) {
12420                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);
12421                destroy_dahdi_pvt(tmp);
12422                return NULL;
12423             }
12424             memset(&p, 0, sizeof(p));
12425             res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
12426             if (res < 0) {
12427                ast_log(LOG_ERROR, "Unable to get parameters: %s\n", strerror(errno));
12428                destroy_dahdi_pvt(tmp);
12429                return NULL;
12430             }
12431             if (conf->is_sig_auto)
12432                chan_sig = sigtype_to_signalling(p.sigtype);
12433             if (p.sigtype != (chan_sig & 0x3ffff)) {
12434                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));
12435                destroy_dahdi_pvt(tmp);
12436                return NULL;
12437             }
12438             tmp->law_default = p.curlaw;
12439             tmp->law = p.curlaw;
12440             tmp->span = p.spanno;
12441 #if defined(HAVE_PRI)
12442             span = p.spanno - 1;
12443 #endif   /* defined(HAVE_PRI) */
12444          } else {
12445             chan_sig = 0;
12446          }
12447          tmp->sig = chan_sig;
12448          tmp->outsigmod = conf->chan.outsigmod;
12449 
12450          if (analog_lib_handles(chan_sig, tmp->radio, tmp->oprmode)) {
12451             analog_p = analog_new(dahdisig_to_analogsig(chan_sig), &dahdi_analog_callbacks, tmp);
12452             if (!analog_p) {
12453                destroy_dahdi_pvt(tmp);
12454                return NULL;
12455             }
12456             tmp->sig_pvt = analog_p;
12457          }
12458 #if defined(HAVE_SS7)
12459          if (chan_sig == SIG_SS7) {
12460             struct dahdi_ss7 *ss7;
12461             int clear = 0;
12462 
12463             if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &clear)) {
12464                ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
12465                destroy_dahdi_pvt(tmp);
12466                return NULL;
12467             }
12468 
12469             ss7 = ss7_resolve_linkset(cur_linkset);
12470             if (!ss7) {
12471                ast_log(LOG_ERROR, "Unable to find linkset %d\n", cur_linkset);
12472                destroy_dahdi_pvt(tmp);
12473                return NULL;
12474             }
12475             ss7->ss7.span = cur_linkset;
12476             if (cur_cicbeginswith < 0) {
12477                ast_log(LOG_ERROR, "Need to set cicbeginswith for the channels!\n");
12478                destroy_dahdi_pvt(tmp);
12479                return NULL;
12480             }
12481             ss7_chan = sig_ss7_chan_new(tmp, &dahdi_ss7_callbacks, &ss7->ss7);
12482             if (!ss7_chan) {
12483                destroy_dahdi_pvt(tmp);
12484                return NULL;
12485             }
12486             tmp->sig_pvt = ss7_chan;
12487             tmp->ss7 = &ss7->ss7;
12488 
12489             ss7_chan->channel = tmp->channel;
12490             ss7_chan->cic = cur_cicbeginswith++;
12491 
12492             /* DB: Add CIC's DPC information */
12493             ss7_chan->dpc = cur_defaultdpc;
12494 
12495             ss7->ss7.pvts[ss7->ss7.numchans++] = ss7_chan;
12496 
12497             ast_copy_string(ss7->ss7.internationalprefix, conf->ss7.ss7.internationalprefix, sizeof(ss7->ss7.internationalprefix));
12498             ast_copy_string(ss7->ss7.nationalprefix, conf->ss7.ss7.nationalprefix, sizeof(ss7->ss7.nationalprefix));
12499             ast_copy_string(ss7->ss7.subscriberprefix, conf->ss7.ss7.subscriberprefix, sizeof(ss7->ss7.subscriberprefix));
12500             ast_copy_string(ss7->ss7.unknownprefix, conf->ss7.ss7.unknownprefix, sizeof(ss7->ss7.unknownprefix));
12501 
12502             ss7->ss7.called_nai = conf->ss7.ss7.called_nai;
12503             ss7->ss7.calling_nai = conf->ss7.ss7.calling_nai;
12504          }
12505 #endif   /* defined(HAVE_SS7) */
12506 #ifdef HAVE_OPENR2
12507          if (chan_sig == SIG_MFCR2) {
12508             struct dahdi_mfcr2 *r2_link;
12509             r2_link = dahdi_r2_get_link(conf);
12510             if (!r2_link) {
12511                ast_log(LOG_WARNING, "Cannot get another R2 DAHDI context!\n");
12512                destroy_dahdi_pvt(tmp);
12513                return NULL;
12514             }
12515             if (!r2_link->protocol_context && dahdi_r2_set_context(r2_link, conf)) {
12516                ast_log(LOG_ERROR, "Cannot create OpenR2 protocol context.\n");
12517                destroy_dahdi_pvt(tmp);
12518                return NULL;
12519             }
12520             if (r2_link->numchans == ARRAY_LEN(r2_link->pvts)) {
12521                ast_log(LOG_ERROR, "Cannot add more channels to this link!\n");
12522                destroy_dahdi_pvt(tmp);
12523                return NULL;
12524             }
12525             r2_link->pvts[r2_link->numchans++] = tmp;
12526             tmp->r2chan = openr2_chan_new_from_fd(r2_link->protocol_context,
12527                                         tmp->subs[SUB_REAL].dfd,
12528                                         NULL, NULL);
12529             if (!tmp->r2chan) {
12530                openr2_liberr_t err = openr2_context_get_last_error(r2_link->protocol_context);
12531                ast_log(LOG_ERROR, "Cannot create OpenR2 channel: %s\n", openr2_context_error_string(err));
12532                destroy_dahdi_pvt(tmp);
12533                return NULL;
12534             }
12535             tmp->mfcr2 = r2_link;
12536             if (conf->mfcr2.call_files) {
12537                openr2_chan_enable_call_files(tmp->r2chan);
12538             }
12539             openr2_chan_set_client_data(tmp->r2chan, tmp);
12540             /* cast seems to be needed to get rid of the annoying warning regarding format attribute  */
12541             openr2_chan_set_logging_func(tmp->r2chan, (openr2_logging_func_t)dahdi_r2_on_chan_log);
12542             openr2_chan_set_log_level(tmp->r2chan, conf->mfcr2.loglevel);
12543             tmp->mfcr2_category = conf->mfcr2.category;
12544             tmp->mfcr2_charge_calls = conf->mfcr2.charge_calls;
12545             tmp->mfcr2_allow_collect_calls = conf->mfcr2.allow_collect_calls;
12546             tmp->mfcr2_forced_release = conf->mfcr2.forced_release;
12547             tmp->mfcr2_accept_on_offer = conf->mfcr2.accept_on_offer;
12548             tmp->mfcr2call = 0;
12549             tmp->mfcr2_dnis_index = 0;
12550             tmp->mfcr2_ani_index = 0;
12551          }
12552 #endif
12553 #ifdef HAVE_PRI
12554          if (dahdi_sig_pri_lib_handles(chan_sig)) {
12555             int offset;
12556             int matchesdchan;
12557             int x,y;
12558             int myswitchtype = 0;
12559 
12560             offset = 0;
12561             if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &offset)) {
12562                ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
12563                destroy_dahdi_pvt(tmp);
12564                return NULL;
12565             }
12566             if (span >= NUM_SPANS) {
12567                ast_log(LOG_ERROR, "Channel %d does not lie on a span I know of (%d)\n", channel, span);
12568                destroy_dahdi_pvt(tmp);
12569                return NULL;
12570             } else {
12571                si.spanno = 0;
12572                if (ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SPANSTAT,&si) == -1) {
12573                   ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno));
12574                   destroy_dahdi_pvt(tmp);
12575                   return NULL;
12576                }
12577                /* Store the logical span first based upon the real span */
12578                tmp->logicalspan = pris[span].prilogicalspan;
12579                pri_resolve_span(&span, channel, (channel - p.chanpos), &si);
12580                if (span < 0) {
12581                   ast_log(LOG_WARNING, "Channel %d: Unable to find locate channel/trunk group!\n", channel);
12582                   destroy_dahdi_pvt(tmp);
12583                   return NULL;
12584                }
12585                myswitchtype = conf->pri.pri.switchtype;
12586                /* Make sure this isn't a d-channel */
12587                matchesdchan=0;
12588                for (x = 0; x < NUM_SPANS; x++) {
12589                   for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
12590                      if (pris[x].dchannels[y] == tmp->channel) {
12591                         matchesdchan = 1;
12592                         break;
12593                      }
12594                   }
12595                }
12596                if (!matchesdchan) {
12597                   if (pris[span].pri.nodetype && (pris[span].pri.nodetype != conf->pri.pri.nodetype)) {
12598                      ast_log(LOG_ERROR, "Span %d is already a %s node\n", span + 1, pri_node2str(pris[span].pri.nodetype));
12599                      destroy_dahdi_pvt(tmp);
12600                      return NULL;
12601                   }
12602                   if (pris[span].pri.switchtype && (pris[span].pri.switchtype != myswitchtype)) {
12603                      ast_log(LOG_ERROR, "Span %d is already a %s switch\n", span + 1, pri_switch2str(pris[span].pri.switchtype));
12604                      destroy_dahdi_pvt(tmp);
12605                      return NULL;
12606                   }
12607                   if ((pris[span].pri.dialplan) && (pris[span].pri.dialplan != conf->pri.pri.dialplan)) {
12608                      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));
12609                      destroy_dahdi_pvt(tmp);
12610                      return NULL;
12611                   }
12612                   if (!ast_strlen_zero(pris[span].pri.idledial) && strcmp(pris[span].pri.idledial, conf->pri.pri.idledial)) {
12613                      ast_log(LOG_ERROR, "Span %d already has idledial '%s'.\n", span + 1, conf->pri.pri.idledial);
12614                      destroy_dahdi_pvt(tmp);
12615                      return NULL;
12616                   }
12617                   if (!ast_strlen_zero(pris[span].pri.idleext) && strcmp(pris[span].pri.idleext, conf->pri.pri.idleext)) {
12618                      ast_log(LOG_ERROR, "Span %d already has idleext '%s'.\n", span + 1, conf->pri.pri.idleext);
12619                      destroy_dahdi_pvt(tmp);
12620                      return NULL;
12621                   }
12622                   if (pris[span].pri.minunused && (pris[span].pri.minunused != conf->pri.pri.minunused)) {
12623                      ast_log(LOG_ERROR, "Span %d already has minunused of %d.\n", span + 1, conf->pri.pri.minunused);
12624                      destroy_dahdi_pvt(tmp);
12625                      return NULL;
12626                   }
12627                   if (pris[span].pri.minidle && (pris[span].pri.minidle != conf->pri.pri.minidle)) {
12628                      ast_log(LOG_ERROR, "Span %d already has minidle of %d.\n", span + 1, conf->pri.pri.minidle);
12629                      destroy_dahdi_pvt(tmp);
12630                      return NULL;
12631                   }
12632                   if (pris[span].pri.numchans >= ARRAY_LEN(pris[span].pri.pvts)) {
12633                      ast_log(LOG_ERROR, "Unable to add channel %d: Too many channels in trunk group %d!\n", channel,
12634                         pris[span].pri.trunkgroup);
12635                      destroy_dahdi_pvt(tmp);
12636                      return NULL;
12637                   }
12638 
12639                   ast_debug(4, "Adding callbacks %p to chan %d\n", &dahdi_pri_callbacks, tmp->channel);
12640                   pri_chan = sig_pri_chan_new(tmp, &dahdi_pri_callbacks, &pris[span].pri, tmp->logicalspan, p.chanpos, pris[span].mastertrunkgroup);
12641                   if (!pri_chan) {
12642                      destroy_dahdi_pvt(tmp);
12643                      return NULL;
12644                   }
12645                   tmp->sig_pvt = pri_chan;
12646                   tmp->pri = &pris[span].pri;
12647 
12648                   tmp->priexclusive = conf->chan.priexclusive;
12649 
12650                   if (!tmp->pri->cc_params) {
12651                      tmp->pri->cc_params = ast_cc_config_params_init();
12652                      if (!tmp->pri->cc_params) {
12653                         destroy_dahdi_pvt(tmp);
12654                         return NULL;
12655                      }
12656                   }
12657                   ast_cc_copy_config_params(tmp->pri->cc_params,
12658                      conf->chan.cc_params);
12659 
12660                   pris[span].pri.sig = chan_sig;
12661                   pris[span].pri.nodetype = conf->pri.pri.nodetype;
12662                   pris[span].pri.switchtype = myswitchtype;
12663                   pris[span].pri.nsf = conf->pri.pri.nsf;
12664                   pris[span].pri.dialplan = conf->pri.pri.dialplan;
12665                   pris[span].pri.localdialplan = conf->pri.pri.localdialplan;
12666                   pris[span].pri.pvts[pris[span].pri.numchans++] = tmp->sig_pvt;
12667                   pris[span].pri.minunused = conf->pri.pri.minunused;
12668                   pris[span].pri.minidle = conf->pri.pri.minidle;
12669                   pris[span].pri.overlapdial = conf->pri.pri.overlapdial;
12670                   pris[span].pri.qsigchannelmapping = conf->pri.pri.qsigchannelmapping;
12671                   pris[span].pri.discardremoteholdretrieval = conf->pri.pri.discardremoteholdretrieval;
12672 #if defined(HAVE_PRI_SERVICE_MESSAGES)
12673                   pris[span].pri.enable_service_message_support = conf->pri.pri.enable_service_message_support;
12674 #endif   /* defined(HAVE_PRI_SERVICE_MESSAGES) */
12675 #ifdef HAVE_PRI_INBANDDISCONNECT
12676                   pris[span].pri.inbanddisconnect = conf->pri.pri.inbanddisconnect;
12677 #endif
12678 #if defined(HAVE_PRI_CALL_HOLD)
12679                   pris[span].pri.hold_disconnect_transfer =
12680                      conf->pri.pri.hold_disconnect_transfer;
12681 #endif   /* defined(HAVE_PRI_CALL_HOLD) */
12682 #if defined(HAVE_PRI_CCSS)
12683                   pris[span].pri.cc_ptmp_recall_mode =
12684                      conf->pri.pri.cc_ptmp_recall_mode;
12685                   pris[span].pri.cc_qsig_signaling_link_req =
12686                      conf->pri.pri.cc_qsig_signaling_link_req;
12687                   pris[span].pri.cc_qsig_signaling_link_rsp =
12688                      conf->pri.pri.cc_qsig_signaling_link_rsp;
12689 #endif   /* defined(HAVE_PRI_CCSS) */
12690 #if defined(HAVE_PRI_CALL_WAITING)
12691                   pris[span].pri.max_call_waiting_calls =
12692                      conf->pri.pri.max_call_waiting_calls;
12693                   pris[span].pri.allow_call_waiting_calls =
12694                      conf->pri.pri.allow_call_waiting_calls;
12695 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
12696                   pris[span].pri.transfer = conf->chan.transfer;
12697                   pris[span].pri.facilityenable = conf->pri.pri.facilityenable;
12698 #if defined(HAVE_PRI_L2_PERSISTENCE)
12699                   pris[span].pri.l2_persistence = conf->pri.pri.l2_persistence;
12700 #endif   /* defined(HAVE_PRI_L2_PERSISTENCE) */
12701 #if defined(HAVE_PRI_AOC_EVENTS)
12702                   pris[span].pri.aoc_passthrough_flag = conf->pri.pri.aoc_passthrough_flag;
12703                   pris[span].pri.aoce_delayhangup = conf->pri.pri.aoce_delayhangup;
12704 #endif   /* defined(HAVE_PRI_AOC_EVENTS) */
12705                   if (chan_sig == SIG_BRI_PTMP) {
12706                      pris[span].pri.layer1_ignored = conf->pri.pri.layer1_ignored;
12707                   } else {
12708                      /* Option does not apply to this line type. */
12709                      pris[span].pri.layer1_ignored = 0;
12710                   }
12711                   pris[span].pri.append_msn_to_user_tag = conf->pri.pri.append_msn_to_user_tag;
12712                   pris[span].pri.inband_on_proceeding = conf->pri.pri.inband_on_proceeding;
12713                   ast_copy_string(pris[span].pri.initial_user_tag, conf->chan.cid_tag, sizeof(pris[span].pri.initial_user_tag));
12714                   ast_copy_string(pris[span].pri.msn_list, conf->pri.pri.msn_list, sizeof(pris[span].pri.msn_list));
12715 #if defined(HAVE_PRI_MWI)
12716                   ast_copy_string(pris[span].pri.mwi_mailboxes,
12717                      conf->pri.pri.mwi_mailboxes,
12718                      sizeof(pris[span].pri.mwi_mailboxes));
12719 #endif   /* defined(HAVE_PRI_MWI) */
12720                   ast_copy_string(pris[span].pri.idledial, conf->pri.pri.idledial, sizeof(pris[span].pri.idledial));
12721                   ast_copy_string(pris[span].pri.idleext, conf->pri.pri.idleext, sizeof(pris[span].pri.idleext));
12722                   ast_copy_string(pris[span].pri.internationalprefix, conf->pri.pri.internationalprefix, sizeof(pris[span].pri.internationalprefix));
12723                   ast_copy_string(pris[span].pri.nationalprefix, conf->pri.pri.nationalprefix, sizeof(pris[span].pri.nationalprefix));
12724                   ast_copy_string(pris[span].pri.localprefix, conf->pri.pri.localprefix, sizeof(pris[span].pri.localprefix));
12725                   ast_copy_string(pris[span].pri.privateprefix, conf->pri.pri.privateprefix, sizeof(pris[span].pri.privateprefix));
12726                   ast_copy_string(pris[span].pri.unknownprefix, conf->pri.pri.unknownprefix, sizeof(pris[span].pri.unknownprefix));
12727                   pris[span].pri.resetinterval = conf->pri.pri.resetinterval;
12728 
12729                   for (x = 0; x < PRI_MAX_TIMERS; x++) {
12730                      pris[span].pri.pritimers[x] = conf->pri.pri.pritimers[x];
12731                   }
12732 
12733 #if defined(HAVE_PRI_CALL_WAITING)
12734                   /* Channel initial config parameters. */
12735                   pris[span].pri.ch_cfg.stripmsd = conf->chan.stripmsd;
12736                   pris[span].pri.ch_cfg.hidecallerid = conf->chan.hidecallerid;
12737                   pris[span].pri.ch_cfg.hidecalleridname = conf->chan.hidecalleridname;
12738                   pris[span].pri.ch_cfg.immediate = conf->chan.immediate;
12739                   pris[span].pri.ch_cfg.priexclusive = conf->chan.priexclusive;
12740                   pris[span].pri.ch_cfg.priindication_oob = conf->chan.priindication_oob;
12741                   pris[span].pri.ch_cfg.use_callerid = conf->chan.use_callerid;
12742                   pris[span].pri.ch_cfg.use_callingpres = conf->chan.use_callingpres;
12743                   ast_copy_string(pris[span].pri.ch_cfg.context, conf->chan.context, sizeof(pris[span].pri.ch_cfg.context));
12744                   ast_copy_string(pris[span].pri.ch_cfg.mohinterpret, conf->chan.mohinterpret, sizeof(pris[span].pri.ch_cfg.mohinterpret));
12745 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
12746                } else {
12747                   ast_log(LOG_ERROR, "Channel %d is reserved for D-channel.\n", p.chanpos);
12748                   destroy_dahdi_pvt(tmp);
12749                   return NULL;
12750                }
12751             }
12752          }
12753 #endif
12754       } else {
12755          /* already exists in interface list */
12756          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));
12757          chan_sig = tmp->sig;
12758          if (tmp->subs[SUB_REAL].dfd > -1) {
12759             memset(&p, 0, sizeof(p));
12760             res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
12761          }
12762       }
12763       /* Adjust starttime on loopstart and kewlstart trunks to reasonable values */
12764       switch (chan_sig) {
12765       case SIG_FXSKS:
12766       case SIG_FXSLS:
12767       case SIG_EM:
12768       case SIG_EM_E1:
12769       case SIG_EMWINK:
12770       case SIG_FEATD:
12771       case SIG_FEATDMF:
12772       case SIG_FEATDMF_TA:
12773       case SIG_FEATB:
12774       case SIG_E911:
12775       case SIG_SF:
12776       case SIG_SFWINK:
12777       case SIG_FGC_CAMA:
12778       case SIG_FGC_CAMAMF:
12779       case SIG_SF_FEATD:
12780       case SIG_SF_FEATDMF:
12781       case SIG_SF_FEATB:
12782          p.starttime = 250;
12783          break;
12784       }
12785 
12786       if (tmp->radio) {
12787          /* XXX Waiting to hear back from Jim if these should be adjustable XXX */
12788          p.channo = channel;
12789          p.rxwinktime = 1;
12790          p.rxflashtime = 1;
12791          p.starttime = 1;
12792          p.debouncetime = 5;
12793       } else {
12794          p.channo = channel;
12795          /* Override timing settings based on config file */
12796          if (conf->timing.prewinktime >= 0)
12797             p.prewinktime = conf->timing.prewinktime;
12798          if (conf->timing.preflashtime >= 0)
12799             p.preflashtime = conf->timing.preflashtime;
12800          if (conf->timing.winktime >= 0)
12801             p.winktime = conf->timing.winktime;
12802          if (conf->timing.flashtime >= 0)
12803             p.flashtime = conf->timing.flashtime;
12804          if (conf->timing.starttime >= 0)
12805             p.starttime = conf->timing.starttime;
12806          if (conf->timing.rxwinktime >= 0)
12807             p.rxwinktime = conf->timing.rxwinktime;
12808          if (conf->timing.rxflashtime >= 0)
12809             p.rxflashtime = conf->timing.rxflashtime;
12810          if (conf->timing.debouncetime >= 0)
12811             p.debouncetime = conf->timing.debouncetime;
12812       }
12813 
12814       /* don't set parms on a pseudo-channel */
12815       if (tmp->subs[SUB_REAL].dfd >= 0)
12816       {
12817          res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_PARAMS, &p);
12818          if (res < 0) {
12819             ast_log(LOG_ERROR, "Unable to set parameters: %s\n", strerror(errno));
12820             destroy_dahdi_pvt(tmp);
12821             return NULL;
12822          }
12823       }
12824 #if 1
12825       if (!here && (tmp->subs[SUB_REAL].dfd > -1)) {
12826          memset(&bi, 0, sizeof(bi));
12827          res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
12828          if (!res) {
12829             bi.txbufpolicy = conf->chan.buf_policy;
12830             bi.rxbufpolicy = conf->chan.buf_policy;
12831             bi.numbufs = conf->chan.buf_no;
12832             res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
12833             if (res < 0) {
12834                ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", channel, strerror(errno));
12835             }
12836          } else {
12837             ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", channel, strerror(errno));
12838          }
12839          tmp->buf_policy = conf->chan.buf_policy;
12840          tmp->buf_no = conf->chan.buf_no;
12841          tmp->usefaxbuffers = conf->chan.usefaxbuffers;
12842          tmp->faxbuf_policy = conf->chan.faxbuf_policy;
12843          tmp->faxbuf_no = conf->chan.faxbuf_no;
12844          /* This is not as gnarly as it may first appear.  If the ioctl above failed, we'd be setting
12845           * tmp->bufsize to zero which would cause subsequent faxbuffer-related ioctl calls to fail.
12846           * The reason the ioctl call above failed should to be determined before worrying about the
12847           * faxbuffer-related ioctl calls */
12848          tmp->bufsize = bi.bufsize;
12849       }
12850 #endif
12851       tmp->immediate = conf->chan.immediate;
12852       tmp->transfertobusy = conf->chan.transfertobusy;
12853       if (chan_sig & __DAHDI_SIG_FXS) {
12854          tmp->mwimonitor_fsk = conf->chan.mwimonitor_fsk;
12855          tmp->mwimonitor_neon = conf->chan.mwimonitor_neon;
12856          tmp->mwimonitor_rpas = conf->chan.mwimonitor_rpas;
12857       }
12858       tmp->ringt_base = ringt_base;
12859       tmp->firstradio = 0;
12860       if ((chan_sig == SIG_FXOKS) || (chan_sig == SIG_FXOLS) || (chan_sig == SIG_FXOGS))
12861          tmp->permcallwaiting = conf->chan.callwaiting;
12862       else
12863          tmp->permcallwaiting = 0;
12864       /* Flag to destroy the channel must be cleared on new mkif.  Part of changes for reload to work */
12865       tmp->destroy = 0;
12866       tmp->drings = conf->chan.drings;
12867 
12868       /* 10 is a nice default. */
12869       if (tmp->drings.ringnum[0].range == 0)
12870          tmp->drings.ringnum[0].range = 10;
12871       if (tmp->drings.ringnum[1].range == 0)
12872          tmp->drings.ringnum[1].range = 10;
12873       if (tmp->drings.ringnum[2].range == 0)
12874          tmp->drings.ringnum[2].range = 10;
12875 
12876       tmp->usedistinctiveringdetection = usedistinctiveringdetection;
12877       tmp->callwaitingcallerid = conf->chan.callwaitingcallerid;
12878       tmp->threewaycalling = conf->chan.threewaycalling;
12879       tmp->adsi = conf->chan.adsi;
12880       tmp->use_smdi = conf->chan.use_smdi;
12881       tmp->permhidecallerid = conf->chan.hidecallerid;
12882       tmp->hidecalleridname = conf->chan.hidecalleridname;
12883       tmp->callreturn = conf->chan.callreturn;
12884       tmp->echocancel = conf->chan.echocancel;
12885       tmp->echotraining = conf->chan.echotraining;
12886       tmp->pulse = conf->chan.pulse;
12887       if (tmp->echocancel.head.tap_length) {
12888          tmp->echocanbridged = conf->chan.echocanbridged;
12889       } else {
12890          if (conf->chan.echocanbridged)
12891             ast_log(LOG_NOTICE, "echocancelwhenbridged requires echocancel to be enabled; ignoring\n");
12892          tmp->echocanbridged = 0;
12893       }
12894       tmp->busydetect = conf->chan.busydetect;
12895       tmp->busycount = conf->chan.busycount;
12896       tmp->busy_tonelength = conf->chan.busy_tonelength;
12897       tmp->busy_quietlength = conf->chan.busy_quietlength;
12898       tmp->callprogress = conf->chan.callprogress;
12899       tmp->waitfordialtone = conf->chan.waitfordialtone;
12900       tmp->cancallforward = conf->chan.cancallforward;
12901       tmp->dtmfrelax = conf->chan.dtmfrelax;
12902       tmp->callwaiting = tmp->permcallwaiting;
12903       tmp->hidecallerid = tmp->permhidecallerid;
12904       tmp->channel = channel;
12905       tmp->stripmsd = conf->chan.stripmsd;
12906       tmp->use_callerid = conf->chan.use_callerid;
12907       tmp->cid_signalling = conf->chan.cid_signalling;
12908       tmp->cid_start = conf->chan.cid_start;
12909       tmp->dahditrcallerid = conf->chan.dahditrcallerid;
12910       tmp->restrictcid = conf->chan.restrictcid;
12911       tmp->use_callingpres = conf->chan.use_callingpres;
12912       if (tmp->usedistinctiveringdetection) {
12913          if (!tmp->use_callerid) {
12914             ast_log(LOG_NOTICE, "Distinctive Ring detect requires 'usecallerid' be on\n");
12915             tmp->use_callerid = 1;
12916          }
12917       }
12918 
12919       if (tmp->cid_signalling == CID_SIG_SMDI) {
12920          if (!tmp->use_smdi) {
12921             ast_log(LOG_WARNING, "SMDI callerid requires SMDI to be enabled, enabling...\n");
12922             tmp->use_smdi = 1;
12923          }
12924       }
12925       if (tmp->use_smdi) {
12926          tmp->smdi_iface = ast_smdi_interface_find(conf->smdi_port);
12927          if (!(tmp->smdi_iface)) {
12928             ast_log(LOG_ERROR, "Invalid SMDI port specfied, disabling SMDI support\n");
12929             tmp->use_smdi = 0;
12930          }
12931       }
12932 
12933       ast_copy_string(tmp->accountcode, conf->chan.accountcode, sizeof(tmp->accountcode));
12934       tmp->amaflags = conf->chan.amaflags;
12935       if (!here) {
12936          tmp->confno = -1;
12937          tmp->propconfno = -1;
12938       }
12939       tmp->canpark = conf->chan.canpark;
12940       tmp->transfer = conf->chan.transfer;
12941       ast_copy_string(tmp->defcontext,conf->chan.context,sizeof(tmp->defcontext));
12942       ast_copy_string(tmp->language, conf->chan.language, sizeof(tmp->language));
12943       ast_copy_string(tmp->mohinterpret, conf->chan.mohinterpret, sizeof(tmp->mohinterpret));
12944       ast_copy_string(tmp->mohsuggest, conf->chan.mohsuggest, sizeof(tmp->mohsuggest));
12945       ast_copy_string(tmp->context, conf->chan.context, sizeof(tmp->context));
12946       ast_copy_string(tmp->parkinglot, conf->chan.parkinglot, sizeof(tmp->parkinglot));
12947       tmp->cid_ton = 0;
12948       if (analog_lib_handles(tmp->sig, tmp->radio, tmp->oprmode)) {
12949          ast_copy_string(tmp->cid_num, conf->chan.cid_num, sizeof(tmp->cid_num));
12950          ast_copy_string(tmp->cid_name, conf->chan.cid_name, sizeof(tmp->cid_name));
12951       } else {
12952          tmp->cid_num[0] = '\0';
12953          tmp->cid_name[0] = '\0';
12954       }
12955 #if defined(HAVE_PRI)
12956       if (dahdi_sig_pri_lib_handles(tmp->sig)) {
12957          tmp->cid_tag[0] = '\0';
12958       } else
12959 #endif   /* defined(HAVE_PRI) */
12960       {
12961          ast_copy_string(tmp->cid_tag, conf->chan.cid_tag, sizeof(tmp->cid_tag));
12962       }
12963       tmp->cid_subaddr[0] = '\0';
12964       ast_copy_string(tmp->mailbox, conf->chan.mailbox, sizeof(tmp->mailbox));
12965       if (channel != CHAN_PSEUDO && !ast_strlen_zero(tmp->mailbox)) {
12966          char *mailbox, *context;
12967          mailbox = context = ast_strdupa(tmp->mailbox);
12968          strsep(&context, "@");
12969          if (ast_strlen_zero(context))
12970             context = "default";
12971          tmp->mwi_event_sub = ast_event_subscribe(AST_EVENT_MWI, mwi_event_cb, "Dahdi MWI subscription", NULL,
12972             AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
12973             AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
12974             AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS,
12975             AST_EVENT_IE_END);
12976       }
12977 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
12978       tmp->mwisend_setting = conf->chan.mwisend_setting;
12979       tmp->mwisend_fsk  = conf->chan.mwisend_fsk;
12980       tmp->mwisend_rpas = conf->chan.mwisend_rpas;
12981 #endif
12982 
12983       tmp->group = conf->chan.group;
12984       tmp->callgroup = conf->chan.callgroup;
12985       tmp->pickupgroup= conf->chan.pickupgroup;
12986       if (conf->chan.vars) {
12987          struct ast_variable *v, *tmpvar;
12988                    for (v = conf->chan.vars ; v ; v = v->next) {
12989                          if ((tmpvar = ast_variable_new(v->name, v->value, v->file))) {
12990                                   tmpvar->next = tmp->vars;
12991                                    tmp->vars = tmpvar;
12992                            }
12993                   }
12994       }
12995       tmp->cid_rxgain = conf->chan.cid_rxgain;
12996       tmp->rxgain = conf->chan.rxgain;
12997       tmp->txgain = conf->chan.txgain;
12998       tmp->txdrc = conf->chan.txdrc;
12999       tmp->rxdrc = conf->chan.rxdrc;
13000       tmp->tonezone = conf->chan.tonezone;
13001       if (tmp->subs[SUB_REAL].dfd > -1) {
13002          set_actual_gain(tmp->subs[SUB_REAL].dfd, tmp->rxgain, tmp->txgain, tmp->rxdrc, tmp->txdrc, tmp->law);
13003          if (tmp->dsp)
13004             ast_dsp_set_digitmode(tmp->dsp, DSP_DIGITMODE_DTMF | tmp->dtmfrelax);
13005          update_conf(tmp);
13006          if (!here) {
13007             switch (chan_sig) {
13008             case SIG_PRI_LIB_HANDLE_CASES:
13009             case SIG_SS7:
13010             case SIG_MFCR2:
13011                break;
13012             default:
13013                /* Hang it up to be sure it's good */
13014                dahdi_set_hook(tmp->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
13015                break;
13016             }
13017          }
13018          ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SETTONEZONE,&tmp->tonezone);
13019          if ((res = get_alarms(tmp)) != DAHDI_ALARM_NONE) {
13020             /* the dchannel is down so put the channel in alarm */
13021             switch (tmp->sig) {
13022 #ifdef HAVE_PRI
13023             case SIG_PRI_LIB_HANDLE_CASES:
13024                sig_pri_set_alarm(tmp->sig_pvt, 1);
13025                break;
13026 #endif
13027 #if defined(HAVE_SS7)
13028             case SIG_SS7:
13029                sig_ss7_set_alarm(tmp->sig_pvt, 1);
13030                break;
13031 #endif   /* defined(HAVE_SS7) */
13032             default:
13033                /* The only sig submodule left should be sig_analog. */
13034                analog_p = tmp->sig_pvt;
13035                if (analog_p) {
13036                   analog_p->inalarm = 1;
13037                }
13038                tmp->inalarm = 1;
13039                break;
13040             }
13041             handle_alarms(tmp, res);
13042          }
13043       }
13044 
13045       tmp->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
13046       tmp->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
13047       tmp->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
13048       tmp->sendcalleridafter = conf->chan.sendcalleridafter;
13049       ast_cc_copy_config_params(tmp->cc_params, conf->chan.cc_params);
13050 
13051       if (!here) {
13052          tmp->locallyblocked = 0;
13053          tmp->remotelyblocked = 0;
13054          switch (tmp->sig) {
13055 #if defined(HAVE_PRI)
13056          case SIG_PRI_LIB_HANDLE_CASES:
13057             tmp->inservice = 1;/* Inservice until actually implemented. */
13058 #if defined(HAVE_PRI_SERVICE_MESSAGES)
13059             ((struct sig_pri_chan *) tmp->sig_pvt)->service_status = 0;
13060             if (chan_sig == SIG_PRI) {
13061                char db_chan_name[20];
13062                char db_answer[5];
13063 
13064                /*
13065                 * Initialize the active out-of-service status
13066                 * and delete any record if the feature is not enabled.
13067                 */
13068                snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, tmp->span, tmp->channel);
13069                if (!ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) {
13070                   unsigned *why;
13071 
13072                   why = &((struct sig_pri_chan *) tmp->sig_pvt)->service_status;
13073                   if (tmp->pri->enable_service_message_support) {
13074                      char state;
13075 
13076                      sscanf(db_answer, "%1c:%30u", &state, why);
13077 
13078                      /* Ensure that only the implemented bits could be set.*/
13079                      *why &= (SRVST_NEAREND | SRVST_FAREND);
13080                   }
13081                   if (!*why) {
13082                      ast_db_del(db_chan_name, SRVST_DBKEY);
13083                   }
13084                }
13085             }
13086 #endif   /* defined(HAVE_PRI_SERVICE_MESSAGES) */
13087             break;
13088 #endif   /* defined(HAVE_PRI) */
13089 #if defined(HAVE_SS7)
13090          case SIG_SS7:
13091             tmp->inservice = 0;
13092             break;
13093 #endif   /* defined(HAVE_SS7) */
13094          default:
13095              /* We default to in service on protocols that don't have a reset */
13096             tmp->inservice = 1;
13097             break;
13098          }
13099       }
13100 
13101       switch (tmp->sig) {
13102 #if defined(HAVE_PRI)
13103       case SIG_PRI_LIB_HANDLE_CASES:
13104          if (pri_chan) {
13105             pri_chan->channel = tmp->channel;
13106             pri_chan->hidecallerid = tmp->hidecallerid;
13107             pri_chan->hidecalleridname = tmp->hidecalleridname;
13108             pri_chan->immediate = tmp->immediate;
13109             pri_chan->inalarm = tmp->inalarm;
13110             pri_chan->priexclusive = tmp->priexclusive;
13111             pri_chan->priindication_oob = tmp->priindication_oob;
13112             pri_chan->use_callerid = tmp->use_callerid;
13113             pri_chan->use_callingpres = tmp->use_callingpres;
13114             ast_copy_string(pri_chan->context, tmp->context,
13115                sizeof(pri_chan->context));
13116             ast_copy_string(pri_chan->mohinterpret, tmp->mohinterpret,
13117                sizeof(pri_chan->mohinterpret));
13118             pri_chan->stripmsd = tmp->stripmsd;
13119          }
13120          break;
13121 #endif   /* defined(HAVE_PRI) */
13122 #if defined(HAVE_SS7)
13123       case SIG_SS7:
13124          if (ss7_chan) {
13125             ss7_chan->inalarm = tmp->inalarm;
13126 
13127             ss7_chan->stripmsd = tmp->stripmsd;
13128             ss7_chan->hidecallerid = tmp->hidecallerid;
13129             ss7_chan->use_callerid = tmp->use_callerid;
13130             ss7_chan->use_callingpres = tmp->use_callingpres;
13131             ss7_chan->immediate = tmp->immediate;
13132             ss7_chan->locallyblocked = tmp->locallyblocked;
13133             ss7_chan->remotelyblocked = tmp->remotelyblocked;
13134             ast_copy_string(ss7_chan->context, tmp->context,
13135                sizeof(ss7_chan->context));
13136             ast_copy_string(ss7_chan->mohinterpret, tmp->mohinterpret,
13137                sizeof(ss7_chan->mohinterpret));
13138          }
13139          break;
13140 #endif   /* defined(HAVE_SS7) */
13141       default:
13142          /* The only sig submodule left should be sig_analog. */
13143          analog_p = tmp->sig_pvt;
13144          if (analog_p) {
13145             analog_p->channel = tmp->channel;
13146             analog_p->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
13147             analog_p->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
13148             analog_p->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
13149             analog_p->permcallwaiting = conf->chan.callwaiting; /* permcallwaiting possibly modified in analog_config_complete */
13150             analog_p->callreturn = conf->chan.callreturn;
13151             analog_p->cancallforward = conf->chan.cancallforward;
13152             analog_p->canpark = conf->chan.canpark;
13153             analog_p->dahditrcallerid = conf->chan.dahditrcallerid;
13154             analog_p->immediate = conf->chan.immediate;
13155             analog_p->permhidecallerid = conf->chan.permhidecallerid;
13156             analog_p->pulse = conf->chan.pulse;
13157             analog_p->threewaycalling = conf->chan.threewaycalling;
13158             analog_p->transfer = conf->chan.transfer;
13159             analog_p->transfertobusy = conf->chan.transfertobusy;
13160             analog_p->use_callerid = tmp->use_callerid;
13161             analog_p->use_smdi = tmp->use_smdi;
13162             analog_p->smdi_iface = tmp->smdi_iface;
13163             analog_p->outsigmod = ANALOG_SIG_NONE;
13164             analog_p->echotraining = conf->chan.echotraining;
13165             analog_p->cid_signalling = conf->chan.cid_signalling;
13166             analog_p->stripmsd = conf->chan.stripmsd;
13167             switch (conf->chan.cid_start) {
13168             case CID_START_POLARITY:
13169                analog_p->cid_start = ANALOG_CID_START_POLARITY;
13170                break;
13171             case CID_START_POLARITY_IN:
13172                analog_p->cid_start = ANALOG_CID_START_POLARITY_IN;
13173                break;
13174             case CID_START_DTMF_NOALERT:
13175                analog_p->cid_start = ANALOG_CID_START_DTMF_NOALERT;
13176                break;
13177             default:
13178                analog_p->cid_start = ANALOG_CID_START_RING;
13179                break;
13180             }
13181             analog_p->callwaitingcallerid = conf->chan.callwaitingcallerid;
13182             analog_p->ringt = conf->chan.ringt;
13183             analog_p->ringt_base = ringt_base;
13184             analog_p->onhooktime = time(NULL);
13185             if (chan_sig & __DAHDI_SIG_FXO) {
13186                memset(&p, 0, sizeof(p));
13187                res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
13188                if (!res) {
13189                   analog_p->fxsoffhookstate = p.rxisoffhook;
13190                }
13191 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
13192                res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_VMWI_CONFIG, &tmp->mwisend_setting);
13193 #endif
13194             }
13195             analog_p->msgstate = -1;
13196 
13197             ast_copy_string(analog_p->mohsuggest, conf->chan.mohsuggest, sizeof(analog_p->mohsuggest));
13198             ast_copy_string(analog_p->cid_num, conf->chan.cid_num, sizeof(analog_p->cid_num));
13199             ast_copy_string(analog_p->cid_name, conf->chan.cid_name, sizeof(analog_p->cid_name));
13200 
13201             analog_config_complete(analog_p);
13202          }
13203          break;
13204       }
13205 #if defined(HAVE_PRI)
13206       if (tmp->channel == CHAN_PSEUDO) {
13207          /*
13208           * Save off pseudo channel buffer policy values for dynamic creation of
13209           * no B channel interfaces.
13210           */
13211          dahdi_pseudo_parms.buf_no = tmp->buf_no;
13212          dahdi_pseudo_parms.buf_policy = tmp->buf_policy;
13213          dahdi_pseudo_parms.faxbuf_no = tmp->faxbuf_no;
13214          dahdi_pseudo_parms.faxbuf_policy = tmp->faxbuf_policy;
13215       }
13216 #endif   /* defined(HAVE_PRI) */
13217    }
13218    if (tmp && !here) {
13219       /* Add the new channel interface to the sorted channel interface list. */
13220       dahdi_iflist_insert(tmp);
13221    }
13222    return tmp;
13223 }
13224 
13225 static int is_group_or_channel_match(struct dahdi_pvt *p, int span, ast_group_t groupmatch, int *groupmatched, int channelmatch, int *channelmatched)
13226 {
13227 #if defined(HAVE_PRI)
13228    if (0 < span) {
13229       /* The channel must be on the specified PRI span. */
13230       if (!p->pri || p->pri->span != span) {
13231          return 0;
13232       }
13233       if (!groupmatch && channelmatch == -1) {
13234          /* Match any group since it only needs to be on the PRI span. */
13235          *groupmatched = 1;
13236          return 1;
13237       }
13238    }
13239 #endif   /* defined(HAVE_PRI) */
13240    /* check group matching */
13241    if (groupmatch) {
13242       if ((p->group & groupmatch) != groupmatch)
13243          /* Doesn't match the specified group, try the next one */
13244          return 0;
13245       *groupmatched = 1;
13246    }
13247    /* Check to see if we have a channel match */
13248    if (channelmatch != -1) {
13249       if (p->channel != channelmatch)
13250          /* Doesn't match the specified channel, try the next one */
13251          return 0;
13252       *channelmatched = 1;
13253    }
13254 
13255    return 1;
13256 }
13257 
13258 static int available(struct dahdi_pvt **pvt, int is_specific_channel)
13259 {
13260    struct dahdi_pvt *p = *pvt;
13261 
13262    if (p->inalarm)
13263       return 0;
13264 
13265    if (analog_lib_handles(p->sig, p->radio, p->oprmode))
13266       return analog_available(p->sig_pvt);
13267 
13268    switch (p->sig) {
13269 #if defined(HAVE_PRI)
13270    case SIG_PRI_LIB_HANDLE_CASES:
13271       {
13272          struct sig_pri_chan *pvt_chan;
13273          int res;
13274 
13275          pvt_chan = p->sig_pvt;
13276          res = sig_pri_available(&pvt_chan, is_specific_channel);
13277          *pvt = pvt_chan->chan_pvt;
13278          return res;
13279       }
13280 #endif   /* defined(HAVE_PRI) */
13281 #if defined(HAVE_SS7)
13282    case SIG_SS7:
13283       return sig_ss7_available(p->sig_pvt);
13284 #endif   /* defined(HAVE_SS7) */
13285    default:
13286       break;
13287    }
13288 
13289    if (p->locallyblocked || p->remotelyblocked) {
13290       return 0;
13291    }
13292 
13293    /* If no owner definitely available */
13294    if (!p->owner) {
13295 #ifdef HAVE_OPENR2
13296       /* Trust MFC/R2 */
13297       if (p->mfcr2) {
13298          if (p->mfcr2call) {
13299             return 0;
13300          } else {
13301             return 1;
13302          }
13303       }
13304 #endif
13305       return 1;
13306    }
13307 
13308    return 0;
13309 }
13310 
13311 #if defined(HAVE_PRI)
13312 #if defined(HAVE_PRI_CALL_WAITING)
13313 /*!
13314  * \internal
13315  * \brief Init the private channel configuration using the span controller.
13316  * \since 1.8
13317  *
13318  * \param priv Channel to init the configuration.
13319  * \param pri sig_pri PRI control structure.
13320  *
13321  * \note Assumes the pri->lock is already obtained.
13322  *
13323  * \return Nothing
13324  */
13325 static void my_pri_init_config(void *priv, struct sig_pri_span *pri)
13326 {
13327    struct dahdi_pvt *pvt = priv;
13328 
13329    pvt->stripmsd = pri->ch_cfg.stripmsd;
13330    pvt->hidecallerid = pri->ch_cfg.hidecallerid;
13331    pvt->hidecalleridname = pri->ch_cfg.hidecalleridname;
13332    pvt->immediate = pri->ch_cfg.immediate;
13333    pvt->priexclusive = pri->ch_cfg.priexclusive;
13334    pvt->priindication_oob = pri->ch_cfg.priindication_oob;
13335    pvt->use_callerid = pri->ch_cfg.use_callerid;
13336    pvt->use_callingpres = pri->ch_cfg.use_callingpres;
13337    ast_copy_string(pvt->context, pri->ch_cfg.context, sizeof(pvt->context));
13338    ast_copy_string(pvt->mohinterpret, pri->ch_cfg.mohinterpret, sizeof(pvt->mohinterpret));
13339 }
13340 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
13341 #endif   /* defined(HAVE_PRI) */
13342 
13343 #if defined(HAVE_PRI)
13344 /*!
13345  * \internal
13346  * \brief Create a no B channel interface.
13347  * \since 1.8
13348  *
13349  * \param pri sig_pri span controller to add interface.
13350  *
13351  * \note Assumes the pri->lock is already obtained.
13352  *
13353  * \retval array-index into private pointer array on success.
13354  * \retval -1 on error.
13355  */
13356 static int dahdi_new_pri_nobch_channel(struct sig_pri_span *pri)
13357 {
13358    int pvt_idx;
13359    int res;
13360    unsigned idx;
13361    struct dahdi_pvt *pvt;
13362    struct sig_pri_chan *chan;
13363    struct dahdi_bufferinfo bi;
13364 
13365    static int nobch_channel = CHAN_PSEUDO;
13366 
13367    /* Find spot in the private pointer array for new interface. */
13368    for (pvt_idx = 0; pvt_idx < pri->numchans; ++pvt_idx) {
13369       if (!pri->pvts[pvt_idx]) {
13370          break;
13371       }
13372    }
13373    if (pri->numchans == pvt_idx) {
13374       if (ARRAY_LEN(pri->pvts) <= pvt_idx) {
13375          ast_log(LOG_ERROR, "Unable to add a no-B-channel interface!\n");
13376          return -1;
13377       }
13378 
13379       /* Add new spot to the private pointer array. */
13380       pri->pvts[pvt_idx] = NULL;
13381       ++pri->numchans;
13382    }
13383 
13384    pvt = ast_calloc(1, sizeof(*pvt));
13385    if (!pvt) {
13386       return -1;
13387    }
13388    pvt->cc_params = ast_cc_config_params_init();
13389    if (!pvt->cc_params) {
13390       ast_free(pvt);
13391       return -1;
13392    }
13393    ast_mutex_init(&pvt->lock);
13394    for (idx = 0; idx < ARRAY_LEN(pvt->subs); ++idx) {
13395       pvt->subs[idx].dfd = -1;
13396    }
13397    pvt->buf_no = dahdi_pseudo_parms.buf_no;
13398    pvt->buf_policy = dahdi_pseudo_parms.buf_policy;
13399    pvt->faxbuf_no = dahdi_pseudo_parms.faxbuf_no;
13400    pvt->faxbuf_policy = dahdi_pseudo_parms.faxbuf_policy;
13401 
13402    chan = sig_pri_chan_new(pvt, &dahdi_pri_callbacks, pri, 0, 0, 0);
13403    if (!chan) {
13404       destroy_dahdi_pvt(pvt);
13405       return -1;
13406    }
13407    chan->no_b_channel = 1;
13408 
13409    /*
13410     * Pseudo channel companding law.
13411     * Needed for outgoing call waiting calls.
13412     * XXX May need to make this determined by switchtype or user option.
13413     */
13414    pvt->law_default = DAHDI_LAW_ALAW;
13415 
13416    pvt->sig = pri->sig;
13417    pvt->outsigmod = -1;
13418    pvt->pri = pri;
13419    pvt->sig_pvt = chan;
13420    pri->pvts[pvt_idx] = chan;
13421 
13422    pvt->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo");
13423    if (pvt->subs[SUB_REAL].dfd < 0) {
13424       ast_log(LOG_ERROR, "Unable to open no B channel interface pseudo channel: %s\n",
13425          strerror(errno));
13426       destroy_dahdi_pvt(pvt);
13427       return -1;
13428    }
13429    memset(&bi, 0, sizeof(bi));
13430    res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
13431    if (!res) {
13432       pvt->bufsize = bi.bufsize;
13433       bi.txbufpolicy = pvt->buf_policy;
13434       bi.rxbufpolicy = pvt->buf_policy;
13435       bi.numbufs = pvt->buf_no;
13436       res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
13437       if (res < 0) {
13438          ast_log(LOG_WARNING,
13439             "Unable to set buffer policy on no B channel interface: %s\n",
13440             strerror(errno));
13441       }
13442    } else
13443       ast_log(LOG_WARNING,
13444          "Unable to check buffer policy on no B channel interface: %s\n",
13445          strerror(errno));
13446 
13447    --nobch_channel;
13448    if (CHAN_PSEUDO < nobch_channel) {
13449       nobch_channel = CHAN_PSEUDO - 1;
13450    }
13451    pvt->channel = nobch_channel;
13452    pvt->span = pri->span;
13453    chan->channel = pvt->channel;
13454 
13455    dahdi_nobch_insert(pri, pvt);
13456 
13457    return pvt_idx;
13458 }
13459 #endif   /* defined(HAVE_PRI) */
13460 
13461 /* This function can *ONLY* be used for copying pseudo (CHAN_PSEUDO) private
13462    structures; it makes no attempt to safely copy regular channel private
13463    structures that might contain reference-counted object pointers and other
13464    scary bits
13465 */
13466 static struct dahdi_pvt *duplicate_pseudo(struct dahdi_pvt *src)
13467 {
13468    struct dahdi_pvt *p;
13469    struct dahdi_bufferinfo bi;
13470    int res;
13471 
13472    p = ast_malloc(sizeof(*p));
13473    if (!p) {
13474       return NULL;
13475    }
13476    *p = *src;
13477 
13478    /* Must deep copy the cc_params. */
13479    p->cc_params = ast_cc_config_params_init();
13480    if (!p->cc_params) {
13481       ast_free(p);
13482       return NULL;
13483    }
13484    ast_cc_copy_config_params(p->cc_params, src->cc_params);
13485 
13486    p->which_iflist = DAHDI_IFLIST_NONE;
13487    p->next = NULL;
13488    p->prev = NULL;
13489    ast_mutex_init(&p->lock);
13490    p->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo");
13491    if (p->subs[SUB_REAL].dfd < 0) {
13492       ast_log(LOG_ERROR, "Unable to dup channel: %s\n", strerror(errno));
13493       destroy_dahdi_pvt(p);
13494       return NULL;
13495    }
13496    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
13497    if (!res) {
13498       bi.txbufpolicy = src->buf_policy;
13499       bi.rxbufpolicy = src->buf_policy;
13500       bi.numbufs = src->buf_no;
13501       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
13502       if (res < 0) {
13503          ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel: %s\n", strerror(errno));
13504       }
13505    } else
13506       ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel: %s\n", strerror(errno));
13507    p->destroy = 1;
13508    dahdi_iflist_insert(p);
13509    return p;
13510 }
13511 
13512 struct dahdi_starting_point {
13513    /*! Group matching mask.  Zero if not specified. */
13514    ast_group_t groupmatch;
13515    /*! DAHDI channel to match with.  -1 if not specified. */
13516    int channelmatch;
13517    /*! Round robin saved search location index. (Valid if roundrobin TRUE) */
13518    int rr_starting_point;
13519    /*! ISDN span where channels can be picked (Zero if not specified) */
13520    int span;
13521    /*! Analog channel distinctive ring cadance index. */
13522    int cadance;
13523    /*! Dialing option. c/r/d if present and valid. */
13524    char opt;
13525    /*! TRUE if to search the channel list backwards. */
13526    char backwards;
13527    /*! TRUE if search is done with round robin sequence. */
13528    char roundrobin;
13529 };
13530 static struct dahdi_pvt *determine_starting_point(const char *data, struct dahdi_starting_point *param)
13531 {
13532    char *dest;
13533    char *s;
13534    int x;
13535    int res = 0;
13536    struct dahdi_pvt *p;
13537    char *subdir = NULL;
13538    AST_DECLARE_APP_ARGS(args,
13539       AST_APP_ARG(group);  /* channel/group token */
13540       //AST_APP_ARG(ext);  /* extension token */
13541       //AST_APP_ARG(opts); /* options token */
13542       AST_APP_ARG(other);  /* Any remining unused arguments */
13543    );
13544 
13545    /*
13546     * data is ---v
13547     * Dial(DAHDI/pseudo[/extension[/options]])
13548     * Dial(DAHDI/<channel#>[c|r<cadance#>|d][/extension[/options]])
13549     * Dial(DAHDI/<subdir>!<channel#>[c|r<cadance#>|d][/extension[/options]])
13550     * Dial(DAHDI/i<span>[/extension[/options]])
13551     * Dial(DAHDI/[i<span>-](g|G|r|R)<group#(0-63)>[c|r<cadance#>|d][/extension[/options]])
13552     *
13553     * i - ISDN span channel restriction.
13554     *     Used by CC to ensure that the CC recall goes out the same span.
13555     *     Also to make ISDN channel names dialable when the sequence number
13556     *     is stripped off.  (Used by DTMF attended transfer feature.)
13557     *
13558     * g - channel group allocation search forward
13559     * G - channel group allocation search backward
13560     * r - channel group allocation round robin search forward
13561     * R - channel group allocation round robin search backward
13562     *
13563     * c - Wait for DTMF digit to confirm answer
13564     * r<cadance#> - Set distintive ring cadance number
13565     * d - Force bearer capability for ISDN/SS7 call to digital.
13566     */
13567 
13568    if (data) {
13569       dest = ast_strdupa(data);
13570    } else {
13571       ast_log(LOG_WARNING, "Channel requested with no data\n");
13572       return NULL;
13573    }
13574    AST_NONSTANDARD_APP_ARGS(args, dest, '/');
13575    if (!args.argc || ast_strlen_zero(args.group)) {
13576       ast_log(LOG_WARNING, "No channel/group specified\n");
13577       return NULL;
13578    }
13579 
13580    /* Initialize the output parameters */
13581    memset(param, 0, sizeof(*param));
13582    param->channelmatch = -1;
13583 
13584    if (strchr(args.group, '!') != NULL) {
13585       char *prev = args.group;
13586       while ((s = strchr(prev, '!')) != NULL) {
13587          *s++ = '/';
13588          prev = s;
13589       }
13590       *(prev - 1) = '\0';
13591       subdir = args.group;
13592       args.group = prev;
13593    } else if (args.group[0] == 'i') {
13594       /* Extract the ISDN span channel restriction specifier. */
13595       res = sscanf(args.group + 1, "%30d", &x);
13596       if (res < 1) {
13597          ast_log(LOG_WARNING, "Unable to determine ISDN span for data %s\n", data);
13598          return NULL;
13599       }
13600       param->span = x;
13601 
13602       /* Remove the ISDN span channel restriction specifier. */
13603       s = strchr(args.group, '-');
13604       if (!s) {
13605          /* Search all groups since we are ISDN span restricted. */
13606          return iflist;
13607       }
13608       args.group = s + 1;
13609       res = 0;
13610    }
13611    if (toupper(args.group[0]) == 'G' || toupper(args.group[0])=='R') {
13612       /* Retrieve the group number */
13613       s = args.group + 1;
13614       res = sscanf(s, "%30d%1c%30d", &x, &param->opt, &param->cadance);
13615       if (res < 1) {
13616          ast_log(LOG_WARNING, "Unable to determine group for data %s\n", data);
13617          return NULL;
13618       }
13619       param->groupmatch = ((ast_group_t) 1 << x);
13620 
13621       if (toupper(args.group[0]) == 'G') {
13622          if (args.group[0] == 'G') {
13623             param->backwards = 1;
13624             p = ifend;
13625          } else
13626             p = iflist;
13627       } else {
13628          if (ARRAY_LEN(round_robin) <= x) {
13629             ast_log(LOG_WARNING, "Round robin index %d out of range for data %s\n",
13630                x, data);
13631             return NULL;
13632          }
13633          if (args.group[0] == 'R') {
13634             param->backwards = 1;
13635             p = round_robin[x] ? round_robin[x]->prev : ifend;
13636             if (!p)
13637                p = ifend;
13638          } else {
13639             p = round_robin[x] ? round_robin[x]->next : iflist;
13640             if (!p)
13641                p = iflist;
13642          }
13643          param->roundrobin = 1;
13644          param->rr_starting_point = x;
13645       }
13646    } else {
13647       s = args.group;
13648       if (!strcasecmp(s, "pseudo")) {
13649          /* Special case for pseudo */
13650          x = CHAN_PSEUDO;
13651          param->channelmatch = x;
13652       } else {
13653          res = sscanf(s, "%30d%1c%30d", &x, &param->opt, &param->cadance);
13654          if (res < 1) {
13655             ast_log(LOG_WARNING, "Unable to determine channel for data %s\n", data);
13656             return NULL;
13657          } else {
13658             param->channelmatch = x;
13659          }
13660       }
13661       if (subdir) {
13662          char path[PATH_MAX];
13663          struct stat stbuf;
13664 
13665          snprintf(path, sizeof(path), "/dev/dahdi/%s/%d",
13666                subdir, param->channelmatch);
13667          if (stat(path, &stbuf) < 0) {
13668             ast_log(LOG_WARNING, "stat(%s) failed: %s\n",
13669                   path, strerror(errno));
13670             return NULL;
13671          }
13672          if (!S_ISCHR(stbuf.st_mode)) {
13673             ast_log(LOG_ERROR, "%s: Not a character device file\n",
13674                   path);
13675             return NULL;
13676          }
13677          param->channelmatch = minor(stbuf.st_rdev);
13678       }
13679 
13680       p = iflist;
13681    }
13682 
13683    if (param->opt == 'r' && res < 3) {
13684       ast_log(LOG_WARNING, "Distinctive ring missing identifier in '%s'\n", data);
13685       param->opt = '\0';
13686    }
13687 
13688    return p;
13689 }
13690 
13691 static struct ast_channel *dahdi_request(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause)
13692 {
13693    int callwait = 0;
13694    struct dahdi_pvt *p;
13695    struct ast_channel *tmp = NULL;
13696    struct dahdi_pvt *exitpvt;
13697    int channelmatched = 0;
13698    int groupmatched = 0;
13699 #if defined(HAVE_PRI) || defined(HAVE_SS7)
13700    int transcapdigital = 0;
13701 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
13702    struct dahdi_starting_point start;
13703 
13704    ast_mutex_lock(&iflock);
13705    p = determine_starting_point(data, &start);
13706    if (!p) {
13707       /* We couldn't determine a starting point, which likely means badly-formatted channel name. Abort! */
13708       ast_mutex_unlock(&iflock);
13709       return NULL;
13710    }
13711 
13712    /* Search for an unowned channel */
13713    exitpvt = p;
13714    while (p && !tmp) {
13715       if (start.roundrobin)
13716          round_robin[start.rr_starting_point] = p;
13717 
13718       if (is_group_or_channel_match(p, start.span, start.groupmatch, &groupmatched, start.channelmatch, &channelmatched)
13719          && available(&p, channelmatched)) {
13720          ast_debug(1, "Using channel %d\n", p->channel);
13721 
13722          callwait = (p->owner != NULL);
13723 #ifdef HAVE_OPENR2
13724          if (p->mfcr2) {
13725             ast_mutex_lock(&p->lock);
13726             if (p->mfcr2call) {
13727                ast_mutex_unlock(&p->lock);
13728                ast_log(LOG_DEBUG, "Yay!, someone just beat us in the race for channel %d.\n", p->channel);
13729                goto next;
13730             }
13731             p->mfcr2call = 1;
13732             ast_mutex_unlock(&p->lock);
13733          }
13734 #endif
13735          if (p->channel == CHAN_PSEUDO) {
13736             p = duplicate_pseudo(p);
13737             if (!p) {
13738                break;
13739             }
13740          }
13741 
13742          p->distinctivering = 0;
13743          /* Make special notes */
13744          switch (start.opt) {
13745          case '\0':
13746             /* No option present. */
13747             break;
13748          case 'c':
13749             /* Confirm answer */
13750             p->confirmanswer = 1;
13751             break;
13752          case 'r':
13753             /* Distinctive ring */
13754             p->distinctivering = start.cadance;
13755             break;
13756          case 'd':
13757 #if defined(HAVE_PRI) || defined(HAVE_SS7)
13758             /* If this is an ISDN call, make it digital */
13759             transcapdigital = AST_TRANS_CAP_DIGITAL;
13760 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
13761             break;
13762          default:
13763             ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", start.opt, (char *)data);
13764             break;
13765          }
13766 
13767          p->outgoing = 1;
13768          if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
13769             tmp = analog_request(p->sig_pvt, &callwait, requestor);
13770 #ifdef HAVE_PRI
13771          } else if (dahdi_sig_pri_lib_handles(p->sig)) {
13772             /*
13773              * We already have the B channel reserved for this call.  We
13774              * just need to make sure that dahdi_hangup() has completed
13775              * cleaning up before continuing.
13776              */
13777             ast_mutex_lock(&p->lock);
13778             ast_mutex_unlock(&p->lock);
13779 
13780             sig_pri_extract_called_num_subaddr(p->sig_pvt, data, p->dnid,
13781                sizeof(p->dnid));
13782             tmp = sig_pri_request(p->sig_pvt, SIG_PRI_DEFLAW, requestor, transcapdigital);
13783 #endif
13784 #if defined(HAVE_SS7)
13785          } else if (p->sig == SIG_SS7) {
13786             tmp = sig_ss7_request(p->sig_pvt, SIG_SS7_DEFLAW, requestor, transcapdigital);
13787 #endif   /* defined(HAVE_SS7) */
13788          } else {
13789             tmp = dahdi_new(p, AST_STATE_RESERVED, 0, p->owner ? SUB_CALLWAIT : SUB_REAL, 0, requestor ? requestor->linkedid : "");
13790          }
13791          if (!tmp) {
13792             p->outgoing = 0;
13793 #if defined(HAVE_PRI)
13794             switch (p->sig) {
13795             case SIG_PRI_LIB_HANDLE_CASES:
13796 #if defined(HAVE_PRI_CALL_WAITING)
13797                if (((struct sig_pri_chan *) p->sig_pvt)->is_call_waiting) {
13798                   ((struct sig_pri_chan *) p->sig_pvt)->is_call_waiting = 0;
13799                   ast_atomic_fetchadd_int(&p->pri->num_call_waiting_calls, -1);
13800                }
13801 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
13802                /*
13803                 * This should be the last thing to clear when we are done with
13804                 * the channel.
13805                 */
13806                ((struct sig_pri_chan *) p->sig_pvt)->allocated = 0;
13807                break;
13808             default:
13809                break;
13810             }
13811 #endif   /* defined(HAVE_PRI) */
13812          } else {
13813             snprintf(p->dialstring, sizeof(p->dialstring), "DAHDI/%s", (char *) data);
13814          }
13815          break;
13816       }
13817 #ifdef HAVE_OPENR2
13818 next:
13819 #endif
13820       if (start.backwards) {
13821          p = p->prev;
13822          if (!p)
13823             p = ifend;
13824       } else {
13825          p = p->next;
13826          if (!p)
13827             p = iflist;
13828       }
13829       /* stop when you roll to the one that we started from */
13830       if (p == exitpvt)
13831          break;
13832    }
13833    ast_mutex_unlock(&iflock);
13834    restart_monitor();
13835    if (cause && !tmp) {
13836       if (callwait || channelmatched) {
13837          *cause = AST_CAUSE_BUSY;
13838       } else if (groupmatched) {
13839          *cause = AST_CAUSE_CONGESTION;
13840       } else {
13841          /*
13842           * We did not match any channel requested.
13843           * Dialplan error requesting non-existant channel?
13844           */
13845       }
13846    }
13847 
13848    return tmp;
13849 }
13850 
13851 /*!
13852  * \internal
13853  * \brief Determine the device state for a given DAHDI device if we can.
13854  * \since 1.8
13855  *
13856  * \param data DAHDI device name after "DAHDI/".
13857  *
13858  * \retval device_state enum ast_device_state value.
13859  * \retval AST_DEVICE_UNKNOWN if we could not determine the device's state.
13860  */
13861 static int dahdi_devicestate(void *data)
13862 {
13863 #if defined(HAVE_PRI)
13864    char *device;
13865    unsigned span;
13866    int res;
13867 
13868    device = data;
13869 
13870    if (*device != 'I') {
13871       /* The request is not for an ISDN span device. */
13872       return AST_DEVICE_UNKNOWN;
13873    }
13874    res = sscanf(device, "I%30u", &span);
13875    if (res != 1 || !span || NUM_SPANS < span) {
13876       /* Bad format for ISDN span device name. */
13877       return AST_DEVICE_UNKNOWN;
13878    }
13879    device = strchr(device, '/');
13880    if (!device) {
13881       /* Bad format for ISDN span device name. */
13882       return AST_DEVICE_UNKNOWN;
13883    }
13884 
13885    /*
13886     * Since there are currently no other span devstate's defined,
13887     * it must be congestion.
13888     */
13889 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
13890    ++device;
13891    if (!strcmp(device, "congestion"))
13892 #endif   /* defined(THRESHOLD_DEVSTATE_PLACEHOLDER) */
13893    {
13894       return pris[span - 1].pri.congestion_devstate;
13895    }
13896 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
13897    else if (!strcmp(device, "threshold")) {
13898       return pris[span - 1].pri.threshold_devstate;
13899    }
13900    return AST_DEVICE_UNKNOWN;
13901 #endif   /* defined(THRESHOLD_DEVSTATE_PLACEHOLDER) */
13902 #else
13903    return AST_DEVICE_UNKNOWN;
13904 #endif   /* defined(HAVE_PRI) */
13905 }
13906 
13907 /*!
13908  * \brief Callback made when dial failed to get a channel out of dahdi_request().
13909  * \since 1.8
13910  *
13911  * \param inbound Incoming asterisk channel.
13912  * \param dest Same dial string passed to dahdi_request().
13913  * \param callback Callback into CC core to announce a busy channel available for CC.
13914  *
13915  * \details
13916  * This callback acts like a forked dial with all prongs of the fork busy.
13917  * Essentially, for each channel that could have taken the call, indicate that
13918  * it is busy.
13919  *
13920  * \retval 0 on success.
13921  * \retval -1 on error.
13922  */
13923 static int dahdi_cc_callback(struct ast_channel *inbound, const char *dest, ast_cc_callback_fn callback)
13924 {
13925    struct dahdi_pvt *p;
13926    struct dahdi_pvt *exitpvt;
13927    struct dahdi_starting_point start;
13928    int groupmatched = 0;
13929    int channelmatched = 0;
13930 
13931    ast_mutex_lock(&iflock);
13932    p = determine_starting_point(dest, &start);
13933    if (!p) {
13934       ast_mutex_unlock(&iflock);
13935       return -1;
13936    }
13937    exitpvt = p;
13938    for (;;) {
13939       if (is_group_or_channel_match(p, start.span, start.groupmatch, &groupmatched, start.channelmatch, &channelmatched)) {
13940          /* We found a potential match. call the callback */
13941          struct ast_str *device_name;
13942          char *dash;
13943          const char *monitor_type;
13944          char dialstring[AST_CHANNEL_NAME];
13945          char full_device_name[AST_CHANNEL_NAME];
13946 
13947          switch (ast_get_cc_monitor_policy(p->cc_params)) {
13948          case AST_CC_MONITOR_NEVER:
13949             break;
13950          case AST_CC_MONITOR_NATIVE:
13951          case AST_CC_MONITOR_ALWAYS:
13952          case AST_CC_MONITOR_GENERIC:
13953 #if defined(HAVE_PRI)
13954             if (dahdi_sig_pri_lib_handles(p->sig)) {
13955                /*
13956                 * ISDN is in a trunk busy condition so we need to monitor
13957                 * the span congestion device state.
13958                 */
13959                snprintf(full_device_name, sizeof(full_device_name),
13960                   "DAHDI/I%d/congestion", p->pri->span);
13961             } else
13962 #endif   /* defined(HAVE_PRI) */
13963             {
13964 #if defined(HAVE_PRI)
13965                device_name = create_channel_name(p, 1, "");
13966 #else
13967                device_name = create_channel_name(p);
13968 #endif   /* defined(HAVE_PRI) */
13969                snprintf(full_device_name, sizeof(full_device_name), "DAHDI/%s",
13970                   device_name ? ast_str_buffer(device_name) : "");
13971                ast_free(device_name);
13972                /*
13973                 * The portion after the '-' in the channel name is either a random
13974                 * number, a sequence number, or a subchannel number. None are
13975                 * necessary so strip them off.
13976                 */
13977                dash = strrchr(full_device_name, '-');
13978                if (dash) {
13979                   *dash = '\0';
13980                }
13981             }
13982             snprintf(dialstring, sizeof(dialstring), "DAHDI/%s", dest);
13983 
13984             /*
13985              * Analog can only do generic monitoring.
13986              * ISDN is in a trunk busy condition and any "device" is going
13987              * to be busy until a B channel becomes available.  The generic
13988              * monitor can do this task.
13989              */
13990             monitor_type = AST_CC_GENERIC_MONITOR_TYPE;
13991             callback(inbound,
13992 #if defined(HAVE_PRI)
13993                p->pri ? p->pri->cc_params : p->cc_params,
13994 #else
13995                p->cc_params,
13996 #endif   /* defined(HAVE_PRI) */
13997                monitor_type, full_device_name, dialstring, NULL);
13998             break;
13999          }
14000       }
14001       p = start.backwards ? p->prev : p->next;
14002       if (!p) {
14003          p = start.backwards ? ifend : iflist;
14004       }
14005       if (p == exitpvt) {
14006          break;
14007       }
14008    }
14009    ast_mutex_unlock(&iflock);
14010    return 0;
14011 }
14012 
14013 #if defined(HAVE_SS7)
14014 static void dahdi_ss7_message(struct ss7 *ss7, char *s)
14015 {
14016    int i;
14017 
14018    if (ss7) {
14019       for (i = 0; i < NUM_SPANS; i++) {
14020          if (linksets[i].ss7.ss7 == ss7) {
14021             ast_verbose("[%d] %s", i + 1, s);
14022             return;
14023          }
14024       }
14025    }
14026    ast_verbose("%s", s);
14027 }
14028 #endif   /* defined(HAVE_SS7) */
14029 
14030 #if defined(HAVE_SS7)
14031 static void dahdi_ss7_error(struct ss7 *ss7, char *s)
14032 {
14033    int i;
14034 
14035    if (ss7) {
14036       for (i = 0; i < NUM_SPANS; i++) {
14037          if (linksets[i].ss7.ss7 == ss7) {
14038             ast_log(LOG_ERROR, "[%d] %s", i + 1, s);
14039             return;
14040          }
14041       }
14042    }
14043    ast_log(LOG_ERROR, "%s", s);
14044 }
14045 #endif   /* defined(HAVE_SS7) */
14046 
14047 #if defined(HAVE_OPENR2)
14048 static void *mfcr2_monitor(void *data)
14049 {
14050    struct dahdi_mfcr2 *mfcr2 = data;
14051    /* we should be using pthread_key_create
14052       and allocate pollers dynamically.
14053       I think do_monitor() could be leaking, since it
14054       could be cancelled at any time and is not
14055       using thread keys, why?, */
14056    struct pollfd pollers[ARRAY_LEN(mfcr2->pvts)];
14057    int res = 0;
14058    int i = 0;
14059    int oldstate = 0;
14060    int quit_loop = 0;
14061    int maxsleep = 20;
14062    int was_idle = 0;
14063    int pollsize = 0;
14064    /* now that we're ready to get calls, unblock our side and
14065       get current line state */
14066    for (i = 0; i < mfcr2->numchans; i++) {
14067       openr2_chan_set_idle(mfcr2->pvts[i]->r2chan);
14068       openr2_chan_handle_cas(mfcr2->pvts[i]->r2chan);
14069    }
14070    while (1) {
14071       /* we trust here that the mfcr2 channel list will not ever change once
14072          the module is loaded */
14073       pollsize = 0;
14074       for (i = 0; i < mfcr2->numchans; i++) {
14075          pollers[i].revents = 0;
14076          pollers[i].events = 0;
14077          if (mfcr2->pvts[i]->owner) {
14078             continue;
14079          }
14080          if (!mfcr2->pvts[i]->r2chan) {
14081             ast_log(LOG_DEBUG, "Wow, no r2chan on channel %d\n", mfcr2->pvts[i]->channel);
14082             quit_loop = 1;
14083             break;
14084          }
14085          openr2_chan_enable_read(mfcr2->pvts[i]->r2chan);
14086          pollers[i].events = POLLIN | POLLPRI;
14087          pollers[i].fd = mfcr2->pvts[i]->subs[SUB_REAL].dfd;
14088          pollsize++;
14089       }
14090       if (quit_loop) {
14091          break;
14092       }
14093       if (pollsize == 0) {
14094          if (!was_idle) {
14095             ast_log(LOG_DEBUG, "Monitor thread going idle since everybody has an owner\n");
14096             was_idle = 1;
14097          }
14098          poll(NULL, 0, maxsleep);
14099          continue;
14100       }
14101       was_idle = 0;
14102       /* probably poll() is a valid cancel point, lets just be on the safe side
14103          by calling pthread_testcancel */
14104       pthread_testcancel();
14105       res = poll(pollers, mfcr2->numchans, maxsleep);
14106       pthread_testcancel();
14107       if ((res < 0) && (errno != EINTR)) {
14108          ast_log(LOG_ERROR, "going out, poll failed: %s\n", strerror(errno));
14109          break;
14110       }
14111       /* do we want to allow to cancel while processing events? */
14112       pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate);
14113       for (i = 0; i < mfcr2->numchans; i++) {
14114          if (pollers[i].revents & POLLPRI || pollers[i].revents & POLLIN) {
14115             openr2_chan_process_event(mfcr2->pvts[i]->r2chan);
14116          }
14117       }
14118       pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
14119    }
14120    ast_log(LOG_NOTICE, "Quitting MFC/R2 monitor thread\n");
14121    return 0;
14122 }
14123 #endif /* HAVE_OPENR2 */
14124 
14125 #if defined(HAVE_PRI)
14126 static void dahdi_pri_message(struct pri *pri, char *s)
14127 {
14128    int x;
14129    int y;
14130    int dchan = -1;
14131    int span = -1;
14132    int dchancount = 0;
14133 
14134    if (pri) {
14135       for (x = 0; x < NUM_SPANS; x++) {
14136          for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
14137             if (pris[x].pri.dchans[y]) {
14138                dchancount++;
14139             }
14140 
14141             if (pris[x].pri.dchans[y] == pri) {
14142                dchan = y;
14143             }
14144          }
14145          if (dchan >= 0) {
14146             span = x;
14147             break;
14148          }
14149          dchancount = 0;
14150       }
14151       if (-1 < span) {
14152          if (1 < dchancount) {
14153             ast_verbose("[PRI Span: %d D-Channel: %d] %s", span + 1, dchan, s);
14154          } else {
14155             ast_verbose("PRI Span: %d %s", span + 1, s);
14156          }
14157       } else {
14158          ast_verbose("PRI Span: ? %s", s);
14159       }
14160    } else {
14161       ast_verbose("PRI Span: ? %s", s);
14162    }
14163 
14164    ast_mutex_lock(&pridebugfdlock);
14165 
14166    if (pridebugfd >= 0) {
14167       if (write(pridebugfd, s, strlen(s)) < 0) {
14168          ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
14169       }
14170    }
14171 
14172    ast_mutex_unlock(&pridebugfdlock);
14173 }
14174 #endif   /* defined(HAVE_PRI) */
14175 
14176 #if defined(HAVE_PRI)
14177 static void dahdi_pri_error(struct pri *pri, char *s)
14178 {
14179    int x;
14180    int y;
14181    int dchan = -1;
14182    int span = -1;
14183    int dchancount = 0;
14184 
14185    if (pri) {
14186       for (x = 0; x < NUM_SPANS; x++) {
14187          for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
14188             if (pris[x].pri.dchans[y]) {
14189                dchancount++;
14190             }
14191 
14192             if (pris[x].pri.dchans[y] == pri) {
14193                dchan = y;
14194             }
14195          }
14196          if (dchan >= 0) {
14197             span = x;
14198             break;
14199          }
14200          dchancount = 0;
14201       }
14202       if (-1 < span) {
14203          if (1 < dchancount) {
14204             ast_log(LOG_ERROR, "[PRI Span: %d D-Channel: %d] %s", span + 1, dchan, s);
14205          } else {
14206             ast_log(LOG_ERROR, "PRI Span: %d %s", span + 1, s);
14207          }
14208       } else {
14209          ast_log(LOG_ERROR, "PRI Span: ? %s", s);
14210       }
14211    } else {
14212       ast_log(LOG_ERROR, "PRI Span: ? %s", s);
14213    }
14214 
14215    ast_mutex_lock(&pridebugfdlock);
14216 
14217    if (pridebugfd >= 0) {
14218       if (write(pridebugfd, s, strlen(s)) < 0) {
14219          ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
14220       }
14221    }
14222 
14223    ast_mutex_unlock(&pridebugfdlock);
14224 }
14225 #endif   /* defined(HAVE_PRI) */
14226 
14227 #if defined(HAVE_PRI)
14228 static int prepare_pri(struct dahdi_pri *pri)
14229 {
14230    int i, res, x;
14231    struct dahdi_params p;
14232    struct dahdi_bufferinfo bi;
14233    struct dahdi_spaninfo si;
14234 
14235    pri->pri.calls = &dahdi_pri_callbacks;
14236 
14237    for (i = 0; i < SIG_PRI_NUM_DCHANS; i++) {
14238       if (!pri->dchannels[i])
14239          break;
14240       pri->pri.fds[i] = open("/dev/dahdi/channel", O_RDWR);
14241       x = pri->dchannels[i];
14242       if ((pri->pri.fds[i] < 0) || (ioctl(pri->pri.fds[i],DAHDI_SPECIFY,&x) == -1)) {
14243          ast_log(LOG_ERROR, "Unable to open D-channel %d (%s)\n", x, strerror(errno));
14244          return -1;
14245       }
14246       memset(&p, 0, sizeof(p));
14247       res = ioctl(pri->pri.fds[i], DAHDI_GET_PARAMS, &p);
14248       if (res) {
14249          dahdi_close_pri_fd(pri, i);
14250          ast_log(LOG_ERROR, "Unable to get parameters for D-channel %d (%s)\n", x, strerror(errno));
14251          return -1;
14252       }
14253       if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC)) {
14254          dahdi_close_pri_fd(pri, i);
14255          ast_log(LOG_ERROR, "D-channel %d is not in HDLC/FCS mode.\n", x);
14256          return -1;
14257       }
14258       memset(&si, 0, sizeof(si));
14259       res = ioctl(pri->pri.fds[i], DAHDI_SPANSTAT, &si);
14260       if (res) {
14261          dahdi_close_pri_fd(pri, i);
14262          ast_log(LOG_ERROR, "Unable to get span state for D-channel %d (%s)\n", x, strerror(errno));
14263       }
14264       if (!si.alarms) {
14265          pri_event_noalarm(&pri->pri, i, 1);
14266       } else {
14267          pri_event_alarm(&pri->pri, i, 1);
14268       }
14269       memset(&bi, 0, sizeof(bi));
14270       bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
14271       bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
14272       bi.numbufs = 32;
14273       bi.bufsize = 1024;
14274       if (ioctl(pri->pri.fds[i], DAHDI_SET_BUFINFO, &bi)) {
14275          ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", x, strerror(errno));
14276          dahdi_close_pri_fd(pri, i);
14277          return -1;
14278       }
14279       pri->pri.dchan_logical_span[i] = pris[p.spanno - 1].prilogicalspan;
14280    }
14281    return 0;
14282 }
14283 #endif   /* defined(HAVE_PRI) */
14284 
14285 #if defined(HAVE_PRI)
14286 static char *complete_span_helper(const char *line, const char *word, int pos, int state, int rpos)
14287 {
14288    int which, span;
14289    char *ret = NULL;
14290 
14291    if (pos != rpos)
14292       return ret;
14293 
14294    for (which = span = 0; span < NUM_SPANS; span++) {
14295       if (pris[span].pri.pri && ++which > state) {
14296          if (ast_asprintf(&ret, "%d", span + 1) < 0) {   /* user indexes start from 1 */
14297             ret = NULL;
14298          }
14299          break;
14300       }
14301    }
14302    return ret;
14303 }
14304 #endif   /* defined(HAVE_PRI) */
14305 
14306 #if defined(HAVE_PRI)
14307 static char *complete_span_4(const char *line, const char *word, int pos, int state)
14308 {
14309    return complete_span_helper(line,word,pos,state,3);
14310 }
14311 #endif   /* defined(HAVE_PRI) */
14312 
14313 #if defined(HAVE_PRI)
14314 static char *handle_pri_set_debug_file(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14315 {
14316    int myfd;
14317    switch (cmd) {
14318    case CLI_INIT:
14319       e->command = "pri set debug file";
14320       e->usage = "Usage: pri set debug file [output-file]\n"
14321          "       Sends PRI debug output to the specified output file\n";
14322       return NULL;
14323    case CLI_GENERATE:
14324       return NULL;
14325    }
14326    if (a->argc < 5)
14327       return CLI_SHOWUSAGE;
14328 
14329    if (ast_strlen_zero(a->argv[4]))
14330       return CLI_SHOWUSAGE;
14331 
14332    myfd = open(a->argv[4], O_CREAT|O_WRONLY, AST_FILE_MODE);
14333    if (myfd < 0) {
14334       ast_cli(a->fd, "Unable to open '%s' for writing\n", a->argv[4]);
14335       return CLI_SUCCESS;
14336    }
14337 
14338    ast_mutex_lock(&pridebugfdlock);
14339 
14340    if (pridebugfd >= 0)
14341       close(pridebugfd);
14342 
14343    pridebugfd = myfd;
14344    ast_copy_string(pridebugfilename,a->argv[4],sizeof(pridebugfilename));
14345    ast_mutex_unlock(&pridebugfdlock);
14346    ast_cli(a->fd, "PRI debug output will be sent to '%s'\n", a->argv[4]);
14347    return CLI_SUCCESS;
14348 }
14349 #endif   /* defined(HAVE_PRI) */
14350 
14351 #if defined(HAVE_PRI)
14352 static char *handle_pri_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14353 {
14354    int span;
14355    int x;
14356    int level = 0;
14357    switch (cmd) {
14358    case CLI_INIT:
14359       e->command = "pri set debug {on|off|0|1|2} span";
14360       e->usage =
14361          "Usage: pri set debug {<level>|on|off} span <span>\n"
14362          "       Enables debugging on a given PRI span\n";
14363       return NULL;
14364    case CLI_GENERATE:
14365       return complete_span_4(a->line, a->word, a->pos, a->n);
14366    }
14367    if (a->argc < 6) {
14368       return CLI_SHOWUSAGE;
14369    }
14370 
14371    if (!strcasecmp(a->argv[3], "on")) {
14372       level = 1;
14373    } else if (!strcasecmp(a->argv[3], "off")) {
14374       level = 0;
14375    } else {
14376       level = atoi(a->argv[3]);
14377    }
14378    span = atoi(a->argv[5]);
14379    if ((span < 1) || (span > NUM_SPANS)) {
14380       ast_cli(a->fd, "Invalid span %s.  Should be a number %d to %d\n", a->argv[5], 1, NUM_SPANS);
14381       return CLI_SUCCESS;
14382    }
14383    if (!pris[span-1].pri.pri) {
14384       ast_cli(a->fd, "No PRI running on span %d\n", span);
14385       return CLI_SUCCESS;
14386    }
14387 
14388    /* Set debug level in libpri */
14389    for (x = 0; x < SIG_PRI_NUM_DCHANS; x++) {
14390       if (pris[span - 1].pri.dchans[x]) {
14391          switch (level) {
14392          case 0:
14393             pri_set_debug(pris[span - 1].pri.dchans[x], 0);
14394             break;
14395          case 1:
14396             pri_set_debug(pris[span - 1].pri.dchans[x], SIG_PRI_DEBUG_NORMAL);
14397             break;
14398          default:
14399             pri_set_debug(pris[span - 1].pri.dchans[x], SIG_PRI_DEBUG_INTENSE);
14400             break;
14401          }
14402       }
14403    }
14404    if (level == 0) {
14405       /* Close the debugging file if it's set */
14406       ast_mutex_lock(&pridebugfdlock);
14407       if (0 <= pridebugfd) {
14408          close(pridebugfd);
14409          pridebugfd = -1;
14410          ast_cli(a->fd, "Disabled PRI debug output to file '%s'\n",
14411             pridebugfilename);
14412       }
14413       ast_mutex_unlock(&pridebugfdlock);
14414    }
14415    pris[span - 1].pri.debug = (level) ? 1 : 0;
14416    ast_cli(a->fd, "%s debugging on span %d\n", (level) ? "Enabled" : "Disabled", span);
14417    return CLI_SUCCESS;
14418 }
14419 #endif   /* defined(HAVE_PRI) */
14420 
14421 #if defined(HAVE_PRI)
14422 #if defined(HAVE_PRI_SERVICE_MESSAGES)
14423 static char *handle_pri_service_generic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a, int changestatus)
14424 {
14425    unsigned *why;
14426    int channel;
14427    int trunkgroup;
14428    int x, y, fd = a->fd;
14429    int interfaceid = 0;
14430    char db_chan_name[20], db_answer[5];
14431    struct dahdi_pvt *tmp;
14432    struct dahdi_pri *pri;
14433 
14434    if (a->argc < 5 || a->argc > 6)
14435       return CLI_SHOWUSAGE;
14436    if (strchr(a->argv[4], ':')) {
14437       if (sscanf(a->argv[4], "%30d:%30d", &trunkgroup, &channel) != 2)
14438          return CLI_SHOWUSAGE;
14439       if ((trunkgroup < 1) || (channel < 1))
14440          return CLI_SHOWUSAGE;
14441       pri = NULL;
14442       for (x=0;x<NUM_SPANS;x++) {
14443          if (pris[x].pri.trunkgroup == trunkgroup) {
14444             pri = pris + x;
14445             break;
14446          }
14447       }
14448       if (!pri) {
14449          ast_cli(fd, "No such trunk group %d\n", trunkgroup);
14450          return CLI_FAILURE;
14451       }
14452    } else
14453       channel = atoi(a->argv[4]);
14454 
14455    if (a->argc == 6)
14456       interfaceid = atoi(a->argv[5]);
14457 
14458    /* either servicing a D-Channel */
14459    for (x = 0; x < NUM_SPANS; x++) {
14460       for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
14461          if (pris[x].dchannels[y] == channel) {
14462             pri = pris + x;
14463             if (pri->pri.enable_service_message_support) {
14464                ast_mutex_lock(&pri->pri.lock);
14465                pri_maintenance_service(pri->pri.pri, interfaceid, -1, changestatus);
14466                ast_mutex_unlock(&pri->pri.lock);
14467             } else {
14468                ast_cli(fd,
14469                   "\n\tThis operation has not been enabled in chan_dahdi.conf, set 'service_message_support=yes' to use this operation.\n"
14470                   "\tNote only 4ESS, 5ESS, and NI2 switch types are supported.\n\n");
14471             }
14472             return CLI_SUCCESS;
14473          }
14474       }
14475    }
14476 
14477    /* or servicing a B-Channel */
14478    ast_mutex_lock(&iflock);
14479    for (tmp = iflist; tmp; tmp = tmp->next) {
14480       if (tmp->pri && tmp->channel == channel) {
14481          ast_mutex_unlock(&iflock);
14482          ast_mutex_lock(&tmp->pri->lock);
14483          if (!tmp->pri->enable_service_message_support) {
14484             ast_mutex_unlock(&tmp->pri->lock);
14485             ast_cli(fd,
14486                "\n\tThis operation has not been enabled in chan_dahdi.conf, set 'service_message_support=yes' to use this operation.\n"
14487                "\tNote only 4ESS, 5ESS, and NI2 switch types are supported.\n\n");
14488             return CLI_SUCCESS;
14489          }
14490          snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, tmp->span, channel);
14491          why = &((struct sig_pri_chan *) tmp->sig_pvt)->service_status;
14492          switch(changestatus) {
14493          case 0: /* enable */
14494             /* Near end wants to be in service now. */
14495             ast_db_del(db_chan_name, SRVST_DBKEY);
14496             *why &= ~SRVST_NEAREND;
14497             if (*why) {
14498                snprintf(db_answer, sizeof(db_answer), "%s:%u", SRVST_TYPE_OOS, *why);
14499                ast_db_put(db_chan_name, SRVST_DBKEY, db_answer);
14500             } else {
14501                dahdi_pri_update_span_devstate(tmp->pri);
14502             }
14503             break;
14504          /* case 1:  -- loop */
14505          case 2: /* disable */
14506             /* Near end wants to be out-of-service now. */
14507             ast_db_del(db_chan_name, SRVST_DBKEY);
14508             *why |= SRVST_NEAREND;
14509             snprintf(db_answer, sizeof(db_answer), "%s:%u", SRVST_TYPE_OOS, *why);
14510             ast_db_put(db_chan_name, SRVST_DBKEY, db_answer);
14511             dahdi_pri_update_span_devstate(tmp->pri);
14512             break;
14513          /* case 3:  -- continuity */
14514          /* case 4:  -- shutdown */
14515          default:
14516             ast_log(LOG_WARNING, "Unsupported changestatus: '%d'\n", changestatus);
14517             break;
14518          }
14519          pri_maintenance_bservice(tmp->pri->pri, tmp->sig_pvt, changestatus);
14520          ast_mutex_unlock(&tmp->pri->lock);
14521          return CLI_SUCCESS;
14522       }
14523    }
14524    ast_mutex_unlock(&iflock);
14525 
14526    ast_cli(fd, "Unable to find given channel %d, possibly not a PRI\n", channel);
14527    return CLI_FAILURE;
14528 }
14529 
14530 static char *handle_pri_service_enable_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14531 {
14532    switch (cmd) {
14533    case CLI_INIT:
14534       e->command = "pri service enable channel";
14535       e->usage =
14536          "Usage: pri service enable channel <channel> [<interface id>]\n"
14537          "       Send an AT&T / NFAS / CCS ANSI T1.607 maintenance message\n"
14538          "  to restore a channel to service, with optional interface id\n"
14539          "  as agreed upon with remote switch operator\n";
14540       return NULL;
14541    case CLI_GENERATE:
14542       return NULL;
14543    }
14544    return handle_pri_service_generic(e, cmd, a, 0);
14545 }
14546 
14547 static char *handle_pri_service_disable_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14548 {
14549    switch (cmd) {
14550    case CLI_INIT:
14551       e->command = "pri service disable channel";
14552       e->usage =
14553          "Usage: pri service disable channel <chan num> [<interface id>]\n"
14554          "  Send an AT&T / NFAS / CCS ANSI T1.607 maintenance message\n"
14555          "  to remove a channel from service, with optional interface id\n"
14556          "  as agreed upon with remote switch operator\n";
14557       return NULL;
14558    case CLI_GENERATE:
14559       return NULL;
14560    }
14561    return handle_pri_service_generic(e, cmd, a, 2);
14562 }
14563 #endif   /* defined(HAVE_PRI_SERVICE_MESSAGES) */
14564 #endif   /* defined(HAVE_PRI) */
14565 
14566 #if defined(HAVE_PRI)
14567 static char *handle_pri_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14568 {
14569    int span;
14570 
14571    switch (cmd) {
14572    case CLI_INIT:
14573       e->command = "pri show channels";
14574       e->usage =
14575          "Usage: pri show channels\n"
14576          "       Displays PRI channel information such as the current mapping\n"
14577          "       of DAHDI B channels to Asterisk channel names and which calls\n"
14578          "       are on hold or call-waiting.  Calls on hold or call-waiting\n"
14579          "       are not associated with any B channel.\n";
14580       return NULL;
14581    case CLI_GENERATE:
14582       return NULL;
14583    }
14584 
14585    if (a->argc != 3)
14586       return CLI_SHOWUSAGE;
14587 
14588    sig_pri_cli_show_channels_header(a->fd);
14589    for (span = 0; span < NUM_SPANS; ++span) {
14590       if (pris[span].pri.pri) {
14591          sig_pri_cli_show_channels(a->fd, &pris[span].pri);
14592       }
14593    }
14594    return CLI_SUCCESS;
14595 }
14596 #endif   /* defined(HAVE_PRI) */
14597 
14598 #if defined(HAVE_PRI)
14599 static char *handle_pri_show_spans(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14600 {
14601    int span;
14602 
14603    switch (cmd) {
14604    case CLI_INIT:
14605       e->command = "pri show spans";
14606       e->usage =
14607          "Usage: pri show spans\n"
14608          "       Displays PRI span information\n";
14609       return NULL;
14610    case CLI_GENERATE:
14611       return NULL;
14612    }
14613 
14614    if (a->argc != 3)
14615       return CLI_SHOWUSAGE;
14616 
14617    for (span = 0; span < NUM_SPANS; span++) {
14618       if (pris[span].pri.pri) {
14619          sig_pri_cli_show_spans(a->fd, span + 1, &pris[span].pri);
14620       }
14621    }
14622    return CLI_SUCCESS;
14623 }
14624 #endif   /* defined(HAVE_PRI) */
14625 
14626 #if defined(HAVE_PRI)
14627 #define container_of(ptr, type, member) \
14628    ((type *)((char *)(ptr) - offsetof(type, member)))
14629 /*!
14630  * \internal
14631  * \brief Destroy a D-Channel of a PRI span
14632  * \since 12
14633  *
14634  * \param pri the pri span
14635  *
14636  * \return TRUE if the span was valid and we attempted destroying.
14637  *
14638  * Shuts down a span and destroys its D-Channel. Further destruction
14639  * of the B-channels using dahdi_destroy_channel() would probably be required
14640  * for the B-Channels.
14641  */
14642 static int pri_destroy_dchan(struct sig_pri_span *pri)
14643 {
14644    int i;
14645    struct dahdi_pri* dahdi_pri;
14646 
14647    if (!pri->master || (pri->master == AST_PTHREADT_NULL)) {
14648       return 0;
14649    }
14650    pthread_cancel(pri->master);
14651    pthread_join(pri->master, NULL);
14652 
14653    /* The 'struct dahdi_pri' that contains our 'struct sig_pri_span' */
14654    dahdi_pri = container_of(pri, struct dahdi_pri, pri);
14655    for (i = 0; i < SIG_PRI_NUM_DCHANS; i++) {
14656       ast_debug(4, "closing pri_fd %d\n", i);
14657       dahdi_close_pri_fd(dahdi_pri, i);
14658    }
14659    pri->pri = NULL;
14660    ast_debug(1, "PRI span %d destroyed\n", pri->span);
14661    return 1;
14662 }
14663 
14664 static char *handle_pri_destroy_span(struct ast_cli_entry *e, int cmd,
14665       struct ast_cli_args *a)
14666 {
14667    int span;
14668    int i;
14669    int res;
14670 
14671    switch (cmd) {
14672    case CLI_INIT:
14673       e->command = "pri destroy span";
14674       e->usage =
14675          "Usage: pri destroy span <span>\n"
14676          "       Destorys D-channel of span and its B-channels.\n"
14677          "  DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n";
14678       return NULL;
14679    case CLI_GENERATE:
14680       return complete_span_4(a->line, a->word, a->pos, a->n);
14681    }
14682 
14683    if (a->argc < 4) {
14684       return CLI_SHOWUSAGE;
14685    }
14686    res = sscanf(a->argv[3], "%30d", &span);
14687    if ((res != 1) || span < 1 || span > NUM_SPANS) {
14688       ast_cli(a->fd,
14689          "Invalid span '%s'.  Should be a number from %d to %d\n",
14690          a->argv[3], 1, NUM_SPANS);
14691       return CLI_SUCCESS;
14692    }
14693    if (!pris[span - 1].pri.pri) {
14694       ast_cli(a->fd, "No PRI running on span %d\n", span);
14695       return CLI_SUCCESS;
14696    }
14697 
14698    for (i = 0; i < pris[span - 1].pri.numchans; i++) {
14699       int channel;
14700       struct sig_pri_chan *pvt = pris[span - 1].pri.pvts[i];
14701 
14702       if (!pvt) {
14703          continue;
14704       }
14705       channel = pvt->channel;
14706       ast_debug(2, "About to destroy B-channel %d.\n", channel);
14707       dahdi_destroy_channel_bynum(channel);
14708    }
14709    ast_debug(2, "About to destroy D-channel of span %d.\n", span);
14710    pri_destroy_dchan(&pris[span - 1].pri);
14711 
14712    return CLI_SUCCESS;
14713 }
14714 
14715 #endif   /* defined(HAVE_PRI) */
14716 
14717 #if defined(HAVE_PRI)
14718 static char *handle_pri_show_span(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14719 {
14720    int span;
14721 
14722    switch (cmd) {
14723    case CLI_INIT:
14724       e->command = "pri show span";
14725       e->usage =
14726          "Usage: pri show span <span>\n"
14727          "       Displays PRI Information on a given PRI span\n";
14728       return NULL;
14729    case CLI_GENERATE:
14730       return complete_span_4(a->line, a->word, a->pos, a->n);
14731    }
14732 
14733    if (a->argc < 4)
14734       return CLI_SHOWUSAGE;
14735    span = atoi(a->argv[3]);
14736    if ((span < 1) || (span > NUM_SPANS)) {
14737       ast_cli(a->fd, "Invalid span '%s'.  Should be a number from %d to %d\n", a->argv[3], 1, NUM_SPANS);
14738       return CLI_SUCCESS;
14739    }
14740    if (!pris[span-1].pri.pri) {
14741       ast_cli(a->fd, "No PRI running on span %d\n", span);
14742       return CLI_SUCCESS;
14743    }
14744 
14745    sig_pri_cli_show_span(a->fd, pris[span-1].dchannels, &pris[span-1].pri);
14746 
14747    return CLI_SUCCESS;
14748 }
14749 #endif   /* defined(HAVE_PRI) */
14750 
14751 #if defined(HAVE_PRI)
14752 static char *handle_pri_show_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14753 {
14754    int x;
14755    int span;
14756    int count=0;
14757    int debug;
14758 
14759    switch (cmd) {
14760    case CLI_INIT:
14761       e->command = "pri show debug";
14762       e->usage =
14763          "Usage: pri show debug\n"
14764          "  Show the debug state of pri spans\n";
14765       return NULL;
14766    case CLI_GENERATE:
14767       return NULL;
14768    }
14769 
14770    for (span = 0; span < NUM_SPANS; span++) {
14771       if (pris[span].pri.pri) {
14772          for (x = 0; x < SIG_PRI_NUM_DCHANS; x++) {
14773             if (pris[span].pri.dchans[x]) {
14774                debug = pri_get_debug(pris[span].pri.dchans[x]);
14775                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" );
14776                count++;
14777             }
14778          }
14779       }
14780 
14781    }
14782    ast_mutex_lock(&pridebugfdlock);
14783    if (pridebugfd >= 0)
14784       ast_cli(a->fd, "Logging PRI debug to file %s\n", pridebugfilename);
14785    ast_mutex_unlock(&pridebugfdlock);
14786 
14787    if (!count)
14788       ast_cli(a->fd, "No PRI running\n");
14789    return CLI_SUCCESS;
14790 }
14791 #endif   /* defined(HAVE_PRI) */
14792 
14793 #if defined(HAVE_PRI)
14794 static char *handle_pri_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14795 {
14796    switch (cmd) {
14797    case CLI_INIT:
14798       e->command = "pri show version";
14799       e->usage =
14800          "Usage: pri show version\n"
14801          "Show libpri version information\n";
14802       return NULL;
14803    case CLI_GENERATE:
14804       return NULL;
14805    }
14806 
14807    ast_cli(a->fd, "libpri version: %s\n", pri_get_version());
14808 
14809    return CLI_SUCCESS;
14810 }
14811 #endif   /* defined(HAVE_PRI) */
14812 
14813 #if defined(HAVE_PRI)
14814 static struct ast_cli_entry dahdi_pri_cli[] = {
14815    AST_CLI_DEFINE(handle_pri_debug, "Enables PRI debugging on a span"),
14816 #if defined(HAVE_PRI_SERVICE_MESSAGES)
14817    AST_CLI_DEFINE(handle_pri_service_enable_channel, "Return a channel to service"),
14818    AST_CLI_DEFINE(handle_pri_service_disable_channel, "Remove a channel from service"),
14819 #endif   /* defined(HAVE_PRI_SERVICE_MESSAGES) */
14820    AST_CLI_DEFINE(handle_pri_show_channels, "Displays PRI channel information"),
14821    AST_CLI_DEFINE(handle_pri_show_spans, "Displays PRI span information"),
14822    AST_CLI_DEFINE(handle_pri_show_span, "Displays PRI span information"),
14823    AST_CLI_DEFINE(handle_pri_destroy_span, "Destroy a PRI span"),
14824    AST_CLI_DEFINE(handle_pri_show_debug, "Displays current PRI debug settings"),
14825    AST_CLI_DEFINE(handle_pri_set_debug_file, "Sends PRI debug output to the specified file"),
14826    AST_CLI_DEFINE(handle_pri_version, "Displays libpri version"),
14827 };
14828 #endif   /* defined(HAVE_PRI) */
14829 
14830 #ifdef HAVE_OPENR2
14831 
14832 static char *handle_mfcr2_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14833 {
14834    switch (cmd) {
14835    case CLI_INIT:
14836       e->command = "mfcr2 show version";
14837       e->usage =
14838          "Usage: mfcr2 show version\n"
14839          "       Shows the version of the OpenR2 library being used.\n";
14840       return NULL;
14841    case CLI_GENERATE:
14842       return NULL;
14843    }
14844    ast_cli(a->fd, "OpenR2 version: %s, revision: %s\n", openr2_get_version(), openr2_get_revision());
14845    return CLI_SUCCESS;
14846 }
14847 
14848 static char *handle_mfcr2_show_variants(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14849 {
14850 #define FORMAT "%4s %40s\n"
14851    int i = 0;
14852    int numvariants = 0;
14853    const openr2_variant_entry_t *variants;
14854    switch (cmd) {
14855    case CLI_INIT:
14856       e->command = "mfcr2 show variants";
14857       e->usage =
14858          "Usage: mfcr2 show variants\n"
14859          "       Shows the list of MFC/R2 variants supported.\n";
14860       return NULL;
14861    case CLI_GENERATE:
14862       return NULL;
14863    }
14864    if (!(variants = openr2_proto_get_variant_list(&numvariants))) {
14865       ast_cli(a->fd, "Failed to get list of variants.\n");
14866       return CLI_FAILURE;
14867    }
14868    ast_cli(a->fd, FORMAT, "Variant Code", "Country");
14869    for (i = 0; i < numvariants; i++) {
14870       ast_cli(a->fd, FORMAT, variants[i].name, variants[i].country);
14871    }
14872    return CLI_SUCCESS;
14873 #undef FORMAT
14874 }
14875 
14876 static char *handle_mfcr2_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14877 {
14878 #define FORMAT "%4s %-7.7s %-7.7s %-8.8s %-9.9s %-16.16s %-8.8s %-8.8s\n"
14879    int filtertype = 0;
14880    int targetnum = 0;
14881    char channo[5];
14882    char anino[5];
14883    char dnisno[5];
14884    struct dahdi_pvt *p;
14885    openr2_context_t *r2context;
14886    openr2_variant_t r2variant;
14887    switch (cmd) {
14888    case CLI_INIT:
14889       e->command = "mfcr2 show channels [group|context]";
14890       e->usage =
14891          "Usage: mfcr2 show channels [group <group> | context <context>]\n"
14892          "       Shows the DAHDI channels configured with MFC/R2 signaling.\n";
14893       return NULL;
14894    case CLI_GENERATE:
14895       return NULL;
14896    }
14897    if (!((a->argc == 3) || (a->argc == 5))) {
14898       return CLI_SHOWUSAGE;
14899    }
14900    if (a->argc == 5) {
14901       if (!strcasecmp(a->argv[3], "group")) {
14902          targetnum = atoi(a->argv[4]);
14903          if ((targetnum < 0) || (targetnum > 63))
14904             return CLI_SHOWUSAGE;
14905          targetnum = 1 << targetnum;
14906          filtertype = 1;
14907       } else if (!strcasecmp(a->argv[3], "context")) {
14908          filtertype = 2;
14909       } else {
14910          return CLI_SHOWUSAGE;
14911       }
14912    }
14913    ast_cli(a->fd, FORMAT, "Chan", "Variant", "Max ANI", "Max DNIS", "ANI First", "Immediate Accept", "Tx CAS", "Rx CAS");
14914    ast_mutex_lock(&iflock);
14915    for (p = iflist; p; p = p->next) {
14916       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14917          continue;
14918       }
14919       if (filtertype) {
14920          switch(filtertype) {
14921          case 1: /* mfcr2 show channels group <group> */
14922             if (p->group != targetnum) {
14923                continue;
14924             }
14925             break;
14926          case 2: /* mfcr2 show channels context <context> */
14927             if (strcasecmp(p->context, a->argv[4])) {
14928                continue;
14929             }
14930             break;
14931          default:
14932             ;
14933          }
14934       }
14935       r2context = openr2_chan_get_context(p->r2chan);
14936       r2variant = openr2_context_get_variant(r2context);
14937       snprintf(channo, sizeof(channo), "%d", p->channel);
14938       snprintf(anino, sizeof(anino), "%d", openr2_context_get_max_ani(r2context));
14939       snprintf(dnisno, sizeof(dnisno), "%d", openr2_context_get_max_dnis(r2context));
14940       ast_cli(a->fd, FORMAT, channo, openr2_proto_get_variant_string(r2variant),
14941             anino, dnisno, openr2_context_get_ani_first(r2context) ? "Yes" : "No",
14942             openr2_context_get_immediate_accept(r2context) ? "Yes" : "No",
14943             openr2_chan_get_tx_cas_string(p->r2chan), openr2_chan_get_rx_cas_string(p->r2chan));
14944    }
14945    ast_mutex_unlock(&iflock);
14946    return CLI_SUCCESS;
14947 #undef FORMAT
14948 }
14949 
14950 static char *handle_mfcr2_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14951 {
14952    struct dahdi_pvt *p = NULL;
14953    int channo = 0;
14954    char *toklevel = NULL;
14955    char *saveptr = NULL;
14956    char *logval = NULL;
14957    openr2_log_level_t loglevel = OR2_LOG_NOTHING;
14958    openr2_log_level_t tmplevel = OR2_LOG_NOTHING;
14959    switch (cmd) {
14960    case CLI_INIT:
14961       e->command = "mfcr2 set debug";
14962       e->usage =
14963          "Usage: mfcr2 set debug <loglevel> <channel>\n"
14964          "       Set a new logging level for the specified channel.\n"
14965          "       If no channel is specified the logging level will be applied to all channels.\n";
14966       return NULL;
14967    case CLI_GENERATE:
14968       return NULL;
14969    }
14970    if (a->argc < 4) {
14971       return CLI_SHOWUSAGE;
14972    }
14973    channo = (a->argc == 5) ? atoi(a->argv[4]) : -1;
14974    logval = ast_strdupa(a->argv[3]);
14975    toklevel = strtok_r(logval, ",", &saveptr);
14976    if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
14977       ast_cli(a->fd, "Invalid MFC/R2 logging level '%s'.\n", a->argv[3]);
14978       return CLI_FAILURE;
14979    } else if (OR2_LOG_NOTHING == tmplevel) {
14980       loglevel = tmplevel;
14981    } else {
14982       loglevel |= tmplevel;
14983       while ((toklevel = strtok_r(NULL, ",", &saveptr))) {
14984          if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
14985             ast_cli(a->fd, "Ignoring invalid logging level: '%s'.\n", toklevel);
14986             continue;
14987          }
14988          loglevel |= tmplevel;
14989       }
14990    }
14991    ast_mutex_lock(&iflock);
14992    for (p = iflist; p; p = p->next) {
14993       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14994          continue;
14995       }
14996       if ((channo != -1) && (p->channel != channo )) {
14997          continue;
14998       }
14999       openr2_chan_set_log_level(p->r2chan, loglevel);
15000       if (channo != -1) {
15001          ast_cli(a->fd, "MFC/R2 debugging set to '%s' for channel %d.\n", a->argv[3], p->channel);
15002          break;
15003       }
15004    }
15005    if ((channo != -1) && !p) {
15006       ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
15007    }
15008    if (channo == -1) {
15009       ast_cli(a->fd, "MFC/R2 debugging set to '%s' for all channels.\n", a->argv[3]);
15010    }
15011    ast_mutex_unlock(&iflock);
15012    return CLI_SUCCESS;
15013 }
15014 
15015 static char *handle_mfcr2_call_files(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15016 {
15017    struct dahdi_pvt *p = NULL;
15018    int channo = 0;
15019    switch (cmd) {
15020    case CLI_INIT:
15021       e->command = "mfcr2 call files [on|off]";
15022       e->usage =
15023          "Usage: mfcr2 call files [on|off] <channel>\n"
15024          "       Enable call files creation on the specified channel.\n"
15025          "       If no channel is specified call files creation policy will be applied to all channels.\n";
15026       return NULL;
15027    case CLI_GENERATE:
15028       return NULL;
15029    }
15030    if (a->argc < 4) {
15031       return CLI_SHOWUSAGE;
15032    }
15033    channo = (a->argc == 5) ? atoi(a->argv[4]) : -1;
15034    ast_mutex_lock(&iflock);
15035    for (p = iflist; p; p = p->next) {
15036       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
15037          continue;
15038       }
15039       if ((channo != -1) && (p->channel != channo )) {
15040          continue;
15041       }
15042       if (ast_true(a->argv[3])) {
15043          openr2_chan_enable_call_files(p->r2chan);
15044       } else {
15045          openr2_chan_disable_call_files(p->r2chan);
15046       }
15047       if (channo != -1) {
15048          if (ast_true(a->argv[3])) {
15049             ast_cli(a->fd, "MFC/R2 call files enabled for channel %d.\n", p->channel);
15050          } else {
15051             ast_cli(a->fd, "MFC/R2 call files disabled for channel %d.\n", p->channel);
15052          }
15053          break;
15054       }
15055    }
15056    if ((channo != -1) && !p) {
15057       ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
15058    }
15059    if (channo == -1) {
15060       if (ast_true(a->argv[3])) {
15061          ast_cli(a->fd, "MFC/R2 Call files enabled for all channels.\n");
15062       } else {
15063          ast_cli(a->fd, "MFC/R2 Call files disabled for all channels.\n");
15064       }
15065    }
15066    ast_mutex_unlock(&iflock);
15067    return CLI_SUCCESS;
15068 }
15069 
15070 static char *handle_mfcr2_set_idle(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15071 {
15072    struct dahdi_pvt *p = NULL;
15073    int channo = 0;
15074    switch (cmd) {
15075    case CLI_INIT:
15076       e->command = "mfcr2 set idle";
15077       e->usage =
15078          "Usage: mfcr2 set idle <channel>\n"
15079          "       DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n"
15080          "       Force the given channel into IDLE state.\n"
15081          "       If no channel is specified, all channels will be set to IDLE.\n";
15082       return NULL;
15083    case CLI_GENERATE:
15084       return NULL;
15085    }
15086    channo = (a->argc == 4) ? atoi(a->argv[3]) : -1;
15087    ast_mutex_lock(&iflock);
15088    for (p = iflist; p; p = p->next) {
15089       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
15090          continue;
15091       }
15092       if ((channo != -1) && (p->channel != channo )) {
15093          continue;
15094       }
15095       openr2_chan_set_idle(p->r2chan);
15096       ast_mutex_lock(&p->lock);
15097       p->locallyblocked = 0;
15098       p->mfcr2call = 0;
15099       ast_mutex_unlock(&p->lock);
15100       if (channo != -1) {
15101          break;
15102       }
15103    }
15104    if ((channo != -1) && !p) {
15105       ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
15106    }
15107    ast_mutex_unlock(&iflock);
15108    return CLI_SUCCESS;
15109 }
15110 
15111 static char *handle_mfcr2_set_blocked(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15112 {
15113    struct dahdi_pvt *p = NULL;
15114    int channo = 0;
15115    switch (cmd) {
15116    case CLI_INIT:
15117       e->command = "mfcr2 set blocked";
15118       e->usage =
15119          "Usage: mfcr2 set blocked <channel>\n"
15120          "       DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n"
15121          "       Force the given channel into BLOCKED state.\n"
15122          "       If no channel is specified, all channels will be set to BLOCKED.\n";
15123       return NULL;
15124    case CLI_GENERATE:
15125       return NULL;
15126    }
15127    channo = (a->argc == 4) ? atoi(a->argv[3]) : -1;
15128    ast_mutex_lock(&iflock);
15129    for (p = iflist; p; p = p->next) {
15130       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
15131          continue;
15132       }
15133       if ((channo != -1) && (p->channel != channo )) {
15134          continue;
15135       }
15136       openr2_chan_set_blocked(p->r2chan);
15137       ast_mutex_lock(&p->lock);
15138       p->locallyblocked = 1;
15139       ast_mutex_unlock(&p->lock);
15140       if (channo != -1) {
15141          break;
15142       }
15143    }
15144    if ((channo != -1) && !p) {
15145       ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
15146    }
15147    ast_mutex_unlock(&iflock);
15148    return CLI_SUCCESS;
15149 }
15150 
15151 static struct ast_cli_entry dahdi_mfcr2_cli[] = {
15152    AST_CLI_DEFINE(handle_mfcr2_version, "Show OpenR2 library version"),
15153    AST_CLI_DEFINE(handle_mfcr2_show_variants, "Show supported MFC/R2 variants"),
15154    AST_CLI_DEFINE(handle_mfcr2_show_channels, "Show MFC/R2 channels"),
15155    AST_CLI_DEFINE(handle_mfcr2_set_debug, "Set MFC/R2 channel logging level"),
15156    AST_CLI_DEFINE(handle_mfcr2_call_files, "Enable/Disable MFC/R2 call files"),
15157    AST_CLI_DEFINE(handle_mfcr2_set_idle, "Reset MFC/R2 channel forcing it to IDLE"),
15158    AST_CLI_DEFINE(handle_mfcr2_set_blocked, "Reset MFC/R2 channel forcing it to BLOCKED"),
15159 };
15160 
15161 #endif /* HAVE_OPENR2 */
15162 
15163 static char *dahdi_destroy_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15164 {
15165    int channel;
15166    int ret;
15167    switch (cmd) {
15168    case CLI_INIT:
15169       e->command = "dahdi destroy channel";
15170       e->usage =
15171          "Usage: dahdi destroy channel <chan num>\n"
15172          "  DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.  Immediately removes a given channel, whether it is in use or not\n";
15173       return NULL;
15174    case CLI_GENERATE:
15175       return NULL;
15176    }
15177    if (a->argc != 4)
15178       return CLI_SHOWUSAGE;
15179 
15180    channel = atoi(a->argv[3]);
15181    ret = dahdi_destroy_channel_bynum(channel);
15182    return ( RESULT_SUCCESS == ret ) ? CLI_SUCCESS : CLI_FAILURE;
15183 }
15184 
15185 static void dahdi_softhangup_all(void)
15186 {
15187    struct dahdi_pvt *p;
15188 retry:
15189    ast_mutex_lock(&iflock);
15190    for (p = iflist; p; p = p->next) {
15191       ast_mutex_lock(&p->lock);
15192       if (p->owner && !p->restartpending) {
15193          if (ast_channel_trylock(p->owner)) {
15194             if (option_debug > 2)
15195                ast_verbose("Avoiding deadlock\n");
15196             /* Avoid deadlock since you're not supposed to lock iflock or pvt before a channel */
15197             ast_mutex_unlock(&p->lock);
15198             ast_mutex_unlock(&iflock);
15199             goto retry;
15200          }
15201          if (option_debug > 2)
15202             ast_verbose("Softhanging up on %s\n", p->owner->name);
15203          ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_EXPLICIT);
15204          p->restartpending = 1;
15205          num_restart_pending++;
15206          ast_channel_unlock(p->owner);
15207       }
15208       ast_mutex_unlock(&p->lock);
15209    }
15210    ast_mutex_unlock(&iflock);
15211 }
15212 
15213 static int setup_dahdi(int reload);
15214 static int dahdi_restart(void)
15215 {
15216 #if defined(HAVE_PRI) || defined(HAVE_SS7)
15217    int i, j;
15218 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
15219    int cancel_code;
15220    struct dahdi_pvt *p;
15221 
15222    ast_mutex_lock(&restart_lock);
15223    ast_verb(1, "Destroying channels and reloading DAHDI configuration.\n");
15224    dahdi_softhangup_all();
15225    ast_verb(4, "Initial softhangup of all DAHDI channels complete.\n");
15226 #ifdef HAVE_OPENR2
15227    dahdi_r2_destroy_links();
15228 #endif
15229 
15230 #if defined(HAVE_PRI)
15231    for (i = 0; i < NUM_SPANS; i++) {
15232       if (pris[i].pri.master && (pris[i].pri.master != AST_PTHREADT_NULL)) {
15233          cancel_code = pthread_cancel(pris[i].pri.master);
15234          pthread_kill(pris[i].pri.master, SIGURG);
15235          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);
15236          pthread_join(pris[i].pri.master, NULL);
15237          ast_debug(4, "Joined thread of span %d\n", i);
15238       }
15239    }
15240 #endif
15241 
15242 #if defined(HAVE_SS7)
15243    for (i = 0; i < NUM_SPANS; i++) {
15244       if (linksets[i].ss7.master && (linksets[i].ss7.master != AST_PTHREADT_NULL)) {
15245          cancel_code = pthread_cancel(linksets[i].ss7.master);
15246          pthread_kill(linksets[i].ss7.master, SIGURG);
15247          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);
15248          pthread_join(linksets[i].ss7.master, NULL);
15249          ast_debug(4, "Joined thread of span %d\n", i);
15250       }
15251    }
15252 #endif   /* defined(HAVE_SS7) */
15253 
15254    ast_mutex_lock(&monlock);
15255    if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
15256       cancel_code = pthread_cancel(monitor_thread);
15257       pthread_kill(monitor_thread, SIGURG);
15258       ast_debug(4, "Waiting to join monitor thread with pid=%p, cancel_code=%d\n", (void *) monitor_thread, cancel_code);
15259       pthread_join(monitor_thread, NULL);
15260       ast_debug(4, "Joined monitor thread\n");
15261    }
15262    monitor_thread = AST_PTHREADT_NULL; /* prepare to restart thread in setup_dahdi once channels are reconfigured */
15263 
15264    ast_mutex_lock(&ss_thread_lock);
15265    while (ss_thread_count > 0) { /* let ss_threads finish and run dahdi_hangup before dahvi_pvts are destroyed */
15266       int x = DAHDI_FLASH;
15267       ast_debug(3, "Waiting on %d analog_ss_thread(s) to finish\n", ss_thread_count);
15268 
15269       ast_mutex_lock(&iflock);
15270       for (p = iflist; p; p = p->next) {
15271          if (p->owner) {
15272             /* important to create an event for dahdi_wait_event to register so that all analog_ss_threads terminate */
15273             ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
15274          }
15275       }
15276       ast_mutex_unlock(&iflock);
15277       ast_cond_wait(&ss_thread_complete, &ss_thread_lock);
15278    }
15279 
15280    /* ensure any created channels before monitor threads were stopped are hungup */
15281    dahdi_softhangup_all();
15282    ast_verb(4, "Final softhangup of all DAHDI channels complete.\n");
15283    destroy_all_channels();
15284    memset(round_robin, 0, sizeof(round_robin));
15285    ast_debug(1, "Channels destroyed. Now re-reading config. %d active channels remaining.\n", ast_active_channels());
15286 
15287    ast_mutex_unlock(&monlock);
15288 
15289 #ifdef HAVE_PRI
15290    for (i = 0; i < NUM_SPANS; i++) {
15291       for (j = 0; j < SIG_PRI_NUM_DCHANS; j++)
15292          dahdi_close_pri_fd(&(pris[i]), j);
15293    }
15294 
15295    memset(pris, 0, sizeof(pris));
15296    for (i = 0; i < NUM_SPANS; i++) {
15297       sig_pri_init_pri(&pris[i].pri);
15298    }
15299    pri_set_error(dahdi_pri_error);
15300    pri_set_message(dahdi_pri_message);
15301 #endif
15302 #if defined(HAVE_SS7)
15303    for (i = 0; i < NUM_SPANS; i++) {
15304       for (j = 0; j < SIG_SS7_NUM_DCHANS; j++)
15305          dahdi_close_ss7_fd(&(linksets[i]), j);
15306    }
15307 
15308    memset(linksets, 0, sizeof(linksets));
15309    for (i = 0; i < NUM_SPANS; i++) {
15310       sig_ss7_init_linkset(&linksets[i].ss7);
15311    }
15312    ss7_set_error(dahdi_ss7_error);
15313    ss7_set_message(dahdi_ss7_message);
15314 #endif   /* defined(HAVE_SS7) */
15315 
15316    if (setup_dahdi(2) != 0) {
15317       ast_log(LOG_WARNING, "Reload channels from dahdi config failed!\n");
15318       ast_mutex_unlock(&ss_thread_lock);
15319       return 1;
15320    }
15321    ast_mutex_unlock(&ss_thread_lock);
15322    ast_mutex_unlock(&restart_lock);
15323    return 0;
15324 }
15325 
15326 static char *dahdi_restart_cmd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15327 {
15328    switch (cmd) {
15329    case CLI_INIT:
15330       e->command = "dahdi restart";
15331       e->usage =
15332          "Usage: dahdi restart\n"
15333          "  Restarts the DAHDI channels: destroys them all and then\n"
15334          "  re-reads them from chan_dahdi.conf.\n"
15335          "  Note that this will STOP any running CALL on DAHDI channels.\n"
15336          "";
15337       return NULL;
15338    case CLI_GENERATE:
15339       return NULL;
15340    }
15341    if (a->argc != 2)
15342       return CLI_SHOWUSAGE;
15343 
15344    if (dahdi_restart() != 0)
15345       return CLI_FAILURE;
15346    return CLI_SUCCESS;
15347 }
15348 
15349 static int action_dahdirestart(struct mansession *s, const struct message *m)
15350 {
15351    if (dahdi_restart() != 0) {
15352       astman_send_error(s, m, "Failed rereading DAHDI configuration");
15353       return 1;
15354    }
15355    astman_send_ack(s, m, "DAHDIRestart: Success");
15356    return 0;
15357 }
15358 
15359 static char *dahdi_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15360 {
15361 #define FORMAT "%7s %-15.15s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
15362 #define FORMAT2 "%7s %-15.15s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
15363    ast_group_t targetnum = 0;
15364    int filtertype = 0;
15365    struct dahdi_pvt *tmp = NULL;
15366    char tmps[20] = "";
15367    char statestr[20] = "";
15368    char blockstr[20] = "";
15369 
15370    switch (cmd) {
15371    case CLI_INIT:
15372       e->command = "dahdi show channels [group|context]";
15373       e->usage =
15374          "Usage: dahdi show channels [ group <group> | context <context> ]\n"
15375          "  Shows a list of available channels with optional filtering\n"
15376          "  <group> must be a number between 0 and 63\n";
15377       return NULL;
15378    case CLI_GENERATE:
15379       return NULL;
15380    }
15381 
15382    /* syntax: dahdi show channels [ group <group> | context <context> ] */
15383 
15384    if (!((a->argc == 3) || (a->argc == 5)))
15385       return CLI_SHOWUSAGE;
15386 
15387    if (a->argc == 5) {
15388       if (!strcasecmp(a->argv[3], "group")) {
15389          targetnum = atoi(a->argv[4]);
15390          if (63 < targetnum) {
15391             return CLI_SHOWUSAGE;
15392          }
15393          targetnum = ((ast_group_t) 1) << targetnum;
15394          filtertype = 1;
15395       } else if (!strcasecmp(a->argv[3], "context")) {
15396          filtertype = 2;
15397       }
15398    }
15399 
15400    ast_cli(a->fd, FORMAT2, "Chan", "Extension", "Context", "Language", "MOH Interpret", "Blocked", "State");
15401    ast_mutex_lock(&iflock);
15402    for (tmp = iflist; tmp; tmp = tmp->next) {
15403       if (filtertype) {
15404          switch(filtertype) {
15405          case 1: /* dahdi show channels group <group> */
15406             if (!(tmp->group & targetnum)) {
15407                continue;
15408             }
15409             break;
15410          case 2: /* dahdi show channels context <context> */
15411             if (strcasecmp(tmp->context, a->argv[4])) {
15412                continue;
15413             }
15414             break;
15415          default:
15416             break;
15417          }
15418       }
15419       if (tmp->channel > 0) {
15420          snprintf(tmps, sizeof(tmps), "%d", tmp->channel);
15421       } else
15422          ast_copy_string(tmps, "pseudo", sizeof(tmps));
15423 
15424       if (tmp->locallyblocked)
15425          blockstr[0] = 'L';
15426       else
15427          blockstr[0] = ' ';
15428 
15429       if (tmp->remotelyblocked)
15430          blockstr[1] = 'R';
15431       else
15432          blockstr[1] = ' ';
15433 
15434       blockstr[2] = '\0';
15435 
15436       snprintf(statestr, sizeof(statestr), "%s", "In Service");
15437 
15438       ast_cli(a->fd, FORMAT, tmps, tmp->exten, tmp->context, tmp->language, tmp->mohinterpret, blockstr, statestr);
15439    }
15440    ast_mutex_unlock(&iflock);
15441    return CLI_SUCCESS;
15442 #undef FORMAT
15443 #undef FORMAT2
15444 }
15445 
15446 static char *dahdi_show_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15447 {
15448    int channel;
15449    struct dahdi_pvt *tmp = NULL;
15450    struct dahdi_confinfo ci;
15451    struct dahdi_params ps;
15452    int x;
15453 
15454    switch (cmd) {
15455    case CLI_INIT:
15456       e->command = "dahdi show channel";
15457       e->usage =
15458          "Usage: dahdi show channel <chan num>\n"
15459          "  Detailed information about a given channel\n";
15460       return NULL;
15461    case CLI_GENERATE:
15462       return NULL;
15463    }
15464 
15465    if (a->argc != 4)
15466       return CLI_SHOWUSAGE;
15467 
15468    channel = atoi(a->argv[3]);
15469 
15470    ast_mutex_lock(&iflock);
15471    for (tmp = iflist; tmp; tmp = tmp->next) {
15472       if (tmp->channel == channel) {
15473          ast_cli(a->fd, "Channel: %d\n", tmp->channel);
15474          ast_cli(a->fd, "File Descriptor: %d\n", tmp->subs[SUB_REAL].dfd);
15475          ast_cli(a->fd, "Span: %d\n", tmp->span);
15476          ast_cli(a->fd, "Extension: %s\n", tmp->exten);
15477          ast_cli(a->fd, "Dialing: %s\n", tmp->dialing ? "yes" : "no");
15478          ast_cli(a->fd, "Context: %s\n", tmp->context);
15479          ast_cli(a->fd, "Caller ID: %s\n", tmp->cid_num);
15480          ast_cli(a->fd, "Calling TON: %d\n", tmp->cid_ton);
15481 #if defined(HAVE_PRI)
15482 #if defined(HAVE_PRI_SUBADDR)
15483          ast_cli(a->fd, "Caller ID subaddress: %s\n", tmp->cid_subaddr);
15484 #endif   /* defined(HAVE_PRI_SUBADDR) */
15485 #endif   /* defined(HAVE_PRI) */
15486          ast_cli(a->fd, "Caller ID name: %s\n", tmp->cid_name);
15487          ast_cli(a->fd, "Mailbox: %s\n", S_OR(tmp->mailbox, "none"));
15488          if (tmp->vars) {
15489             struct ast_variable *v;
15490             ast_cli(a->fd, "Variables:\n");
15491             for (v = tmp->vars ; v ; v = v->next)
15492                ast_cli(a->fd, "       %s = %s\n", v->name, v->value);
15493          }
15494          ast_cli(a->fd, "Destroy: %d\n", tmp->destroy);
15495          ast_cli(a->fd, "InAlarm: %d\n", tmp->inalarm);
15496          ast_cli(a->fd, "Signalling Type: %s\n", sig2str(tmp->sig));
15497          ast_cli(a->fd, "Radio: %d\n", tmp->radio);
15498          ast_cli(a->fd, "Owner: %s\n", tmp->owner ? tmp->owner->name : "<None>");
15499          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)" : "");
15500          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)" : "");
15501          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)" : "");
15502          ast_cli(a->fd, "Confno: %d\n", tmp->confno);
15503          ast_cli(a->fd, "Propagated Conference: %d\n", tmp->propconfno);
15504          ast_cli(a->fd, "Real in conference: %d\n", tmp->inconference);
15505          ast_cli(a->fd, "DSP: %s\n", tmp->dsp ? "yes" : "no");
15506          ast_cli(a->fd, "Busy Detection: %s\n", tmp->busydetect ? "yes" : "no");
15507          if (tmp->busydetect) {
15508 #if defined(BUSYDETECT_TONEONLY)
15509             ast_cli(a->fd, "    Busy Detector Helper: BUSYDETECT_TONEONLY\n");
15510 #elif defined(BUSYDETECT_COMPARE_TONE_AND_SILENCE)
15511             ast_cli(a->fd, "    Busy Detector Helper: BUSYDETECT_COMPARE_TONE_AND_SILENCE\n");
15512 #endif
15513 #ifdef BUSYDETECT_DEBUG
15514             ast_cli(a->fd, "    Busy Detector Debug: Enabled\n");
15515 #endif
15516             ast_cli(a->fd, "    Busy Count: %d\n", tmp->busycount);
15517             ast_cli(a->fd, "    Busy Pattern: %d,%d\n", tmp->busy_tonelength, tmp->busy_quietlength);
15518          }
15519          ast_cli(a->fd, "TDD: %s\n", tmp->tdd ? "yes" : "no");
15520          ast_cli(a->fd, "Relax DTMF: %s\n", tmp->dtmfrelax ? "yes" : "no");
15521          ast_cli(a->fd, "Dialing/CallwaitCAS: %d/%d\n", tmp->dialing, tmp->callwaitcas);
15522          ast_cli(a->fd, "Default law: %s\n", tmp->law_default == DAHDI_LAW_MULAW ? "ulaw" : tmp->law_default == DAHDI_LAW_ALAW ? "alaw" : "unknown");
15523          ast_cli(a->fd, "Fax Handled: %s\n", tmp->faxhandled ? "yes" : "no");
15524          ast_cli(a->fd, "Pulse phone: %s\n", tmp->pulsedial ? "yes" : "no");
15525          ast_cli(a->fd, "Gains (RX/TX): %.2f/%.2f\n", tmp->rxgain, tmp->txgain);
15526          ast_cli(a->fd, "Dynamic Range Compression (RX/TX): %.2f/%.2f\n", tmp->rxdrc, tmp->txdrc);
15527          ast_cli(a->fd, "DND: %s\n", dahdi_dnd(tmp, -1) ? "yes" : "no");
15528          ast_cli(a->fd, "Echo Cancellation:\n");
15529 
15530          if (tmp->echocancel.head.tap_length) {
15531             ast_cli(a->fd, "\t%d taps\n", tmp->echocancel.head.tap_length);
15532             for (x = 0; x < tmp->echocancel.head.param_count; x++) {
15533                ast_cli(a->fd, "\t\t%s: %ud\n", tmp->echocancel.params[x].name, tmp->echocancel.params[x].value);
15534             }
15535             ast_cli(a->fd, "\t%scurrently %s\n", tmp->echocanbridged ? "" : "(unless TDM bridged) ", tmp->echocanon ? "ON" : "OFF");
15536          } else {
15537             ast_cli(a->fd, "\tnone\n");
15538          }
15539          ast_cli(a->fd, "Wait for dialtone: %dms\n", tmp->waitfordialtone);
15540          if (tmp->master)
15541             ast_cli(a->fd, "Master Channel: %d\n", tmp->master->channel);
15542          for (x = 0; x < MAX_SLAVES; x++) {
15543             if (tmp->slaves[x])
15544                ast_cli(a->fd, "Slave Channel: %d\n", tmp->slaves[x]->channel);
15545          }
15546 #ifdef HAVE_OPENR2
15547          if (tmp->mfcr2) {
15548             char calldir[OR2_MAX_PATH];
15549             openr2_context_t *r2context = openr2_chan_get_context(tmp->r2chan);
15550             openr2_variant_t r2variant = openr2_context_get_variant(r2context);
15551             ast_cli(a->fd, "MFC/R2 MF State: %s\n", openr2_chan_get_mf_state_string(tmp->r2chan));
15552             ast_cli(a->fd, "MFC/R2 MF Group: %s\n", openr2_chan_get_mf_group_string(tmp->r2chan));
15553             ast_cli(a->fd, "MFC/R2 State: %s\n", openr2_chan_get_r2_state_string(tmp->r2chan));
15554             ast_cli(a->fd, "MFC/R2 Call State: %s\n", openr2_chan_get_call_state_string(tmp->r2chan));
15555             ast_cli(a->fd, "MFC/R2 Call Files Enabled: %s\n", openr2_chan_get_call_files_enabled(tmp->r2chan) ? "Yes" : "No");
15556             ast_cli(a->fd, "MFC/R2 Variant: %s\n", openr2_proto_get_variant_string(r2variant));
15557             ast_cli(a->fd, "MFC/R2 Max ANI: %d\n", openr2_context_get_max_ani(r2context));
15558             ast_cli(a->fd, "MFC/R2 Max DNIS: %d\n", openr2_context_get_max_dnis(r2context));
15559             ast_cli(a->fd, "MFC/R2 Get ANI First: %s\n", openr2_context_get_ani_first(r2context) ? "Yes" : "No");
15560 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
15561             ast_cli(a->fd, "MFC/R2 Skip Category Request: %s\n", openr2_context_get_skip_category_request(r2context) ? "Yes" : "No");
15562 #endif
15563             ast_cli(a->fd, "MFC/R2 Immediate Accept: %s\n", openr2_context_get_immediate_accept(r2context) ? "Yes" : "No");
15564             ast_cli(a->fd, "MFC/R2 Accept on Offer: %s\n", tmp->mfcr2_accept_on_offer ? "Yes" : "No");
15565             ast_cli(a->fd, "MFC/R2 Charge Calls: %s\n", tmp->mfcr2_charge_calls ? "Yes" : "No");
15566             ast_cli(a->fd, "MFC/R2 Allow Collect Calls: %s\n", tmp->mfcr2_allow_collect_calls ? "Yes" : "No");
15567             ast_cli(a->fd, "MFC/R2 Forced Release: %s\n", tmp->mfcr2_forced_release ? "Yes" : "No");
15568             ast_cli(a->fd, "MFC/R2 MF Back Timeout: %dms\n", openr2_context_get_mf_back_timeout(r2context));
15569             ast_cli(a->fd, "MFC/R2 R2 Metering Pulse Timeout: %dms\n", openr2_context_get_metering_pulse_timeout(r2context));
15570             ast_cli(a->fd, "MFC/R2 Rx CAS: %s\n", openr2_chan_get_rx_cas_string(tmp->r2chan));
15571             ast_cli(a->fd, "MFC/R2 Tx CAS: %s\n", openr2_chan_get_tx_cas_string(tmp->r2chan));
15572             ast_cli(a->fd, "MFC/R2 MF Tx Signal: %d\n", openr2_chan_get_tx_mf_signal(tmp->r2chan));
15573             ast_cli(a->fd, "MFC/R2 MF Rx Signal: %d\n", openr2_chan_get_rx_mf_signal(tmp->r2chan));
15574             ast_cli(a->fd, "MFC/R2 Call Files Directory: %s\n", openr2_context_get_log_directory(r2context, calldir, sizeof(calldir)));
15575          }
15576 #endif
15577 #if defined(HAVE_SS7)
15578          if (tmp->ss7) {
15579             struct sig_ss7_chan *chan = tmp->sig_pvt;
15580 
15581             ast_cli(a->fd, "CIC: %d\n", chan->cic);
15582          }
15583 #endif   /* defined(HAVE_SS7) */
15584 #ifdef HAVE_PRI
15585          if (tmp->pri) {
15586             struct sig_pri_chan *chan = tmp->sig_pvt;
15587 
15588             ast_cli(a->fd, "PRI Flags: ");
15589             if (chan->resetting != SIG_PRI_RESET_IDLE) {
15590                ast_cli(a->fd, "Resetting=%d ", chan->resetting);
15591             }
15592             if (chan->call)
15593                ast_cli(a->fd, "Call ");
15594             if (chan->allocated) {
15595                ast_cli(a->fd, "Allocated ");
15596             }
15597             ast_cli(a->fd, "\n");
15598             if (tmp->logicalspan)
15599                ast_cli(a->fd, "PRI Logical Span: %d\n", tmp->logicalspan);
15600             else
15601                ast_cli(a->fd, "PRI Logical Span: Implicit\n");
15602          }
15603 #endif
15604          memset(&ci, 0, sizeof(ci));
15605          ps.channo = tmp->channel;
15606          if (tmp->subs[SUB_REAL].dfd > -1) {
15607             memset(&ci, 0, sizeof(ci));
15608             if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
15609                ast_cli(a->fd, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci.confno, ci.confmode);
15610             }
15611             if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONFMUTE, &x)) {
15612                ast_cli(a->fd, "Actual Confmute: %s\n", x ? "Yes" : "No");
15613             }
15614             memset(&ps, 0, sizeof(ps));
15615             if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
15616                ast_log(LOG_WARNING, "Failed to get parameters on channel %d: %s\n", tmp->channel, strerror(errno));
15617             } else {
15618                ast_cli(a->fd, "Hookstate (FXS only): %s\n", ps.rxisoffhook ? "Offhook" : "Onhook");
15619             }
15620          }
15621          ast_mutex_unlock(&iflock);
15622          return CLI_SUCCESS;
15623       }
15624    }
15625    ast_mutex_unlock(&iflock);
15626 
15627    ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15628    return CLI_FAILURE;
15629 }
15630 
15631 static char *handle_dahdi_show_cadences(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15632 {
15633    int i, j;
15634    switch (cmd) {
15635    case CLI_INIT:
15636       e->command = "dahdi show cadences";
15637       e->usage =
15638          "Usage: dahdi show cadences\n"
15639          "       Shows all cadences currently defined\n";
15640       return NULL;
15641    case CLI_GENERATE:
15642       return NULL;
15643    }
15644    for (i = 0; i < num_cadence; i++) {
15645       char output[1024];
15646       char tmp[16], tmp2[64];
15647       snprintf(tmp, sizeof(tmp), "r%d: ", i + 1);
15648       term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output));
15649 
15650       for (j = 0; j < 16; j++) {
15651          if (cadences[i].ringcadence[j] == 0)
15652             break;
15653          snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]);
15654          if (cidrings[i] * 2 - 1 == j)
15655             term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1);
15656          else
15657             term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1);
15658          if (j != 0)
15659             strncat(output, ",", sizeof(output) - strlen(output) - 1);
15660          strncat(output, tmp2, sizeof(output) - strlen(output) - 1);
15661       }
15662       ast_cli(a->fd,"%s\n",output);
15663    }
15664    return CLI_SUCCESS;
15665 }
15666 
15667 /* Based on irqmiss.c */
15668 static char *dahdi_show_status(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15669 {
15670    #define FORMAT "%-40.40s %-7.7s %-6d %-6d %-6d %-3.3s %-4.4s %-8.8s %s\n"
15671    #define FORMAT2 "%-40.40s %-7.7s %-6.6s %-6.6s %-6.6s %-3.3s %-4.4s %-8.8s %s\n"
15672    int span;
15673    int res;
15674    char alarmstr[50];
15675 
15676    int ctl;
15677    struct dahdi_spaninfo s;
15678 
15679    switch (cmd) {
15680    case CLI_INIT:
15681       e->command = "dahdi show status";
15682       e->usage =
15683          "Usage: dahdi show status\n"
15684          "       Shows a list of DAHDI cards with status\n";
15685       return NULL;
15686    case CLI_GENERATE:
15687       return NULL;
15688    }
15689    ctl = open("/dev/dahdi/ctl", O_RDWR);
15690    if (ctl < 0) {
15691       ast_cli(a->fd, "No DAHDI found. Unable to open /dev/dahdi/ctl: %s\n", strerror(errno));
15692       return CLI_FAILURE;
15693    }
15694    ast_cli(a->fd, FORMAT2, "Description", "Alarms", "IRQ", "bpviol", "CRC", "Framing", "Coding", "Options", "LBO");
15695 
15696    for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
15697       s.spanno = span;
15698       res = ioctl(ctl, DAHDI_SPANSTAT, &s);
15699       if (res) {
15700          continue;
15701       }
15702       alarmstr[0] = '\0';
15703       if (s.alarms > 0) {
15704          if (s.alarms & DAHDI_ALARM_BLUE)
15705             strcat(alarmstr, "BLU/");
15706          if (s.alarms & DAHDI_ALARM_YELLOW)
15707             strcat(alarmstr, "YEL/");
15708          if (s.alarms & DAHDI_ALARM_RED)
15709             strcat(alarmstr, "RED/");
15710          if (s.alarms & DAHDI_ALARM_LOOPBACK)
15711             strcat(alarmstr, "LB/");
15712          if (s.alarms & DAHDI_ALARM_RECOVER)
15713             strcat(alarmstr, "REC/");
15714          if (s.alarms & DAHDI_ALARM_NOTOPEN)
15715             strcat(alarmstr, "NOP/");
15716          if (!strlen(alarmstr))
15717             strcat(alarmstr, "UUU/");
15718          if (strlen(alarmstr)) {
15719             /* Strip trailing / */
15720             alarmstr[strlen(alarmstr) - 1] = '\0';
15721          }
15722       } else {
15723          if (s.numchans)
15724             strcpy(alarmstr, "OK");
15725          else
15726             strcpy(alarmstr, "UNCONFIGURED");
15727       }
15728 
15729       ast_cli(a->fd, FORMAT, s.desc, alarmstr, s.irqmisses, s.bpvcount, s.crc4count,
15730          s.lineconfig & DAHDI_CONFIG_D4 ? "D4" :
15731          s.lineconfig & DAHDI_CONFIG_ESF ? "ESF" :
15732          s.lineconfig & DAHDI_CONFIG_CCS ? "CCS" :
15733          "CAS",
15734          s.lineconfig & DAHDI_CONFIG_B8ZS ? "B8ZS" :
15735          s.lineconfig & DAHDI_CONFIG_HDB3 ? "HDB3" :
15736          s.lineconfig & DAHDI_CONFIG_AMI ? "AMI" :
15737          "Unk",
15738          s.lineconfig & DAHDI_CONFIG_CRC4 ?
15739             s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" :
15740             s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "YEL" : "",
15741          lbostr[s.lbo]
15742          );
15743    }
15744    close(ctl);
15745 
15746    return CLI_SUCCESS;
15747 #undef FORMAT
15748 #undef FORMAT2
15749 }
15750 
15751 static char *dahdi_show_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15752 {
15753    int pseudo_fd = -1;
15754    struct dahdi_versioninfo vi;
15755 
15756    switch (cmd) {
15757    case CLI_INIT:
15758       e->command = "dahdi show version";
15759       e->usage =
15760          "Usage: dahdi show version\n"
15761          "       Shows the DAHDI version in use\n";
15762       return NULL;
15763    case CLI_GENERATE:
15764       return NULL;
15765    }
15766    if ((pseudo_fd = open("/dev/dahdi/ctl", O_RDONLY)) < 0) {
15767       ast_cli(a->fd, "Failed to open control file to get version.\n");
15768       return CLI_SUCCESS;
15769    }
15770 
15771    strcpy(vi.version, "Unknown");
15772    strcpy(vi.echo_canceller, "Unknown");
15773 
15774    if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi))
15775       ast_cli(a->fd, "Failed to get DAHDI version: %s\n", strerror(errno));
15776    else
15777       ast_cli(a->fd, "DAHDI Version: %s Echo Canceller: %s\n", vi.version, vi.echo_canceller);
15778 
15779    close(pseudo_fd);
15780 
15781    return CLI_SUCCESS;
15782 }
15783 
15784 static char *dahdi_set_hwgain(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15785 {
15786    int channel;
15787    int gain;
15788    int tx;
15789    struct dahdi_hwgain hwgain;
15790    struct dahdi_pvt *tmp = NULL;
15791 
15792    switch (cmd) {
15793    case CLI_INIT:
15794       e->command = "dahdi set hwgain {rx|tx}";
15795       e->usage =
15796          "Usage: dahdi set hwgain <rx|tx> <chan#> <gain>\n"
15797          "   Sets the hardware gain on a given channel.  Changes take effect\n"
15798          "   immediately whether the channel is in use or not.\n"
15799          "\n"
15800          "   <rx|tx> which direction do you want to change (relative to our module)\n"
15801          "   <chan num> is the channel number relative to the device\n"
15802          "   <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n"
15803          "\n"
15804          "   Please note:\n"
15805          "   * This is currently the only way to set hwgain by the channel driver.\n"
15806          "   * hwgain is only supportable by hardware with analog ports because\n"
15807          "     hwgain works on the analog side of an analog-digital conversion.\n";
15808       return NULL;
15809    case CLI_GENERATE:
15810       return NULL;
15811    }
15812 
15813    if (a->argc != 6)
15814       return CLI_SHOWUSAGE;
15815 
15816    if (!strcasecmp("rx", a->argv[3]))
15817       tx = 0; /* rx */
15818    else if (!strcasecmp("tx", a->argv[3]))
15819       tx = 1; /* tx */
15820    else
15821       return CLI_SHOWUSAGE;
15822 
15823    channel = atoi(a->argv[4]);
15824    gain = atof(a->argv[5])*10.0;
15825 
15826    ast_mutex_lock(&iflock);
15827 
15828    for (tmp = iflist; tmp; tmp = tmp->next) {
15829 
15830       if (tmp->channel != channel)
15831          continue;
15832 
15833       if (tmp->subs[SUB_REAL].dfd == -1)
15834          break;
15835 
15836       hwgain.newgain = gain;
15837       hwgain.tx = tx;
15838       if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_HWGAIN, &hwgain) < 0) {
15839          ast_cli(a->fd, "Unable to set the hardware gain for channel %d: %s\n", channel, strerror(errno));
15840          ast_mutex_unlock(&iflock);
15841          return CLI_FAILURE;
15842       }
15843       ast_cli(a->fd, "hardware %s gain set to %d (%.1f dB) on channel %d\n",
15844          tx ? "tx" : "rx", gain, (float)gain/10.0, channel);
15845       break;
15846    }
15847 
15848    ast_mutex_unlock(&iflock);
15849 
15850    if (tmp)
15851       return CLI_SUCCESS;
15852 
15853    ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15854    return CLI_FAILURE;
15855 
15856 }
15857 
15858 static char *dahdi_set_swgain(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15859 {
15860    int channel;
15861    float gain;
15862    int tx;
15863    int res;
15864    struct dahdi_pvt *tmp = NULL;
15865 
15866    switch (cmd) {
15867    case CLI_INIT:
15868       e->command = "dahdi set swgain {rx|tx}";
15869       e->usage =
15870          "Usage: dahdi set swgain <rx|tx> <chan#> <gain>\n"
15871          "   Sets the software gain on a given channel and overrides the\n"
15872          "   value provided at module loadtime.  Changes take effect\n"
15873          "   immediately whether the channel is in use or not.\n"
15874          "\n"
15875          "   <rx|tx> which direction do you want to change (relative to our module)\n"
15876          "   <chan num> is the channel number relative to the device\n"
15877          "   <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
15878       return NULL;
15879    case CLI_GENERATE:
15880       return NULL;
15881    }
15882 
15883    if (a->argc != 6)
15884       return CLI_SHOWUSAGE;
15885 
15886    if (!strcasecmp("rx", a->argv[3]))
15887       tx = 0; /* rx */
15888    else if (!strcasecmp("tx", a->argv[3]))
15889       tx = 1; /* tx */
15890    else
15891       return CLI_SHOWUSAGE;
15892 
15893    channel = atoi(a->argv[4]);
15894    gain = atof(a->argv[5]);
15895 
15896    ast_mutex_lock(&iflock);
15897    for (tmp = iflist; tmp; tmp = tmp->next) {
15898 
15899       if (tmp->channel != channel)
15900          continue;
15901 
15902       if (tmp->subs[SUB_REAL].dfd == -1)
15903          break;
15904 
15905       if (tx)
15906          res = set_actual_txgain(tmp->subs[SUB_REAL].dfd, gain, tmp->txdrc, tmp->law);
15907       else
15908          res = set_actual_rxgain(tmp->subs[SUB_REAL].dfd, gain, tmp->rxdrc, tmp->law);
15909 
15910       if (res) {
15911          ast_cli(a->fd, "Unable to set the software gain for channel %d\n", channel);
15912          ast_mutex_unlock(&iflock);
15913          return CLI_FAILURE;
15914       }
15915 
15916       ast_cli(a->fd, "software %s gain set to %.1f on channel %d\n",
15917          tx ? "tx" : "rx", gain, channel);
15918 
15919       if (tx) {
15920          tmp->txgain = gain;
15921       } else {
15922          tmp->rxgain = gain;
15923       }
15924       break;
15925    }
15926    ast_mutex_unlock(&iflock);
15927 
15928    if (tmp)
15929       return CLI_SUCCESS;
15930 
15931    ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15932    return CLI_FAILURE;
15933 
15934 }
15935 
15936 static char *dahdi_set_dnd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15937 {
15938    int channel;
15939    int on;
15940    struct dahdi_pvt *dahdi_chan = NULL;
15941 
15942    switch (cmd) {
15943    case CLI_INIT:
15944       e->command = "dahdi set dnd";
15945       e->usage =
15946          "Usage: dahdi set dnd <chan#> <on|off>\n"
15947          "  Sets/resets DND (Do Not Disturb) mode on a channel.\n"
15948          "  Changes take effect immediately.\n"
15949          "  <chan num> is the channel number\n"
15950          "  <on|off> Enable or disable DND mode?\n"
15951          ;
15952       return NULL;
15953    case CLI_GENERATE:
15954       return NULL;
15955    }
15956 
15957    if (a->argc != 5)
15958       return CLI_SHOWUSAGE;
15959 
15960    if ((channel = atoi(a->argv[3])) <= 0) {
15961       ast_cli(a->fd, "Expected channel number, got '%s'\n", a->argv[3]);
15962       return CLI_SHOWUSAGE;
15963    }
15964 
15965    if (ast_true(a->argv[4]))
15966       on = 1;
15967    else if (ast_false(a->argv[4]))
15968       on = 0;
15969    else {
15970       ast_cli(a->fd, "Expected 'on' or 'off', got '%s'\n", a->argv[4]);
15971       return CLI_SHOWUSAGE;
15972    }
15973 
15974    ast_mutex_lock(&iflock);
15975    for (dahdi_chan = iflist; dahdi_chan; dahdi_chan = dahdi_chan->next) {
15976       if (dahdi_chan->channel != channel)
15977          continue;
15978 
15979       /* Found the channel. Actually set it */
15980       dahdi_dnd(dahdi_chan, on);
15981       break;
15982    }
15983    ast_mutex_unlock(&iflock);
15984 
15985    if (!dahdi_chan) {
15986       ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15987       return CLI_FAILURE;
15988    }
15989 
15990    return CLI_SUCCESS;
15991 }
15992 
15993 static struct ast_cli_entry dahdi_cli[] = {
15994    AST_CLI_DEFINE(handle_dahdi_show_cadences, "List cadences"),
15995    AST_CLI_DEFINE(dahdi_show_channels, "Show active DAHDI channels"),
15996    AST_CLI_DEFINE(dahdi_show_channel, "Show information on a channel"),
15997    AST_CLI_DEFINE(dahdi_destroy_channel, "Destroy a channel"),
15998    AST_CLI_DEFINE(dahdi_restart_cmd, "Fully restart DAHDI channels"),
15999    AST_CLI_DEFINE(dahdi_show_status, "Show all DAHDI cards status"),
16000    AST_CLI_DEFINE(dahdi_show_version, "Show the DAHDI version in use"),
16001    AST_CLI_DEFINE(dahdi_set_hwgain, "Set hardware gain on a channel"),
16002    AST_CLI_DEFINE(dahdi_set_swgain, "Set software gain on a channel"),
16003    AST_CLI_DEFINE(dahdi_set_dnd, "Sets/resets DND (Do Not Disturb) mode on a channel"),
16004 };
16005 
16006 #define TRANSFER  0
16007 #define HANGUP    1
16008 
16009 static int dahdi_fake_event(struct dahdi_pvt *p, int mode)
16010 {
16011    if (p) {
16012       switch (mode) {
16013       case TRANSFER:
16014          p->fake_event = DAHDI_EVENT_WINKFLASH;
16015          break;
16016       case HANGUP:
16017          p->fake_event = DAHDI_EVENT_ONHOOK;
16018          break;
16019       default:
16020          ast_log(LOG_WARNING, "I don't know how to handle transfer event with this: %d on channel %s\n",mode, p->owner->name);
16021       }
16022    }
16023    return 0;
16024 }
16025 static struct dahdi_pvt *find_channel(int channel)
16026 {
16027    struct dahdi_pvt *p;
16028 
16029    ast_mutex_lock(&iflock);
16030    for (p = iflist; p; p = p->next) {
16031       if (p->channel == channel) {
16032          break;
16033       }
16034    }
16035    ast_mutex_unlock(&iflock);
16036    return p;
16037 }
16038 
16039 /*!
16040  * \internal
16041  * \brief Get private struct using given numeric channel string.
16042  *
16043  * \param channel Numeric channel number string get private struct.
16044  *
16045  * \retval pvt on success.
16046  * \retval NULL on error.
16047  */
16048 static struct dahdi_pvt *find_channel_from_str(const char *channel)
16049 {
16050    int chan_num;
16051 
16052    if (sscanf(channel, "%30d", &chan_num) != 1) {
16053       /* Not numeric string. */
16054       return NULL;
16055    }
16056 
16057    return find_channel(chan_num);
16058 }
16059 
16060 static int action_dahdidndon(struct mansession *s, const struct message *m)
16061 {
16062    struct dahdi_pvt *p;
16063    const char *channel = astman_get_header(m, "DAHDIChannel");
16064 
16065    if (ast_strlen_zero(channel)) {
16066       astman_send_error(s, m, "No channel specified");
16067       return 0;
16068    }
16069    p = find_channel_from_str(channel);
16070    if (!p) {
16071       astman_send_error(s, m, "No such channel");
16072       return 0;
16073    }
16074    dahdi_dnd(p, 1);
16075    astman_send_ack(s, m, "DND Enabled");
16076    return 0;
16077 }
16078 
16079 static int action_dahdidndoff(struct mansession *s, const struct message *m)
16080 {
16081    struct dahdi_pvt *p;
16082    const char *channel = astman_get_header(m, "DAHDIChannel");
16083 
16084    if (ast_strlen_zero(channel)) {
16085       astman_send_error(s, m, "No channel specified");
16086       return 0;
16087    }
16088    p = find_channel_from_str(channel);
16089    if (!p) {
16090       astman_send_error(s, m, "No such channel");
16091       return 0;
16092    }
16093    dahdi_dnd(p, 0);
16094    astman_send_ack(s, m, "DND Disabled");
16095    return 0;
16096 }
16097 
16098 static int action_transfer(struct mansession *s, const struct message *m)
16099 {
16100    struct dahdi_pvt *p;
16101    const char *channel = astman_get_header(m, "DAHDIChannel");
16102 
16103    if (ast_strlen_zero(channel)) {
16104       astman_send_error(s, m, "No channel specified");
16105       return 0;
16106    }
16107    p = find_channel_from_str(channel);
16108    if (!p) {
16109       astman_send_error(s, m, "No such channel");
16110       return 0;
16111    }
16112    if (!analog_lib_handles(p->sig, 0, 0)) {
16113       astman_send_error(s, m, "Channel signaling is not analog");
16114       return 0;
16115    }
16116    dahdi_fake_event(p,TRANSFER);
16117    astman_send_ack(s, m, "DAHDITransfer");
16118    return 0;
16119 }
16120 
16121 static int action_transferhangup(struct mansession *s, const struct message *m)
16122 {
16123    struct dahdi_pvt *p;
16124    const char *channel = astman_get_header(m, "DAHDIChannel");
16125 
16126    if (ast_strlen_zero(channel)) {
16127       astman_send_error(s, m, "No channel specified");
16128       return 0;
16129    }
16130    p = find_channel_from_str(channel);
16131    if (!p) {
16132       astman_send_error(s, m, "No such channel");
16133       return 0;
16134    }
16135    if (!analog_lib_handles(p->sig, 0, 0)) {
16136       astman_send_error(s, m, "Channel signaling is not analog");
16137       return 0;
16138    }
16139    dahdi_fake_event(p,HANGUP);
16140    astman_send_ack(s, m, "DAHDIHangup");
16141    return 0;
16142 }
16143 
16144 static int action_dahdidialoffhook(struct mansession *s, const struct message *m)
16145 {
16146    struct dahdi_pvt *p;
16147    const char *channel = astman_get_header(m, "DAHDIChannel");
16148    const char *number = astman_get_header(m, "Number");
16149    int i;
16150 
16151    if (ast_strlen_zero(channel)) {
16152       astman_send_error(s, m, "No channel specified");
16153       return 0;
16154    }
16155    if (ast_strlen_zero(number)) {
16156       astman_send_error(s, m, "No number specified");
16157       return 0;
16158    }
16159    p = find_channel_from_str(channel);
16160    if (!p) {
16161       astman_send_error(s, m, "No such channel");
16162       return 0;
16163    }
16164    if (!p->owner) {
16165       astman_send_error(s, m, "Channel does not have it's owner");
16166       return 0;
16167    }
16168    for (i = 0; i < strlen(number); i++) {
16169       struct ast_frame f = { AST_FRAME_DTMF, .subclass.integer = number[i] };
16170       dahdi_queue_frame(p, &f);
16171    }
16172    astman_send_ack(s, m, "DAHDIDialOffhook");
16173    return 0;
16174 }
16175 
16176 static int action_dahdishowchannels(struct mansession *s, const struct message *m)
16177 {
16178    struct dahdi_pvt *tmp = NULL;
16179    const char *id = astman_get_header(m, "ActionID");
16180    const char *dahdichannel = astman_get_header(m, "DAHDIChannel");
16181    char idText[256] = "";
16182    int channels = 0;
16183    int dahdichanquery;
16184 
16185    if (!dahdichannel || sscanf(dahdichannel, "%30d", &dahdichanquery) != 1) {
16186       /* Not numeric string. */
16187       dahdichanquery = -1;
16188    }
16189 
16190    astman_send_ack(s, m, "DAHDI channel status will follow");
16191    if (!ast_strlen_zero(id))
16192       snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
16193 
16194    ast_mutex_lock(&iflock);
16195 
16196    for (tmp = iflist; tmp; tmp = tmp->next) {
16197       if (tmp->channel > 0) {
16198          int alm;
16199 
16200          /* If a specific channel is queried for, only deliver status for that channel */
16201          if (dahdichanquery > 0 && tmp->channel != dahdichanquery)
16202             continue;
16203 
16204          alm = get_alarms(tmp);
16205          channels++;
16206          if (tmp->owner) {
16207             /* Add data if we have a current call */
16208             astman_append(s,
16209                "Event: DAHDIShowChannels\r\n"
16210                "DAHDIChannel: %d\r\n"
16211                "Channel: %s\r\n"
16212                "Uniqueid: %s\r\n"
16213                "AccountCode: %s\r\n"
16214                "Signalling: %s\r\n"
16215                "SignallingCode: %d\r\n"
16216                "Context: %s\r\n"
16217                "DND: %s\r\n"
16218                "Alarm: %s\r\n"
16219                "%s"
16220                "\r\n",
16221                tmp->channel,
16222                tmp->owner->name,
16223                tmp->owner->uniqueid,
16224                tmp->owner->accountcode,
16225                sig2str(tmp->sig),
16226                tmp->sig,
16227                tmp->context,
16228                dahdi_dnd(tmp, -1) ? "Enabled" : "Disabled",
16229                alarm2str(alm), idText);
16230          } else {
16231             astman_append(s,
16232                "Event: DAHDIShowChannels\r\n"
16233                "DAHDIChannel: %d\r\n"
16234                "Signalling: %s\r\n"
16235                "SignallingCode: %d\r\n"
16236                "Context: %s\r\n"
16237                "DND: %s\r\n"
16238                "Alarm: %s\r\n"
16239                "%s"
16240                "\r\n",
16241                tmp->channel, sig2str(tmp->sig), tmp->sig,
16242                tmp->context,
16243                dahdi_dnd(tmp, -1) ? "Enabled" : "Disabled",
16244                alarm2str(alm), idText);
16245          }
16246       }
16247    }
16248 
16249    ast_mutex_unlock(&iflock);
16250 
16251    astman_append(s,
16252       "Event: DAHDIShowChannelsComplete\r\n"
16253       "%s"
16254       "Items: %d\r\n"
16255       "\r\n",
16256       idText,
16257       channels);
16258    return 0;
16259 }
16260 
16261 #if defined(HAVE_SS7)
16262 static int linkset_addsigchan(int sigchan)
16263 {
16264    struct dahdi_ss7 *link;
16265    int res;
16266    int curfd;
16267    struct dahdi_params params;
16268    struct dahdi_bufferinfo bi;
16269    struct dahdi_spaninfo si;
16270 
16271    if (sigchan < 0) {
16272       ast_log(LOG_ERROR, "Invalid sigchan!\n");
16273       return -1;
16274    }
16275    if (cur_ss7type < 0) {
16276       ast_log(LOG_ERROR, "Unspecified or invalid ss7type\n");
16277       return -1;
16278    }
16279    if (cur_pointcode < 0) {
16280       ast_log(LOG_ERROR, "Unspecified pointcode!\n");
16281       return -1;
16282    }
16283    if (cur_adjpointcode < 0) {
16284       ast_log(LOG_ERROR, "Unspecified adjpointcode!\n");
16285       return -1;
16286    }
16287    if (cur_defaultdpc < 0) {
16288       ast_log(LOG_ERROR, "Unspecified defaultdpc!\n");
16289       return -1;
16290    }
16291    if (cur_networkindicator < 0) {
16292       ast_log(LOG_ERROR, "Invalid networkindicator!\n");
16293       return -1;
16294    }
16295    link = ss7_resolve_linkset(cur_linkset);
16296    if (!link) {
16297       ast_log(LOG_ERROR, "Invalid linkset number.  Must be between 1 and %d\n", NUM_SPANS + 1);
16298       return -1;
16299    }
16300    if (link->ss7.numsigchans >= SIG_SS7_NUM_DCHANS) {
16301       ast_log(LOG_ERROR, "Too many sigchans on linkset %d\n", cur_linkset);
16302       return -1;
16303    }
16304 
16305    curfd = link->ss7.numsigchans;
16306 
16307    /* Open signaling channel */
16308    link->ss7.fds[curfd] = open("/dev/dahdi/channel", O_RDWR, 0600);
16309    if (link->ss7.fds[curfd] < 0) {
16310       ast_log(LOG_ERROR, "Unable to open SS7 sigchan %d (%s)\n", sigchan,
16311          strerror(errno));
16312       return -1;
16313    }
16314    if (ioctl(link->ss7.fds[curfd], DAHDI_SPECIFY, &sigchan) == -1) {
16315       dahdi_close_ss7_fd(link, curfd);
16316       ast_log(LOG_ERROR, "Unable to specify SS7 sigchan %d (%s)\n", sigchan,
16317          strerror(errno));
16318       return -1;
16319    }
16320 
16321    /* Get signaling channel parameters */
16322    memset(&params, 0, sizeof(params));
16323    res = ioctl(link->ss7.fds[curfd], DAHDI_GET_PARAMS, &params);
16324    if (res) {
16325       dahdi_close_ss7_fd(link, curfd);
16326       ast_log(LOG_ERROR, "Unable to get parameters for sigchan %d (%s)\n", sigchan,
16327          strerror(errno));
16328       return -1;
16329    }
16330    if (params.sigtype != DAHDI_SIG_HDLCFCS
16331       && params.sigtype != DAHDI_SIG_HARDHDLC
16332       && params.sigtype != DAHDI_SIG_MTP2) {
16333       dahdi_close_ss7_fd(link, curfd);
16334       ast_log(LOG_ERROR, "sigchan %d is not in HDLC/FCS mode.\n", sigchan);
16335       return -1;
16336    }
16337 
16338    /* Set signaling channel buffer policy. */
16339    memset(&bi, 0, sizeof(bi));
16340    bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
16341    bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
16342    bi.numbufs = 32;
16343    bi.bufsize = 512;
16344    if (ioctl(link->ss7.fds[curfd], DAHDI_SET_BUFINFO, &bi)) {
16345       ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n",
16346          sigchan, strerror(errno));
16347       dahdi_close_ss7_fd(link, curfd);
16348       return -1;
16349    }
16350 
16351    /* Get current signaling channel alarm status. */
16352    memset(&si, 0, sizeof(si));
16353    res = ioctl(link->ss7.fds[curfd], DAHDI_SPANSTAT, &si);
16354    if (res) {
16355       dahdi_close_ss7_fd(link, curfd);
16356       ast_log(LOG_ERROR, "Unable to get span state for sigchan %d (%s)\n", sigchan,
16357          strerror(errno));
16358    }
16359 
16360    res = sig_ss7_add_sigchan(&link->ss7, curfd, cur_ss7type,
16361       (params.sigtype == DAHDI_SIG_MTP2)
16362          ? SS7_TRANSPORT_DAHDIMTP2
16363          : SS7_TRANSPORT_DAHDIDCHAN,
16364       si.alarms, cur_networkindicator, cur_pointcode, cur_adjpointcode);
16365    if (res) {
16366       dahdi_close_ss7_fd(link, curfd);
16367       return -1;
16368    }
16369 
16370    ++link->ss7.numsigchans;
16371 
16372    return 0;
16373 }
16374 #endif   /* defined(HAVE_SS7) */
16375 
16376 #if defined(HAVE_SS7)
16377 static char *handle_ss7_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16378 {
16379    int span;
16380    switch (cmd) {
16381    case CLI_INIT:
16382       e->command = "ss7 set debug {on|off} linkset";
16383       e->usage =
16384          "Usage: ss7 set debug {on|off} linkset <linkset>\n"
16385          "       Enables debugging on a given SS7 linkset\n";
16386       return NULL;
16387    case CLI_GENERATE:
16388       return NULL;
16389    }
16390    if (a->argc < 6)
16391       return CLI_SHOWUSAGE;
16392    span = atoi(a->argv[5]);
16393    if ((span < 1) || (span > NUM_SPANS)) {
16394       ast_cli(a->fd, "Invalid linkset %s.  Should be a number from %d to %d\n", a->argv[5], 1, NUM_SPANS);
16395       return CLI_SUCCESS;
16396    }
16397    if (!linksets[span-1].ss7.ss7) {
16398       ast_cli(a->fd, "No SS7 running on linkset %d\n", span);
16399    } else {
16400       if (!strcasecmp(a->argv[3], "on")) {
16401          linksets[span - 1].ss7.debug = 1;
16402          ss7_set_debug(linksets[span-1].ss7.ss7, SIG_SS7_DEBUG);
16403          ast_cli(a->fd, "Enabled debugging on linkset %d\n", span);
16404       } else {
16405          linksets[span - 1].ss7.debug = 0;
16406          ss7_set_debug(linksets[span-1].ss7.ss7, 0);
16407          ast_cli(a->fd, "Disabled debugging on linkset %d\n", span);
16408       }
16409    }
16410 
16411    return CLI_SUCCESS;
16412 }
16413 #endif   /* defined(HAVE_SS7) */
16414 
16415 #if defined(HAVE_SS7)
16416 static char *handle_ss7_block_cic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16417 {
16418    int linkset, cic;
16419    int blocked = -1, i;
16420    switch (cmd) {
16421    case CLI_INIT:
16422       e->command = "ss7 block cic";
16423       e->usage =
16424          "Usage: ss7 block cic <linkset> <CIC>\n"
16425          "       Sends a remote blocking request for the given CIC on the specified linkset\n";
16426       return NULL;
16427    case CLI_GENERATE:
16428       return NULL;
16429    }
16430    if (a->argc == 5)
16431       linkset = atoi(a->argv[3]);
16432    else
16433       return CLI_SHOWUSAGE;
16434 
16435    if ((linkset < 1) || (linkset > NUM_SPANS)) {
16436       ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16437       return CLI_SUCCESS;
16438    }
16439 
16440    if (!linksets[linkset-1].ss7.ss7) {
16441       ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16442       return CLI_SUCCESS;
16443    }
16444 
16445    cic = atoi(a->argv[4]);
16446 
16447    if (cic < 1) {
16448       ast_cli(a->fd, "Invalid CIC specified!\n");
16449       return CLI_SUCCESS;
16450    }
16451 
16452    for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
16453       if (linksets[linkset-1].ss7.pvts[i]->cic == cic) {
16454          blocked = linksets[linkset-1].ss7.pvts[i]->locallyblocked;
16455          if (!blocked) {
16456             ast_mutex_lock(&linksets[linkset-1].ss7.lock);
16457             isup_blo(linksets[linkset-1].ss7.ss7, cic, linksets[linkset-1].ss7.pvts[i]->dpc);
16458             ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
16459          }
16460       }
16461    }
16462 
16463    if (blocked < 0) {
16464       ast_cli(a->fd, "Invalid CIC specified!\n");
16465       return CLI_SUCCESS;
16466    }
16467 
16468    if (!blocked)
16469       ast_cli(a->fd, "Sent blocking request for linkset %d on CIC %d\n", linkset, cic);
16470    else
16471       ast_cli(a->fd, "CIC %d already locally blocked\n", cic);
16472 
16473    /* Break poll on the linkset so it sends our messages */
16474    pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
16475 
16476    return CLI_SUCCESS;
16477 }
16478 #endif   /* defined(HAVE_SS7) */
16479 
16480 #if defined(HAVE_SS7)
16481 static char *handle_ss7_block_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16482 {
16483    int linkset;
16484    int i;
16485    switch (cmd) {
16486    case CLI_INIT:
16487       e->command = "ss7 block linkset";
16488       e->usage =
16489          "Usage: ss7 block linkset <linkset number>\n"
16490          "       Sends a remote blocking request for all CICs on the given linkset\n";
16491       return NULL;
16492    case CLI_GENERATE:
16493       return NULL;
16494    }
16495    if (a->argc == 4)
16496       linkset = atoi(a->argv[3]);
16497    else
16498       return CLI_SHOWUSAGE;
16499 
16500    if ((linkset < 1) || (linkset > NUM_SPANS)) {
16501       ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16502       return CLI_SUCCESS;
16503    }
16504 
16505    if (!linksets[linkset-1].ss7.ss7) {
16506       ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16507       return CLI_SUCCESS;
16508    }
16509 
16510    for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
16511       ast_cli(a->fd, "Sending remote blocking request on CIC %d\n", linksets[linkset-1].ss7.pvts[i]->cic);
16512       ast_mutex_lock(&linksets[linkset-1].ss7.lock);
16513       isup_blo(linksets[linkset-1].ss7.ss7, linksets[linkset-1].ss7.pvts[i]->cic, linksets[linkset-1].ss7.pvts[i]->dpc);
16514       ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
16515    }
16516 
16517    /* Break poll on the linkset so it sends our messages */
16518    pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
16519 
16520    return CLI_SUCCESS;
16521 }
16522 #endif   /* defined(HAVE_SS7) */
16523 
16524 #if defined(HAVE_SS7)
16525 static char *handle_ss7_unblock_cic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16526 {
16527    int linkset, cic;
16528    int i, blocked = -1;
16529    switch (cmd) {
16530    case CLI_INIT:
16531       e->command = "ss7 unblock cic";
16532       e->usage =
16533          "Usage: ss7 unblock cic <linkset> <CIC>\n"
16534          "       Sends a remote unblocking request for the given CIC on the specified linkset\n";
16535       return NULL;
16536    case CLI_GENERATE:
16537       return NULL;
16538    }
16539 
16540    if (a->argc == 5)
16541       linkset = atoi(a->argv[3]);
16542    else
16543       return CLI_SHOWUSAGE;
16544 
16545    if ((linkset < 1) || (linkset > NUM_SPANS)) {
16546       ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16547       return CLI_SUCCESS;
16548    }
16549 
16550    if (!linksets[linkset-1].ss7.ss7) {
16551       ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16552       return CLI_SUCCESS;
16553    }
16554 
16555    cic = atoi(a->argv[4]);
16556 
16557    if (cic < 1) {
16558       ast_cli(a->fd, "Invalid CIC specified!\n");
16559       return CLI_SUCCESS;
16560    }
16561 
16562    for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
16563       if (linksets[linkset-1].ss7.pvts[i]->cic == cic) {
16564          blocked = linksets[linkset-1].ss7.pvts[i]->locallyblocked;
16565          if (blocked) {
16566             ast_mutex_lock(&linksets[linkset-1].ss7.lock);
16567             isup_ubl(linksets[linkset-1].ss7.ss7, cic, linksets[linkset-1].ss7.pvts[i]->dpc);
16568             ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
16569          }
16570       }
16571    }
16572 
16573    if (blocked > 0)
16574       ast_cli(a->fd, "Sent unblocking request for linkset %d on CIC %d\n", linkset, cic);
16575 
16576    /* Break poll on the linkset so it sends our messages */
16577    pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
16578 
16579    return CLI_SUCCESS;
16580 }
16581 #endif   /* defined(HAVE_SS7) */
16582 
16583 #if defined(HAVE_SS7)
16584 static char *handle_ss7_unblock_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16585 {
16586    int linkset;
16587    int i;
16588    switch (cmd) {
16589    case CLI_INIT:
16590       e->command = "ss7 unblock linkset";
16591       e->usage =
16592          "Usage: ss7 unblock linkset <linkset number>\n"
16593          "       Sends a remote unblocking request for all CICs on the specified linkset\n";
16594       return NULL;
16595    case CLI_GENERATE:
16596       return NULL;
16597    }
16598 
16599    if (a->argc == 4)
16600       linkset = atoi(a->argv[3]);
16601    else
16602       return CLI_SHOWUSAGE;
16603 
16604    if ((linkset < 1) || (linkset > NUM_SPANS)) {
16605       ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16606       return CLI_SUCCESS;
16607    }
16608 
16609    if (!linksets[linkset-1].ss7.ss7) {
16610       ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16611       return CLI_SUCCESS;
16612    }
16613 
16614    for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
16615       ast_cli(a->fd, "Sending remote unblock request on CIC %d\n", linksets[linkset-1].ss7.pvts[i]->cic);
16616       ast_mutex_lock(&linksets[linkset-1].ss7.lock);
16617       isup_ubl(linksets[linkset-1].ss7.ss7, linksets[linkset-1].ss7.pvts[i]->cic, linksets[linkset-1].ss7.pvts[i]->dpc);
16618       ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
16619    }
16620 
16621    /* Break poll on the linkset so it sends our messages */
16622    pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
16623 
16624    return CLI_SUCCESS;
16625 }
16626 #endif   /* defined(HAVE_SS7) */
16627 
16628 #if defined(HAVE_SS7)
16629 static char *handle_ss7_show_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16630 {
16631    int linkset;
16632    struct sig_ss7_linkset *ss7;
16633    switch (cmd) {
16634    case CLI_INIT:
16635       e->command = "ss7 show linkset";
16636       e->usage =
16637          "Usage: ss7 show linkset <span>\n"
16638          "       Shows the status of an SS7 linkset.\n";
16639       return NULL;
16640    case CLI_GENERATE:
16641       return NULL;
16642    }
16643 
16644    if (a->argc < 4)
16645       return CLI_SHOWUSAGE;
16646    linkset = atoi(a->argv[3]);
16647    if ((linkset < 1) || (linkset > NUM_SPANS)) {
16648       ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16649       return CLI_SUCCESS;
16650    }
16651    ss7 = &linksets[linkset - 1].ss7;
16652    if (!ss7->ss7) {
16653       ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16654       return CLI_SUCCESS;
16655    }
16656 
16657    ast_cli(a->fd, "SS7 linkset %d status: %s\n", linkset, (ss7->state == LINKSET_STATE_UP) ? "Up" : "Down");
16658 
16659    return CLI_SUCCESS;
16660 }
16661 #endif   /* defined(HAVE_SS7) */
16662 
16663 #if defined(HAVE_SS7)
16664 static char *handle_ss7_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16665 {
16666    int linkset;
16667 
16668    switch (cmd) {
16669    case CLI_INIT:
16670       e->command = "ss7 show channels";
16671       e->usage =
16672          "Usage: ss7 show channels\n"
16673          "       Displays SS7 channel information at a glance.\n";
16674       return NULL;
16675    case CLI_GENERATE:
16676       return NULL;
16677    }
16678 
16679    if (a->argc != 3)
16680       return CLI_SHOWUSAGE;
16681 
16682    sig_ss7_cli_show_channels_header(a->fd);
16683    for (linkset = 0; linkset < NUM_SPANS; ++linkset) {
16684       if (linksets[linkset].ss7.ss7) {
16685          sig_ss7_cli_show_channels(a->fd, &linksets[linkset].ss7);
16686       }
16687    }
16688    return CLI_SUCCESS;
16689 }
16690 #endif   /* defined(HAVE_SS7) */
16691 
16692 #if defined(HAVE_SS7)
16693 static char *handle_ss7_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16694 {
16695    switch (cmd) {
16696    case CLI_INIT:
16697       e->command = "ss7 show version";
16698       e->usage =
16699          "Usage: ss7 show version\n"
16700          "  Show the libss7 version\n";
16701       return NULL;
16702    case CLI_GENERATE:
16703       return NULL;
16704    }
16705 
16706    ast_cli(a->fd, "libss7 version: %s\n", ss7_get_version());
16707 
16708    return CLI_SUCCESS;
16709 }
16710 #endif   /* defined(HAVE_SS7) */
16711 
16712 #if defined(HAVE_SS7)
16713 static struct ast_cli_entry dahdi_ss7_cli[] = {
16714    AST_CLI_DEFINE(handle_ss7_debug, "Enables SS7 debugging on a linkset"),
16715    AST_CLI_DEFINE(handle_ss7_block_cic, "Blocks the given CIC"),
16716    AST_CLI_DEFINE(handle_ss7_unblock_cic, "Unblocks the given CIC"),
16717    AST_CLI_DEFINE(handle_ss7_block_linkset, "Blocks all CICs on a linkset"),
16718    AST_CLI_DEFINE(handle_ss7_unblock_linkset, "Unblocks all CICs on a linkset"),
16719    AST_CLI_DEFINE(handle_ss7_show_linkset, "Shows the status of a linkset"),
16720    AST_CLI_DEFINE(handle_ss7_show_channels, "Displays SS7 channel information"),
16721    AST_CLI_DEFINE(handle_ss7_version, "Displays libss7 version"),
16722 };
16723 #endif   /* defined(HAVE_SS7) */
16724 
16725 #if defined(HAVE_PRI)
16726 #if defined(HAVE_PRI_CCSS)
16727 /*!
16728  * \internal
16729  * \brief CC agent initialization.
16730  * \since 1.8
16731  *
16732  * \param agent CC core agent control.
16733  * \param chan Original channel the agent will attempt to recall.
16734  *
16735  * \details
16736  * This callback is called when the CC core is initialized.  Agents should allocate
16737  * any private data necessary for the call and assign it to the private_data
16738  * on the agent.  Additionally, if any ast_cc_agent_flags are pertinent to the
16739  * specific agent type, they should be set in this function as well.
16740  *
16741  * \retval 0 on success.
16742  * \retval -1 on error.
16743  */
16744 static int dahdi_pri_cc_agent_init(struct ast_cc_agent *agent, struct ast_channel *chan)
16745 {
16746    struct dahdi_pvt *pvt;
16747    struct sig_pri_chan *pvt_chan;
16748    int res;
16749 
16750    ast_assert(!strcmp(chan->tech->type, "DAHDI"));
16751 
16752    pvt = chan->tech_pvt;
16753    if (dahdi_sig_pri_lib_handles(pvt->sig)) {
16754       pvt_chan = pvt->sig_pvt;
16755    } else {
16756       pvt_chan = NULL;
16757    }
16758    if (!pvt_chan) {
16759       return -1;
16760    }
16761 
16762    ast_module_ref(ast_module_info->self);
16763 
16764    res = sig_pri_cc_agent_init(agent, pvt_chan);
16765    if (res) {
16766       ast_module_unref(ast_module_info->self);
16767    }
16768    return res;
16769 }
16770 #endif   /* defined(HAVE_PRI_CCSS) */
16771 #endif   /* defined(HAVE_PRI) */
16772 
16773 #if defined(HAVE_PRI)
16774 #if defined(HAVE_PRI_CCSS)
16775 /*!
16776  * \internal
16777  * \brief Destroy private data on the agent.
16778  * \since 1.8
16779  *
16780  * \param agent CC core agent control.
16781  *
16782  * \details
16783  * The core will call this function upon completion
16784  * or failure of CC.
16785  *
16786  * \return Nothing
16787  */
16788 static void dahdi_pri_cc_agent_destructor(struct ast_cc_agent *agent)
16789 {
16790    sig_pri_cc_agent_destructor(agent);
16791 
16792    ast_module_unref(ast_module_info->self);
16793 }
16794 #endif   /* defined(HAVE_PRI_CCSS) */
16795 #endif   /* defined(HAVE_PRI) */
16796 
16797 #if defined(HAVE_PRI)
16798 #if defined(HAVE_PRI_CCSS)
16799 static struct ast_cc_agent_callbacks dahdi_pri_cc_agent_callbacks = {
16800    .type = dahdi_pri_cc_type,
16801    .init = dahdi_pri_cc_agent_init,
16802    .start_offer_timer = sig_pri_cc_agent_start_offer_timer,
16803    .stop_offer_timer = sig_pri_cc_agent_stop_offer_timer,
16804    .respond = sig_pri_cc_agent_req_rsp,
16805    .status_request = sig_pri_cc_agent_status_req,
16806    .stop_ringing = sig_pri_cc_agent_stop_ringing,
16807    .party_b_free = sig_pri_cc_agent_party_b_free,
16808    .start_monitoring = sig_pri_cc_agent_start_monitoring,
16809    .callee_available = sig_pri_cc_agent_callee_available,
16810    .destructor = dahdi_pri_cc_agent_destructor,
16811 };
16812 #endif   /* defined(HAVE_PRI_CCSS) */
16813 #endif   /* defined(HAVE_PRI) */
16814 
16815 #if defined(HAVE_PRI)
16816 #if defined(HAVE_PRI_CCSS)
16817 static struct ast_cc_monitor_callbacks dahdi_pri_cc_monitor_callbacks = {
16818    .type = dahdi_pri_cc_type,
16819    .request_cc = sig_pri_cc_monitor_req_cc,
16820    .suspend = sig_pri_cc_monitor_suspend,
16821    .unsuspend = sig_pri_cc_monitor_unsuspend,
16822    .status_response = sig_pri_cc_monitor_status_rsp,
16823    .cancel_available_timer = sig_pri_cc_monitor_cancel_available_timer,
16824    .destructor = sig_pri_cc_monitor_destructor,
16825 };
16826 #endif   /* defined(HAVE_PRI_CCSS) */
16827 #endif   /* defined(HAVE_PRI) */
16828 
16829 static int __unload_module(void)
16830 {
16831    struct dahdi_pvt *p;
16832 #if defined(HAVE_PRI) || defined(HAVE_SS7)
16833    int i, j;
16834 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
16835 
16836 #ifdef HAVE_PRI
16837    for (i = 0; i < NUM_SPANS; i++) {
16838       if (pris[i].pri.master != AST_PTHREADT_NULL) {
16839          pthread_cancel(pris[i].pri.master);
16840          pthread_kill(pris[i].pri.master, SIGURG);
16841       }
16842    }
16843    ast_cli_unregister_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
16844    ast_unregister_application(dahdi_send_keypad_facility_app);
16845 #ifdef HAVE_PRI_PROG_W_CAUSE
16846    ast_unregister_application(dahdi_send_callrerouting_facility_app);
16847 #endif
16848 #endif
16849 #if defined(HAVE_SS7)
16850    for (i = 0; i < NUM_SPANS; i++) {
16851       if (linksets[i].ss7.master != AST_PTHREADT_NULL) {
16852          pthread_cancel(linksets[i].ss7.master);
16853          pthread_kill(linksets[i].ss7.master, SIGURG);
16854       }
16855    }
16856    ast_cli_unregister_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
16857 #endif   /* defined(HAVE_SS7) */
16858 #if defined(HAVE_OPENR2)
16859    dahdi_r2_destroy_links();
16860    ast_cli_unregister_multiple(dahdi_mfcr2_cli, ARRAY_LEN(dahdi_mfcr2_cli));
16861    ast_unregister_application(dahdi_accept_r2_call_app);
16862 #endif
16863 
16864    ast_cli_unregister_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli));
16865    ast_manager_unregister("DAHDIDialOffhook");
16866    ast_manager_unregister("DAHDIHangup");
16867    ast_manager_unregister("DAHDITransfer");
16868    ast_manager_unregister("DAHDIDNDoff");
16869    ast_manager_unregister("DAHDIDNDon");
16870    ast_manager_unregister("DAHDIShowChannels");
16871    ast_manager_unregister("DAHDIRestart");
16872    ast_data_unregister(NULL);
16873    ast_channel_unregister(&dahdi_tech);
16874 
16875    /* Hangup all interfaces if they have an owner */
16876    ast_mutex_lock(&iflock);
16877    for (p = iflist; p; p = p->next) {
16878       if (p->owner)
16879          ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
16880    }
16881    ast_mutex_unlock(&iflock);
16882 
16883    ast_mutex_lock(&monlock);
16884    if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
16885       pthread_cancel(monitor_thread);
16886       pthread_kill(monitor_thread, SIGURG);
16887       pthread_join(monitor_thread, NULL);
16888    }
16889    monitor_thread = AST_PTHREADT_STOP;
16890    ast_mutex_unlock(&monlock);
16891 
16892    destroy_all_channels();
16893 
16894 #if defined(HAVE_PRI)
16895    for (i = 0; i < NUM_SPANS; i++) {
16896       if (pris[i].pri.master && (pris[i].pri.master != AST_PTHREADT_NULL)) {
16897          pthread_join(pris[i].pri.master, NULL);
16898       }
16899       for (j = 0; j < SIG_PRI_NUM_DCHANS; j++) {
16900          dahdi_close_pri_fd(&(pris[i]), j);
16901       }
16902       sig_pri_stop_pri(&pris[i].pri);
16903    }
16904 #if defined(HAVE_PRI_CCSS)
16905    ast_cc_agent_unregister(&dahdi_pri_cc_agent_callbacks);
16906    ast_cc_monitor_unregister(&dahdi_pri_cc_monitor_callbacks);
16907 #endif   /* defined(HAVE_PRI_CCSS) */
16908    sig_pri_unload();
16909 #endif
16910 
16911 #if defined(HAVE_SS7)
16912    for (i = 0; i < NUM_SPANS; i++) {
16913       if (linksets[i].ss7.master && (linksets[i].ss7.master != AST_PTHREADT_NULL)) {
16914          pthread_join(linksets[i].ss7.master, NULL);
16915       }
16916       for (j = 0; j < SIG_SS7_NUM_DCHANS; j++) {
16917          dahdi_close_ss7_fd(&(linksets[i]), j);
16918       }
16919    }
16920 #endif   /* defined(HAVE_SS7) */
16921    ast_cond_destroy(&ss_thread_complete);
16922    return 0;
16923 }
16924 
16925 static int unload_module(void)
16926 {
16927 #if defined(HAVE_PRI) || defined(HAVE_SS7)
16928    int y;
16929 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
16930 #ifdef HAVE_PRI
16931    for (y = 0; y < NUM_SPANS; y++)
16932       ast_mutex_destroy(&pris[y].pri.lock);
16933 #endif
16934 #if defined(HAVE_SS7)
16935    for (y = 0; y < NUM_SPANS; y++)
16936       ast_mutex_destroy(&linksets[y].ss7.lock);
16937 #endif   /* defined(HAVE_SS7) */
16938    return __unload_module();
16939 }
16940 
16941 static void string_replace(char *str, int char1, int char2)
16942 {
16943    for (; *str; str++) {
16944       if (*str == char1) {
16945          *str = char2;
16946       }
16947    }
16948 }
16949 
16950 static char *parse_spanchan(char *chanstr, char **subdir)
16951 {
16952    char *p;
16953 
16954    if ((p = strrchr(chanstr, '!')) == NULL) {
16955       *subdir = NULL;
16956       return chanstr;
16957    }
16958    *p++ = '\0';
16959    string_replace(chanstr, '!', '/');
16960    *subdir = chanstr;
16961    return p;
16962 }
16963 
16964 static int build_channels(struct dahdi_chan_conf *conf, const char *value, int reload, int lineno, int *found_pseudo)
16965 {
16966    char *c, *chan;
16967    char *subdir;
16968    int x, start, finish;
16969    struct dahdi_pvt *tmp;
16970 
16971    if ((reload == 0) && (conf->chan.sig < 0) && !conf->is_sig_auto) {
16972       ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n");
16973       return -1;
16974    }
16975 
16976    c = ast_strdupa(value);
16977    c = parse_spanchan(c, &subdir);
16978 
16979    while ((chan = strsep(&c, ","))) {
16980       if (sscanf(chan, "%30d-%30d", &start, &finish) == 2) {
16981          /* Range */
16982       } else if (sscanf(chan, "%30d", &start)) {
16983          /* Just one */
16984          finish = start;
16985       } else if (!strcasecmp(chan, "pseudo")) {
16986          finish = start = CHAN_PSEUDO;
16987          if (found_pseudo)
16988             *found_pseudo = 1;
16989       } else {
16990          ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan);
16991          return -1;
16992       }
16993       if (finish < start) {
16994          ast_log(LOG_WARNING, "Sillyness: %d < %d\n", start, finish);
16995          x = finish;
16996          finish = start;
16997          start = x;
16998       }
16999 
17000       for (x = start; x <= finish; x++) {
17001          char fn[PATH_MAX];
17002          int real_channel = x;
17003 
17004          if (!ast_strlen_zero(subdir)) {
17005             real_channel = device2chan(subdir, x, fn, sizeof(fn));
17006             if (real_channel < 0) {
17007                if (conf->ignore_failed_channels) {
17008                   ast_log(LOG_WARNING, "Failed configuring %s!%d, (got %d). But moving on to others.\n",
17009                         subdir, x, real_channel);
17010                   continue;
17011                } else {
17012                   ast_log(LOG_ERROR, "Failed configuring %s!%d, (got %d).\n",
17013                         subdir, x, real_channel);
17014                   return -1;
17015                }
17016             }
17017          }
17018          tmp = mkintf(real_channel, conf, reload);
17019 
17020          if (tmp) {
17021             ast_verb(3, "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", real_channel, sig2str(tmp->sig));
17022          } else {
17023             ast_log(LOG_ERROR, "Unable to %s channel '%s'\n",
17024                   (reload == 1) ? "reconfigure" : "register", value);
17025             return -1;
17026          }
17027       }
17028    }
17029 
17030    return 0;
17031 }
17032 
17033 /** The length of the parameters list of 'dahdichan'.
17034  * \todo Move definition of MAX_CHANLIST_LEN to a proper place. */
17035 #define MAX_CHANLIST_LEN 80
17036 
17037 static void process_echocancel(struct dahdi_chan_conf *confp, const char *data, unsigned int line)
17038 {
17039    char *parse = ast_strdupa(data);
17040    char *params[DAHDI_MAX_ECHOCANPARAMS + 1];
17041    unsigned int param_count;
17042    unsigned int x;
17043 
17044    if (!(param_count = ast_app_separate_args(parse, ',', params, ARRAY_LEN(params))))
17045       return;
17046 
17047    memset(&confp->chan.echocancel, 0, sizeof(confp->chan.echocancel));
17048 
17049    /* first parameter is tap length, process it here */
17050 
17051    x = ast_strlen_zero(params[0]) ? 0 : atoi(params[0]);
17052 
17053    if ((x == 32) || (x == 64) || (x == 128) || (x == 256) || (x == 512) || (x == 1024))
17054       confp->chan.echocancel.head.tap_length = x;
17055    else if ((confp->chan.echocancel.head.tap_length = ast_true(params[0])))
17056       confp->chan.echocancel.head.tap_length = 128;
17057 
17058    /* now process any remaining parameters */
17059 
17060    for (x = 1; x < param_count; x++) {
17061       struct {
17062          char *name;
17063          char *value;
17064       } param;
17065 
17066       if (ast_app_separate_args(params[x], '=', (char **) &param, 2) < 1) {
17067          ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, params[x]);
17068          continue;
17069       }
17070 
17071       if (ast_strlen_zero(param.name) || (strlen(param.name) > sizeof(confp->chan.echocancel.params[0].name)-1)) {
17072          ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, param.name);
17073          continue;
17074       }
17075 
17076       strcpy(confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].name, param.name);
17077 
17078       if (param.value) {
17079          if (sscanf(param.value, "%30d", &confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].value) != 1) {
17080             ast_log(LOG_WARNING, "Invalid echocancel parameter value supplied at line %d: '%s'\n", line, param.value);
17081             continue;
17082          }
17083       }
17084       confp->chan.echocancel.head.param_count++;
17085    }
17086 }
17087 
17088 /*! process_dahdi() - ignore keyword 'channel' and similar */
17089 #define PROC_DAHDI_OPT_NOCHAN  (1 << 0)
17090 /*! process_dahdi() - No warnings on non-existing cofiguration keywords */
17091 #define PROC_DAHDI_OPT_NOWARN  (1 << 1)
17092 
17093 static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct ast_variable *v, int reload, int options)
17094 {
17095    struct dahdi_pvt *tmp;
17096    int y;
17097    int found_pseudo = 0;
17098    struct ast_variable *dahdichan = NULL;
17099 
17100    for (; v; v = v->next) {
17101       if (!ast_jb_read_conf(&global_jbconf, v->name, v->value))
17102          continue;
17103 
17104       /* Create the interface list */
17105       if (!strcasecmp(v->name, "channel") || !strcasecmp(v->name, "channels")) {
17106          if (options & PROC_DAHDI_OPT_NOCHAN) {
17107             ast_log(LOG_WARNING, "Channel '%s' ignored.\n", v->value);
17108             continue;
17109          }
17110          if (build_channels(confp, v->value, reload, v->lineno, &found_pseudo)) {
17111             if (confp->ignore_failed_channels) {
17112                ast_log(LOG_WARNING, "Channel '%s' failure ignored: ignore_failed_channels.\n", v->value);
17113                continue;
17114             } else {
17115                return -1;
17116             }
17117          }
17118          ast_log(LOG_DEBUG, "Channel '%s' configured.\n", v->value);
17119       } else if (!strcasecmp(v->name, "ignore_failed_channels")) {
17120          confp->ignore_failed_channels = ast_true(v->value);
17121       } else if (!strcasecmp(v->name, "buffers")) {
17122          if (parse_buffers_policy(v->value, &confp->chan.buf_no, &confp->chan.buf_policy)) {
17123             ast_log(LOG_WARNING, "Using default buffer policy.\n");
17124             confp->chan.buf_no = numbufs;
17125             confp->chan.buf_policy = DAHDI_POLICY_IMMEDIATE;
17126          }
17127       } else if (!strcasecmp(v->name, "faxbuffers")) {
17128          if (!parse_buffers_policy(v->value, &confp->chan.faxbuf_no, &confp->chan.faxbuf_policy)) {
17129             confp->chan.usefaxbuffers = 1;
17130          }
17131       } else if (!strcasecmp(v->name, "dahdichan")) {
17132          /* Only process the last dahdichan value. */
17133          dahdichan = v;
17134       } else if (!strcasecmp(v->name, "usedistinctiveringdetection")) {
17135          usedistinctiveringdetection = ast_true(v->value);
17136       } else if (!strcasecmp(v->name, "distinctiveringaftercid")) {
17137          distinctiveringaftercid = ast_true(v->value);
17138       } else if (!strcasecmp(v->name, "dring1context")) {
17139          ast_copy_string(confp->chan.drings.ringContext[0].contextData,v->value,sizeof(confp->chan.drings.ringContext[0].contextData));
17140       } else if (!strcasecmp(v->name, "dring2context")) {
17141          ast_copy_string(confp->chan.drings.ringContext[1].contextData,v->value,sizeof(confp->chan.drings.ringContext[1].contextData));
17142       } else if (!strcasecmp(v->name, "dring3context")) {
17143          ast_copy_string(confp->chan.drings.ringContext[2].contextData,v->value,sizeof(confp->chan.drings.ringContext[2].contextData));
17144       } else if (!strcasecmp(v->name, "dring1range")) {
17145          confp->chan.drings.ringnum[0].range = atoi(v->value);
17146       } else if (!strcasecmp(v->name, "dring2range")) {
17147          confp->chan.drings.ringnum[1].range = atoi(v->value);
17148       } else if (!strcasecmp(v->name, "dring3range")) {
17149          confp->chan.drings.ringnum[2].range = atoi(v->value);
17150       } else if (!strcasecmp(v->name, "dring1")) {
17151          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]);
17152       } else if (!strcasecmp(v->name, "dring2")) {
17153          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]);
17154       } else if (!strcasecmp(v->name, "dring3")) {
17155          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]);
17156       } else if (!strcasecmp(v->name, "usecallerid")) {
17157          confp->chan.use_callerid = ast_true(v->value);
17158       } else if (!strcasecmp(v->name, "cidsignalling")) {
17159          if (!strcasecmp(v->value, "bell"))
17160             confp->chan.cid_signalling = CID_SIG_BELL;
17161          else if (!strcasecmp(v->value, "v23"))
17162             confp->chan.cid_signalling = CID_SIG_V23;
17163          else if (!strcasecmp(v->value, "dtmf"))
17164             confp->chan.cid_signalling = CID_SIG_DTMF;
17165          else if (!strcasecmp(v->value, "smdi"))
17166             confp->chan.cid_signalling = CID_SIG_SMDI;
17167          else if (!strcasecmp(v->value, "v23_jp"))
17168             confp->chan.cid_signalling = CID_SIG_V23_JP;
17169          else if (ast_true(v->value))
17170             confp->chan.cid_signalling = CID_SIG_BELL;
17171       } else if (!strcasecmp(v->name, "cidstart")) {
17172          if (!strcasecmp(v->value, "ring"))
17173             confp->chan.cid_start = CID_START_RING;
17174          else if (!strcasecmp(v->value, "polarity_in"))
17175             confp->chan.cid_start = CID_START_POLARITY_IN;
17176          else if (!strcasecmp(v->value, "polarity"))
17177             confp->chan.cid_start = CID_START_POLARITY;
17178          else if (!strcasecmp(v->value, "dtmf"))
17179             confp->chan.cid_start = CID_START_DTMF_NOALERT;
17180          else if (ast_true(v->value))
17181             confp->chan.cid_start = CID_START_RING;
17182       } else if (!strcasecmp(v->name, "threewaycalling")) {
17183          confp->chan.threewaycalling = ast_true(v->value);
17184       } else if (!strcasecmp(v->name, "cancallforward")) {
17185          confp->chan.cancallforward = ast_true(v->value);
17186       } else if (!strcasecmp(v->name, "relaxdtmf")) {
17187          if (ast_true(v->value))
17188             confp->chan.dtmfrelax = DSP_DIGITMODE_RELAXDTMF;
17189          else
17190             confp->chan.dtmfrelax = 0;
17191       } else if (!strcasecmp(v->name, "mailbox")) {
17192          ast_copy_string(confp->chan.mailbox, v->value, sizeof(confp->chan.mailbox));
17193       } else if (!strcasecmp(v->name, "hasvoicemail")) {
17194          if (ast_true(v->value) && ast_strlen_zero(confp->chan.mailbox)) {
17195             ast_copy_string(confp->chan.mailbox, cat, sizeof(confp->chan.mailbox));
17196          }
17197       } else if (!strcasecmp(v->name, "adsi")) {
17198          confp->chan.adsi = ast_true(v->value);
17199       } else if (!strcasecmp(v->name, "usesmdi")) {
17200          confp->chan.use_smdi = ast_true(v->value);
17201       } else if (!strcasecmp(v->name, "smdiport")) {
17202          ast_copy_string(confp->smdi_port, v->value, sizeof(confp->smdi_port));
17203       } else if (!strcasecmp(v->name, "transfer")) {
17204          confp->chan.transfer = ast_true(v->value);
17205       } else if (!strcasecmp(v->name, "canpark")) {
17206          confp->chan.canpark = ast_true(v->value);
17207       } else if (!strcasecmp(v->name, "echocancelwhenbridged")) {
17208          confp->chan.echocanbridged = ast_true(v->value);
17209       } else if (!strcasecmp(v->name, "busydetect")) {
17210          confp->chan.busydetect = ast_true(v->value);
17211       } else if (!strcasecmp(v->name, "busycount")) {
17212          confp->chan.busycount = atoi(v->value);
17213       } else if (!strcasecmp(v->name, "busypattern")) {
17214          if (sscanf(v->value, "%30d,%30d", &confp->chan.busy_tonelength, &confp->chan.busy_quietlength) != 2) {
17215             ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength,quietlength at line %d.\n", v->lineno);
17216          }
17217       } else if (!strcasecmp(v->name, "callprogress")) {
17218          confp->chan.callprogress &= ~CALLPROGRESS_PROGRESS;
17219          if (ast_true(v->value))
17220             confp->chan.callprogress |= CALLPROGRESS_PROGRESS;
17221       } else if (!strcasecmp(v->name, "waitfordialtone")) {
17222          confp->chan.waitfordialtone = atoi(v->value);
17223       } else if (!strcasecmp(v->name, "faxdetect")) {
17224          confp->chan.callprogress &= ~CALLPROGRESS_FAX;
17225          if (!strcasecmp(v->value, "incoming")) {
17226             confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING;
17227          } else if (!strcasecmp(v->value, "outgoing")) {
17228             confp->chan.callprogress |= CALLPROGRESS_FAX_OUTGOING;
17229          } else if (!strcasecmp(v->value, "both") || ast_true(v->value))
17230             confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING;
17231       } else if (!strcasecmp(v->name, "echocancel")) {
17232          process_echocancel(confp, v->value, v->lineno);
17233       } else if (!strcasecmp(v->name, "echotraining")) {
17234          if (sscanf(v->value, "%30d", &y) == 1) {
17235             if ((y < 10) || (y > 4000)) {
17236                ast_log(LOG_WARNING, "Echo training time must be within the range of 10 to 4000 ms at line %d.\n", v->lineno);
17237             } else {
17238                confp->chan.echotraining = y;
17239             }
17240          } else if (ast_true(v->value)) {
17241             confp->chan.echotraining = 400;
17242          } else
17243             confp->chan.echotraining = 0;
17244       } else if (!strcasecmp(v->name, "hidecallerid")) {
17245          confp->chan.hidecallerid = ast_true(v->value);
17246       } else if (!strcasecmp(v->name, "hidecalleridname")) {
17247          confp->chan.hidecalleridname = ast_true(v->value);
17248       } else if (!strcasecmp(v->name, "pulsedial")) {
17249          confp->chan.pulse = ast_true(v->value);
17250       } else if (!strcasecmp(v->name, "callreturn")) {
17251          confp->chan.callreturn = ast_true(v->value);
17252       } else if (!strcasecmp(v->name, "callwaiting")) {
17253          confp->chan.callwaiting = ast_true(v->value);
17254       } else if (!strcasecmp(v->name, "callwaitingcallerid")) {
17255          confp->chan.callwaitingcallerid = ast_true(v->value);
17256       } else if (!strcasecmp(v->name, "context")) {
17257          ast_copy_string(confp->chan.context, v->value, sizeof(confp->chan.context));
17258       } else if (!strcasecmp(v->name, "language")) {
17259          ast_copy_string(confp->chan.language, v->value, sizeof(confp->chan.language));
17260       } else if (!strcasecmp(v->name, "progzone")) {
17261          ast_copy_string(progzone, v->value, sizeof(progzone));
17262       } else if (!strcasecmp(v->name, "mohinterpret")
17263          ||!strcasecmp(v->name, "musiconhold") || !strcasecmp(v->name, "musicclass")) {
17264          ast_copy_string(confp->chan.mohinterpret, v->value, sizeof(confp->chan.mohinterpret));
17265       } else if (!strcasecmp(v->name, "mohsuggest")) {
17266          ast_copy_string(confp->chan.mohsuggest, v->value, sizeof(confp->chan.mohsuggest));
17267       } else if (!strcasecmp(v->name, "parkinglot")) {
17268          ast_copy_string(confp->chan.parkinglot, v->value, sizeof(confp->chan.parkinglot));
17269       } else if (!strcasecmp(v->name, "stripmsd")) {
17270          ast_log(LOG_NOTICE, "Configuration option \"%s\" has been deprecated. Please use dialplan instead\n", v->name);
17271          confp->chan.stripmsd = atoi(v->value);
17272       } else if (!strcasecmp(v->name, "jitterbuffers")) {
17273          numbufs = atoi(v->value);
17274       } else if (!strcasecmp(v->name, "group")) {
17275          confp->chan.group = ast_get_group(v->value);
17276       } else if (!strcasecmp(v->name, "callgroup")) {
17277          if (!strcasecmp(v->value, "none"))
17278             confp->chan.callgroup = 0;
17279          else
17280             confp->chan.callgroup = ast_get_group(v->value);
17281       } else if (!strcasecmp(v->name, "pickupgroup")) {
17282          if (!strcasecmp(v->value, "none"))
17283             confp->chan.pickupgroup = 0;
17284          else
17285             confp->chan.pickupgroup = ast_get_group(v->value);
17286       } else if (!strcasecmp(v->name, "setvar")) {
17287          char *varname = ast_strdupa(v->value), *varval = NULL;
17288          struct ast_variable *tmpvar;
17289          if (varname && (varval = strchr(varname, '='))) {
17290             *varval++ = '\0';
17291             if ((tmpvar = ast_variable_new(varname, varval, ""))) {
17292                tmpvar->next = confp->chan.vars;
17293                confp->chan.vars = tmpvar;
17294             }
17295          }
17296       } else if (!strcasecmp(v->name, "immediate")) {
17297          confp->chan.immediate = ast_true(v->value);
17298       } else if (!strcasecmp(v->name, "transfertobusy")) {
17299          confp->chan.transfertobusy = ast_true(v->value);
17300       } else if (!strcasecmp(v->name, "mwimonitor")) {
17301          confp->chan.mwimonitor_neon = 0;
17302          confp->chan.mwimonitor_fsk = 0;
17303          confp->chan.mwimonitor_rpas = 0;
17304          if (strcasestr(v->value, "fsk")) {
17305             confp->chan.mwimonitor_fsk = 1;
17306          }
17307          if (strcasestr(v->value, "rpas")) {
17308             confp->chan.mwimonitor_rpas = 1;
17309          }
17310          if (strcasestr(v->value, "neon")) {
17311             confp->chan.mwimonitor_neon = 1;
17312          }
17313          /* If set to true or yes, assume that simple fsk is desired */
17314          if (ast_true(v->value)) {
17315             confp->chan.mwimonitor_fsk = 1;
17316          }
17317       } else if (!strcasecmp(v->name, "cid_rxgain")) {
17318          if (sscanf(v->value, "%30f", &confp->chan.cid_rxgain) != 1) {
17319             ast_log(LOG_WARNING, "Invalid cid_rxgain: %s at line %d.\n", v->value, v->lineno);
17320          }
17321       } else if (!strcasecmp(v->name, "rxgain")) {
17322          if (sscanf(v->value, "%30f", &confp->chan.rxgain) != 1) {
17323             ast_log(LOG_WARNING, "Invalid rxgain: %s at line %d.\n", v->value, v->lineno);
17324          }
17325       } else if (!strcasecmp(v->name, "txgain")) {
17326          if (sscanf(v->value, "%30f", &confp->chan.txgain) != 1) {
17327             ast_log(LOG_WARNING, "Invalid txgain: %s at line %d.\n", v->value, v->lineno);
17328          }
17329       } else if (!strcasecmp(v->name, "txdrc")) {
17330          if (sscanf(v->value, "%f", &confp->chan.txdrc) != 1) {
17331             ast_log(LOG_WARNING, "Invalid txdrc: %s\n", v->value);
17332          }
17333       } else if (!strcasecmp(v->name, "rxdrc")) {
17334          if (sscanf(v->value, "%f", &confp->chan.rxdrc) != 1) {
17335             ast_log(LOG_WARNING, "Invalid rxdrc: %s\n", v->value);
17336          }
17337       } else if (!strcasecmp(v->name, "tonezone")) {
17338          if (sscanf(v->value, "%30d", &confp->chan.tonezone) != 1) {
17339             ast_log(LOG_WARNING, "Invalid tonezone: %s at line %d.\n", v->value, v->lineno);
17340          }
17341       } else if (!strcasecmp(v->name, "callerid")) {
17342          if (!strcasecmp(v->value, "asreceived")) {
17343             confp->chan.cid_num[0] = '\0';
17344             confp->chan.cid_name[0] = '\0';
17345          } else {
17346             ast_callerid_split(v->value, confp->chan.cid_name, sizeof(confp->chan.cid_name), confp->chan.cid_num, sizeof(confp->chan.cid_num));
17347          }
17348       } else if (!strcasecmp(v->name, "fullname")) {
17349          ast_copy_string(confp->chan.cid_name, v->value, sizeof(confp->chan.cid_name));
17350       } else if (!strcasecmp(v->name, "cid_number")) {
17351          ast_copy_string(confp->chan.cid_num, v->value, sizeof(confp->chan.cid_num));
17352       } else if (!strcasecmp(v->name, "cid_tag")) {
17353          ast_copy_string(confp->chan.cid_tag, v->value, sizeof(confp->chan.cid_tag));
17354       } else if (!strcasecmp(v->name, "useincomingcalleridondahditransfer")) {
17355          confp->chan.dahditrcallerid = ast_true(v->value);
17356       } else if (!strcasecmp(v->name, "restrictcid")) {
17357          confp->chan.restrictcid = ast_true(v->value);
17358       } else if (!strcasecmp(v->name, "usecallingpres")) {
17359          confp->chan.use_callingpres = ast_true(v->value);
17360       } else if (!strcasecmp(v->name, "accountcode")) {
17361          ast_copy_string(confp->chan.accountcode, v->value, sizeof(confp->chan.accountcode));
17362       } else if (!strcasecmp(v->name, "amaflags")) {
17363          y = ast_cdr_amaflags2int(v->value);
17364          if (y < 0)
17365             ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d.\n", v->value, v->lineno);
17366          else
17367             confp->chan.amaflags = y;
17368       } else if (!strcasecmp(v->name, "polarityonanswerdelay")) {
17369          confp->chan.polarityonanswerdelay = atoi(v->value);
17370       } else if (!strcasecmp(v->name, "answeronpolarityswitch")) {
17371          confp->chan.answeronpolarityswitch = ast_true(v->value);
17372       } else if (!strcasecmp(v->name, "hanguponpolarityswitch")) {
17373          confp->chan.hanguponpolarityswitch = ast_true(v->value);
17374       } else if (!strcasecmp(v->name, "sendcalleridafter")) {
17375          confp->chan.sendcalleridafter = atoi(v->value);
17376       } else if (!strcasecmp(v->name, "mwimonitornotify")) {
17377          ast_copy_string(mwimonitornotify, v->value, sizeof(mwimonitornotify));
17378       } else if (ast_cc_is_config_param(v->name)) {
17379          ast_cc_set_param(confp->chan.cc_params, v->name, v->value);
17380       } else if (!strcasecmp(v->name, "mwisendtype")) {
17381 #ifndef HAVE_DAHDI_LINEREVERSE_VMWI  /* backward compatibility for older dahdi VMWI implementation */
17382          if (!strcasecmp(v->value, "rpas")) { /* Ring Pulse Alert Signal */
17383             mwisend_rpas = 1;
17384          } else {
17385             mwisend_rpas = 0;
17386          }
17387 #else
17388          /* Default is fsk, to turn it off you must specify nofsk */
17389          memset(&confp->chan.mwisend_setting, 0, sizeof(confp->chan.mwisend_setting));
17390          if (strcasestr(v->value, "nofsk")) {      /* NoFSK */
17391             confp->chan.mwisend_fsk = 0;
17392          } else {             /* Default FSK */
17393             confp->chan.mwisend_fsk = 1;
17394          }
17395          if (strcasestr(v->value, "rpas")) {       /* Ring Pulse Alert Signal, normally followed by FSK */
17396             confp->chan.mwisend_rpas = 1;
17397          } else {
17398             confp->chan.mwisend_rpas = 0;
17399          }
17400          if (strcasestr(v->value, "lrev")) {       /* Line Reversal */
17401             confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_LREV;
17402          }
17403          if (strcasestr(v->value, "hvdc")) {       /* HV 90VDC */
17404             confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_HVDC;
17405          }
17406          if ( (strcasestr(v->value, "neon")) || (strcasestr(v->value, "hvac")) ){   /* 90V DC pulses */
17407             confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_HVAC;
17408          }
17409 #endif
17410       } else if (reload != 1) {
17411           if (!strcasecmp(v->name, "signalling") || !strcasecmp(v->name, "signaling")) {
17412             int orig_radio = confp->chan.radio;
17413             int orig_outsigmod = confp->chan.outsigmod;
17414             int orig_auto = confp->is_sig_auto;
17415 
17416             confp->chan.radio = 0;
17417             confp->chan.outsigmod = -1;
17418             confp->is_sig_auto = 0;
17419             if (!strcasecmp(v->value, "em")) {
17420                confp->chan.sig = SIG_EM;
17421             } else if (!strcasecmp(v->value, "em_e1")) {
17422                confp->chan.sig = SIG_EM_E1;
17423             } else if (!strcasecmp(v->value, "em_w")) {
17424                confp->chan.sig = SIG_EMWINK;
17425             } else if (!strcasecmp(v->value, "fxs_ls")) {
17426                confp->chan.sig = SIG_FXSLS;
17427             } else if (!strcasecmp(v->value, "fxs_gs")) {
17428                confp->chan.sig = SIG_FXSGS;
17429             } else if (!strcasecmp(v->value, "fxs_ks")) {
17430                confp->chan.sig = SIG_FXSKS;
17431             } else if (!strcasecmp(v->value, "fxo_ls")) {
17432                confp->chan.sig = SIG_FXOLS;
17433             } else if (!strcasecmp(v->value, "fxo_gs")) {
17434                confp->chan.sig = SIG_FXOGS;
17435             } else if (!strcasecmp(v->value, "fxo_ks")) {
17436                confp->chan.sig = SIG_FXOKS;
17437             } else if (!strcasecmp(v->value, "fxs_rx")) {
17438                confp->chan.sig = SIG_FXSKS;
17439                confp->chan.radio = 1;
17440             } else if (!strcasecmp(v->value, "fxo_rx")) {
17441                confp->chan.sig = SIG_FXOLS;
17442                confp->chan.radio = 1;
17443             } else if (!strcasecmp(v->value, "fxs_tx")) {
17444                confp->chan.sig = SIG_FXSLS;
17445                confp->chan.radio = 1;
17446             } else if (!strcasecmp(v->value, "fxo_tx")) {
17447                confp->chan.sig = SIG_FXOGS;
17448                confp->chan.radio = 1;
17449             } else if (!strcasecmp(v->value, "em_rx")) {
17450                confp->chan.sig = SIG_EM;
17451                confp->chan.radio = 1;
17452             } else if (!strcasecmp(v->value, "em_tx")) {
17453                confp->chan.sig = SIG_EM;
17454                confp->chan.radio = 1;
17455             } else if (!strcasecmp(v->value, "em_rxtx")) {
17456                confp->chan.sig = SIG_EM;
17457                confp->chan.radio = 2;
17458             } else if (!strcasecmp(v->value, "em_txrx")) {
17459                confp->chan.sig = SIG_EM;
17460                confp->chan.radio = 2;
17461             } else if (!strcasecmp(v->value, "sf")) {
17462                confp->chan.sig = SIG_SF;
17463             } else if (!strcasecmp(v->value, "sf_w")) {
17464                confp->chan.sig = SIG_SFWINK;
17465             } else if (!strcasecmp(v->value, "sf_featd")) {
17466                confp->chan.sig = SIG_FEATD;
17467             } else if (!strcasecmp(v->value, "sf_featdmf")) {
17468                confp->chan.sig = SIG_FEATDMF;
17469             } else if (!strcasecmp(v->value, "sf_featb")) {
17470                confp->chan.sig = SIG_SF_FEATB;
17471             } else if (!strcasecmp(v->value, "sf")) {
17472                confp->chan.sig = SIG_SF;
17473             } else if (!strcasecmp(v->value, "sf_rx")) {
17474                confp->chan.sig = SIG_SF;
17475                confp->chan.radio = 1;
17476             } else if (!strcasecmp(v->value, "sf_tx")) {
17477                confp->chan.sig = SIG_SF;
17478                confp->chan.radio = 1;
17479             } else if (!strcasecmp(v->value, "sf_rxtx")) {
17480                confp->chan.sig = SIG_SF;
17481                confp->chan.radio = 2;
17482             } else if (!strcasecmp(v->value, "sf_txrx")) {
17483                confp->chan.sig = SIG_SF;
17484                confp->chan.radio = 2;
17485             } else if (!strcasecmp(v->value, "featd")) {
17486                confp->chan.sig = SIG_FEATD;
17487             } else if (!strcasecmp(v->value, "featdmf")) {
17488                confp->chan.sig = SIG_FEATDMF;
17489             } else if (!strcasecmp(v->value, "featdmf_ta")) {
17490                confp->chan.sig = SIG_FEATDMF_TA;
17491             } else if (!strcasecmp(v->value, "e911")) {
17492                confp->chan.sig = SIG_E911;
17493             } else if (!strcasecmp(v->value, "fgccama")) {
17494                confp->chan.sig = SIG_FGC_CAMA;
17495             } else if (!strcasecmp(v->value, "fgccamamf")) {
17496                confp->chan.sig = SIG_FGC_CAMAMF;
17497             } else if (!strcasecmp(v->value, "featb")) {
17498                confp->chan.sig = SIG_FEATB;
17499 #ifdef HAVE_PRI
17500             } else if (!strcasecmp(v->value, "pri_net")) {
17501                confp->chan.sig = SIG_PRI;
17502                confp->pri.pri.nodetype = PRI_NETWORK;
17503             } else if (!strcasecmp(v->value, "pri_cpe")) {
17504                confp->chan.sig = SIG_PRI;
17505                confp->pri.pri.nodetype = PRI_CPE;
17506             } else if (!strcasecmp(v->value, "bri_cpe")) {
17507                confp->chan.sig = SIG_BRI;
17508                confp->pri.pri.nodetype = PRI_CPE;
17509             } else if (!strcasecmp(v->value, "bri_net")) {
17510                confp->chan.sig = SIG_BRI;
17511                confp->pri.pri.nodetype = PRI_NETWORK;
17512             } else if (!strcasecmp(v->value, "bri_cpe_ptmp")) {
17513                confp->chan.sig = SIG_BRI_PTMP;
17514                confp->pri.pri.nodetype = PRI_CPE;
17515             } else if (!strcasecmp(v->value, "bri_net_ptmp")) {
17516 #if defined(HAVE_PRI_CALL_HOLD)
17517                confp->chan.sig = SIG_BRI_PTMP;
17518                confp->pri.pri.nodetype = PRI_NETWORK;
17519 #else
17520                ast_log(LOG_WARNING, "How cool would it be if someone implemented this mode!  For now, sucks for you. (line %d)\n", v->lineno);
17521 #endif   /* !defined(HAVE_PRI_CALL_HOLD) */
17522 #endif
17523 #if defined(HAVE_SS7)
17524             } else if (!strcasecmp(v->value, "ss7")) {
17525                confp->chan.sig = SIG_SS7;
17526 #endif   /* defined(HAVE_SS7) */
17527 #ifdef HAVE_OPENR2
17528             } else if (!strcasecmp(v->value, "mfcr2")) {
17529                confp->chan.sig = SIG_MFCR2;
17530 #endif
17531             } else if (!strcasecmp(v->value, "auto")) {
17532                confp->is_sig_auto = 1;
17533             } else {
17534                confp->chan.outsigmod = orig_outsigmod;
17535                confp->chan.radio = orig_radio;
17536                confp->is_sig_auto = orig_auto;
17537                ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
17538             }
17539           } else if (!strcasecmp(v->name, "outsignalling") || !strcasecmp(v->name, "outsignaling")) {
17540             if (!strcasecmp(v->value, "em")) {
17541                confp->chan.outsigmod = SIG_EM;
17542             } else if (!strcasecmp(v->value, "em_e1")) {
17543                confp->chan.outsigmod = SIG_EM_E1;
17544             } else if (!strcasecmp(v->value, "em_w")) {
17545                confp->chan.outsigmod = SIG_EMWINK;
17546             } else if (!strcasecmp(v->value, "sf")) {
17547                confp->chan.outsigmod = SIG_SF;
17548             } else if (!strcasecmp(v->value, "sf_w")) {
17549                confp->chan.outsigmod = SIG_SFWINK;
17550             } else if (!strcasecmp(v->value, "sf_featd")) {
17551                confp->chan.outsigmod = SIG_FEATD;
17552             } else if (!strcasecmp(v->value, "sf_featdmf")) {
17553                confp->chan.outsigmod = SIG_FEATDMF;
17554             } else if (!strcasecmp(v->value, "sf_featb")) {
17555                confp->chan.outsigmod = SIG_SF_FEATB;
17556             } else if (!strcasecmp(v->value, "sf")) {
17557                confp->chan.outsigmod = SIG_SF;
17558             } else if (!strcasecmp(v->value, "featd")) {
17559                confp->chan.outsigmod = SIG_FEATD;
17560             } else if (!strcasecmp(v->value, "featdmf")) {
17561                confp->chan.outsigmod = SIG_FEATDMF;
17562             } else if (!strcasecmp(v->value, "featdmf_ta")) {
17563                confp->chan.outsigmod = SIG_FEATDMF_TA;
17564             } else if (!strcasecmp(v->value, "e911")) {
17565                confp->chan.outsigmod = SIG_E911;
17566             } else if (!strcasecmp(v->value, "fgccama")) {
17567                confp->chan.outsigmod = SIG_FGC_CAMA;
17568             } else if (!strcasecmp(v->value, "fgccamamf")) {
17569                confp->chan.outsigmod = SIG_FGC_CAMAMF;
17570             } else if (!strcasecmp(v->value, "featb")) {
17571                confp->chan.outsigmod = SIG_FEATB;
17572             } else {
17573                ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
17574             }
17575 #ifdef HAVE_PRI
17576          } else if (!strcasecmp(v->name, "pridialplan")) {
17577             if (!strcasecmp(v->value, "national")) {
17578                confp->pri.pri.dialplan = PRI_NATIONAL_ISDN + 1;
17579             } else if (!strcasecmp(v->value, "unknown")) {
17580                confp->pri.pri.dialplan = PRI_UNKNOWN + 1;
17581             } else if (!strcasecmp(v->value, "private")) {
17582                confp->pri.pri.dialplan = PRI_PRIVATE + 1;
17583             } else if (!strcasecmp(v->value, "international")) {
17584                confp->pri.pri.dialplan = PRI_INTERNATIONAL_ISDN + 1;
17585             } else if (!strcasecmp(v->value, "local")) {
17586                confp->pri.pri.dialplan = PRI_LOCAL_ISDN + 1;
17587             } else if (!strcasecmp(v->value, "dynamic")) {
17588                confp->pri.pri.dialplan = -1;
17589             } else if (!strcasecmp(v->value, "redundant")) {
17590                confp->pri.pri.dialplan = -2;
17591             } else {
17592                ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno);
17593             }
17594          } else if (!strcasecmp(v->name, "prilocaldialplan")) {
17595             if (!strcasecmp(v->value, "national")) {
17596                confp->pri.pri.localdialplan = PRI_NATIONAL_ISDN + 1;
17597             } else if (!strcasecmp(v->value, "unknown")) {
17598                confp->pri.pri.localdialplan = PRI_UNKNOWN + 1;
17599             } else if (!strcasecmp(v->value, "private")) {
17600                confp->pri.pri.localdialplan = PRI_PRIVATE + 1;
17601             } else if (!strcasecmp(v->value, "international")) {
17602                confp->pri.pri.localdialplan = PRI_INTERNATIONAL_ISDN + 1;
17603             } else if (!strcasecmp(v->value, "local")) {
17604                confp->pri.pri.localdialplan = PRI_LOCAL_ISDN + 1;
17605             } else if (!strcasecmp(v->value, "dynamic")) {
17606                confp->pri.pri.localdialplan = -1;
17607             } else if (!strcasecmp(v->value, "redundant")) {
17608                confp->pri.pri.localdialplan = -2;
17609             } else {
17610                ast_log(LOG_WARNING, "Unknown PRI localdialplan '%s' at line %d.\n", v->value, v->lineno);
17611             }
17612          } else if (!strcasecmp(v->name, "switchtype")) {
17613             if (!strcasecmp(v->value, "national"))
17614                confp->pri.pri.switchtype = PRI_SWITCH_NI2;
17615             else if (!strcasecmp(v->value, "ni1"))
17616                confp->pri.pri.switchtype = PRI_SWITCH_NI1;
17617             else if (!strcasecmp(v->value, "dms100"))
17618                confp->pri.pri.switchtype = PRI_SWITCH_DMS100;
17619             else if (!strcasecmp(v->value, "4ess"))
17620                confp->pri.pri.switchtype = PRI_SWITCH_ATT4ESS;
17621             else if (!strcasecmp(v->value, "5ess"))
17622                confp->pri.pri.switchtype = PRI_SWITCH_LUCENT5E;
17623             else if (!strcasecmp(v->value, "euroisdn"))
17624                confp->pri.pri.switchtype = PRI_SWITCH_EUROISDN_E1;
17625             else if (!strcasecmp(v->value, "qsig"))
17626                confp->pri.pri.switchtype = PRI_SWITCH_QSIG;
17627             else {
17628                ast_log(LOG_ERROR, "Unknown switchtype '%s' at line %d.\n", v->value, v->lineno);
17629                return -1;
17630             }
17631          } else if (!strcasecmp(v->name, "msn")) {
17632             ast_copy_string(confp->pri.pri.msn_list, v->value,
17633                sizeof(confp->pri.pri.msn_list));
17634          } else if (!strcasecmp(v->name, "nsf")) {
17635             if (!strcasecmp(v->value, "sdn"))
17636                confp->pri.pri.nsf = PRI_NSF_SDN;
17637             else if (!strcasecmp(v->value, "megacom"))
17638                confp->pri.pri.nsf = PRI_NSF_MEGACOM;
17639             else if (!strcasecmp(v->value, "tollfreemegacom"))
17640                confp->pri.pri.nsf = PRI_NSF_TOLL_FREE_MEGACOM;
17641             else if (!strcasecmp(v->value, "accunet"))
17642                confp->pri.pri.nsf = PRI_NSF_ACCUNET;
17643             else if (!strcasecmp(v->value, "none"))
17644                confp->pri.pri.nsf = PRI_NSF_NONE;
17645             else {
17646                ast_log(LOG_WARNING, "Unknown network-specific facility '%s' at line %d.\n", v->value, v->lineno);
17647                confp->pri.pri.nsf = PRI_NSF_NONE;
17648             }
17649          } else if (!strcasecmp(v->name, "priindication")) {
17650             if (!strcasecmp(v->value, "outofband"))
17651                confp->chan.priindication_oob = 1;
17652             else if (!strcasecmp(v->value, "inband"))
17653                confp->chan.priindication_oob = 0;
17654             else
17655                ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d.\n",
17656                   v->value, v->lineno);
17657          } else if (!strcasecmp(v->name, "priexclusive")) {
17658             confp->chan.priexclusive = ast_true(v->value);
17659          } else if (!strcasecmp(v->name, "internationalprefix")) {
17660             ast_copy_string(confp->pri.pri.internationalprefix, v->value, sizeof(confp->pri.pri.internationalprefix));
17661          } else if (!strcasecmp(v->name, "nationalprefix")) {
17662             ast_copy_string(confp->pri.pri.nationalprefix, v->value, sizeof(confp->pri.pri.nationalprefix));
17663          } else if (!strcasecmp(v->name, "localprefix")) {
17664             ast_copy_string(confp->pri.pri.localprefix, v->value, sizeof(confp->pri.pri.localprefix));
17665          } else if (!strcasecmp(v->name, "privateprefix")) {
17666             ast_copy_string(confp->pri.pri.privateprefix, v->value, sizeof(confp->pri.pri.privateprefix));
17667          } else if (!strcasecmp(v->name, "unknownprefix")) {
17668             ast_copy_string(confp->pri.pri.unknownprefix, v->value, sizeof(confp->pri.pri.unknownprefix));
17669          } else if (!strcasecmp(v->name, "resetinterval")) {
17670             if (!strcasecmp(v->value, "never"))
17671                confp->pri.pri.resetinterval = -1;
17672             else if (atoi(v->value) >= 60)
17673                confp->pri.pri.resetinterval = atoi(v->value);
17674             else
17675                ast_log(LOG_WARNING, "'%s' is not a valid reset interval, should be >= 60 seconds or 'never' at line %d.\n",
17676                   v->value, v->lineno);
17677          } else if (!strcasecmp(v->name, "minunused")) {
17678             confp->pri.pri.minunused = atoi(v->value);
17679          } else if (!strcasecmp(v->name, "minidle")) {
17680             confp->pri.pri.minidle = atoi(v->value);
17681          } else if (!strcasecmp(v->name, "idleext")) {
17682             ast_copy_string(confp->pri.pri.idleext, v->value, sizeof(confp->pri.pri.idleext));
17683          } else if (!strcasecmp(v->name, "idledial")) {
17684             ast_copy_string(confp->pri.pri.idledial, v->value, sizeof(confp->pri.pri.idledial));
17685          } else if (!strcasecmp(v->name, "overlapdial")) {
17686             if (ast_true(v->value)) {
17687                confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
17688             } else if (!strcasecmp(v->value, "incoming")) {
17689                confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_INCOMING;
17690             } else if (!strcasecmp(v->value, "outgoing")) {
17691                confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_OUTGOING;
17692             } else if (!strcasecmp(v->value, "both") || ast_true(v->value)) {
17693                confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
17694             } else {
17695                confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_NONE;
17696             }
17697 #ifdef HAVE_PRI_PROG_W_CAUSE
17698          } else if (!strcasecmp(v->name, "qsigchannelmapping")) {
17699             if (!strcasecmp(v->value, "logical")) {
17700                confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_LOGICAL;
17701             } else if (!strcasecmp(v->value, "physical")) {
17702                confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL;
17703             } else {
17704                confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL;
17705             }
17706 #endif
17707          } else if (!strcasecmp(v->name, "discardremoteholdretrieval")) {
17708             confp->pri.pri.discardremoteholdretrieval = ast_true(v->value);
17709 #if defined(HAVE_PRI_SERVICE_MESSAGES)
17710          } else if (!strcasecmp(v->name, "service_message_support")) {
17711             /* assuming switchtype for this channel group has been configured already */
17712             if ((confp->pri.pri.switchtype == PRI_SWITCH_ATT4ESS 
17713                || confp->pri.pri.switchtype == PRI_SWITCH_LUCENT5E
17714                || confp->pri.pri.switchtype == PRI_SWITCH_NI2) && ast_true(v->value)) {
17715                confp->pri.pri.enable_service_message_support = 1;
17716             } else {
17717                confp->pri.pri.enable_service_message_support = 0;
17718             }
17719 #endif   /* defined(HAVE_PRI_SERVICE_MESSAGES) */
17720 #ifdef HAVE_PRI_INBANDDISCONNECT
17721          } else if (!strcasecmp(v->name, "inbanddisconnect")) {
17722             confp->pri.pri.inbanddisconnect = ast_true(v->value);
17723 #endif
17724          } else if (!strcasecmp(v->name, "pritimer")) {
17725 #ifdef PRI_GETSET_TIMERS
17726             char tmp[20];
17727             char *timerc;
17728             char *c;
17729             int timer;
17730             int timeridx;
17731 
17732             ast_copy_string(tmp, v->value, sizeof(tmp));
17733             c = tmp;
17734             timerc = strsep(&c, ",");
17735             if (!ast_strlen_zero(timerc) && !ast_strlen_zero(c)) {
17736                timeridx = pri_timer2idx(timerc);
17737                timer = atoi(c);
17738                if (timeridx < 0 || PRI_MAX_TIMERS <= timeridx) {
17739                   ast_log(LOG_WARNING,
17740                      "'%s' is not a valid ISDN timer at line %d.\n", timerc,
17741                      v->lineno);
17742                } else if (!timer) {
17743                   ast_log(LOG_WARNING,
17744                      "'%s' is not a valid value for ISDN timer '%s' at line %d.\n",
17745                      c, timerc, v->lineno);
17746                } else {
17747                   confp->pri.pri.pritimers[timeridx] = timer;
17748                }
17749             } else {
17750                ast_log(LOG_WARNING,
17751                   "'%s' is not a valid ISDN timer configuration string at line %d.\n",
17752                   v->value, v->lineno);
17753             }
17754 #endif /* PRI_GETSET_TIMERS */
17755          } else if (!strcasecmp(v->name, "facilityenable")) {
17756             confp->pri.pri.facilityenable = ast_true(v->value);
17757 #if defined(HAVE_PRI_AOC_EVENTS)
17758          } else if (!strcasecmp(v->name, "aoc_enable")) {
17759             confp->pri.pri.aoc_passthrough_flag = 0;
17760             if (strchr(v->value, 's') || strchr(v->value, 'S')) {
17761                confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_S;
17762             }
17763             if (strchr(v->value, 'd') || strchr(v->value, 'D')) {
17764                confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_D;
17765             }
17766             if (strchr(v->value, 'e') || strchr(v->value, 'E')) {
17767                confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_E;
17768             }
17769          } else if (!strcasecmp(v->name, "aoce_delayhangup")) {
17770             confp->pri.pri.aoce_delayhangup = ast_true(v->value);
17771 #endif   /* defined(HAVE_PRI_AOC_EVENTS) */
17772 #if defined(HAVE_PRI_CALL_HOLD)
17773          } else if (!strcasecmp(v->name, "hold_disconnect_transfer")) {
17774             confp->pri.pri.hold_disconnect_transfer = ast_true(v->value);
17775 #endif   /* defined(HAVE_PRI_CALL_HOLD) */
17776 #if defined(HAVE_PRI_CCSS)
17777          } else if (!strcasecmp(v->name, "cc_ptmp_recall_mode")) {
17778             if (!strcasecmp(v->value, "global")) {
17779                confp->pri.pri.cc_ptmp_recall_mode = 0;/* globalRecall */
17780             } else if (!strcasecmp(v->value, "specific")) {
17781                confp->pri.pri.cc_ptmp_recall_mode = 1;/* specificRecall */
17782             } else {
17783                confp->pri.pri.cc_ptmp_recall_mode = 1;/* specificRecall */
17784             }
17785          } else if (!strcasecmp(v->name, "cc_qsig_signaling_link_req")) {
17786             if (!strcasecmp(v->value, "release")) {
17787                confp->pri.pri.cc_qsig_signaling_link_req = 0;/* release */
17788             } else if (!strcasecmp(v->value, "retain")) {
17789                confp->pri.pri.cc_qsig_signaling_link_req = 1;/* retain */
17790             } else if (!strcasecmp(v->value, "do_not_care")) {
17791                confp->pri.pri.cc_qsig_signaling_link_req = 2;/* do-not-care */
17792             } else {
17793                confp->pri.pri.cc_qsig_signaling_link_req = 1;/* retain */
17794             }
17795          } else if (!strcasecmp(v->name, "cc_qsig_signaling_link_rsp")) {
17796             if (!strcasecmp(v->value, "release")) {
17797                confp->pri.pri.cc_qsig_signaling_link_rsp = 0;/* release */
17798             } else if (!strcasecmp(v->value, "retain")) {
17799                confp->pri.pri.cc_qsig_signaling_link_rsp = 1;/* retain */
17800             } else {
17801                confp->pri.pri.cc_qsig_signaling_link_rsp = 1;/* retain */
17802             }
17803 #endif   /* defined(HAVE_PRI_CCSS) */
17804 #if defined(HAVE_PRI_CALL_WAITING)
17805          } else if (!strcasecmp(v->name, "max_call_waiting_calls")) {
17806             confp->pri.pri.max_call_waiting_calls = atoi(v->value);
17807             if (confp->pri.pri.max_call_waiting_calls < 0) {
17808                /* Negative values are not allowed. */
17809                confp->pri.pri.max_call_waiting_calls = 0;
17810             }
17811          } else if (!strcasecmp(v->name, "allow_call_waiting_calls")) {
17812             confp->pri.pri.allow_call_waiting_calls = ast_true(v->value);
17813 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
17814 #if defined(HAVE_PRI_MWI)
17815          } else if (!strcasecmp(v->name, "mwi_mailboxes")) {
17816             ast_copy_string(confp->pri.pri.mwi_mailboxes, v->value,
17817                sizeof(confp->pri.pri.mwi_mailboxes));
17818 #endif   /* defined(HAVE_PRI_MWI) */
17819          } else if (!strcasecmp(v->name, "append_msn_to_cid_tag")) {
17820             confp->pri.pri.append_msn_to_user_tag = ast_true(v->value);
17821          } else if (!strcasecmp(v->name, "inband_on_proceeding")) {
17822             confp->pri.pri.inband_on_proceeding = ast_true(v->value);
17823          } else if (!strcasecmp(v->name, "layer1_presence")) {
17824             if (!strcasecmp(v->value, "required")) {
17825                confp->pri.pri.layer1_ignored = 0;
17826             } else if (!strcasecmp(v->value, "ignore")) {
17827                confp->pri.pri.layer1_ignored = 1;
17828             } else {
17829                /* Default */
17830                confp->pri.pri.layer1_ignored = 0;
17831             }
17832 #if defined(HAVE_PRI_L2_PERSISTENCE)
17833          } else if (!strcasecmp(v->name, "layer2_persistence")) {
17834             if (!strcasecmp(v->value, "keep_up")) {
17835                confp->pri.pri.l2_persistence = PRI_L2_PERSISTENCE_KEEP_UP;
17836             } else if (!strcasecmp(v->value, "leave_down")) {
17837                confp->pri.pri.l2_persistence = PRI_L2_PERSISTENCE_LEAVE_DOWN;
17838             } else {
17839                confp->pri.pri.l2_persistence = PRI_L2_PERSISTENCE_DEFAULT;
17840             }
17841 #endif   /* defined(HAVE_PRI_L2_PERSISTENCE) */
17842 #endif /* HAVE_PRI */
17843 #if defined(HAVE_SS7)
17844          } else if (!strcasecmp(v->name, "ss7type")) {
17845             if (!strcasecmp(v->value, "itu")) {
17846                cur_ss7type = SS7_ITU;
17847             } else if (!strcasecmp(v->value, "ansi")) {
17848                cur_ss7type = SS7_ANSI;
17849             } else
17850                ast_log(LOG_WARNING, "'%s' is an unknown ss7 switch type at line %d.!\n", v->value, v->lineno);
17851          } else if (!strcasecmp(v->name, "linkset")) {
17852             cur_linkset = atoi(v->value);
17853          } else if (!strcasecmp(v->name, "pointcode")) {
17854             cur_pointcode = parse_pointcode(v->value);
17855          } else if (!strcasecmp(v->name, "adjpointcode")) {
17856             cur_adjpointcode = parse_pointcode(v->value);
17857          } else if (!strcasecmp(v->name, "defaultdpc")) {
17858             cur_defaultdpc = parse_pointcode(v->value);
17859          } else if (!strcasecmp(v->name, "cicbeginswith")) {
17860             cur_cicbeginswith = atoi(v->value);
17861          } else if (!strcasecmp(v->name, "networkindicator")) {
17862             if (!strcasecmp(v->value, "national"))
17863                cur_networkindicator = SS7_NI_NAT;
17864             else if (!strcasecmp(v->value, "national_spare"))
17865                cur_networkindicator = SS7_NI_NAT_SPARE;
17866             else if (!strcasecmp(v->value, "international"))
17867                cur_networkindicator = SS7_NI_INT;
17868             else if (!strcasecmp(v->value, "international_spare"))
17869                cur_networkindicator = SS7_NI_INT_SPARE;
17870             else
17871                cur_networkindicator = -1;
17872          } else if (!strcasecmp(v->name, "ss7_internationalprefix")) {
17873             ast_copy_string(confp->ss7.ss7.internationalprefix, v->value, sizeof(confp->ss7.ss7.internationalprefix));
17874          } else if (!strcasecmp(v->name, "ss7_nationalprefix")) {
17875             ast_copy_string(confp->ss7.ss7.nationalprefix, v->value, sizeof(confp->ss7.ss7.nationalprefix));
17876          } else if (!strcasecmp(v->name, "ss7_subscriberprefix")) {
17877             ast_copy_string(confp->ss7.ss7.subscriberprefix, v->value, sizeof(confp->ss7.ss7.subscriberprefix));
17878          } else if (!strcasecmp(v->name, "ss7_unknownprefix")) {
17879             ast_copy_string(confp->ss7.ss7.unknownprefix, v->value, sizeof(confp->ss7.ss7.unknownprefix));
17880          } else if (!strcasecmp(v->name, "ss7_called_nai")) {
17881             if (!strcasecmp(v->value, "national")) {
17882                confp->ss7.ss7.called_nai = SS7_NAI_NATIONAL;
17883             } else if (!strcasecmp(v->value, "international")) {
17884                confp->ss7.ss7.called_nai = SS7_NAI_INTERNATIONAL;
17885             } else if (!strcasecmp(v->value, "subscriber")) {
17886                confp->ss7.ss7.called_nai = SS7_NAI_SUBSCRIBER;
17887             } else if (!strcasecmp(v->value, "unknown")) {
17888                confp->ss7.ss7.called_nai = SS7_NAI_UNKNOWN;
17889             } else if (!strcasecmp(v->value, "dynamic")) {
17890                confp->ss7.ss7.called_nai = SS7_NAI_DYNAMIC;
17891             } else {
17892                ast_log(LOG_WARNING, "Unknown SS7 called_nai '%s' at line %d.\n", v->value, v->lineno);
17893             }
17894          } else if (!strcasecmp(v->name, "ss7_calling_nai")) {
17895             if (!strcasecmp(v->value, "national")) {
17896                confp->ss7.ss7.calling_nai = SS7_NAI_NATIONAL;
17897             } else if (!strcasecmp(v->value, "international")) {
17898                confp->ss7.ss7.calling_nai = SS7_NAI_INTERNATIONAL;
17899             } else if (!strcasecmp(v->value, "subscriber")) {
17900                confp->ss7.ss7.calling_nai = SS7_NAI_SUBSCRIBER;
17901             } else if (!strcasecmp(v->value, "unknown")) {
17902                confp->ss7.ss7.calling_nai = SS7_NAI_UNKNOWN;
17903             } else if (!strcasecmp(v->value, "dynamic")) {
17904                confp->ss7.ss7.calling_nai = SS7_NAI_DYNAMIC;
17905             } else {
17906                ast_log(LOG_WARNING, "Unknown SS7 calling_nai '%s' at line %d.\n", v->value, v->lineno);
17907             }
17908          } else if (!strcasecmp(v->name, "sigchan")) {
17909             int sigchan, res;
17910             sigchan = atoi(v->value);
17911             res = linkset_addsigchan(sigchan);
17912             if (res < 0)
17913                return -1;
17914 
17915          } else if (!strcasecmp(v->name, "ss7_explicitacm")) {
17916             struct dahdi_ss7 *link;
17917             link = ss7_resolve_linkset(cur_linkset);
17918             if (!link) {
17919                ast_log(LOG_ERROR, "Invalid linkset number.  Must be between 1 and %d\n", NUM_SPANS + 1);
17920                return -1;
17921             }
17922             if (ast_true(v->value))
17923                link->ss7.flags |= LINKSET_FLAG_EXPLICITACM;
17924 #endif   /* defined(HAVE_SS7) */
17925 #ifdef HAVE_OPENR2
17926          } else if (!strcasecmp(v->name, "mfcr2_advanced_protocol_file")) {
17927             ast_copy_string(confp->mfcr2.r2proto_file, v->value, sizeof(confp->mfcr2.r2proto_file));
17928             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);
17929          } else if (!strcasecmp(v->name, "mfcr2_logdir")) {
17930             ast_copy_string(confp->mfcr2.logdir, v->value, sizeof(confp->mfcr2.logdir));
17931          } else if (!strcasecmp(v->name, "mfcr2_variant")) {
17932             confp->mfcr2.variant = openr2_proto_get_variant(v->value);
17933             if (OR2_VAR_UNKNOWN == confp->mfcr2.variant) {
17934                ast_log(LOG_WARNING, "Unknown MFC/R2 variant '%s' at line %d, defaulting to ITU.\n", v->value, v->lineno);
17935                confp->mfcr2.variant = OR2_VAR_ITU;
17936             }
17937          } else if (!strcasecmp(v->name, "mfcr2_mfback_timeout")) {
17938             confp->mfcr2.mfback_timeout = atoi(v->value);
17939             if (!confp->mfcr2.mfback_timeout) {
17940                ast_log(LOG_WARNING, "MF timeout of 0? hum, I will protect you from your ignorance. Setting default.\n");
17941                confp->mfcr2.mfback_timeout = -1;
17942             } else if (confp->mfcr2.mfback_timeout > 0 && confp->mfcr2.mfback_timeout < 500) {
17943                ast_log(LOG_WARNING, "MF timeout less than 500ms is not recommended, you have been warned!\n");
17944             }
17945          } else if (!strcasecmp(v->name, "mfcr2_metering_pulse_timeout")) {
17946             confp->mfcr2.metering_pulse_timeout = atoi(v->value);
17947             if (confp->mfcr2.metering_pulse_timeout > 500) {
17948                ast_log(LOG_WARNING, "Metering pulse timeout greater than 500ms is not recommended, you have been warned!\n");
17949             }
17950          } else if (!strcasecmp(v->name, "mfcr2_get_ani_first")) {
17951             confp->mfcr2.get_ani_first = ast_true(v->value) ? 1 : 0;
17952          } else if (!strcasecmp(v->name, "mfcr2_double_answer")) {
17953             confp->mfcr2.double_answer = ast_true(v->value) ? 1 : 0;
17954          } else if (!strcasecmp(v->name, "mfcr2_charge_calls")) {
17955             confp->mfcr2.charge_calls = ast_true(v->value) ? 1 : 0;
17956          } else if (!strcasecmp(v->name, "mfcr2_accept_on_offer")) {
17957             confp->mfcr2.accept_on_offer = ast_true(v->value) ? 1 : 0;
17958          } else if (!strcasecmp(v->name, "mfcr2_allow_collect_calls")) {
17959             confp->mfcr2.allow_collect_calls = ast_true(v->value) ? 1 : 0;
17960          } else if (!strcasecmp(v->name, "mfcr2_forced_release")) {
17961             confp->mfcr2.forced_release = ast_true(v->value) ? 1 : 0;
17962          } else if (!strcasecmp(v->name, "mfcr2_immediate_accept")) {
17963             confp->mfcr2.immediate_accept = ast_true(v->value) ? 1 : 0;
17964 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
17965          } else if (!strcasecmp(v->name, "mfcr2_skip_category")) {
17966             confp->mfcr2.skip_category_request = ast_true(v->value) ? 1 : 0;
17967 #endif
17968          } else if (!strcasecmp(v->name, "mfcr2_call_files")) {
17969             confp->mfcr2.call_files = ast_true(v->value) ? 1 : 0;
17970          } else if (!strcasecmp(v->name, "mfcr2_max_ani")) {
17971             confp->mfcr2.max_ani = atoi(v->value);
17972             if (confp->mfcr2.max_ani >= AST_MAX_EXTENSION){
17973                confp->mfcr2.max_ani = AST_MAX_EXTENSION - 1;
17974             }
17975          } else if (!strcasecmp(v->name, "mfcr2_max_dnis")) {
17976             confp->mfcr2.max_dnis = atoi(v->value);
17977             if (confp->mfcr2.max_dnis >= AST_MAX_EXTENSION){
17978                confp->mfcr2.max_dnis = AST_MAX_EXTENSION - 1;
17979             }
17980          } else if (!strcasecmp(v->name, "mfcr2_category")) {
17981             confp->mfcr2.category = openr2_proto_get_category(v->value);
17982             if (OR2_CALLING_PARTY_CATEGORY_UNKNOWN == confp->mfcr2.category) {
17983                confp->mfcr2.category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER;
17984                ast_log(LOG_WARNING, "Invalid MFC/R2 caller category '%s' at line %d. Using national subscriber as default.\n",
17985                      v->value, v->lineno);
17986             }
17987          } else if (!strcasecmp(v->name, "mfcr2_logging")) {
17988             openr2_log_level_t tmplevel;
17989             char *clevel;
17990             char *logval = ast_strdupa(v->value);
17991             while (logval) {
17992                clevel = strsep(&logval,",");
17993                if (-1 == (tmplevel = openr2_log_get_level(clevel))) {
17994                   ast_log(LOG_WARNING, "Ignoring invalid logging level: '%s' at line %d.\n", clevel, v->lineno);
17995                   continue;
17996                }
17997                confp->mfcr2.loglevel |= tmplevel;
17998             }
17999 #endif /* HAVE_OPENR2 */
18000          } else if (!strcasecmp(v->name, "cadence")) {
18001             /* setup to scan our argument */
18002             int element_count, c[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
18003             int i;
18004             struct dahdi_ring_cadence new_cadence;
18005             int cid_location = -1;
18006             int firstcadencepos = 0;
18007             char original_args[80];
18008             int cadence_is_ok = 1;
18009 
18010             ast_copy_string(original_args, v->value, sizeof(original_args));
18011             /* 16 cadences allowed (8 pairs) */
18012             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]);
18013 
18014             /* Cadence must be even (on/off) */
18015             if (element_count % 2 == 1) {
18016                ast_log(LOG_ERROR, "Must be a silence duration for each ring duration: %s at line %d.\n", original_args, v->lineno);
18017                cadence_is_ok = 0;
18018             }
18019 
18020             /* Ring cadences cannot be negative */
18021             for (i = 0; i < element_count; i++) {
18022                if (c[i] == 0) {
18023                   ast_log(LOG_ERROR, "Ring or silence duration cannot be zero: %s at line %d.\n", original_args, v->lineno);
18024                   cadence_is_ok = 0;
18025                   break;
18026                } else if (c[i] < 0) {
18027                   if (i % 2 == 1) {
18028                      /* Silence duration, negative possibly okay */
18029                      if (cid_location == -1) {
18030                         cid_location = i;
18031                         c[i] *= -1;
18032                      } else {
18033                         ast_log(LOG_ERROR, "CID location specified twice: %s at line %d.\n", original_args, v->lineno);
18034                         cadence_is_ok = 0;
18035                         break;
18036                      }
18037                   } else {
18038                      if (firstcadencepos == 0) {
18039                         firstcadencepos = i; /* only recorded to avoid duplicate specification */
18040                                  /* duration will be passed negative to the DAHDI driver */
18041                      } else {
18042                          ast_log(LOG_ERROR, "First cadence position specified twice: %s at line %d.\n", original_args, v->lineno);
18043                         cadence_is_ok = 0;
18044                         break;
18045                      }
18046                   }
18047                }
18048             }
18049 
18050             /* Substitute our scanned cadence */
18051             for (i = 0; i < 16; i++) {
18052                new_cadence.ringcadence[i] = c[i];
18053             }
18054 
18055             if (cadence_is_ok) {
18056                /* ---we scanned it without getting annoyed; now some sanity checks--- */
18057                if (element_count < 2) {
18058                   ast_log(LOG_ERROR, "Minimum cadence is ring,pause: %s at line %d.\n", original_args, v->lineno);
18059                } else {
18060                   if (cid_location == -1) {
18061                      /* user didn't say; default to first pause */
18062                      cid_location = 1;
18063                   } else {
18064                      /* convert element_index to cidrings value */
18065                      cid_location = (cid_location + 1) / 2;
18066                   }
18067                   /* ---we like their cadence; try to install it--- */
18068                   if (!user_has_defined_cadences++)
18069                      /* this is the first user-defined cadence; clear the default user cadences */
18070                      num_cadence = 0;
18071                   if ((num_cadence+1) >= NUM_CADENCE_MAX)
18072                      ast_log(LOG_ERROR, "Already %d cadences; can't add another: %s at line %d.\n", NUM_CADENCE_MAX, original_args, v->lineno);
18073                   else {
18074                      cadences[num_cadence] = new_cadence;
18075                      cidrings[num_cadence++] = cid_location;
18076                      ast_verb(3, "cadence 'r%d' added: %s\n",num_cadence,original_args);
18077                   }
18078                }
18079             }
18080          } else if (!strcasecmp(v->name, "ringtimeout")) {
18081             ringt_base = (atoi(v->value) * 8) / READ_SIZE;
18082          } else if (!strcasecmp(v->name, "prewink")) {
18083             confp->timing.prewinktime = atoi(v->value);
18084          } else if (!strcasecmp(v->name, "preflash")) {
18085             confp->timing.preflashtime = atoi(v->value);
18086          } else if (!strcasecmp(v->name, "wink")) {
18087             confp->timing.winktime = atoi(v->value);
18088          } else if (!strcasecmp(v->name, "flash")) {
18089             confp->timing.flashtime = atoi(v->value);
18090          } else if (!strcasecmp(v->name, "start")) {
18091             confp->timing.starttime = atoi(v->value);
18092          } else if (!strcasecmp(v->name, "rxwink")) {
18093             confp->timing.rxwinktime = atoi(v->value);
18094          } else if (!strcasecmp(v->name, "rxflash")) {
18095             confp->timing.rxflashtime = atoi(v->value);
18096          } else if (!strcasecmp(v->name, "debounce")) {
18097             confp->timing.debouncetime = atoi(v->value);
18098          } else if (!strcasecmp(v->name, "toneduration")) {
18099             int toneduration;
18100             int ctlfd;
18101             int res;
18102             struct dahdi_dialparams dps;
18103 
18104             ctlfd = open("/dev/dahdi/ctl", O_RDWR);
18105             if (ctlfd == -1) {
18106                ast_log(LOG_ERROR, "Unable to open /dev/dahdi/ctl to set toneduration at line %d.\n", v->lineno);
18107                return -1;
18108             }
18109 
18110             toneduration = atoi(v->value);
18111             if (toneduration > -1) {
18112                memset(&dps, 0, sizeof(dps));
18113 
18114                dps.dtmf_tonelen = dps.mfv1_tonelen = toneduration;
18115                res = ioctl(ctlfd, DAHDI_SET_DIALPARAMS, &dps);
18116                if (res < 0) {
18117                   ast_log(LOG_ERROR, "Invalid tone duration: %d ms at line %d: %s\n", toneduration, v->lineno, strerror(errno));
18118                   close(ctlfd);
18119                   return -1;
18120                }
18121             }
18122             close(ctlfd);
18123          } else if (!strcasecmp(v->name, "defaultcic")) {
18124             ast_copy_string(defaultcic, v->value, sizeof(defaultcic));
18125          } else if (!strcasecmp(v->name, "defaultozz")) {
18126             ast_copy_string(defaultozz, v->value, sizeof(defaultozz));
18127          } else if (!strcasecmp(v->name, "mwilevel")) {
18128             mwilevel = atoi(v->value);
18129          } else if (!strcasecmp(v->name, "dtmfcidlevel")) {
18130             dtmfcid_level = atoi(v->value);
18131          } else if (!strcasecmp(v->name, "reportalarms")) {
18132             if (!strcasecmp(v->value, "all"))
18133                report_alarms = REPORT_CHANNEL_ALARMS | REPORT_SPAN_ALARMS;
18134             if (!strcasecmp(v->value, "none"))
18135                report_alarms = 0;
18136             else if (!strcasecmp(v->value, "channels"))
18137                report_alarms = REPORT_CHANNEL_ALARMS;
18138             else if (!strcasecmp(v->value, "spans"))
18139                report_alarms = REPORT_SPAN_ALARMS;
18140           }
18141       } else if (!(options & PROC_DAHDI_OPT_NOWARN) )
18142          ast_log(LOG_WARNING, "Ignoring any changes to '%s' (on reload) at line %d.\n", v->name, v->lineno);
18143    }
18144 
18145    /* Since confp has already filled invidual dahdi_pvt objects with channels at this point, clear the variables in confp's pvt. */
18146    if (confp->chan.vars) {
18147       ast_variables_destroy(confp->chan.vars);
18148       confp->chan.vars = NULL;
18149    }
18150 
18151    if (dahdichan) {
18152       /* Process the deferred dahdichan value. */
18153       if (build_channels(confp, dahdichan->value, reload, dahdichan->lineno,
18154          &found_pseudo)) {
18155          if (confp->ignore_failed_channels) {
18156             ast_log(LOG_WARNING,
18157                "Dahdichan '%s' failure ignored: ignore_failed_channels.\n",
18158                dahdichan->value);
18159          } else {
18160             return -1;
18161          }
18162       }
18163    }
18164 
18165    /* mark the first channels of each DAHDI span to watch for their span alarms */
18166    for (tmp = iflist, y=-1; tmp; tmp = tmp->next) {
18167       if (!tmp->destroy && tmp->span != y) {
18168          tmp->manages_span_alarms = 1;
18169          y = tmp->span; 
18170       } else {
18171          tmp->manages_span_alarms = 0;
18172       }
18173    }
18174 
18175    /*< \todo why check for the pseudo in the per-channel section.
18176     * Any actual use for manual setup of the pseudo channel? */
18177    if (!found_pseudo && reload != 1 && !(options & PROC_DAHDI_OPT_NOCHAN)) {
18178       /* use the default configuration for a channel, so
18179          that any settings from real configured channels
18180          don't "leak" into the pseudo channel config
18181       */
18182       struct dahdi_chan_conf conf = dahdi_chan_conf_default();
18183 
18184       if (conf.chan.cc_params) {
18185          tmp = mkintf(CHAN_PSEUDO, &conf, reload);
18186       } else {
18187          tmp = NULL;
18188       }
18189       if (tmp) {
18190          ast_verb(3, "Automatically generated pseudo channel\n");
18191       } else {
18192          ast_log(LOG_WARNING, "Unable to register pseudo channel!\n");
18193       }
18194       ast_cc_config_params_destroy(conf.chan.cc_params);
18195    }
18196    return 0;
18197 }
18198 
18199 /*!
18200  * \internal
18201  * \brief Deep copy struct dahdi_chan_conf.
18202  * \since 1.8
18203  *
18204  * \param dest Destination.
18205  * \param src Source.
18206  *
18207  * \return Nothing
18208  */
18209 static void deep_copy_dahdi_chan_conf(struct dahdi_chan_conf *dest, const struct dahdi_chan_conf *src)
18210 {
18211    struct ast_cc_config_params *cc_params;
18212 
18213    cc_params = dest->chan.cc_params;
18214    *dest = *src;
18215    dest->chan.cc_params = cc_params;
18216    ast_cc_copy_config_params(dest->chan.cc_params, src->chan.cc_params);
18217 }
18218 
18219 /*!
18220  * \internal
18221  * \brief Setup DAHDI channel driver.
18222  *
18223  * \param reload enum: load_module(0), reload(1), restart(2).
18224  * \param default_conf Default config parameters.  So cc_params can be properly destroyed.
18225  * \param base_conf Default config parameters per section.  So cc_params can be properly destroyed.
18226  * \param conf Local config parameters.  So cc_params can be properly destroyed.
18227  *
18228  * \retval 0 on success.
18229  * \retval -1 on error.
18230  */
18231 static int setup_dahdi_int(int reload, struct dahdi_chan_conf *default_conf, struct dahdi_chan_conf *base_conf, struct dahdi_chan_conf *conf)
18232 {
18233    struct ast_config *cfg;
18234    struct ast_config *ucfg;
18235    struct ast_variable *v;
18236    struct ast_flags config_flags = { reload == 1 ? CONFIG_FLAG_FILEUNCHANGED : 0 };
18237    const char *chans;
18238    const char *cat;
18239    int res;
18240 
18241 #ifdef HAVE_PRI
18242    char *c;
18243    int spanno;
18244    int i;
18245    int logicalspan;
18246    int trunkgroup;
18247    int dchannels[SIG_PRI_NUM_DCHANS];
18248 #endif
18249    int have_cfg_now;
18250    static int had_cfg_before = 1;/* So initial load will complain if we don't have cfg. */
18251 
18252    cfg = ast_config_load(config, config_flags);
18253    have_cfg_now = !!cfg;
18254    if (!cfg) {
18255       /* Error if we have no config file */
18256       if (had_cfg_before) {
18257          ast_log(LOG_ERROR, "Unable to load config %s\n", config);
18258          ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
18259       }
18260       cfg = ast_config_new();/* Dummy config */
18261       if (!cfg) {
18262          return 0;
18263       }
18264       ucfg = ast_config_load("users.conf", config_flags);
18265       if (ucfg == CONFIG_STATUS_FILEUNCHANGED) {
18266          ast_config_destroy(cfg);
18267          return 0;
18268       }
18269       if (ucfg == CONFIG_STATUS_FILEINVALID) {
18270          ast_log(LOG_ERROR, "File users.conf cannot be parsed.  Aborting.\n");
18271          ast_config_destroy(cfg);
18272          return 0;
18273       }
18274    } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
18275       ucfg = ast_config_load("users.conf", config_flags);
18276       if (ucfg == CONFIG_STATUS_FILEUNCHANGED) {
18277          return 0;
18278       }
18279       if (ucfg == CONFIG_STATUS_FILEINVALID) {
18280          ast_log(LOG_ERROR, "File users.conf cannot be parsed.  Aborting.\n");
18281          return 0;
18282       }
18283       ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
18284       cfg = ast_config_load(config, config_flags);
18285       have_cfg_now = !!cfg;
18286       if (!cfg) {
18287          if (had_cfg_before) {
18288             /* We should have been able to load the config. */
18289             ast_log(LOG_ERROR, "Bad. Unable to load config %s\n", config);
18290             ast_config_destroy(ucfg);
18291             return 0;
18292          }
18293          cfg = ast_config_new();/* Dummy config */
18294          if (!cfg) {
18295             ast_config_destroy(ucfg);
18296             return 0;
18297          }
18298       } else if (cfg == CONFIG_STATUS_FILEINVALID) {
18299          ast_log(LOG_ERROR, "File %s cannot be parsed.  Aborting.\n", config);
18300          ast_config_destroy(ucfg);
18301          return 0;
18302       }
18303    } else if (cfg == CONFIG_STATUS_FILEINVALID) {
18304       ast_log(LOG_ERROR, "File %s cannot be parsed.  Aborting.\n", config);
18305       return 0;
18306    } else {
18307       ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
18308       ucfg = ast_config_load("users.conf", config_flags);
18309       if (ucfg == CONFIG_STATUS_FILEINVALID) {
18310          ast_log(LOG_ERROR, "File users.conf cannot be parsed.  Aborting.\n");
18311          ast_config_destroy(cfg);
18312          return 0;
18313       }
18314    }
18315    had_cfg_before = have_cfg_now;
18316 
18317    /* It's a little silly to lock it, but we might as well just to be sure */
18318    ast_mutex_lock(&iflock);
18319 #ifdef HAVE_PRI
18320    if (reload != 1) {
18321       /* Process trunkgroups first */
18322       v = ast_variable_browse(cfg, "trunkgroups");
18323       while (v) {
18324          if (!strcasecmp(v->name, "trunkgroup")) {
18325             trunkgroup = atoi(v->value);
18326             if (trunkgroup > 0) {
18327                if ((c = strchr(v->value, ','))) {
18328                   i = 0;
18329                   memset(dchannels, 0, sizeof(dchannels));
18330                   while (c && (i < SIG_PRI_NUM_DCHANS)) {
18331                      dchannels[i] = atoi(c + 1);
18332                      if (dchannels[i] < 0) {
18333                         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);
18334                      } else
18335                         i++;
18336                      c = strchr(c + 1, ',');
18337                   }
18338                   if (i) {
18339                      if (pri_create_trunkgroup(trunkgroup, dchannels)) {
18340                         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);
18341                   } else
18342                         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");
18343                   } else
18344                      ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
18345                } else
18346                   ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
18347             } else
18348                ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of chan_dahdi.conf\n", v->lineno);
18349          } else if (!strcasecmp(v->name, "spanmap")) {
18350             spanno = atoi(v->value);
18351             if (spanno > 0) {
18352                if ((c = strchr(v->value, ','))) {
18353                   trunkgroup = atoi(c + 1);
18354                   if (trunkgroup > 0) {
18355                      if ((c = strchr(c + 1, ',')))
18356                         logicalspan = atoi(c + 1);
18357                      else
18358                         logicalspan = 0;
18359                      if (logicalspan >= 0) {
18360                         if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) {
18361                            ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
18362                      } else
18363                            ast_verb(2, "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
18364                      } else
18365                         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);
18366                   } else
18367                      ast_log(LOG_WARNING, "Trunk group must be a postive number at line %d of chan_dahdi.conf\n", v->lineno);
18368                } else
18369                   ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of chan_dahdi.conf\n", v->lineno);
18370             } else
18371                ast_log(LOG_WARNING, "Span number must be a postive integer at line %d of chan_dahdi.conf\n", v->lineno);
18372          } else {
18373             ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name);
18374          }
18375          v = v->next;
18376       }
18377    }
18378 #endif
18379 
18380    /* Copy the default jb config over global_jbconf */
18381    memcpy(&global_jbconf, &default_jbconf, sizeof(global_jbconf));
18382 
18383    mwimonitornotify[0] = '\0';
18384 
18385    v = ast_variable_browse(cfg, "channels");
18386    if ((res = process_dahdi(base_conf,
18387       "" /* Must be empty for the channels category.  Silly voicemail mailbox. */,
18388       v, reload, 0))) {
18389       ast_mutex_unlock(&iflock);
18390       ast_config_destroy(cfg);
18391       if (ucfg) {
18392          ast_config_destroy(ucfg);
18393       }
18394       return res;
18395    }
18396 
18397    /* Now get configuration from all normal sections in chan_dahdi.conf: */
18398    for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) {
18399       /* [channels] and [trunkgroups] are used. Let's also reserve
18400        * [globals] and [general] for future use
18401        */
18402       if (!strcasecmp(cat, "general") ||
18403          !strcasecmp(cat, "trunkgroups") ||
18404          !strcasecmp(cat, "globals") ||
18405          !strcasecmp(cat, "channels")) {
18406          continue;
18407       }
18408 
18409       chans = ast_variable_retrieve(cfg, cat, "dahdichan");
18410       if (ast_strlen_zero(chans)) {
18411          /* Section is useless without a dahdichan value present. */
18412          continue;
18413       }
18414 
18415       /* Copy base_conf to conf. */
18416       deep_copy_dahdi_chan_conf(conf, base_conf);
18417 
18418       if ((res = process_dahdi(conf, cat, ast_variable_browse(cfg, cat), reload, PROC_DAHDI_OPT_NOCHAN))) {
18419          ast_mutex_unlock(&iflock);
18420          ast_config_destroy(cfg);
18421          if (ucfg) {
18422             ast_config_destroy(ucfg);
18423          }
18424          return res;
18425       }
18426    }
18427 
18428    ast_config_destroy(cfg);
18429 
18430    if (ucfg) {
18431       /* Reset base_conf, so things don't leak from chan_dahdi.conf */
18432       deep_copy_dahdi_chan_conf(base_conf, default_conf);
18433       process_dahdi(base_conf,
18434          "" /* Must be empty for the general category.  Silly voicemail mailbox. */,
18435          ast_variable_browse(ucfg, "general"), 1, 0);
18436 
18437       for (cat = ast_category_browse(ucfg, NULL); cat ; cat = ast_category_browse(ucfg, cat)) {
18438          if (!strcasecmp(cat, "general")) {
18439             continue;
18440          }
18441 
18442          chans = ast_variable_retrieve(ucfg, cat, "dahdichan");
18443          if (ast_strlen_zero(chans)) {
18444             /* Section is useless without a dahdichan value present. */
18445             continue;
18446          }
18447 
18448          /* Copy base_conf to conf. */
18449          deep_copy_dahdi_chan_conf(conf, base_conf);
18450 
18451          if ((res = process_dahdi(conf, cat, ast_variable_browse(ucfg, cat), reload, PROC_DAHDI_OPT_NOCHAN | PROC_DAHDI_OPT_NOWARN))) {
18452             ast_config_destroy(ucfg);
18453             ast_mutex_unlock(&iflock);
18454             return res;
18455          }
18456       }
18457       ast_config_destroy(ucfg);
18458    }
18459    ast_mutex_unlock(&iflock);
18460 
18461 #ifdef HAVE_PRI
18462    if (reload != 1) {
18463       int x;
18464       for (x = 0; x < NUM_SPANS; x++) {
18465          if (pris[x].pri.pvts[0]) {
18466             prepare_pri(pris + x);
18467             if (sig_pri_start_pri(&pris[x].pri)) {
18468                ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1);
18469                return -1;
18470             } else
18471                ast_verb(2, "Starting D-Channel on span %d\n", x + 1);
18472          }
18473       }
18474    }
18475 #endif
18476 #if defined(HAVE_SS7)
18477    if (reload != 1) {
18478       int x;
18479       for (x = 0; x < NUM_SPANS; x++) {
18480          if (linksets[x].ss7.ss7) {
18481             linksets[x].ss7.calls = &dahdi_ss7_callbacks;
18482             if (ast_pthread_create(&linksets[x].ss7.master, NULL, ss7_linkset, &linksets[x].ss7)) {
18483                ast_log(LOG_ERROR, "Unable to start SS7 linkset on span %d\n", x + 1);
18484                return -1;
18485             } else
18486                ast_verb(2, "Starting SS7 linkset on span %d\n", x + 1);
18487          }
18488       }
18489    }
18490 #endif   /* defined(HAVE_SS7) */
18491 #ifdef HAVE_OPENR2
18492    if (reload != 1) {
18493       int x;
18494       for (x = 0; x < r2links_count; x++) {
18495          if (ast_pthread_create(&r2links[x]->r2master, NULL, mfcr2_monitor, r2links[x])) {
18496             ast_log(LOG_ERROR, "Unable to start R2 monitor on channel group %d\n", x + 1);
18497             return -1;
18498          } else {
18499             ast_verb(2, "Starting R2 monitor on channel group %d\n", x + 1);
18500          }
18501       }
18502    }
18503 #endif
18504    /* And start the monitor for the first time */
18505    restart_monitor();
18506    return 0;
18507 }
18508 
18509 /*!
18510  * \internal
18511  * \brief Setup DAHDI channel driver.
18512  *
18513  * \param reload enum: load_module(0), reload(1), restart(2).
18514  *
18515  * \retval 0 on success.
18516  * \retval -1 on error.
18517  */
18518 static int setup_dahdi(int reload)
18519 {
18520    int res;
18521    struct dahdi_chan_conf default_conf = dahdi_chan_conf_default();
18522    struct dahdi_chan_conf base_conf = dahdi_chan_conf_default();
18523    struct dahdi_chan_conf conf = dahdi_chan_conf_default();
18524 
18525    if (default_conf.chan.cc_params && base_conf.chan.cc_params && conf.chan.cc_params) {
18526       res = setup_dahdi_int(reload, &default_conf, &base_conf, &conf);
18527    } else {
18528       res = -1;
18529    }
18530    ast_cc_config_params_destroy(default_conf.chan.cc_params);
18531    ast_cc_config_params_destroy(base_conf.chan.cc_params);
18532    ast_cc_config_params_destroy(conf.chan.cc_params);
18533 
18534    return res;
18535 }
18536 
18537 /*!
18538  * \internal
18539  * \brief Callback used to generate the dahdi status tree.
18540  * \param[in] search The search pattern tree.
18541  * \retval NULL on error.
18542  * \retval non-NULL The generated tree.
18543  */
18544 static int dahdi_status_data_provider_get(const struct ast_data_search *search,
18545       struct ast_data *data_root)
18546 {
18547    int ctl, res, span;
18548    struct ast_data *data_span, *data_alarms;
18549    struct dahdi_spaninfo s;
18550 
18551    ctl = open("/dev/dahdi/ctl", O_RDWR);
18552    if (ctl < 0) {
18553       ast_log(LOG_ERROR, "No DAHDI found. Unable to open /dev/dahdi/ctl: %s\n", strerror(errno));
18554       return -1;
18555    }
18556    for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
18557       s.spanno = span;
18558       res = ioctl(ctl, DAHDI_SPANSTAT, &s);
18559       if (res) {
18560          continue;
18561       }
18562 
18563       data_span = ast_data_add_node(data_root, "span");
18564       if (!data_span) {
18565          continue;
18566       }
18567       ast_data_add_str(data_span, "description", s.desc);
18568 
18569       /* insert the alarms status */
18570       data_alarms = ast_data_add_node(data_span, "alarms");
18571       if (!data_alarms) {
18572          continue;
18573       }
18574 
18575       ast_data_add_bool(data_alarms, "BLUE", s.alarms & DAHDI_ALARM_BLUE);
18576       ast_data_add_bool(data_alarms, "YELLOW", s.alarms & DAHDI_ALARM_YELLOW);
18577       ast_data_add_bool(data_alarms, "RED", s.alarms & DAHDI_ALARM_RED);
18578       ast_data_add_bool(data_alarms, "LOOPBACK", s.alarms & DAHDI_ALARM_LOOPBACK);
18579       ast_data_add_bool(data_alarms, "RECOVER", s.alarms & DAHDI_ALARM_RECOVER);
18580       ast_data_add_bool(data_alarms, "NOTOPEN", s.alarms & DAHDI_ALARM_NOTOPEN);
18581 
18582       ast_data_add_int(data_span, "irqmisses", s.irqmisses);
18583       ast_data_add_int(data_span, "bpviol", s.bpvcount);
18584       ast_data_add_int(data_span, "crc4", s.crc4count);
18585       ast_data_add_str(data_span, "framing", s.lineconfig & DAHDI_CONFIG_D4 ? "D4" :
18586                      s.lineconfig & DAHDI_CONFIG_ESF ? "ESF" :
18587                      s.lineconfig & DAHDI_CONFIG_CCS ? "CCS" :
18588                      "CAS");
18589       ast_data_add_str(data_span, "coding",  s.lineconfig & DAHDI_CONFIG_B8ZS ? "B8ZS" :
18590                      s.lineconfig & DAHDI_CONFIG_HDB3 ? "HDB3" :
18591                      s.lineconfig & DAHDI_CONFIG_AMI ? "AMI" :
18592                      "Unknown");
18593       ast_data_add_str(data_span, "options", s.lineconfig & DAHDI_CONFIG_CRC4 ?
18594                      s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" :
18595                      s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "YEL" : "");
18596       ast_data_add_str(data_span, "lbo", lbostr[s.lbo]);
18597 
18598       /* if this span doesn't match remove it. */
18599       if (!ast_data_search_match(search, data_span)) {
18600          ast_data_remove_node(data_root, data_span);
18601       }
18602    }
18603    close(ctl);
18604 
18605    return 0;
18606 }
18607 
18608 /*!
18609  * \internal
18610  * \brief Callback used to generate the dahdi channels tree.
18611  * \param[in] search The search pattern tree.
18612  * \retval NULL on error.
18613  * \retval non-NULL The generated tree.
18614  */
18615 static int dahdi_channels_data_provider_get(const struct ast_data_search *search,
18616       struct ast_data *data_root)
18617 {
18618    struct dahdi_pvt *tmp;
18619    struct ast_data *data_channel;
18620 
18621    ast_mutex_lock(&iflock);
18622    for (tmp = iflist; tmp; tmp = tmp->next) {
18623       data_channel = ast_data_add_node(data_root, "channel");
18624       if (!data_channel) {
18625          continue;
18626       }
18627 
18628       ast_data_add_structure(dahdi_pvt, data_channel, tmp);
18629 
18630       /* if this channel doesn't match remove it. */
18631       if (!ast_data_search_match(search, data_channel)) {
18632          ast_data_remove_node(data_root, data_channel);
18633       }
18634    }
18635    ast_mutex_unlock(&iflock);
18636 
18637    return 0;
18638 }
18639 
18640 /*!
18641  * \internal
18642  * \brief Callback used to generate the dahdi channels tree.
18643  * \param[in] search The search pattern tree.
18644  * \retval NULL on error.
18645  * \retval non-NULL The generated tree.
18646  */
18647 static int dahdi_version_data_provider_get(const struct ast_data_search *search,
18648       struct ast_data *data_root)
18649 {
18650    int pseudo_fd = -1;
18651    struct dahdi_versioninfo vi = {
18652       .version = "Unknown",
18653       .echo_canceller = "Unknown"
18654    };
18655 
18656    if ((pseudo_fd = open("/dev/dahdi/ctl", O_RDONLY)) < 0) {
18657       ast_log(LOG_ERROR, "Failed to open control file to get version.\n");
18658       return -1;
18659    }
18660 
18661    if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi)) {
18662       ast_log(LOG_ERROR, "Failed to get DAHDI version: %s\n", strerror(errno));
18663    }
18664 
18665    close(pseudo_fd);
18666 
18667    ast_data_add_str(data_root, "value", vi.version);
18668    ast_data_add_str(data_root, "echocanceller", vi.echo_canceller);
18669 
18670    return 0;
18671 }
18672 
18673 static const struct ast_data_handler dahdi_status_data_provider = {
18674    .version = AST_DATA_HANDLER_VERSION,
18675    .get = dahdi_status_data_provider_get
18676 };
18677 
18678 static const struct ast_data_handler dahdi_channels_data_provider = {
18679    .version = AST_DATA_HANDLER_VERSION,
18680    .get = dahdi_channels_data_provider_get
18681 };
18682 
18683 static const struct ast_data_handler dahdi_version_data_provider = {
18684    .version = AST_DATA_HANDLER_VERSION,
18685    .get = dahdi_version_data_provider_get
18686 };
18687 
18688 static const struct ast_data_entry dahdi_data_providers[] = {
18689    AST_DATA_ENTRY("asterisk/channel/dahdi/status", &dahdi_status_data_provider),
18690    AST_DATA_ENTRY("asterisk/channel/dahdi/channels", &dahdi_channels_data_provider),
18691    AST_DATA_ENTRY("asterisk/channel/dahdi/version", &dahdi_version_data_provider)
18692 };
18693 
18694 static int load_module(void)
18695 {
18696    int res;
18697 #if defined(HAVE_PRI) || defined(HAVE_SS7)
18698    int y;
18699 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
18700 
18701 #ifdef HAVE_PRI
18702    memset(pris, 0, sizeof(pris));
18703    for (y = 0; y < NUM_SPANS; y++) {
18704       sig_pri_init_pri(&pris[y].pri);
18705    }
18706    pri_set_error(dahdi_pri_error);
18707    pri_set_message(dahdi_pri_message);
18708    ast_register_application_xml(dahdi_send_keypad_facility_app, dahdi_send_keypad_facility_exec);
18709 #ifdef HAVE_PRI_PROG_W_CAUSE
18710    ast_register_application_xml(dahdi_send_callrerouting_facility_app, dahdi_send_callrerouting_facility_exec);
18711 #endif
18712 #if defined(HAVE_PRI_CCSS)
18713    if (ast_cc_agent_register(&dahdi_pri_cc_agent_callbacks)
18714       || ast_cc_monitor_register(&dahdi_pri_cc_monitor_callbacks)) {
18715       __unload_module();
18716       return AST_MODULE_LOAD_FAILURE;
18717    }
18718 #endif   /* defined(HAVE_PRI_CCSS) */
18719    if (sig_pri_load(
18720 #if defined(HAVE_PRI_CCSS)
18721       dahdi_pri_cc_type
18722 #else
18723       NULL
18724 #endif   /* defined(HAVE_PRI_CCSS) */
18725       )) {
18726       __unload_module();
18727       return AST_MODULE_LOAD_FAILURE;
18728    }
18729 #endif
18730 #if defined(HAVE_SS7)
18731    memset(linksets, 0, sizeof(linksets));
18732    for (y = 0; y < NUM_SPANS; y++) {
18733       sig_ss7_init_linkset(&linksets[y].ss7);
18734    }
18735    ss7_set_error(dahdi_ss7_error);
18736    ss7_set_message(dahdi_ss7_message);
18737 #endif   /* defined(HAVE_SS7) */
18738    res = setup_dahdi(0);
18739    /* Make sure we can register our DAHDI channel type */
18740    if (res)
18741       return AST_MODULE_LOAD_DECLINE;
18742    if (ast_channel_register(&dahdi_tech)) {
18743       ast_log(LOG_ERROR, "Unable to register channel class 'DAHDI'\n");
18744       __unload_module();
18745       return AST_MODULE_LOAD_FAILURE;
18746    }
18747 #ifdef HAVE_PRI
18748    ast_cli_register_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
18749 #endif
18750 #if defined(HAVE_SS7)
18751    ast_cli_register_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
18752 #endif   /* defined(HAVE_SS7) */
18753 #ifdef HAVE_OPENR2
18754    ast_cli_register_multiple(dahdi_mfcr2_cli, ARRAY_LEN(dahdi_mfcr2_cli));
18755    ast_register_application_xml(dahdi_accept_r2_call_app, dahdi_accept_r2_call_exec);
18756 #endif
18757 
18758    ast_cli_register_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli));
18759    /* register all the data providers */
18760    ast_data_register_multiple(dahdi_data_providers, ARRAY_LEN(dahdi_data_providers));
18761    memset(round_robin, 0, sizeof(round_robin));
18762    ast_manager_register_xml("DAHDITransfer", 0, action_transfer);
18763    ast_manager_register_xml("DAHDIHangup", 0, action_transferhangup);
18764    ast_manager_register_xml("DAHDIDialOffhook", 0, action_dahdidialoffhook);
18765    ast_manager_register_xml("DAHDIDNDon", 0, action_dahdidndon);
18766    ast_manager_register_xml("DAHDIDNDoff", 0, action_dahdidndoff);
18767    ast_manager_register_xml("DAHDIShowChannels", 0, action_dahdishowchannels);
18768    ast_manager_register_xml("DAHDIRestart", 0, action_dahdirestart);
18769 
18770    ast_cond_init(&ss_thread_complete, NULL);
18771 
18772    return res;
18773 }
18774 
18775 static int dahdi_sendtext(struct ast_channel *c, const char *text)
18776 {
18777 #define  END_SILENCE_LEN 400
18778 #define  HEADER_MS 50
18779 #define  TRAILER_MS 5
18780 #define  HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8)
18781 #define  ASCII_BYTES_PER_CHAR 80
18782 
18783    unsigned char *buf,*mybuf;
18784    struct dahdi_pvt *p = c->tech_pvt;
18785    struct pollfd fds[1];
18786    int size,res,fd,len,x;
18787    int bytes=0;
18788    /* Initial carrier (imaginary) */
18789    float cr = 1.0;
18790    float ci = 0.0;
18791    float scont = 0.0;
18792    int idx;
18793 
18794    idx = dahdi_get_index(c, p, 0);
18795    if (idx < 0) {
18796       ast_log(LOG_WARNING, "Huh?  I don't exist?\n");
18797       return -1;
18798    }
18799    if (!text[0]) return(0); /* if nothing to send, don't */
18800    if ((!p->tdd) && (!p->mate)) return(0);  /* if not in TDD mode, just return */
18801    if (p->mate)
18802       buf = ast_malloc(((strlen(text) + 1) * ASCII_BYTES_PER_CHAR) + END_SILENCE_LEN + HEADER_LEN);
18803    else
18804       buf = ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN);
18805    if (!buf)
18806       return -1;
18807    mybuf = buf;
18808    if (p->mate) {
18809       int codec = AST_LAW(p);
18810       for (x = 0; x < HEADER_MS; x++) {   /* 50 ms of Mark */
18811          PUT_CLID_MARKMS;
18812       }
18813       /* Put actual message */
18814       for (x = 0; text[x]; x++) {
18815          PUT_CLID(text[x]);
18816       }
18817       for (x = 0; x < TRAILER_MS; x++) {  /* 5 ms of Mark */
18818          PUT_CLID_MARKMS;
18819       }
18820       len = bytes;
18821       buf = mybuf;
18822    } else {
18823       len = tdd_generate(p->tdd, buf, text);
18824       if (len < 1) {
18825          ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text));
18826          ast_free(mybuf);
18827          return -1;
18828       }
18829    }
18830    memset(buf + len, 0x7f, END_SILENCE_LEN);
18831    len += END_SILENCE_LEN;
18832    fd = p->subs[idx].dfd;
18833    while (len) {
18834       if (ast_check_hangup(c)) {
18835          ast_free(mybuf);
18836          return -1;
18837       }
18838       size = len;
18839       if (size > READ_SIZE)
18840          size = READ_SIZE;
18841       fds[0].fd = fd;
18842       fds[0].events = POLLOUT | POLLPRI;
18843       fds[0].revents = 0;
18844       res = poll(fds, 1, -1);
18845       if (!res) {
18846          ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
18847          continue;
18848       }
18849       /* if got exception */
18850       if (fds[0].revents & POLLPRI) {
18851          ast_free(mybuf);
18852          return -1;
18853       }
18854       if (!(fds[0].revents & POLLOUT)) {
18855          ast_debug(1, "write fd not ready on channel %d\n", p->channel);
18856          continue;
18857       }
18858       res = write(fd, buf, size);
18859       if (res != size) {
18860          if (res == -1) {
18861             ast_free(mybuf);
18862             return -1;
18863          }
18864          ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
18865          break;
18866       }
18867       len -= size;
18868       buf += size;
18869    }
18870    ast_free(mybuf);
18871    return(0);
18872 }
18873 
18874 
18875 static int reload(void)
18876 {
18877    int res = 0;
18878 
18879    res = setup_dahdi(1);
18880    if (res) {
18881       ast_log(LOG_WARNING, "Reload of chan_dahdi.so is unsuccessful!\n");
18882       return -1;
18883    }
18884    return 0;
18885 }
18886 
18887 /* This is a workaround so that menuselect displays a proper description
18888  * AST_MODULE_INFO(, , "DAHDI Telephony"
18889  */
18890 
18891 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, tdesc,
18892    .load = load_module,
18893    .unload = unload_module,
18894    .reload = reload,
18895    .load_pri = AST_MODPRI_CHANNEL_DRIVER,
18896       .nonoptreq = "res_smdi",
18897    );