Fri Apr 29 2011 07:54:02

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  ***/
00048 
00049 #include "asterisk.h"
00050 
00051 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 301134 $")
00052 
00053 #if defined(__NetBSD__) || defined(__FreeBSD__)
00054 #include <pthread.h>
00055 #include <signal.h>
00056 #else
00057 #include <sys/signal.h>
00058 #endif
00059 #include <sys/ioctl.h>
00060 #include <sys/stat.h>
00061 #include <math.h>
00062 #include <ctype.h>
00063 
00064 #include <dahdi/user.h>
00065 #include <dahdi/tonezone.h>
00066 #include "sig_analog.h"
00067 /* Analog signaling is currently still present in chan_dahdi for use with
00068  * radio. Sig_analog does not currently handle any radio operations. If
00069  * radio only uses analog signaling, then the radio handling logic could
00070  * be placed in sig_analog and the duplicated code could be removed.
00071  */
00072 
00073 #ifdef HAVE_PRI
00074 #include "sig_pri.h"
00075 #endif
00076 
00077 #if defined(HAVE_SS7)
00078 #include "sig_ss7.h"
00079 #endif   /* defined(HAVE_SS7) */
00080 
00081 #ifdef HAVE_OPENR2
00082 /* put this here until sig_mfcr2 comes along */
00083 #define SIG_MFCR2_MAX_CHANNELS   672      /*!< No more than a DS3 per trunk group */
00084 #include <openr2.h>
00085 #endif
00086 
00087 #include "asterisk/lock.h"
00088 #include "asterisk/channel.h"
00089 #include "asterisk/config.h"
00090 #include "asterisk/module.h"
00091 #include "asterisk/pbx.h"
00092 #include "asterisk/file.h"
00093 #include "asterisk/ulaw.h"
00094 #include "asterisk/alaw.h"
00095 #include "asterisk/callerid.h"
00096 #include "asterisk/adsi.h"
00097 #include "asterisk/cli.h"
00098 #include "asterisk/cdr.h"
00099 #include "asterisk/cel.h"
00100 #include "asterisk/features.h"
00101 #include "asterisk/musiconhold.h"
00102 #include "asterisk/say.h"
00103 #include "asterisk/tdd.h"
00104 #include "asterisk/app.h"
00105 #include "asterisk/dsp.h"
00106 #include "asterisk/astdb.h"
00107 #include "asterisk/manager.h"
00108 #include "asterisk/causes.h"
00109 #include "asterisk/term.h"
00110 #include "asterisk/utils.h"
00111 #include "asterisk/transcap.h"
00112 #include "asterisk/stringfields.h"
00113 #include "asterisk/abstract_jb.h"
00114 #include "asterisk/smdi.h"
00115 #include "asterisk/astobj.h"
00116 #include "asterisk/event.h"
00117 #include "asterisk/devicestate.h"
00118 #include "asterisk/paths.h"
00119 #include "asterisk/ccss.h"
00120 #include "asterisk/data.h"
00121 
00122 /*** DOCUMENTATION
00123    <application name="DAHDISendKeypadFacility" language="en_US">
00124       <synopsis>
00125          Send digits out of band over a PRI.
00126       </synopsis>
00127       <syntax>
00128          <parameter name="digits" required="true" />
00129       </syntax>
00130       <description>
00131          <para>This application will send the given string of digits in a Keypad
00132          Facility IE over the current channel.</para>
00133       </description>
00134    </application>
00135    <application name="DAHDISendCallreroutingFacility" language="en_US">
00136       <synopsis>
00137          Send QSIG call rerouting facility over a PRI.
00138       </synopsis>
00139       <syntax argsep=",">
00140          <parameter name="destination" required="true">
00141             <para>Destination number.</para>
00142          </parameter>
00143          <parameter name="original">
00144             <para>Original called number.</para>
00145          </parameter>
00146          <parameter name="reason">
00147             <para>Diversion reason, if not specified defaults to <literal>unknown</literal></para>
00148          </parameter>
00149       </syntax>
00150       <description>
00151          <para>This application will send a Callrerouting Facility IE over the
00152          current channel.</para>
00153       </description>
00154    </application>
00155    <application name="DAHDIAcceptR2Call" language="en_US">
00156       <synopsis>
00157          Accept an R2 call if its not already accepted (you still need to answer it)
00158       </synopsis>
00159       <syntax>
00160          <parameter name="charge" required="true">
00161             <para>Yes or No.</para>
00162             <para>Whether you want to accept the call with charge or without charge.</para>
00163          </parameter>
00164       </syntax>
00165       <description>
00166          <para>This application will Accept the R2 call either with charge or no charge.</para>
00167       </description>
00168    </application>
00169    <manager name="DAHDITransfer" language="en_US">
00170       <synopsis>
00171          Transfer DAHDI Channel.
00172       </synopsis>
00173       <syntax>
00174          <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
00175          <parameter name="DAHDIChannel" required="true">
00176             <para>DAHDI channel name to transfer.</para>
00177          </parameter>
00178       </syntax>
00179       <description>
00180          <para>Transfer a DAHDI channel.</para>
00181       </description>
00182    </manager>
00183    <manager name="DAHDIHangup" language="en_US">
00184       <synopsis>
00185          Hangup DAHDI Channel.
00186       </synopsis>
00187       <syntax>
00188          <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
00189          <parameter name="DAHDIChannel" required="true">
00190             <para>DAHDI channel name to hangup.</para>
00191          </parameter>
00192       </syntax>
00193       <description>
00194          <para>Hangup a DAHDI channel.</para>
00195       </description>
00196    </manager>
00197    <manager name="DAHDIDialOffhook" language="en_US">
00198       <synopsis>
00199          Dial over DAHDI channel while offhook.
00200       </synopsis>
00201       <syntax>
00202          <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
00203          <parameter name="DAHDIChannel" required="true" />
00204          <parameter name="Number" required="true" />
00205       </syntax>
00206       <description>
00207       </description>
00208    </manager>
00209    <manager name="DAHDIDNDon" language="en_US">
00210       <synopsis>
00211          Toggle DAHDI channel Do Not Disturb status ON.
00212       </synopsis>
00213       <syntax>
00214          <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
00215          <parameter name="DAHDIChannel" required="true" />
00216       </syntax>
00217       <description>
00218       </description>
00219    </manager>
00220    <manager name="DAHDIDNDoff" language="en_US">
00221       <synopsis>
00222          Toggle DAHDI channel Do Not Disturb status OFF.
00223       </synopsis>
00224       <syntax>
00225          <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
00226          <parameter name="DAHDIChannel" required="true" />
00227       </syntax>
00228       <description>
00229       </description>
00230    </manager>
00231    <manager name="DAHDIShowChannels" language="en_US">
00232       <synopsis>
00233          Show status DAHDI channels.
00234       </synopsis>
00235       <syntax>
00236          <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
00237          <parameter name="DAHDIChannel" required="true" />
00238       </syntax>
00239       <description>
00240       </description>
00241    </manager>
00242    <manager name="DAHDIRestart" language="en_US">
00243       <synopsis>
00244          Fully Restart DAHDI channels (terminates calls).
00245       </synopsis>
00246       <syntax>
00247          <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
00248       </syntax>
00249       <description>
00250       </description>
00251    </manager>
00252  ***/
00253 
00254 #define SMDI_MD_WAIT_TIMEOUT 1500 /* 1.5 seconds */
00255 
00256 static const char * const lbostr[] = {
00257 "0 db (CSU)/0-133 feet (DSX-1)",
00258 "133-266 feet (DSX-1)",
00259 "266-399 feet (DSX-1)",
00260 "399-533 feet (DSX-1)",
00261 "533-655 feet (DSX-1)",
00262 "-7.5db (CSU)",
00263 "-15db (CSU)",
00264 "-22.5db (CSU)"
00265 };
00266 
00267 /*! Global jitterbuffer configuration - by default, jb is disabled */
00268 static struct ast_jb_conf default_jbconf =
00269 {
00270    .flags = 0,
00271    .max_size = -1,
00272    .resync_threshold = -1,
00273    .impl = "",
00274    .target_extra = -1,
00275 };
00276 static struct ast_jb_conf global_jbconf;
00277 
00278 /*!
00279  * \note Define ZHONE_HACK to cause us to go off hook and then back on hook when
00280  * the user hangs up to reset the state machine so ring works properly.
00281  * This is used to be able to support kewlstart by putting the zhone in
00282  * groundstart mode since their forward disconnect supervision is entirely
00283  * broken even though their documentation says it isn't and their support
00284  * is entirely unwilling to provide any assistance with their channel banks
00285  * even though their web site says they support their products for life.
00286  */
00287 /* #define ZHONE_HACK */
00288 
00289 /*! \brief Typically, how many rings before we should send Caller*ID */
00290 #define DEFAULT_CIDRINGS 1
00291 
00292 #define AST_LAW(p) (((p)->law == DAHDI_LAW_ALAW) ? AST_FORMAT_ALAW : AST_FORMAT_ULAW)
00293 
00294 
00295 /*! \brief Signaling types that need to use MF detection should be placed in this macro */
00296 #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))
00297 
00298 static const char tdesc[] = "DAHDI Telephony Driver"
00299 #if defined(HAVE_PRI) || defined(HAVE_SS7) || defined(HAVE_OPENR2)
00300    " w/"
00301    #if defined(HAVE_PRI)
00302       "PRI"
00303    #endif   /* defined(HAVE_PRI) */
00304    #if defined(HAVE_SS7)
00305       #if defined(HAVE_PRI)
00306       " & "
00307       #endif   /* defined(HAVE_PRI) */
00308       "SS7"
00309    #endif   /* defined(HAVE_SS7) */
00310    #if defined(HAVE_OPENR2)
00311       #if defined(HAVE_PRI) || defined(HAVE_SS7)
00312       " & "
00313       #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
00314       "MFC/R2"
00315    #endif   /* defined(HAVE_OPENR2) */
00316 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) || defined(HAVE_OPENR2) */
00317 ;
00318 
00319 static const char config[] = "chan_dahdi.conf";
00320 
00321 #define SIG_EM    DAHDI_SIG_EM
00322 #define SIG_EMWINK   (0x0100000 | DAHDI_SIG_EM)
00323 #define SIG_FEATD (0x0200000 | DAHDI_SIG_EM)
00324 #define  SIG_FEATDMF (0x0400000 | DAHDI_SIG_EM)
00325 #define  SIG_FEATB   (0x0800000 | DAHDI_SIG_EM)
00326 #define  SIG_E911 (0x1000000 | DAHDI_SIG_EM)
00327 #define  SIG_FEATDMF_TA (0x2000000 | DAHDI_SIG_EM)
00328 #define  SIG_FGC_CAMA   (0x4000000 | DAHDI_SIG_EM)
00329 #define  SIG_FGC_CAMAMF (0x8000000 | DAHDI_SIG_EM)
00330 #define SIG_FXSLS DAHDI_SIG_FXSLS
00331 #define SIG_FXSGS DAHDI_SIG_FXSGS
00332 #define SIG_FXSKS DAHDI_SIG_FXSKS
00333 #define SIG_FXOLS DAHDI_SIG_FXOLS
00334 #define SIG_FXOGS DAHDI_SIG_FXOGS
00335 #define SIG_FXOKS DAHDI_SIG_FXOKS
00336 #define SIG_PRI      DAHDI_SIG_CLEAR
00337 #define SIG_BRI      (0x2000000 | DAHDI_SIG_CLEAR)
00338 #define SIG_BRI_PTMP (0X4000000 | DAHDI_SIG_CLEAR)
00339 #define SIG_SS7      (0x1000000 | DAHDI_SIG_CLEAR)
00340 #define SIG_MFCR2    DAHDI_SIG_CAS
00341 #define  SIG_SF      DAHDI_SIG_SF
00342 #define SIG_SFWINK   (0x0100000 | DAHDI_SIG_SF)
00343 #define SIG_SF_FEATD (0x0200000 | DAHDI_SIG_SF)
00344 #define  SIG_SF_FEATDMF (0x0400000 | DAHDI_SIG_SF)
00345 #define  SIG_SF_FEATB   (0x0800000 | DAHDI_SIG_SF)
00346 #define SIG_EM_E1 DAHDI_SIG_EM_E1
00347 
00348 #ifdef LOTS_OF_SPANS
00349 #define NUM_SPANS DAHDI_MAX_SPANS
00350 #else
00351 #define NUM_SPANS       32
00352 #endif
00353 
00354 #define CHAN_PSEUDO  -2
00355 
00356 #define CALLPROGRESS_PROGRESS    1
00357 #define CALLPROGRESS_FAX_OUTGOING   2
00358 #define CALLPROGRESS_FAX_INCOMING   4
00359 #define CALLPROGRESS_FAX      (CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING)
00360 
00361 #define NUM_CADENCE_MAX 25
00362 static int num_cadence = 4;
00363 static int user_has_defined_cadences = 0;
00364 
00365 static struct dahdi_ring_cadence cadences[NUM_CADENCE_MAX] = {
00366    { { 125, 125, 2000, 4000 } },       /*!< Quick chirp followed by normal ring */
00367    { { 250, 250, 500, 1000, 250, 250, 500, 4000 } }, /*!< British style ring */
00368    { { 125, 125, 125, 125, 125, 4000 } }, /*!< Three short bursts */
00369    { { 1000, 500, 2500, 5000 } },   /*!< Long ring */
00370 };
00371 
00372 /*! \brief cidrings says in which pause to transmit the cid information, where the first pause
00373  * is 1, the second pause is 2 and so on.
00374  */
00375 
00376 static int cidrings[NUM_CADENCE_MAX] = {
00377    2,                            /*!< Right after first long ring */
00378    4,                            /*!< Right after long part */
00379    3,                            /*!< After third chirp */
00380    2,                            /*!< Second spell */
00381 };
00382 
00383 /* ETSI EN300 659-1 specifies the ring pulse between 200 and 300 mS */
00384 static struct dahdi_ring_cadence AS_RP_cadence = {{250, 10000}};
00385 
00386 #define ISTRUNK(p) ((p->sig == SIG_FXSLS) || (p->sig == SIG_FXSKS) || \
00387          (p->sig == SIG_FXSGS) || (p->sig == SIG_PRI))
00388 
00389 #define CANBUSYDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */)
00390 #define CANPROGRESSDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */)
00391 
00392 static char defaultcic[64] = "";
00393 static char defaultozz[64] = "";
00394 
00395 static char parkinglot[AST_MAX_EXTENSION] = "";    /*!< Default parking lot for this channel */
00396 
00397 /*! Run this script when the MWI state changes on an FXO line, if mwimonitor is enabled */
00398 static char mwimonitornotify[PATH_MAX] = "";
00399 #ifndef HAVE_DAHDI_LINEREVERSE_VMWI
00400 static int  mwisend_rpas = 0;
00401 #endif
00402 
00403 static char progzone[10] = "";
00404 
00405 static int usedistinctiveringdetection = 0;
00406 static int distinctiveringaftercid = 0;
00407 
00408 static int numbufs = 4;
00409 
00410 static int mwilevel = 512;
00411 static int dtmfcid_level = 256;
00412 
00413 #define REPORT_CHANNEL_ALARMS 1
00414 #define REPORT_SPAN_ALARMS    2 
00415 static int report_alarms = REPORT_CHANNEL_ALARMS;
00416 
00417 #ifdef HAVE_PRI
00418 static int pridebugfd = -1;
00419 static char pridebugfilename[1024] = "";
00420 #endif
00421 
00422 /*! \brief Wait up to 16 seconds for first digit (FXO logic) */
00423 static int firstdigittimeout = 16000;
00424 
00425 /*! \brief How long to wait for following digits (FXO logic) */
00426 static int gendigittimeout = 8000;
00427 
00428 /*! \brief How long to wait for an extra digit, if there is an ambiguous match */
00429 static int matchdigittimeout = 3000;
00430 
00431 /*! \brief Protect the interface list (of dahdi_pvt's) */
00432 AST_MUTEX_DEFINE_STATIC(iflock);
00433 
00434 
00435 static int ifcount = 0;
00436 
00437 #ifdef HAVE_PRI
00438 AST_MUTEX_DEFINE_STATIC(pridebugfdlock);
00439 #endif
00440 
00441 /*! \brief Protect the monitoring thread, so only one process can kill or start it, and not
00442    when it's doing something critical. */
00443 AST_MUTEX_DEFINE_STATIC(monlock);
00444 
00445 /*! \brief This is the thread for the monitor which checks for input on the channels
00446    which are not currently in use. */
00447 static pthread_t monitor_thread = AST_PTHREADT_NULL;
00448 static ast_cond_t ss_thread_complete;
00449 AST_MUTEX_DEFINE_STATIC(ss_thread_lock);
00450 AST_MUTEX_DEFINE_STATIC(restart_lock);
00451 static int ss_thread_count = 0;
00452 static int num_restart_pending = 0;
00453 
00454 static int restart_monitor(void);
00455 
00456 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);
00457 
00458 static int dahdi_sendtext(struct ast_channel *c, const char *text);
00459 
00460 static void mwi_event_cb(const struct ast_event *event, void *userdata)
00461 {
00462    /* This module does not handle MWI in an event-based manner.  However, it
00463     * subscribes to MWI for each mailbox that is configured so that the core
00464     * knows that we care about it.  Then, chan_dahdi will get the MWI from the
00465     * event cache instead of checking the mailbox directly. */
00466 }
00467 
00468 /*! \brief Avoid the silly dahdi_getevent which ignores a bunch of events */
00469 static inline int dahdi_get_event(int fd)
00470 {
00471    int j;
00472    if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
00473       return -1;
00474    return j;
00475 }
00476 
00477 /*! \brief Avoid the silly dahdi_waitevent which ignores a bunch of events */
00478 static inline int dahdi_wait_event(int fd)
00479 {
00480    int i, j = 0;
00481    i = DAHDI_IOMUX_SIGEVENT;
00482    if (ioctl(fd, DAHDI_IOMUX, &i) == -1)
00483       return -1;
00484    if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
00485       return -1;
00486    return j;
00487 }
00488 
00489 /*! Chunk size to read -- we use 20ms chunks to make things happy. */
00490 #define READ_SIZE 160
00491 
00492 #define MASK_AVAIL      (1 << 0) /*!< Channel available for PRI use */
00493 #define MASK_INUSE      (1 << 1) /*!< Channel currently in use */
00494 
00495 #define CALLWAITING_SILENT_SAMPLES     ((300 * 8) / READ_SIZE) /*!< 300 ms */
00496 #define CALLWAITING_REPEAT_SAMPLES     ((10000 * 8) / READ_SIZE) /*!< 10,000 ms */
00497 #define CALLWAITING_SUPPRESS_SAMPLES   ((100 * 8) / READ_SIZE) /*!< 100 ms */
00498 #define CIDCW_EXPIRE_SAMPLES        ((500 * 8) / READ_SIZE) /*!< 500 ms */
00499 #define MIN_MS_SINCE_FLASH          ((2000) )   /*!< 2000 ms */
00500 #define DEFAULT_RINGT               ((8000 * 8) / READ_SIZE) /*!< 8,000 ms */
00501 
00502 struct dahdi_pvt;
00503 
00504 /*!
00505  * \brief Configured ring timeout base.
00506  * \note Value computed from "ringtimeout" read in from chan_dahdi.conf if it exists.
00507  */
00508 static int ringt_base = DEFAULT_RINGT;
00509 
00510 #if defined(HAVE_SS7)
00511 
00512 struct dahdi_ss7 {
00513    struct sig_ss7_linkset ss7;
00514 };
00515 
00516 static struct dahdi_ss7 linksets[NUM_SPANS];
00517 
00518 static int cur_ss7type = -1;
00519 static int cur_linkset = -1;
00520 static int cur_pointcode = -1;
00521 static int cur_cicbeginswith = -1;
00522 static int cur_adjpointcode = -1;
00523 static int cur_networkindicator = -1;
00524 static int cur_defaultdpc = -1;
00525 #endif   /* defined(HAVE_SS7) */
00526 
00527 #ifdef HAVE_OPENR2
00528 struct dahdi_mfcr2 {
00529    pthread_t r2master;            /*!< Thread of master */
00530    openr2_context_t *protocol_context;    /*!< OpenR2 context handle */
00531    struct dahdi_pvt *pvts[SIG_MFCR2_MAX_CHANNELS];     /*!< Member channel pvt structs */
00532    int numchans;                          /*!< Number of channels in this R2 block */
00533    int monitored_count;                   /*!< Number of channels being monitored */
00534 };
00535 
00536 struct dahdi_mfcr2_conf {
00537    openr2_variant_t variant;
00538    int mfback_timeout;
00539    int metering_pulse_timeout;
00540    int max_ani;
00541    int max_dnis;
00542    signed int get_ani_first:2;
00543 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
00544    signed int skip_category_request:2;
00545 #endif
00546    unsigned int call_files:1;
00547    unsigned int allow_collect_calls:1;
00548    unsigned int charge_calls:1;
00549    unsigned int accept_on_offer:1;
00550    unsigned int forced_release:1;
00551    unsigned int double_answer:1;
00552    signed int immediate_accept:2;
00553    char logdir[OR2_MAX_PATH];
00554    char r2proto_file[OR2_MAX_PATH];
00555    openr2_log_level_t loglevel;
00556    openr2_calling_party_category_t category;
00557 };
00558 
00559 /* malloc'd array of malloc'd r2links */
00560 static struct dahdi_mfcr2 **r2links;
00561 /* how many r2links have been malloc'd */
00562 static int r2links_count = 0;
00563 
00564 #endif /* HAVE_OPENR2 */
00565 
00566 #ifdef HAVE_PRI
00567 
00568 struct dahdi_pri {
00569    int dchannels[SIG_PRI_NUM_DCHANS];     /*!< What channel are the dchannels on */
00570    int mastertrunkgroup;               /*!< What trunk group is our master */
00571    int prilogicalspan;                 /*!< Logical span number within trunk group */
00572    struct sig_pri_span pri;
00573 };
00574 
00575 static struct dahdi_pri pris[NUM_SPANS];
00576 
00577 #if defined(HAVE_PRI_CCSS)
00578 /*! DAHDI PRI CCSS agent and monitor type name. */
00579 static const char dahdi_pri_cc_type[] = "DAHDI/PRI";
00580 #endif   /* defined(HAVE_PRI_CCSS) */
00581 
00582 #else
00583 /*! Shut up the compiler */
00584 struct dahdi_pri;
00585 #endif
00586 
00587 #define SUB_REAL  0        /*!< Active call */
00588 #define SUB_CALLWAIT 1        /*!< Call-Waiting call on hold */
00589 #define SUB_THREEWAY 2        /*!< Three-way call */
00590 
00591 /* Polarity states */
00592 #define POLARITY_IDLE   0
00593 #define POLARITY_REV    1
00594 
00595 
00596 struct distRingData {
00597    int ring[3];
00598    int range;
00599 };
00600 struct ringContextData {
00601    char contextData[AST_MAX_CONTEXT];
00602 };
00603 struct dahdi_distRings {
00604    struct distRingData ringnum[3];
00605    struct ringContextData ringContext[3];
00606 };
00607 
00608 static const char * const subnames[] = {
00609    "Real",
00610    "Callwait",
00611    "Threeway"
00612 };
00613 
00614 struct dahdi_subchannel {
00615    int dfd;
00616    struct ast_channel *owner;
00617    int chan;
00618    short buffer[AST_FRIENDLY_OFFSET/2 + READ_SIZE];
00619    struct ast_frame f;     /*!< One frame for each channel.  How did this ever work before? */
00620    unsigned int needringing:1;
00621    unsigned int needbusy:1;
00622    unsigned int needcongestion:1;
00623    unsigned int needanswer:1;
00624    unsigned int needflash:1;
00625    unsigned int needhold:1;
00626    unsigned int needunhold:1;
00627    unsigned int linear:1;
00628    unsigned int inthreeway:1;
00629    struct dahdi_confinfo curconf;
00630 };
00631 
00632 #define CONF_USER_REAL     (1 << 0)
00633 #define CONF_USER_THIRDCALL   (1 << 1)
00634 
00635 #define MAX_SLAVES   4
00636 
00637 /* States for sending MWI message
00638  * First three states are required for send Ring Pulse Alert Signal
00639  */
00640 typedef enum {
00641    MWI_SEND_NULL = 0,
00642    MWI_SEND_SA,
00643    MWI_SEND_SA_WAIT,
00644    MWI_SEND_PAUSE,
00645    MWI_SEND_SPILL,
00646    MWI_SEND_CLEANUP,
00647    MWI_SEND_DONE,
00648 } mwisend_states;
00649 
00650 struct mwisend_info {
00651    struct   timeval  pause;
00652    mwisend_states    mwisend_current;
00653 };
00654 
00655 /*! Specify the lists dahdi_pvt can be put in. */
00656 enum DAHDI_IFLIST {
00657    DAHDI_IFLIST_NONE,   /*!< The dahdi_pvt is not in any list. */
00658    DAHDI_IFLIST_MAIN,   /*!< The dahdi_pvt is in the main interface list */
00659 #if defined(HAVE_PRI)
00660    DAHDI_IFLIST_NO_B_CHAN, /*!< The dahdi_pvt is in a no B channel interface list */
00661 #endif   /* defined(HAVE_PRI) */
00662 };
00663 
00664 struct dahdi_pvt {
00665    ast_mutex_t lock;             /*!< Channel private lock. */
00666    struct callerid_state *cs;
00667    struct ast_channel *owner;       /*!< Our current active owner (if applicable) */
00668                      /*!< Up to three channels can be associated with this call */
00669 
00670    struct dahdi_subchannel sub_unused;    /*!< Just a safety precaution */
00671    struct dahdi_subchannel subs[3];       /*!< Sub-channels */
00672    struct dahdi_confinfo saveconf;        /*!< Saved conference info */
00673 
00674    struct dahdi_pvt *slaves[MAX_SLAVES];     /*!< Slave to us (follows our conferencing) */
00675    struct dahdi_pvt *master;           /*!< Master to us (we follow their conferencing) */
00676    int inconference;          /*!< If our real should be in the conference */
00677 
00678    int bufsize;                /*!< Size of the buffers */
00679    int buf_no;             /*!< Number of buffers */
00680    int buf_policy;            /*!< Buffer policy */
00681    int faxbuf_no;              /*!< Number of Fax buffers */
00682    int faxbuf_policy;          /*!< Fax buffer policy */
00683    int sig;             /*!< Signalling style */
00684    /*!
00685     * \brief Nonzero if the signaling type is sent over a radio.
00686     * \note Set to a couple of nonzero values but it is only tested like a boolean.
00687     */
00688    int radio;
00689    int outsigmod;             /*!< Outbound Signalling style (modifier) */
00690    int oprmode;               /*!< "Operator Services" mode */
00691    struct dahdi_pvt *oprpeer;          /*!< "Operator Services" peer tech_pvt ptr */
00692    /*! \brief Amount of gain to increase during caller id */
00693    float cid_rxgain;
00694    /*! \brief Rx gain set by chan_dahdi.conf */
00695    float rxgain;
00696    /*! \brief Tx gain set by chan_dahdi.conf */
00697    float txgain;
00698 
00699    float txdrc; /*!< Dynamic Range Compression factor. a number between 1 and 6ish */
00700    float rxdrc;
00701    
00702    int tonezone;              /*!< tone zone for this chan, or -1 for default */
00703    enum DAHDI_IFLIST which_iflist;  /*!< Which interface list is this structure listed? */
00704    struct dahdi_pvt *next;          /*!< Next channel in list */
00705    struct dahdi_pvt *prev;          /*!< Prev channel in list */
00706 
00707    /* flags */
00708 
00709    /*!
00710     * \brief TRUE if ADSI (Analog Display Services Interface) available
00711     * \note Set from the "adsi" value read in from chan_dahdi.conf
00712     */
00713    unsigned int adsi:1;
00714    /*!
00715     * \brief TRUE if we can use a polarity reversal to mark when an outgoing
00716     * call is answered by the remote party.
00717     * \note Set from the "answeronpolarityswitch" value read in from chan_dahdi.conf
00718     */
00719    unsigned int answeronpolarityswitch:1;
00720    /*!
00721     * \brief TRUE if busy detection is enabled.
00722     * (Listens for the beep-beep busy pattern.)
00723     * \note Set from the "busydetect" value read in from chan_dahdi.conf
00724     */
00725    unsigned int busydetect:1;
00726    /*!
00727     * \brief TRUE if call return is enabled.
00728     * (*69, if your dialplan doesn't catch this first)
00729     * \note Set from the "callreturn" value read in from chan_dahdi.conf
00730     */
00731    unsigned int callreturn:1;
00732    /*!
00733     * \brief TRUE if busy extensions will hear the call-waiting tone
00734     * and can use hook-flash to switch between callers.
00735     * \note Can be disabled by dialing *70.
00736     * \note Initialized with the "callwaiting" value read in from chan_dahdi.conf
00737     */
00738    unsigned int callwaiting:1;
00739    /*!
00740     * \brief TRUE if send caller ID for Call Waiting
00741     * \note Set from the "callwaitingcallerid" value read in from chan_dahdi.conf
00742     */
00743    unsigned int callwaitingcallerid:1;
00744    /*!
00745     * \brief TRUE if support for call forwarding enabled.
00746     * Dial *72 to enable call forwarding.
00747     * Dial *73 to disable call forwarding.
00748     * \note Set from the "cancallforward" value read in from chan_dahdi.conf
00749     */
00750    unsigned int cancallforward:1;
00751    /*!
00752     * \brief TRUE if support for call parking is enabled.
00753     * \note Set from the "canpark" value read in from chan_dahdi.conf
00754     */
00755    unsigned int canpark:1;
00756    /*! \brief TRUE if to wait for a DTMF digit to confirm answer */
00757    unsigned int confirmanswer:1;
00758    /*!
00759     * \brief TRUE if the channel is to be destroyed on hangup.
00760     * (Used by pseudo channels.)
00761     */
00762    unsigned int destroy:1;
00763    unsigned int didtdd:1;           /*!< flag to say its done it once */
00764    /*! \brief TRUE if analog type line dialed no digits in Dial() */
00765    unsigned int dialednone:1;
00766    /*!
00767     * \brief TRUE if in the process of dialing digits or sending something.
00768     * \note This is used as a receive squelch for ISDN until connected.
00769     */
00770    unsigned int dialing:1;
00771    /*! \brief TRUE if the transfer capability of the call is digital. */
00772    unsigned int digital:1;
00773    /*! \brief TRUE if Do-Not-Disturb is enabled, present only for non sig_analog */
00774    unsigned int dnd:1;
00775    /*! \brief XXX BOOLEAN Purpose??? */
00776    unsigned int echobreak:1;
00777    /*!
00778     * \brief TRUE if echo cancellation enabled when bridged.
00779     * \note Initialized with the "echocancelwhenbridged" value read in from chan_dahdi.conf
00780     * \note Disabled if the echo canceller is not setup.
00781     */
00782    unsigned int echocanbridged:1;
00783    /*! \brief TRUE if echo cancellation is turned on. */
00784    unsigned int echocanon:1;
00785    /*! \brief TRUE if a fax tone has already been handled. */
00786    unsigned int faxhandled:1;
00787    /*! TRUE if dynamic faxbuffers are configured for use, default is OFF */
00788    unsigned int usefaxbuffers:1;
00789    /*! TRUE while buffer configuration override is in use */
00790    unsigned int bufferoverrideinuse:1;
00791    /*! \brief TRUE if over a radio and dahdi_read() has been called. */
00792    unsigned int firstradio:1;
00793    /*!
00794     * \brief TRUE if the call will be considered "hung up" on a polarity reversal.
00795     * \note Set from the "hanguponpolarityswitch" value read in from chan_dahdi.conf
00796     */
00797    unsigned int hanguponpolarityswitch:1;
00798    /*! \brief TRUE if DTMF detection needs to be done by hardware. */
00799    unsigned int hardwaredtmf:1;
00800    /*!
00801     * \brief TRUE if the outgoing caller ID is blocked/hidden.
00802     * \note Caller ID can be disabled by dialing *67.
00803     * \note Caller ID can be enabled by dialing *82.
00804     * \note Initialized with the "hidecallerid" value read in from chan_dahdi.conf
00805     */
00806    unsigned int hidecallerid:1;
00807    /*!
00808     * \brief TRUE if hide just the name not the number for legacy PBX use.
00809     * \note Only applies to PRI channels.
00810     * \note Set from the "hidecalleridname" value read in from chan_dahdi.conf
00811     */
00812    unsigned int hidecalleridname:1;
00813    /*! \brief TRUE if DTMF detection is disabled. */
00814    unsigned int ignoredtmf:1;
00815    /*!
00816     * \brief TRUE if the channel should be answered immediately
00817     * without attempting to gather any digits.
00818     * \note Set from the "immediate" value read in from chan_dahdi.conf
00819     */
00820    unsigned int immediate:1;
00821    /*! \brief TRUE if in an alarm condition. */
00822    unsigned int inalarm:1;
00823    /*! \brief TRUE if TDD in MATE mode */
00824    unsigned int mate:1;
00825    /*! \brief TRUE if we originated the call leg. */
00826    unsigned int outgoing:1;
00827    /* unsigned int overlapdial:1;         unused and potentially confusing */
00828    /*!
00829     * \brief TRUE if busy extensions will hear the call-waiting tone
00830     * and can use hook-flash to switch between callers.
00831     * \note Set from the "callwaiting" value read in from chan_dahdi.conf
00832     */
00833    unsigned int permcallwaiting:1;
00834    /*!
00835     * \brief TRUE if the outgoing caller ID is blocked/restricted/hidden.
00836     * \note Set from the "hidecallerid" value read in from chan_dahdi.conf
00837     */
00838    unsigned int permhidecallerid:1;
00839    /*!
00840     * \brief TRUE if PRI congestion/busy indications are sent out-of-band.
00841     * \note Set from the "priindication" value read in from chan_dahdi.conf
00842     */
00843    unsigned int priindication_oob:1;
00844    /*!
00845     * \brief TRUE if PRI B channels are always exclusively selected.
00846     * \note Set from the "priexclusive" value read in from chan_dahdi.conf
00847     */
00848    unsigned int priexclusive:1;
00849    /*!
00850     * \brief TRUE if we will pulse dial.
00851     * \note Set from the "pulsedial" value read in from chan_dahdi.conf
00852     */
00853    unsigned int pulse:1;
00854    /*! \brief TRUE if a pulsed digit was detected. (Pulse dial phone detected) */
00855    unsigned int pulsedial:1;
00856    unsigned int restartpending:1;      /*!< flag to ensure counted only once for restart */
00857    /*!
00858     * \brief TRUE if caller ID is restricted.
00859     * \note Set but not used.  Should be deleted.  Redundant with permhidecallerid.
00860     * \note Set from the "restrictcid" value read in from chan_dahdi.conf
00861     */
00862    unsigned int restrictcid:1;
00863    /*!
00864     * \brief TRUE if three way calling is enabled
00865     * \note Set from the "threewaycalling" value read in from chan_dahdi.conf
00866     */
00867    unsigned int threewaycalling:1;
00868    /*!
00869     * \brief TRUE if call transfer is enabled
00870     * \note For FXS ports (either direct analog or over T1/E1):
00871     *   Support flash-hook call transfer
00872     * \note For digital ports using ISDN PRI protocols:
00873     *   Support switch-side transfer (called 2BCT, RLT or other names)
00874     * \note Set from the "transfer" value read in from chan_dahdi.conf
00875     */
00876    unsigned int transfer:1;
00877    /*!
00878     * \brief TRUE if caller ID is used on this channel.
00879     * \note PRI and SS7 spans will save caller ID from the networking peer.
00880     * \note FXS ports will generate the caller ID spill.
00881     * \note FXO ports will listen for the caller ID spill.
00882     * \note Set from the "usecallerid" value read in from chan_dahdi.conf
00883     */
00884    unsigned int use_callerid:1;
00885    /*!
00886     * \brief TRUE if we will use the calling presentation setting
00887     * from the Asterisk channel for outgoing calls.
00888     * \note Only applies to PRI and SS7 channels.
00889     * \note Set from the "usecallingpres" value read in from chan_dahdi.conf
00890     */
00891    unsigned int use_callingpres:1;
00892    /*!
00893     * \brief TRUE if distinctive rings are to be detected.
00894     * \note For FXO lines
00895     * \note Set indirectly from the "usedistinctiveringdetection" value read in from chan_dahdi.conf
00896     */
00897    unsigned int usedistinctiveringdetection:1;
00898    /*!
00899     * \brief TRUE if we should use the callerid from incoming call on dahdi transfer.
00900     * \note Set from the "useincomingcalleridondahditransfer" value read in from chan_dahdi.conf
00901     */
00902    unsigned int dahditrcallerid:1;
00903    /*!
00904     * \brief TRUE if allowed to flash-transfer to busy channels.
00905     * \note Set from the "transfertobusy" value read in from chan_dahdi.conf
00906     */
00907    unsigned int transfertobusy:1;
00908    /*!
00909     * \brief TRUE if the FXO port monitors for neon type MWI indications from the other end.
00910     * \note Set if the "mwimonitor" value read in contains "neon" from chan_dahdi.conf
00911     */
00912    unsigned int mwimonitor_neon:1;
00913    /*!
00914     * \brief TRUE if the FXO port monitors for fsk type MWI indications from the other end.
00915     * \note Set if the "mwimonitor" value read in contains "fsk" from chan_dahdi.conf
00916     */
00917    unsigned int mwimonitor_fsk:1;
00918    /*!
00919     * \brief TRUE if the FXO port monitors for rpas precursor to fsk MWI indications from the other end.
00920     * \note RPAS - Ring Pulse Alert Signal
00921     * \note Set if the "mwimonitor" value read in contains "rpas" from chan_dahdi.conf
00922     */
00923    unsigned int mwimonitor_rpas:1;
00924    /*! \brief TRUE if an MWI monitor thread is currently active */
00925    unsigned int mwimonitoractive:1;
00926    /*! \brief TRUE if a MWI message sending thread is active */
00927    unsigned int mwisendactive:1;
00928    /*!
00929     * \brief TRUE if channel is out of reset and ready
00930     * \note Set but not used.
00931     */
00932    unsigned int inservice:1;
00933    /*!
00934     * \brief TRUE if the channel is locally blocked.
00935     * \note Applies to SS7 and MFCR2 channels.
00936     */
00937    unsigned int locallyblocked:1;
00938    /*!
00939     * \brief TRUE if the channel is remotely blocked.
00940     * \note Applies to SS7 and MFCR2 channels.
00941     */
00942    unsigned int remotelyblocked:1;
00943    /*!
00944     * \brief TRUE if the channel alarms will be managed also as Span ones
00945     * \note Applies to all channels
00946     */
00947    unsigned int manages_span_alarms:1;
00948 
00949 #if defined(HAVE_PRI)
00950    struct sig_pri_span *pri;
00951    int logicalspan;
00952 #endif
00953    /*!
00954     * \brief TRUE if SMDI (Simplified Message Desk Interface) is enabled
00955     * \note Set from the "usesmdi" value read in from chan_dahdi.conf
00956     */
00957    unsigned int use_smdi:1;
00958    struct mwisend_info mwisend_data;
00959    /*! \brief The SMDI interface to get SMDI messages from. */
00960    struct ast_smdi_interface *smdi_iface;
00961 
00962    /*! \brief Distinctive Ring data */
00963    struct dahdi_distRings drings;
00964 
00965    /*!
00966     * \brief The configured context for incoming calls.
00967     * \note The "context" string read in from chan_dahdi.conf
00968     */
00969    char context[AST_MAX_CONTEXT];
00970    /*!
00971     * \brief Saved context string.
00972     */
00973    char defcontext[AST_MAX_CONTEXT];
00974    /*! \brief Extension to use in the dialplan. */
00975    char exten[AST_MAX_EXTENSION];
00976    /*!
00977     * \brief Language configured for calls.
00978     * \note The "language" string read in from chan_dahdi.conf
00979     */
00980    char language[MAX_LANGUAGE];
00981    /*!
00982     * \brief The configured music-on-hold class to use for calls.
00983     * \note The "musicclass" or "mohinterpret" or "musiconhold" string read in from chan_dahdi.conf
00984     */
00985    char mohinterpret[MAX_MUSICCLASS];
00986    /*!
00987     * \brief Suggested music-on-hold class for peer channel to use for calls.
00988     * \note The "mohsuggest" string read in from chan_dahdi.conf
00989     */
00990    char mohsuggest[MAX_MUSICCLASS];
00991    char parkinglot[AST_MAX_EXTENSION]; /*!< Parking lot for this channel */
00992 #if defined(HAVE_PRI) || defined(HAVE_SS7)
00993    /*! \brief Automatic Number Identification number (Alternate PRI caller ID number) */
00994    char cid_ani[AST_MAX_EXTENSION];
00995 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
00996    /*! \brief Automatic Number Identification code from PRI */
00997    int cid_ani2;
00998    /*! \brief Caller ID number from an incoming call. */
00999    char cid_num[AST_MAX_EXTENSION];
01000    /*!
01001     * \brief Caller ID tag from incoming call
01002     * \note the "cid_tag" string read in from chan_dahdi.conf
01003     */
01004    char cid_tag[AST_MAX_EXTENSION];
01005    /*! \brief Caller ID Q.931 TON/NPI field values.  Set by PRI. Zero otherwise. */
01006    int cid_ton;
01007    /*! \brief Caller ID name from an incoming call. */
01008    char cid_name[AST_MAX_EXTENSION];
01009    /*! \brief Caller ID subaddress from an incoming call. */
01010    char cid_subaddr[AST_MAX_EXTENSION];
01011    char *origcid_num;            /*!< malloced original callerid */
01012    char *origcid_name;           /*!< malloced original callerid */
01013    /*! \brief Call waiting number. */
01014    char callwait_num[AST_MAX_EXTENSION];
01015    /*! \brief Call waiting name. */
01016    char callwait_name[AST_MAX_EXTENSION];
01017    /*! \brief Redirecting Directory Number Information Service (RDNIS) number */
01018    char rdnis[AST_MAX_EXTENSION];
01019    /*! \brief Dialed Number Identifier */
01020    char dnid[AST_MAX_EXTENSION];
01021    /*!
01022     * \brief Bitmapped groups this belongs to.
01023     * \note The "group" bitmapped group string read in from chan_dahdi.conf
01024     */
01025    ast_group_t group;
01026    /*! \brief Default call PCM encoding format: DAHDI_LAW_ALAW or DAHDI_LAW_MULAW. */
01027    int law_default;
01028    /*! \brief Active PCM encoding format: DAHDI_LAW_ALAW or DAHDI_LAW_MULAW */
01029    int law;
01030    int confno;             /*!< Our conference */
01031    int confusers;             /*!< Who is using our conference */
01032    int propconfno;               /*!< Propagated conference number */
01033    /*!
01034     * \brief Bitmapped call groups this belongs to.
01035     * \note The "callgroup" bitmapped group string read in from chan_dahdi.conf
01036     */
01037    ast_group_t callgroup;
01038    /*!
01039     * \brief Bitmapped pickup groups this belongs to.
01040     * \note The "pickupgroup" bitmapped group string read in from chan_dahdi.conf
01041     */
01042    ast_group_t pickupgroup;
01043    /*!
01044     * \brief Channel variable list with associated values to set when a channel is created.
01045     * \note The "setvar" strings read in from chan_dahdi.conf
01046     */
01047    struct ast_variable *vars;
01048    int channel;               /*!< Channel Number */
01049    int span;               /*!< Span number */
01050    time_t guardtime;          /*!< Must wait this much time before using for new call */
01051    int cid_signalling;           /*!< CID signalling type bell202 or v23 */
01052    int cid_start;             /*!< CID start indicator, polarity or ring or DTMF without warning event */
01053    int dtmfcid_holdoff_state;    /*!< State indicator that allows for line to settle before checking for dtmf energy */
01054    struct timeval dtmfcid_delay;  /*!< Time value used for allow line to settle */
01055    int callingpres;           /*!< The value of calling presentation that we're going to use when placing a PRI call */
01056    int callwaitingrepeat;           /*!< How many samples to wait before repeating call waiting */
01057    int cidcwexpire;           /*!< When to stop waiting for CID/CW CAS response (In samples) */
01058    int cid_suppress_expire;      /*!< How many samples to suppress after a CID spill. */
01059    /*! \brief Analog caller ID waveform sample buffer */
01060    unsigned char *cidspill;
01061    /*! \brief Position in the cidspill buffer to send out next. */
01062    int cidpos;
01063    /*! \brief Length of the cidspill buffer containing samples. */
01064    int cidlen;
01065    /*! \brief Ring timeout timer?? */
01066    int ringt;
01067    /*!
01068     * \brief Ring timeout base.
01069     * \note Value computed indirectly from "ringtimeout" read in from chan_dahdi.conf
01070     */
01071    int ringt_base;
01072    /*!
01073     * \brief Number of most significant digits/characters to strip from the dialed number.
01074     * \note Feature is deprecated.  Use dialplan logic.
01075     * \note The characters are stripped before the PRI TON/NPI prefix
01076     * characters are processed.
01077     */
01078    int stripmsd;
01079    /*!
01080     * \brief TRUE if Call Waiting (CW) CPE Alert Signal (CAS) is being sent.
01081     * \note
01082     * After CAS is sent, the call waiting caller id will be sent if the phone
01083     * gives a positive reply.
01084     */
01085    int callwaitcas;
01086    /*! \brief Number of call waiting rings. */
01087    int callwaitrings;
01088    /*! \brief Echo cancel parameters. */
01089    struct {
01090       struct dahdi_echocanparams head;
01091       struct dahdi_echocanparam params[DAHDI_MAX_ECHOCANPARAMS];
01092    } echocancel;
01093    /*!
01094     * \brief Echo training time. 0 = disabled
01095     * \note Set from the "echotraining" value read in from chan_dahdi.conf
01096     */
01097    int echotraining;
01098    /*! \brief Filled with 'w'.  XXX Purpose?? */
01099    char echorest[20];
01100    /*!
01101     * \brief Number of times to see "busy" tone before hanging up.
01102     * \note Set from the "busycount" value read in from chan_dahdi.conf
01103     */
01104    int busycount;
01105    /*!
01106     * \brief Length of "busy" tone on time.
01107     * \note Set from the "busypattern" value read in from chan_dahdi.conf
01108     */
01109    int busy_tonelength;
01110    /*!
01111     * \brief Length of "busy" tone off time.
01112     * \note Set from the "busypattern" value read in from chan_dahdi.conf
01113     */
01114    int busy_quietlength;
01115    /*!
01116     * \brief Bitmapped call progress detection flags. CALLPROGRESS_xxx values.
01117     * \note Bits set from the "callprogress" and "faxdetect" values read in from chan_dahdi.conf
01118     */
01119    int callprogress;
01120    /*!
01121     * \brief Number of milliseconds to wait for dialtone.
01122     * \note Set from the "waitfordialtone" value read in from chan_dahdi.conf
01123     */
01124    int waitfordialtone;
01125    struct timeval waitingfordt;        /*!< Time we started waiting for dialtone */
01126    struct timeval flashtime;        /*!< Last flash-hook time */
01127    /*! \brief Opaque DSP configuration structure. */
01128    struct ast_dsp *dsp;
01129    /*! \brief DAHDI dial operation command struct for ioctl() call. */
01130    struct dahdi_dialoperation dop;
01131    int whichwink;             /*!< SIG_FEATDMF_TA Which wink are we on? */
01132    /*! \brief Second part of SIG_FEATDMF_TA wink operation. */
01133    char finaldial[64];
01134    char accountcode[AST_MAX_ACCOUNT_CODE];      /*!< Account code */
01135    int amaflags;              /*!< AMA Flags */
01136    struct tdd_state *tdd;           /*!< TDD flag */
01137    /*! \brief Accumulated call forwarding number. */
01138    char call_forward[AST_MAX_EXTENSION];
01139    /*!
01140     * \brief Voice mailbox location.
01141     * \note Set from the "mailbox" string read in from chan_dahdi.conf
01142     */
01143    char mailbox[AST_MAX_EXTENSION];
01144    /*! \brief Opaque event subscription parameters for message waiting indication support. */
01145    struct ast_event_sub *mwi_event_sub;
01146    /*! \brief Delayed dialing for E911.  Overlap digits for ISDN. */
01147    char dialdest[256];
01148 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
01149    struct dahdi_vmwi_info mwisend_setting;            /*!< Which VMWI methods to use */
01150    unsigned int mwisend_fsk: 1;     /*! Variable for enabling FSK MWI handling in chan_dahdi */
01151    unsigned int mwisend_rpas:1;     /*! Variable for enabling Ring Pulse Alert before MWI FSK Spill */
01152 #endif
01153    int distinctivering;          /*!< Which distinctivering to use */
01154    int dtmfrelax;             /*!< whether to run in relaxed DTMF mode */
01155    /*! \brief Holding place for event injected from outside normal operation. */
01156    int fake_event;
01157    /*!
01158     * \brief Minimal time period (ms) between the answer polarity
01159     * switch and hangup polarity switch.
01160     */
01161    int polarityonanswerdelay;
01162    /*! \brief Start delay time if polarityonanswerdelay is nonzero. */
01163    struct timeval polaritydelaytv;
01164    /*!
01165     * \brief Send caller ID on FXS after this many rings. Set to 1 for US.
01166     * \note Set from the "sendcalleridafter" value read in from chan_dahdi.conf
01167     */
01168    int sendcalleridafter;
01169    /*! \brief Current line interface polarity. POLARITY_IDLE, POLARITY_REV */
01170    int polarity;
01171    /*! \brief DSP feature flags: DSP_FEATURE_xxx */
01172    int dsp_features;
01173 #if defined(HAVE_SS7)
01174    /*! \brief SS7 control parameters */
01175    struct sig_ss7_linkset *ss7;
01176 #endif   /* defined(HAVE_SS7) */
01177 #ifdef HAVE_OPENR2
01178    struct dahdi_mfcr2 *mfcr2;
01179    openr2_chan_t *r2chan;
01180    openr2_calling_party_category_t mfcr2_recvd_category;
01181    openr2_calling_party_category_t mfcr2_category;
01182    int mfcr2_dnis_index;
01183    int mfcr2_ani_index;
01184    int mfcr2call:1;
01185    int mfcr2_answer_pending:1;
01186    int mfcr2_charge_calls:1;
01187    int mfcr2_allow_collect_calls:1;
01188    int mfcr2_forced_release:1;
01189    int mfcr2_dnis_matched:1;
01190    int mfcr2_call_accepted:1;
01191    int mfcr2_progress:1;
01192    int mfcr2_accept_on_offer:1;
01193 #endif
01194    /*! \brief DTMF digit in progress.  0 when no digit in progress. */
01195    char begindigit;
01196    /*! \brief TRUE if confrence is muted. */
01197    int muting;
01198    void *sig_pvt;
01199    struct ast_cc_config_params *cc_params;
01200    /* DAHDI channel names may differ greatly from the
01201     * string that was provided to an app such as Dial. We
01202     * need to save the original string passed to dahdi_request
01203     * for call completion purposes. This way, we can replicate
01204     * the original dialed string later.
01205     */
01206    char dialstring[AST_CHANNEL_NAME];
01207 };
01208 
01209 #define DATA_EXPORT_DAHDI_PVT(MEMBER)              \
01210    MEMBER(dahdi_pvt, cid_rxgain, AST_DATA_DOUBLE)        \
01211    MEMBER(dahdi_pvt, rxgain, AST_DATA_DOUBLE)         \
01212    MEMBER(dahdi_pvt, txgain, AST_DATA_DOUBLE)         \
01213    MEMBER(dahdi_pvt, txdrc, AST_DATA_DOUBLE)       \
01214    MEMBER(dahdi_pvt, rxdrc, AST_DATA_DOUBLE)       \
01215    MEMBER(dahdi_pvt, adsi, AST_DATA_BOOLEAN)       \
01216    MEMBER(dahdi_pvt, answeronpolarityswitch, AST_DATA_BOOLEAN) \
01217    MEMBER(dahdi_pvt, busydetect, AST_DATA_BOOLEAN)       \
01218    MEMBER(dahdi_pvt, callreturn, AST_DATA_BOOLEAN)       \
01219    MEMBER(dahdi_pvt, callwaiting, AST_DATA_BOOLEAN)      \
01220    MEMBER(dahdi_pvt, callwaitingcallerid, AST_DATA_BOOLEAN) \
01221    MEMBER(dahdi_pvt, cancallforward, AST_DATA_BOOLEAN)      \
01222    MEMBER(dahdi_pvt, canpark, AST_DATA_BOOLEAN)       \
01223    MEMBER(dahdi_pvt, confirmanswer, AST_DATA_BOOLEAN)    \
01224    MEMBER(dahdi_pvt, destroy, AST_DATA_BOOLEAN)       \
01225    MEMBER(dahdi_pvt, didtdd, AST_DATA_BOOLEAN)        \
01226    MEMBER(dahdi_pvt, dialednone, AST_DATA_BOOLEAN)       \
01227    MEMBER(dahdi_pvt, dialing, AST_DATA_BOOLEAN)       \
01228    MEMBER(dahdi_pvt, digital, AST_DATA_BOOLEAN)       \
01229    MEMBER(dahdi_pvt, dnd, AST_DATA_BOOLEAN)        \
01230    MEMBER(dahdi_pvt, echobreak, AST_DATA_BOOLEAN)        \
01231    MEMBER(dahdi_pvt, echocanbridged, AST_DATA_BOOLEAN)      \
01232    MEMBER(dahdi_pvt, echocanon, AST_DATA_BOOLEAN)        \
01233    MEMBER(dahdi_pvt, faxhandled, AST_DATA_BOOLEAN)       \
01234    MEMBER(dahdi_pvt, usefaxbuffers, AST_DATA_BOOLEAN)    \
01235    MEMBER(dahdi_pvt, bufferoverrideinuse, AST_DATA_BOOLEAN) \
01236    MEMBER(dahdi_pvt, firstradio, AST_DATA_BOOLEAN)       \
01237    MEMBER(dahdi_pvt, hanguponpolarityswitch, AST_DATA_BOOLEAN) \
01238    MEMBER(dahdi_pvt, hardwaredtmf, AST_DATA_BOOLEAN)     \
01239    MEMBER(dahdi_pvt, hidecallerid, AST_DATA_BOOLEAN)     \
01240    MEMBER(dahdi_pvt, hidecalleridname, AST_DATA_BOOLEAN)    \
01241    MEMBER(dahdi_pvt, ignoredtmf, AST_DATA_BOOLEAN)       \
01242    MEMBER(dahdi_pvt, immediate, AST_DATA_BOOLEAN)        \
01243    MEMBER(dahdi_pvt, inalarm, AST_DATA_BOOLEAN)       \
01244    MEMBER(dahdi_pvt, mate, AST_DATA_BOOLEAN)       \
01245    MEMBER(dahdi_pvt, outgoing, AST_DATA_BOOLEAN)         \
01246    MEMBER(dahdi_pvt, permcallwaiting, AST_DATA_BOOLEAN)     \
01247    MEMBER(dahdi_pvt, priindication_oob, AST_DATA_BOOLEAN)      \
01248    MEMBER(dahdi_pvt, priexclusive, AST_DATA_BOOLEAN)     \
01249    MEMBER(dahdi_pvt, pulse, AST_DATA_BOOLEAN)         \
01250    MEMBER(dahdi_pvt, pulsedial, AST_DATA_BOOLEAN)        \
01251    MEMBER(dahdi_pvt, restartpending, AST_DATA_BOOLEAN)      \
01252    MEMBER(dahdi_pvt, restrictcid, AST_DATA_BOOLEAN)      \
01253    MEMBER(dahdi_pvt, threewaycalling, AST_DATA_BOOLEAN)     \
01254    MEMBER(dahdi_pvt, transfer, AST_DATA_BOOLEAN)         \
01255    MEMBER(dahdi_pvt, use_callerid, AST_DATA_BOOLEAN)     \
01256    MEMBER(dahdi_pvt, use_callingpres, AST_DATA_BOOLEAN)     \
01257    MEMBER(dahdi_pvt, usedistinctiveringdetection, AST_DATA_BOOLEAN)  \
01258    MEMBER(dahdi_pvt, dahditrcallerid, AST_DATA_BOOLEAN)        \
01259    MEMBER(dahdi_pvt, transfertobusy, AST_DATA_BOOLEAN)         \
01260    MEMBER(dahdi_pvt, mwimonitor_neon, AST_DATA_BOOLEAN)        \
01261    MEMBER(dahdi_pvt, mwimonitor_fsk, AST_DATA_BOOLEAN)         \
01262    MEMBER(dahdi_pvt, mwimonitor_rpas, AST_DATA_BOOLEAN)        \
01263    MEMBER(dahdi_pvt, mwimonitoractive, AST_DATA_BOOLEAN)       \
01264    MEMBER(dahdi_pvt, mwisendactive, AST_DATA_BOOLEAN)       \
01265    MEMBER(dahdi_pvt, inservice, AST_DATA_BOOLEAN)           \
01266    MEMBER(dahdi_pvt, locallyblocked, AST_DATA_BOOLEAN)         \
01267    MEMBER(dahdi_pvt, remotelyblocked, AST_DATA_BOOLEAN)        \
01268    MEMBER(dahdi_pvt, manages_span_alarms, AST_DATA_BOOLEAN)    \
01269    MEMBER(dahdi_pvt, use_smdi, AST_DATA_BOOLEAN)            \
01270    MEMBER(dahdi_pvt, context, AST_DATA_STRING)           \
01271    MEMBER(dahdi_pvt, defcontext, AST_DATA_STRING)           \
01272    MEMBER(dahdi_pvt, exten, AST_DATA_STRING)          \
01273    MEMBER(dahdi_pvt, language, AST_DATA_STRING)          \
01274    MEMBER(dahdi_pvt, mohinterpret, AST_DATA_STRING)         \
01275    MEMBER(dahdi_pvt, mohsuggest, AST_DATA_STRING)           \
01276    MEMBER(dahdi_pvt, parkinglot, AST_DATA_STRING)
01277 
01278 AST_DATA_STRUCTURE(dahdi_pvt, DATA_EXPORT_DAHDI_PVT);
01279 
01280 static struct dahdi_pvt *iflist = NULL;   /*!< Main interface list start */
01281 static struct dahdi_pvt *ifend = NULL; /*!< Main interface list end */
01282 
01283 #if defined(HAVE_PRI)
01284 static struct dahdi_parms_pseudo {
01285    int buf_no;             /*!< Number of buffers */
01286    int buf_policy;            /*!< Buffer policy */
01287    int faxbuf_no;              /*!< Number of Fax buffers */
01288    int faxbuf_policy;          /*!< Fax buffer policy */
01289 } dahdi_pseudo_parms;
01290 #endif   /* defined(HAVE_PRI) */
01291 
01292 /*! \brief Channel configuration from chan_dahdi.conf .
01293  * This struct is used for parsing the [channels] section of chan_dahdi.conf.
01294  * Generally there is a field here for every possible configuration item.
01295  *
01296  * The state of fields is saved along the parsing and whenever a 'channel'
01297  * statement is reached, the current dahdi_chan_conf is used to configure the
01298  * channel (struct dahdi_pvt)
01299  *
01300  * \see dahdi_chan_init for the default values.
01301  */
01302 struct dahdi_chan_conf {
01303    struct dahdi_pvt chan;
01304 #ifdef HAVE_PRI
01305    struct dahdi_pri pri;
01306 #endif
01307 
01308 #if defined(HAVE_SS7)
01309    struct dahdi_ss7 ss7;
01310 #endif   /* defined(HAVE_SS7) */
01311 
01312 #ifdef HAVE_OPENR2
01313    struct dahdi_mfcr2_conf mfcr2;
01314 #endif
01315    struct dahdi_params timing;
01316    int is_sig_auto; /*!< Use channel signalling from DAHDI? */
01317    /*! Continue configuration even if a channel is not there. */
01318    int ignore_failed_channels;
01319 
01320    /*!
01321     * \brief The serial port to listen for SMDI data on
01322     * \note Set from the "smdiport" string read in from chan_dahdi.conf
01323     */
01324    char smdi_port[SMDI_MAX_FILENAME_LEN];
01325 };
01326 
01327 /*! returns a new dahdi_chan_conf with default values (by-value) */
01328 static struct dahdi_chan_conf dahdi_chan_conf_default(void)
01329 {
01330    /* recall that if a field is not included here it is initialized
01331     * to 0 or equivalent
01332     */
01333    struct dahdi_chan_conf conf = {
01334 #ifdef HAVE_PRI
01335       .pri.pri = {
01336          .nsf = PRI_NSF_NONE,
01337          .switchtype = PRI_SWITCH_NI2,
01338          .dialplan = PRI_UNKNOWN + 1,
01339          .localdialplan = PRI_NATIONAL_ISDN + 1,
01340          .nodetype = PRI_CPE,
01341          .qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL,
01342 
01343 #if defined(HAVE_PRI_CCSS)
01344          .cc_ptmp_recall_mode = 1,/* specificRecall */
01345          .cc_qsig_signaling_link_req = 1,/* retain */
01346          .cc_qsig_signaling_link_rsp = 1,/* retain */
01347 #endif   /* defined(HAVE_PRI_CCSS) */
01348 
01349          .minunused = 2,
01350          .idleext = "",
01351          .idledial = "",
01352          .internationalprefix = "",
01353          .nationalprefix = "",
01354          .localprefix = "",
01355          .privateprefix = "",
01356          .unknownprefix = "",
01357          .resetinterval = -1,
01358       },
01359 #endif
01360 #if defined(HAVE_SS7)
01361       .ss7.ss7 = {
01362          .called_nai = SS7_NAI_NATIONAL,
01363          .calling_nai = SS7_NAI_NATIONAL,
01364          .internationalprefix = "",
01365          .nationalprefix = "",
01366          .subscriberprefix = "",
01367          .unknownprefix = ""
01368       },
01369 #endif   /* defined(HAVE_SS7) */
01370 #ifdef HAVE_OPENR2
01371       .mfcr2 = {
01372          .variant = OR2_VAR_ITU,
01373          .mfback_timeout = -1,
01374          .metering_pulse_timeout = -1,
01375          .max_ani = 10,
01376          .max_dnis = 4,
01377          .get_ani_first = -1,
01378 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
01379          .skip_category_request = -1,
01380 #endif
01381          .call_files = 0,
01382          .allow_collect_calls = 0,
01383          .charge_calls = 1,
01384          .accept_on_offer = 1,
01385          .forced_release = 0,
01386          .double_answer = 0,
01387          .immediate_accept = -1,
01388          .logdir = "",
01389          .r2proto_file = "",
01390          .loglevel = OR2_LOG_ERROR | OR2_LOG_WARNING,
01391          .category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER
01392       },
01393 #endif
01394       .chan = {
01395          .context = "default",
01396          .cid_num = "",
01397          .cid_name = "",
01398          .cid_tag = "",
01399          .mohinterpret = "default",
01400          .mohsuggest = "",
01401          .parkinglot = "",
01402          .transfertobusy = 1,
01403 
01404          .cid_signalling = CID_SIG_BELL,
01405          .cid_start = CID_START_RING,
01406          .dahditrcallerid = 0,
01407          .use_callerid = 1,
01408          .sig = -1,
01409          .outsigmod = -1,
01410 
01411          .cid_rxgain = +5.0,
01412 
01413          .tonezone = -1,
01414 
01415          .echocancel.head.tap_length = 1,
01416 
01417          .busycount = 3,
01418 
01419          .accountcode = "",
01420 
01421          .mailbox = "",
01422 
01423 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
01424          .mwisend_fsk = 1,
01425 #endif
01426          .polarityonanswerdelay = 600,
01427 
01428          .sendcalleridafter = DEFAULT_CIDRINGS,
01429 
01430          .buf_policy = DAHDI_POLICY_IMMEDIATE,
01431          .buf_no = numbufs,
01432          .usefaxbuffers = 0,
01433          .cc_params = ast_cc_config_params_init(),
01434       },
01435       .timing = {
01436          .prewinktime = -1,
01437          .preflashtime = -1,
01438          .winktime = -1,
01439          .flashtime = -1,
01440          .starttime = -1,
01441          .rxwinktime = -1,
01442          .rxflashtime = -1,
01443          .debouncetime = -1
01444       },
01445       .is_sig_auto = 1,
01446       .smdi_port = "/dev/ttyS0",
01447    };
01448 
01449    return conf;
01450 }
01451 
01452 
01453 static struct ast_channel *dahdi_request(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause);
01454 static int dahdi_digit_begin(struct ast_channel *ast, char digit);
01455 static int dahdi_digit_end(struct ast_channel *ast, char digit, unsigned int duration);
01456 static int dahdi_sendtext(struct ast_channel *c, const char *text);
01457 static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout);
01458 static int dahdi_hangup(struct ast_channel *ast);
01459 static int dahdi_answer(struct ast_channel *ast);
01460 static struct ast_frame *dahdi_read(struct ast_channel *ast);
01461 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame);
01462 static struct ast_frame *dahdi_exception(struct ast_channel *ast);
01463 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen);
01464 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
01465 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen);
01466 static int dahdi_queryoption(struct ast_channel *chan, int option, void *data, int *datalen);
01467 static int dahdi_func_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len);
01468 static int dahdi_func_write(struct ast_channel *chan, const char *function, char *data, const char *value);
01469 static int dahdi_devicestate(void *data);
01470 static int dahdi_cc_callback(struct ast_channel *inbound, const char *dest, ast_cc_callback_fn callback);
01471 
01472 static const struct ast_channel_tech dahdi_tech = {
01473    .type = "DAHDI",
01474    .description = tdesc,
01475    .capabilities = AST_FORMAT_SLINEAR | AST_FORMAT_ULAW | AST_FORMAT_ALAW,
01476    .requester = dahdi_request,
01477    .send_digit_begin = dahdi_digit_begin,
01478    .send_digit_end = dahdi_digit_end,
01479    .send_text = dahdi_sendtext,
01480    .call = dahdi_call,
01481    .hangup = dahdi_hangup,
01482    .answer = dahdi_answer,
01483    .read = dahdi_read,
01484    .write = dahdi_write,
01485    .bridge = dahdi_bridge,
01486    .exception = dahdi_exception,
01487    .indicate = dahdi_indicate,
01488    .fixup = dahdi_fixup,
01489    .setoption = dahdi_setoption,
01490    .queryoption = dahdi_queryoption,
01491    .func_channel_read = dahdi_func_read,
01492    .func_channel_write = dahdi_func_write,
01493    .devicestate = dahdi_devicestate,
01494    .cc_callback = dahdi_cc_callback,
01495 };
01496 
01497 #define GET_CHANNEL(p) ((p)->channel)
01498 
01499 #define SIG_PRI_LIB_HANDLE_CASES \
01500    SIG_PRI:                \
01501    case SIG_BRI:              \
01502    case SIG_BRI_PTMP
01503 
01504 /*!
01505  * \internal
01506  * \brief Determine if sig_pri handles the signaling.
01507  * \since 1.8
01508  *
01509  * \param signaling Signaling to determine if is for sig_pri.
01510  *
01511  * \return TRUE if the signaling is for sig_pri.
01512  */
01513 static inline int dahdi_sig_pri_lib_handles(int signaling)
01514 {
01515    int handles;
01516 
01517    switch (signaling) {
01518    case SIG_PRI_LIB_HANDLE_CASES:
01519       handles = 1;
01520       break;
01521    default:
01522       handles = 0;
01523       break;
01524    }
01525 
01526    return handles;
01527 }
01528 
01529 static enum analog_sigtype dahdisig_to_analogsig(int sig)
01530 {
01531    switch (sig) {
01532    case SIG_FXOLS:
01533       return ANALOG_SIG_FXOLS;
01534    case SIG_FXOGS:
01535       return ANALOG_SIG_FXOGS;
01536    case SIG_FXOKS:
01537       return ANALOG_SIG_FXOKS;
01538    case SIG_FXSLS:
01539       return ANALOG_SIG_FXSLS;
01540    case SIG_FXSGS:
01541       return ANALOG_SIG_FXSGS;
01542    case SIG_FXSKS:
01543       return ANALOG_SIG_FXSKS;
01544    case SIG_EMWINK:
01545       return ANALOG_SIG_EMWINK;
01546    case SIG_EM:
01547       return ANALOG_SIG_EM;
01548    case SIG_EM_E1:
01549       return ANALOG_SIG_EM_E1;
01550    case SIG_FEATD:
01551       return ANALOG_SIG_FEATD;
01552    case SIG_FEATDMF:
01553       return ANALOG_SIG_FEATDMF;
01554    case SIG_E911:
01555       return SIG_E911;
01556    case SIG_FGC_CAMA:
01557       return ANALOG_SIG_FGC_CAMA;
01558    case SIG_FGC_CAMAMF:
01559       return ANALOG_SIG_FGC_CAMAMF;
01560    case SIG_FEATB:
01561       return ANALOG_SIG_FEATB;
01562    case SIG_SFWINK:
01563       return ANALOG_SIG_SFWINK;
01564    case SIG_SF:
01565       return ANALOG_SIG_SF;
01566    case SIG_SF_FEATD:
01567       return ANALOG_SIG_SF_FEATD;
01568    case SIG_SF_FEATDMF:
01569       return ANALOG_SIG_SF_FEATDMF;
01570    case SIG_FEATDMF_TA:
01571       return ANALOG_SIG_FEATDMF_TA;
01572    case SIG_SF_FEATB:
01573       return ANALOG_SIG_FEATB;
01574    default:
01575       return -1;
01576    }
01577 }
01578 
01579 
01580 static int analog_tone_to_dahditone(enum analog_tone tone)
01581 {
01582    switch (tone) {
01583    case ANALOG_TONE_RINGTONE:
01584       return DAHDI_TONE_RINGTONE;
01585    case ANALOG_TONE_STUTTER:
01586       return DAHDI_TONE_STUTTER;
01587    case ANALOG_TONE_CONGESTION:
01588       return DAHDI_TONE_CONGESTION;
01589    case ANALOG_TONE_DIALTONE:
01590       return DAHDI_TONE_DIALTONE;
01591    case ANALOG_TONE_DIALRECALL:
01592       return DAHDI_TONE_DIALRECALL;
01593    case ANALOG_TONE_INFO:
01594       return DAHDI_TONE_INFO;
01595    default:
01596       return -1;
01597    }
01598 }
01599 
01600 static int analogsub_to_dahdisub(enum analog_sub analogsub)
01601 {
01602    int index;
01603 
01604    switch (analogsub) {
01605    case ANALOG_SUB_REAL:
01606       index = SUB_REAL;
01607       break;
01608    case ANALOG_SUB_CALLWAIT:
01609       index = SUB_CALLWAIT;
01610       break;
01611    case ANALOG_SUB_THREEWAY:
01612       index = SUB_THREEWAY;
01613       break;
01614    default:
01615       ast_log(LOG_ERROR, "Unidentified sub!\n");
01616       index = SUB_REAL;
01617    }
01618 
01619    return index;
01620 }
01621 
01622 static enum analog_event dahdievent_to_analogevent(int event);
01623 static int bump_gains(struct dahdi_pvt *p);
01624 static int dahdi_setlinear(int dfd, int linear);
01625 
01626 static int my_start_cid_detect(void *pvt, int cid_signalling)
01627 {
01628    struct dahdi_pvt *p = pvt;
01629    int index = SUB_REAL;
01630    p->cs = callerid_new(cid_signalling);
01631    if (!p->cs) {
01632       ast_log(LOG_ERROR, "Unable to alloc callerid\n");
01633       return -1;
01634    }
01635    bump_gains(p);
01636    dahdi_setlinear(p->subs[index].dfd, 0);
01637 
01638    return 0;
01639 }
01640 
01641 static int my_stop_cid_detect(void *pvt)
01642 {
01643    struct dahdi_pvt *p = pvt;
01644    int index = SUB_REAL;
01645    if (p->cs)
01646       callerid_free(p->cs);
01647    dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
01648    return 0;
01649 }
01650 
01651 static int my_get_callerid(void *pvt, char *namebuf, char *numbuf, enum analog_event *ev, size_t timeout)
01652 {
01653    struct dahdi_pvt *p = pvt;
01654    struct analog_pvt *analog_p = p->sig_pvt;
01655    struct pollfd poller;
01656    char *name, *num;
01657    int index = SUB_REAL;
01658    int res;
01659    unsigned char buf[256];
01660    int flags;
01661 
01662    poller.fd = p->subs[SUB_REAL].dfd;
01663    poller.events = POLLPRI | POLLIN;
01664    poller.revents = 0;
01665 
01666    res = poll(&poller, 1, timeout);
01667 
01668    if (poller.revents & POLLPRI) {
01669       *ev = dahdievent_to_analogevent(dahdi_get_event(p->subs[SUB_REAL].dfd));
01670       return 1;
01671    }
01672 
01673    if (poller.revents & POLLIN) {
01674       /*** NOTES ***/
01675       /* Change API: remove cid_signalling from get_callerid, add a new start_cid_detect and stop_cid_detect function
01676        * to enable slin mode and allocate cid detector. get_callerid should be able to be called any number of times until
01677        * either a timeout occurs or CID is detected (returns 0). returning 1 should be event received, and -1 should be
01678        * a failure and die, and returning 2 means no event was received. */
01679       res = read(p->subs[index].dfd, buf, sizeof(buf));
01680       if (res < 0) {
01681          if (errno != ELAST) {
01682             ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
01683             callerid_free(p->cs);
01684             return -1;
01685          }
01686       }
01687 
01688       if (analog_p->ringt > 0) {
01689          if (!(--analog_p->ringt)) {
01690             /* only return if we timeout from a ring event */
01691             return -1;
01692          }
01693       }
01694 
01695       if (p->cid_signalling == CID_SIG_V23_JP) {
01696          res = callerid_feed_jp(p->cs, buf, res, AST_LAW(p));
01697       } else {
01698          res = callerid_feed(p->cs, buf, res, AST_LAW(p));
01699       }
01700       if (res < 0) {
01701          /*
01702           * The previous diagnostic message output likely
01703           * explains why it failed.
01704           */
01705          ast_log(LOG_WARNING, "Failed to decode CallerID\n");
01706          return -1;
01707       }
01708 
01709       if (res == 1) {
01710          callerid_get(p->cs, &name, &num, &flags);
01711          if (name)
01712             ast_copy_string(namebuf, name, ANALOG_MAX_CID);
01713          if (num)
01714             ast_copy_string(numbuf, num, ANALOG_MAX_CID);
01715 
01716          ast_log(LOG_DEBUG, "CallerID number: %s, name: %s, flags=%d\n", num, name, flags);
01717          return 0;
01718       }
01719    }
01720 
01721    *ev = ANALOG_EVENT_NONE;
01722    return 2;
01723 }
01724 
01725 static const char *event2str(int event);
01726 static int restore_gains(struct dahdi_pvt *p);
01727 
01728 static int my_distinctive_ring(struct ast_channel *chan, void *pvt, int idx, int *ringdata)
01729 {
01730    unsigned char buf[256];
01731    int distMatches;
01732    int curRingData[RING_PATTERNS];
01733    int receivedRingT;
01734    int counter1;
01735    int counter;
01736    int i;
01737    int res;
01738    int checkaftercid = 0;
01739 
01740    struct dahdi_pvt *p = pvt;
01741    struct analog_pvt *analog_p = p->sig_pvt;
01742 
01743    if (ringdata == NULL) {
01744       ringdata = curRingData;
01745    } else {
01746       checkaftercid = 1;
01747    }
01748 
01749    /* We must have a ring by now, so, if configured, lets try to listen for
01750     * distinctive ringing */
01751    if ((checkaftercid && distinctiveringaftercid) || !checkaftercid) {
01752       /* Clear the current ring data array so we don't have old data in it. */
01753       for (receivedRingT = 0; receivedRingT < RING_PATTERNS; receivedRingT++)
01754          ringdata[receivedRingT] = 0;
01755       receivedRingT = 0;
01756       if (checkaftercid && distinctiveringaftercid)
01757          ast_verb(3, "Detecting post-CID distinctive ring\n");
01758       /* Check to see if context is what it should be, if not set to be. */
01759       else if (strcmp(p->context,p->defcontext) != 0) {
01760          ast_copy_string(p->context, p->defcontext, sizeof(p->context));
01761          ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
01762       }
01763 
01764       for (;;) {
01765          i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
01766          if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
01767             ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
01768             ast_hangup(chan);
01769             return 1;
01770          }
01771          if (i & DAHDI_IOMUX_SIGEVENT) {
01772             res = dahdi_get_event(p->subs[idx].dfd);
01773             if (res == DAHDI_EVENT_NOALARM) {
01774                p->inalarm = 0;
01775                analog_p->inalarm = 0;
01776             }
01777             ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
01778             res = 0;
01779             /* Let us detect distinctive ring */
01780 
01781             ringdata[receivedRingT] = analog_p->ringt;
01782 
01783             if (analog_p->ringt < analog_p->ringt_base/2)
01784                break;
01785             /* Increment the ringT counter so we can match it against
01786                values in chan_dahdi.conf for distinctive ring */
01787             if (++receivedRingT == RING_PATTERNS)
01788                break;
01789          } else if (i & DAHDI_IOMUX_READ) {
01790             res = read(p->subs[idx].dfd, buf, sizeof(buf));
01791             if (res < 0) {
01792                if (errno != ELAST) {
01793                   ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
01794                   ast_hangup(chan);
01795                   return 1;
01796                }
01797                break;
01798             }
01799             if (analog_p->ringt > 0) {
01800                if (!(--analog_p->ringt)) {
01801                   res = -1;
01802                   break;
01803                }
01804             }
01805          }
01806       }
01807    }
01808    if ((checkaftercid && usedistinctiveringdetection) || !checkaftercid) {
01809       /* this only shows up if you have n of the dring patterns filled in */
01810       ast_verb(3, "Detected ring pattern: %d,%d,%d\n",ringdata[0],ringdata[1],ringdata[2]);
01811       for (counter = 0; counter < 3; counter++) {
01812       /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this channel */
01813          distMatches = 0;
01814          /* this only shows up if you have n of the dring patterns filled in */
01815          ast_verb(3, "Checking %d,%d,%d\n",
01816                p->drings.ringnum[counter].ring[0],
01817                p->drings.ringnum[counter].ring[1],
01818                p->drings.ringnum[counter].ring[2]);
01819          for (counter1 = 0; counter1 < 3; counter1++) {
01820             ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
01821             if (p->drings.ringnum[counter].ring[counter1] == -1) {
01822                ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
01823                ringdata[counter1]);
01824                distMatches++;
01825             } else if (ringdata[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
01826                               ringdata[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
01827                ast_verb(3, "Ring pattern matched in range: %d to %d\n",
01828                (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
01829                (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
01830                distMatches++;
01831             }
01832          }
01833 
01834          if (distMatches == 3) {
01835             /* The ring matches, set the context to whatever is for distinctive ring.. */
01836             ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context));
01837             ast_copy_string(chan->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(chan->context));
01838             ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
01839             break;
01840          }
01841       }
01842    }
01843    /* Restore linear mode (if appropriate) for Caller*ID processing */
01844    dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
01845    restore_gains(p);
01846 
01847    return 0;
01848 }
01849 
01850 static int my_stop_callwait(void *pvt)
01851 {
01852    struct dahdi_pvt *p = pvt;
01853    p->callwaitingrepeat = 0;
01854    p->cidcwexpire = 0;
01855    p->cid_suppress_expire = 0;
01856 
01857    return 0;
01858 }
01859 
01860 static int send_callerid(struct dahdi_pvt *p);
01861 static int save_conference(struct dahdi_pvt *p);
01862 static int restore_conference(struct dahdi_pvt *p);
01863 
01864 static int my_callwait(void *pvt)
01865 {
01866    struct dahdi_pvt *p = pvt;
01867    p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
01868    if (p->cidspill) {
01869       ast_log(LOG_WARNING, "Spill already exists?!?\n");
01870       ast_free(p->cidspill);
01871    }
01872 
01873    /*
01874     * SAS: Subscriber Alert Signal, 440Hz for 300ms
01875     * CAS: CPE Alert Signal, 2130Hz * 2750Hz sine waves
01876     */
01877    if (!(p->cidspill = ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE * 4)))
01878       return -1;
01879    save_conference(p);
01880    /* Silence */
01881    memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
01882    if (!p->callwaitrings && p->callwaitingcallerid) {
01883       ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
01884       p->callwaitcas = 1;
01885       p->cidlen = 2400 + 680 + READ_SIZE * 4;
01886    } else {
01887       ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
01888       p->callwaitcas = 0;
01889       p->cidlen = 2400 + READ_SIZE * 4;
01890    }
01891    p->cidpos = 0;
01892    send_callerid(p);
01893 
01894    return 0;
01895 }
01896 
01897 static int my_send_callerid(void *pvt, int cwcid, struct ast_party_caller *caller)
01898 {
01899    struct dahdi_pvt *p = pvt;
01900 
01901    ast_debug(2, "Starting cid spill\n");
01902 
01903    if (p->cidspill) {
01904       ast_log(LOG_WARNING, "cidspill already exists??\n");
01905       ast_free(p->cidspill);
01906    }
01907 
01908    if ((p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) {
01909       if (cwcid == 0) {
01910          p->cidlen = ast_callerid_generate(p->cidspill,
01911             caller->id.name.str,
01912             caller->id.number.str,
01913             AST_LAW(p));
01914       } else {
01915          ast_verb(3, "CPE supports Call Waiting Caller*ID.  Sending '%s/%s'\n",
01916             caller->id.name.str, caller->id.number.str);
01917          p->callwaitcas = 0;
01918          p->cidcwexpire = 0;
01919          p->cidlen = ast_callerid_callwaiting_generate(p->cidspill,
01920             caller->id.name.str,
01921             caller->id.number.str,
01922             AST_LAW(p));
01923          p->cidlen += READ_SIZE * 4;
01924       }
01925       p->cidpos = 0;
01926       p->cid_suppress_expire = 0;
01927       send_callerid(p);
01928    }
01929    return 0;
01930 }
01931 
01932 static int my_dsp_reset_and_flush_digits(void *pvt)
01933 {
01934    struct dahdi_pvt *p = pvt;
01935    if (p->dsp)
01936       ast_dsp_digitreset(p->dsp);
01937 
01938    return 0;
01939 }
01940 
01941 static int my_dsp_set_digitmode(void *pvt, enum analog_dsp_digitmode mode)
01942 {
01943    struct dahdi_pvt *p = pvt;
01944 
01945    if (p->channel == CHAN_PSEUDO)
01946       ast_log(LOG_ERROR, "You have assumed incorrectly sir!\n");
01947 
01948    if (mode == ANALOG_DIGITMODE_DTMF) {
01949       /* If we do hardware dtmf, no need for a DSP */
01950       if (p->hardwaredtmf) {
01951          if (p->dsp) {
01952             ast_dsp_free(p->dsp);
01953             p->dsp = NULL;
01954          }
01955          return 0;
01956       }
01957 
01958       if (!p->dsp) {
01959          p->dsp = ast_dsp_new();
01960          if (!p->dsp) {
01961             ast_log(LOG_ERROR, "Unable to allocate DSP\n");
01962             return -1;
01963          }
01964       }
01965 
01966       ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
01967    } else if (mode == ANALOG_DIGITMODE_MF) {
01968       if (!p->dsp) {
01969          p->dsp = ast_dsp_new();
01970          if (!p->dsp) {
01971             ast_log(LOG_ERROR, "Unable to allocate DSP\n");
01972             return -1;
01973          }
01974       }
01975       ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
01976    }
01977    return 0;
01978 }
01979 
01980 static int dahdi_wink(struct dahdi_pvt *p, int index);
01981 
01982 static int my_wink(void *pvt, enum analog_sub sub)
01983 {
01984    struct dahdi_pvt *p = pvt;
01985    int index = analogsub_to_dahdisub(sub);
01986    if (index != SUB_REAL) {
01987       ast_log(LOG_ERROR, "We used a sub other than SUB_REAL (incorrect assumption sir)\n");
01988    }
01989    return dahdi_wink(p, index);
01990 }
01991 
01992 static void wakeup_sub(struct dahdi_pvt *p, int a);
01993 
01994 static int reset_conf(struct dahdi_pvt *p);
01995 
01996 static inline int dahdi_confmute(struct dahdi_pvt *p, int muted);
01997 
01998 static void my_handle_dtmf(void *pvt, struct ast_channel *ast, enum analog_sub analog_index, struct ast_frame **dest)
01999 {
02000    struct ast_frame *f = *dest;
02001    struct dahdi_pvt *p = pvt;
02002    int idx = analogsub_to_dahdisub(analog_index);
02003 
02004    ast_debug(1, "%s DTMF digit: 0x%02X '%c' on %s\n",
02005       f->frametype == AST_FRAME_DTMF_BEGIN ? "Begin" : "End",
02006       f->subclass.integer, f->subclass.integer, ast->name);
02007 
02008    if (f->subclass.integer == 'f') {
02009       if (f->frametype == AST_FRAME_DTMF_END) {
02010          /* Fax tone -- Handle and return NULL */
02011          if ((p->callprogress & CALLPROGRESS_FAX) && !p->faxhandled) {
02012             /* If faxbuffers are configured, use them for the fax transmission */
02013             if (p->usefaxbuffers && !p->bufferoverrideinuse) {
02014                struct dahdi_bufferinfo bi = {
02015                   .txbufpolicy = p->faxbuf_policy,
02016                   .bufsize = p->bufsize,
02017                   .numbufs = p->faxbuf_no
02018                };
02019                int res;
02020 
02021                if ((res = ioctl(p->subs[idx].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
02022                   ast_log(LOG_WARNING, "Channel '%s' unable to set buffer policy, reason: %s\n", ast->name, strerror(errno));
02023                } else {
02024                   p->bufferoverrideinuse = 1;
02025                }
02026             }
02027             p->faxhandled = 1;
02028             if (p->dsp) {
02029                p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
02030                ast_dsp_set_features(p->dsp, p->dsp_features);
02031                ast_debug(1, "Disabling FAX tone detection on %s after tone received\n", ast->name);
02032             }
02033             if (strcmp(ast->exten, "fax")) {
02034                const char *target_context = S_OR(ast->macrocontext, ast->context);
02035 
02036                /* We need to unlock 'ast' here because ast_exists_extension has the
02037                 * potential to start autoservice on the channel. Such action is prone
02038                 * to deadlock.
02039                 */
02040                ast_mutex_unlock(&p->lock);
02041                ast_channel_unlock(ast);
02042                if (ast_exists_extension(ast, target_context, "fax", 1,
02043                   S_COR(ast->caller.id.number.valid, ast->caller.id.number.str, NULL))) {
02044                   ast_channel_lock(ast);
02045                   ast_mutex_lock(&p->lock);
02046                   ast_verb(3, "Redirecting %s to fax extension\n", ast->name);
02047                   /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
02048                   pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten);
02049                   if (ast_async_goto(ast, target_context, "fax", 1))
02050                      ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context);
02051                } else {
02052                   ast_channel_lock(ast);
02053                   ast_mutex_lock(&p->lock);
02054                   ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
02055                }
02056             } else {
02057                ast_debug(1, "Already in a fax extension, not redirecting\n");
02058             }
02059          } else {
02060             ast_debug(1, "Fax already handled\n");
02061          }
02062          dahdi_confmute(p, 0);
02063       }
02064       p->subs[idx].f.frametype = AST_FRAME_NULL;
02065       p->subs[idx].f.subclass.integer = 0;
02066       *dest = &p->subs[idx].f;
02067    }
02068 }
02069 
02070 static void my_lock_private(void *pvt)
02071 {
02072    struct dahdi_pvt *p = pvt;
02073    ast_mutex_lock(&p->lock);
02074 }
02075 
02076 static void my_unlock_private(void *pvt)
02077 {
02078    struct dahdi_pvt *p = pvt;
02079    ast_mutex_unlock(&p->lock);
02080 }
02081 
02082 static void my_deadlock_avoidance_private(void *pvt)
02083 {
02084    struct dahdi_pvt *p = pvt;
02085 
02086    DEADLOCK_AVOIDANCE(&p->lock);
02087 }
02088 
02089 /* linear_mode = 0 - turn linear mode off, >0 - turn linear mode on
02090 *  returns the last value of the linear setting 
02091 */ 
02092 static int my_set_linear_mode(void *pvt, enum analog_sub sub, int linear_mode)
02093 {
02094    struct dahdi_pvt *p = pvt;
02095    int oldval;
02096    int idx = analogsub_to_dahdisub(sub);
02097    
02098    dahdi_setlinear(p->subs[idx].dfd, linear_mode);
02099    oldval = p->subs[idx].linear;
02100    p->subs[idx].linear = linear_mode ? 1 : 0;
02101    return oldval;
02102 }
02103 
02104 static void my_set_inthreeway(void *pvt, enum analog_sub sub, int inthreeway)
02105 {
02106    struct dahdi_pvt *p = pvt;
02107    int idx = analogsub_to_dahdisub(sub);
02108 
02109    p->subs[idx].inthreeway = inthreeway;
02110 }
02111 
02112 static int get_alarms(struct dahdi_pvt *p);
02113 static void handle_alarms(struct dahdi_pvt *p, int alms);
02114 static void my_get_and_handle_alarms(void *pvt)
02115 {
02116    int res;
02117    struct dahdi_pvt *p = pvt;
02118 
02119    res = get_alarms(p);
02120    handle_alarms(p, res);
02121 }
02122 
02123 static void *my_get_sigpvt_bridged_channel(struct ast_channel *chan)
02124 {
02125    struct dahdi_pvt *p = ast_bridged_channel(chan)->tech_pvt;
02126    if (p)
02127       return p->sig_pvt;
02128    else
02129       return NULL;
02130 }
02131 
02132 static int my_get_sub_fd(void *pvt, enum analog_sub sub)
02133 {
02134    struct dahdi_pvt *p = pvt;
02135    int dahdi_sub = analogsub_to_dahdisub(sub);
02136    return p->subs[dahdi_sub].dfd;
02137 }
02138 
02139 static void my_set_cadence(void *pvt, int *cidrings, struct ast_channel *ast)
02140 {
02141    struct dahdi_pvt *p = pvt;
02142 
02143    /* Choose proper cadence */
02144    if ((p->distinctivering > 0) && (p->distinctivering <= num_cadence)) {
02145       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &cadences[p->distinctivering - 1]))
02146          ast_log(LOG_WARNING, "Unable to set distinctive ring cadence %d on '%s': %s\n", p->distinctivering, ast->name, strerror(errno));
02147       *cidrings = cidrings[p->distinctivering - 1];
02148    } else {
02149       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, NULL))
02150          ast_log(LOG_WARNING, "Unable to reset default ring on '%s': %s\n", ast->name, strerror(errno));
02151       *cidrings = p->sendcalleridafter;
02152    }
02153 }
02154 
02155 static void my_set_alarm(void *pvt, int in_alarm)
02156 {
02157    struct dahdi_pvt *p = pvt;
02158 
02159    p->inalarm = in_alarm;
02160 }
02161 
02162 static void my_set_dialing(void *pvt, int is_dialing)
02163 {
02164    struct dahdi_pvt *p = pvt;
02165 
02166    p->dialing = is_dialing;
02167 }
02168 
02169 #if defined(HAVE_PRI) || defined(HAVE_SS7)
02170 static void my_set_digital(void *pvt, int is_digital)
02171 {
02172    struct dahdi_pvt *p = pvt;
02173 
02174    p->digital = is_digital;
02175 }
02176 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
02177 
02178 #if defined(HAVE_SS7)
02179 static void my_set_inservice(void *pvt, int is_inservice)
02180 {
02181    struct dahdi_pvt *p = pvt;
02182 
02183    p->inservice = is_inservice;
02184 }
02185 #endif   /* defined(HAVE_SS7) */
02186 
02187 #if defined(HAVE_SS7)
02188 static void my_set_locallyblocked(void *pvt, int is_blocked)
02189 {
02190    struct dahdi_pvt *p = pvt;
02191 
02192    p->locallyblocked = is_blocked;
02193 }
02194 #endif   /* defined(HAVE_SS7) */
02195 
02196 #if defined(HAVE_SS7)
02197 static void my_set_remotelyblocked(void *pvt, int is_blocked)
02198 {
02199    struct dahdi_pvt *p = pvt;
02200 
02201    p->remotelyblocked = is_blocked;
02202 }
02203 #endif   /* defined(HAVE_SS7) */
02204 
02205 static void my_set_ringtimeout(void *pvt, int ringt)
02206 {
02207    struct dahdi_pvt *p = pvt;
02208    p->ringt = ringt;
02209 }
02210 
02211 static void my_set_waitingfordt(void *pvt, struct ast_channel *ast)
02212 {
02213    struct dahdi_pvt *p = pvt;
02214 
02215    if (p->waitfordialtone && CANPROGRESSDETECT(p) && p->dsp) {
02216       ast_log(LOG_DEBUG, "Defer dialing for %dms or dialtone\n", p->waitfordialtone);
02217       gettimeofday(&p->waitingfordt, NULL);
02218       ast_setstate(ast, AST_STATE_OFFHOOK);
02219    }
02220 }
02221 
02222 static int my_check_waitingfordt(void *pvt)
02223 {
02224    struct dahdi_pvt *p = pvt;
02225 
02226    if (p->waitingfordt.tv_usec) {
02227       return 1;
02228    }
02229 
02230    return 0;
02231 }
02232 
02233 static void my_set_confirmanswer(void *pvt, int flag)
02234 {
02235    struct dahdi_pvt *p = pvt;
02236    p->confirmanswer = flag;
02237 }
02238 
02239 static int my_check_confirmanswer(void *pvt)
02240 {
02241    struct dahdi_pvt *p = pvt;
02242    if (p->confirmanswer) {
02243       return 1;
02244    }
02245 
02246    return 0;
02247 }
02248 
02249 static void my_set_callwaiting(void *pvt, int callwaiting_enable)
02250 {
02251    struct dahdi_pvt *p = pvt;
02252 
02253    p->callwaiting = callwaiting_enable;
02254 }
02255 
02256 static void my_cancel_cidspill(void *pvt)
02257 {
02258    struct dahdi_pvt *p = pvt;
02259 
02260    ast_free(p->cidspill);
02261    p->cidspill = NULL;
02262    restore_conference(p);
02263 }
02264 
02265 static int my_confmute(void *pvt, int mute)
02266 {
02267    struct dahdi_pvt *p = pvt;
02268    return dahdi_confmute(p, mute);
02269 }
02270 
02271 static void my_set_pulsedial(void *pvt, int flag)
02272 {
02273    struct dahdi_pvt *p = pvt;
02274    p->pulsedial = flag;
02275 }
02276 
02277 static void my_set_new_owner(void *pvt, struct ast_channel *new_owner)
02278 {
02279    struct dahdi_pvt *p = pvt;
02280 
02281    p->owner = new_owner;
02282 }
02283 
02284 static const char *my_get_orig_dialstring(void *pvt)
02285 {
02286    struct dahdi_pvt *p = pvt;
02287 
02288    return p->dialstring;
02289 }
02290 
02291 static void my_increase_ss_count(void)
02292 {
02293    ast_mutex_lock(&ss_thread_lock);
02294    ss_thread_count++;
02295    ast_mutex_unlock(&ss_thread_lock);
02296 }
02297 
02298 static void my_decrease_ss_count(void)
02299 {
02300    ast_mutex_lock(&ss_thread_lock);
02301    ss_thread_count--;
02302    ast_cond_signal(&ss_thread_complete);
02303    ast_mutex_unlock(&ss_thread_lock);
02304 }
02305 
02306 static void my_all_subchannels_hungup(void *pvt)
02307 {
02308    struct dahdi_pvt *p = pvt;
02309    int res, law;
02310 
02311    p->faxhandled = 0;
02312    p->didtdd = 0;
02313 
02314    if (p->dsp) {
02315       ast_dsp_free(p->dsp);
02316       p->dsp = NULL;
02317    }
02318 
02319    p->law = p->law_default;
02320    law = p->law_default;
02321    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
02322    if (res < 0)
02323       ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
02324 
02325    dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
02326 
02327 #if 1
02328    {
02329    int i;
02330    p->owner = NULL;
02331    /* Cleanup owners here */
02332    for (i = 0; i < 3; i++) {
02333       p->subs[i].owner = NULL;
02334    }
02335    }
02336 #endif
02337 
02338    reset_conf(p);
02339    if (num_restart_pending == 0) {
02340       restart_monitor();
02341    }
02342 }
02343 
02344 static int conf_del(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index);
02345 
02346 static int my_conf_del(void *pvt, enum analog_sub sub)
02347 {
02348    struct dahdi_pvt *p = pvt;
02349    int x = analogsub_to_dahdisub(sub);
02350 
02351    return conf_del(p, &p->subs[x], x);
02352 }
02353 
02354 static int conf_add(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index, int slavechannel);
02355 
02356 static int my_conf_add(void *pvt, enum analog_sub sub)
02357 {
02358    struct dahdi_pvt *p = pvt;
02359    int x = analogsub_to_dahdisub(sub);
02360 
02361    return conf_add(p, &p->subs[x], x, 0);
02362 }
02363 
02364 static int isslavenative(struct dahdi_pvt *p, struct dahdi_pvt **out);
02365 
02366 static int my_complete_conference_update(void *pvt, int needconference)
02367 {
02368    struct dahdi_pvt *p = pvt;
02369    int needconf = needconference;
02370    int x;
02371    int useslavenative;
02372    struct dahdi_pvt *slave = NULL;
02373 
02374    useslavenative = isslavenative(p, &slave);
02375 
02376    /* If we have a slave, add him to our conference now. or DAX
02377       if this is slave native */
02378    for (x = 0; x < MAX_SLAVES; x++) {
02379       if (p->slaves[x]) {
02380          if (useslavenative)
02381             conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
02382          else {
02383             conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
02384             needconf++;
02385          }
02386       }
02387    }
02388    /* If we're supposed to be in there, do so now */
02389    if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
02390       if (useslavenative)
02391          conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
02392       else {
02393          conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
02394          needconf++;
02395       }
02396    }
02397    /* If we have a master, add ourselves to his conference */
02398    if (p->master) {
02399       if (isslavenative(p->master, NULL)) {
02400          conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
02401       } else {
02402          conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
02403       }
02404    }
02405    if (!needconf) {
02406       /* Nobody is left (or should be left) in our conference.
02407          Kill it. */
02408       p->confno = -1;
02409    }
02410 
02411    return 0;
02412 }
02413 
02414 static int check_for_conference(struct dahdi_pvt *p);
02415 
02416 static int my_check_for_conference(void *pvt)
02417 {
02418    struct dahdi_pvt *p = pvt;
02419    return check_for_conference(p);
02420 }
02421 
02422 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)
02423 {
02424    struct dahdi_pvt *p = pvt;
02425    int da, db;
02426    int tchan;
02427    int tinthreeway;
02428 
02429    da = analogsub_to_dahdisub(a);
02430    db = analogsub_to_dahdisub(b);
02431 
02432    tchan = p->subs[da].chan;
02433    p->subs[da].chan = p->subs[db].chan;
02434    p->subs[db].chan = tchan;
02435 
02436    tinthreeway = p->subs[da].inthreeway;
02437    p->subs[da].inthreeway = p->subs[db].inthreeway;
02438    p->subs[db].inthreeway = tinthreeway;
02439 
02440    p->subs[da].owner = ast_a;
02441    p->subs[db].owner = ast_b;
02442 
02443    if (ast_a)
02444       ast_channel_set_fd(ast_a, 0, p->subs[da].dfd);
02445    if (ast_b)
02446       ast_channel_set_fd(ast_b, 0, p->subs[db].dfd);
02447 
02448    wakeup_sub(p, a);
02449    wakeup_sub(p, b);
02450 
02451    return;
02452 }
02453 
02454 static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpbx, int idx, int law, const char *linkedid);
02455 
02456 static struct ast_channel *my_new_analog_ast_channel(void *pvt, int state, int startpbx, enum analog_sub sub, const struct ast_channel *requestor)
02457 {
02458    struct dahdi_pvt *p = pvt;
02459    int dsub = analogsub_to_dahdisub(sub);
02460 
02461    return dahdi_new(p, state, startpbx, dsub, 0, requestor ? requestor->linkedid : "");
02462 }
02463 
02464 #if defined(HAVE_PRI) || defined(HAVE_SS7)
02465 static int dahdi_setlaw(int dfd, int law)
02466 {
02467    int res;
02468    res = ioctl(dfd, DAHDI_SETLAW, &law);
02469    if (res)
02470       return res;
02471    return 0;
02472 }
02473 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
02474 
02475 #if defined(HAVE_PRI)
02476 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)
02477 {
02478    struct dahdi_pvt *p = pvt;
02479    int audio;
02480    int newlaw = -1;
02481 
02482    switch (p->sig) {
02483    case SIG_PRI_LIB_HANDLE_CASES:
02484       if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
02485          /* PRI nobch pseudo channel.  Does not handle ioctl(DAHDI_AUDIOMODE) */
02486          break;
02487       }
02488       /* Fall through */
02489    default:
02490       /* Set to audio mode at this point */
02491       audio = 1;
02492       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &audio) == -1) {
02493          ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n",
02494             p->channel, audio, strerror(errno));
02495       }
02496       break;
02497    }
02498 
02499    if (law != SIG_PRI_DEFLAW) {
02500       dahdi_setlaw(p->subs[SUB_REAL].dfd, (law == SIG_PRI_ULAW) ? DAHDI_LAW_MULAW : DAHDI_LAW_ALAW);
02501    }
02502 
02503    ast_copy_string(p->exten, exten, sizeof(p->exten));
02504 
02505    switch (law) {
02506       case SIG_PRI_DEFLAW:
02507          newlaw = 0;
02508          break;
02509       case SIG_PRI_ALAW:
02510          newlaw = DAHDI_LAW_ALAW;
02511          break;
02512       case SIG_PRI_ULAW:
02513          newlaw = DAHDI_LAW_MULAW;
02514          break;
02515    }
02516    return dahdi_new(p, state, 0, SUB_REAL, newlaw, requestor ? requestor->linkedid : "");
02517 }
02518 #endif   /* defined(HAVE_PRI) */
02519 
02520 static int set_actual_gain(int fd, float rxgain, float txgain, float rxdrc, float txdrc, int law);
02521 
02522 #if defined(HAVE_PRI)
02523 /*!
02524  * \internal
02525  * \brief Open the PRI channel media path.
02526  * \since 1.8
02527  *
02528  * \param p Channel private control structure.
02529  *
02530  * \return Nothing
02531  */
02532 static void my_pri_open_media(void *p)
02533 {
02534    struct dahdi_pvt *pvt = p;
02535    int res;
02536    int dfd;
02537    int set_val;
02538 
02539    dfd = pvt->subs[SUB_REAL].dfd;
02540 
02541    /* Open the media path. */
02542    set_val = 1;
02543    res = ioctl(dfd, DAHDI_AUDIOMODE, &set_val);
02544    if (res < 0) {
02545       ast_log(LOG_WARNING, "Unable to enable audio mode on channel %d (%s)\n",
02546          pvt->channel, strerror(errno));
02547    }
02548 
02549    /* Set correct companding law for this call. */
02550    res = dahdi_setlaw(dfd, pvt->law);
02551    if (res < 0) {
02552       ast_log(LOG_WARNING, "Unable to set law on channel %d\n", pvt->channel);
02553    }
02554 
02555    /* Set correct gain for this call. */
02556    if (pvt->digital) {
02557       res = set_actual_gain(dfd, 0, 0, pvt->rxdrc, pvt->txdrc, pvt->law);
02558    } else {
02559       res = set_actual_gain(dfd, pvt->rxgain, pvt->txgain, pvt->rxdrc, pvt->txdrc,
02560          pvt->law);
02561    }
02562    if (res < 0) {
02563       ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", pvt->channel);
02564    }
02565 
02566    if (pvt->dsp_features && pvt->dsp) {
02567       ast_dsp_set_features(pvt->dsp, pvt->dsp_features);
02568       pvt->dsp_features = 0;
02569    }
02570 }
02571 #endif   /* defined(HAVE_PRI) */
02572 
02573 static int unalloc_sub(struct dahdi_pvt *p, int x);
02574 
02575 static int my_unallocate_sub(void *pvt, enum analog_sub analogsub)
02576 {
02577    struct dahdi_pvt *p = pvt;
02578 
02579    return unalloc_sub(p, analogsub_to_dahdisub(analogsub));
02580 }
02581 
02582 static int alloc_sub(struct dahdi_pvt *p, int x);
02583 
02584 static int my_allocate_sub(void *pvt, enum analog_sub analogsub)
02585 {
02586    struct dahdi_pvt *p = pvt;
02587 
02588    return alloc_sub(p, analogsub_to_dahdisub(analogsub));
02589 }
02590 
02591 static int has_voicemail(struct dahdi_pvt *p);
02592 
02593 static int my_has_voicemail(void *pvt)
02594 {
02595    struct dahdi_pvt *p = pvt;
02596 
02597    return has_voicemail(p);
02598 }
02599 
02600 static int my_play_tone(void *pvt, enum analog_sub sub, enum analog_tone tone)
02601 {
02602    struct dahdi_pvt *p = pvt;
02603    int index;
02604 
02605    index = analogsub_to_dahdisub(sub);
02606 
02607    return tone_zone_play_tone(p->subs[index].dfd, analog_tone_to_dahditone(tone));
02608 }
02609 
02610 static enum analog_event dahdievent_to_analogevent(int event)
02611 {
02612    enum analog_event res;
02613 
02614    switch (event) {
02615    case DAHDI_EVENT_ONHOOK:
02616       res = ANALOG_EVENT_ONHOOK;
02617       break;
02618    case DAHDI_EVENT_RINGOFFHOOK:
02619       res = ANALOG_EVENT_RINGOFFHOOK;
02620       break;
02621    case DAHDI_EVENT_WINKFLASH:
02622       res = ANALOG_EVENT_WINKFLASH;
02623       break;
02624    case DAHDI_EVENT_ALARM:
02625       res = ANALOG_EVENT_ALARM;
02626       break;
02627    case DAHDI_EVENT_NOALARM:
02628       res = ANALOG_EVENT_NOALARM;
02629       break;
02630    case DAHDI_EVENT_DIALCOMPLETE:
02631       res = ANALOG_EVENT_DIALCOMPLETE;
02632       break;
02633    case DAHDI_EVENT_RINGERON:
02634       res = ANALOG_EVENT_RINGERON;
02635       break;
02636    case DAHDI_EVENT_RINGEROFF:
02637       res = ANALOG_EVENT_RINGEROFF;
02638       break;
02639    case DAHDI_EVENT_HOOKCOMPLETE:
02640       res = ANALOG_EVENT_HOOKCOMPLETE;
02641       break;
02642    case DAHDI_EVENT_PULSE_START:
02643       res = ANALOG_EVENT_PULSE_START;
02644       break;
02645    case DAHDI_EVENT_POLARITY:
02646       res = ANALOG_EVENT_POLARITY;
02647       break;
02648    case DAHDI_EVENT_RINGBEGIN:
02649       res = ANALOG_EVENT_RINGBEGIN;
02650       break;
02651    case DAHDI_EVENT_EC_DISABLED:
02652       res = ANALOG_EVENT_EC_DISABLED;
02653       break;
02654    case DAHDI_EVENT_REMOVED:
02655       res = ANALOG_EVENT_REMOVED;
02656       break;
02657    case DAHDI_EVENT_NEONMWI_ACTIVE:
02658       res = ANALOG_EVENT_NEONMWI_ACTIVE;
02659       break;
02660    case DAHDI_EVENT_NEONMWI_INACTIVE:
02661       res = ANALOG_EVENT_NEONMWI_INACTIVE;
02662       break;
02663 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
02664    case DAHDI_EVENT_TX_CED_DETECTED:
02665       res = ANALOG_EVENT_TX_CED_DETECTED;
02666       break;
02667    case DAHDI_EVENT_RX_CED_DETECTED:
02668       res = ANALOG_EVENT_RX_CED_DETECTED;
02669       break;
02670    case DAHDI_EVENT_EC_NLP_DISABLED:
02671       res = ANALOG_EVENT_EC_NLP_DISABLED;
02672       break;
02673    case DAHDI_EVENT_EC_NLP_ENABLED:
02674       res = ANALOG_EVENT_EC_NLP_ENABLED;
02675       break;
02676 #endif
02677    case DAHDI_EVENT_PULSEDIGIT:
02678       res = ANALOG_EVENT_PULSEDIGIT;
02679       break;
02680    case DAHDI_EVENT_DTMFDOWN:
02681       res = ANALOG_EVENT_DTMFDOWN;
02682       break;
02683    case DAHDI_EVENT_DTMFUP:
02684       res = ANALOG_EVENT_DTMFUP;
02685       break;
02686    default:
02687       switch(event & 0xFFFF0000) {
02688       case DAHDI_EVENT_PULSEDIGIT:
02689       case DAHDI_EVENT_DTMFDOWN:
02690       case DAHDI_EVENT_DTMFUP:
02691          /* The event includes a digit number in the low word.
02692           * Converting it to a 'enum analog_event' would remove
02693           * that information. Thus it is returned as-is.
02694           */
02695          return event;
02696       }
02697 
02698       res = ANALOG_EVENT_ERROR;
02699       break;
02700    }
02701 
02702    return res;
02703 }
02704 
02705 static inline int dahdi_wait_event(int fd);
02706 
02707 static int my_wait_event(void *pvt)
02708 {
02709    struct dahdi_pvt *p = pvt;
02710 
02711    return dahdi_wait_event(p->subs[SUB_REAL].dfd);
02712 }
02713 
02714 static int my_get_event(void *pvt)
02715 {
02716    struct dahdi_pvt *p = pvt;
02717    int res;
02718 
02719    if (p->fake_event) {
02720       res = p->fake_event;
02721       p->fake_event = 0;
02722    } else
02723       res = dahdi_get_event(p->subs[SUB_REAL].dfd);
02724 
02725    return dahdievent_to_analogevent(res);
02726 }
02727 
02728 static int my_is_off_hook(void *pvt)
02729 {
02730    struct dahdi_pvt *p = pvt;
02731    int res;
02732    struct dahdi_params par;
02733 
02734    memset(&par, 0, sizeof(par));
02735 
02736    if (p->subs[SUB_REAL].dfd > -1)
02737       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
02738    else {
02739       /* Assume not off hook on CVRS */
02740       res = 0;
02741       par.rxisoffhook = 0;
02742    }
02743    if (res) {
02744       ast_log(LOG_WARNING, "Unable to check hook state on channel %d: %s\n", p->channel, strerror(errno));
02745    }
02746 
02747    if ((p->sig == SIG_FXSKS) || (p->sig == SIG_FXSGS)) {
02748       /* When "onhook" that means no battery on the line, and thus
02749       it is out of service..., if it's on a TDM card... If it's a channel
02750       bank, there is no telling... */
02751       return (par.rxbits > -1) || par.rxisoffhook;
02752    }
02753 
02754    return par.rxisoffhook;
02755 }
02756 
02757 static void dahdi_enable_ec(struct dahdi_pvt *p);
02758 static void dahdi_disable_ec(struct dahdi_pvt *p);
02759 
02760 static int my_set_echocanceller(void *pvt, int enable)
02761 {
02762    struct dahdi_pvt *p = pvt;
02763 
02764    if (enable)
02765       dahdi_enable_ec(p);
02766    else
02767       dahdi_disable_ec(p);
02768 
02769    return 0;
02770 }
02771 
02772 static int dahdi_ring_phone(struct dahdi_pvt *p);
02773 
02774 static int my_ring(void *pvt)
02775 {
02776    struct dahdi_pvt *p = pvt;
02777 
02778    return dahdi_ring_phone(p);
02779 }
02780 
02781 static int my_flash(void *pvt)
02782 {
02783    struct dahdi_pvt *p = pvt;
02784    int func = DAHDI_FLASH;
02785    return ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &func);
02786 }
02787 
02788 static inline int dahdi_set_hook(int fd, int hs);
02789 
02790 static int my_off_hook(void *pvt)
02791 {
02792    struct dahdi_pvt *p = pvt;
02793    return dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
02794 }
02795 
02796 static void my_set_needringing(void *pvt, int value)
02797 {
02798    struct dahdi_pvt *p = pvt;
02799    p->subs[SUB_REAL].needringing = value;
02800 }
02801 
02802 static void my_set_polarity(void *pvt, int value)
02803 {
02804    struct dahdi_pvt *p = pvt;
02805 
02806    if (p->channel == CHAN_PSEUDO) {
02807       return;
02808    }
02809    p->polarity = value;
02810    ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETPOLARITY, &value);
02811 }
02812 
02813 static void my_start_polarityswitch(void *pvt)
02814 {
02815    struct dahdi_pvt *p = pvt;
02816 
02817    if (p->answeronpolarityswitch || p->hanguponpolarityswitch) {
02818       my_set_polarity(pvt, 0);
02819    }
02820 }
02821 
02822 static void my_answer_polarityswitch(void *pvt)
02823 {
02824    struct dahdi_pvt *p = pvt;
02825 
02826    if (!p->answeronpolarityswitch) {
02827       return;
02828    }
02829 
02830    my_set_polarity(pvt, 1);
02831 }
02832 
02833 static void my_hangup_polarityswitch(void *pvt)
02834 {
02835    struct dahdi_pvt *p = pvt;
02836 
02837    if (!p->hanguponpolarityswitch) {
02838       return;
02839    }
02840 
02841    if (p->answeronpolarityswitch) {
02842       my_set_polarity(pvt, 0);
02843    } else {
02844       my_set_polarity(pvt, 1);
02845    }
02846 }
02847 
02848 static int my_start(void *pvt)
02849 {
02850    struct dahdi_pvt *p = pvt;
02851    int x = DAHDI_START;
02852 
02853    return ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
02854 }
02855 
02856 static int my_dial_digits(void *pvt, enum analog_sub sub, struct analog_dialoperation *dop)
02857 {
02858    int index = analogsub_to_dahdisub(sub);
02859    int res;
02860    struct dahdi_pvt *p = pvt;
02861    struct dahdi_dialoperation ddop;
02862 
02863    if (dop->op != ANALOG_DIAL_OP_REPLACE) {
02864       ast_log(LOG_ERROR, "Fix the dial_digits callback!\n");
02865       return -1;
02866    }
02867 
02868    if (sub != ANALOG_SUB_REAL)
02869       printf("Trying to dial digits on sub %d\n", sub);
02870 
02871    ddop.op = DAHDI_DIAL_OP_REPLACE;
02872    strncpy(ddop.dialstr, dop->dialstr, sizeof(ddop.dialstr));
02873 
02874    printf("Dialing %s on %d\n", ddop.dialstr, p->channel);
02875 
02876    res = ioctl(p->subs[index].dfd, DAHDI_DIAL, &ddop);
02877 
02878    if (res == -1)
02879       ast_log(LOG_DEBUG, "DAHDI_DIAL ioctl failed on %s: %s\n", p->owner->name, strerror(errno));
02880 
02881    return res;
02882 }
02883 
02884 static void dahdi_train_ec(struct dahdi_pvt *p);
02885 
02886 static int my_train_echocanceller(void *pvt)
02887 {
02888    struct dahdi_pvt *p = pvt;
02889 
02890    dahdi_train_ec(p);
02891 
02892    return 0;
02893 }
02894 
02895 static int my_is_dialing(void *pvt, enum analog_sub sub)
02896 {
02897    struct dahdi_pvt *p = pvt;
02898    int index;
02899    int x;
02900 
02901    index = analogsub_to_dahdisub(sub);
02902 
02903    if (ioctl(p->subs[index].dfd, DAHDI_DIALING, &x)) {
02904       ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed!\n");
02905       return -1;
02906    }
02907 
02908    return x;
02909 }
02910 
02911 static int my_on_hook(void *pvt)
02912 {
02913    struct dahdi_pvt *p = pvt;
02914    return dahdi_set_hook(p->subs[ANALOG_SUB_REAL].dfd, DAHDI_ONHOOK);
02915 }
02916 
02917 #if defined(HAVE_PRI)
02918 static void my_pri_fixup_chans(void *chan_old, void *chan_new)
02919 {
02920    struct dahdi_pvt *old_chan = chan_old;
02921    struct dahdi_pvt *new_chan = chan_new;
02922 
02923    new_chan->owner = old_chan->owner;
02924    old_chan->owner = NULL;
02925    if (new_chan->owner) {
02926       new_chan->owner->tech_pvt = new_chan;
02927       new_chan->owner->fds[0] = new_chan->subs[SUB_REAL].dfd;
02928       new_chan->subs[SUB_REAL].owner = old_chan->subs[SUB_REAL].owner;
02929       old_chan->subs[SUB_REAL].owner = NULL;
02930    }
02931    /* Copy any DSP that may be present */
02932    new_chan->dsp = old_chan->dsp;
02933    new_chan->dsp_features = old_chan->dsp_features;
02934    old_chan->dsp = NULL;
02935    old_chan->dsp_features = 0;
02936 
02937    /* Transfer flags from the old channel. */
02938    new_chan->dialing = old_chan->dialing;
02939    new_chan->digital = old_chan->digital;
02940    new_chan->outgoing = old_chan->outgoing;
02941    old_chan->dialing = 0;
02942    old_chan->digital = 0;
02943    old_chan->outgoing = 0;
02944 
02945    /* More stuff to transfer to the new channel. */
02946    new_chan->law = old_chan->law;
02947    strcpy(new_chan->dialstring, old_chan->dialstring);
02948 }
02949 #endif   /* defined(HAVE_PRI) */
02950 
02951 #if defined(HAVE_PRI)
02952 static int sig_pri_tone_to_dahditone(enum sig_pri_tone tone)
02953 {
02954    switch (tone) {
02955    case SIG_PRI_TONE_RINGTONE:
02956       return DAHDI_TONE_RINGTONE;
02957    case SIG_PRI_TONE_STUTTER:
02958       return DAHDI_TONE_STUTTER;
02959    case SIG_PRI_TONE_CONGESTION:
02960       return DAHDI_TONE_CONGESTION;
02961    case SIG_PRI_TONE_DIALTONE:
02962       return DAHDI_TONE_DIALTONE;
02963    case SIG_PRI_TONE_DIALRECALL:
02964       return DAHDI_TONE_DIALRECALL;
02965    case SIG_PRI_TONE_INFO:
02966       return DAHDI_TONE_INFO;
02967    case SIG_PRI_TONE_BUSY:
02968       return DAHDI_TONE_BUSY;
02969    default:
02970       return -1;
02971    }
02972 }
02973 #endif   /* defined(HAVE_PRI) */
02974 
02975 #if defined(HAVE_PRI)
02976 static void my_handle_dchan_exception(struct sig_pri_span *pri, int index)
02977 {
02978    int x, res;
02979 
02980    res = ioctl(pri->fds[index], DAHDI_GETEVENT, &x);
02981    if (x) {
02982       ast_log(LOG_NOTICE, "PRI got event: %s (%d) on D-channel of span %d\n", event2str(x), x, pri->span);
02983    }
02984    /* Keep track of alarm state */
02985    switch (x) {
02986    case DAHDI_EVENT_ALARM:
02987       pri_event_alarm(pri, index, 0);
02988       break;
02989    case DAHDI_EVENT_NOALARM:
02990       pri_event_noalarm(pri, index, 0);
02991       break;
02992    default:
02993       break;
02994    }
02995 }
02996 #endif   /* defined(HAVE_PRI) */
02997 
02998 #if defined(HAVE_PRI)
02999 static int my_pri_play_tone(void *pvt, enum sig_pri_tone tone)
03000 {
03001    struct dahdi_pvt *p = pvt;
03002 
03003    return tone_zone_play_tone(p->subs[SUB_REAL].dfd, sig_pri_tone_to_dahditone(tone));
03004 }
03005 #endif   /* defined(HAVE_PRI) */
03006 
03007 #if defined(HAVE_PRI) || defined(HAVE_SS7)
03008 /*!
03009  * \internal
03010  * \brief Set the caller id information.
03011  * \since 1.8
03012  *
03013  * \param pvt DAHDI private structure
03014  * \param caller Caller-id information to set.
03015  *
03016  * \return Nothing
03017  */
03018 static void my_set_callerid(void *pvt, const struct ast_party_caller *caller)
03019 {
03020    struct dahdi_pvt *p = pvt;
03021 
03022    ast_copy_string(p->cid_num,
03023       S_COR(caller->id.number.valid, caller->id.number.str, ""),
03024       sizeof(p->cid_num));
03025    ast_copy_string(p->cid_name,
03026       S_COR(caller->id.name.valid, caller->id.name.str, ""),
03027       sizeof(p->cid_name));
03028    ast_copy_string(p->cid_subaddr,
03029       S_COR(caller->id.subaddress.valid, caller->id.subaddress.str, ""),
03030       sizeof(p->cid_subaddr));
03031    p->cid_ton = caller->id.number.plan;
03032    p->callingpres = ast_party_id_presentation(&caller->id);
03033    if (caller->id.tag) {
03034       ast_copy_string(p->cid_tag, caller->id.tag, sizeof(p->cid_tag));
03035    }
03036    ast_copy_string(p->cid_ani,
03037       S_COR(caller->ani.number.valid, caller->ani.number.str, ""),
03038       sizeof(p->cid_ani));
03039    p->cid_ani2 = caller->ani2;
03040 }
03041 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
03042 
03043 #if defined(HAVE_PRI) || defined(HAVE_SS7)
03044 /*!
03045  * \internal
03046  * \brief Set the Dialed Number Identifier.
03047  * \since 1.8
03048  *
03049  * \param pvt DAHDI private structure
03050  * \param dnid Dialed Number Identifier string.
03051  *
03052  * \return Nothing
03053  */
03054 static void my_set_dnid(void *pvt, const char *dnid)
03055 {
03056    struct dahdi_pvt *p = pvt;
03057 
03058    ast_copy_string(p->dnid, dnid, sizeof(p->dnid));
03059 }
03060 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
03061 
03062 #if defined(HAVE_PRI)
03063 /*!
03064  * \internal
03065  * \brief Set the Redirecting Directory Number Information Service (RDNIS).
03066  * \since 1.8
03067  *
03068  * \param pvt DAHDI private structure
03069  * \param rdnis Redirecting Directory Number Information Service (RDNIS) string.
03070  *
03071  * \return Nothing
03072  */
03073 static void my_set_rdnis(void *pvt, const char *rdnis)
03074 {
03075    struct dahdi_pvt *p = pvt;
03076 
03077    ast_copy_string(p->rdnis, rdnis, sizeof(p->rdnis));
03078 }
03079 #endif   /* defined(HAVE_PRI) */
03080 
03081 #if defined(HAVE_PRI)
03082 /*!
03083  * \internal
03084  * \brief Make a dialstring for native ISDN CC to recall properly.
03085  * \since 1.8
03086  *
03087  * \param priv Channel private control structure.
03088  * \param buf Where to put the modified dialstring.
03089  * \param buf_size Size of modified dialstring buffer.
03090  *
03091  * \details
03092  * original dialstring:
03093  * DAHDI/[i<span>-](g|G|r|R)<group#(0-63)>[c|r<cadance#>|d][/extension[/options]]
03094  *
03095  * The modified dialstring will have prefixed the channel-group section
03096  * with the ISDN channel restriction.
03097  *
03098  * buf:
03099  * DAHDI/i<span>-(g|G|r|R)<group#(0-63)>[c|r<cadance#>|d][/extension[/options]]
03100  *
03101  * The routine will check to see if the ISDN channel restriction is already
03102  * in the original dialstring.
03103  *
03104  * \return Nothing
03105  */
03106 static void my_pri_make_cc_dialstring(void *priv, char *buf, size_t buf_size)
03107 {
03108    char *dial;
03109    struct dahdi_pvt *pvt;
03110    AST_DECLARE_APP_ARGS(args,
03111       AST_APP_ARG(tech);   /* channel technology token */
03112       AST_APP_ARG(group);  /* channel/group token */
03113       //AST_APP_ARG(ext);  /* extension token */
03114       //AST_APP_ARG(opts); /* options token */
03115       //AST_APP_ARG(other);   /* Any remining unused arguments */
03116    );
03117 
03118    pvt = priv;
03119    dial = ast_strdupa(pvt->dialstring);
03120    AST_NONSTANDARD_APP_ARGS(args, dial, '/');
03121    if (!args.tech) {
03122       ast_copy_string(buf, pvt->dialstring, buf_size);
03123       return;
03124    }
03125    if (!args.group) {
03126       /* Append the ISDN span channel restriction to the dialstring. */
03127       snprintf(buf, buf_size, "%s/i%d-", args.tech, pvt->pri->span);
03128       return;
03129    }
03130    if (isdigit(args.group[0]) || args.group[0] == 'i' || strchr(args.group, '!')) {
03131       /* The ISDN span channel restriction is not needed or already
03132        * in the dialstring. */
03133       ast_copy_string(buf, pvt->dialstring, buf_size);
03134       return;
03135    }
03136    /* Insert the ISDN span channel restriction into the dialstring. */
03137    snprintf(buf, buf_size, "%s/i%d-%s", args.tech, pvt->pri->span, args.group);
03138 }
03139 #endif   /* defined(HAVE_PRI) */
03140 
03141 #if defined(HAVE_PRI)
03142 /*!
03143  * \internal
03144  * \brief Reevaluate the PRI span device state.
03145  * \since 1.8
03146  *
03147  * \param pri Asterisk D channel control structure.
03148  *
03149  * \return Nothing
03150  *
03151  * \note Assumes the pri->lock is already obtained.
03152  */
03153 static void dahdi_pri_update_span_devstate(struct sig_pri_span *pri)
03154 {
03155    unsigned idx;
03156    unsigned num_b_chans;   /* Number of B channels provisioned on the span. */
03157    unsigned in_use;     /* Number of B channels in use on the span. */
03158    unsigned in_alarm;      /* TRUE if the span is in alarm condition. */
03159    enum ast_device_state new_state;
03160 
03161    /* Count the number of B channels and the number of B channels in use. */
03162    num_b_chans = 0;
03163    in_use = 0;
03164    in_alarm = 1;
03165    for (idx = pri->numchans; idx--;) {
03166       if (pri->pvts[idx] && !pri->pvts[idx]->no_b_channel) {
03167          /* This is a B channel interface. */
03168          ++num_b_chans;
03169          if (pri->pvts[idx]->owner
03170 #if defined(HAVE_PRI_SERVICE_MESSAGES)
03171             /* Out-of-service B channels are "in-use". */
03172             || pri->pvts[idx]->service_status
03173 #endif   /* defined(HAVE_PRI_SERVICE_MESSAGES) */
03174             ) {
03175             ++in_use;
03176          }
03177          if (!pri->pvts[idx]->inalarm) {
03178             /* There is a channel that is not in alarm. */
03179             in_alarm = 0;
03180          }
03181       }
03182    }
03183 
03184    /* Update the span congestion device state and report any change. */
03185    if (in_alarm) {
03186       new_state = AST_DEVICE_UNAVAILABLE;
03187    } else {
03188       new_state = num_b_chans == in_use ? AST_DEVICE_BUSY : AST_DEVICE_NOT_INUSE;
03189    }
03190    if (pri->congestion_devstate != new_state) {
03191       pri->congestion_devstate = new_state;
03192       ast_devstate_changed(AST_DEVICE_UNKNOWN, "DAHDI/I%d/congestion", pri->span);
03193    }
03194 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
03195    /* Update the span threshold device state and report any change. */
03196    if (in_alarm) {
03197       new_state = AST_DEVICE_UNAVAILABLE;
03198    } else if (!in_use) {
03199       new_state = AST_DEVICE_NOT_INUSE;
03200    } else if (!pri->user_busy_threshold) {
03201       new_state = in_use < num_b_chans ? AST_DEVICE_INUSE : AST_DEVICE_BUSY;
03202    } else {
03203       new_state = in_use < pri->user_busy_threshold ? AST_DEVICE_INUSE
03204          : AST_DEVICE_BUSY;
03205    }
03206    if (pri->threshold_devstate != new_state) {
03207       pri->threshold_devstate = new_state;
03208       ast_devstate_changed(AST_DEVICE_UNKNOWN, "DAHDI/I%d/threshold", pri->span);
03209    }
03210 #endif   /* defined(THRESHOLD_DEVSTATE_PLACEHOLDER) */
03211 }
03212 #endif   /* defined(HAVE_PRI) */
03213 
03214 #if defined(HAVE_PRI)
03215 /*!
03216  * \internal
03217  * \brief Reference this module.
03218  * \since 1.8
03219  *
03220  * \return Nothing
03221  */
03222 static void my_module_ref(void)
03223 {
03224    ast_module_ref(ast_module_info->self);
03225 }
03226 #endif   /* defined(HAVE_PRI) */
03227 
03228 #if defined(HAVE_PRI)
03229 /*!
03230  * \internal
03231  * \brief Unreference this module.
03232  * \since 1.8
03233  *
03234  * \return Nothing
03235  */
03236 static void my_module_unref(void)
03237 {
03238    ast_module_unref(ast_module_info->self);
03239 }
03240 #endif   /* defined(HAVE_PRI) */
03241 
03242 #if defined(HAVE_PRI)
03243 #if defined(HAVE_PRI_CALL_WAITING)
03244 static void my_pri_init_config(void *priv, struct sig_pri_span *pri);
03245 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
03246 static int dahdi_new_pri_nobch_channel(struct sig_pri_span *pri);
03247 
03248 static struct sig_pri_callback dahdi_pri_callbacks =
03249 {
03250    .handle_dchan_exception = my_handle_dchan_exception,
03251    .play_tone = my_pri_play_tone,
03252    .set_echocanceller = my_set_echocanceller,
03253    .dsp_reset_and_flush_digits = my_dsp_reset_and_flush_digits,
03254    .lock_private = my_lock_private,
03255    .unlock_private = my_unlock_private,
03256    .new_ast_channel = my_new_pri_ast_channel,
03257    .fixup_chans = my_pri_fixup_chans,
03258    .set_alarm = my_set_alarm,
03259    .set_dialing = my_set_dialing,
03260    .set_digital = my_set_digital,
03261    .set_callerid = my_set_callerid,
03262    .set_dnid = my_set_dnid,
03263    .set_rdnis = my_set_rdnis,
03264    .new_nobch_intf = dahdi_new_pri_nobch_channel,
03265 #if defined(HAVE_PRI_CALL_WAITING)
03266    .init_config = my_pri_init_config,
03267 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
03268    .get_orig_dialstring = my_get_orig_dialstring,
03269    .make_cc_dialstring = my_pri_make_cc_dialstring,
03270    .update_span_devstate = dahdi_pri_update_span_devstate,
03271    .module_ref = my_module_ref,
03272    .module_unref = my_module_unref,
03273    .open_media = my_pri_open_media,
03274 };
03275 #endif   /* defined(HAVE_PRI) */
03276 
03277 #if defined(HAVE_SS7)
03278 /*!
03279  * \internal
03280  * \brief Handle the SS7 link exception.
03281  * \since 1.8
03282  *
03283  * \param linkset Controlling linkset for the channel.
03284  * \param which Link index of the signaling channel.
03285  *
03286  * \return Nothing
03287  */
03288 static void my_handle_link_exception(struct sig_ss7_linkset *linkset, int which)
03289 {
03290    int event;
03291 
03292    if (ioctl(linkset->fds[which], DAHDI_GETEVENT, &event)) {
03293       ast_log(LOG_ERROR, "SS7: Error in exception retrieval on span %d/%d!\n",
03294          linkset->span, which);
03295       return;
03296    }
03297    switch (event) {
03298    case DAHDI_EVENT_NONE:
03299       break;
03300    case DAHDI_EVENT_ALARM:
03301       ast_log(LOG_ERROR, "SS7 got event: %s(%d) on span %d/%d\n",
03302          event2str(event), event, linkset->span, which);
03303       sig_ss7_link_alarm(linkset, which);
03304       break;
03305    case DAHDI_EVENT_NOALARM:
03306       ast_log(LOG_ERROR, "SS7 got event: %s(%d) on span %d/%d\n",
03307          event2str(event), event, linkset->span, which);
03308       sig_ss7_link_noalarm(linkset, which);
03309       break;
03310    default:
03311       ast_log(LOG_NOTICE, "SS7 got event: %s(%d) on span %d/%d\n",
03312          event2str(event), event, linkset->span, which);
03313       break;
03314    }
03315 }
03316 #endif   /* defined(HAVE_SS7) */
03317 
03318 #if defined(HAVE_SS7)
03319 static void my_ss7_set_loopback(void *pvt, int enable)
03320 {
03321    struct dahdi_pvt *p = pvt;
03322 
03323    if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_LOOPBACK, &enable)) {
03324       ast_log(LOG_WARNING, "Unable to set loopback on channel %d: %s\n", p->channel,
03325          strerror(errno));
03326    }
03327 }
03328 #endif   /* defined(HAVE_SS7) */
03329 
03330 #if defined(HAVE_SS7)
03331 /*!
03332  * \internal
03333  * \brief Create a new asterisk channel structure for SS7.
03334  * \since 1.8
03335  *
03336  * \param pvt Private channel structure.
03337  * \param state Initial state of new channel.
03338  * \param law Combanding law to use.
03339  * \param exten Dialplan extension for incoming call.
03340  * \param requestor Channel requesting this new channel.
03341  *
03342  * \retval ast_channel on success.
03343  * \retval NULL on error.
03344  */
03345 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)
03346 {
03347    struct dahdi_pvt *p = pvt;
03348    int audio;
03349    int newlaw;
03350 
03351    /* Set to audio mode at this point */
03352    audio = 1;
03353    if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &audio) == -1)
03354       ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n",
03355          p->channel, audio, strerror(errno));
03356 
03357    if (law != SIG_SS7_DEFLAW) {
03358       dahdi_setlaw(p->subs[SUB_REAL].dfd,
03359          (law == SIG_SS7_ULAW) ? DAHDI_LAW_MULAW : DAHDI_LAW_ALAW);
03360    }
03361 
03362    ast_copy_string(p->exten, exten, sizeof(p->exten));
03363 
03364    newlaw = -1;
03365    switch (law) {
03366    case SIG_SS7_DEFLAW:
03367       newlaw = 0;
03368       break;
03369    case SIG_SS7_ALAW:
03370       newlaw = DAHDI_LAW_ALAW;
03371       break;
03372    case SIG_SS7_ULAW:
03373       newlaw = DAHDI_LAW_MULAW;
03374       break;
03375    }
03376    return dahdi_new(p, state, 0, SUB_REAL, newlaw, requestor ? requestor->linkedid : "");
03377 }
03378 #endif   /* defined(HAVE_SS7) */
03379 
03380 #if defined(HAVE_SS7)
03381 static int sig_ss7_tone_to_dahditone(enum sig_ss7_tone tone)
03382 {
03383    switch (tone) {
03384    case SIG_SS7_TONE_RINGTONE:
03385       return DAHDI_TONE_RINGTONE;
03386    case SIG_SS7_TONE_STUTTER:
03387       return DAHDI_TONE_STUTTER;
03388    case SIG_SS7_TONE_CONGESTION:
03389       return DAHDI_TONE_CONGESTION;
03390    case SIG_SS7_TONE_DIALTONE:
03391       return DAHDI_TONE_DIALTONE;
03392    case SIG_SS7_TONE_DIALRECALL:
03393       return DAHDI_TONE_DIALRECALL;
03394    case SIG_SS7_TONE_INFO:
03395       return DAHDI_TONE_INFO;
03396    case SIG_SS7_TONE_BUSY:
03397       return DAHDI_TONE_BUSY;
03398    default:
03399       return -1;
03400    }
03401 }
03402 #endif   /* defined(HAVE_SS7) */
03403 
03404 #if defined(HAVE_SS7)
03405 static int my_ss7_play_tone(void *pvt, enum sig_ss7_tone tone)
03406 {
03407    struct dahdi_pvt *p = pvt;
03408 
03409    return tone_zone_play_tone(p->subs[SUB_REAL].dfd, sig_ss7_tone_to_dahditone(tone));
03410 }
03411 #endif   /* defined(HAVE_SS7) */
03412 
03413 #if defined(HAVE_SS7)
03414 static struct sig_ss7_callback dahdi_ss7_callbacks =
03415 {
03416    .lock_private = my_lock_private,
03417    .unlock_private = my_unlock_private,
03418 
03419    .set_echocanceller = my_set_echocanceller,
03420    .set_loopback = my_ss7_set_loopback,
03421 
03422    .new_ast_channel = my_new_ss7_ast_channel,
03423    .play_tone = my_ss7_play_tone,
03424 
03425    .handle_link_exception = my_handle_link_exception,
03426    .set_alarm = my_set_alarm,
03427    .set_dialing = my_set_dialing,
03428    .set_digital = my_set_digital,
03429    .set_inservice = my_set_inservice,
03430    .set_locallyblocked = my_set_locallyblocked,
03431    .set_remotelyblocked = my_set_remotelyblocked,
03432    .set_callerid = my_set_callerid,
03433    .set_dnid = my_set_dnid,
03434 };
03435 #endif   /* defined(HAVE_SS7) */
03436 
03437 /*!
03438  * \brief Send MWI state change
03439  *
03440  * \arg mailbox_full This is the mailbox associated with the FXO line that the
03441  *      MWI state has changed on.
03442  * \arg thereornot This argument should simply be set to 1 or 0, to indicate
03443  *      whether there are messages waiting or not.
03444  *
03445  *  \return nothing
03446  *
03447  * This function does two things:
03448  *
03449  * 1) It generates an internal Asterisk event notifying any other module that
03450  *    cares about MWI that the state of a mailbox has changed.
03451  *
03452  * 2) It runs the script specified by the mwimonitornotify option to allow
03453  *    some custom handling of the state change.
03454  */
03455 static void notify_message(char *mailbox_full, int thereornot)
03456 {
03457    char s[sizeof(mwimonitornotify) + 80];
03458    struct ast_event *event;
03459    char *mailbox, *context;
03460 
03461    /* Strip off @default */
03462    context = mailbox = ast_strdupa(mailbox_full);
03463    strsep(&context, "@");
03464    if (ast_strlen_zero(context))
03465       context = "default";
03466 
03467    if (!(event = ast_event_new(AST_EVENT_MWI,
03468          AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
03469          AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
03470          AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot,
03471          AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot,
03472          AST_EVENT_IE_END))) {
03473       return;
03474    }
03475 
03476    ast_event_queue_and_cache(event);
03477 
03478    if (!ast_strlen_zero(mailbox) && !ast_strlen_zero(mwimonitornotify)) {
03479       snprintf(s, sizeof(s), "%s %s %d", mwimonitornotify, mailbox, thereornot);
03480       ast_safe_system(s);
03481    }
03482 }
03483 
03484 static void my_handle_notify_message(struct ast_channel *chan, void *pvt, int cid_flags, int neon_mwievent)
03485 {
03486    struct dahdi_pvt *p = pvt;
03487 
03488    if (neon_mwievent > -1 && !p->mwimonitor_neon)
03489       return;
03490 
03491    if (neon_mwievent == ANALOG_EVENT_NEONMWI_ACTIVE || cid_flags & CID_MSGWAITING) {
03492       ast_log(LOG_NOTICE, "MWI: Channel %d message waiting, mailbox %s\n", p->channel, p->mailbox);
03493       notify_message(p->mailbox, 1);
03494    } else if (neon_mwievent == ANALOG_EVENT_NEONMWI_INACTIVE || cid_flags & CID_NOMSGWAITING) {
03495       ast_log(LOG_NOTICE, "MWI: Channel %d no message waiting, mailbox %s\n", p->channel, p->mailbox);
03496       notify_message(p->mailbox, 0);
03497    }
03498    /* If the CID had Message waiting payload, assume that this for MWI only and hangup the call */
03499    /* If generated using Ring Pulse Alert, then ring has been answered as a call and needs to be hungup */
03500    if (neon_mwievent == -1 && p->mwimonitor_rpas) {
03501       ast_hangup(chan);
03502       return;
03503    }
03504 }
03505 
03506 
03507 
03508 static struct analog_callback dahdi_analog_callbacks =
03509 {
03510    .play_tone = my_play_tone,
03511    .get_event = my_get_event,
03512    .wait_event = my_wait_event,
03513    .is_off_hook = my_is_off_hook,
03514    .set_echocanceller = my_set_echocanceller,
03515    .ring = my_ring,
03516    .flash = my_flash,
03517    .off_hook = my_off_hook,
03518    .dial_digits = my_dial_digits,
03519    .train_echocanceller = my_train_echocanceller,
03520    .on_hook = my_on_hook,
03521    .is_dialing = my_is_dialing,
03522    .allocate_sub = my_allocate_sub,
03523    .unallocate_sub = my_unallocate_sub,
03524    .swap_subs = my_swap_subchannels,
03525    .has_voicemail = my_has_voicemail,
03526    .check_for_conference = my_check_for_conference,
03527    .conf_add = my_conf_add,
03528    .conf_del = my_conf_del,
03529    .complete_conference_update = my_complete_conference_update,
03530    .start = my_start,
03531    .all_subchannels_hungup = my_all_subchannels_hungup,
03532    .lock_private = my_lock_private,
03533    .unlock_private = my_unlock_private,
03534    .deadlock_avoidance_private = my_deadlock_avoidance_private,
03535    .handle_dtmf = my_handle_dtmf,
03536    .wink = my_wink,
03537    .new_ast_channel = my_new_analog_ast_channel,
03538    .dsp_set_digitmode = my_dsp_set_digitmode,
03539    .dsp_reset_and_flush_digits = my_dsp_reset_and_flush_digits,
03540    .send_callerid = my_send_callerid,
03541    .callwait = my_callwait,
03542    .stop_callwait = my_stop_callwait,
03543    .get_callerid = my_get_callerid,
03544    .start_cid_detect = my_start_cid_detect,
03545    .stop_cid_detect = my_stop_cid_detect,
03546    .handle_notify_message = my_handle_notify_message,
03547    .increase_ss_count = my_increase_ss_count,
03548    .decrease_ss_count = my_decrease_ss_count,
03549    .distinctive_ring = my_distinctive_ring,
03550    .set_linear_mode = my_set_linear_mode,
03551    .set_inthreeway = my_set_inthreeway,
03552    .get_and_handle_alarms = my_get_and_handle_alarms,
03553    .get_sigpvt_bridged_channel = my_get_sigpvt_bridged_channel,
03554    .get_sub_fd = my_get_sub_fd,
03555    .set_cadence = my_set_cadence,
03556    .set_alarm = my_set_alarm,
03557    .set_dialing = my_set_dialing,
03558    .set_ringtimeout = my_set_ringtimeout,
03559    .set_waitingfordt = my_set_waitingfordt,
03560    .check_waitingfordt = my_check_waitingfordt,
03561    .set_confirmanswer = my_set_confirmanswer,
03562    .check_confirmanswer = my_check_confirmanswer,
03563    .set_callwaiting = my_set_callwaiting,
03564    .cancel_cidspill = my_cancel_cidspill,
03565    .confmute = my_confmute,
03566    .set_pulsedial = my_set_pulsedial,
03567    .set_new_owner = my_set_new_owner,
03568    .get_orig_dialstring = my_get_orig_dialstring,
03569    .set_needringing = my_set_needringing,
03570    .set_polarity = my_set_polarity,
03571    .start_polarityswitch = my_start_polarityswitch,
03572    .answer_polarityswitch = my_answer_polarityswitch,
03573    .hangup_polarityswitch = my_hangup_polarityswitch,
03574 };
03575 
03576 /*! Round robin search locations. */
03577 static struct dahdi_pvt *round_robin[32];
03578 
03579 #define dahdi_get_index(ast, p, nullok)   _dahdi_get_index(ast, p, nullok, __PRETTY_FUNCTION__, __LINE__)
03580 static int _dahdi_get_index(struct ast_channel *ast, struct dahdi_pvt *p, int nullok, const char *fname, unsigned long line)
03581 {
03582    int res;
03583    if (p->subs[SUB_REAL].owner == ast)
03584       res = 0;
03585    else if (p->subs[SUB_CALLWAIT].owner == ast)
03586       res = 1;
03587    else if (p->subs[SUB_THREEWAY].owner == ast)
03588       res = 2;
03589    else {
03590       res = -1;
03591       if (!nullok)
03592          ast_log(LOG_WARNING,
03593             "Unable to get index for '%s' on channel %d (%s(), line %lu)\n",
03594             ast ? ast->name : "", p->channel, fname, line);
03595    }
03596    return res;
03597 }
03598 
03599 /*!
03600  * \internal
03601  * \brief Obtain the specified subchannel owner lock if the owner exists.
03602  *
03603  * \param pvt Channel private struct.
03604  * \param sub_idx Subchannel owner to lock.
03605  *
03606  * \note Assumes the pvt->lock is already obtained.
03607  *
03608  * \note
03609  * Because deadlock avoidance may have been necessary, you need to confirm
03610  * the state of things before continuing.
03611  *
03612  * \return Nothing
03613  */
03614 static void dahdi_lock_sub_owner(struct dahdi_pvt *pvt, int sub_idx)
03615 {
03616    for (;;) {
03617       if (!pvt->subs[sub_idx].owner) {
03618          /* No subchannel owner pointer */
03619          break;
03620       }
03621       if (!ast_channel_trylock(pvt->subs[sub_idx].owner)) {
03622          /* Got subchannel owner lock */
03623          break;
03624       }
03625       /* We must unlock the private to avoid the possibility of a deadlock */
03626       DEADLOCK_AVOIDANCE(&pvt->lock);
03627    }
03628 }
03629 
03630 static void wakeup_sub(struct dahdi_pvt *p, int a)
03631 {
03632    dahdi_lock_sub_owner(p, a);
03633    if (p->subs[a].owner) {
03634       ast_queue_frame(p->subs[a].owner, &ast_null_frame);
03635       ast_channel_unlock(p->subs[a].owner);
03636    }
03637 }
03638 
03639 static void dahdi_queue_frame(struct dahdi_pvt *p, struct ast_frame *f)
03640 {
03641    for (;;) {
03642       if (p->owner) {
03643          if (ast_channel_trylock(p->owner)) {
03644             DEADLOCK_AVOIDANCE(&p->lock);
03645          } else {
03646             ast_queue_frame(p->owner, f);
03647             ast_channel_unlock(p->owner);
03648             break;
03649          }
03650       } else
03651          break;
03652    }
03653 }
03654 
03655 static void handle_clear_alarms(struct dahdi_pvt *p)
03656 {
03657    if (report_alarms & REPORT_CHANNEL_ALARMS) {
03658       ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel);
03659       manager_event(EVENT_FLAG_SYSTEM, "AlarmClear", "Channel: %d\r\n", p->channel);
03660    }
03661    if (report_alarms & REPORT_SPAN_ALARMS && p->manages_span_alarms) {
03662       ast_log(LOG_NOTICE, "Alarm cleared on span %d\n", p->span);
03663       manager_event(EVENT_FLAG_SYSTEM, "SpanAlarmClear", "Span: %d\r\n", p->span);
03664    }
03665 }
03666 
03667 #ifdef HAVE_OPENR2
03668 
03669 static int dahdi_r2_answer(struct dahdi_pvt *p)
03670 {
03671    int res = 0;
03672    /* openr2 1.1.0 and older does not even define OR2_LIB_INTERFACE
03673    * and does not has support for openr2_chan_answer_call_with_mode
03674    *  */
03675 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
03676    const char *double_answer = pbx_builtin_getvar_helper(p->owner, "MFCR2_DOUBLE_ANSWER");
03677    int wants_double_answer = ast_true(double_answer) ? 1 : 0;
03678    if (!double_answer) {
03679       /* this still can result in double answer if the channel context
03680       * was configured that way */
03681       res = openr2_chan_answer_call(p->r2chan);
03682    } else if (wants_double_answer) {
03683       res = openr2_chan_answer_call_with_mode(p->r2chan, OR2_ANSWER_DOUBLE);
03684    } else {
03685       res = openr2_chan_answer_call_with_mode(p->r2chan, OR2_ANSWER_SIMPLE);
03686    }
03687 #else
03688    res = openr2_chan_answer_call(p->r2chan);
03689 #endif
03690    return res;
03691 }
03692 
03693 
03694 
03695 /* should be called with the ast_channel locked */
03696 static openr2_calling_party_category_t dahdi_r2_get_channel_category(struct ast_channel *c)
03697 {
03698    openr2_calling_party_category_t cat;
03699    const char *catstr = pbx_builtin_getvar_helper(c, "MFCR2_CATEGORY");
03700    struct dahdi_pvt *p = c->tech_pvt;
03701    if (ast_strlen_zero(catstr)) {
03702       ast_debug(1, "No MFC/R2 category specified for chan %s, using default %s\n",
03703             c->name, openr2_proto_get_category_string(p->mfcr2_category));
03704       return p->mfcr2_category;
03705    }
03706    if ((cat = openr2_proto_get_category(catstr)) == OR2_CALLING_PARTY_CATEGORY_UNKNOWN) {
03707       ast_log(LOG_WARNING, "Invalid category specified '%s' for chan %s, using default %s\n",
03708             catstr, c->name, openr2_proto_get_category_string(p->mfcr2_category));
03709       return p->mfcr2_category;
03710    }
03711    ast_debug(1, "Using category %s\n", catstr);
03712    return cat;
03713 }
03714 
03715 static void dahdi_r2_on_call_init(openr2_chan_t *r2chan)
03716 {
03717    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
03718    ast_mutex_lock(&p->lock);
03719    if (p->mfcr2call) {
03720       ast_mutex_unlock(&p->lock);
03721       /* TODO: This can happen when some other thread just finished dahdi_request requesting this very same
03722          interface but has not yet seized the line (dahdi_call), and the far end wins and seize the line,
03723          can we avoid this somehow?, at this point when dahdi_call send the seize, it is likely that since
03724          the other end will see our seize as a forced release and drop the call, we will see an invalid
03725          pattern that will be seen and treated as protocol error. */
03726       ast_log(LOG_ERROR, "Collision of calls on chan %d detected!.\n", openr2_chan_get_number(r2chan));
03727       return;
03728    }
03729    p->mfcr2call = 1;
03730    /* better safe than sorry ... */
03731    p->cid_name[0] = '\0';
03732    p->cid_num[0] = '\0';
03733    p->cid_subaddr[0] = '\0';
03734    p->rdnis[0] = '\0';
03735    p->exten[0] = '\0';
03736    p->mfcr2_ani_index = '\0';
03737    p->mfcr2_dnis_index = '\0';
03738    p->mfcr2_dnis_matched = 0;
03739    p->mfcr2_answer_pending = 0;
03740    p->mfcr2_call_accepted = 0;
03741    ast_mutex_unlock(&p->lock);
03742    ast_verbose("New MFC/R2 call detected on chan %d.\n", openr2_chan_get_number(r2chan));
03743 }
03744 
03745 static void dahdi_r2_on_hardware_alarm(openr2_chan_t *r2chan, int alarm)
03746 {
03747    int res;
03748    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
03749    ast_mutex_lock(&p->lock);
03750    p->inalarm = alarm ? 1 : 0;
03751    if (p->inalarm) {
03752       res = get_alarms(p);
03753       handle_alarms(p, res);
03754    } else {
03755       handle_clear_alarms(p);
03756    }
03757    ast_mutex_unlock(&p->lock);
03758 }
03759 
03760 static void dahdi_r2_on_os_error(openr2_chan_t *r2chan, int errorcode)
03761 {
03762    ast_log(LOG_ERROR, "OS error on chan %d: %s\n", openr2_chan_get_number(r2chan), strerror(errorcode));
03763 }
03764 
03765 static void dahdi_r2_on_protocol_error(openr2_chan_t *r2chan, openr2_protocol_error_t reason)
03766 {
03767    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
03768    ast_log(LOG_ERROR, "MFC/R2 protocol error on chan %d: %s\n", openr2_chan_get_number(r2chan), openr2_proto_get_error(reason));
03769    if (p->owner) {
03770       p->owner->hangupcause = AST_CAUSE_PROTOCOL_ERROR;
03771       p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
03772    }
03773    ast_mutex_lock(&p->lock);
03774    p->mfcr2call = 0;
03775    ast_mutex_unlock(&p->lock);
03776 }
03777 
03778 static void dahdi_r2_disconnect_call(struct dahdi_pvt *p, openr2_call_disconnect_cause_t cause)
03779 {
03780    if (openr2_chan_disconnect_call(p->r2chan, cause)) {
03781       ast_log(LOG_NOTICE, "Bad! failed to disconnect call on channel %d with reason %s, hope for the best!\n",
03782          p->channel, openr2_proto_get_disconnect_string(cause));
03783       /* force the chan to idle and release the call flag now since we will not see a clean on_call_end */
03784       openr2_chan_set_idle(p->r2chan);
03785       ast_mutex_lock(&p->lock);
03786       p->mfcr2call = 0;
03787       ast_mutex_unlock(&p->lock);
03788    }
03789 }
03790 
03791 static void dahdi_r2_on_call_offered(openr2_chan_t *r2chan, const char *ani, const char *dnis, openr2_calling_party_category_t category)
03792 {
03793    struct dahdi_pvt *p;
03794    struct ast_channel *c;
03795    ast_verbose("MFC/R2 call offered on chan %d. ANI = %s, DNIS = %s, Category = %s\n",
03796          openr2_chan_get_number(r2chan), ani ? ani : "(restricted)", dnis,
03797          openr2_proto_get_category_string(category));
03798    p = openr2_chan_get_client_data(r2chan);
03799    /* if collect calls are not allowed and this is a collect call, reject it! */
03800    if (!p->mfcr2_allow_collect_calls && category == OR2_CALLING_PARTY_CATEGORY_COLLECT_CALL) {
03801       ast_log(LOG_NOTICE, "Rejecting MFC/R2 collect call\n");
03802       dahdi_r2_disconnect_call(p, OR2_CAUSE_COLLECT_CALL_REJECTED);
03803       return;
03804    }
03805    ast_mutex_lock(&p->lock);
03806    p->mfcr2_recvd_category = category;
03807    /* if we're not supposed to use CID, clear whatever we have */
03808    if (!p->use_callerid) {
03809       ast_log(LOG_DEBUG, "No CID allowed in configuration, CID is being cleared!\n");
03810       p->cid_num[0] = 0;
03811       p->cid_name[0] = 0;
03812    }
03813    /* if we're supposed to answer immediately, clear DNIS and set 's' exten */
03814    if (p->immediate || !openr2_context_get_max_dnis(openr2_chan_get_context(r2chan))) {
03815       ast_log(LOG_DEBUG, "Setting exten => s because of immediate or 0 DNIS configured\n");
03816       p->exten[0] = 's';
03817       p->exten[1] = 0;
03818    }
03819    ast_mutex_unlock(&p->lock);
03820    if (!ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
03821       ast_log(LOG_NOTICE, "MFC/R2 call on channel %d requested non-existent extension '%s' in context '%s'. Rejecting call.\n",
03822             p->channel, p->exten, p->context);
03823       dahdi_r2_disconnect_call(p, OR2_CAUSE_UNALLOCATED_NUMBER);
03824       return;
03825    }
03826    if (!p->mfcr2_accept_on_offer) {
03827       /* The user wants us to start the PBX thread right away without accepting the call first */
03828       c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, NULL);
03829       if (c) {
03830          /* Done here, don't disable reading now since we still need to generate MF tones to accept
03831             the call or reject it and detect the tone off condition of the other end, all of this
03832             will be done in the PBX thread now */
03833          return;
03834       }
03835       ast_log(LOG_WARNING, "Unable to create PBX channel in DAHDI channel %d\n", p->channel);
03836       dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER);
03837    } else if (p->mfcr2_charge_calls) {
03838       ast_log(LOG_DEBUG, "Accepting MFC/R2 call with charge on chan %d\n", p->channel);
03839       openr2_chan_accept_call(r2chan, OR2_CALL_WITH_CHARGE);
03840    } else {
03841       ast_log(LOG_DEBUG, "Accepting MFC/R2 call with no charge on chan %d\n", p->channel);
03842       openr2_chan_accept_call(r2chan, OR2_CALL_NO_CHARGE);
03843    }
03844 }
03845 
03846 static void dahdi_r2_on_call_end(openr2_chan_t *r2chan)
03847 {
03848    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
03849    ast_verbose("MFC/R2 call end on channel %d\n", p->channel);
03850    ast_mutex_lock(&p->lock);
03851    p->mfcr2call = 0;
03852    ast_mutex_unlock(&p->lock);
03853 }
03854 
03855 static void dahdi_enable_ec(struct dahdi_pvt *p);
03856 static void dahdi_r2_on_call_accepted(openr2_chan_t *r2chan, openr2_call_mode_t mode)
03857 {
03858    struct dahdi_pvt *p = NULL;
03859    struct ast_channel *c = NULL;
03860    p = openr2_chan_get_client_data(r2chan);
03861    dahdi_enable_ec(p);
03862    p->mfcr2_call_accepted = 1;
03863    /* if it's an incoming call ... */
03864    if (OR2_DIR_BACKWARD == openr2_chan_get_direction(r2chan)) {
03865       ast_verbose("MFC/R2 call has been accepted on backward channel %d\n", openr2_chan_get_number(r2chan));
03866       /* If accept on offer is not set, it means at this point the PBX thread is already
03867          launched (was launched in the 'on call offered' handler) and therefore this callback
03868          is being executed already in the PBX thread rather than the monitor thread, don't launch
03869          any other thread, just disable the openr2 reading and answer the call if needed */
03870       if (!p->mfcr2_accept_on_offer) {
03871          openr2_chan_disable_read(r2chan);
03872          if (p->mfcr2_answer_pending) {
03873             ast_log(LOG_DEBUG, "Answering MFC/R2 call after accepting it on chan %d\n", openr2_chan_get_number(r2chan));
03874             dahdi_r2_answer(p);
03875          }
03876          return;
03877       }
03878       c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, NULL);
03879       if (c) {
03880          /* chan_dahdi will take care of reading from now on in the PBX thread, tell the
03881             library to forget about it */
03882          openr2_chan_disable_read(r2chan);
03883          return;
03884       }
03885       ast_log(LOG_WARNING, "Unable to create PBX channel in DAHDI channel %d\n", p->channel);
03886       /* failed to create the channel, bail out and report it as an out of order line */
03887       dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER);
03888       return;
03889    }
03890    /* this is an outgoing call, no need to launch the PBX thread, most likely we're in one already */
03891    ast_verbose("MFC/R2 call has been accepted on forward channel %d\n", p->channel);
03892    p->subs[SUB_REAL].needringing = 1;
03893    p->dialing = 0;
03894    /* chan_dahdi will take care of reading from now on in the PBX thread, tell the library to forget about it */
03895    openr2_chan_disable_read(r2chan);
03896 }
03897 
03898 static void dahdi_r2_on_call_answered(openr2_chan_t *r2chan)
03899 {
03900    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
03901    ast_verbose("MFC/R2 call has been answered on channel %d\n", openr2_chan_get_number(r2chan));
03902    p->subs[SUB_REAL].needanswer = 1;
03903 }
03904 
03905 static void dahdi_r2_on_call_read(openr2_chan_t *r2chan, const unsigned char *buf, int buflen)
03906 {
03907    /*ast_log(LOG_DEBUG, "Read data from dahdi channel %d\n", openr2_chan_get_number(r2chan));*/
03908 }
03909 
03910 static int dahdi_r2_cause_to_ast_cause(openr2_call_disconnect_cause_t cause)
03911 {
03912    switch (cause) {
03913    case OR2_CAUSE_BUSY_NUMBER:
03914       return AST_CAUSE_BUSY;
03915    case OR2_CAUSE_NETWORK_CONGESTION:
03916       return AST_CAUSE_CONGESTION;
03917    case OR2_CAUSE_OUT_OF_ORDER:
03918       return AST_CAUSE_DESTINATION_OUT_OF_ORDER;
03919    case OR2_CAUSE_UNALLOCATED_NUMBER:
03920       return AST_CAUSE_UNREGISTERED;
03921    case OR2_CAUSE_NO_ANSWER:
03922       return AST_CAUSE_NO_ANSWER;
03923    case OR2_CAUSE_NORMAL_CLEARING:
03924       return AST_CAUSE_NORMAL_CLEARING;
03925    case OR2_CAUSE_UNSPECIFIED:
03926    default:
03927       return AST_CAUSE_NOTDEFINED;
03928    }
03929 }
03930 
03931 static void dahdi_r2_on_call_disconnect(openr2_chan_t *r2chan, openr2_call_disconnect_cause_t cause)
03932 {
03933    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
03934    ast_verbose("MFC/R2 call disconnected on channel %d\n", openr2_chan_get_number(r2chan));
03935    ast_mutex_lock(&p->lock);
03936    if (!p->owner) {
03937       ast_mutex_unlock(&p->lock);
03938       /* no owner, therefore we can't use dahdi_hangup to disconnect, do it right now */
03939       dahdi_r2_disconnect_call(p, OR2_CAUSE_NORMAL_CLEARING);
03940       return;
03941    }
03942    /* when we have an owner we don't call dahdi_r2_disconnect_call here, that will
03943       be done in dahdi_hangup */
03944    if (p->owner->_state == AST_STATE_UP) {
03945       p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
03946       ast_mutex_unlock(&p->lock);
03947    } else if (openr2_chan_get_direction(r2chan) == OR2_DIR_FORWARD) {
03948       /* being the forward side we must report what happened to the call to whoever requested it */
03949       switch (cause) {
03950       case OR2_CAUSE_BUSY_NUMBER:
03951          p->subs[SUB_REAL].needbusy = 1;
03952          break;
03953       case OR2_CAUSE_NETWORK_CONGESTION:
03954       case OR2_CAUSE_OUT_OF_ORDER:
03955       case OR2_CAUSE_UNALLOCATED_NUMBER:
03956       case OR2_CAUSE_NO_ANSWER:
03957       case OR2_CAUSE_UNSPECIFIED:
03958       case OR2_CAUSE_NORMAL_CLEARING:
03959          p->subs[SUB_REAL].needcongestion = 1;
03960          break;
03961       default:
03962          p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
03963       }
03964       ast_mutex_unlock(&p->lock);
03965    } else {
03966       ast_mutex_unlock(&p->lock);
03967       /* being the backward side and not UP yet, we only need to request hangup */
03968       /* TODO: what about doing this same thing when were AST_STATE_UP? */
03969       ast_queue_hangup_with_cause(p->owner, dahdi_r2_cause_to_ast_cause(cause));
03970    }
03971 }
03972 
03973 static void dahdi_r2_write_log(openr2_log_level_t level, char *logmessage)
03974 {
03975    switch (level) {
03976    case OR2_LOG_NOTICE:
03977       ast_verbose("%s", logmessage);
03978       break;
03979    case OR2_LOG_WARNING:
03980       ast_log(LOG_WARNING, "%s", logmessage);
03981       break;
03982    case OR2_LOG_ERROR:
03983       ast_log(LOG_ERROR, "%s", logmessage);
03984       break;
03985    case OR2_LOG_STACK_TRACE:
03986    case OR2_LOG_MF_TRACE:
03987    case OR2_LOG_CAS_TRACE:
03988    case OR2_LOG_DEBUG:
03989    case OR2_LOG_EX_DEBUG:
03990       ast_log(LOG_DEBUG, "%s", logmessage);
03991       break;
03992    default:
03993       ast_log(LOG_WARNING, "We should handle logging level %d here.\n", level);
03994       ast_log(LOG_DEBUG, "%s", logmessage);
03995       break;
03996    }
03997 }
03998 
03999 static void dahdi_r2_on_line_blocked(openr2_chan_t *r2chan)
04000 {
04001    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04002    ast_mutex_lock(&p->lock);
04003    p->remotelyblocked = 1;
04004    ast_mutex_unlock(&p->lock);
04005    ast_log(LOG_NOTICE, "Far end blocked on chan %d\n", openr2_chan_get_number(r2chan));
04006 }
04007 
04008 static void dahdi_r2_on_line_idle(openr2_chan_t *r2chan)
04009 {
04010    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04011    ast_mutex_lock(&p->lock);
04012    p->remotelyblocked = 0;
04013    ast_mutex_unlock(&p->lock);
04014    ast_log(LOG_NOTICE, "Far end unblocked on chan %d\n", openr2_chan_get_number(r2chan));
04015 }
04016 
04017 static void dahdi_r2_on_context_log(openr2_context_t *r2context, openr2_log_level_t level, const char *fmt, va_list ap)
04018    __attribute__((format (printf, 3, 0)));
04019 static void dahdi_r2_on_context_log(openr2_context_t *r2context, openr2_log_level_t level, const char *fmt, va_list ap)
04020 {
04021 #define CONTEXT_TAG "Context - "
04022    char logmsg[256];
04023    char completemsg[sizeof(logmsg) + sizeof(CONTEXT_TAG) - 1];
04024    vsnprintf(logmsg, sizeof(logmsg), fmt, ap);
04025    snprintf(completemsg, sizeof(completemsg), CONTEXT_TAG "%s", logmsg);
04026    dahdi_r2_write_log(level, completemsg);
04027 #undef CONTEXT_TAG
04028 }
04029 
04030 static void dahdi_r2_on_chan_log(openr2_chan_t *r2chan, openr2_log_level_t level, const char *fmt, va_list ap)
04031    __attribute__((format (printf, 3, 0)));
04032 static void dahdi_r2_on_chan_log(openr2_chan_t *r2chan, openr2_log_level_t level, const char *fmt, va_list ap)
04033 {
04034 #define CHAN_TAG "Chan "
04035    char logmsg[256];
04036    char completemsg[sizeof(logmsg) + sizeof(CHAN_TAG) - 1];
04037    vsnprintf(logmsg, sizeof(logmsg), fmt, ap);
04038    snprintf(completemsg, sizeof(completemsg), CHAN_TAG "%d - %s", openr2_chan_get_number(r2chan), logmsg);
04039    dahdi_r2_write_log(level, completemsg);
04040 }
04041 
04042 static int dahdi_r2_on_dnis_digit_received(openr2_chan_t *r2chan, char digit)
04043 {
04044    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04045    /* if 'immediate' is set, let's stop requesting DNIS */
04046    if (p->immediate) {
04047       return 0;
04048    }
04049    p->exten[p->mfcr2_dnis_index] = digit;
04050    p->rdnis[p->mfcr2_dnis_index] = digit;
04051    p->mfcr2_dnis_index++;
04052    p->exten[p->mfcr2_dnis_index] = 0;
04053    p->rdnis[p->mfcr2_dnis_index] = 0;
04054    /* if the DNIS is a match and cannot match more, stop requesting DNIS */
04055    if ((p->mfcr2_dnis_matched ||
04056        (ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num) && (p->mfcr2_dnis_matched = 1))) &&
04057        !ast_matchmore_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
04058       return 0;
04059    }
04060    /* otherwise keep going */
04061    return 1;
04062 }
04063 
04064 static void dahdi_r2_on_ani_digit_received(openr2_chan_t *r2chan, char digit)
04065 {
04066    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04067    p->cid_num[p->mfcr2_ani_index] = digit;
04068    p->cid_name[p->mfcr2_ani_index] = digit;
04069    p->mfcr2_ani_index++;
04070    p->cid_num[p->mfcr2_ani_index] = 0;
04071    p->cid_name[p->mfcr2_ani_index] = 0;
04072 }
04073 
04074 static void dahdi_r2_on_billing_pulse_received(openr2_chan_t *r2chan)
04075 {
04076    ast_verbose("MFC/R2 billing pulse received on channel %d\n", openr2_chan_get_number(r2chan));
04077 }
04078 
04079 static openr2_event_interface_t dahdi_r2_event_iface = {
04080    .on_call_init = dahdi_r2_on_call_init,
04081    .on_call_offered = dahdi_r2_on_call_offered,
04082    .on_call_accepted = dahdi_r2_on_call_accepted,
04083    .on_call_answered = dahdi_r2_on_call_answered,
04084    .on_call_disconnect = dahdi_r2_on_call_disconnect,
04085    .on_call_end = dahdi_r2_on_call_end,
04086    .on_call_read = dahdi_r2_on_call_read,
04087    .on_hardware_alarm = dahdi_r2_on_hardware_alarm,
04088    .on_os_error = dahdi_r2_on_os_error,
04089    .on_protocol_error = dahdi_r2_on_protocol_error,
04090    .on_line_blocked = dahdi_r2_on_line_blocked,
04091    .on_line_idle = dahdi_r2_on_line_idle,
04092    /* cast seems to be needed to get rid of the annoying warning regarding format attribute  */
04093    .on_context_log = (openr2_handle_context_logging_func)dahdi_r2_on_context_log,
04094    .on_dnis_digit_received = dahdi_r2_on_dnis_digit_received,
04095    .on_ani_digit_received = dahdi_r2_on_ani_digit_received,
04096    /* so far we do nothing with billing pulses */
04097    .on_billing_pulse_received = dahdi_r2_on_billing_pulse_received
04098 };
04099 
04100 static inline int16_t dahdi_r2_alaw_to_linear(uint8_t sample)
04101 {
04102    return AST_ALAW(sample);
04103 }
04104 
04105 static inline uint8_t dahdi_r2_linear_to_alaw(int sample)
04106 {
04107    return AST_LIN2A(sample);
04108 }
04109 
04110 static openr2_transcoder_interface_t dahdi_r2_transcode_iface = {
04111    dahdi_r2_alaw_to_linear,
04112    dahdi_r2_linear_to_alaw
04113 };
04114 
04115 #endif /* HAVE_OPENR2 */
04116 
04117 static void swap_subs(struct dahdi_pvt *p, int a, int b)
04118 {
04119    int tchan;
04120    int tinthreeway;
04121    struct ast_channel *towner;
04122 
04123    ast_debug(1, "Swapping %d and %d\n", a, b);
04124 
04125    tchan = p->subs[a].chan;
04126    towner = p->subs[a].owner;
04127    tinthreeway = p->subs[a].inthreeway;
04128 
04129    p->subs[a].chan = p->subs[b].chan;
04130    p->subs[a].owner = p->subs[b].owner;
04131    p->subs[a].inthreeway = p->subs[b].inthreeway;
04132 
04133    p->subs[b].chan = tchan;
04134    p->subs[b].owner = towner;
04135    p->subs[b].inthreeway = tinthreeway;
04136 
04137    if (p->subs[a].owner)
04138       ast_channel_set_fd(p->subs[a].owner, 0, p->subs[a].dfd);
04139    if (p->subs[b].owner)
04140       ast_channel_set_fd(p->subs[b].owner, 0, p->subs[b].dfd);
04141    wakeup_sub(p, a);
04142    wakeup_sub(p, b);
04143 }
04144 
04145 static int dahdi_open(char *fn)
04146 {
04147    int fd;
04148    int isnum;
04149    int chan = 0;
04150    int bs;
04151    int x;
04152    isnum = 1;
04153    for (x = 0; x < strlen(fn); x++) {
04154       if (!isdigit(fn[x])) {
04155          isnum = 0;
04156          break;
04157       }
04158    }
04159    if (isnum) {
04160       chan = atoi(fn);
04161       if (chan < 1) {
04162          ast_log(LOG_WARNING, "Invalid channel number '%s'\n", fn);
04163          return -1;
04164       }
04165       fn = "/dev/dahdi/channel";
04166    }
04167    fd = open(fn, O_RDWR | O_NONBLOCK);
04168    if (fd < 0) {
04169       ast_log(LOG_WARNING, "Unable to open '%s': %s\n", fn, strerror(errno));
04170       return -1;
04171    }
04172    if (chan) {
04173       if (ioctl(fd, DAHDI_SPECIFY, &chan)) {
04174          x = errno;
04175          close(fd);
04176          errno = x;
04177          ast_log(LOG_WARNING, "Unable to specify channel %d: %s\n", chan, strerror(errno));
04178          return -1;
04179       }
04180    }
04181    bs = READ_SIZE;
04182    if (ioctl(fd, DAHDI_SET_BLOCKSIZE, &bs) == -1) {
04183       ast_log(LOG_WARNING, "Unable to set blocksize '%d': %s\n", bs,  strerror(errno));
04184       x = errno;
04185       close(fd);
04186       errno = x;
04187       return -1;
04188    }
04189    return fd;
04190 }
04191 
04192 static void dahdi_close(int fd)
04193 {
04194    if (fd > 0)
04195       close(fd);
04196 }
04197 
04198 static void dahdi_close_sub(struct dahdi_pvt *chan_pvt, int sub_num)
04199 {
04200    dahdi_close(chan_pvt->subs[sub_num].dfd);
04201    chan_pvt->subs[sub_num].dfd = -1;
04202 }
04203 
04204 #if defined(HAVE_PRI)
04205 static void dahdi_close_pri_fd(struct dahdi_pri *pri, int fd_num)
04206 {
04207    dahdi_close(pri->pri.fds[fd_num]);
04208    pri->pri.fds[fd_num] = -1;
04209 }
04210 #endif   /* defined(HAVE_PRI) */
04211 
04212 #if defined(HAVE_SS7)
04213 static void dahdi_close_ss7_fd(struct dahdi_ss7 *ss7, int fd_num)
04214 {
04215    dahdi_close(ss7->ss7.fds[fd_num]);
04216    ss7->ss7.fds[fd_num] = -1;
04217 }
04218 #endif   /* defined(HAVE_SS7) */
04219 
04220 static int dahdi_setlinear(int dfd, int linear)
04221 {
04222    return ioctl(dfd, DAHDI_SETLINEAR, &linear);
04223 }
04224 
04225 
04226 static int alloc_sub(struct dahdi_pvt *p, int x)
04227 {
04228    struct dahdi_bufferinfo bi;
04229    int res;
04230    if (p->subs[x].dfd >= 0) {
04231       ast_log(LOG_WARNING, "%s subchannel of %d already in use\n", subnames[x], p->channel);
04232       return -1;
04233    }
04234 
04235    p->subs[x].dfd = dahdi_open("/dev/dahdi/pseudo");
04236    if (p->subs[x].dfd <= -1) {
04237       ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno));
04238       return -1;
04239    }
04240 
04241    res = ioctl(p->subs[x].dfd, DAHDI_GET_BUFINFO, &bi);
04242    if (!res) {
04243       bi.txbufpolicy = p->buf_policy;
04244       bi.rxbufpolicy = p->buf_policy;
04245       bi.numbufs = p->buf_no;
04246       res = ioctl(p->subs[x].dfd, DAHDI_SET_BUFINFO, &bi);
04247       if (res < 0) {
04248          ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", x, strerror(errno));
04249       }
04250    } else
04251       ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", x, strerror(errno));
04252 
04253    if (ioctl(p->subs[x].dfd, DAHDI_CHANNO, &p->subs[x].chan) == 1) {
04254       ast_log(LOG_WARNING, "Unable to get channel number for pseudo channel on FD %d: %s\n", p->subs[x].dfd, strerror(errno));
04255       dahdi_close_sub(p, x);
04256       p->subs[x].dfd = -1;
04257       return -1;
04258    }
04259    ast_debug(1, "Allocated %s subchannel on FD %d channel %d\n", subnames[x], p->subs[x].dfd, p->subs[x].chan);
04260    return 0;
04261 }
04262 
04263 static int unalloc_sub(struct dahdi_pvt *p, int x)
04264 {
04265    if (!x) {
04266       ast_log(LOG_WARNING, "Trying to unalloc the real channel %d?!?\n", p->channel);
04267       return -1;
04268    }
04269    ast_debug(1, "Released sub %d of channel %d\n", x, p->channel);
04270    dahdi_close_sub(p, x);
04271    p->subs[x].linear = 0;
04272    p->subs[x].chan = 0;
04273    p->subs[x].owner = NULL;
04274    p->subs[x].inthreeway = 0;
04275    p->polarity = POLARITY_IDLE;
04276    memset(&p->subs[x].curconf, 0, sizeof(p->subs[x].curconf));
04277    return 0;
04278 }
04279 
04280 static int digit_to_dtmfindex(char digit)
04281 {
04282    if (isdigit(digit))
04283       return DAHDI_TONE_DTMF_BASE + (digit - '0');
04284    else if (digit >= 'A' && digit <= 'D')
04285       return DAHDI_TONE_DTMF_A + (digit - 'A');
04286    else if (digit >= 'a' && digit <= 'd')
04287       return DAHDI_TONE_DTMF_A + (digit - 'a');
04288    else if (digit == '*')
04289       return DAHDI_TONE_DTMF_s;
04290    else if (digit == '#')
04291       return DAHDI_TONE_DTMF_p;
04292    else
04293       return -1;
04294 }
04295 
04296 static int dahdi_digit_begin(struct ast_channel *chan, char digit)
04297 {
04298    struct dahdi_pvt *pvt;
04299    int idx;
04300    int dtmf = -1;
04301    int res;
04302 
04303    pvt = chan->tech_pvt;
04304 
04305    ast_mutex_lock(&pvt->lock);
04306 
04307    idx = dahdi_get_index(chan, pvt, 0);
04308 
04309    if ((idx != SUB_REAL) || !pvt->owner)
04310       goto out;
04311 
04312 #ifdef HAVE_PRI
04313    switch (pvt->sig) {
04314    case SIG_PRI_LIB_HANDLE_CASES:
04315       res = sig_pri_digit_begin(pvt->sig_pvt, chan, digit);
04316       if (!res)
04317          goto out;
04318       break;
04319    default:
04320       break;
04321    }
04322 #endif
04323    if ((dtmf = digit_to_dtmfindex(digit)) == -1)
04324       goto out;
04325 
04326    if (pvt->pulse || ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &dtmf)) {
04327       struct dahdi_dialoperation zo = {
04328          .op = DAHDI_DIAL_OP_APPEND,
04329       };
04330 
04331       zo.dialstr[0] = 'T';
04332       zo.dialstr[1] = digit;
04333       zo.dialstr[2] = '\0';
04334       if ((res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo)))
04335          ast_log(LOG_WARNING, "Couldn't dial digit %c: %s\n", digit, strerror(errno));
04336       else
04337          pvt->dialing = 1;
04338    } else {
04339       ast_debug(1, "Started VLDTMF digit '%c'\n", digit);
04340       pvt->dialing = 1;
04341       pvt->begindigit = digit;
04342    }
04343 
04344 out:
04345    ast_mutex_unlock(&pvt->lock);
04346 
04347    return 0;
04348 }
04349 
04350 static int dahdi_digit_end(struct ast_channel *chan, char digit, unsigned int duration)
04351 {
04352    struct dahdi_pvt *pvt;
04353    int res = 0;
04354    int idx;
04355    int x;
04356 
04357    pvt = chan->tech_pvt;
04358 
04359    ast_mutex_lock(&pvt->lock);
04360 
04361    idx = dahdi_get_index(chan, pvt, 0);
04362 
04363    if ((idx != SUB_REAL) || !pvt->owner || pvt->pulse)
04364       goto out;
04365 
04366 #ifdef HAVE_PRI
04367    /* This means that the digit was already sent via PRI signalling */
04368    if (dahdi_sig_pri_lib_handles(pvt->sig) && !pvt->begindigit) {
04369       goto out;
04370    }
04371 #endif
04372 
04373    if (pvt->begindigit) {
04374       x = -1;
04375       ast_debug(1, "Ending VLDTMF digit '%c'\n", digit);
04376       res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &x);
04377       pvt->dialing = 0;
04378       pvt->begindigit = 0;
04379    }
04380 
04381 out:
04382    ast_mutex_unlock(&pvt->lock);
04383 
04384    return res;
04385 }
04386 
04387 static const char * const events[] = {
04388    "No event",
04389    "On hook",
04390    "Ring/Answered",
04391    "Wink/Flash",
04392    "Alarm",
04393    "No more alarm",
04394    "HDLC Abort",
04395    "HDLC Overrun",
04396    "HDLC Bad FCS",
04397    "Dial Complete",
04398    "Ringer On",
04399    "Ringer Off",
04400    "Hook Transition Complete",
04401    "Bits Changed",
04402    "Pulse Start",
04403    "Timer Expired",
04404    "Timer Ping",
04405    "Polarity Reversal",
04406    "Ring Begin",
04407 };
04408 
04409 static struct {
04410    int alarm;
04411    char *name;
04412 } alarms[] = {
04413    { DAHDI_ALARM_RED, "Red Alarm" },
04414    { DAHDI_ALARM_YELLOW, "Yellow Alarm" },
04415    { DAHDI_ALARM_BLUE, "Blue Alarm" },
04416    { DAHDI_ALARM_RECOVER, "Recovering" },
04417    { DAHDI_ALARM_LOOPBACK, "Loopback" },
04418    { DAHDI_ALARM_NOTOPEN, "Not Open" },
04419    { DAHDI_ALARM_NONE, "None" },
04420 };
04421 
04422 static char *alarm2str(int alm)
04423 {
04424    int x;
04425    for (x = 0; x < ARRAY_LEN(alarms); x++) {
04426       if (alarms[x].alarm & alm)
04427          return alarms[x].name;
04428    }
04429    return alm ? "Unknown Alarm" : "No Alarm";
04430 }
04431 
04432 static const char *event2str(int event)
04433 {
04434    static char buf[256];
04435    if ((event < (ARRAY_LEN(events))) && (event > -1))
04436       return events[event];
04437    sprintf(buf, "Event %d", event); /* safe */
04438    return buf;
04439 }
04440 
04441 static char *dahdi_sig2str(int sig)
04442 {
04443    static char buf[256];
04444    switch (sig) {
04445    case SIG_EM:
04446       return "E & M Immediate";
04447    case SIG_EMWINK:
04448       return "E & M Wink";
04449    case SIG_EM_E1:
04450       return "E & M E1";
04451    case SIG_FEATD:
04452       return "Feature Group D (DTMF)";
04453    case SIG_FEATDMF:
04454       return "Feature Group D (MF)";
04455    case SIG_FEATDMF_TA:
04456       return "Feature Groud D (MF) Tandem Access";
04457    case SIG_FEATB:
04458       return "Feature Group B (MF)";
04459    case SIG_E911:
04460       return "E911 (MF)";
04461    case SIG_FGC_CAMA:
04462       return "FGC/CAMA (Dialpulse)";
04463    case SIG_FGC_CAMAMF:
04464       return "FGC/CAMA (MF)";
04465    case SIG_FXSLS:
04466       return "FXS Loopstart";
04467    case SIG_FXSGS:
04468       return "FXS Groundstart";
04469    case SIG_FXSKS:
04470       return "FXS Kewlstart";
04471    case SIG_FXOLS:
04472       return "FXO Loopstart";
04473    case SIG_FXOGS:
04474       return "FXO Groundstart";
04475    case SIG_FXOKS:
04476       return "FXO Kewlstart";
04477    case SIG_PRI:
04478       return "ISDN PRI";
04479    case SIG_BRI:
04480       return "ISDN BRI Point to Point";
04481    case SIG_BRI_PTMP:
04482       return "ISDN BRI Point to MultiPoint";
04483    case SIG_SS7:
04484       return "SS7";
04485    case SIG_MFCR2:
04486       return "MFC/R2";
04487    case SIG_SF:
04488       return "SF (Tone) Immediate";
04489    case SIG_SFWINK:
04490       return "SF (Tone) Wink";
04491    case SIG_SF_FEATD:
04492       return "SF (Tone) with Feature Group D (DTMF)";
04493    case SIG_SF_FEATDMF:
04494       return "SF (Tone) with Feature Group D (MF)";
04495    case SIG_SF_FEATB:
04496       return "SF (Tone) with Feature Group B (MF)";
04497    case 0:
04498       return "Pseudo";
04499    default:
04500       snprintf(buf, sizeof(buf), "Unknown signalling %d", sig);
04501       return buf;
04502    }
04503 }
04504 
04505 #define sig2str dahdi_sig2str
04506 
04507 static int analog_lib_handles(int signalling, int radio, int oprmode)
04508 {
04509    switch (signalling) {
04510    case SIG_FXOLS:
04511    case SIG_FXOGS:
04512    case SIG_FXOKS:
04513    case SIG_FXSLS:
04514    case SIG_FXSGS:
04515    case SIG_FXSKS:
04516    case SIG_EMWINK:
04517    case SIG_EM:
04518    case SIG_EM_E1:
04519    case SIG_FEATD:
04520    case SIG_FEATDMF:
04521    case SIG_E911:
04522    case SIG_FGC_CAMA:
04523    case SIG_FGC_CAMAMF:
04524    case SIG_FEATB:
04525    case SIG_SFWINK:
04526    case SIG_SF:
04527    case SIG_SF_FEATD:
04528    case SIG_SF_FEATDMF:
04529    case SIG_FEATDMF_TA:
04530    case SIG_SF_FEATB:
04531       break;
04532    default:
04533       /* The rest of the function should cover the remainder of signalling types */
04534       return 0;
04535    }
04536 
04537    if (radio)
04538       return 0;
04539 
04540    if (oprmode)
04541       return 0;
04542 
04543    return 1;
04544 }
04545 
04546 static int conf_add(struct dahdi_pvt *p, struct dahdi_subchannel *c, int idx, int slavechannel)
04547 {
04548    /* If the conference already exists, and we're already in it
04549       don't bother doing anything */
04550    struct dahdi_confinfo zi;
04551 
04552    memset(&zi, 0, sizeof(zi));
04553    zi.chan = 0;
04554 
04555    if (slavechannel > 0) {
04556       /* If we have only one slave, do a digital mon */
04557       zi.confmode = DAHDI_CONF_DIGITALMON;
04558       zi.confno = slavechannel;
04559    } else {
04560       if (!idx) {
04561          /* Real-side and pseudo-side both participate in conference */
04562          zi.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER |
04563             DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER;
04564       } else
04565          zi.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER;
04566       zi.confno = p->confno;
04567    }
04568    if ((zi.confno == c->curconf.confno) && (zi.confmode == c->curconf.confmode))
04569       return 0;
04570    if (c->dfd < 0)
04571       return 0;
04572    if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
04573       ast_log(LOG_WARNING, "Failed to add %d to conference %d/%d: %s\n", c->dfd, zi.confmode, zi.confno, strerror(errno));
04574       return -1;
04575    }
04576    if (slavechannel < 1) {
04577       p->confno = zi.confno;
04578    }
04579    c->curconf = zi;
04580    ast_debug(1, "Added %d to conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
04581    return 0;
04582 }
04583 
04584 static int isourconf(struct dahdi_pvt *p, struct dahdi_subchannel *c)
04585 {
04586    /* If they're listening to our channel, they're ours */
04587    if ((p->channel == c->curconf.confno) && (c->curconf.confmode == DAHDI_CONF_DIGITALMON))
04588       return 1;
04589    /* If they're a talker on our (allocated) conference, they're ours */
04590    if ((p->confno > 0) && (p->confno == c->curconf.confno) && (c->curconf.confmode & DAHDI_CONF_TALKER))
04591       return 1;
04592    return 0;
04593 }
04594 
04595 static int conf_del(struct dahdi_pvt *p, struct dahdi_subchannel *c, int idx)
04596 {
04597    struct dahdi_confinfo zi;
04598    if (/* Can't delete if there's no dfd */
04599       (c->dfd < 0) ||
04600       /* Don't delete from the conference if it's not our conference */
04601       !isourconf(p, c)
04602       /* Don't delete if we don't think it's conferenced at all (implied) */
04603       ) return 0;
04604    memset(&zi, 0, sizeof(zi));
04605    if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
04606       ast_log(LOG_WARNING, "Failed to drop %d from conference %d/%d: %s\n", c->dfd, c->curconf.confmode, c->curconf.confno, strerror(errno));
04607       return -1;
04608    }
04609    ast_debug(1, "Removed %d from conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
04610    memcpy(&c->curconf, &zi, sizeof(c->curconf));
04611    return 0;
04612 }
04613 
04614 static int isslavenative(struct dahdi_pvt *p, struct dahdi_pvt **out)
04615 {
04616    int x;
04617    int useslavenative;
04618    struct dahdi_pvt *slave = NULL;
04619    /* Start out optimistic */
04620    useslavenative = 1;
04621    /* Update conference state in a stateless fashion */
04622    for (x = 0; x < 3; x++) {
04623       /* Any three-way calling makes slave native mode *definitely* out
04624          of the question */
04625       if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway)
04626          useslavenative = 0;
04627    }
04628    /* If we don't have any 3-way calls, check to see if we have
04629       precisely one slave */
04630    if (useslavenative) {
04631       for (x = 0; x < MAX_SLAVES; x++) {
04632          if (p->slaves[x]) {
04633             if (slave) {
04634                /* Whoops already have a slave!  No
04635                   slave native and stop right away */
04636                slave = NULL;
04637                useslavenative = 0;
04638                break;
04639             } else {
04640                /* We have one slave so far */
04641                slave = p->slaves[x];
04642             }
04643          }
04644       }
04645    }
04646    /* If no slave, slave native definitely out */
04647    if (!slave)
04648       useslavenative = 0;
04649    else if (slave->law != p->law) {
04650       useslavenative = 0;
04651       slave = NULL;
04652    }
04653    if (out)
04654       *out = slave;
04655    return useslavenative;
04656 }
04657 
04658 static int reset_conf(struct dahdi_pvt *p)
04659 {
04660    p->confno = -1;
04661    memset(&p->subs[SUB_REAL].curconf, 0, sizeof(p->subs[SUB_REAL].curconf));
04662    if (p->subs[SUB_REAL].dfd > -1) {
04663       struct dahdi_confinfo zi;
04664 
04665       memset(&zi, 0, sizeof(zi));
04666       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &zi))
04667          ast_log(LOG_WARNING, "Failed to reset conferencing on channel %d: %s\n", p->channel, strerror(errno));
04668    }
04669    return 0;
04670 }
04671 
04672 static int update_conf(struct dahdi_pvt *p)
04673 {
04674    int needconf = 0;
04675    int x;
04676    int useslavenative;
04677    struct dahdi_pvt *slave = NULL;
04678 
04679    useslavenative = isslavenative(p, &slave);
04680    /* Start with the obvious, general stuff */
04681    for (x = 0; x < 3; x++) {
04682       /* Look for three way calls */
04683       if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) {
04684          conf_add(p, &p->subs[x], x, 0);
04685          needconf++;
04686       } else {
04687          conf_del(p, &p->subs[x], x);
04688       }
04689    }
04690    /* If we have a slave, add him to our conference now. or DAX
04691       if this is slave native */
04692    for (x = 0; x < MAX_SLAVES; x++) {
04693       if (p->slaves[x]) {
04694          if (useslavenative)
04695             conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
04696          else {
04697             conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
04698             needconf++;
04699          }
04700       }
04701    }
04702    /* If we're supposed to be in there, do so now */
04703    if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
04704       if (useslavenative)
04705          conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
04706       else {
04707          conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
04708          needconf++;
04709       }
04710    }
04711    /* If we have a master, add ourselves to his conference */
04712    if (p->master) {
04713       if (isslavenative(p->master, NULL)) {
04714          conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
04715       } else {
04716          conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
04717       }
04718    }
04719    if (!needconf) {
04720       /* Nobody is left (or should be left) in our conference.
04721          Kill it. */
04722       p->confno = -1;
04723    }
04724    ast_debug(1, "Updated conferencing on %d, with %d conference users\n", p->channel, needconf);
04725    return 0;
04726 }
04727 
04728 static void dahdi_enable_ec(struct dahdi_pvt *p)
04729 {
04730    int res;
04731    if (!p)
04732       return;
04733    if (p->echocanon) {
04734       ast_debug(1, "Echo cancellation already on\n");
04735       return;
04736    }
04737    if (p->digital) {
04738       ast_debug(1, "Echo cancellation isn't required on digital connection\n");
04739       return;
04740    }
04741    if (p->echocancel.head.tap_length) {
04742 #if defined(HAVE_PRI) || defined(HAVE_SS7)
04743       switch (p->sig) {
04744 #if defined(HAVE_PRI)
04745       case SIG_PRI_LIB_HANDLE_CASES:
04746          if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
04747             /*
04748              * PRI nobch pseudo channel.  Does not need ec anyway.
04749              * Does not handle ioctl(DAHDI_AUDIOMODE)
04750              */
04751             return;
04752          }
04753          /* Fall through */
04754 #endif   /* defined(HAVE_PRI) */
04755 #if defined(HAVE_SS7)
04756       case SIG_SS7:
04757 #endif   /* defined(HAVE_SS7) */
04758          {
04759             int x = 1;
04760 
04761             res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x);
04762             if (res)
04763                ast_log(LOG_WARNING,
04764                   "Unable to enable audio mode on channel %d (%s)\n",
04765                   p->channel, strerror(errno));
04766          }
04767          break;
04768       default:
04769          break;
04770       }
04771 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
04772       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &p->echocancel);
04773       if (res) {
04774          ast_log(LOG_WARNING, "Unable to enable echo cancellation on channel %d (%s)\n", p->channel, strerror(errno));
04775       } else {
04776          p->echocanon = 1;
04777          ast_debug(1, "Enabled echo cancellation on channel %d\n", p->channel);
04778       }
04779    } else
04780       ast_debug(1, "No echo cancellation requested\n");
04781 }
04782 
04783 static void dahdi_train_ec(struct dahdi_pvt *p)
04784 {
04785    int x;
04786    int res;
04787 
04788    if (p && p->echocanon && p->echotraining) {
04789       x = p->echotraining;
04790       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOTRAIN, &x);
04791       if (res)
04792          ast_log(LOG_WARNING, "Unable to request echo training on channel %d: %s\n", p->channel, strerror(errno));
04793       else
04794          ast_debug(1, "Engaged echo training on channel %d\n", p->channel);
04795    } else {
04796       ast_debug(1, "No echo training requested\n");
04797    }
04798 }
04799 
04800 static void dahdi_disable_ec(struct dahdi_pvt *p)
04801 {
04802    int res;
04803 
04804    if (p->echocanon) {
04805       struct dahdi_echocanparams ecp = { .tap_length = 0 };
04806 
04807       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &ecp);
04808 
04809       if (res)
04810          ast_log(LOG_WARNING, "Unable to disable echo cancellation on channel %d: %s\n", p->channel, strerror(errno));
04811       else
04812          ast_debug(1, "Disabled echo cancellation on channel %d\n", p->channel);
04813    }
04814 
04815    p->echocanon = 0;
04816 }
04817 
04818 /* perform a dynamic range compression transform on the given sample */
04819 static int drc_sample(int sample, float drc)
04820 {
04821    float neg;
04822    float shallow, steep;
04823    float max = SHRT_MAX;
04824    
04825    neg = (sample < 0 ? -1 : 1);
04826    steep = drc*sample;
04827    shallow = neg*(max-max/drc)+(float)sample/drc;
04828    if (abs(steep) < abs(shallow)) {
04829       sample = steep;
04830    }
04831    else {
04832       sample = shallow;
04833    }
04834 
04835    return sample;
04836 }
04837 
04838 
04839 static void fill_txgain(struct dahdi_gains *g, float gain, float drc, int law)
04840 {
04841    int j;
04842    int k;
04843 
04844    float linear_gain = pow(10.0, gain / 20.0);
04845 
04846    switch (law) {
04847    case DAHDI_LAW_ALAW:
04848       for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
04849          if (gain || drc) {
04850             k = AST_ALAW(j);
04851             if (drc) {
04852                k = drc_sample(k, drc);
04853             }
04854             k = (float)k*linear_gain;
04855             if (k > 32767) k = 32767;
04856             if (k < -32767) k = -32767;
04857             g->txgain[j] = AST_LIN2A(k);
04858          } else {
04859             g->txgain[j] = j;
04860          }
04861       }
04862       break;
04863    case DAHDI_LAW_MULAW:
04864       for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
04865          if (gain || drc) {
04866             k = AST_MULAW(j);
04867             if (drc) {
04868                k = drc_sample(k, drc);
04869             }
04870             k = (float)k*linear_gain;
04871             if (k > 32767) k = 32767;
04872             if (k < -32767) k = -32767;
04873             g->txgain[j] = AST_LIN2MU(k);
04874 
04875          } else {
04876             g->txgain[j] = j;
04877          }
04878       }
04879       break;
04880    }
04881 }
04882 
04883 static void fill_rxgain(struct dahdi_gains *g, float gain, float drc, int law)
04884 {
04885    int j;
04886    int k;
04887    float linear_gain = pow(10.0, gain / 20.0);
04888 
04889    switch (law) {
04890    case DAHDI_LAW_ALAW:
04891       for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
04892          if (gain || drc) {
04893             k = AST_ALAW(j);
04894             if (drc) {
04895                k = drc_sample(k, drc);
04896             }
04897             k = (float)k*linear_gain;
04898             if (k > 32767) k = 32767;
04899             if (k < -32767) k = -32767;
04900             g->rxgain[j] = AST_LIN2A(k);
04901          } else {
04902             g->rxgain[j] = j;
04903          }
04904       }
04905       break;
04906    case DAHDI_LAW_MULAW:
04907       for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
04908          if (gain || drc) {
04909             k = AST_MULAW(j);
04910             if (drc) {
04911                k = drc_sample(k, drc);
04912             }
04913             k = (float)k*linear_gain;
04914             if (k > 32767) k = 32767;
04915             if (k < -32767) k = -32767;
04916             g->rxgain[j] = AST_LIN2MU(k);
04917          } else {
04918             g->rxgain[j] = j;
04919          }
04920       }
04921       break;
04922    }
04923 }
04924 
04925 static int set_actual_txgain(int fd, float gain, float drc, int law)
04926 {
04927    struct dahdi_gains g;
04928    int res;
04929 
04930    memset(&g, 0, sizeof(g));
04931    res = ioctl(fd, DAHDI_GETGAINS, &g);
04932    if (res) {
04933       ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
04934       return res;
04935    }
04936 
04937    fill_txgain(&g, gain, drc, law);
04938 
04939    return ioctl(fd, DAHDI_SETGAINS, &g);
04940 }
04941 
04942 static int set_actual_rxgain(int fd, float gain, float drc, int law)
04943 {
04944    struct dahdi_gains g;
04945    int res;
04946 
04947    memset(&g, 0, sizeof(g));
04948    res = ioctl(fd, DAHDI_GETGAINS, &g);
04949    if (res) {
04950       ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
04951       return res;
04952    }
04953 
04954    fill_rxgain(&g, gain, drc, law);
04955 
04956    return ioctl(fd, DAHDI_SETGAINS, &g);
04957 }
04958 
04959 static int set_actual_gain(int fd, float rxgain, float txgain, float rxdrc, float txdrc, int law)
04960 {
04961    return set_actual_txgain(fd, txgain, txdrc, law) | set_actual_rxgain(fd, rxgain, rxdrc, law);
04962 }
04963 
04964 static int bump_gains(struct dahdi_pvt *p)
04965 {
04966    int res;
04967 
04968    /* Bump receive gain by value stored in cid_rxgain */
04969    res = set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain + p->cid_rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
04970    if (res) {
04971       ast_log(LOG_WARNING, "Unable to bump gain: %s\n", strerror(errno));
04972       return -1;
04973    }
04974 
04975    return 0;
04976 }
04977 
04978 static int restore_gains(struct dahdi_pvt *p)
04979 {
04980    int res;
04981 
04982    res = set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
04983    if (res) {
04984       ast_log(LOG_WARNING, "Unable to restore gains: %s\n", strerror(errno));
04985       return -1;
04986    }
04987 
04988    return 0;
04989 }
04990 
04991 static inline int dahdi_set_hook(int fd, int hs)
04992 {
04993    int x, res;
04994 
04995    x = hs;
04996    res = ioctl(fd, DAHDI_HOOK, &x);
04997 
04998    if (res < 0) {
04999       if (errno == EINPROGRESS)
05000          return 0;
05001       ast_log(LOG_WARNING, "DAHDI hook failed returned %d (trying %d): %s\n", res, hs, strerror(errno));
05002       /* will expectedly fail if phone is off hook during operation, such as during a restart */
05003    }
05004 
05005    return res;
05006 }
05007 
05008 static inline int dahdi_confmute(struct dahdi_pvt *p, int muted)
05009 {
05010    int x, res;
05011 
05012    x = muted;
05013 #if defined(HAVE_PRI) || defined(HAVE_SS7)
05014    switch (p->sig) {
05015 #if defined(HAVE_PRI)
05016    case SIG_PRI_LIB_HANDLE_CASES:
05017       if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
05018          /* PRI nobch pseudo channel.  Does not handle ioctl(DAHDI_AUDIOMODE) */
05019          break;
05020       }
05021       /* Fall through */
05022 #endif   /* defined(HAVE_PRI) */
05023 #if defined(HAVE_SS7)
05024    case SIG_SS7:
05025 #endif   /* defined(HAVE_SS7) */
05026       {
05027          int y = 1;
05028 
05029          res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &y);
05030          if (res)
05031             ast_log(LOG_WARNING, "Unable to set audio mode on %d: %s\n",
05032                p->channel, strerror(errno));
05033       }
05034       break;
05035    default:
05036       break;
05037    }
05038 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
05039    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_CONFMUTE, &x);
05040    if (res < 0)
05041       ast_log(LOG_WARNING, "DAHDI confmute(%d) failed on channel %d: %s\n", muted, p->channel, strerror(errno));
05042    return res;
05043 }
05044 
05045 static int save_conference(struct dahdi_pvt *p)
05046 {
05047    struct dahdi_confinfo c;
05048    int res;
05049    if (p->saveconf.confmode) {
05050       ast_log(LOG_WARNING, "Can't save conference -- already in use\n");
05051       return -1;
05052    }
05053    p->saveconf.chan = 0;
05054    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &p->saveconf);
05055    if (res) {
05056       ast_log(LOG_WARNING, "Unable to get conference info: %s\n", strerror(errno));
05057       p->saveconf.confmode = 0;
05058       return -1;
05059    }
05060    memset(&c, 0, sizeof(c));
05061    c.confmode = DAHDI_CONF_NORMAL;
05062    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &c);
05063    if (res) {
05064       ast_log(LOG_WARNING, "Unable to set conference info: %s\n", strerror(errno));
05065       return -1;
05066    }
05067    ast_debug(1, "Disabled conferencing\n");
05068    return 0;
05069 }
05070 
05071 static int restore_conference(struct dahdi_pvt *p)
05072 {
05073    int res;
05074    if (p->saveconf.confmode) {
05075       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &p->saveconf);
05076       p->saveconf.confmode = 0;
05077       if (res) {
05078          ast_log(LOG_WARNING, "Unable to restore conference info: %s\n", strerror(errno));
05079          return -1;
05080       }
05081       ast_debug(1, "Restored conferencing\n");
05082    }
05083    return 0;
05084 }
05085 
05086 static int send_cwcidspill(struct dahdi_pvt *p)
05087 {
05088    p->callwaitcas = 0;
05089    p->cidcwexpire = 0;
05090    p->cid_suppress_expire = 0;
05091    if (!(p->cidspill = ast_malloc(MAX_CALLERID_SIZE)))
05092       return -1;
05093    p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, p->callwait_name, p->callwait_num, AST_LAW(p));
05094    /* Make sure we account for the end */
05095    p->cidlen += READ_SIZE * 4;
05096    p->cidpos = 0;
05097    send_callerid(p);
05098    ast_verb(3, "CPE supports Call Waiting Caller*ID.  Sending '%s/%s'\n", p->callwait_name, p->callwait_num);
05099    return 0;
05100 }
05101 
05102 static int has_voicemail(struct dahdi_pvt *p)
05103 {
05104    int new_msgs;
05105    struct ast_event *event;
05106    char *mailbox, *context;
05107 
05108    mailbox = context = ast_strdupa(p->mailbox);
05109    strsep(&context, "@");
05110    if (ast_strlen_zero(context))
05111       context = "default";
05112 
05113    event = ast_event_get_cached(AST_EVENT_MWI,
05114       AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
05115       AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
05116       AST_EVENT_IE_END);
05117 
05118    if (event) {
05119       new_msgs = ast_event_get_ie_uint(event, AST_EVENT_IE_NEWMSGS);
05120       ast_event_destroy(event);
05121    } else
05122       new_msgs = ast_app_has_voicemail(p->mailbox, NULL);
05123 
05124    return new_msgs;
05125 }
05126 
05127 
05128 
05129 static int send_callerid(struct dahdi_pvt *p)
05130 {
05131    /* Assumes spill in p->cidspill, p->cidlen in length and we're p->cidpos into it */
05132    int res;
05133    /* Take out of linear mode if necessary */
05134    if (p->subs[SUB_REAL].linear) {
05135       p->subs[SUB_REAL].linear = 0;
05136       dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
05137    }
05138    while (p->cidpos < p->cidlen) {
05139       res = write(p->subs[SUB_REAL].dfd, p->cidspill + p->cidpos, p->cidlen - p->cidpos);
05140       ast_debug(4, "writing callerid at pos %d of %d, res = %d\n", p->cidpos, p->cidlen, res);
05141       if (res < 0) {
05142          if (errno == EAGAIN)
05143             return 0;
05144          else {
05145             ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
05146             return -1;
05147          }
05148       }
05149       if (!res)
05150          return 0;
05151       p->cidpos += res;
05152    }
05153    p->cid_suppress_expire = CALLWAITING_SUPPRESS_SAMPLES;
05154    ast_free(p->cidspill);
05155    p->cidspill = NULL;
05156    if (p->callwaitcas) {
05157       /* Wait for CID/CW to expire */
05158       p->cidcwexpire = CIDCW_EXPIRE_SAMPLES;
05159       p->cid_suppress_expire = p->cidcwexpire;
05160    } else
05161       restore_conference(p);
05162    return 0;
05163 }
05164 
05165 static int dahdi_callwait(struct ast_channel *ast)
05166 {
05167    struct dahdi_pvt *p = ast->tech_pvt;
05168    p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
05169    if (p->cidspill) {
05170       ast_log(LOG_WARNING, "Spill already exists?!?\n");
05171       ast_free(p->cidspill);
05172    }
05173 
05174    /*
05175     * SAS: Subscriber Alert Signal, 440Hz for 300ms
05176     * CAS: CPE Alert Signal, 2130Hz * 2750Hz sine waves
05177     */
05178    if (!(p->cidspill = ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE * 4)))
05179       return -1;
05180    save_conference(p);
05181    /* Silence */
05182    memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
05183    if (!p->callwaitrings && p->callwaitingcallerid) {
05184       ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
05185       p->callwaitcas = 1;
05186       p->cidlen = 2400 + 680 + READ_SIZE * 4;
05187    } else {
05188       ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
05189       p->callwaitcas = 0;
05190       p->cidlen = 2400 + READ_SIZE * 4;
05191    }
05192    p->cidpos = 0;
05193    send_callerid(p);
05194 
05195    return 0;
05196 }
05197 
05198 static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout)
05199 {
05200    struct dahdi_pvt *p = ast->tech_pvt;
05201    int x, res, mysig;
05202    char dest[256]; /* must be same length as p->dialdest */
05203 
05204    ast_mutex_lock(&p->lock);
05205    ast_copy_string(dest, rdest, sizeof(dest));
05206    ast_copy_string(p->dialdest, rdest, sizeof(p->dialdest));
05207    if ((ast->_state == AST_STATE_BUSY)) {
05208       p->subs[SUB_REAL].needbusy = 1;
05209       ast_mutex_unlock(&p->lock);
05210       return 0;
05211    }
05212    if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
05213       ast_log(LOG_WARNING, "dahdi_call called on %s, neither down nor reserved\n", ast->name);
05214       ast_mutex_unlock(&p->lock);
05215       return -1;
05216    }
05217    p->waitingfordt.tv_sec = 0;
05218    p->dialednone = 0;
05219    if ((p->radio || (p->oprmode < 0)))  /* if a radio channel, up immediately */
05220    {
05221       /* Special pseudo -- automatically up */
05222       ast_setstate(ast, AST_STATE_UP);
05223       ast_mutex_unlock(&p->lock);
05224       return 0;
05225    }
05226    x = DAHDI_FLUSH_READ | DAHDI_FLUSH_WRITE;
05227    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
05228    if (res)
05229       ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", p->channel, strerror(errno));
05230    p->outgoing = 1;
05231 
05232    if (IS_DIGITAL(ast->transfercapability)){
05233       set_actual_gain(p->subs[SUB_REAL].dfd, 0, 0, p->rxdrc, p->txdrc, p->law);
05234    } else {
05235       set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
05236    }  
05237 
05238 #ifdef HAVE_PRI
05239    if (dahdi_sig_pri_lib_handles(p->sig)) {
05240       res = sig_pri_call(p->sig_pvt, ast, rdest, timeout,
05241          (p->law == DAHDI_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW);
05242       ast_mutex_unlock(&p->lock);
05243       return res;
05244    }
05245 #endif
05246 
05247 #if defined(HAVE_SS7)
05248    if (p->sig == SIG_SS7) {
05249       res = sig_ss7_call(p->sig_pvt, ast, rdest);
05250       ast_mutex_unlock(&p->lock);
05251       return res;
05252    }
05253 #endif   /* defined(HAVE_SS7) */
05254 
05255    /* If this is analog signalling we can exit here */
05256    if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
05257       p->callwaitrings = 0;
05258       res = analog_call(p->sig_pvt, ast, rdest, timeout);
05259       ast_mutex_unlock(&p->lock);
05260       return res;
05261    }
05262 
05263    mysig = p->outsigmod > -1 ? p->outsigmod : p->sig;
05264    switch (mysig) {
05265    case 0:
05266       /* Special pseudo -- automatically up*/
05267       ast_setstate(ast, AST_STATE_UP);
05268       break;
05269    case SIG_MFCR2:
05270       break;
05271    default:
05272       ast_debug(1, "not yet implemented\n");
05273       ast_mutex_unlock(&p->lock);
05274       return -1;
05275    }
05276 
05277 #ifdef HAVE_OPENR2
05278    if (p->mfcr2) {
05279       openr2_calling_party_category_t chancat;
05280       int callres = 0;
05281       char *c, *l;
05282 
05283       /* We'll get it in a moment -- but use dialdest to store pre-setup_ack digits */
05284       p->dialdest[0] = '\0';
05285 
05286       c = strchr(dest, '/');
05287       if (c) {
05288          c++;
05289       } else {
05290          c = "";
05291       }
05292       if (!p->hidecallerid) {
05293          l = ast->caller.id.number.valid ? ast->caller.id.number.str : NULL;
05294       } else {
05295          l = NULL;
05296       }
05297       if (strlen(c) < p->stripmsd) {
05298          ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
05299          ast_mutex_unlock(&p->lock);
05300          return -1;
05301       }
05302       p->dialing = 1;
05303       chancat = dahdi_r2_get_channel_category(ast);
05304       callres = openr2_chan_make_call(p->r2chan, l, (c + p->stripmsd), chancat);
05305       if (-1 == callres) {
05306          ast_mutex_unlock(&p->lock);
05307          ast_log(LOG_ERROR, "unable to make new MFC/R2 call!\n");
05308          return -1;
05309       }
05310       p->mfcr2_call_accepted = 0;
05311       p->mfcr2_progress = 0;
05312       ast_setstate(ast, AST_STATE_DIALING);
05313    }
05314 #endif /* HAVE_OPENR2 */
05315    ast_mutex_unlock(&p->lock);
05316    return 0;
05317 }
05318 
05319 /*!
05320  * \internal
05321  * \brief Insert the given chan_dahdi interface structure into the interface list.
05322  * \since 1.8
05323  *
05324  * \param pvt chan_dahdi private interface structure to insert.
05325  *
05326  * \details
05327  * The interface list is a doubly linked list sorted by the chan_dahdi channel number.
05328  * Any duplicates are inserted after the existing entries.
05329  *
05330  * \note The new interface must not already be in the list.
05331  *
05332  * \return Nothing
05333  */
05334 static void dahdi_iflist_insert(struct dahdi_pvt *pvt)
05335 {
05336    struct dahdi_pvt *cur;
05337 
05338    pvt->which_iflist = DAHDI_IFLIST_MAIN;
05339 
05340    /* Find place in middle of list for the new interface. */
05341    for (cur = iflist; cur; cur = cur->next) {
05342       if (pvt->channel < cur->channel) {
05343          /* New interface goes before the current interface. */
05344          pvt->prev = cur->prev;
05345          pvt->next = cur;
05346          if (cur->prev) {
05347             /* Insert into the middle of the list. */
05348             cur->prev->next = pvt;
05349          } else {
05350             /* Insert at head of list. */
05351             iflist = pvt;
05352          }
05353          cur->prev = pvt;
05354          return;
05355       }
05356    }
05357 
05358    /* New interface goes onto the end of the list */
05359    pvt->prev = ifend;
05360    pvt->next = NULL;
05361    if (ifend) {
05362       ifend->next = pvt;
05363    }
05364    ifend = pvt;
05365    if (!iflist) {
05366       /* List was empty */
05367       iflist = pvt;
05368    }
05369 }
05370 
05371 /*!
05372  * \internal
05373  * \brief Extract the given chan_dahdi interface structure from the interface list.
05374  * \since 1.8
05375  *
05376  * \param pvt chan_dahdi private interface structure to extract.
05377  *
05378  * \note
05379  * The given interface structure can be either in the interface list or a stand alone
05380  * structure that has not been put in the list if the next and prev pointers are NULL.
05381  *
05382  * \return Nothing
05383  */
05384 static void dahdi_iflist_extract(struct dahdi_pvt *pvt)
05385 {
05386    /* Extract from the forward chain. */
05387    if (pvt->prev) {
05388       pvt->prev->next = pvt->next;
05389    } else if (iflist == pvt) {
05390       /* Node is at the head of the list. */
05391       iflist = pvt->next;
05392    }
05393 
05394    /* Extract from the reverse chain. */
05395    if (pvt->next) {
05396       pvt->next->prev = pvt->prev;
05397    } else if (ifend == pvt) {
05398       /* Node is at the end of the list. */
05399       ifend = pvt->prev;
05400    }
05401 
05402    /* Node is no longer in the list. */
05403    pvt->which_iflist = DAHDI_IFLIST_NONE;
05404    pvt->prev = NULL;
05405    pvt->next = NULL;
05406 }
05407 
05408 #if defined(HAVE_PRI)
05409 /*!
05410  * \internal
05411  * \brief Insert the given chan_dahdi interface structure into the no B channel list.
05412  * \since 1.8
05413  *
05414  * \param pri sig_pri span control structure holding no B channel list.
05415  * \param pvt chan_dahdi private interface structure to insert.
05416  *
05417  * \details
05418  * The interface list is a doubly linked list sorted by the chan_dahdi channel number.
05419  * Any duplicates are inserted after the existing entries.
05420  *
05421  * \note The new interface must not already be in the list.
05422  *
05423  * \return Nothing
05424  */
05425 static void dahdi_nobch_insert(struct sig_pri_span *pri, struct dahdi_pvt *pvt)
05426 {
05427    struct dahdi_pvt *cur;
05428 
05429    pvt->which_iflist = DAHDI_IFLIST_NO_B_CHAN;
05430 
05431    /* Find place in middle of list for the new interface. */
05432    for (cur = pri->no_b_chan_iflist; cur; cur = cur->next) {
05433       if (pvt->channel < cur->channel) {
05434          /* New interface goes before the current interface. */
05435          pvt->prev = cur->prev;
05436          pvt->next = cur;
05437          if (cur->prev) {
05438             /* Insert into the middle of the list. */
05439             cur->prev->next = pvt;
05440          } else {
05441             /* Insert at head of list. */
05442             pri->no_b_chan_iflist = pvt;
05443          }
05444          cur->prev = pvt;
05445          return;
05446       }
05447    }
05448 
05449    /* New interface goes onto the end of the list */
05450    pvt->prev = pri->no_b_chan_end;
05451    pvt->next = NULL;
05452    if (pri->no_b_chan_end) {
05453       ((struct dahdi_pvt *) pri->no_b_chan_end)->next = pvt;
05454    }
05455    pri->no_b_chan_end = pvt;
05456    if (!pri->no_b_chan_iflist) {
05457       /* List was empty */
05458       pri->no_b_chan_iflist = pvt;
05459    }
05460 }
05461 #endif   /* defined(HAVE_PRI) */
05462 
05463 #if defined(HAVE_PRI)
05464 /*!
05465  * \internal
05466  * \brief Extract the given chan_dahdi interface structure from the no B channel list.
05467  * \since 1.8
05468  *
05469  * \param pri sig_pri span control structure holding no B channel list.
05470  * \param pvt chan_dahdi private interface structure to extract.
05471  *
05472  * \note
05473  * The given interface structure can be either in the interface list or a stand alone
05474  * structure that has not been put in the list if the next and prev pointers are NULL.
05475  *
05476  * \return Nothing
05477  */
05478 static void dahdi_nobch_extract(struct sig_pri_span *pri, struct dahdi_pvt *pvt)
05479 {
05480    /* Extract from the forward chain. */
05481    if (pvt->prev) {
05482       pvt->prev->next = pvt->next;
05483    } else if (pri->no_b_chan_iflist == pvt) {
05484       /* Node is at the head of the list. */
05485       pri->no_b_chan_iflist = pvt->next;
05486    }
05487 
05488    /* Extract from the reverse chain. */
05489    if (pvt->next) {
05490       pvt->next->prev = pvt->prev;
05491    } else if (pri->no_b_chan_end == pvt) {
05492       /* Node is at the end of the list. */
05493       pri->no_b_chan_end = pvt->prev;
05494    }
05495 
05496    /* Node is no longer in the list. */
05497    pvt->which_iflist = DAHDI_IFLIST_NONE;
05498    pvt->prev = NULL;
05499    pvt->next = NULL;
05500 }
05501 #endif   /* defined(HAVE_PRI) */
05502 
05503 #if defined(HAVE_PRI)
05504 /*!
05505  * \internal
05506  * \brief Unlink the channel interface from the PRI private pointer array.
05507  * \since 1.8
05508  *
05509  * \param pvt chan_dahdi private interface structure to unlink.
05510  *
05511  * \return Nothing
05512  */
05513 static void dahdi_unlink_pri_pvt(struct dahdi_pvt *pvt)
05514 {
05515    unsigned idx;
05516    struct sig_pri_span *pri;
05517 
05518    pri = pvt->pri;
05519    if (!pri) {
05520       /* Not PRI signaling so cannot be in a PRI private pointer array. */
05521       return;
05522    }
05523    ast_mutex_lock(&pri->lock);
05524    for (idx = 0; idx < pri->numchans; ++idx) {
05525       if (pri->pvts[idx] == pvt->sig_pvt) {
05526          pri->pvts[idx] = NULL;
05527          ast_mutex_unlock(&pri->lock);
05528          return;
05529       }
05530    }
05531    ast_mutex_unlock(&pri->lock);
05532 }
05533 #endif   /* defined(HAVE_PRI) */
05534 
05535 #if defined(HAVE_SS7)
05536 /*!
05537  * \internal
05538  * \brief Unlink the channel interface from the SS7 private pointer array.
05539  * \since 1.8
05540  *
05541  * \param pvt chan_dahdi private interface structure to unlink.
05542  *
05543  * \return Nothing
05544  */
05545 static void dahdi_unlink_ss7_pvt(struct dahdi_pvt *pvt)
05546 {
05547    unsigned idx;
05548    struct sig_ss7_linkset *ss7;
05549 
05550    ss7 = pvt->ss7;
05551    if (!ss7) {
05552       /* Not SS7 signaling so cannot be in a SS7 private pointer array. */
05553       return;
05554    }
05555    ast_mutex_lock(&ss7->lock);
05556    for (idx = 0; idx < ss7->numchans; ++idx) {
05557       if (ss7->pvts[idx] == pvt->sig_pvt) {
05558          ss7->pvts[idx] = NULL;
05559          ast_mutex_unlock(&ss7->lock);
05560          return;
05561       }
05562    }
05563    ast_mutex_unlock(&ss7->lock);
05564 }
05565 #endif   /* defined(HAVE_SS7) */
05566 
05567 static struct dahdi_pvt *find_next_iface_in_span(struct dahdi_pvt *cur)
05568 {
05569    if (cur->next && cur->next->span == cur->span) {
05570       return cur->next;
05571    } else if (cur->prev && cur->prev->span == cur->span) {
05572       return cur->prev;
05573    }
05574 
05575    return NULL;
05576 }
05577 
05578 static void destroy_dahdi_pvt(struct dahdi_pvt *pvt)
05579 {
05580    struct dahdi_pvt *p = pvt;
05581 
05582    if (p->manages_span_alarms) {
05583       struct dahdi_pvt *next = find_next_iface_in_span(p);
05584       if (next) {
05585          next->manages_span_alarms = 1;
05586       }
05587    }
05588 
05589    /* Remove channel from the list */
05590 #if defined(HAVE_PRI)
05591    dahdi_unlink_pri_pvt(p);
05592 #endif   /* defined(HAVE_PRI) */
05593 #if defined(HAVE_SS7)
05594    dahdi_unlink_ss7_pvt(p);
05595 #endif   /* defined(HAVE_SS7) */
05596    switch (pvt->which_iflist) {
05597    case DAHDI_IFLIST_NONE:
05598       break;
05599    case DAHDI_IFLIST_MAIN:
05600       dahdi_iflist_extract(p);
05601       break;
05602 #if defined(HAVE_PRI)
05603    case DAHDI_IFLIST_NO_B_CHAN:
05604       if (p->pri) {
05605          dahdi_nobch_extract(p->pri, p);
05606       }
05607       break;
05608 #endif   /* defined(HAVE_PRI) */
05609    }
05610 
05611    if (p->sig_pvt) {
05612       if (analog_lib_handles(p->sig, 0, 0)) {
05613          analog_delete(p->sig_pvt);
05614       }
05615       switch (p->sig) {
05616 #if defined(HAVE_PRI)
05617       case SIG_PRI_LIB_HANDLE_CASES:
05618          sig_pri_chan_delete(p->sig_pvt);
05619          break;
05620 #endif   /* defined(HAVE_PRI) */
05621 #if defined(HAVE_SS7)
05622       case SIG_SS7:
05623          sig_ss7_chan_delete(p->sig_pvt);
05624          break;
05625 #endif   /* defined(HAVE_SS7) */
05626       default:
05627          break;
05628       }
05629    }
05630    ast_free(p->cidspill);
05631    if (p->use_smdi)
05632       ast_smdi_interface_unref(p->smdi_iface);
05633    if (p->mwi_event_sub)
05634       ast_event_unsubscribe(p->mwi_event_sub);
05635    if (p->vars) {
05636       ast_variables_destroy(p->vars);
05637    }
05638    if (p->cc_params) {
05639       ast_cc_config_params_destroy(p->cc_params);
05640    }
05641    ast_mutex_destroy(&p->lock);
05642    dahdi_close_sub(p, SUB_REAL);
05643    if (p->owner)
05644       p->owner->tech_pvt = NULL;
05645    ast_free(p);
05646 }
05647 
05648 static void destroy_channel(struct dahdi_pvt *cur, int now)
05649 {
05650    int i;
05651 
05652    if (!now) {
05653       /* Do not destroy the channel now if it is owned by someone. */
05654       if (cur->owner) {
05655          return;
05656       }
05657       for (i = 0; i < 3; i++) {
05658          if (cur->subs[i].owner) {
05659             return;
05660          }
05661       }
05662    }
05663    destroy_dahdi_pvt(cur);
05664 }
05665 
05666 static void destroy_all_channels(void)
05667 {
05668    int chan;
05669 #if defined(HAVE_PRI)
05670    unsigned span;
05671    struct sig_pri_span *pri;
05672 #endif   /* defined(HAVE_PRI) */
05673    struct dahdi_pvt *p;
05674 
05675    while (num_restart_pending) {
05676       usleep(1);
05677    }
05678 
05679    ast_mutex_lock(&iflock);
05680    /* Destroy all the interfaces and free their memory */
05681    while (iflist) {
05682       p = iflist;
05683 
05684       chan = p->channel;
05685 #if defined(HAVE_PRI_SERVICE_MESSAGES)
05686       {
05687          char db_chan_name[20];
05688          char db_answer[5];
05689          char state;
05690          int why = -1;
05691 
05692          snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, p->span, chan);
05693          if (!ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) {
05694             sscanf(db_answer, "%1c:%30d", &state, &why);
05695          }
05696          if (!why) {
05697             /* SRVST persistence is not required */
05698             ast_db_del(db_chan_name, SRVST_DBKEY);
05699          }
05700       }
05701 #endif   /* defined(HAVE_PRI_SERVICE_MESSAGES) */
05702       /* Free associated memory */
05703       destroy_dahdi_pvt(p);
05704       ast_verb(3, "Unregistered channel %d\n", chan);
05705    }
05706    ifcount = 0;
05707    ast_mutex_unlock(&iflock);
05708 
05709 #if defined(HAVE_PRI)
05710    /* Destroy all of the no B channel interface lists */
05711    for (span = 0; span < NUM_SPANS; ++span) {
05712       if (!pris[span].dchannels[0]) {
05713          break;
05714       }
05715       pri = &pris[span].pri;
05716       ast_mutex_lock(&pri->lock);
05717       while (pri->no_b_chan_iflist) {
05718          p = pri->no_b_chan_iflist;
05719 
05720          /* Free associated memory */
05721          destroy_dahdi_pvt(p);
05722       }
05723       ast_mutex_unlock(&pri->lock);
05724    }
05725 #endif   /* defined(HAVE_PRI) */
05726 }
05727 
05728 #if defined(HAVE_PRI)
05729 static char *dahdi_send_keypad_facility_app = "DAHDISendKeypadFacility";
05730 
05731 static int dahdi_send_keypad_facility_exec(struct ast_channel *chan, const char *digits)
05732 {
05733    /* Data will be our digit string */
05734    struct dahdi_pvt *p;
05735 
05736    if (ast_strlen_zero(digits)) {
05737       ast_debug(1, "No digit string sent to application!\n");
05738       return -1;
05739    }
05740 
05741    p = (struct dahdi_pvt *)chan->tech_pvt;
05742 
05743    if (!p) {
05744       ast_debug(1, "Unable to find technology private\n");
05745       return -1;
05746    }
05747 
05748    pri_send_keypad_facility_exec(p->sig_pvt, digits);
05749 
05750    return 0;
05751 }
05752 #endif   /* defined(HAVE_PRI) */
05753 
05754 #if defined(HAVE_PRI)
05755 #if defined(HAVE_PRI_PROG_W_CAUSE)
05756 static char *dahdi_send_callrerouting_facility_app = "DAHDISendCallreroutingFacility";
05757 
05758 static int dahdi_send_callrerouting_facility_exec(struct ast_channel *chan, const char *data)
05759 {
05760    /* Data will be our digit string */
05761    struct dahdi_pvt *pvt;
05762    char *parse;
05763    int res = -1;
05764    AST_DECLARE_APP_ARGS(args,
05765       AST_APP_ARG(destination);
05766       AST_APP_ARG(original);
05767       AST_APP_ARG(reason);
05768    );
05769 
05770    if (ast_strlen_zero(data)) {
05771       ast_log(LOG_DEBUG, "No data sent to application!\n");
05772       return -1;
05773    }
05774    if (chan->tech != &dahdi_tech) {
05775       ast_log(LOG_DEBUG, "Only DAHDI technology accepted!\n");
05776       return -1;
05777    }
05778    pvt = (struct dahdi_pvt *) chan->tech_pvt;
05779    if (!pvt) {
05780       ast_log(LOG_DEBUG, "Unable to find technology private\n");
05781       return -1;
05782    }
05783    switch (pvt->sig) {
05784    case SIG_PRI_LIB_HANDLE_CASES:
05785       break;
05786    default:
05787       ast_log(LOG_DEBUG, "callrerouting attempted on non-ISDN channel %s\n",
05788          chan->name);
05789       return -1;
05790    }
05791 
05792    parse = ast_strdupa(data);
05793    AST_STANDARD_APP_ARGS(args, parse);
05794 
05795    if (ast_strlen_zero(args.destination)) {
05796       ast_log(LOG_WARNING, "callrerouting facility requires at least destination number argument\n");
05797       return -1;
05798    }
05799 
05800    if (ast_strlen_zero(args.original)) {
05801       ast_log(LOG_WARNING, "Callrerouting Facility without original called number argument\n");
05802       args.original = NULL;
05803    }
05804 
05805    if (ast_strlen_zero(args.reason)) {
05806       ast_log(LOG_NOTICE, "Callrerouting Facility without diversion reason argument, defaulting to unknown\n");
05807       args.reason = NULL;
05808    }
05809 
05810    pri_send_callrerouting_facility_exec(pvt->sig_pvt, chan->_state, args.destination,
05811       args.original, args.reason);
05812 
05813    return res;
05814 }
05815 #endif   /* defined(HAVE_PRI_PROG_W_CAUSE) */
05816 #endif   /* defined(HAVE_PRI) */
05817 
05818 #if defined(HAVE_OPENR2)
05819 static const char * const dahdi_accept_r2_call_app = "DAHDIAcceptR2Call";
05820 
05821 static int dahdi_accept_r2_call_exec(struct ast_channel *chan, const char *data)
05822 {
05823    /* data is whether to accept with charge or no charge */
05824    openr2_call_mode_t accept_mode;
05825    int res, timeout, maxloops;
05826    struct ast_frame *f;
05827    struct dahdi_pvt *p;
05828    char *parse;
05829    AST_DECLARE_APP_ARGS(args,
05830          AST_APP_ARG(charge);
05831    );
05832 
05833    if (ast_strlen_zero(data)) {
05834       ast_log(LOG_DEBUG, "No data sent to application!\n");
05835       return -1;
05836    }
05837 
05838    if (chan->tech != &dahdi_tech) {
05839       ast_log(LOG_DEBUG, "Only DAHDI technology accepted!\n");
05840       return -1;
05841    }
05842 
05843    p = (struct dahdi_pvt *)chan->tech_pvt;
05844    if (!p) {
05845       ast_log(LOG_DEBUG, "Unable to find technology private!\n");
05846       return -1;
05847    }
05848 
05849    parse = ast_strdupa(data);
05850    AST_STANDARD_APP_ARGS(args, parse);
05851 
05852    if (ast_strlen_zero(args.charge)) {
05853       ast_log(LOG_WARNING, "DAHDIAcceptR2Call requires 'yes' or 'no' for the charge parameter\n");
05854       return -1;
05855    }
05856 
05857    ast_mutex_lock(&p->lock);
05858    if (!p->mfcr2 || !p->mfcr2call) {
05859       ast_mutex_unlock(&p->lock);
05860       ast_log(LOG_DEBUG, "Channel %s does not seems to be an R2 active channel!\n", chan->name);
05861       return -1;
05862    }
05863 
05864    if (p->mfcr2_call_accepted) {
05865       ast_mutex_unlock(&p->lock);
05866       ast_log(LOG_DEBUG, "MFC/R2 call already accepted on channel %s!\n", chan->name);
05867       return 0;
05868    }
05869    accept_mode = ast_true(args.charge) ? OR2_CALL_WITH_CHARGE : OR2_CALL_NO_CHARGE;
05870    if (openr2_chan_accept_call(p->r2chan, accept_mode)) {
05871       ast_mutex_unlock(&p->lock);
05872       ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n");
05873       return -1;
05874    }
05875    ast_mutex_unlock(&p->lock);
05876 
05877    res = 0;
05878    timeout = 100;
05879    maxloops = 50; /* wait up to 5 seconds */
05880    /* we need to read() until the call is accepted */
05881    while (maxloops > 0) {
05882       maxloops--;
05883       if (ast_check_hangup(chan)) {
05884          break;
05885       }
05886       res = ast_waitfor(chan, timeout);
05887       if (res < 0) {
05888          ast_log(LOG_DEBUG, "ast_waitfor failed on channel %s, going out ...\n", chan->name);
05889          res = -1;
05890          break;
05891       }
05892       if (res == 0) {
05893          continue;
05894       }
05895       f = ast_read(chan);
05896       if (!f) {
05897          ast_log(LOG_DEBUG, "No frame read on channel %s, going out ...\n", chan->name);
05898          res = -1;
05899          break;
05900       }
05901       if (f->frametype == AST_FRAME_CONTROL && f->subclass.integer == AST_CONTROL_HANGUP) {
05902          ast_log(LOG_DEBUG, "Got HANGUP frame on channel %s, going out ...\n", chan->name);
05903          ast_frfree(f);
05904          res = -1;
05905          break;
05906       }
05907       ast_frfree(f);
05908       ast_mutex_lock(&p->lock);
05909       if (p->mfcr2_call_accepted) {
05910          ast_mutex_unlock(&p->lock);
05911          ast_log(LOG_DEBUG, "Accepted MFC/R2 call!\n");
05912          break;
05913       }
05914       ast_mutex_unlock(&p->lock);
05915    }
05916    if (res == -1) {
05917       ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n");
05918    }
05919    return res;
05920 }
05921 
05922 static openr2_call_disconnect_cause_t dahdi_ast_cause_to_r2_cause(int cause)
05923 {
05924    openr2_call_disconnect_cause_t r2cause = OR2_CAUSE_NORMAL_CLEARING;
05925    switch (cause) {
05926    case AST_CAUSE_USER_BUSY:
05927    case AST_CAUSE_CALL_REJECTED:
05928    case AST_CAUSE_INTERWORKING: /* I don't know wtf is this but is used sometimes when ekiga rejects a call */
05929       r2cause = OR2_CAUSE_BUSY_NUMBER;
05930       break;
05931 
05932    case AST_CAUSE_NORMAL_CIRCUIT_CONGESTION:
05933    case AST_CAUSE_SWITCH_CONGESTION:
05934       r2cause = OR2_CAUSE_NETWORK_CONGESTION;
05935       break;
05936 
05937    case AST_CAUSE_UNALLOCATED:
05938       r2cause = OR2_CAUSE_UNALLOCATED_NUMBER;
05939       break;
05940 
05941    case AST_CAUSE_NETWORK_OUT_OF_ORDER:
05942    case AST_CAUSE_DESTINATION_OUT_OF_ORDER:
05943       r2cause = OR2_CAUSE_OUT_OF_ORDER;
05944       break;
05945 
05946    case AST_CAUSE_NO_ANSWER:
05947    case AST_CAUSE_NO_USER_RESPONSE:
05948       r2cause = OR2_CAUSE_NO_ANSWER;
05949       break;
05950 
05951    default:
05952       r2cause = OR2_CAUSE_NORMAL_CLEARING;
05953       break;
05954    }
05955    ast_log(LOG_DEBUG, "ast cause %d resulted in openr2 cause %d/%s\n",
05956          cause, r2cause, openr2_proto_get_disconnect_string(r2cause));
05957    return r2cause;
05958 }
05959 #endif
05960 
05961 static int revert_fax_buffers(struct dahdi_pvt *p, struct ast_channel *ast)
05962 {
05963    if (p->bufferoverrideinuse) {
05964       /* faxbuffers are in use, revert them */
05965       struct dahdi_bufferinfo bi = {
05966          .txbufpolicy = p->buf_policy,
05967          .rxbufpolicy = p->buf_policy,
05968          .bufsize = p->bufsize,
05969          .numbufs = p->buf_no
05970       };
05971       int bpres;
05972 
05973       if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
05974          ast_log(LOG_WARNING, "Channel '%s' unable to revert buffer policy: %s\n", ast->name, strerror(errno));
05975       }
05976       p->bufferoverrideinuse = 0;
05977       return bpres;
05978    }
05979 
05980    return -1;
05981 }
05982 
05983 static int dahdi_hangup(struct ast_channel *ast)
05984 {
05985    int res = 0;
05986    int idx,x;
05987    int law;
05988    /*static int restore_gains(struct dahdi_pvt *p);*/
05989    struct dahdi_pvt *p = ast->tech_pvt;
05990    struct dahdi_params par;
05991 
05992    ast_debug(1, "dahdi_hangup(%s)\n", ast->name);
05993    if (!ast->tech_pvt) {
05994       ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
05995       return 0;
05996    }
05997 
05998    ast_mutex_lock(&p->lock);
05999    p->exten[0] = '\0';
06000    if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
06001       dahdi_confmute(p, 0);
06002       restore_gains(p);
06003       p->ignoredtmf = 0;
06004       p->waitingfordt.tv_sec = 0;
06005 
06006       res = analog_hangup(p->sig_pvt, ast);
06007       revert_fax_buffers(p, ast);
06008 
06009       goto hangup_out;
06010    } else {
06011       p->cid_num[0] = '\0';
06012       p->cid_name[0] = '\0';
06013       p->cid_subaddr[0] = '\0';
06014    }
06015 
06016 #ifdef HAVE_PRI
06017    if (dahdi_sig_pri_lib_handles(p->sig)) {
06018       x = 1;
06019       ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
06020       dahdi_confmute(p, 0);
06021       p->muting = 0;
06022       restore_gains(p);
06023       if (p->dsp) {
06024          ast_dsp_free(p->dsp);
06025          p->dsp = NULL;
06026       }
06027       p->ignoredtmf = 0;
06028       revert_fax_buffers(p, ast);
06029       dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
06030       p->law = p->law_default;
06031       law = p->law_default;
06032       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
06033       dahdi_disable_ec(p);
06034       update_conf(p);
06035       reset_conf(p);
06036       sig_pri_hangup(p->sig_pvt, ast);
06037       p->subs[SUB_REAL].owner = NULL;
06038       p->subs[SUB_REAL].needbusy = 0;
06039       p->owner = NULL;
06040       p->cid_tag[0] = '\0';
06041       p->ringt = 0;/* Probably not used in this mode.  Reset anyway. */
06042       p->distinctivering = 0;/* Probably not used in this mode. Reset anyway. */
06043       p->confirmanswer = 0;/* Probably not used in this mode. Reset anyway. */
06044       p->outgoing = 0;
06045       p->digital = 0;
06046       p->faxhandled = 0;
06047       p->pulsedial = 0;/* Probably not used in this mode. Reset anyway. */
06048       goto hangup_out;
06049    }
06050 #endif
06051 
06052 #if defined(HAVE_SS7)
06053    if (p->sig == SIG_SS7) {
06054       x = 1;
06055       ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
06056 
06057       dahdi_confmute(p, 0);
06058       p->muting = 0;
06059       restore_gains(p);
06060       if (p->dsp) {
06061          ast_dsp_free(p->dsp);
06062          p->dsp = NULL;
06063       }
06064       p->ignoredtmf = 0;
06065 
06066       /* Real channel, do some fixup */
06067       p->subs[SUB_REAL].owner = NULL;
06068       p->subs[SUB_REAL].needbusy = 0;
06069       p->polarity = POLARITY_IDLE;
06070       dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
06071 
06072       p->owner = NULL;
06073       p->ringt = 0;/* Probably not used in this mode.  Reset anyway. */
06074       p->distinctivering = 0;/* Probably not used in this mode. Reset anyway. */
06075       p->confirmanswer = 0;/* Probably not used in this mode. Reset anyway. */
06076       p->outgoing = 0;
06077       p->digital = 0;
06078       p->faxhandled = 0;
06079       p->pulsedial = 0;/* Probably not used in this mode. Reset anyway. */
06080 
06081       revert_fax_buffers(p, ast);
06082 
06083       p->law = p->law_default;
06084       law = p->law_default;
06085       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
06086       if (res < 0)
06087          ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
06088 
06089       sig_ss7_hangup(p->sig_pvt, ast);
06090 
06091       tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06092       dahdi_disable_ec(p);
06093       x = 0;
06094       ast_channel_setoption(ast,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0);
06095       ast_channel_setoption(ast,AST_OPTION_TDD,&x,sizeof(char),0);
06096       p->didtdd = 0;/* Probably not used in this mode. Reset anyway. */
06097       update_conf(p);
06098       reset_conf(p);
06099 
06100       /* Restore data mode */
06101       x = 0;
06102       ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
06103 
06104       if (num_restart_pending == 0)
06105          restart_monitor();
06106 
06107       ast->tech_pvt = NULL;
06108       goto hangup_out;
06109    }
06110 #endif   /* defined(HAVE_SS7) */
06111 
06112    idx = dahdi_get_index(ast, p, 1);
06113 
06114    dahdi_confmute(p, 0);
06115    p->muting = 0;
06116    restore_gains(p);
06117    if (p->origcid_num) {
06118       ast_copy_string(p->cid_num, p->origcid_num, sizeof(p->cid_num));
06119       ast_free(p->origcid_num);
06120       p->origcid_num = NULL;
06121    }
06122    if (p->origcid_name) {
06123       ast_copy_string(p->cid_name, p->origcid_name, sizeof(p->cid_name));
06124       ast_free(p->origcid_name);
06125       p->origcid_name = NULL;
06126    }
06127    if (p->dsp)
06128       ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
06129 
06130    ast_debug(1, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n",
06131       p->channel, idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
06132    p->ignoredtmf = 0;
06133 
06134    if (idx > -1) {
06135       /* Real channel, do some fixup */
06136       p->subs[idx].owner = NULL;
06137       p->subs[idx].needanswer = 0;
06138       p->subs[idx].needflash = 0;
06139       p->subs[idx].needringing = 0;
06140       p->subs[idx].needbusy = 0;
06141       p->subs[idx].needcongestion = 0;
06142       p->subs[idx].linear = 0;
06143       p->polarity = POLARITY_IDLE;
06144       dahdi_setlinear(p->subs[idx].dfd, 0);
06145       if (idx == SUB_REAL) {
06146          if ((p->subs[SUB_CALLWAIT].dfd > -1) && (p->subs[SUB_THREEWAY].dfd > -1)) {
06147             ast_debug(1, "Normal call hung up with both three way call and a call waiting call in place?\n");
06148             if (p->subs[SUB_CALLWAIT].inthreeway) {
06149                /* We had flipped over to answer a callwait and now it's gone */
06150                ast_debug(1, "We were flipped over to the callwait, moving back and unowning.\n");
06151                /* Move to the call-wait, but un-own us until they flip back. */
06152                swap_subs(p, SUB_CALLWAIT, SUB_REAL);
06153                unalloc_sub(p, SUB_CALLWAIT);
06154                p->owner = NULL;
06155             } else {
06156                /* The three way hung up, but we still have a call wait */
06157                ast_debug(1, "We were in the threeway and have a callwait still.  Ditching the threeway.\n");
06158                swap_subs(p, SUB_THREEWAY, SUB_REAL);
06159                unalloc_sub(p, SUB_THREEWAY);
06160                if (p->subs[SUB_REAL].inthreeway) {
06161                   /* This was part of a three way call.  Immediately make way for
06162                      another call */
06163                   ast_debug(1, "Call was complete, setting owner to former third call\n");
06164                   p->owner = p->subs[SUB_REAL].owner;
06165                } else {
06166                   /* This call hasn't been completed yet...  Set owner to NULL */
06167                   ast_debug(1, "Call was incomplete, setting owner to NULL\n");
06168                   p->owner = NULL;
06169                }
06170                p->subs[SUB_REAL].inthreeway = 0;
06171             }
06172          } else if (p->subs[SUB_CALLWAIT].dfd > -1) {
06173             /* Move to the call-wait and switch back to them. */
06174             swap_subs(p, SUB_CALLWAIT, SUB_REAL);
06175             unalloc_sub(p, SUB_CALLWAIT);
06176             p->owner = p->subs[SUB_REAL].owner;
06177             if (p->owner->_state != AST_STATE_UP)
06178                p->subs[SUB_REAL].needanswer = 1;
06179             if (ast_bridged_channel(p->subs[SUB_REAL].owner))
06180                ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
06181          } else if (p->subs[SUB_THREEWAY].dfd > -1) {
06182             swap_subs(p, SUB_THREEWAY, SUB_REAL);
06183             unalloc_sub(p, SUB_THREEWAY);
06184             if (p->subs[SUB_REAL].inthreeway) {
06185                /* This was part of a three way call.  Immediately make way for
06186                   another call */
06187                ast_debug(1, "Call was complete, setting owner to former third call\n");
06188                p->owner = p->subs[SUB_REAL].owner;
06189             } else {
06190                /* This call hasn't been completed yet...  Set owner to NULL */
06191                ast_debug(1, "Call was incomplete, setting owner to NULL\n");
06192                p->owner = NULL;
06193             }
06194             p->subs[SUB_REAL].inthreeway = 0;
06195          }
06196       } else if (idx == SUB_CALLWAIT) {
06197          /* Ditch the holding callwait call, and immediately make it availabe */
06198          if (p->subs[SUB_CALLWAIT].inthreeway) {
06199             /* This is actually part of a three way, placed on hold.  Place the third part
06200                on music on hold now */
06201             if (p->subs[SUB_THREEWAY].owner && ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
06202                ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
06203                   S_OR(p->mohsuggest, NULL),
06204                   !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
06205             }
06206             p->subs[SUB_THREEWAY].inthreeway = 0;
06207             /* Make it the call wait now */
06208             swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
06209             unalloc_sub(p, SUB_THREEWAY);
06210          } else
06211             unalloc_sub(p, SUB_CALLWAIT);
06212       } else if (idx == SUB_THREEWAY) {
06213          if (p->subs[SUB_CALLWAIT].inthreeway) {
06214             /* The other party of the three way call is currently in a call-wait state.
06215                Start music on hold for them, and take the main guy out of the third call */
06216             if (p->subs[SUB_CALLWAIT].owner && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
06217                ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
06218                   S_OR(p->mohsuggest, NULL),
06219                   !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
06220             }
06221             p->subs[SUB_CALLWAIT].inthreeway = 0;
06222          }
06223          p->subs[SUB_REAL].inthreeway = 0;
06224          /* If this was part of a three way call index, let us make
06225             another three way call */
06226          unalloc_sub(p, SUB_THREEWAY);
06227       } else {
06228          /* This wasn't any sort of call, but how are we an index? */
06229          ast_log(LOG_WARNING, "Index found but not any type of call?\n");
06230       }
06231    }
06232 
06233    if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) {
06234       p->owner = NULL;
06235       p->ringt = 0;
06236       p->distinctivering = 0;
06237       p->confirmanswer = 0;
06238       p->outgoing = 0;
06239       p->digital = 0;
06240       p->faxhandled = 0;
06241       p->pulsedial = 0;
06242       if (p->dsp) {
06243          ast_dsp_free(p->dsp);
06244          p->dsp = NULL;
06245       }
06246 
06247       revert_fax_buffers(p, ast);
06248 
06249       p->law = p->law_default;
06250       law = p->law_default;
06251       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
06252       if (res < 0)
06253          ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
06254       /* Perform low level hangup if no owner left */
06255 #ifdef HAVE_OPENR2
06256       if (p->mfcr2 && p->mfcr2call && openr2_chan_get_direction(p->r2chan) != OR2_DIR_STOPPED) {
06257          ast_log(LOG_DEBUG, "disconnecting MFC/R2 call on chan %d\n", p->channel);
06258          /* If it's an incoming call, check the mfcr2_forced_release setting */
06259          if (openr2_chan_get_direction(p->r2chan) == OR2_DIR_BACKWARD && p->mfcr2_forced_release) {
06260             dahdi_r2_disconnect_call(p, OR2_CAUSE_FORCED_RELEASE);
06261          } else {
06262             const char *r2causestr = pbx_builtin_getvar_helper(ast, "MFCR2_CAUSE");
06263             int r2cause_user = r2causestr ? atoi(r2causestr) : 0;
06264             openr2_call_disconnect_cause_t r2cause = r2cause_user ? dahdi_ast_cause_to_r2_cause(r2cause_user)
06265                                                              : dahdi_ast_cause_to_r2_cause(ast->hangupcause);
06266             dahdi_r2_disconnect_call(p, r2cause);
06267          }
06268       } else if (p->mfcr2call) {
06269          ast_log(LOG_DEBUG, "Clearing call request on channel %d\n", p->channel);
06270          /* since ast_request() was called but not ast_call() we have not yet dialed
06271          and the openr2 stack will not call on_call_end callback, we need to unset
06272          the mfcr2call flag and bump the monitor count so the monitor thread can take
06273          care of this channel events from now on */
06274          p->mfcr2call = 0;
06275       }
06276 #endif
06277       switch (p->sig) {
06278       case SIG_SS7:
06279       case SIG_MFCR2:
06280       case SIG_PRI_LIB_HANDLE_CASES:
06281       case 0:
06282          break;
06283       default:
06284          res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
06285          break;
06286       }
06287       if (res < 0) {
06288          ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast->name);
06289       }
06290       switch (p->sig) {
06291       case SIG_FXOGS:
06292       case SIG_FXOLS:
06293       case SIG_FXOKS:
06294          memset(&par, 0, sizeof(par));
06295          res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
06296          if (!res) {
06297             struct analog_pvt *analog_p = p->sig_pvt;
06298 #if 0
06299             ast_debug(1, "Hanging up channel %d, offhook = %d\n", p->channel, par.rxisoffhook);
06300 #endif
06301             /* If they're off hook, try playing congestion */
06302             if ((par.rxisoffhook) && (!(p->radio || (p->oprmode < 0))))
06303                tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
06304             else
06305                tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06306             analog_p->fxsoffhookstate = par.rxisoffhook;
06307          }
06308          break;
06309       case SIG_FXSGS:
06310       case SIG_FXSLS:
06311       case SIG_FXSKS:
06312          /* Make sure we're not made available for at least two seconds assuming
06313          we were actually used for an inbound or outbound call. */
06314          if (ast->_state != AST_STATE_RESERVED) {
06315             time(&p->guardtime);
06316             p->guardtime += 2;
06317          }
06318          break;
06319       default:
06320          tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06321       }
06322       if (p->sig)
06323          dahdi_disable_ec(p);
06324       x = 0;
06325       ast_channel_setoption(ast,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0);
06326       ast_channel_setoption(ast,AST_OPTION_TDD,&x,sizeof(char),0);
06327       p->didtdd = 0;
06328       p->callwaitcas = 0;
06329       p->callwaiting = p->permcallwaiting;
06330       p->hidecallerid = p->permhidecallerid;
06331       p->waitingfordt.tv_sec = 0;
06332       p->dialing = 0;
06333       p->rdnis[0] = '\0';
06334       update_conf(p);
06335       reset_conf(p);
06336       /* Restore data mode */
06337       switch (p->sig) {
06338       case SIG_PRI_LIB_HANDLE_CASES:
06339       case SIG_SS7:
06340          x = 0;
06341          ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
06342          break;
06343       default:
06344          break;
06345       }
06346       if (num_restart_pending == 0)
06347          restart_monitor();
06348    }
06349 
06350    p->callwaitingrepeat = 0;
06351    p->cidcwexpire = 0;
06352    p->cid_suppress_expire = 0;
06353    p->oprmode = 0;
06354    ast->tech_pvt = NULL;
06355 hangup_out:
06356    ast_free(p->cidspill);
06357    p->cidspill = NULL;
06358 
06359    ast_mutex_unlock(&p->lock);
06360    ast_module_unref(ast_module_info->self);
06361    ast_verb(3, "Hungup '%s'\n", ast->name);
06362 
06363    ast_mutex_lock(&iflock);
06364 
06365    if (p->restartpending) {
06366       num_restart_pending--;
06367    }
06368 
06369    if (p->destroy) {
06370       destroy_channel(p, 0);
06371    }
06372    ast_mutex_unlock(&iflock);
06373    return 0;
06374 }
06375 
06376 static int dahdi_answer(struct ast_channel *ast)
06377 {
06378    struct dahdi_pvt *p = ast->tech_pvt;
06379    int res = 0;
06380    int idx;
06381    ast_setstate(ast, AST_STATE_UP);/*! \todo XXX this is redundantly set by the analog and PRI submodules! */
06382    ast_mutex_lock(&p->lock);
06383    idx = dahdi_get_index(ast, p, 0);
06384    if (idx < 0)
06385       idx = SUB_REAL;
06386    /* nothing to do if a radio channel */
06387    if ((p->radio || (p->oprmode < 0))) {
06388       ast_mutex_unlock(&p->lock);
06389       return 0;
06390    }
06391 
06392    if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
06393       res = analog_answer(p->sig_pvt, ast);
06394       ast_mutex_unlock(&p->lock);
06395       return res;
06396    }
06397 
06398    switch (p->sig) {
06399 #if defined(HAVE_PRI)
06400    case SIG_PRI_LIB_HANDLE_CASES:
06401       res = sig_pri_answer(p->sig_pvt, ast);
06402       break;
06403 #endif   /* defined(HAVE_PRI) */
06404 #if defined(HAVE_SS7)
06405    case SIG_SS7:
06406       res = sig_ss7_answer(p->sig_pvt, ast);
06407       break;
06408 #endif   /* defined(HAVE_SS7) */
06409 #ifdef HAVE_OPENR2
06410    case SIG_MFCR2:
06411       if (!p->mfcr2_call_accepted) {
06412          /* The call was not accepted on offer nor the user, so it must be accepted now before answering,
06413             openr2_chan_answer_call will be called when the callback on_call_accepted is executed */
06414          p->mfcr2_answer_pending = 1;
06415          if (p->mfcr2_charge_calls) {
06416             ast_log(LOG_DEBUG, "Accepting MFC/R2 call with charge before answering on chan %d\n", p->channel);
06417             openr2_chan_accept_call(p->r2chan, OR2_CALL_WITH_CHARGE);
06418          } else {
06419             ast_log(LOG_DEBUG, "Accepting MFC/R2 call with no charge before answering on chan %d\n", p->channel);
06420             openr2_chan_accept_call(p->r2chan, OR2_CALL_NO_CHARGE);
06421          }
06422       } else {
06423          ast_log(LOG_DEBUG, "Answering MFC/R2 call on chan %d\n", p->channel);
06424          dahdi_r2_answer(p);
06425       }
06426       break;
06427 #endif
06428    case 0:
06429       ast_mutex_unlock(&p->lock);
06430       return 0;
06431    default:
06432       ast_log(LOG_WARNING, "Don't know how to answer signalling %d (channel %d)\n", p->sig, p->channel);
06433       res = -1;
06434       break;
06435    }
06436    ast_mutex_unlock(&p->lock);
06437    return res;
06438 }
06439 
06440 static void disable_dtmf_detect(struct dahdi_pvt *p)
06441 {
06442    int val = 0;
06443 
06444    p->ignoredtmf = 1;
06445 
06446    ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
06447 
06448    if (!p->hardwaredtmf && p->dsp) {
06449       p->dsp_features &= ~DSP_FEATURE_DIGIT_DETECT;
06450       ast_dsp_set_features(p->dsp, p->dsp_features);
06451    }
06452 }
06453 
06454 static void enable_dtmf_detect(struct dahdi_pvt *p)
06455 {
06456    int val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
06457 
06458    if (p->channel == CHAN_PSEUDO)
06459       return;
06460 
06461    p->ignoredtmf = 0;
06462 
06463    ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
06464 
06465    if (!p->hardwaredtmf && p->dsp) {
06466       p->dsp_features |= DSP_FEATURE_DIGIT_DETECT;
06467       ast_dsp_set_features(p->dsp, p->dsp_features);
06468    }
06469 }
06470 
06471 static int dahdi_queryoption(struct ast_channel *chan, int option, void *data, int *datalen)
06472 {
06473    char *cp;
06474    struct dahdi_pvt *p = chan->tech_pvt;
06475 
06476    /* all supported options require data */
06477    if (!data || (*datalen < 1)) {
06478       errno = EINVAL;
06479       return -1;
06480    }
06481 
06482    switch (option) {
06483    case AST_OPTION_DIGIT_DETECT:
06484       cp = (char *) data;
06485       *cp = p->ignoredtmf ? 0 : 1;
06486       ast_debug(1, "Reporting digit detection %sabled on %s\n", *cp ? "en" : "dis", chan->name);
06487       break;
06488    case AST_OPTION_FAX_DETECT:
06489       cp = (char *) data;
06490       *cp = (p->dsp_features & DSP_FEATURE_FAX_DETECT) ? 0 : 1;
06491       ast_debug(1, "Reporting fax tone detection %sabled on %s\n", *cp ? "en" : "dis", chan->name);
06492       break;
06493    case AST_OPTION_CC_AGENT_TYPE:
06494 #if defined(HAVE_PRI)
06495 #if defined(HAVE_PRI_CCSS)
06496       if (dahdi_sig_pri_lib_handles(p->sig)) {
06497          ast_copy_string((char *) data, dahdi_pri_cc_type, *datalen);
06498          break;
06499       }
06500 #endif   /* defined(HAVE_PRI_CCSS) */
06501 #endif   /* defined(HAVE_PRI) */
06502       return -1;
06503    default:
06504       return -1;
06505    }
06506 
06507    errno = 0;
06508 
06509    return 0;
06510 }
06511 
06512 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen)
06513 {
06514    char *cp;
06515    signed char *scp;
06516    int x;
06517    int idx;
06518    struct dahdi_pvt *p = chan->tech_pvt, *pp;
06519    struct oprmode *oprmode;
06520 
06521 
06522    /* all supported options require data */
06523    if (!data || (datalen < 1)) {
06524       errno = EINVAL;
06525       return -1;
06526    }
06527 
06528    switch (option) {
06529    case AST_OPTION_TXGAIN:
06530       scp = (signed char *) data;
06531       idx = dahdi_get_index(chan, p, 0);
06532       if (idx < 0) {
06533          ast_log(LOG_WARNING, "No index in TXGAIN?\n");
06534          return -1;
06535       }
06536       ast_debug(1, "Setting actual tx gain on %s to %f\n", chan->name, p->txgain + (float) *scp);
06537       return set_actual_txgain(p->subs[idx].dfd, p->txgain + (float) *scp, p->txdrc, p->law);
06538    case AST_OPTION_RXGAIN:
06539       scp = (signed char *) data;
06540       idx = dahdi_get_index(chan, p, 0);
06541       if (idx < 0) {
06542          ast_log(LOG_WARNING, "No index in RXGAIN?\n");
06543          return -1;
06544       }
06545       ast_debug(1, "Setting actual rx gain on %s to %f\n", chan->name, p->rxgain + (float) *scp);
06546       return set_actual_rxgain(p->subs[idx].dfd, p->rxgain + (float) *scp, p->rxdrc, p->law);
06547    case AST_OPTION_TONE_VERIFY:
06548       if (!p->dsp)
06549          break;
06550       cp = (char *) data;
06551       switch (*cp) {
06552       case 1:
06553          ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",chan->name);
06554          ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | p->dtmfrelax);  /* set mute mode if desired */
06555          break;
06556       case 2:
06557          ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",chan->name);
06558          ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX | p->dtmfrelax);  /* set mute mode if desired */
06559          break;
06560       default:
06561          ast_debug(1, "Set option TONE VERIFY, mode: OFF(0) on %s\n",chan->name);
06562          ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);  /* set mute mode if desired */
06563          break;
06564       }
06565       break;
06566    case AST_OPTION_TDD:
06567       /* turn on or off TDD */
06568       cp = (char *) data;
06569       p->mate = 0;
06570       if (!*cp) { /* turn it off */
06571          ast_debug(1, "Set option TDD MODE, value: OFF(0) on %s\n",chan->name);
06572          if (p->tdd)
06573             tdd_free(p->tdd);
06574          p->tdd = 0;
06575          break;
06576       }
06577       ast_debug(1, "Set option TDD MODE, value: %s(%d) on %s\n",
06578          (*cp == 2) ? "MATE" : "ON", (int) *cp, chan->name);
06579       dahdi_disable_ec(p);
06580       /* otherwise, turn it on */
06581       if (!p->didtdd) { /* if havent done it yet */
06582          unsigned char mybuf[41000];/*! \todo XXX This is an abuse of the stack!! */
06583          unsigned char *buf;
06584          int size, res, fd, len;
06585          struct pollfd fds[1];
06586 
06587          buf = mybuf;
06588          memset(buf, 0x7f, sizeof(mybuf)); /* set to silence */
06589          ast_tdd_gen_ecdisa(buf + 16000, 16000);  /* put in tone */
06590          len = 40000;
06591          idx = dahdi_get_index(chan, p, 0);
06592          if (idx < 0) {
06593             ast_log(LOG_WARNING, "No index in TDD?\n");
06594             return -1;
06595          }
06596          fd = p->subs[idx].dfd;
06597          while (len) {
06598             if (ast_check_hangup(chan))
06599                return -1;
06600             size = len;
06601             if (size > READ_SIZE)
06602                size = READ_SIZE;
06603             fds[0].fd = fd;
06604             fds[0].events = POLLPRI | POLLOUT;
06605             fds[0].revents = 0;
06606             res = poll(fds, 1, -1);
06607             if (!res) {
06608                ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
06609                continue;
06610             }
06611             /* if got exception */
06612             if (fds[0].revents & POLLPRI)
06613                return -1;
06614             if (!(fds[0].revents & POLLOUT)) {
06615                ast_debug(1, "write fd not ready on channel %d\n", p->channel);
06616                continue;
06617             }
06618             res = write(fd, buf, size);
06619             if (res != size) {
06620                if (res == -1) return -1;
06621                ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
06622                break;
06623             }
06624             len -= size;
06625             buf += size;
06626          }
06627          p->didtdd = 1; /* set to have done it now */
06628       }
06629       if (*cp == 2) { /* Mate mode */
06630          if (p->tdd)
06631             tdd_free(p->tdd);
06632          p->tdd = 0;
06633          p->mate = 1;
06634          break;
06635       }
06636       if (!p->tdd) { /* if we don't have one yet */
06637          p->tdd = tdd_new(); /* allocate one */
06638       }
06639       break;
06640    case AST_OPTION_RELAXDTMF:  /* Relax DTMF decoding (or not) */
06641       if (!p->dsp)
06642          break;
06643       cp = (char *) data;
06644       ast_debug(1, "Set option RELAX DTMF, value: %s(%d) on %s\n",
06645          *cp ? "ON" : "OFF", (int) *cp, chan->name);
06646       ast_dsp_set_digitmode(p->dsp, ((*cp) ? DSP_DIGITMODE_RELAXDTMF : DSP_DIGITMODE_DTMF) | p->dtmfrelax);
06647       break;
06648    case AST_OPTION_AUDIO_MODE:  /* Set AUDIO mode (or not) */
06649 #if defined(HAVE_PRI)
06650       if (dahdi_sig_pri_lib_handles(p->sig)
06651          && ((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
06652          /* PRI nobch pseudo channel.  Does not handle ioctl(DAHDI_AUDIOMODE) */
06653          break;
06654       }
06655 #endif   /* defined(HAVE_PRI) */
06656 
06657       cp = (char *) data;
06658       if (!*cp) {
06659          ast_debug(1, "Set option AUDIO MODE, value: OFF(0) on %s\n", chan->name);
06660          x = 0;
06661          dahdi_disable_ec(p);
06662       } else {
06663          ast_debug(1, "Set option AUDIO MODE, value: ON(1) on %s\n", chan->name);
06664          x = 1;
06665       }
06666       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x) == -1)
06667          ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, x, strerror(errno));
06668       break;
06669    case AST_OPTION_OPRMODE:  /* Operator services mode */
06670       oprmode = (struct oprmode *) data;
06671       /* We don't support operator mode across technologies */
06672       if (strcasecmp(chan->tech->type, oprmode->peer->tech->type)) {
06673          ast_log(LOG_NOTICE, "Operator mode not supported on %s to %s calls.\n",
06674                chan->tech->type, oprmode->peer->tech->type);
06675          errno = EINVAL;
06676          return -1;
06677       }
06678       pp = oprmode->peer->tech_pvt;
06679       p->oprmode = pp->oprmode = 0;
06680       /* setup peers */
06681       p->oprpeer = pp;
06682       pp->oprpeer = p;
06683       /* setup modes, if any */
06684       if (oprmode->mode)
06685       {
06686          pp->oprmode = oprmode->mode;
06687          p->oprmode = -oprmode->mode;
06688       }
06689       ast_debug(1, "Set Operator Services mode, value: %d on %s/%s\n",
06690          oprmode->mode, chan->name,oprmode->peer->name);
06691       break;
06692    case AST_OPTION_ECHOCAN:
06693       cp = (char *) data;
06694       if (*cp) {
06695          ast_debug(1, "Enabling echo cancellation on %s\n", chan->name);
06696          dahdi_enable_ec(p);
06697       } else {
06698          ast_debug(1, "Disabling echo cancellation on %s\n", chan->name);
06699          dahdi_disable_ec(p);
06700       }
06701       break;
06702    case AST_OPTION_DIGIT_DETECT:
06703       cp = (char *) data;
06704       ast_debug(1, "%sabling digit detection on %s\n", *cp ? "En" : "Dis", chan->name);
06705       if (*cp) {
06706          enable_dtmf_detect(p);
06707       } else {
06708          disable_dtmf_detect(p);
06709       }
06710       break;
06711    case AST_OPTION_FAX_DETECT:
06712       cp = (char *) data;
06713       if (p->dsp) {
06714          ast_debug(1, "%sabling fax tone detection on %s\n", *cp ? "En" : "Dis", chan->name);
06715          if (*cp) {
06716             p->dsp_features |= DSP_FEATURE_FAX_DETECT;
06717          } else {
06718             p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
06719          }
06720          ast_dsp_set_features(p->dsp, p->dsp_features);
06721       }
06722       break;
06723    default:
06724       return -1;
06725    }
06726    errno = 0;
06727 
06728    return 0;
06729 }
06730 
06731 static int dahdi_func_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len)
06732 {
06733    struct dahdi_pvt *p = chan->tech_pvt;
06734    int res = 0;
06735 
06736    if (!strcasecmp(data, "rxgain")) {
06737       ast_mutex_lock(&p->lock);
06738       snprintf(buf, len, "%f", p->rxgain);
06739       ast_mutex_unlock(&p->lock);
06740    } else if (!strcasecmp(data, "txgain")) {
06741       ast_mutex_lock(&p->lock);
06742       snprintf(buf, len, "%f", p->txgain);
06743       ast_mutex_unlock(&p->lock);
06744 #if defined(HAVE_PRI)
06745 #if defined(HAVE_PRI_REVERSE_CHARGE)
06746    } else if (!strcasecmp(data, "reversecharge")) {
06747       ast_mutex_lock(&p->lock);
06748       switch (p->sig) {
06749       case SIG_PRI_LIB_HANDLE_CASES:
06750          snprintf(buf, len, "%d", ((struct sig_pri_chan *) p->sig_pvt)->reverse_charging_indication);
06751          break;
06752       default:
06753          *buf = '\0';
06754          res = -1;
06755          break;
06756       }
06757       ast_mutex_unlock(&p->lock);
06758 #endif
06759 #if defined(HAVE_PRI_SETUP_KEYPAD)
06760    } else if (!strcasecmp(data, "keypad_digits")) {
06761       ast_mutex_lock(&p->lock);
06762       switch (p->sig) {
06763       case SIG_PRI_LIB_HANDLE_CASES:
06764          ast_copy_string(buf, ((struct sig_pri_chan *) p->sig_pvt)->keypad_digits,
06765             len);
06766          break;
06767       default:
06768          *buf = '\0';
06769          res = -1;
06770          break;
06771       }
06772       ast_mutex_unlock(&p->lock);
06773 #endif   /* defined(HAVE_PRI_SETUP_KEYPAD) */
06774    } else if (!strcasecmp(data, "no_media_path")) {
06775       ast_mutex_lock(&p->lock);
06776       switch (p->sig) {
06777       case SIG_PRI_LIB_HANDLE_CASES:
06778          /*
06779           * TRUE if the call is on hold or is call waiting because
06780           * there is no media path available.
06781           */
06782          snprintf(buf, len, "%d", ((struct sig_pri_chan *) p->sig_pvt)->no_b_channel);
06783          break;
06784       default:
06785          *buf = '\0';
06786          res = -1;
06787          break;
06788       }
06789       ast_mutex_unlock(&p->lock);
06790 #endif   /* defined(HAVE_PRI) */
06791    } else {
06792       *buf = '\0';
06793       res = -1;
06794    }
06795 
06796    return res;
06797 }
06798 
06799 
06800 static int parse_buffers_policy(const char *parse, int *num_buffers, int *policy)
06801 {
06802    int res;
06803    char policy_str[21] = "";
06804 
06805    if ((res = sscanf(parse, "%30d,%20s", num_buffers, policy_str)) != 2) {
06806       ast_log(LOG_WARNING, "Parsing buffer string '%s' failed.\n", parse);
06807       return 1;
06808    }
06809    if (*num_buffers < 0) {
06810       ast_log(LOG_WARNING, "Invalid buffer count given '%d'.\n", *num_buffers);
06811       return -1;
06812    }
06813    if (!strcasecmp(policy_str, "full")) {
06814       *policy = DAHDI_POLICY_WHEN_FULL;
06815    } else if (!strcasecmp(policy_str, "immediate")) {
06816       *policy = DAHDI_POLICY_IMMEDIATE;
06817 #if defined(HAVE_DAHDI_HALF_FULL)
06818    } else if (!strcasecmp(policy_str, "half")) {
06819       *policy = DAHDI_POLICY_HALF_FULL;
06820 #endif
06821    } else {
06822       ast_log(LOG_WARNING, "Invalid policy name given '%s'.\n", policy_str);
06823       return -1;
06824    }
06825 
06826    return 0;
06827 }
06828 
06829 static int dahdi_func_write(struct ast_channel *chan, const char *function, char *data, const char *value)
06830 {
06831    struct dahdi_pvt *p = chan->tech_pvt;
06832    int res = 0;
06833 
06834    if (!strcasecmp(data, "buffers")) {
06835       int num_bufs, policy;
06836 
06837       if (!(parse_buffers_policy(value, &num_bufs, &policy))) {
06838          struct dahdi_bufferinfo bi = {
06839             .txbufpolicy = policy,
06840             .rxbufpolicy = policy,
06841             .bufsize = p->bufsize,
06842             .numbufs = num_bufs,
06843          };
06844          int bpres;
06845 
06846          if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
06847             ast_log(LOG_WARNING, "Channel '%d' unable to override buffer policy: %s\n", p->channel, strerror(errno));
06848          } else {
06849             p->bufferoverrideinuse = 1;
06850          }
06851       } else {
06852          res = -1;
06853       }
06854    } else if (!strcasecmp(data, "echocan_mode")) {
06855       if (!strcasecmp(value, "on")) {
06856          ast_mutex_lock(&p->lock);
06857          dahdi_enable_ec(p);
06858          ast_mutex_unlock(&p->lock);
06859       } else if (!strcasecmp(value, "off")) {
06860          ast_mutex_lock(&p->lock);
06861          dahdi_disable_ec(p);
06862          ast_mutex_unlock(&p->lock);
06863 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
06864       } else if (!strcasecmp(value, "fax")) {
06865          int blah = 1;
06866 
06867          ast_mutex_lock(&p->lock);
06868          if (!p->echocanon) {
06869             dahdi_enable_ec(p);
06870          }
06871          if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_FAX_MODE, &blah)) {
06872             ast_log(LOG_WARNING, "Unable to place echocan into fax mode on channel %d: %s\n", p->channel, strerror(errno));
06873          }
06874          ast_mutex_unlock(&p->lock);
06875       } else if (!strcasecmp(value, "voice")) {
06876          int blah = 0;
06877 
06878          ast_mutex_lock(&p->lock);
06879          if (!p->echocanon) {
06880             dahdi_enable_ec(p);
06881          }
06882          if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_FAX_MODE, &blah)) {
06883             ast_log(LOG_WARNING, "Unable to place echocan into voice mode on channel %d: %s\n", p->channel, strerror(errno));
06884          }
06885          ast_mutex_unlock(&p->lock);
06886 #endif
06887       } else {
06888          ast_log(LOG_WARNING, "Unsupported value '%s' provided for '%s' item.\n", value, data);
06889          res = -1;
06890       }
06891    } else {
06892       res = -1;
06893    }
06894 
06895    return res;
06896 }
06897 
06898 static void dahdi_unlink(struct dahdi_pvt *slave, struct dahdi_pvt *master, int needlock)
06899 {
06900    /* Unlink a specific slave or all slaves/masters from a given master */
06901    int x;
06902    int hasslaves;
06903    if (!master)
06904       return;
06905    if (needlock) {
06906       ast_mutex_lock(&master->lock);
06907       if (slave) {
06908          while (ast_mutex_trylock(&slave->lock)) {
06909             DEADLOCK_AVOIDANCE(&master->lock);
06910          }
06911       }
06912    }
06913    hasslaves = 0;
06914    for (x = 0; x < MAX_SLAVES; x++) {
06915       if (master->slaves[x]) {
06916          if (!slave || (master->slaves[x] == slave)) {
06917             /* Take slave out of the conference */
06918             ast_debug(1, "Unlinking slave %d from %d\n", master->slaves[x]->channel, master->channel);
06919             conf_del(master, &master->slaves[x]->subs[SUB_REAL], SUB_REAL);
06920             conf_del(master->slaves[x], &master->subs[SUB_REAL], SUB_REAL);
06921             master->slaves[x]->master = NULL;
06922             master->slaves[x] = NULL;
06923          } else
06924             hasslaves = 1;
06925       }
06926       if (!hasslaves)
06927          master->inconference = 0;
06928    }
06929    if (!slave) {
06930       if (master->master) {
06931          /* Take master out of the conference */
06932          conf_del(master->master, &master->subs[SUB_REAL], SUB_REAL);
06933          conf_del(master, &master->master->subs[SUB_REAL], SUB_REAL);
06934          hasslaves = 0;
06935          for (x = 0; x < MAX_SLAVES; x++) {
06936             if (master->master->slaves[x] == master)
06937                master->master->slaves[x] = NULL;
06938             else if (master->master->slaves[x])
06939                hasslaves = 1;
06940          }
06941          if (!hasslaves)
06942             master->master->inconference = 0;
06943       }
06944       master->master = NULL;
06945    }
06946    update_conf(master);
06947    if (needlock) {
06948       if (slave)
06949          ast_mutex_unlock(&slave->lock);
06950       ast_mutex_unlock(&master->lock);
06951    }
06952 }
06953 
06954 static void dahdi_link(struct dahdi_pvt *slave, struct dahdi_pvt *master) {
06955    int x;
06956    if (!slave || !master) {
06957       ast_log(LOG_WARNING, "Tried to link to/from NULL??\n");
06958       return;
06959    }
06960    for (x = 0; x < MAX_SLAVES; x++) {
06961       if (!master->slaves[x]) {
06962          master->slaves[x] = slave;
06963          break;
06964       }
06965    }
06966    if (x >= MAX_SLAVES) {
06967       ast_log(LOG_WARNING, "Replacing slave %d with new slave, %d\n", master->slaves[MAX_SLAVES - 1]->channel, slave->channel);
06968       master->slaves[MAX_SLAVES - 1] = slave;
06969    }
06970    if (slave->master)
06971       ast_log(LOG_WARNING, "Replacing master %d with new master, %d\n", slave->master->channel, master->channel);
06972    slave->master = master;
06973 
06974    ast_debug(1, "Making %d slave to master %d at %d\n", slave->channel, master->channel, x);
06975 }
06976 
06977 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)
06978 {
06979    struct ast_channel *who;
06980    struct dahdi_pvt *p0, *p1, *op0, *op1;
06981    struct dahdi_pvt *master = NULL, *slave = NULL;
06982    struct ast_frame *f;
06983    int inconf = 0;
06984    int nothingok = 1;
06985    int ofd0, ofd1;
06986    int oi0, oi1, i0 = -1, i1 = -1, t0, t1;
06987    int os0 = -1, os1 = -1;
06988    int priority = 0;
06989    struct ast_channel *oc0, *oc1;
06990    enum ast_bridge_result res;
06991 #ifdef PRI_2BCT
06992    int triedtopribridge = 0;
06993    q931_call *q931c0;
06994    q931_call *q931c1;
06995 #endif
06996 
06997    /* For now, don't attempt to native bridge if either channel needs DTMF detection.
06998       There is code below to handle it properly until DTMF is actually seen,
06999       but due to currently unresolved issues it's ignored...
07000    */
07001 
07002    if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1))
07003       return AST_BRIDGE_FAILED_NOWARN;
07004 
07005    ast_channel_lock(c0);
07006    while (ast_channel_trylock(c1)) {
07007       CHANNEL_DEADLOCK_AVOIDANCE(c0);
07008    }
07009 
07010    p0 = c0->tech_pvt;
07011    p1 = c1->tech_pvt;
07012    /* cant do pseudo-channels here */
07013    if (!p0 || (!p0->sig) || !p1 || (!p1->sig)) {
07014       ast_channel_unlock(c0);
07015       ast_channel_unlock(c1);
07016       return AST_BRIDGE_FAILED_NOWARN;
07017    }
07018 
07019    oi0 = dahdi_get_index(c0, p0, 0);
07020    oi1 = dahdi_get_index(c1, p1, 0);
07021    if ((oi0 < 0) || (oi1 < 0)) {
07022       ast_channel_unlock(c0);
07023       ast_channel_unlock(c1);
07024       return AST_BRIDGE_FAILED;
07025    }
07026 
07027    op0 = p0 = c0->tech_pvt;
07028    op1 = p1 = c1->tech_pvt;
07029    ofd0 = c0->fds[0];
07030    ofd1 = c1->fds[0];
07031    oc0 = p0->owner;
07032    oc1 = p1->owner;
07033 
07034    if (ast_mutex_trylock(&p0->lock)) {
07035       /* Don't block, due to potential for deadlock */
07036       ast_channel_unlock(c0);
07037       ast_channel_unlock(c1);
07038       ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
07039       return AST_BRIDGE_RETRY;
07040    }
07041    if (ast_mutex_trylock(&p1->lock)) {
07042       /* Don't block, due to potential for deadlock */
07043       ast_mutex_unlock(&p0->lock);
07044       ast_channel_unlock(c0);
07045       ast_channel_unlock(c1);
07046       ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
07047       return AST_BRIDGE_RETRY;
07048    }
07049 
07050    if ((p0->callwaiting && p0->callwaitingcallerid)
07051       || (p1->callwaiting && p1->callwaitingcallerid)) {
07052       /*
07053        * Call Waiting Caller ID requires DTMF detection to know if it
07054        * can send the CID spill.
07055        *
07056        * For now, don't attempt to native bridge if either channel
07057        * needs DTMF detection.  There is code below to handle it
07058        * properly until DTMF is actually seen, but due to currently
07059        * unresolved issues it's ignored...
07060        */
07061       ast_mutex_unlock(&p0->lock);
07062       ast_mutex_unlock(&p1->lock);
07063       ast_channel_unlock(c0);
07064       ast_channel_unlock(c1);
07065       return AST_BRIDGE_FAILED_NOWARN;
07066    }
07067 
07068 #if defined(HAVE_PRI)
07069    if ((dahdi_sig_pri_lib_handles(p0->sig)
07070          && ((struct sig_pri_chan *) p0->sig_pvt)->no_b_channel)
07071       || (dahdi_sig_pri_lib_handles(p1->sig)
07072          && ((struct sig_pri_chan *) p1->sig_pvt)->no_b_channel)) {
07073       /*
07074        * PRI nobch channels (hold and call waiting) are equivalent to
07075        * pseudo channels and cannot be done here.
07076        */
07077       ast_mutex_unlock(&p0->lock);
07078       ast_mutex_unlock(&p1->lock);
07079       ast_channel_unlock(c0);
07080       ast_channel_unlock(c1);
07081       return AST_BRIDGE_FAILED_NOWARN;
07082    }
07083 #endif   /* defined(HAVE_PRI) */
07084 
07085    if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
07086       if (p0->owner && p1->owner) {
07087          /* If we don't have a call-wait in a 3-way, and we aren't in a 3-way, we can be master */
07088          if (!p0->subs[SUB_CALLWAIT].inthreeway && !p1->subs[SUB_REAL].inthreeway) {
07089             master = p0;
07090             slave = p1;
07091             inconf = 1;
07092          } else if (!p1->subs[SUB_CALLWAIT].inthreeway && !p0->subs[SUB_REAL].inthreeway) {
07093             master = p1;
07094             slave = p0;
07095             inconf = 1;
07096          } else {
07097             ast_log(LOG_WARNING, "Huh?  Both calls are callwaits or 3-ways?  That's clever...?\n");
07098             ast_log(LOG_WARNING, "p0: chan %d/%d/CW%d/3W%d, p1: chan %d/%d/CW%d/3W%d\n",
07099                p0->channel,
07100                oi0, (p0->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
07101                p0->subs[SUB_REAL].inthreeway, p0->channel,
07102                oi0, (p1->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
07103                p1->subs[SUB_REAL].inthreeway);
07104          }
07105          nothingok = 0;
07106       }
07107    } else if ((oi0 == SUB_REAL) && (oi1 == SUB_THREEWAY)) {
07108       if (p1->subs[SUB_THREEWAY].inthreeway) {
07109          master = p1;
07110          slave = p0;
07111          nothingok = 0;
07112       }
07113    } else if ((oi0 == SUB_THREEWAY) && (oi1 == SUB_REAL)) {
07114       if (p0->subs[SUB_THREEWAY].inthreeway) {
07115          master = p0;
07116          slave = p1;
07117          nothingok = 0;
07118       }
07119    } else if ((oi0 == SUB_REAL) && (oi1 == SUB_CALLWAIT)) {
07120       /* We have a real and a call wait.  If we're in a three way call, put us in it, otherwise,
07121          don't put us in anything */
07122       if (p1->subs[SUB_CALLWAIT].inthreeway) {
07123          master = p1;
07124          slave = p0;
07125          nothingok = 0;
07126       }
07127    } else if ((oi0 == SUB_CALLWAIT) && (oi1 == SUB_REAL)) {
07128       /* Same as previous */
07129       if (p0->subs[SUB_CALLWAIT].inthreeway) {
07130          master = p0;
07131          slave = p1;
07132          nothingok = 0;
07133       }
07134    }
07135    ast_debug(1, "master: %d, slave: %d, nothingok: %d\n",
07136       master ? master->channel : 0, slave ? slave->channel : 0, nothingok);
07137    if (master && slave) {
07138       /* Stop any tones, or play ringtone as appropriate.  If they're bridged
07139          in an active threeway call with a channel that is ringing, we should
07140          indicate ringing. */
07141       if ((oi1 == SUB_THREEWAY) &&
07142          p1->subs[SUB_THREEWAY].inthreeway &&
07143          p1->subs[SUB_REAL].owner &&
07144          p1->subs[SUB_REAL].inthreeway &&
07145          (p1->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
07146          ast_debug(1,
07147             "Playing ringback on %d/%d(%s) since %d/%d(%s) is in a ringing three-way\n",
07148             p0->channel, oi0, c0->name, p1->channel, oi1, c1->name);
07149          tone_zone_play_tone(p0->subs[oi0].dfd, DAHDI_TONE_RINGTONE);
07150          os1 = p1->subs[SUB_REAL].owner->_state;
07151       } else {
07152          ast_debug(1, "Stopping tones on %d/%d(%s) talking to %d/%d(%s)\n",
07153             p0->channel, oi0, c0->name, p1->channel, oi1, c1->name);
07154          tone_zone_play_tone(p0->subs[oi0].dfd, -1);
07155       }
07156       if ((oi0 == SUB_THREEWAY) &&
07157          p0->subs[SUB_THREEWAY].inthreeway &&
07158          p0->subs[SUB_REAL].owner &&
07159          p0->subs[SUB_REAL].inthreeway &&
07160          (p0->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
07161          ast_debug(1,
07162             "Playing ringback on %d/%d(%s) since %d/%d(%s) is in a ringing three-way\n",
07163             p1->channel, oi1, c1->name, p0->channel, oi0, c0->name);
07164          tone_zone_play_tone(p1->subs[oi1].dfd, DAHDI_TONE_RINGTONE);
07165          os0 = p0->subs[SUB_REAL].owner->_state;
07166       } else {
07167          ast_debug(1, "Stopping tones on %d/%d(%s) talking to %d/%d(%s)\n",
07168             p1->channel, oi1, c1->name, p0->channel, oi0, c0->name);
07169          tone_zone_play_tone(p1->subs[oi1].dfd, -1);
07170       }
07171       if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
07172          if (!p0->echocanbridged || !p1->echocanbridged) {
07173             /* Disable echo cancellation if appropriate */
07174             dahdi_disable_ec(p0);
07175             dahdi_disable_ec(p1);
07176          }
07177       }
07178       dahdi_link(slave, master);
07179       master->inconference = inconf;
07180    } else if (!nothingok)
07181       ast_log(LOG_WARNING, "Can't link %d/%s with %d/%s\n", p0->channel, subnames[oi0], p1->channel, subnames[oi1]);
07182 
07183    update_conf(p0);
07184    update_conf(p1);
07185    t0 = p0->subs[SUB_REAL].inthreeway;
07186    t1 = p1->subs[SUB_REAL].inthreeway;
07187 
07188    ast_mutex_unlock(&p0->lock);
07189    ast_mutex_unlock(&p1->lock);
07190 
07191    ast_channel_unlock(c0);
07192    ast_channel_unlock(c1);
07193 
07194    /* Native bridge failed */
07195    if ((!master || !slave) && !nothingok) {
07196       dahdi_enable_ec(p0);
07197       dahdi_enable_ec(p1);
07198       return AST_BRIDGE_FAILED;
07199    }
07200 
07201    ast_verb(3, "Native bridging %s and %s\n", c0->name, c1->name);
07202 
07203    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
07204       disable_dtmf_detect(op0);
07205 
07206    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
07207       disable_dtmf_detect(op1);
07208 
07209    for (;;) {
07210       struct ast_channel *c0_priority[2] = {c0, c1};
07211       struct ast_channel *c1_priority[2] = {c1, c0};
07212 
07213       /* Here's our main loop...  Start by locking things, looking for private parts,
07214          and then balking if anything is wrong */
07215 
07216       ast_channel_lock(c0);
07217       while (ast_channel_trylock(c1)) {
07218          CHANNEL_DEADLOCK_AVOIDANCE(c0);
07219       }
07220 
07221       p0 = c0->tech_pvt;
07222       p1 = c1->tech_pvt;
07223 
07224       if (op0 == p0)
07225          i0 = dahdi_get_index(c0, p0, 1);
07226       if (op1 == p1)
07227          i1 = dahdi_get_index(c1, p1, 1);
07228 
07229       ast_channel_unlock(c0);
07230       ast_channel_unlock(c1);
07231 
07232       if (!timeoutms ||
07233          (op0 != p0) ||
07234          (op1 != p1) ||
07235          (ofd0 != c0->fds[0]) ||
07236          (ofd1 != c1->fds[0]) ||
07237          (p0->subs[SUB_REAL].owner && (os0 > -1) && (os0 != p0->subs[SUB_REAL].owner->_state)) ||
07238          (p1->subs[SUB_REAL].owner && (os1 > -1) && (os1 != p1->subs[SUB_REAL].owner->_state)) ||
07239          (oc0 != p0->owner) ||
07240          (oc1 != p1->owner) ||
07241          (t0 != p0->subs[SUB_REAL].inthreeway) ||
07242          (t1 != p1->subs[SUB_REAL].inthreeway) ||
07243          (oi0 != i0) ||
07244          (oi1 != i1)) {
07245          ast_debug(1, "Something changed out on %d/%d to %d/%d, returning -3 to restart\n",
07246             op0->channel, oi0, op1->channel, oi1);
07247          res = AST_BRIDGE_RETRY;
07248          goto return_from_bridge;
07249       }
07250 
07251 #ifdef PRI_2BCT
07252       if (!triedtopribridge) {
07253          triedtopribridge = 1;
07254          if (p0->pri && p0->pri == p1->pri && p0->pri->transfer) {
07255             ast_mutex_lock(&p0->pri->lock);
07256             switch (p0->sig) {
07257             case SIG_PRI_LIB_HANDLE_CASES:
07258                q931c0 = ((struct sig_pri_chan *) (p0->sig_pvt))->call;
07259                break;
07260             default:
07261                q931c0 = NULL;
07262                break;
07263             }
07264             switch (p1->sig) {
07265             case SIG_PRI_LIB_HANDLE_CASES:
07266                q931c1 = ((struct sig_pri_chan *) (p1->sig_pvt))->call;
07267                break;
07268             default:
07269                q931c1 = NULL;
07270                break;
07271             }
07272             if (q931c0 && q931c1) {
07273                pri_channel_bridge(q931c0, q931c1);
07274             }
07275             ast_mutex_unlock(&p0->pri->lock);
07276          }
07277       }
07278 #endif
07279 
07280       who = ast_waitfor_n(priority ? c0_priority : c1_priority, 2, &timeoutms);
07281       if (!who) {
07282          ast_debug(1, "Ooh, empty read...\n");
07283          continue;
07284       }
07285       f = ast_read(who);
07286       if (!f || (f->frametype == AST_FRAME_CONTROL)) {
07287          *fo = f;
07288          *rc = who;
07289          res = AST_BRIDGE_COMPLETE;
07290          goto return_from_bridge;
07291       }
07292       if (f->frametype == AST_FRAME_DTMF) {
07293          if ((who == c0) && p0->pulsedial) {
07294             ast_write(c1, f);
07295          } else if ((who == c1) && p1->pulsedial) {
07296             ast_write(c0, f);
07297          } else {
07298             *fo = f;
07299             *rc = who;
07300             res = AST_BRIDGE_COMPLETE;
07301             goto return_from_bridge;
07302          }
07303       }
07304       ast_frfree(f);
07305 
07306       /* Swap who gets priority */
07307       priority = !priority;
07308    }
07309 
07310 return_from_bridge:
07311    if (op0 == p0)
07312       dahdi_enable_ec(p0);
07313 
07314    if (op1 == p1)
07315       dahdi_enable_ec(p1);
07316 
07317    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
07318       enable_dtmf_detect(op0);
07319 
07320    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
07321       enable_dtmf_detect(op1);
07322 
07323    dahdi_unlink(slave, master, 1);
07324 
07325    return res;
07326 }
07327 
07328 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
07329 {
07330    struct dahdi_pvt *p = newchan->tech_pvt;
07331    int x;
07332 
07333    ast_mutex_lock(&p->lock);
07334 
07335    ast_debug(1, "New owner for channel %d is %s\n", p->channel, newchan->name);
07336    if (p->owner == oldchan) {
07337       p->owner = newchan;
07338    }
07339    for (x = 0; x < 3; x++) {
07340       if (p->subs[x].owner == oldchan) {
07341          if (!x) {
07342             dahdi_unlink(NULL, p, 0);
07343          }
07344          p->subs[x].owner = newchan;
07345       }
07346    }
07347    if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
07348       analog_fixup(oldchan, newchan, p->sig_pvt);
07349 #if defined(HAVE_PRI)
07350    } else if (dahdi_sig_pri_lib_handles(p->sig)) {
07351       sig_pri_fixup(oldchan, newchan, p->sig_pvt);
07352 #endif   /* defined(HAVE_PRI) */
07353 #if defined(HAVE_SS7)
07354    } else if (p->sig == SIG_SS7) {
07355       sig_ss7_fixup(oldchan, newchan, p->sig_pvt);
07356 #endif   /* defined(HAVE_SS7) */
07357    }
07358    update_conf(p);
07359 
07360    ast_mutex_unlock(&p->lock);
07361 
07362    if (newchan->_state == AST_STATE_RINGING) {
07363       dahdi_indicate(newchan, AST_CONTROL_RINGING, NULL, 0);
07364    }
07365    return 0;
07366 }
07367 
07368 static int dahdi_ring_phone(struct dahdi_pvt *p)
07369 {
07370    int x;
07371    int res;
07372    /* Make sure our transmit state is on hook */
07373    x = 0;
07374    x = DAHDI_ONHOOK;
07375    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
07376    do {
07377       x = DAHDI_RING;
07378       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
07379       if (res) {
07380          switch (errno) {
07381          case EBUSY:
07382          case EINTR:
07383             /* Wait just in case */
07384             usleep(10000);
07385             continue;
07386          case EINPROGRESS:
07387             res = 0;
07388             break;
07389          default:
07390             ast_log(LOG_WARNING, "Couldn't ring the phone: %s\n", strerror(errno));
07391             res = 0;
07392          }
07393       }
07394    } while (res);
07395    return res;
07396 }
07397 
07398 static void *analog_ss_thread(void *data);
07399 
07400 static int attempt_transfer(struct dahdi_pvt *p)
07401 {
07402    /* In order to transfer, we need at least one of the channels to
07403       actually be in a call bridge.  We can't conference two applications
07404       together (but then, why would we want to?) */
07405    if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
07406       /* The three-way person we're about to transfer to could still be in MOH, so
07407          stop if now if appropriate */
07408       if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner))
07409          ast_queue_control(p->subs[SUB_THREEWAY].owner, AST_CONTROL_UNHOLD);
07410       if (p->subs[SUB_REAL].owner->_state == AST_STATE_RINGING) {
07411          ast_indicate(ast_bridged_channel(p->subs[SUB_REAL].owner), AST_CONTROL_RINGING);
07412       }
07413       if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RING) {
07414          tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE);
07415       }
07416        if (ast_channel_masquerade(p->subs[SUB_THREEWAY].owner, ast_bridged_channel(p->subs[SUB_REAL].owner))) {
07417          ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
07418                ast_bridged_channel(p->subs[SUB_REAL].owner)->name, p->subs[SUB_THREEWAY].owner->name);
07419          return -1;
07420       }
07421       /* Orphan the channel after releasing the lock */
07422       ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
07423       unalloc_sub(p, SUB_THREEWAY);
07424    } else if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
07425       ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
07426       if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RINGING) {
07427          ast_indicate(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), AST_CONTROL_RINGING);
07428       }
07429       if (p->subs[SUB_REAL].owner->_state == AST_STATE_RING) {
07430          tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
07431       }
07432       if (ast_channel_masquerade(p->subs[SUB_REAL].owner, ast_bridged_channel(p->subs[SUB_THREEWAY].owner))) {
07433          ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
07434                ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->name, p->subs[SUB_REAL].owner->name);
07435          return -1;
07436       }
07437       /* Three-way is now the REAL */
07438       swap_subs(p, SUB_THREEWAY, SUB_REAL);
07439       ast_channel_unlock(p->subs[SUB_REAL].owner);
07440       unalloc_sub(p, SUB_THREEWAY);
07441       /* Tell the caller not to hangup */
07442       return 1;
07443    } else {
07444       ast_debug(1, "Neither %s nor %s are in a bridge, nothing to transfer\n",
07445          p->subs[SUB_REAL].owner->name, p->subs[SUB_THREEWAY].owner->name);
07446       p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
07447       return -1;
07448    }
07449    return 0;
07450 }
07451 
07452 static int check_for_conference(struct dahdi_pvt *p)
07453 {
07454    struct dahdi_confinfo ci;
07455    /* Fine if we already have a master, etc */
07456    if (p->master || (p->confno > -1))
07457       return 0;
07458    memset(&ci, 0, sizeof(ci));
07459    if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
07460       ast_log(LOG_WARNING, "Failed to get conference info on channel %d: %s\n", p->channel, strerror(errno));
07461       return 0;
07462    }
07463    /* If we have no master and don't have a confno, then
07464       if we're in a conference, it's probably a MeetMe room or
07465       some such, so don't let us 3-way out! */
07466    if ((p->subs[SUB_REAL].curconf.confno != ci.confno) || (p->subs[SUB_REAL].curconf.confmode != ci.confmode)) {
07467       ast_verb(3, "Avoiding 3-way call when in an external conference\n");
07468       return 1;
07469    }
07470    return 0;
07471 }
07472 
07473 /*! Checks channel for alarms
07474  * \param p a channel to check for alarms.
07475  * \returns the alarms on the span to which the channel belongs, or alarms on
07476  *          the channel if no span alarms.
07477  */
07478 static int get_alarms(struct dahdi_pvt *p)
07479 {
07480    int res;
07481    struct dahdi_spaninfo zi;
07482    struct dahdi_params params;
07483 
07484    memset(&zi, 0, sizeof(zi));
07485    zi.spanno = p->span;
07486 
07487    if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SPANSTAT, &zi)) >= 0) {
07488       if (zi.alarms != DAHDI_ALARM_NONE)
07489          return zi.alarms;
07490    } else {
07491       ast_log(LOG_WARNING, "Unable to determine alarm on channel %d: %s\n", p->channel, strerror(errno));
07492       return 0;
07493    }
07494 
07495    /* No alarms on the span. Check for channel alarms. */
07496    memset(&params, 0, sizeof(params));
07497    if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &params)) >= 0)
07498       return params.chan_alarms;
07499 
07500    ast_log(LOG_WARNING, "Unable to determine alarm on channel %d\n", p->channel);
07501 
07502    return DAHDI_ALARM_NONE;
07503 }
07504 
07505 static void dahdi_handle_dtmf(struct ast_channel *ast, int idx, struct ast_frame **dest)
07506 {
07507    struct dahdi_pvt *p = ast->tech_pvt;
07508    struct ast_frame *f = *dest;
07509 
07510    ast_debug(1, "%s DTMF digit: 0x%02X '%c' on %s\n",
07511       f->frametype == AST_FRAME_DTMF_BEGIN ? "Begin" : "End",
07512       f->subclass.integer, f->subclass.integer, ast->name);
07513 
07514    if (p->confirmanswer) {
07515       if (f->frametype == AST_FRAME_DTMF_END) {
07516          ast_debug(1, "Confirm answer on %s!\n", ast->name);
07517          /* Upon receiving a DTMF digit, consider this an answer confirmation instead
07518             of a DTMF digit */
07519          p->subs[idx].f.frametype = AST_FRAME_CONTROL;
07520          p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
07521          /* Reset confirmanswer so DTMF's will behave properly for the duration of the call */
07522          p->confirmanswer = 0;
07523       } else {
07524          p->subs[idx].f.frametype = AST_FRAME_NULL;
07525          p->subs[idx].f.subclass.integer = 0;
07526       }
07527       *dest = &p->subs[idx].f;
07528    } else if (p->callwaitcas) {
07529       if (f->frametype == AST_FRAME_DTMF_END) {
07530          if ((f->subclass.integer == 'A') || (f->subclass.integer == 'D')) {
07531             ast_debug(1, "Got some DTMF, but it's for the CAS\n");
07532             ast_free(p->cidspill);
07533             p->cidspill = NULL;
07534             send_cwcidspill(p);
07535          }
07536          p->callwaitcas = 0;
07537       }
07538       p->subs[idx].f.frametype = AST_FRAME_NULL;
07539       p->subs[idx].f.subclass.integer = 0;
07540       *dest = &p->subs[idx].f;
07541    } else if (f->subclass.integer == 'f') {
07542       if (f->frametype == AST_FRAME_DTMF_END) {
07543          /* Fax tone -- Handle and return NULL */
07544          if ((p->callprogress & CALLPROGRESS_FAX) && !p->faxhandled) {
07545             /* If faxbuffers are configured, use them for the fax transmission */
07546             if (p->usefaxbuffers && !p->bufferoverrideinuse) {
07547                struct dahdi_bufferinfo bi = {
07548                   .txbufpolicy = p->faxbuf_policy,
07549                   .bufsize = p->bufsize,
07550                   .numbufs = p->faxbuf_no
07551                };
07552                int res;
07553 
07554                if ((res = ioctl(p->subs[idx].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
07555                   ast_log(LOG_WARNING, "Channel '%s' unable to set buffer policy, reason: %s\n", ast->name, strerror(errno));
07556                } else {
07557                   p->bufferoverrideinuse = 1;
07558                }
07559             }
07560             p->faxhandled = 1;
07561             if (p->dsp) {
07562                p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
07563                ast_dsp_set_features(p->dsp, p->dsp_features);
07564                ast_debug(1, "Disabling FAX tone detection on %s after tone received\n", ast->name);
07565             }
07566             if (strcmp(ast->exten, "fax")) {
07567                const char *target_context = S_OR(ast->macrocontext, ast->context);
07568 
07569                /* We need to unlock 'ast' here because ast_exists_extension has the
07570                 * potential to start autoservice on the channel. Such action is prone
07571                 * to deadlock.
07572                 */
07573                ast_mutex_unlock(&p->lock);
07574                ast_channel_unlock(ast);
07575                if (ast_exists_extension(ast, target_context, "fax", 1,
07576                   S_COR(ast->caller.id.number.valid, ast->caller.id.number.str, NULL))) {
07577                   ast_channel_lock(ast);
07578                   ast_mutex_lock(&p->lock);
07579                   ast_verb(3, "Redirecting %s to fax extension\n", ast->name);
07580                   /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
07581                   pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten);
07582                   if (ast_async_goto(ast, target_context, "fax", 1))
07583                      ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context);
07584                } else {
07585                   ast_channel_lock(ast);
07586                   ast_mutex_lock(&p->lock);
07587                   ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
07588                }
07589             } else {
07590                ast_debug(1, "Already in a fax extension, not redirecting\n");
07591             }
07592          } else {
07593             ast_debug(1, "Fax already handled\n");
07594          }
07595          dahdi_confmute(p, 0);
07596       }
07597       p->subs[idx].f.frametype = AST_FRAME_NULL;
07598       p->subs[idx].f.subclass.integer = 0;
07599       *dest = &p->subs[idx].f;
07600    }
07601 }
07602 
07603 static void handle_alarms(struct dahdi_pvt *p, int alms)
07604 {
07605    const char *alarm_str = alarm2str(alms);
07606 
07607    if (report_alarms & REPORT_CHANNEL_ALARMS) {
07608       ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", p->channel, alarm_str);
07609       manager_event(EVENT_FLAG_SYSTEM, "Alarm",
07610                  "Alarm: %s\r\n"
07611                  "Channel: %d\r\n",
07612                  alarm_str, p->channel);
07613    }
07614 
07615    if (report_alarms & REPORT_SPAN_ALARMS && p->manages_span_alarms) {
07616       ast_log(LOG_WARNING, "Detected alarm on span %d: %s\n", p->span, alarm_str);
07617       manager_event(EVENT_FLAG_SYSTEM, "SpanAlarm",
07618                  "Alarm: %s\r\n"
07619                  "Span: %d\r\n",
07620                  alarm_str, p->span);
07621    }
07622 }
07623 
07624 static struct ast_frame *dahdi_handle_event(struct ast_channel *ast)
07625 {
07626    int res, x;
07627    int idx, mysig;
07628    char *c;
07629    struct dahdi_pvt *p = ast->tech_pvt;
07630    pthread_t threadid;
07631    struct ast_channel *chan;
07632    struct ast_frame *f;
07633 
07634    idx = dahdi_get_index(ast, p, 0);
07635    mysig = p->sig;
07636    if (p->outsigmod > -1)
07637       mysig = p->outsigmod;
07638    p->subs[idx].f.frametype = AST_FRAME_NULL;
07639    p->subs[idx].f.subclass.integer = 0;
07640    p->subs[idx].f.datalen = 0;
07641    p->subs[idx].f.samples = 0;
07642    p->subs[idx].f.mallocd = 0;
07643    p->subs[idx].f.offset = 0;
07644    p->subs[idx].f.src = "dahdi_handle_event";
07645    p->subs[idx].f.data.ptr = NULL;
07646    f = &p->subs[idx].f;
07647 
07648    if (idx < 0)
07649       return &p->subs[idx].f;
07650    if (p->fake_event) {
07651       res = p->fake_event;
07652       p->fake_event = 0;
07653    } else
07654       res = dahdi_get_event(p->subs[idx].dfd);
07655 
07656    ast_debug(1, "Got event %s(%d) on channel %d (index %d)\n", event2str(res), res, p->channel, idx);
07657 
07658    if (res & (DAHDI_EVENT_PULSEDIGIT | DAHDI_EVENT_DTMFUP)) {
07659       p->pulsedial = (res & DAHDI_EVENT_PULSEDIGIT) ? 1 : 0;
07660       ast_debug(1, "Detected %sdigit '%c'\n", p->pulsedial ? "pulse ": "", res & 0xff);
07661 #if defined(HAVE_PRI)
07662       if (dahdi_sig_pri_lib_handles(p->sig)
07663          && !((struct sig_pri_chan *) p->sig_pvt)->proceeding
07664          && p->pri
07665          && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
07666          /* absorb event */
07667       } else
07668 #endif   /* defined(HAVE_PRI) */
07669       {
07670          /* Unmute conference */
07671          dahdi_confmute(p, 0);
07672          p->subs[idx].f.frametype = AST_FRAME_DTMF_END;
07673          p->subs[idx].f.subclass.integer = res & 0xff;
07674          dahdi_handle_dtmf(ast, idx, &f);
07675       }
07676       return f;
07677    }
07678 
07679    if (res & DAHDI_EVENT_DTMFDOWN) {
07680       ast_debug(1, "DTMF Down '%c'\n", res & 0xff);
07681 #if defined(HAVE_PRI)
07682       if (dahdi_sig_pri_lib_handles(p->sig)
07683          && !((struct sig_pri_chan *) p->sig_pvt)->proceeding
07684          && p->pri
07685          && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
07686          /* absorb event */
07687       } else
07688 #endif   /* defined(HAVE_PRI) */
07689       {
07690          /* Mute conference */
07691          dahdi_confmute(p, 1);
07692          p->subs[idx].f.frametype = AST_FRAME_DTMF_BEGIN;
07693          p->subs[idx].f.subclass.integer = res & 0xff;
07694          dahdi_handle_dtmf(ast, idx, &f);
07695       }
07696       return &p->subs[idx].f;
07697    }
07698 
07699    switch (res) {
07700    case DAHDI_EVENT_EC_DISABLED:
07701       ast_verb(3, "Channel %d echo canceler disabled.\n", p->channel);
07702       p->echocanon = 0;
07703       break;
07704 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
07705    case DAHDI_EVENT_TX_CED_DETECTED:
07706       ast_verb(3, "Channel %d detected a CED tone towards the network.\n", p->channel);
07707       break;
07708    case DAHDI_EVENT_RX_CED_DETECTED:
07709       ast_verb(3, "Channel %d detected a CED tone from the network.\n", p->channel);
07710       break;
07711    case DAHDI_EVENT_EC_NLP_DISABLED:
07712       ast_verb(3, "Channel %d echo canceler disabled its NLP.\n", p->channel);
07713       break;
07714    case DAHDI_EVENT_EC_NLP_ENABLED:
07715       ast_verb(3, "Channel %d echo canceler enabled its NLP.\n", p->channel);
07716       break;
07717 #endif
07718    case DAHDI_EVENT_BITSCHANGED:
07719 #ifdef HAVE_OPENR2
07720       if (p->sig != SIG_MFCR2) {
07721          ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig));
07722       } else {
07723          ast_log(LOG_DEBUG, "bits changed in chan %d\n", p->channel);
07724          openr2_chan_handle_cas(p->r2chan);
07725       }
07726 #else
07727       ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig));
07728 #endif
07729    case DAHDI_EVENT_PULSE_START:
07730       /* Stop tone if there's a pulse start and the PBX isn't started */
07731       if (!ast->pbx)
07732          tone_zone_play_tone(p->subs[idx].dfd, -1);
07733       break;
07734    case DAHDI_EVENT_DIALCOMPLETE:
07735 #ifdef HAVE_OPENR2
07736       if ((p->sig & SIG_MFCR2) && p->r2chan && ast->_state != AST_STATE_UP) {
07737          /* we don't need to do anything for this event for R2 signaling
07738             if the call is being setup */
07739          break;
07740       }
07741 #endif
07742       if (p->inalarm) break;
07743       if ((p->radio || (p->oprmode < 0))) break;
07744       if (ioctl(p->subs[idx].dfd,DAHDI_DIALING,&x) == -1) {
07745          ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed on %s: %s\n",ast->name, strerror(errno));
07746          return NULL;
07747       }
07748       if (!x) { /* if not still dialing in driver */
07749          dahdi_enable_ec(p);
07750          if (p->echobreak) {
07751             dahdi_train_ec(p);
07752             ast_copy_string(p->dop.dialstr, p->echorest, sizeof(p->dop.dialstr));
07753             p->dop.op = DAHDI_DIAL_OP_REPLACE;
07754             res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
07755             p->echobreak = 0;
07756          } else {
07757             p->dialing = 0;
07758             if ((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) {
07759                /* if thru with dialing after offhook */
07760                if (ast->_state == AST_STATE_DIALING_OFFHOOK) {
07761                   ast_setstate(ast, AST_STATE_UP);
07762                   p->subs[idx].f.frametype = AST_FRAME_CONTROL;
07763                   p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
07764                   break;
07765                } else { /* if to state wait for offhook to dial rest */
07766                   /* we now wait for off hook */
07767                   ast_setstate(ast,AST_STATE_DIALING_OFFHOOK);
07768                }
07769             }
07770             if (ast->_state == AST_STATE_DIALING) {
07771                if ((p->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
07772                   ast_debug(1, "Done dialing, but waiting for progress detection before doing more...\n");
07773                } else if (p->confirmanswer || (!p->dialednone
07774                   && ((mysig == SIG_EM) || (mysig == SIG_EM_E1)
07775                      || (mysig == SIG_EMWINK) || (mysig == SIG_FEATD)
07776                      || (mysig == SIG_FEATDMF_TA) || (mysig == SIG_FEATDMF)
07777                      || (mysig == SIG_E911) || (mysig == SIG_FGC_CAMA)
07778                      || (mysig == SIG_FGC_CAMAMF) || (mysig == SIG_FEATB)
07779                      || (mysig == SIG_SF) || (mysig == SIG_SFWINK)
07780                      || (mysig == SIG_SF_FEATD) || (mysig == SIG_SF_FEATDMF)
07781                      || (mysig == SIG_SF_FEATB)))) {
07782                   ast_setstate(ast, AST_STATE_RINGING);
07783                } else if (!p->answeronpolarityswitch) {
07784                   ast_setstate(ast, AST_STATE_UP);
07785                   p->subs[idx].f.frametype = AST_FRAME_CONTROL;
07786                   p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
07787                   /* If aops=0 and hops=1, this is necessary */
07788                   p->polarity = POLARITY_REV;
07789                } else {
07790                   /* Start clean, so we can catch the change to REV polarity when party answers */
07791                   p->polarity = POLARITY_IDLE;
07792                }
07793             }
07794          }
07795       }
07796       break;
07797    case DAHDI_EVENT_ALARM:
07798       switch (p->sig) {
07799 #if defined(HAVE_PRI)
07800       case SIG_PRI_LIB_HANDLE_CASES:
07801          sig_pri_chan_alarm_notify(p->sig_pvt, 0);
07802          break;
07803 #endif   /* defined(HAVE_PRI) */
07804 #if defined(HAVE_SS7)
07805       case SIG_SS7:
07806          sig_ss7_set_alarm(p->sig_pvt, 1);
07807          break;
07808 #endif   /* defined(HAVE_SS7) */
07809       default:
07810          p->inalarm = 1;
07811          break;
07812       }
07813       res = get_alarms(p);
07814       handle_alarms(p, res);
07815 #ifdef HAVE_PRI
07816       if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
07817          /* fall through intentionally */
07818       } else {
07819          break;
07820       }
07821 #endif
07822 #if defined(HAVE_SS7)
07823       if (p->sig == SIG_SS7)
07824          break;
07825 #endif   /* defined(HAVE_SS7) */
07826 #ifdef HAVE_OPENR2
07827       if (p->sig == SIG_MFCR2)
07828          break;
07829 #endif
07830    case DAHDI_EVENT_ONHOOK:
07831       if (p->radio) {
07832          p->subs[idx].f.frametype = AST_FRAME_CONTROL;
07833          p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_UNKEY;
07834          break;
07835       }
07836       if (p->oprmode < 0)
07837       {
07838          if (p->oprmode != -1) break;
07839          if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
07840          {
07841             /* Make sure it starts ringing */
07842             dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
07843             dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RING);
07844             save_conference(p->oprpeer);
07845             tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
07846          }
07847          break;
07848       }
07849       switch (p->sig) {
07850       case SIG_FXOLS:
07851       case SIG_FXOGS:
07852       case SIG_FXOKS:
07853          /* Check for some special conditions regarding call waiting */
07854          if (idx == SUB_REAL) {
07855             /* The normal line was hung up */
07856             if (p->subs[SUB_CALLWAIT].owner) {
07857                /* There's a call waiting call, so ring the phone, but make it unowned in the mean time */
07858                swap_subs(p, SUB_CALLWAIT, SUB_REAL);
07859                ast_verb(3, "Channel %d still has (callwait) call, ringing phone\n", p->channel);
07860                unalloc_sub(p, SUB_CALLWAIT);
07861 #if 0
07862                p->subs[idx].needanswer = 0;
07863                p->subs[idx].needringing = 0;
07864 #endif
07865                p->callwaitingrepeat = 0;
07866                p->cidcwexpire = 0;
07867                p->cid_suppress_expire = 0;
07868                p->owner = NULL;
07869                /* Don't start streaming audio yet if the incoming call isn't up yet */
07870                if (p->subs[SUB_REAL].owner->_state != AST_STATE_UP)
07871                   p->dialing = 1;
07872                dahdi_ring_phone(p);
07873             } else if (p->subs[SUB_THREEWAY].owner) {
07874                unsigned int mssinceflash;
07875                /* Here we have to retain the lock on both the main channel, the 3-way channel, and
07876                   the private structure -- not especially easy or clean */
07877                while (p->subs[SUB_THREEWAY].owner && ast_channel_trylock(p->subs[SUB_THREEWAY].owner)) {
07878                   /* Yuck, didn't get the lock on the 3-way, gotta release everything and re-grab! */
07879                   DLA_UNLOCK(&p->lock);
07880                   CHANNEL_DEADLOCK_AVOIDANCE(ast);
07881                   /* We can grab ast and p in that order, without worry.  We should make sure
07882                      nothing seriously bad has happened though like some sort of bizarre double
07883                      masquerade! */
07884                   DLA_LOCK(&p->lock);
07885                   if (p->owner != ast) {
07886                      ast_log(LOG_WARNING, "This isn't good...\n");
07887                      return NULL;
07888                   }
07889                }
07890                if (!p->subs[SUB_THREEWAY].owner) {
07891                   ast_log(LOG_NOTICE, "Whoa, threeway disappeared kinda randomly.\n");
07892                   return NULL;
07893                }
07894                mssinceflash = ast_tvdiff_ms(ast_tvnow(), p->flashtime);
07895                ast_debug(1, "Last flash was %d ms ago\n", mssinceflash);
07896                if (mssinceflash < MIN_MS_SINCE_FLASH) {
07897                   /* It hasn't been long enough since the last flashook.  This is probably a bounce on
07898                      hanging up.  Hangup both channels now */
07899                   if (p->subs[SUB_THREEWAY].owner)
07900                      ast_queue_hangup_with_cause(p->subs[SUB_THREEWAY].owner, AST_CAUSE_NO_ANSWER);
07901                   p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
07902                   ast_debug(1, "Looks like a bounced flash, hanging up both calls on %d\n", p->channel);
07903                   ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
07904                } else if ((ast->pbx) || (ast->_state == AST_STATE_UP)) {
07905                   if (p->transfer) {
07906                      /* In any case this isn't a threeway call anymore */
07907                      p->subs[SUB_REAL].inthreeway = 0;
07908                      p->subs[SUB_THREEWAY].inthreeway = 0;
07909                      /* Only attempt transfer if the phone is ringing; why transfer to busy tone eh? */
07910                      if (!p->transfertobusy && ast->_state == AST_STATE_BUSY) {
07911                         ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
07912                         /* Swap subs and dis-own channel */
07913                         swap_subs(p, SUB_THREEWAY, SUB_REAL);
07914                         p->owner = NULL;
07915                         /* Ring the phone */
07916                         dahdi_ring_phone(p);
07917                      } else {
07918                         if ((res = attempt_transfer(p)) < 0) {
07919                            p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
07920                            if (p->subs[SUB_THREEWAY].owner)
07921                               ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
07922                         } else if (res) {
07923                            /* Don't actually hang up at this point */
07924                            if (p->subs[SUB_THREEWAY].owner)
07925                               ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
07926                            break;
07927                         }
07928                      }
07929                   } else {
07930                      p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
07931                      if (p->subs[SUB_THREEWAY].owner)
07932                         ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
07933                   }
07934                } else {
07935                   ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
07936                   /* Swap subs and dis-own channel */
07937                   swap_subs(p, SUB_THREEWAY, SUB_REAL);
07938                   p->owner = NULL;
07939                   /* Ring the phone */
07940                   dahdi_ring_phone(p);
07941                }
07942             }
07943          } else {
07944             ast_log(LOG_WARNING, "Got a hangup and my index is %d?\n", idx);
07945          }
07946          /* Fall through */
07947       default:
07948          dahdi_disable_ec(p);
07949          return NULL;
07950       }
07951       break;
07952    case DAHDI_EVENT_RINGOFFHOOK:
07953       if (p->inalarm) break;
07954       if (p->oprmode < 0)
07955       {
07956          if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
07957          {
07958             /* Make sure it stops ringing */
07959             dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
07960             tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, -1);
07961             restore_conference(p->oprpeer);
07962          }
07963          break;
07964       }
07965       if (p->radio)
07966       {
07967          p->subs[idx].f.frametype = AST_FRAME_CONTROL;
07968          p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_KEY;
07969          break;
07970       }
07971       /* for E911, its supposed to wait for offhook then dial
07972          the second half of the dial string */
07973       if (((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) && (ast->_state == AST_STATE_DIALING_OFFHOOK)) {
07974          c = strchr(p->dialdest, '/');
07975          if (c)
07976             c++;
07977          else
07978             c = p->dialdest;
07979          if (*c) snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*0%s#", c);
07980          else ast_copy_string(p->dop.dialstr,"M*2#", sizeof(p->dop.dialstr));
07981          if (strlen(p->dop.dialstr) > 4) {
07982             memset(p->echorest, 'w', sizeof(p->echorest) - 1);
07983             strcpy(p->echorest + (p->echotraining / 401) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
07984             p->echorest[sizeof(p->echorest) - 1] = '\0';
07985             p->echobreak = 1;
07986             p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
07987          } else
07988             p->echobreak = 0;
07989          if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
07990             int saveerr = errno;
07991 
07992             x = DAHDI_ONHOOK;
07993             ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
07994             ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
07995             return NULL;
07996             }
07997          p->dialing = 1;
07998          return &p->subs[idx].f;
07999       }
08000       switch (p->sig) {
08001       case SIG_FXOLS:
08002       case SIG_FXOGS:
08003       case SIG_FXOKS:
08004          switch (ast->_state) {
08005          case AST_STATE_RINGING:
08006             dahdi_enable_ec(p);
08007             dahdi_train_ec(p);
08008             p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08009             p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
08010             /* Make sure it stops ringing */
08011             p->subs[SUB_REAL].needringing = 0;
08012             dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
08013             ast_debug(1, "channel %d answered\n", p->channel);
08014 
08015             /* Cancel any running CallerID spill */
08016             ast_free(p->cidspill);
08017             p->cidspill = NULL;
08018             restore_conference(p);
08019 
08020             p->dialing = 0;
08021             p->callwaitcas = 0;
08022             if (p->confirmanswer) {
08023                /* Ignore answer if "confirm answer" is enabled */
08024                p->subs[idx].f.frametype = AST_FRAME_NULL;
08025                p->subs[idx].f.subclass.integer = 0;
08026             } else if (!ast_strlen_zero(p->dop.dialstr)) {
08027                /* nick@dccinc.com 4/3/03 - fxo should be able to do deferred dialing */
08028                res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
08029                if (res < 0) {
08030                   ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
08031                   p->dop.dialstr[0] = '\0';
08032                   return NULL;
08033                } else {
08034                   ast_debug(1, "Sent FXO deferred digit string: %s\n", p->dop.dialstr);
08035                   p->subs[idx].f.frametype = AST_FRAME_NULL;
08036                   p->subs[idx].f.subclass.integer = 0;
08037                   p->dialing = 1;
08038                }
08039                p->dop.dialstr[0] = '\0';
08040                ast_setstate(ast, AST_STATE_DIALING);
08041             } else
08042                ast_setstate(ast, AST_STATE_UP);
08043             return &p->subs[idx].f;
08044          case AST_STATE_DOWN:
08045             ast_setstate(ast, AST_STATE_RING);
08046             ast->rings = 1;
08047             p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08048             p->subs[idx].f.subclass.integer = AST_CONTROL_OFFHOOK;
08049             ast_debug(1, "channel %d picked up\n", p->channel);
08050             return &p->subs[idx].f;
08051          case AST_STATE_UP:
08052             /* Make sure it stops ringing */
08053             dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
08054             /* Okay -- probably call waiting*/
08055             if (ast_bridged_channel(p->owner))
08056                ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
08057             p->subs[idx].needunhold = 1;
08058             break;
08059          case AST_STATE_RESERVED:
08060             /* Start up dialtone */
08061             if (has_voicemail(p))
08062                res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
08063             else
08064                res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
08065             break;
08066          default:
08067             ast_log(LOG_WARNING, "FXO phone off hook in weird state %d??\n", ast->_state);
08068          }
08069          break;
08070       case SIG_FXSLS:
08071       case SIG_FXSGS:
08072       case SIG_FXSKS:
08073          if (ast->_state == AST_STATE_RING) {
08074             p->ringt = p->ringt_base;
08075          }
08076 
08077          /* If we get a ring then we cannot be in
08078           * reversed polarity. So we reset to idle */
08079          ast_debug(1, "Setting IDLE polarity due "
08080             "to ring. Old polarity was %d\n",
08081             p->polarity);
08082          p->polarity = POLARITY_IDLE;
08083 
08084          /* Fall through */
08085       case SIG_EM:
08086       case SIG_EM_E1:
08087       case SIG_EMWINK:
08088       case SIG_FEATD:
08089       case SIG_FEATDMF:
08090       case SIG_FEATDMF_TA:
08091       case SIG_E911:
08092       case SIG_FGC_CAMA:
08093       case SIG_FGC_CAMAMF:
08094       case SIG_FEATB:
08095       case SIG_SF:
08096       case SIG_SFWINK:
08097       case SIG_SF_FEATD:
08098       case SIG_SF_FEATDMF:
08099       case SIG_SF_FEATB:
08100          if (ast->_state == AST_STATE_PRERING)
08101             ast_setstate(ast, AST_STATE_RING);
08102          if ((ast->_state == AST_STATE_DOWN) || (ast->_state == AST_STATE_RING)) {
08103             ast_debug(1, "Ring detected\n");
08104             p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08105             p->subs[idx].f.subclass.integer = AST_CONTROL_RING;
08106          } else if (p->outgoing && ((ast->_state == AST_STATE_RINGING) || (ast->_state == AST_STATE_DIALING))) {
08107             ast_debug(1, "Line answered\n");
08108             if (p->confirmanswer) {
08109                p->subs[idx].f.frametype = AST_FRAME_NULL;
08110                p->subs[idx].f.subclass.integer = 0;
08111             } else {
08112                p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08113                p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
08114                ast_setstate(ast, AST_STATE_UP);
08115             }
08116          } else if (ast->_state != AST_STATE_RING)
08117             ast_log(LOG_WARNING, "Ring/Off-hook in strange state %d on channel %d\n", ast->_state, p->channel);
08118          break;
08119       default:
08120          ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
08121       }
08122       break;
08123    case DAHDI_EVENT_RINGBEGIN:
08124       switch (p->sig) {
08125       case SIG_FXSLS:
08126       case SIG_FXSGS:
08127       case SIG_FXSKS:
08128          if (ast->_state == AST_STATE_RING) {
08129             p->ringt = p->ringt_base;
08130          }
08131          break;
08132       }
08133       break;
08134    case DAHDI_EVENT_RINGERON:
08135       break;
08136    case DAHDI_EVENT_NOALARM:
08137       switch (p->sig) {
08138 #if defined(HAVE_PRI)
08139       case SIG_PRI_LIB_HANDLE_CASES:
08140          sig_pri_chan_alarm_notify(p->sig_pvt, 1);
08141          break;
08142 #endif   /* defined(HAVE_PRI) */
08143 #if defined(HAVE_SS7)
08144       case SIG_SS7:
08145          sig_ss7_set_alarm(p->sig_pvt, 0);
08146          break;
08147 #endif   /* defined(HAVE_SS7) */
08148       default:
08149          p->inalarm = 0;
08150          break;
08151       }
08152       handle_clear_alarms(p);
08153       break;
08154    case DAHDI_EVENT_WINKFLASH:
08155       if (p->inalarm) break;
08156       if (p->radio) break;
08157       if (p->oprmode < 0) break;
08158       if (p->oprmode > 1)
08159       {
08160          struct dahdi_params par;
08161 
08162          memset(&par, 0, sizeof(par));
08163          if (ioctl(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par) != -1)
08164          {
08165             if (!par.rxisoffhook)
08166             {
08167                /* Make sure it stops ringing */
08168                dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
08169                dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RING);
08170                save_conference(p);
08171                tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
08172             }
08173          }
08174          break;
08175       }
08176       /* Remember last time we got a flash-hook */
08177       p->flashtime = ast_tvnow();
08178       switch (mysig) {
08179       case SIG_FXOLS:
08180       case SIG_FXOGS:
08181       case SIG_FXOKS:
08182          ast_debug(1, "Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n",
08183             idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
08184 
08185          /* Cancel any running CallerID spill */
08186          ast_free(p->cidspill);
08187          p->cidspill = NULL;
08188          restore_conference(p);
08189          p->callwaitcas = 0;
08190 
08191          if (idx != SUB_REAL) {
08192             ast_log(LOG_WARNING, "Got flash hook with index %d on channel %d?!?\n", idx, p->channel);
08193             goto winkflashdone;
08194          }
08195 
08196          if (p->subs[SUB_CALLWAIT].owner) {
08197             /* Swap to call-wait */
08198             swap_subs(p, SUB_REAL, SUB_CALLWAIT);
08199             tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
08200             p->owner = p->subs[SUB_REAL].owner;
08201             ast_debug(1, "Making %s the new owner\n", p->owner->name);
08202             if (p->owner->_state == AST_STATE_RINGING) {
08203                ast_setstate(p->owner, AST_STATE_UP);
08204                p->subs[SUB_REAL].needanswer = 1;
08205             }
08206             p->callwaitingrepeat = 0;
08207             p->cidcwexpire = 0;
08208             p->cid_suppress_expire = 0;
08209             /* Start music on hold if appropriate */
08210             if (!p->subs[SUB_CALLWAIT].inthreeway && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
08211                ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
08212                   S_OR(p->mohsuggest, NULL),
08213                   !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
08214             }
08215             p->subs[SUB_CALLWAIT].needhold = 1;
08216             if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
08217                ast_queue_control_data(p->subs[SUB_REAL].owner, AST_CONTROL_HOLD,
08218                   S_OR(p->mohsuggest, NULL),
08219                   !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
08220             }
08221             p->subs[SUB_REAL].needunhold = 1;
08222          } else if (!p->subs[SUB_THREEWAY].owner) {
08223             if (!p->threewaycalling) {
08224                /* Just send a flash if no 3-way calling */
08225                p->subs[SUB_REAL].needflash = 1;
08226                goto winkflashdone;
08227             } else if (!check_for_conference(p)) {
08228                char cid_num[256];
08229                char cid_name[256];
08230 
08231                cid_num[0] = 0;
08232                cid_name[0] = 0;
08233                if (p->dahditrcallerid && p->owner) {
08234                   if (p->owner->caller.id.number.valid
08235                      && p->owner->caller.id.number.str) {
08236                      ast_copy_string(cid_num, p->owner->caller.id.number.str,
08237                         sizeof(cid_num));
08238                   }
08239                   if (p->owner->caller.id.name.valid
08240                      && p->owner->caller.id.name.str) {
08241                      ast_copy_string(cid_name, p->owner->caller.id.name.str,
08242                         sizeof(cid_name));
08243                   }
08244                }
08245                /* XXX This section needs much more error checking!!! XXX */
08246                /* Start a 3-way call if feasible */
08247                if (!((ast->pbx) ||
08248                   (ast->_state == AST_STATE_UP) ||
08249                   (ast->_state == AST_STATE_RING))) {
08250                   ast_debug(1, "Flash when call not up or ringing\n");
08251                   goto winkflashdone;
08252                }
08253                if (alloc_sub(p, SUB_THREEWAY)) {
08254                   ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n");
08255                   goto winkflashdone;
08256                }
08257                /* Make new channel */
08258                chan = dahdi_new(p, AST_STATE_RESERVED, 0, SUB_THREEWAY, 0, NULL);
08259                if (p->dahditrcallerid) {
08260                   if (!p->origcid_num)
08261                      p->origcid_num = ast_strdup(p->cid_num);
08262                   if (!p->origcid_name)
08263                      p->origcid_name = ast_strdup(p->cid_name);
08264                   ast_copy_string(p->cid_num, cid_num, sizeof(p->cid_num));
08265                   ast_copy_string(p->cid_name, cid_name, sizeof(p->cid_name));
08266                }
08267                /* Swap things around between the three-way and real call */
08268                swap_subs(p, SUB_THREEWAY, SUB_REAL);
08269                /* Disable echo canceller for better dialing */
08270                dahdi_disable_ec(p);
08271                res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALRECALL);
08272                if (res)
08273                   ast_log(LOG_WARNING, "Unable to start dial recall tone on channel %d\n", p->channel);
08274                p->owner = chan;
08275                if (!chan) {
08276                   ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", p->channel);
08277                } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
08278                   ast_log(LOG_WARNING, "Unable to start simple switch on channel %d\n", p->channel);
08279                   res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
08280                   dahdi_enable_ec(p);
08281                   ast_hangup(chan);
08282                } else {
08283                   ast_verb(3, "Started three way call on channel %d\n", p->channel);
08284 
08285                   /* Start music on hold if appropriate */
08286                   if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
08287                      ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
08288                         S_OR(p->mohsuggest, NULL),
08289                         !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
08290                   }
08291                   p->subs[SUB_THREEWAY].needhold = 1;
08292                }
08293             }
08294          } else {
08295             /* Already have a 3 way call */
08296             if (p->subs[SUB_THREEWAY].inthreeway) {
08297                /* Call is already up, drop the last person */
08298                ast_debug(1, "Got flash with three way call up, dropping last call on %d\n", p->channel);
08299                /* If the primary call isn't answered yet, use it */
08300                if ((p->subs[SUB_REAL].owner->_state != AST_STATE_UP) && (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_UP)) {
08301                   /* Swap back -- we're dropping the real 3-way that isn't finished yet*/
08302                   swap_subs(p, SUB_THREEWAY, SUB_REAL);
08303                   p->owner = p->subs[SUB_REAL].owner;
08304                }
08305                /* Drop the last call and stop the conference */
08306                ast_verb(3, "Dropping three-way call on %s\n", p->subs[SUB_THREEWAY].owner->name);
08307                p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08308                p->subs[SUB_REAL].inthreeway = 0;
08309                p->subs[SUB_THREEWAY].inthreeway = 0;
08310             } else {
08311                /* Lets see what we're up to */
08312                if (((ast->pbx) || (ast->_state == AST_STATE_UP)) &&
08313                   (p->transfertobusy || (ast->_state != AST_STATE_BUSY))) {
08314                   int otherindex = SUB_THREEWAY;
08315 
08316                   ast_verb(3, "Building conference call with %s and %s\n",
08317                      p->subs[SUB_THREEWAY].owner->name,
08318                      p->subs[SUB_REAL].owner->name);
08319                   /* Put them in the threeway, and flip */
08320                   p->subs[SUB_THREEWAY].inthreeway = 1;
08321                   p->subs[SUB_REAL].inthreeway = 1;
08322                   if (ast->_state == AST_STATE_UP) {
08323                      swap_subs(p, SUB_THREEWAY, SUB_REAL);
08324                      otherindex = SUB_REAL;
08325                   }
08326                   if (p->subs[otherindex].owner && ast_bridged_channel(p->subs[otherindex].owner))
08327                      ast_queue_control(p->subs[otherindex].owner, AST_CONTROL_UNHOLD);
08328                   p->subs[otherindex].needunhold = 1;
08329                   p->owner = p->subs[SUB_REAL].owner;
08330                } else {
08331                   ast_verb(3, "Dumping incomplete call on on %s\n", p->subs[SUB_THREEWAY].owner->name);
08332                   swap_subs(p, SUB_THREEWAY, SUB_REAL);
08333                   p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08334                   p->owner = p->subs[SUB_REAL].owner;
08335                   if (p->subs[SUB_REAL].owner && ast_bridged_channel(p->subs[SUB_REAL].owner))
08336                      ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
08337                   p->subs[SUB_REAL].needunhold = 1;
08338                   dahdi_enable_ec(p);
08339                }
08340             }
08341          }
08342 winkflashdone:
08343          update_conf(p);
08344          break;
08345       case SIG_EM:
08346       case SIG_EM_E1:
08347       case SIG_FEATD:
08348       case SIG_SF:
08349       case SIG_SFWINK:
08350       case SIG_SF_FEATD:
08351       case SIG_FXSLS:
08352       case SIG_FXSGS:
08353          if (p->dialing)
08354             ast_debug(1, "Ignoring wink on channel %d\n", p->channel);
08355          else
08356             ast_debug(1, "Got wink in weird state %d on channel %d\n", ast->_state, p->channel);
08357          break;
08358       case SIG_FEATDMF_TA:
08359          switch (p->whichwink) {
08360          case 0:
08361             ast_debug(1, "ANI2 set to '%d' and ANI is '%s'\n", p->owner->caller.ani2,
08362                S_COR(p->owner->caller.ani.number.valid,
08363                   p->owner->caller.ani.number.str, ""));
08364             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%d%s#",
08365                p->owner->caller.ani2,
08366                S_COR(p->owner->caller.ani.number.valid,
08367                   p->owner->caller.ani.number.str, ""));
08368             break;
08369          case 1:
08370             ast_copy_string(p->dop.dialstr, p->finaldial, sizeof(p->dop.dialstr));
08371             break;
08372          case 2:
08373             ast_log(LOG_WARNING, "Received unexpected wink on channel of type SIG_FEATDMF_TA\n");
08374             return NULL;
08375          }
08376          p->whichwink++;
08377          /* Fall through */
08378       case SIG_FEATDMF:
08379       case SIG_E911:
08380       case SIG_FGC_CAMAMF:
08381       case SIG_FGC_CAMA:
08382       case SIG_FEATB:
08383       case SIG_SF_FEATDMF:
08384       case SIG_SF_FEATB:
08385       case SIG_EMWINK:
08386          /* FGD MF and EMWINK *Must* wait for wink */
08387          if (!ast_strlen_zero(p->dop.dialstr)) {
08388             res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
08389             if (res < 0) {
08390                ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
08391                p->dop.dialstr[0] = '\0';
08392                return NULL;
08393             } else
08394                ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
08395          }
08396          p->dop.dialstr[0] = '\0';
08397          break;
08398       default:
08399          ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
08400       }
08401       break;
08402    case DAHDI_EVENT_HOOKCOMPLETE:
08403       if (p->inalarm) break;
08404       if ((p->radio || (p->oprmode < 0))) break;
08405       if (p->waitingfordt.tv_sec) break;
08406       switch (mysig) {
08407       case SIG_FXSLS:  /* only interesting for FXS */
08408       case SIG_FXSGS:
08409       case SIG_FXSKS:
08410       case SIG_EM:
08411       case SIG_EM_E1:
08412       case SIG_EMWINK:
08413       case SIG_FEATD:
08414       case SIG_SF:
08415       case SIG_SFWINK:
08416       case SIG_SF_FEATD:
08417          if (!ast_strlen_zero(p->dop.dialstr)) {
08418             res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
08419             if (res < 0) {
08420                ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
08421                p->dop.dialstr[0] = '\0';
08422                return NULL;
08423             } else
08424                ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
08425          }
08426          p->dop.dialstr[0] = '\0';
08427          p->dop.op = DAHDI_DIAL_OP_REPLACE;
08428          break;
08429       case SIG_FEATDMF:
08430       case SIG_FEATDMF_TA:
08431       case SIG_E911:
08432       case SIG_FGC_CAMA:
08433       case SIG_FGC_CAMAMF:
08434       case SIG_FEATB:
08435       case SIG_SF_FEATDMF:
08436       case SIG_SF_FEATB:
08437          ast_debug(1, "Got hook complete in MF FGD, waiting for wink now on channel %d\n",p->channel);
08438          break;
08439       default:
08440          break;
08441       }
08442       break;
08443    case DAHDI_EVENT_POLARITY:
08444       /*
08445        * If we get a Polarity Switch event, check to see
08446        * if we should change the polarity state and
08447        * mark the channel as UP or if this is an indication
08448        * of remote end disconnect.
08449        */
08450       if (p->polarity == POLARITY_IDLE) {
08451          p->polarity = POLARITY_REV;
08452          if (p->answeronpolarityswitch &&
08453             ((ast->_state == AST_STATE_DIALING) ||
08454             (ast->_state == AST_STATE_RINGING))) {
08455             ast_debug(1, "Answering on polarity switch!\n");
08456             ast_setstate(p->owner, AST_STATE_UP);
08457             if (p->hanguponpolarityswitch) {
08458                p->polaritydelaytv = ast_tvnow();
08459             }
08460          } else
08461             ast_debug(1, "Ignore switch to REVERSED Polarity on channel %d, state %d\n", p->channel, ast->_state);
08462       }
08463       /* Removed else statement from here as it was preventing hangups from ever happening*/
08464       /* Added AST_STATE_RING in if statement below to deal with calling party hangups that take place when ringing */
08465       if (p->hanguponpolarityswitch &&
08466          (p->polarityonanswerdelay > 0) &&
08467          (p->polarity == POLARITY_REV) &&
08468          ((ast->_state == AST_STATE_UP) || (ast->_state == AST_STATE_RING)) ) {
08469          /* Added log_debug information below to provide a better indication of what is going on */
08470          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) );
08471 
08472          if (ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) > p->polarityonanswerdelay) {
08473             ast_debug(1, "Polarity Reversal detected and now Hanging up on channel %d\n", p->channel);
08474             ast_softhangup(p->owner, AST_SOFTHANGUP_EXPLICIT);
08475             p->polarity = POLARITY_IDLE;
08476          } else
08477             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);
08478 
08479       } else {
08480          p->polarity = POLARITY_IDLE;
08481          ast_debug(1, "Ignoring Polarity switch to IDLE on channel %d, state %d\n", p->channel, ast->_state);
08482       }
08483       /* Added more log_debug information below to provide a better indication of what is going on */
08484       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) );
08485       break;
08486    default:
08487       ast_debug(1, "Dunno what to do with event %d on channel %d\n", res, p->channel);
08488    }
08489    return &p->subs[idx].f;
08490 }
08491 
08492 static struct ast_frame *__dahdi_exception(struct ast_channel *ast)
08493 {
08494    int res;
08495    int idx;
08496    struct ast_frame *f;
08497    int usedindex = -1;
08498    struct dahdi_pvt *p = ast->tech_pvt;
08499 
08500    idx = dahdi_get_index(ast, p, 1);
08501 
08502    p->subs[idx].f.frametype = AST_FRAME_NULL;
08503    p->subs[idx].f.datalen = 0;
08504    p->subs[idx].f.samples = 0;
08505    p->subs[idx].f.mallocd = 0;
08506    p->subs[idx].f.offset = 0;
08507    p->subs[idx].f.subclass.integer = 0;
08508    p->subs[idx].f.delivery = ast_tv(0,0);
08509    p->subs[idx].f.src = "dahdi_exception";
08510    p->subs[idx].f.data.ptr = NULL;
08511 
08512 
08513    if ((!p->owner) && (!(p->radio || (p->oprmode < 0)))) {
08514       /* If nobody owns us, absorb the event appropriately, otherwise
08515          we loop indefinitely.  This occurs when, during call waiting, the
08516          other end hangs up our channel so that it no longer exists, but we
08517          have neither FLASH'd nor ONHOOK'd to signify our desire to
08518          change to the other channel. */
08519       if (p->fake_event) {
08520          res = p->fake_event;
08521          p->fake_event = 0;
08522       } else
08523          res = dahdi_get_event(p->subs[SUB_REAL].dfd);
08524       /* Switch to real if there is one and this isn't something really silly... */
08525       if ((res != DAHDI_EVENT_RINGEROFF) && (res != DAHDI_EVENT_RINGERON) &&
08526          (res != DAHDI_EVENT_HOOKCOMPLETE)) {
08527          ast_debug(1, "Restoring owner of channel %d on event %d\n", p->channel, res);
08528          p->owner = p->subs[SUB_REAL].owner;
08529          if (p->owner && ast_bridged_channel(p->owner))
08530             ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
08531          p->subs[SUB_REAL].needunhold = 1;
08532       }
08533       switch (res) {
08534       case DAHDI_EVENT_ONHOOK:
08535          dahdi_disable_ec(p);
08536          if (p->owner) {
08537             ast_verb(3, "Channel %s still has call, ringing phone\n", p->owner->name);
08538             dahdi_ring_phone(p);
08539             p->callwaitingrepeat = 0;
08540             p->cidcwexpire = 0;
08541             p->cid_suppress_expire = 0;
08542          } else
08543             ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
08544          update_conf(p);
08545          break;
08546       case DAHDI_EVENT_RINGOFFHOOK:
08547          dahdi_enable_ec(p);
08548          dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
08549          if (p->owner && (p->owner->_state == AST_STATE_RINGING)) {
08550             p->subs[SUB_REAL].needanswer = 1;
08551             p->dialing = 0;
08552          }
08553          break;
08554       case DAHDI_EVENT_HOOKCOMPLETE:
08555       case DAHDI_EVENT_RINGERON:
08556       case DAHDI_EVENT_RINGEROFF:
08557          /* Do nothing */
08558          break;
08559       case DAHDI_EVENT_WINKFLASH:
08560          p->flashtime = ast_tvnow();
08561          if (p->owner) {
08562             ast_verb(3, "Channel %d flashed to other channel %s\n", p->channel, p->owner->name);
08563             if (p->owner->_state != AST_STATE_UP) {
08564                /* Answer if necessary */
08565                usedindex = dahdi_get_index(p->owner, p, 0);
08566                if (usedindex > -1) {
08567                   p->subs[usedindex].needanswer = 1;
08568                }
08569                ast_setstate(p->owner, AST_STATE_UP);
08570             }
08571             p->callwaitingrepeat = 0;
08572             p->cidcwexpire = 0;
08573             p->cid_suppress_expire = 0;
08574             if (ast_bridged_channel(p->owner))
08575                ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
08576             p->subs[SUB_REAL].needunhold = 1;
08577          } else
08578             ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
08579          update_conf(p);
08580          break;
08581       default:
08582          ast_log(LOG_WARNING, "Don't know how to absorb event %s\n", event2str(res));
08583       }
08584       f = &p->subs[idx].f;
08585       return f;
08586    }
08587    if (!(p->radio || (p->oprmode < 0)))
08588       ast_debug(1, "Exception on %d, channel %d\n", ast->fds[0],p->channel);
08589    /* If it's not us, return NULL immediately */
08590    if (ast != p->owner) {
08591       ast_log(LOG_WARNING, "We're %s, not %s\n", ast->name, p->owner->name);
08592       f = &p->subs[idx].f;
08593       return f;
08594    }
08595    f = dahdi_handle_event(ast);
08596 
08597    /* tell the cdr this zap device hung up */
08598    if (f == NULL) {
08599       ast_set_hangupsource(ast, ast->name, 0);
08600    }
08601 
08602    return f;
08603 }
08604 
08605 static struct ast_frame *dahdi_exception(struct ast_channel *ast)
08606 {
08607    struct dahdi_pvt *p = ast->tech_pvt;
08608    struct ast_frame *f;
08609    ast_mutex_lock(&p->lock);
08610    if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
08611       struct analog_pvt *analog_p = p->sig_pvt;
08612       f = analog_exception(analog_p, ast);
08613    } else {
08614       f = __dahdi_exception(ast);
08615    }
08616    ast_mutex_unlock(&p->lock);
08617    return f;
08618 }
08619 
08620 static struct ast_frame *dahdi_read(struct ast_channel *ast)
08621 {
08622    struct dahdi_pvt *p = ast->tech_pvt;
08623    int res;
08624    int idx;
08625    void *readbuf;
08626    struct ast_frame *f;
08627 
08628    while (ast_mutex_trylock(&p->lock)) {
08629       CHANNEL_DEADLOCK_AVOIDANCE(ast);
08630    }
08631 
08632    idx = dahdi_get_index(ast, p, 0);
08633 
08634    /* Hang up if we don't really exist */
08635    if (idx < 0)   {
08636       ast_log(LOG_WARNING, "We don't exist?\n");
08637       ast_mutex_unlock(&p->lock);
08638       return NULL;
08639    }
08640 
08641    if ((p->radio || (p->oprmode < 0)) && p->inalarm) {
08642       ast_mutex_unlock(&p->lock);
08643       return NULL;
08644    }
08645 
08646    p->subs[idx].f.frametype = AST_FRAME_NULL;
08647    p->subs[idx].f.datalen = 0;
08648    p->subs[idx].f.samples = 0;
08649    p->subs[idx].f.mallocd = 0;
08650    p->subs[idx].f.offset = 0;
08651    p->subs[idx].f.subclass.integer = 0;
08652    p->subs[idx].f.delivery = ast_tv(0,0);
08653    p->subs[idx].f.src = "dahdi_read";
08654    p->subs[idx].f.data.ptr = NULL;
08655 
08656    /* make sure it sends initial key state as first frame */
08657    if ((p->radio || (p->oprmode < 0)) && (!p->firstradio))
08658    {
08659       struct dahdi_params ps;
08660 
08661       memset(&ps, 0, sizeof(ps));
08662       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
08663          ast_mutex_unlock(&p->lock);
08664          return NULL;
08665       }
08666       p->firstradio = 1;
08667       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08668       if (ps.rxisoffhook)
08669       {
08670          p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_KEY;
08671       }
08672       else
08673       {
08674          p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_UNKEY;
08675       }
08676       ast_mutex_unlock(&p->lock);
08677       return &p->subs[idx].f;
08678    }
08679    if (p->ringt > 0) {
08680       if (!(--p->ringt)) {
08681          ast_mutex_unlock(&p->lock);
08682          return NULL;
08683       }
08684    }
08685 
08686 #ifdef HAVE_OPENR2
08687    if (p->mfcr2) {
08688       openr2_chan_process_event(p->r2chan);
08689       if (OR2_DIR_FORWARD == openr2_chan_get_direction(p->r2chan)) {
08690          struct ast_frame f = { AST_FRAME_CONTROL, { AST_CONTROL_PROGRESS }, };
08691          /* if the call is already accepted and we already delivered AST_CONTROL_RINGING
08692           * now enqueue a progress frame to bridge the media up */
08693          if (p->mfcr2_call_accepted &&
08694              !p->mfcr2_progress && 
08695              ast->_state == AST_STATE_RINGING) {
08696             ast_log(LOG_DEBUG, "Enqueuing progress frame after R2 accept in chan %d\n", p->channel);
08697             ast_queue_frame(p->owner, &f);
08698             p->mfcr2_progress = 1;
08699          }
08700       }
08701    }
08702 #endif
08703 
08704    if (p->subs[idx].needringing) {
08705       /* Send ringing frame if requested */
08706       p->subs[idx].needringing = 0;
08707       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08708       p->subs[idx].f.subclass.integer = AST_CONTROL_RINGING;
08709       ast_setstate(ast, AST_STATE_RINGING);
08710       ast_mutex_unlock(&p->lock);
08711       return &p->subs[idx].f;
08712    }
08713 
08714    if (p->subs[idx].needbusy) {
08715       /* Send busy frame if requested */
08716       p->subs[idx].needbusy = 0;
08717       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08718       p->subs[idx].f.subclass.integer = AST_CONTROL_BUSY;
08719       ast_mutex_unlock(&p->lock);
08720       return &p->subs[idx].f;
08721    }
08722 
08723    if (p->subs[idx].needcongestion) {
08724       /* Send congestion frame if requested */
08725       p->subs[idx].needcongestion = 0;
08726       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08727       p->subs[idx].f.subclass.integer = AST_CONTROL_CONGESTION;
08728       ast_mutex_unlock(&p->lock);
08729       return &p->subs[idx].f;
08730    }
08731 
08732    if (p->subs[idx].needanswer) {
08733       /* Send answer frame if requested */
08734       p->subs[idx].needanswer = 0;
08735       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08736       p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
08737       ast_mutex_unlock(&p->lock);
08738       return &p->subs[idx].f;
08739    }
08740 #ifdef HAVE_OPENR2
08741    if (p->mfcr2 && openr2_chan_get_read_enabled(p->r2chan)) {
08742       /* openr2 took care of reading and handling any event
08743         (needanswer, needbusy etc), if we continue we will read()
08744         twice, lets just return a null frame. This should only
08745         happen when openr2 is dialing out */
08746       ast_mutex_unlock(&p->lock);
08747       return &ast_null_frame;
08748    }
08749 #endif
08750 
08751    if (p->subs[idx].needflash) {
08752       /* Send answer frame if requested */
08753       p->subs[idx].needflash = 0;
08754       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08755       p->subs[idx].f.subclass.integer = AST_CONTROL_FLASH;
08756       ast_mutex_unlock(&p->lock);
08757       return &p->subs[idx].f;
08758    }
08759 
08760    if (p->subs[idx].needhold) {
08761       /* Send answer frame if requested */
08762       p->subs[idx].needhold = 0;
08763       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08764       p->subs[idx].f.subclass.integer = AST_CONTROL_HOLD;
08765       ast_mutex_unlock(&p->lock);
08766       ast_debug(1, "Sending hold on '%s'\n", ast->name);
08767       return &p->subs[idx].f;
08768    }
08769 
08770    if (p->subs[idx].needunhold) {
08771       /* Send answer frame if requested */
08772       p->subs[idx].needunhold = 0;
08773       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08774       p->subs[idx].f.subclass.integer = AST_CONTROL_UNHOLD;
08775       ast_mutex_unlock(&p->lock);
08776       ast_debug(1, "Sending unhold on '%s'\n", ast->name);
08777       return &p->subs[idx].f;
08778    }
08779 
08780    if (ast->rawreadformat == AST_FORMAT_SLINEAR) {
08781       if (!p->subs[idx].linear) {
08782          p->subs[idx].linear = 1;
08783          res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
08784          if (res)
08785             ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to linear mode.\n", p->channel, idx);
08786       }
08787    } else if ((ast->rawreadformat == AST_FORMAT_ULAW) ||
08788       (ast->rawreadformat == AST_FORMAT_ALAW)) {
08789       if (p->subs[idx].linear) {
08790          p->subs[idx].linear = 0;
08791          res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
08792          if (res)
08793             ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to companded mode.\n", p->channel, idx);
08794       }
08795    } else {
08796       ast_log(LOG_WARNING, "Don't know how to read frames in format %s\n", ast_getformatname(ast->rawreadformat));
08797       ast_mutex_unlock(&p->lock);
08798       return NULL;
08799    }
08800    readbuf = ((unsigned char *)p->subs[idx].buffer) + AST_FRIENDLY_OFFSET;
08801    CHECK_BLOCKING(ast);
08802    res = read(p->subs[idx].dfd, readbuf, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
08803    ast_clear_flag(ast, AST_FLAG_BLOCKING);
08804    /* Check for hangup */
08805    if (res < 0) {
08806       f = NULL;
08807       if (res == -1) {
08808          if (errno == EAGAIN) {
08809             /* Return "NULL" frame if there is nobody there */
08810             ast_mutex_unlock(&p->lock);
08811             return &p->subs[idx].f;
08812          } else if (errno == ELAST) {
08813             if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
08814                struct analog_pvt *analog_p = p->sig_pvt;
08815                f = analog_exception(analog_p, ast);
08816             } else {
08817                f = __dahdi_exception(ast);
08818             }
08819          } else
08820             ast_log(LOG_WARNING, "dahdi_rec: %s\n", strerror(errno));
08821       }
08822       ast_mutex_unlock(&p->lock);
08823       return f;
08824    }
08825    if (res != (p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE)) {
08826       ast_debug(1, "Short read (%d/%d), must be an event...\n", res, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
08827       if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
08828          struct analog_pvt *analog_p = p->sig_pvt;
08829          f = analog_exception(analog_p, ast);
08830       } else {
08831          f = __dahdi_exception(ast);
08832       }
08833       ast_mutex_unlock(&p->lock);
08834       return f;
08835    }
08836    if (p->tdd) { /* if in TDD mode, see if we receive that */
08837       int c;
08838 
08839       c = tdd_feed(p->tdd,readbuf,READ_SIZE);
08840       if (c < 0) {
08841          ast_debug(1,"tdd_feed failed\n");
08842          ast_mutex_unlock(&p->lock);
08843          return NULL;
08844       }
08845       if (c) { /* if a char to return */
08846          p->subs[idx].f.subclass.integer = 0;
08847          p->subs[idx].f.frametype = AST_FRAME_TEXT;
08848          p->subs[idx].f.mallocd = 0;
08849          p->subs[idx].f.offset = AST_FRIENDLY_OFFSET;
08850          p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET;
08851          p->subs[idx].f.datalen = 1;
08852          *((char *) p->subs[idx].f.data.ptr) = c;
08853          ast_mutex_unlock(&p->lock);
08854          return &p->subs[idx].f;
08855       }
08856    }
08857    if (idx == SUB_REAL) {
08858       /* Ensure the CW timers decrement only on a single subchannel */
08859       if (p->cidcwexpire) {
08860          if (!--p->cidcwexpire) {
08861             /* Expired CID/CW */
08862             ast_verb(3, "CPE does not support Call Waiting Caller*ID.\n");
08863             restore_conference(p);
08864          }
08865       }
08866       if (p->cid_suppress_expire) {
08867          --p->cid_suppress_expire;
08868       }
08869       if (p->callwaitingrepeat) {
08870          if (!--p->callwaitingrepeat) {
08871             /* Expired, Repeat callwaiting tone */
08872             ++p->callwaitrings;
08873             dahdi_callwait(ast);
08874          }
08875       }
08876    }
08877    if (p->subs[idx].linear) {
08878       p->subs[idx].f.datalen = READ_SIZE * 2;
08879    } else
08880       p->subs[idx].f.datalen = READ_SIZE;
08881 
08882    /* Handle CallerID Transmission */
08883    if ((p->owner == ast) && p->cidspill) {
08884       send_callerid(p);
08885    }
08886 
08887    p->subs[idx].f.frametype = AST_FRAME_VOICE;
08888    p->subs[idx].f.subclass.codec = ast->rawreadformat;
08889    p->subs[idx].f.samples = READ_SIZE;
08890    p->subs[idx].f.mallocd = 0;
08891    p->subs[idx].f.offset = AST_FRIENDLY_OFFSET;
08892    p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET / sizeof(p->subs[idx].buffer[0]);
08893 #if 0
08894    ast_debug(1, "Read %d of voice on %s\n", p->subs[idx].f.datalen, ast->name);
08895 #endif
08896    if (p->dialing ||  p->radio || /* Transmitting something */
08897       (idx && (ast->_state != AST_STATE_UP)) || /* Three-way or callwait that isn't up */
08898       ((idx == SUB_CALLWAIT) && !p->subs[SUB_CALLWAIT].inthreeway) /* Inactive and non-confed call-wait */
08899       ) {
08900       /* Whoops, we're still dialing, or in a state where we shouldn't transmit....
08901          don't send anything */
08902       p->subs[idx].f.frametype = AST_FRAME_NULL;
08903       p->subs[idx].f.subclass.integer = 0;
08904       p->subs[idx].f.samples = 0;
08905       p->subs[idx].f.mallocd = 0;
08906       p->subs[idx].f.offset = 0;
08907       p->subs[idx].f.data.ptr = NULL;
08908       p->subs[idx].f.datalen= 0;
08909    }
08910    if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect || p->callprogress || p->waitingfordt.tv_sec) && !idx) {
08911       /* Perform busy detection etc on the dahdi line */
08912       int mute;
08913 
08914       f = ast_dsp_process(ast, p->dsp, &p->subs[idx].f);
08915 
08916       /* Check if DSP code thinks we should be muting this frame and mute the conference if so */
08917       mute = ast_dsp_was_muted(p->dsp);
08918       if (p->muting != mute) {
08919          p->muting = mute;
08920          dahdi_confmute(p, mute);
08921       }
08922 
08923       if (f) {
08924          if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass.integer == AST_CONTROL_BUSY)) {
08925             if ((ast->_state == AST_STATE_UP) && !p->outgoing) {
08926                /* Treat this as a "hangup" instead of a "busy" on the assumption that
08927                   a busy */
08928                f = NULL;
08929             }
08930          } else if (f->frametype == AST_FRAME_DTMF_BEGIN
08931             || f->frametype == AST_FRAME_DTMF_END) {
08932 #ifdef HAVE_PRI
08933             if (dahdi_sig_pri_lib_handles(p->sig)
08934                && !((struct sig_pri_chan *) p->sig_pvt)->proceeding
08935                && p->pri
08936                && ((!p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING))
08937                   || (p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)))) {
08938                /* Don't accept in-band DTMF when in overlap dial mode */
08939                ast_debug(1, "Absorbing inband %s DTMF digit: 0x%02X '%c' on %s\n",
08940                   f->frametype == AST_FRAME_DTMF_BEGIN ? "begin" : "end",
08941                   f->subclass.integer, f->subclass.integer, ast->name);
08942 
08943                f->frametype = AST_FRAME_NULL;
08944                f->subclass.integer = 0;
08945             }
08946 #endif
08947             /* DSP clears us of being pulse */
08948             p->pulsedial = 0;
08949          } else if (p->waitingfordt.tv_sec) {
08950             if (ast_tvdiff_ms(ast_tvnow(), p->waitingfordt) >= p->waitfordialtone ) {
08951                p->waitingfordt.tv_sec = 0;
08952                ast_log(LOG_WARNING, "Never saw dialtone on channel %d\n", p->channel);
08953                f=NULL;
08954             } else if (f->frametype == AST_FRAME_VOICE) {
08955                f->frametype = AST_FRAME_NULL;
08956                f->subclass.integer = 0;
08957                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) {
08958                   p->waitingfordt.tv_sec = 0;
08959                   p->dsp_features &= ~DSP_FEATURE_WAITDIALTONE;
08960                   ast_dsp_set_features(p->dsp, p->dsp_features);
08961                   ast_log(LOG_DEBUG, "Got 10 samples of dialtone!\n");
08962                   if (!ast_strlen_zero(p->dop.dialstr)) { /* Dial deferred digits */
08963                      res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
08964                      if (res < 0) {
08965                         ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d\n", p->channel);
08966                         p->dop.dialstr[0] = '\0';
08967                         ast_mutex_unlock(&p->lock);
08968                         return NULL;
08969                      } else {
08970                         ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", p->dop.dialstr);
08971                         p->dialing = 1;
08972                         p->dop.dialstr[0] = '\0';
08973                         p->dop.op = DAHDI_DIAL_OP_REPLACE;
08974                         ast_setstate(ast, AST_STATE_DIALING);
08975                      }
08976                   }
08977                }
08978             }
08979          }
08980       }
08981    } else
08982       f = &p->subs[idx].f;
08983 
08984    if (f) {
08985       switch (f->frametype) {
08986       case AST_FRAME_DTMF_BEGIN:
08987       case AST_FRAME_DTMF_END:
08988          if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
08989             analog_handle_dtmf(p->sig_pvt, ast, idx, &f);
08990          } else {
08991             dahdi_handle_dtmf(ast, idx, &f);
08992          }
08993          break;
08994       case AST_FRAME_VOICE:
08995          if (p->cidspill || p->cid_suppress_expire) {
08996             /* We are/were sending a caller id spill.  Suppress any echo. */
08997             p->subs[idx].f.frametype = AST_FRAME_NULL;
08998             p->subs[idx].f.subclass.integer = 0;
08999             p->subs[idx].f.samples = 0;
09000             p->subs[idx].f.mallocd = 0;
09001             p->subs[idx].f.offset = 0;
09002             p->subs[idx].f.data.ptr = NULL;
09003             p->subs[idx].f.datalen= 0;
09004          }
09005          break;
09006       default:
09007          break;
09008       }
09009    }
09010 
09011    /* If we have a fake_event, trigger exception to handle it */
09012    if (p->fake_event)
09013       ast_set_flag(ast, AST_FLAG_EXCEPTION);
09014 
09015    ast_mutex_unlock(&p->lock);
09016    return f;
09017 }
09018 
09019 static int my_dahdi_write(struct dahdi_pvt *p, unsigned char *buf, int len, int idx, int linear)
09020 {
09021    int sent=0;
09022    int size;
09023    int res;
09024    int fd;
09025    fd = p->subs[idx].dfd;
09026    while (len) {
09027       size = len;
09028       if (size > (linear ? READ_SIZE * 2 : READ_SIZE))
09029          size = (linear ? READ_SIZE * 2 : READ_SIZE);
09030       res = write(fd, buf, size);
09031       if (res != size) {
09032          ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
09033          return sent;
09034       }
09035       len -= size;
09036       buf += size;
09037    }
09038    return sent;
09039 }
09040 
09041 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame)
09042 {
09043    struct dahdi_pvt *p = ast->tech_pvt;
09044    int res;
09045    int idx;
09046    idx = dahdi_get_index(ast, p, 0);
09047    if (idx < 0) {
09048       ast_log(LOG_WARNING, "%s doesn't really exist?\n", ast->name);
09049       return -1;
09050    }
09051 
09052    /* Write a frame of (presumably voice) data */
09053    if (frame->frametype != AST_FRAME_VOICE) {
09054       if (frame->frametype != AST_FRAME_IMAGE)
09055          ast_log(LOG_WARNING, "Don't know what to do with frame type '%d'\n", frame->frametype);
09056       return 0;
09057    }
09058    if ((frame->subclass.codec != AST_FORMAT_SLINEAR) &&
09059       (frame->subclass.codec != AST_FORMAT_ULAW) &&
09060       (frame->subclass.codec != AST_FORMAT_ALAW)) {
09061       ast_log(LOG_WARNING, "Cannot handle frames in %s format\n", ast_getformatname(frame->subclass.codec));
09062       return -1;
09063    }
09064    if (p->dialing) {
09065       ast_debug(1, "Dropping frame since I'm still dialing on %s...\n",ast->name);
09066       return 0;
09067    }
09068    if (!p->owner) {
09069       ast_debug(1, "Dropping frame since there is no active owner on %s...\n",ast->name);
09070       return 0;
09071    }
09072    if (p->cidspill) {
09073       ast_debug(1, "Dropping frame since I've still got a callerid spill on %s...\n",
09074          ast->name);
09075       return 0;
09076    }
09077    /* Return if it's not valid data */
09078    if (!frame->data.ptr || !frame->datalen)
09079       return 0;
09080 
09081    if (frame->subclass.codec == AST_FORMAT_SLINEAR) {
09082       if (!p->subs[idx].linear) {
09083          p->subs[idx].linear = 1;
09084          res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09085          if (res)
09086             ast_log(LOG_WARNING, "Unable to set linear mode on channel %d\n", p->channel);
09087       }
09088       res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 1);
09089    } else {
09090       /* x-law already */
09091       if (p->subs[idx].linear) {
09092          p->subs[idx].linear = 0;
09093          res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09094          if (res)
09095             ast_log(LOG_WARNING, "Unable to set companded mode on channel %d\n", p->channel);
09096       }
09097       res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 0);
09098    }
09099    if (res < 0) {
09100       ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
09101       return -1;
09102    }
09103    return 0;
09104 }
09105 
09106 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen)
09107 {
09108    struct dahdi_pvt *p = chan->tech_pvt;
09109    int res=-1;
09110    int idx;
09111    int func = DAHDI_FLASH;
09112 
09113    ast_mutex_lock(&p->lock);
09114    ast_debug(1, "Requested indication %d on channel %s\n", condition, chan->name);
09115    switch (p->sig) {
09116 #if defined(HAVE_PRI)
09117    case SIG_PRI_LIB_HANDLE_CASES:
09118       res = sig_pri_indicate(p->sig_pvt, chan, condition, data, datalen);
09119       ast_mutex_unlock(&p->lock);
09120       return res;
09121 #endif   /* defined(HAVE_PRI) */
09122 #if defined(HAVE_SS7)
09123    case SIG_SS7:
09124       res = sig_ss7_indicate(p->sig_pvt, chan, condition, data, datalen);
09125       ast_mutex_unlock(&p->lock);
09126       return res;
09127 #endif   /* defined(HAVE_SS7) */
09128    default:
09129       break;
09130    }
09131 #ifdef HAVE_OPENR2
09132    if (p->mfcr2 && !p->mfcr2_call_accepted) {
09133       ast_mutex_unlock(&p->lock);
09134       /* if this is an R2 call and the call is not yet accepted, we don't want the
09135          tone indications to mess up with the MF tones */
09136       return 0;
09137    }
09138 #endif
09139    idx = dahdi_get_index(chan, p, 0);
09140    if (idx == SUB_REAL) {
09141       switch (condition) {
09142       case AST_CONTROL_BUSY:
09143          res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_BUSY);
09144          break;
09145       case AST_CONTROL_RINGING:
09146          res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_RINGTONE);
09147 
09148          if (chan->_state != AST_STATE_UP) {
09149             if ((chan->_state != AST_STATE_RING) ||
09150                ((p->sig != SIG_FXSKS) &&
09151              (p->sig != SIG_FXSLS) &&
09152              (p->sig != SIG_FXSGS)))
09153             ast_setstate(chan, AST_STATE_RINGING);
09154          }
09155          break;
09156       case AST_CONTROL_PROCEEDING:
09157          ast_debug(1,"Received AST_CONTROL_PROCEEDING on %s\n",chan->name);
09158          /* don't continue in ast_indicate */
09159          res = 0;
09160          break;
09161       case AST_CONTROL_PROGRESS:
09162          ast_debug(1,"Received AST_CONTROL_PROGRESS on %s\n",chan->name);
09163          /* don't continue in ast_indicate */
09164          res = 0;
09165          break;
09166       case AST_CONTROL_CONGESTION:
09167          chan->hangupcause = AST_CAUSE_CONGESTION;
09168          break;
09169       case AST_CONTROL_HOLD:
09170          ast_moh_start(chan, data, p->mohinterpret);
09171          break;
09172       case AST_CONTROL_UNHOLD:
09173          ast_moh_stop(chan);
09174          break;
09175       case AST_CONTROL_RADIO_KEY:
09176          if (p->radio)
09177             res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
09178          res = 0;
09179          break;
09180       case AST_CONTROL_RADIO_UNKEY:
09181          if (p->radio)
09182             res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_RINGOFF);
09183          res = 0;
09184          break;
09185       case AST_CONTROL_FLASH:
09186          /* flash hookswitch */
09187          if (ISTRUNK(p) && (p->sig != SIG_PRI)) {
09188             /* Clear out the dial buffer */
09189             p->dop.dialstr[0] = '\0';
09190             if ((ioctl(p->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
09191                ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
09192                   chan->name, strerror(errno));
09193             } else
09194                res = 0;
09195          } else
09196             res = 0;
09197          break;
09198       case AST_CONTROL_SRCUPDATE:
09199          res = 0;
09200          break;
09201       case -1:
09202          res = tone_zone_play_tone(p->subs[idx].dfd, -1);
09203          break;
09204       }
09205    } else {
09206       res = 0;
09207    }
09208    ast_mutex_unlock(&p->lock);
09209    return res;
09210 }
09211 
09212 #if defined(HAVE_PRI)
09213 static struct ast_str *create_channel_name(struct dahdi_pvt *i, int is_outgoing, char *address)
09214 #else
09215 static struct ast_str *create_channel_name(struct dahdi_pvt *i)
09216 #endif   /* defined(HAVE_PRI) */
09217 {
09218    struct ast_str *chan_name;
09219    int x, y;
09220 
09221    /* Create the new channel name tail. */
09222    if (!(chan_name = ast_str_create(32))) {
09223       return NULL;
09224    }
09225    if (i->channel == CHAN_PSEUDO) {
09226       ast_str_set(&chan_name, 0, "pseudo-%ld", ast_random());
09227 #if defined(HAVE_PRI)
09228    } else if (i->pri) {
09229       ast_mutex_lock(&i->pri->lock);
09230       y = ++i->pri->new_chan_seq;
09231       if (is_outgoing) {
09232          ast_str_set(&chan_name, 0, "i%d/%s-%x", i->pri->span, address, y);
09233          address[0] = '\0';
09234       } else if (ast_strlen_zero(i->cid_subaddr)) {
09235          /* Put in caller-id number only since there is no subaddress. */
09236          ast_str_set(&chan_name, 0, "i%d/%s-%x", i->pri->span, i->cid_num, y);
09237       } else {
09238          /* Put in caller-id number and subaddress. */
09239          ast_str_set(&chan_name, 0, "i%d/%s:%s-%x", i->pri->span, i->cid_num,
09240             i->cid_subaddr, y);
09241       }
09242       ast_mutex_unlock(&i->pri->lock);
09243 #endif   /* defined(HAVE_PRI) */
09244    } else {
09245       y = 1;
09246       do {
09247          ast_str_set(&chan_name, 0, "%d-%d", i->channel, y);
09248          for (x = 0; x < 3; ++x) {
09249             if (i->subs[x].owner && !strcasecmp(ast_str_buffer(chan_name),
09250                i->subs[x].owner->name + 6)) {
09251                break;
09252             }
09253          }
09254          ++y;
09255       } while (x < 3);
09256    }
09257    return chan_name;
09258 }
09259 
09260 static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpbx, int idx, int law, const char *linkedid)
09261 {
09262    struct ast_channel *tmp;
09263    format_t deflaw;
09264    int x;
09265    int features;
09266    struct ast_str *chan_name;
09267    struct ast_variable *v;
09268 
09269    if (i->subs[idx].owner) {
09270       ast_log(LOG_WARNING, "Channel %d already has a %s call\n", i->channel,subnames[idx]);
09271       return NULL;
09272    }
09273 
09274 #if defined(HAVE_PRI)
09275    /*
09276     * The dnid has been stuffed with the called-number[:subaddress]
09277     * by dahdi_request() for outgoing calls.
09278     */
09279    chan_name = create_channel_name(i, i->outgoing, i->dnid);
09280 #else
09281    chan_name = create_channel_name(i);
09282 #endif   /* defined(HAVE_PRI) */
09283    if (!chan_name) {
09284       return NULL;
09285    }
09286 
09287    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));
09288    ast_free(chan_name);
09289    if (!tmp)
09290       return NULL;
09291    tmp->tech = &dahdi_tech;
09292 #if defined(HAVE_PRI)
09293    if (i->pri) {
09294       ast_cc_copy_config_params(i->cc_params, i->pri->cc_params);
09295    }
09296 #endif   /* defined(HAVE_PRI) */
09297    ast_channel_cc_params_init(tmp, i->cc_params);
09298    if (law) {
09299       i->law = law;
09300       if (law == DAHDI_LAW_ALAW) {
09301          deflaw = AST_FORMAT_ALAW;
09302       } else {
09303          deflaw = AST_FORMAT_ULAW;
09304       }
09305    } else {
09306       switch (i->sig) {
09307       case SIG_PRI_LIB_HANDLE_CASES:
09308          /* Make sure companding law is known. */
09309          i->law = (i->law_default == DAHDI_LAW_ALAW)
09310             ? DAHDI_LAW_ALAW : DAHDI_LAW_MULAW;
09311          break;
09312       default:
09313          i->law = i->law_default;
09314          break;
09315       }
09316       if (i->law_default == DAHDI_LAW_ALAW) {
09317          deflaw = AST_FORMAT_ALAW;
09318       } else {
09319          deflaw = AST_FORMAT_ULAW;
09320       }
09321    }
09322    ast_channel_set_fd(tmp, 0, i->subs[idx].dfd);
09323    tmp->nativeformats = deflaw;
09324    /* Start out assuming ulaw since it's smaller :) */
09325    tmp->rawreadformat = deflaw;
09326    tmp->readformat = deflaw;
09327    tmp->rawwriteformat = deflaw;
09328    tmp->writeformat = deflaw;
09329    i->subs[idx].linear = 0;
09330    dahdi_setlinear(i->subs[idx].dfd, i->subs[idx].linear);
09331    features = 0;
09332    if (idx == SUB_REAL) {
09333       if (i->busydetect && CANBUSYDETECT(i))
09334          features |= DSP_FEATURE_BUSY_DETECT;
09335       if ((i->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(i))
09336          features |= DSP_FEATURE_CALL_PROGRESS;
09337       if ((i->waitfordialtone) && CANPROGRESSDETECT(i))
09338          features |= DSP_FEATURE_WAITDIALTONE;
09339       if ((!i->outgoing && (i->callprogress & CALLPROGRESS_FAX_INCOMING)) ||
09340          (i->outgoing && (i->callprogress & CALLPROGRESS_FAX_OUTGOING))) {
09341          features |= DSP_FEATURE_FAX_DETECT;
09342       }
09343       x = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
09344       if (ioctl(i->subs[idx].dfd, DAHDI_TONEDETECT, &x)) {
09345          i->hardwaredtmf = 0;
09346          features |= DSP_FEATURE_DIGIT_DETECT;
09347       } else if (NEED_MFDETECT(i)) {
09348          i->hardwaredtmf = 1;
09349          features |= DSP_FEATURE_DIGIT_DETECT;
09350       }
09351    }
09352    if (features) {
09353       if (i->dsp) {
09354          ast_debug(1, "Already have a dsp on %s?\n", tmp->name);
09355       } else {
09356          if (i->channel != CHAN_PSEUDO)
09357             i->dsp = ast_dsp_new();
09358          else
09359             i->dsp = NULL;
09360          if (i->dsp) {
09361             i->dsp_features = features;
09362 #if defined(HAVE_PRI) || defined(HAVE_SS7)
09363             /* We cannot do progress detection until receive PROGRESS message */
09364             if (i->outgoing && (dahdi_sig_pri_lib_handles(i->sig) || (i->sig == SIG_SS7))) {
09365                /* Remember requested DSP features, don't treat
09366                   talking as ANSWER */
09367                i->dsp_features = features & ~DSP_PROGRESS_TALK;
09368                features = 0;
09369             }
09370 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
09371             ast_dsp_set_features(i->dsp, features);
09372             ast_dsp_set_digitmode(i->dsp, DSP_DIGITMODE_DTMF | i->dtmfrelax);
09373             if (!ast_strlen_zero(progzone))
09374                ast_dsp_set_call_progress_zone(i->dsp, progzone);
09375             if (i->busydetect && CANBUSYDETECT(i)) {
09376                ast_dsp_set_busy_count(i->dsp, i->busycount);
09377                ast_dsp_set_busy_pattern(i->dsp, i->busy_tonelength, i->busy_quietlength);
09378             }
09379          }
09380       }
09381    }
09382 
09383    if (state == AST_STATE_RING)
09384       tmp->rings = 1;
09385    tmp->tech_pvt = i;
09386    if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) {
09387       /* Only FXO signalled stuff can be picked up */
09388       tmp->callgroup = i->callgroup;
09389       tmp->pickupgroup = i->pickupgroup;
09390    }
09391    if (!ast_strlen_zero(i->parkinglot))
09392       ast_string_field_set(tmp, parkinglot, i->parkinglot);
09393    if (!ast_strlen_zero(i->language))
09394       ast_string_field_set(tmp, language, i->language);
09395    if (!i->owner)
09396       i->owner = tmp;
09397    if (!ast_strlen_zero(i->accountcode))
09398       ast_string_field_set(tmp, accountcode, i->accountcode);
09399    if (i->amaflags)
09400       tmp->amaflags = i->amaflags;
09401    i->subs[idx].owner = tmp;
09402    ast_copy_string(tmp->context, i->context, sizeof(tmp->context));
09403    if (!analog_lib_handles(i->sig, i->radio, i->oprmode)) {
09404       ast_string_field_set(tmp, call_forward, i->call_forward);
09405    }
09406    /* If we've been told "no ADSI" then enforce it */
09407    if (!i->adsi)
09408       tmp->adsicpe = AST_ADSI_UNAVAILABLE;
09409    if (!ast_strlen_zero(i->exten))
09410       ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten));
09411    if (!ast_strlen_zero(i->rdnis)) {
09412       tmp->redirecting.from.number.valid = 1;
09413       tmp->redirecting.from.number.str = ast_strdup(i->rdnis);
09414    }
09415    if (!ast_strlen_zero(i->dnid)) {
09416       tmp->dialed.number.str = ast_strdup(i->dnid);
09417    }
09418 
09419    /* Don't use ast_set_callerid() here because it will
09420     * generate a needless NewCallerID event */
09421 #if defined(HAVE_PRI) || defined(HAVE_SS7)
09422    if (!ast_strlen_zero(i->cid_ani)) {
09423       tmp->caller.ani.number.valid = 1;
09424       tmp->caller.ani.number.str = ast_strdup(i->cid_ani);
09425    } else if (!ast_strlen_zero(i->cid_num)) {
09426       tmp->caller.ani.number.valid = 1;
09427       tmp->caller.ani.number.str = ast_strdup(i->cid_num);
09428    }
09429 #else
09430    if (!ast_strlen_zero(i->cid_num)) {
09431       tmp->caller.ani.number.valid = 1;
09432       tmp->caller.ani.number.str = ast_strdup(i->cid_num);
09433    }
09434 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
09435    tmp->caller.id.name.presentation = i->callingpres;
09436    tmp->caller.id.number.presentation = i->callingpres;
09437    tmp->caller.id.number.plan = i->cid_ton;
09438    tmp->caller.ani2 = i->cid_ani2;
09439    tmp->caller.id.tag = ast_strdup(i->cid_tag);
09440    /* clear the fake event in case we posted one before we had ast_channel */
09441    i->fake_event = 0;
09442    /* Assure there is no confmute on this channel */
09443    dahdi_confmute(i, 0);
09444    i->muting = 0;
09445    /* Configure the new channel jb */
09446    ast_jb_configure(tmp, &global_jbconf);
09447 
09448    ast_devstate_changed_literal(ast_state_chan2dev(state), tmp->name);
09449 
09450    for (v = i->vars ; v ; v = v->next)
09451       pbx_builtin_setvar_helper(tmp, v->name, v->value);
09452 
09453    ast_module_ref(ast_module_info->self);
09454 
09455    if (startpbx) {
09456 #ifdef HAVE_OPENR2
09457       if (i->mfcr2call) {
09458          pbx_builtin_setvar_helper(tmp, "MFCR2_CATEGORY", openr2_proto_get_category_string(i->mfcr2_recvd_category));
09459       }
09460 #endif
09461       if (ast_pbx_start(tmp)) {
09462          ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
09463          ast_hangup(tmp);
09464          return NULL;
09465       }
09466    }
09467    return tmp;
09468 }
09469 
09470 
09471 static int my_getsigstr(struct ast_channel *chan, char *str, const char *term, int ms)
09472 {
09473    char c;
09474 
09475    *str = 0; /* start with empty output buffer */
09476    for (;;)
09477    {
09478       /* Wait for the first digit (up to specified ms). */
09479       c = ast_waitfordigit(chan, ms);
09480       /* if timeout, hangup or error, return as such */
09481       if (c < 1)
09482          return c;
09483       *str++ = c;
09484       *str = 0;
09485       if (strchr(term, c))
09486          return 1;
09487    }
09488 }
09489 
09490 static int dahdi_wink(struct dahdi_pvt *p, int idx)
09491 {
09492    int j;
09493    dahdi_set_hook(p->subs[idx].dfd, DAHDI_WINK);
09494    for (;;)
09495    {
09496       /* set bits of interest */
09497       j = DAHDI_IOMUX_SIGEVENT;
09498       /* wait for some happening */
09499       if (ioctl(p->subs[idx].dfd,DAHDI_IOMUX,&j) == -1) return(-1);
09500       /* exit loop if we have it */
09501       if (j & DAHDI_IOMUX_SIGEVENT) break;
09502    }
09503    /* get the event info */
09504    if (ioctl(p->subs[idx].dfd,DAHDI_GETEVENT,&j) == -1) return(-1);
09505    return 0;
09506 }
09507 
09508 /*! \brief enable or disable the chan_dahdi Do-Not-Disturb mode for a DAHDI channel
09509  * \param dahdichan "Physical" DAHDI channel (e.g: DAHDI/5)
09510  * \param flag on 1 to enable, 0 to disable, -1 return dnd value
09511  *
09512  * chan_dahdi has a DND (Do Not Disturb) mode for each dahdichan (physical
09513  * DAHDI channel). Use this to enable or disable it.
09514  *
09515  * \bug the use of the word "channel" for those dahdichans is really confusing.
09516  */
09517 static int dahdi_dnd(struct dahdi_pvt *dahdichan, int flag)
09518 {
09519    if (analog_lib_handles(dahdichan->sig, dahdichan->radio, dahdichan->oprmode)) {
09520       return analog_dnd(dahdichan->sig_pvt, flag);
09521    }
09522 
09523    if (flag == -1) {
09524       return dahdichan->dnd;
09525    }
09526 
09527    /* Do not disturb */
09528    dahdichan->dnd = flag;
09529    ast_verb(3, "%s DND on channel %d\n",
09530          flag? "Enabled" : "Disabled",
09531          dahdichan->channel);
09532    manager_event(EVENT_FLAG_SYSTEM, "DNDState",
09533          "Channel: DAHDI/%d\r\n"
09534          "Status: %s\r\n", dahdichan->channel,
09535          flag? "enabled" : "disabled");
09536 
09537    return 0;
09538 }
09539 
09540 static void *analog_ss_thread(void *data)
09541 {
09542    struct ast_channel *chan = data;
09543    struct dahdi_pvt *p = chan->tech_pvt;
09544    char exten[AST_MAX_EXTENSION] = "";
09545    char exten2[AST_MAX_EXTENSION] = "";
09546    unsigned char buf[256];
09547    char dtmfcid[300];
09548    char dtmfbuf[300];
09549    struct callerid_state *cs = NULL;
09550    char *name = NULL, *number = NULL;
09551    int distMatches;
09552    int curRingData[3];
09553    int receivedRingT;
09554    int counter1;
09555    int counter;
09556    int samples = 0;
09557    struct ast_smdi_md_message *smdi_msg = NULL;
09558    int flags = 0;
09559    int i;
09560    int timeout;
09561    int getforward = 0;
09562    char *s1, *s2;
09563    int len = 0;
09564    int res;
09565    int idx;
09566 
09567    ast_mutex_lock(&ss_thread_lock);
09568    ss_thread_count++;
09569    ast_mutex_unlock(&ss_thread_lock);
09570    /* in the bizarre case where the channel has become a zombie before we
09571       even get started here, abort safely
09572    */
09573    if (!p) {
09574       ast_log(LOG_WARNING, "Channel became a zombie before simple switch could be started (%s)\n", chan->name);
09575       ast_hangup(chan);
09576       goto quit;
09577    }
09578    ast_verb(3, "Starting simple switch on '%s'\n", chan->name);
09579    idx = dahdi_get_index(chan, p, 1);
09580    if (idx < 0) {
09581       ast_log(LOG_WARNING, "Huh?\n");
09582       ast_hangup(chan);
09583       goto quit;
09584    }
09585    if (p->dsp)
09586       ast_dsp_digitreset(p->dsp);
09587    switch (p->sig) {
09588    case SIG_FEATD:
09589    case SIG_FEATDMF:
09590    case SIG_FEATDMF_TA:
09591    case SIG_E911:
09592    case SIG_FGC_CAMAMF:
09593    case SIG_FEATB:
09594    case SIG_EMWINK:
09595    case SIG_SF_FEATD:
09596    case SIG_SF_FEATDMF:
09597    case SIG_SF_FEATB:
09598    case SIG_SFWINK:
09599       if (dahdi_wink(p, idx))
09600          goto quit;
09601       /* Fall through */
09602    case SIG_EM:
09603    case SIG_EM_E1:
09604    case SIG_SF:
09605    case SIG_FGC_CAMA:
09606       res = tone_zone_play_tone(p->subs[idx].dfd, -1);
09607       if (p->dsp)
09608          ast_dsp_digitreset(p->dsp);
09609       /* set digit mode appropriately */
09610       if (p->dsp) {
09611          if (NEED_MFDETECT(p))
09612             ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
09613          else
09614             ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
09615       }
09616       memset(dtmfbuf, 0, sizeof(dtmfbuf));
09617       /* Wait for the first digit only if immediate=no */
09618       if (!p->immediate)
09619          /* Wait for the first digit (up to 5 seconds). */
09620          res = ast_waitfordigit(chan, 5000);
09621       else
09622          res = 0;
09623       if (res > 0) {
09624          /* save first char */
09625          dtmfbuf[0] = res;
09626          switch (p->sig) {
09627          case SIG_FEATD:
09628          case SIG_SF_FEATD:
09629             res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
09630             if (res > 0)
09631                res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
09632             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
09633             break;
09634          case SIG_FEATDMF_TA:
09635             res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
09636             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
09637             if (dahdi_wink(p, idx)) goto quit;
09638             dtmfbuf[0] = 0;
09639             /* Wait for the first digit (up to 5 seconds). */
09640             res = ast_waitfordigit(chan, 5000);
09641             if (res <= 0) break;
09642             dtmfbuf[0] = res;
09643             /* fall through intentionally */
09644          case SIG_FEATDMF:
09645          case SIG_E911:
09646          case SIG_FGC_CAMAMF:
09647          case SIG_SF_FEATDMF:
09648             res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
09649             /* if international caca, do it again to get real ANO */
09650             if ((p->sig == SIG_FEATDMF) && (dtmfbuf[1] != '0') && (strlen(dtmfbuf) != 14))
09651             {
09652                if (dahdi_wink(p, idx)) goto quit;
09653                dtmfbuf[0] = 0;
09654                /* Wait for the first digit (up to 5 seconds). */
09655                res = ast_waitfordigit(chan, 5000);
09656                if (res <= 0) break;
09657                dtmfbuf[0] = res;
09658                res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
09659             }
09660             if (res > 0) {
09661                /* if E911, take off hook */
09662                if (p->sig == SIG_E911)
09663                   dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
09664                res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "#", 3000);
09665             }
09666             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
09667             break;
09668          case SIG_FEATB:
09669          case SIG_SF_FEATB:
09670             res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
09671             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
09672             break;
09673          case SIG_EMWINK:
09674             /* if we received a '*', we are actually receiving Feature Group D
09675                dial syntax, so use that mode; otherwise, fall through to normal
09676                mode
09677             */
09678             if (res == '*') {
09679                res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
09680                if (res > 0)
09681                   res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
09682                if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
09683                break;
09684             }
09685          default:
09686             /* If we got the first digit, get the rest */
09687             len = 1;
09688             dtmfbuf[len] = '\0';
09689             while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
09690                if (ast_exists_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
09691                   timeout = matchdigittimeout;
09692                } else {
09693                   timeout = gendigittimeout;
09694                }
09695                res = ast_waitfordigit(chan, timeout);
09696                if (res < 0) {
09697                   ast_debug(1, "waitfordigit returned < 0...\n");
09698                   ast_hangup(chan);
09699                   goto quit;
09700                } else if (res) {
09701                   dtmfbuf[len++] = res;
09702                   dtmfbuf[len] = '\0';
09703                } else {
09704                   break;
09705                }
09706             }
09707             break;
09708          }
09709       }
09710       if (res == -1) {
09711          ast_log(LOG_WARNING, "getdtmf on channel %d: %s\n", p->channel, strerror(errno));
09712          ast_hangup(chan);
09713          goto quit;
09714       } else if (res < 0) {
09715          ast_debug(1, "Got hung up before digits finished\n");
09716          ast_hangup(chan);
09717          goto quit;
09718       }
09719 
09720       if (p->sig == SIG_FGC_CAMA) {
09721          char anibuf[100];
09722 
09723          if (ast_safe_sleep(chan,1000) == -1) {
09724             ast_hangup(chan);
09725             goto quit;
09726          }
09727          dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
09728          ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
09729          res = my_getsigstr(chan, anibuf, "#", 10000);
09730          if ((res > 0) && (strlen(anibuf) > 2)) {
09731             if (anibuf[strlen(anibuf) - 1] == '#')
09732                anibuf[strlen(anibuf) - 1] = 0;
09733             ast_set_callerid(chan, anibuf + 2, NULL, anibuf + 2);
09734          }
09735          ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
09736       }
09737 
09738       ast_copy_string(exten, dtmfbuf, sizeof(exten));
09739       if (ast_strlen_zero(exten))
09740          ast_copy_string(exten, "s", sizeof(exten));
09741       if (p->sig == SIG_FEATD || p->sig == SIG_EMWINK) {
09742          /* Look for Feature Group D on all E&M Wink and Feature Group D trunks */
09743          if (exten[0] == '*') {
09744             char *stringp=NULL;
09745             ast_copy_string(exten2, exten, sizeof(exten2));
09746             /* Parse out extension and callerid */
09747             stringp=exten2 +1;
09748             s1 = strsep(&stringp, "*");
09749             s2 = strsep(&stringp, "*");
09750             if (s2) {
09751                if (!ast_strlen_zero(p->cid_num))
09752                   ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
09753                else
09754                   ast_set_callerid(chan, s1, NULL, s1);
09755                ast_copy_string(exten, s2, sizeof(exten));
09756             } else
09757                ast_copy_string(exten, s1, sizeof(exten));
09758          } else if (p->sig == SIG_FEATD)
09759             ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d.  Assuming E&M Wink instead\n", p->channel);
09760       }
09761       if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
09762          if (exten[0] == '*') {
09763             char *stringp=NULL;
09764             ast_copy_string(exten2, exten, sizeof(exten2));
09765             /* Parse out extension and callerid */
09766             stringp=exten2 +1;
09767             s1 = strsep(&stringp, "#");
09768             s2 = strsep(&stringp, "#");
09769             if (s2) {
09770                if (!ast_strlen_zero(p->cid_num))
09771                   ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
09772                else
09773                   if (*(s1 + 2))
09774                      ast_set_callerid(chan, s1 + 2, NULL, s1 + 2);
09775                ast_copy_string(exten, s2 + 1, sizeof(exten));
09776             } else
09777                ast_copy_string(exten, s1 + 2, sizeof(exten));
09778          } else
09779             ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d.  Assuming E&M Wink instead\n", p->channel);
09780       }
09781       if ((p->sig == SIG_E911) || (p->sig == SIG_FGC_CAMAMF)) {
09782          if (exten[0] == '*') {
09783             char *stringp=NULL;
09784             ast_copy_string(exten2, exten, sizeof(exten2));
09785             /* Parse out extension and callerid */
09786             stringp=exten2 +1;
09787             s1 = strsep(&stringp, "#");
09788             s2 = strsep(&stringp, "#");
09789             if (s2 && (*(s2 + 1) == '0')) {
09790                if (*(s2 + 2))
09791                   ast_set_callerid(chan, s2 + 2, NULL, s2 + 2);
09792             }
09793             if (s1)  ast_copy_string(exten, s1, sizeof(exten));
09794             else ast_copy_string(exten, "911", sizeof(exten));
09795          } else
09796             ast_log(LOG_WARNING, "Got a non-E911/FGC CAMA input on channel %d.  Assuming E&M Wink instead\n", p->channel);
09797       }
09798       if (p->sig == SIG_FEATB) {
09799          if (exten[0] == '*') {
09800             char *stringp=NULL;
09801             ast_copy_string(exten2, exten, sizeof(exten2));
09802             /* Parse out extension and callerid */
09803             stringp=exten2 +1;
09804             s1 = strsep(&stringp, "#");
09805             ast_copy_string(exten, exten2 + 1, sizeof(exten));
09806          } else
09807             ast_log(LOG_WARNING, "Got a non-Feature Group B input on channel %d.  Assuming E&M Wink instead\n", p->channel);
09808       }
09809       if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
09810          dahdi_wink(p, idx);
09811          /* some switches require a minimum guard time between
09812             the last FGD wink and something that answers
09813             immediately. This ensures it */
09814          if (ast_safe_sleep(chan,100)) goto quit;
09815       }
09816       dahdi_enable_ec(p);
09817       if (NEED_MFDETECT(p)) {
09818          if (p->dsp) {
09819             if (!p->hardwaredtmf)
09820                ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
09821             else {
09822                ast_dsp_free(p->dsp);
09823                p->dsp = NULL;
09824             }
09825          }
09826       }
09827 
09828       if (ast_exists_extension(chan, chan->context, exten, 1,
09829          S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
09830          ast_copy_string(chan->exten, exten, sizeof(chan->exten));
09831          if (p->dsp) ast_dsp_digitreset(p->dsp);
09832          res = ast_pbx_run(chan);
09833          if (res) {
09834             ast_log(LOG_WARNING, "PBX exited non-zero\n");
09835             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
09836          }
09837          goto quit;
09838       } else {
09839          ast_verb(2, "Unknown extension '%s' in context '%s' requested\n", exten, chan->context);
09840          sleep(2);
09841          res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_INFO);
09842          if (res < 0)
09843             ast_log(LOG_WARNING, "Unable to start special tone on %d\n", p->channel);
09844          else
09845             sleep(1);
09846          res = ast_streamfile(chan, "ss-noservice", chan->language);
09847          if (res >= 0)
09848             ast_waitstream(chan, "");
09849          res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
09850          ast_hangup(chan);
09851          goto quit;
09852       }
09853       break;
09854    case SIG_FXOLS:
09855    case SIG_FXOGS:
09856    case SIG_FXOKS:
09857       /* Read the first digit */
09858       timeout = firstdigittimeout;
09859       /* If starting a threeway call, never timeout on the first digit so someone
09860          can use flash-hook as a "hold" feature */
09861       if (p->subs[SUB_THREEWAY].owner)
09862          timeout = 999999;
09863       while (len < AST_MAX_EXTENSION-1) {
09864          /* Read digit unless it's supposed to be immediate, in which case the
09865             only answer is 's' */
09866          if (p->immediate)
09867             res = 's';
09868          else
09869             res = ast_waitfordigit(chan, timeout);
09870          timeout = 0;
09871          if (res < 0) {
09872             ast_debug(1, "waitfordigit returned < 0...\n");
09873             res = tone_zone_play_tone(p->subs[idx].dfd, -1);
09874             ast_hangup(chan);
09875             goto quit;
09876          } else if (res) {
09877             ast_debug(1,"waitfordigit returned '%c' (%d), timeout = %d\n", res, res, timeout);
09878             exten[len++]=res;
09879             exten[len] = '\0';
09880          }
09881          if (!ast_ignore_pattern(chan->context, exten))
09882             tone_zone_play_tone(p->subs[idx].dfd, -1);
09883          else
09884             tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
09885          if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num) && !ast_parking_ext_valid(exten, chan, chan->context)) {
09886             if (!res || !ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
09887                if (getforward) {
09888                   /* Record this as the forwarding extension */
09889                   ast_copy_string(p->call_forward, exten, sizeof(p->call_forward));
09890                   ast_verb(3, "Setting call forward to '%s' on channel %d\n", p->call_forward, p->channel);
09891                   res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
09892                   if (res)
09893                      break;
09894                   usleep(500000);
09895                   res = tone_zone_play_tone(p->subs[idx].dfd, -1);
09896                   sleep(1);
09897                   memset(exten, 0, sizeof(exten));
09898                   res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
09899                   len = 0;
09900                   getforward = 0;
09901                } else {
09902                   res = tone_zone_play_tone(p->subs[idx].dfd, -1);
09903                   ast_copy_string(chan->exten, exten, sizeof(chan->exten));
09904                   if (!ast_strlen_zero(p->cid_num)) {
09905                      if (!p->hidecallerid)
09906                         ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
09907                      else
09908                         ast_set_callerid(chan, NULL, NULL, p->cid_num);
09909                   }
09910                   if (!ast_strlen_zero(p->cid_name)) {
09911                      if (!p->hidecallerid)
09912                         ast_set_callerid(chan, NULL, p->cid_name, NULL);
09913                   }
09914                   ast_setstate(chan, AST_STATE_RING);
09915                   dahdi_enable_ec(p);
09916                   res = ast_pbx_run(chan);
09917                   if (res) {
09918                      ast_log(LOG_WARNING, "PBX exited non-zero\n");
09919                      res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
09920                   }
09921                   goto quit;
09922                }
09923             } else {
09924                /* It's a match, but they just typed a digit, and there is an ambiguous match,
09925                   so just set the timeout to matchdigittimeout and wait some more */
09926                timeout = matchdigittimeout;
09927             }
09928          } else if (res == 0) {
09929             ast_debug(1, "not enough digits (and no ambiguous match)...\n");
09930             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
09931             dahdi_wait_event(p->subs[idx].dfd);
09932             ast_hangup(chan);
09933             goto quit;
09934          } else if (p->callwaiting && !strcmp(exten, "*70")) {
09935             ast_verb(3, "Disabling call waiting on %s\n", chan->name);
09936             /* Disable call waiting if enabled */
09937             p->callwaiting = 0;
09938             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
09939             if (res) {
09940                ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
09941                   chan->name, strerror(errno));
09942             }
09943             len = 0;
09944             ioctl(p->subs[idx].dfd,DAHDI_CONFDIAG,&len);
09945             memset(exten, 0, sizeof(exten));
09946             timeout = firstdigittimeout;
09947 
09948          } else if (!strcmp(exten,ast_pickup_ext())) {
09949             /* Scan all channels and see if there are any
09950              * ringing channels that have call groups
09951              * that equal this channels pickup group
09952              */
09953             if (idx == SUB_REAL) {
09954                /* Switch us from Third call to Call Wait */
09955                if (p->subs[SUB_THREEWAY].owner) {
09956                   /* If you make a threeway call and the *8# a call, it should actually
09957                      look like a callwait */
09958                   alloc_sub(p, SUB_CALLWAIT);
09959                   swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
09960                   unalloc_sub(p, SUB_THREEWAY);
09961                }
09962                dahdi_enable_ec(p);
09963                if (ast_pickup_call(chan)) {
09964                   ast_debug(1, "No call pickup possible...\n");
09965                   res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
09966                   dahdi_wait_event(p->subs[idx].dfd);
09967                }
09968                ast_hangup(chan);
09969                goto quit;
09970             } else {
09971                ast_log(LOG_WARNING, "Huh?  Got *8# on call not on real\n");
09972                ast_hangup(chan);
09973                goto quit;
09974             }
09975 
09976          } else if (!p->hidecallerid && !strcmp(exten, "*67")) {
09977             ast_verb(3, "Disabling Caller*ID on %s\n", chan->name);
09978             /* Disable Caller*ID if enabled */
09979             p->hidecallerid = 1;
09980             ast_party_number_free(&chan->caller.id.number);
09981             ast_party_number_init(&chan->caller.id.number);
09982             ast_party_name_free(&chan->caller.id.name);
09983             ast_party_name_init(&chan->caller.id.name);
09984             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
09985             if (res) {
09986                ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
09987                   chan->name, strerror(errno));
09988             }
09989             len = 0;
09990             memset(exten, 0, sizeof(exten));
09991             timeout = firstdigittimeout;
09992          } else if (p->callreturn && !strcmp(exten, "*69")) {
09993             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
09994             break;
09995          } else if (!strcmp(exten, "*78")) {
09996             dahdi_dnd(p, 1);
09997             /* Do not disturb */
09998             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
09999             getforward = 0;
10000             memset(exten, 0, sizeof(exten));
10001             len = 0;
10002          } else if (!strcmp(exten, "*79")) {
10003             dahdi_dnd(p, 0);
10004             /* Do not disturb */
10005             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10006             getforward = 0;
10007             memset(exten, 0, sizeof(exten));
10008             len = 0;
10009          } else if (p->cancallforward && !strcmp(exten, "*72")) {
10010             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10011             getforward = 1;
10012             memset(exten, 0, sizeof(exten));
10013             len = 0;
10014          } else if (p->cancallforward && !strcmp(exten, "*73")) {
10015             ast_verb(3, "Cancelling call forwarding on channel %d\n", p->channel);
10016             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10017             memset(p->call_forward, 0, sizeof(p->call_forward));
10018             getforward = 0;
10019             memset(exten, 0, sizeof(exten));
10020             len = 0;
10021          } else if ((p->transfer || p->canpark) && ast_parking_ext_valid(exten, chan, chan->context) &&
10022                   p->subs[SUB_THREEWAY].owner &&
10023                   ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
10024             /* This is a three way call, the main call being a real channel,
10025                and we're parking the first call. */
10026             ast_masq_park_call(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), chan, 0, NULL);
10027             ast_verb(3, "Parking call to '%s'\n", chan->name);
10028             break;
10029          } else if (p->hidecallerid && !strcmp(exten, "*82")) {
10030             ast_verb(3, "Enabling Caller*ID on %s\n", chan->name);
10031             /* Enable Caller*ID if enabled */
10032             p->hidecallerid = 0;
10033             ast_set_callerid(chan, p->cid_num, p->cid_name, NULL);
10034             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10035             if (res) {
10036                ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
10037                   chan->name, strerror(errno));
10038             }
10039             len = 0;
10040             memset(exten, 0, sizeof(exten));
10041             timeout = firstdigittimeout;
10042          } else if (!strcmp(exten, "*0")) {
10043             struct ast_channel *nbridge =
10044                p->subs[SUB_THREEWAY].owner;
10045             struct dahdi_pvt *pbridge = NULL;
10046             /* set up the private struct of the bridged one, if any */
10047             if (nbridge && ast_bridged_channel(nbridge))
10048                pbridge = ast_bridged_channel(nbridge)->tech_pvt;
10049             if (nbridge && pbridge &&
10050                (nbridge->tech == &dahdi_tech) &&
10051                (ast_bridged_channel(nbridge)->tech == &dahdi_tech) &&
10052                ISTRUNK(pbridge)) {
10053                int func = DAHDI_FLASH;
10054                /* Clear out the dial buffer */
10055                p->dop.dialstr[0] = '\0';
10056                /* flash hookswitch */
10057                if ((ioctl(pbridge->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
10058                   ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
10059                      nbridge->name, strerror(errno));
10060                }
10061                swap_subs(p, SUB_REAL, SUB_THREEWAY);
10062                unalloc_sub(p, SUB_THREEWAY);
10063                p->owner = p->subs[SUB_REAL].owner;
10064                if (ast_bridged_channel(p->subs[SUB_REAL].owner))
10065                   ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
10066                ast_hangup(chan);
10067                goto quit;
10068             } else {
10069                tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10070                dahdi_wait_event(p->subs[idx].dfd);
10071                tone_zone_play_tone(p->subs[idx].dfd, -1);
10072                swap_subs(p, SUB_REAL, SUB_THREEWAY);
10073                unalloc_sub(p, SUB_THREEWAY);
10074                p->owner = p->subs[SUB_REAL].owner;
10075                ast_hangup(chan);
10076                goto quit;
10077             }
10078          } else if (!ast_canmatch_extension(chan, chan->context, exten, 1,
10079             S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))
10080             && ((exten[0] != '*') || (strlen(exten) > 2))) {
10081             ast_debug(1, "Can't match %s from '%s' in context %s\n", exten,
10082                S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, "<Unknown Caller>"),
10083                chan->context);
10084             break;
10085          }
10086          if (!timeout)
10087             timeout = gendigittimeout;
10088          if (len && !ast_ignore_pattern(chan->context, exten))
10089             tone_zone_play_tone(p->subs[idx].dfd, -1);
10090       }
10091       break;
10092    case SIG_FXSLS:
10093    case SIG_FXSGS:
10094    case SIG_FXSKS:
10095       /* check for SMDI messages */
10096       if (p->use_smdi && p->smdi_iface) {
10097          smdi_msg = ast_smdi_md_message_wait(p->smdi_iface, SMDI_MD_WAIT_TIMEOUT);
10098 
10099          if (smdi_msg != NULL) {
10100             ast_copy_string(chan->exten, smdi_msg->fwd_st, sizeof(chan->exten));
10101 
10102             if (smdi_msg->type == 'B')
10103                pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "b");
10104             else if (smdi_msg->type == 'N')
10105                pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "u");
10106 
10107             ast_debug(1, "Received SMDI message on %s\n", chan->name);
10108          } else {
10109             ast_log(LOG_WARNING, "SMDI enabled but no SMDI message present\n");
10110          }
10111       }
10112 
10113       if (p->use_callerid && (p->cid_signalling == CID_SIG_SMDI && smdi_msg)) {
10114          number = smdi_msg->calling_st;
10115 
10116       /* If we want caller id, we're in a prering state due to a polarity reversal
10117        * and we're set to use a polarity reversal to trigger the start of caller id,
10118        * grab the caller id and wait for ringing to start... */
10119       } else if (p->use_callerid && (chan->_state == AST_STATE_PRERING &&
10120                    (p->cid_start == CID_START_POLARITY || p->cid_start == CID_START_POLARITY_IN || p->cid_start == CID_START_DTMF_NOALERT))) {
10121          /* If set to use DTMF CID signalling, listen for DTMF */
10122          if (p->cid_signalling == CID_SIG_DTMF) {
10123             int k = 0;
10124             cs = NULL;
10125             ast_debug(1, "Receiving DTMF cid on channel %s\n", chan->name);
10126             dahdi_setlinear(p->subs[idx].dfd, 0);
10127             /*
10128              * We are the only party interested in the Rx stream since
10129              * we have not answered yet.  We don't need or even want DTMF
10130              * emulation.  The DTMF digits can come so fast that emulation
10131              * can drop some of them.
10132              */
10133             ast_set_flag(chan, AST_FLAG_END_DTMF_ONLY);
10134             res = 4000;/* This is a typical OFF time between rings. */
10135             for (;;) {
10136                struct ast_frame *f;
10137                res = ast_waitfor(chan, res);
10138                if (res <= 0) {
10139                   /*
10140                    * We do not need to restore the dahdi_setlinear()
10141                    * or AST_FLAG_END_DTMF_ONLY flag settings since we
10142                    * are hanging up the channel.
10143                    */
10144                   ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
10145                      "Exiting simple switch\n");
10146                   ast_hangup(chan);
10147                   goto quit;
10148                }
10149                f = ast_read(chan);
10150                if (!f)
10151                   break;
10152                if (f->frametype == AST_FRAME_DTMF) {
10153                   if (k < ARRAY_LEN(dtmfbuf) - 1) {
10154                      dtmfbuf[k++] = f->subclass.integer;
10155                   }
10156                   ast_debug(1, "CID got digit '%c'\n", f->subclass.integer);
10157                   res = 4000;/* This is a typical OFF time between rings. */
10158                }
10159                ast_frfree(f);
10160                if (chan->_state == AST_STATE_RING ||
10161                   chan->_state == AST_STATE_RINGING)
10162                   break; /* Got ring */
10163             }
10164             ast_clear_flag(chan, AST_FLAG_END_DTMF_ONLY);
10165             dtmfbuf[k] = '\0';
10166             dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10167             /* Got cid and ring. */
10168             ast_debug(1, "CID got string '%s'\n", dtmfbuf);
10169             callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
10170             ast_debug(1, "CID is '%s', flags %d\n", dtmfcid, flags);
10171             /* If first byte is NULL, we have no cid */
10172             if (!ast_strlen_zero(dtmfcid))
10173                number = dtmfcid;
10174             else
10175                number = NULL;
10176          /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */
10177          } else if ((p->cid_signalling == CID_SIG_V23) || (p->cid_signalling == CID_SIG_V23_JP)) {
10178             cs = callerid_new(p->cid_signalling);
10179             if (cs) {
10180                samples = 0;
10181 #if 1
10182                bump_gains(p);
10183 #endif
10184                /* Take out of linear mode for Caller*ID processing */
10185                dahdi_setlinear(p->subs[idx].dfd, 0);
10186 
10187                /* First we wait and listen for the Caller*ID */
10188                for (;;) {
10189                   i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10190                   if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10191                      ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10192                      callerid_free(cs);
10193                      ast_hangup(chan);
10194                      goto quit;
10195                   }
10196                   if (i & DAHDI_IOMUX_SIGEVENT) {
10197                      res = dahdi_get_event(p->subs[idx].dfd);
10198                      ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10199                      if (res == DAHDI_EVENT_NOALARM) {
10200                         p->inalarm = 0;
10201                      }
10202 
10203                      if (p->cid_signalling == CID_SIG_V23_JP) {
10204                         if (res == DAHDI_EVENT_RINGBEGIN) {
10205                            res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
10206                            usleep(1);
10207                         }
10208                      } else {
10209                         res = 0;
10210                         break;
10211                      }
10212                   } else if (i & DAHDI_IOMUX_READ) {
10213                      res = read(p->subs[idx].dfd, buf, sizeof(buf));
10214                      if (res < 0) {
10215                         if (errno != ELAST) {
10216                            ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10217                            callerid_free(cs);
10218                            ast_hangup(chan);
10219                            goto quit;
10220                         }
10221                         break;
10222                      }
10223                      samples += res;
10224 
10225                      if (p->cid_signalling == CID_SIG_V23_JP) {
10226                         res = callerid_feed_jp(cs, buf, res, AST_LAW(p));
10227                      } else {
10228                         res = callerid_feed(cs, buf, res, AST_LAW(p));
10229                      }
10230                      if (res < 0) {
10231                         /*
10232                          * The previous diagnostic message output likely
10233                          * explains why it failed.
10234                          */
10235                         ast_log(LOG_WARNING,
10236                            "Failed to decode CallerID on channel '%s'\n",
10237                            chan->name);
10238                         break;
10239                      } else if (res)
10240                         break;
10241                      else if (samples > (8000 * 10))
10242                         break;
10243                   }
10244                }
10245                if (res == 1) {
10246                   callerid_get(cs, &name, &number, &flags);
10247                   ast_log(LOG_NOTICE, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
10248                }
10249 
10250                if (p->cid_signalling == CID_SIG_V23_JP) {
10251                   res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
10252                   usleep(1);
10253                }
10254 
10255                /* Finished with Caller*ID, now wait for a ring to make sure there really is a call coming */
10256                res = 4000;/* This is a typical OFF time between rings. */
10257                for (;;) {
10258                   struct ast_frame *f;
10259                   res = ast_waitfor(chan, res);
10260                   if (res <= 0) {
10261                      ast_log(LOG_WARNING, "CID timed out waiting for ring. "
10262                         "Exiting simple switch\n");
10263                      ast_hangup(chan);
10264                      goto quit;
10265                   }
10266                   if (!(f = ast_read(chan))) {
10267                      ast_log(LOG_WARNING, "Hangup received waiting for ring. Exiting simple switch\n");
10268                      ast_hangup(chan);
10269                      goto quit;
10270                   }
10271                   ast_frfree(f);
10272                   if (chan->_state == AST_STATE_RING ||
10273                      chan->_state == AST_STATE_RINGING)
10274                      break; /* Got ring */
10275                }
10276 
10277                /* We must have a ring by now, so, if configured, lets try to listen for
10278                 * distinctive ringing */
10279                if (p->usedistinctiveringdetection) {
10280                   len = 0;
10281                   distMatches = 0;
10282                   /* Clear the current ring data array so we don't have old data in it. */
10283                   for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
10284                      curRingData[receivedRingT] = 0;
10285                   receivedRingT = 0;
10286                   counter = 0;
10287                   counter1 = 0;
10288                   /* Check to see if context is what it should be, if not set to be. */
10289                   if (strcmp(p->context,p->defcontext) != 0) {
10290                      ast_copy_string(p->context, p->defcontext, sizeof(p->context));
10291                      ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
10292                   }
10293 
10294                   for (;;) {
10295                      i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10296                      if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10297                         ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10298                         callerid_free(cs);
10299                         ast_hangup(chan);
10300                         goto quit;
10301                      }
10302                      if (i & DAHDI_IOMUX_SIGEVENT) {
10303                         res = dahdi_get_event(p->subs[idx].dfd);
10304                         ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10305                         if (res == DAHDI_EVENT_NOALARM) {
10306                            p->inalarm = 0;
10307                         }
10308                         res = 0;
10309                         /* Let us detect distinctive ring */
10310 
10311                         curRingData[receivedRingT] = p->ringt;
10312 
10313                         if (p->ringt < p->ringt_base/2)
10314                            break;
10315                         /* Increment the ringT counter so we can match it against
10316                            values in chan_dahdi.conf for distinctive ring */
10317                         if (++receivedRingT == ARRAY_LEN(curRingData))
10318                            break;
10319                      } else if (i & DAHDI_IOMUX_READ) {
10320                         res = read(p->subs[idx].dfd, buf, sizeof(buf));
10321                         if (res < 0) {
10322                            if (errno != ELAST) {
10323                               ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10324                               callerid_free(cs);
10325                               ast_hangup(chan);
10326                               goto quit;
10327                            }
10328                            break;
10329                         }
10330                         if (p->ringt > 0) {
10331                            if (!(--p->ringt)) {
10332                               res = -1;
10333                               break;
10334                            }
10335                         }
10336                      }
10337                   }
10338                      /* this only shows up if you have n of the dring patterns filled in */
10339                   ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
10340                   for (counter = 0; counter < 3; counter++) {
10341                      /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this
10342                      channel */
10343                      distMatches = 0;
10344                      for (counter1 = 0; counter1 < 3; counter1++) {
10345                         ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
10346                         if (p->drings.ringnum[counter].ring[counter1] == -1) {
10347                            ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
10348                            curRingData[counter1]);
10349                            distMatches++;
10350                         } else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
10351                               curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
10352                            ast_verb(3, "Ring pattern matched in range: %d to %d\n",
10353                            (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
10354                            (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
10355                            distMatches++;
10356                         }
10357                      }
10358 
10359                      if (distMatches == 3) {
10360                         /* The ring matches, set the context to whatever is for distinctive ring.. */
10361                         ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context));
10362                         ast_copy_string(chan->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(chan->context));
10363                         ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
10364                         break;
10365                      }
10366                   }
10367                }
10368                /* Restore linear mode (if appropriate) for Caller*ID processing */
10369                dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10370 #if 1
10371                restore_gains(p);
10372 #endif
10373             } else
10374                ast_log(LOG_WARNING, "Unable to get caller ID space\n");
10375          } else {
10376             ast_log(LOG_WARNING, "Channel %s in prering "
10377                "state, but I have nothing to do. "
10378                "Terminating simple switch, should be "
10379                "restarted by the actual ring.\n",
10380                chan->name);
10381             ast_hangup(chan);
10382             goto quit;
10383          }
10384       } else if (p->use_callerid && p->cid_start == CID_START_RING) {
10385          if (p->cid_signalling == CID_SIG_DTMF) {
10386             int k = 0;
10387             cs = NULL;
10388             dahdi_setlinear(p->subs[idx].dfd, 0);
10389             res = 2000;
10390             for (;;) {
10391                struct ast_frame *f;
10392                res = ast_waitfor(chan, res);
10393                if (res <= 0) {
10394                   ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
10395                      "Exiting simple switch\n");
10396                   ast_hangup(chan);
10397                   return NULL;
10398                }
10399                f = ast_read(chan);
10400                if (f->frametype == AST_FRAME_DTMF) {
10401                   dtmfbuf[k++] = f->subclass.integer;
10402                   ast_log(LOG_DEBUG, "CID got digit '%c'\n", f->subclass.integer);
10403                   res = 2000;
10404                }
10405                ast_frfree(f);
10406 
10407                if (p->ringt_base == p->ringt)
10408                   break;
10409             }
10410             dtmfbuf[k] = '\0';
10411             dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10412             /* Got cid and ring. */
10413             callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
10414             ast_log(LOG_DEBUG, "CID is '%s', flags %d\n",
10415                dtmfcid, flags);
10416             /* If first byte is NULL, we have no cid */
10417             if (!ast_strlen_zero(dtmfcid))
10418                number = dtmfcid;
10419             else
10420                number = NULL;
10421             /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */
10422          } else {
10423             /* FSK Bell202 callerID */
10424             cs = callerid_new(p->cid_signalling);
10425             if (cs) {
10426 #if 1
10427                bump_gains(p);
10428 #endif
10429                samples = 0;
10430                len = 0;
10431                distMatches = 0;
10432                /* Clear the current ring data array so we don't have old data in it. */
10433                for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
10434                   curRingData[receivedRingT] = 0;
10435                receivedRingT = 0;
10436                counter = 0;
10437                counter1 = 0;
10438                /* Check to see if context is what it should be, if not set to be. */
10439                if (strcmp(p->context,p->defcontext) != 0) {
10440                   ast_copy_string(p->context, p->defcontext, sizeof(p->context));
10441                   ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
10442                }
10443 
10444                /* Take out of linear mode for Caller*ID processing */
10445                dahdi_setlinear(p->subs[idx].dfd, 0);
10446                for (;;) {
10447                   i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10448                   if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10449                      ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10450                      callerid_free(cs);
10451                      ast_hangup(chan);
10452                      goto quit;
10453                   }
10454                   if (i & DAHDI_IOMUX_SIGEVENT) {
10455                      res = dahdi_get_event(p->subs[idx].dfd);
10456                      ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10457                      if (res == DAHDI_EVENT_NOALARM) {
10458                         p->inalarm = 0;
10459                      }
10460                      /* If we get a PR event, they hung up while processing calerid */
10461                      if ( res == DAHDI_EVENT_POLARITY && p->hanguponpolarityswitch && p->polarity == POLARITY_REV) {
10462                         ast_log(LOG_DEBUG, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p->channel);
10463                         p->polarity = POLARITY_IDLE;
10464                         callerid_free(cs);
10465                         ast_hangup(chan);
10466                         goto quit;
10467                      }
10468                      res = 0;
10469                      /* Let us detect callerid when the telco uses distinctive ring */
10470 
10471                      curRingData[receivedRingT] = p->ringt;
10472 
10473                      if (p->ringt < p->ringt_base/2)
10474                         break;
10475                      /* Increment the ringT counter so we can match it against
10476                         values in chan_dahdi.conf for distinctive ring */
10477                      if (++receivedRingT == ARRAY_LEN(curRingData))
10478                         break;
10479                   } else if (i & DAHDI_IOMUX_READ) {
10480                      res = read(p->subs[idx].dfd, buf, sizeof(buf));
10481                      if (res < 0) {
10482                         if (errno != ELAST) {
10483                            ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10484                            callerid_free(cs);
10485                            ast_hangup(chan);
10486                            goto quit;
10487                         }
10488                         break;
10489                      }
10490                      if (p->ringt > 0) {
10491                         if (!(--p->ringt)) {
10492                            res = -1;
10493                            break;
10494                         }
10495                      }
10496                      samples += res;
10497                      res = callerid_feed(cs, buf, res, AST_LAW(p));
10498                      if (res < 0) {
10499                         /*
10500                          * The previous diagnostic message output likely
10501                          * explains why it failed.
10502                          */
10503                         ast_log(LOG_WARNING,
10504                            "Failed to decode CallerID on channel '%s'\n",
10505                            chan->name);
10506                         break;
10507                      } else if (res)
10508                         break;
10509                      else if (samples > (8000 * 10))
10510                         break;
10511                   }
10512                }
10513                if (res == 1) {
10514                   callerid_get(cs, &name, &number, &flags);
10515                   ast_debug(1, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
10516                }
10517                if (distinctiveringaftercid == 1) {
10518                   /* Clear the current ring data array so we don't have old data in it. */
10519                   for (receivedRingT = 0; receivedRingT < 3; receivedRingT++) {
10520                      curRingData[receivedRingT] = 0;
10521                   }
10522                   receivedRingT = 0;
10523                   ast_verb(3, "Detecting post-CID distinctive ring\n");
10524                   for (;;) {
10525                      i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10526                      if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10527                         ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10528                         callerid_free(cs);
10529                         ast_hangup(chan);
10530                         goto quit;
10531                      }
10532                      if (i & DAHDI_IOMUX_SIGEVENT) {
10533                         res = dahdi_get_event(p->subs[idx].dfd);
10534                         ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10535                         if (res == DAHDI_EVENT_NOALARM) {
10536                            p->inalarm = 0;
10537                         }
10538                         res = 0;
10539                         /* Let us detect callerid when the telco uses distinctive ring */
10540 
10541                         curRingData[receivedRingT] = p->ringt;
10542 
10543                         if (p->ringt < p->ringt_base/2)
10544                            break;
10545                         /* Increment the ringT counter so we can match it against
10546                            values in chan_dahdi.conf for distinctive ring */
10547                         if (++receivedRingT == ARRAY_LEN(curRingData))
10548                            break;
10549                      } else if (i & DAHDI_IOMUX_READ) {
10550                         res = read(p->subs[idx].dfd, buf, sizeof(buf));
10551                         if (res < 0) {
10552                            if (errno != ELAST) {
10553                               ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10554                               callerid_free(cs);
10555                               ast_hangup(chan);
10556                               goto quit;
10557                            }
10558                            break;
10559                         }
10560                         if (p->ringt > 0) {
10561                            if (!(--p->ringt)) {
10562                               res = -1;
10563                               break;
10564                            }
10565                         }
10566                      }
10567                   }
10568                }
10569                if (p->usedistinctiveringdetection) {
10570                   /* this only shows up if you have n of the dring patterns filled in */
10571                   ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
10572 
10573                   for (counter = 0; counter < 3; counter++) {
10574                      /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this
10575                      channel */
10576                      /* this only shows up if you have n of the dring patterns filled in */
10577                      ast_verb(3, "Checking %d,%d,%d\n",
10578                            p->drings.ringnum[counter].ring[0],
10579                            p->drings.ringnum[counter].ring[1],
10580                            p->drings.ringnum[counter].ring[2]);
10581                      distMatches = 0;
10582                      for (counter1 = 0; counter1 < 3; counter1++) {
10583                         ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
10584                         if (p->drings.ringnum[counter].ring[counter1] == -1) {
10585                            ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
10586                            curRingData[counter1]);
10587                            distMatches++;
10588                         }
10589                         else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
10590                            curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
10591                            ast_verb(3, "Ring pattern matched in range: %d to %d\n",
10592                            (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
10593                            (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
10594                            distMatches++;
10595                         }
10596                      }
10597                      if (distMatches == 3) {
10598                         /* The ring matches, set the context to whatever is for distinctive ring.. */
10599                         ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context));
10600                         ast_copy_string(chan->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(chan->context));
10601                         ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
10602                         break;
10603                      }
10604                   }
10605                }
10606                /* Restore linear mode (if appropriate) for Caller*ID processing */
10607                dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10608 #if 1
10609                restore_gains(p);
10610 #endif
10611                if (res < 0) {
10612                   ast_log(LOG_WARNING, "CallerID returned with error on channel '%s'\n", chan->name);
10613                }
10614             } else
10615                ast_log(LOG_WARNING, "Unable to get caller ID space\n");
10616          }
10617       } else
10618          cs = NULL;
10619 
10620       if (number)
10621          ast_shrink_phone_number(number);
10622       ast_set_callerid(chan, number, name, number);
10623 
10624       if (smdi_msg)
10625          ASTOBJ_UNREF(smdi_msg, ast_smdi_md_message_destroy);
10626 
10627       if (cs)
10628          callerid_free(cs);
10629 
10630       my_handle_notify_message(chan, p, flags, -1);
10631 
10632       ast_setstate(chan, AST_STATE_RING);
10633       chan->rings = 1;
10634       p->ringt = p->ringt_base;
10635       res = ast_pbx_run(chan);
10636       if (res) {
10637          ast_hangup(chan);
10638          ast_log(LOG_WARNING, "PBX exited non-zero\n");
10639       }
10640       goto quit;
10641    default:
10642       ast_log(LOG_WARNING, "Don't know how to handle simple switch with signalling %s on channel %d\n", sig2str(p->sig), p->channel);
10643       res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10644       if (res < 0)
10645             ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
10646    }
10647    res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10648    if (res < 0)
10649          ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
10650    ast_hangup(chan);
10651 quit:
10652    ast_mutex_lock(&ss_thread_lock);
10653    ss_thread_count--;
10654    ast_cond_signal(&ss_thread_complete);
10655    ast_mutex_unlock(&ss_thread_lock);
10656    return NULL;
10657 }
10658 
10659 struct mwi_thread_data {
10660    struct dahdi_pvt *pvt;
10661    unsigned char buf[READ_SIZE];
10662    size_t len;
10663 };
10664 
10665 static int calc_energy(const unsigned char *buf, int len, format_t law)
10666 {
10667    int x;
10668    int sum = 0;
10669 
10670    if (!len)
10671       return 0;
10672 
10673    for (x = 0; x < len; x++)
10674       sum += abs(law == AST_FORMAT_ULAW ? AST_MULAW(buf[x]) : AST_ALAW(buf[x]));
10675 
10676    return sum / len;
10677 }
10678 
10679 static void *mwi_thread(void *data)
10680 {
10681    struct mwi_thread_data *mtd = data;
10682    struct callerid_state *cs;
10683    pthread_t threadid;
10684    int samples = 0;
10685    char *name, *number;
10686    int flags;
10687    int i, res;
10688    unsigned int spill_done = 0;
10689    int spill_result = -1;
10690 
10691    if (!(cs = callerid_new(mtd->pvt->cid_signalling))) {
10692       mtd->pvt->mwimonitoractive = 0;
10693 
10694       return NULL;
10695    }
10696 
10697    callerid_feed(cs, mtd->buf, mtd->len, AST_LAW(mtd->pvt));
10698 
10699    bump_gains(mtd->pvt);
10700 
10701    for (;;) {
10702       i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10703       if ((res = ioctl(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_IOMUX, &i))) {
10704          ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10705          goto quit;
10706       }
10707 
10708       if (i & DAHDI_IOMUX_SIGEVENT) {
10709          struct ast_channel *chan;
10710 
10711          /* If we get an event, screen out events that we do not act on.
10712           * Otherwise, cancel and go to the simple switch to let it deal with it.
10713           */
10714          res = dahdi_get_event(mtd->pvt->subs[SUB_REAL].dfd);
10715 
10716          switch (res) {
10717          case DAHDI_EVENT_NEONMWI_ACTIVE:
10718          case DAHDI_EVENT_NEONMWI_INACTIVE:
10719          case DAHDI_EVENT_NONE:
10720          case DAHDI_EVENT_BITSCHANGED:
10721             break;
10722          case DAHDI_EVENT_NOALARM:
10723             if (analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) {
10724                struct analog_pvt *analog_p = mtd->pvt->sig_pvt;
10725 
10726                analog_p->inalarm = 0;
10727             }
10728             mtd->pvt->inalarm = 0;
10729             handle_clear_alarms(mtd->pvt);
10730             break;
10731          case DAHDI_EVENT_ALARM:
10732             if (analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) {
10733                struct analog_pvt *analog_p = mtd->pvt->sig_pvt;
10734 
10735                analog_p->inalarm = 1;
10736             }
10737             mtd->pvt->inalarm = 1;
10738             res = get_alarms(mtd->pvt);
10739             handle_alarms(mtd->pvt, res);
10740             break; /* What to do on channel alarm ???? -- fall thru intentionally?? */
10741          default:
10742             ast_log(LOG_NOTICE, "Got event %d (%s)...  Passing along to analog_ss_thread\n", res, event2str(res));
10743             callerid_free(cs);
10744 
10745             restore_gains(mtd->pvt);
10746             mtd->pvt->ringt = mtd->pvt->ringt_base;
10747 
10748             if ((chan = dahdi_new(mtd->pvt, AST_STATE_RING, 0, SUB_REAL, 0, NULL))) {
10749                int result;
10750                if (analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) {
10751                   result = analog_ss_thread_start(mtd->pvt->sig_pvt, chan);
10752                } else {
10753                   result = ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan);
10754                }
10755                if (result) {
10756                   ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", mtd->pvt->channel);
10757                   res = tone_zone_play_tone(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
10758                   if (res < 0)
10759                      ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", mtd->pvt->channel);
10760                   ast_hangup(chan);
10761                   goto quit;
10762                }
10763                goto quit_no_clean;
10764 
10765             } else {
10766                ast_log(LOG_WARNING, "Could not create channel to handle call\n");
10767             }
10768          }
10769       } else if (i & DAHDI_IOMUX_READ) {
10770          if ((res = read(mtd->pvt->subs[SUB_REAL].dfd, mtd->buf, sizeof(mtd->buf))) < 0) {
10771             if (errno != ELAST) {
10772                ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10773                goto quit;
10774             }
10775             break;
10776          }
10777          samples += res;
10778          if (!spill_done) {
10779             if ((spill_result = callerid_feed(cs, mtd->buf, res, AST_LAW(mtd->pvt))) < 0) {
10780                /*
10781                 * The previous diagnostic message output likely
10782                 * explains why it failed.
10783                 */
10784                ast_log(LOG_WARNING, "Failed to decode CallerID\n");
10785                break;
10786             } else if (spill_result) {
10787                spill_done = 1;
10788             }
10789          } else {
10790             /* keep reading data until the energy level drops below the threshold
10791                so we don't get another 'trigger' on the remaining carrier signal
10792             */
10793             if (calc_energy(mtd->buf, res, AST_LAW(mtd->pvt)) <= mwilevel)
10794                break;
10795          }
10796          if (samples > (8000 * 4)) /*Termination case - time to give up*/
10797             break;
10798       }
10799    }
10800 
10801    if (spill_result == 1) {
10802       callerid_get(cs, &name, &number, &flags);
10803       if (flags & CID_MSGWAITING) {
10804          ast_log(LOG_NOTICE, "mwi: Have Messages on channel %d\n", mtd->pvt->channel);
10805          notify_message(mtd->pvt->mailbox, 1);
10806       } else if (flags & CID_NOMSGWAITING) {
10807          ast_log(LOG_NOTICE, "mwi: No Messages on channel %d\n", mtd->pvt->channel);
10808          notify_message(mtd->pvt->mailbox, 0);
10809       } else {
10810          ast_log(LOG_NOTICE, "mwi: Status unknown on channel %d\n", mtd->pvt->channel);
10811       }
10812    }
10813 
10814 
10815 quit:
10816    callerid_free(cs);
10817 
10818    restore_gains(mtd->pvt);
10819 
10820 quit_no_clean:
10821    mtd->pvt->mwimonitoractive = 0;
10822 
10823    ast_free(mtd);
10824 
10825    return NULL;
10826 }
10827 
10828 /*
10829 * The following three functions (mwi_send_init, mwi_send_process_buffer,
10830 * mwi_send_process_event) work with the do_monitor thread to generate mwi spills
10831 * that are sent out via FXS port on voicemail state change.  The execution of
10832 * the mwi send is state driven and can either generate a ring pulse prior to
10833 * sending the fsk spill or simply send an fsk spill.
10834 */
10835 static int mwi_send_init(struct dahdi_pvt * pvt)
10836 {
10837    int x, res;
10838 
10839 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
10840    /* Determine how this spill is to be sent */
10841    if (pvt->mwisend_rpas) {
10842       pvt->mwisend_data.mwisend_current = MWI_SEND_SA;
10843       pvt->mwisendactive = 1;
10844    } else if (pvt->mwisend_fsk) {
10845       pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
10846       pvt->mwisendactive = 1;
10847    } else {
10848       pvt->mwisendactive = 0;
10849       return 0;
10850    }
10851 #else
10852    if (mwisend_rpas) {
10853       pvt->mwisend_data.mwisend_current = MWI_SEND_SA;
10854    } else {
10855       pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
10856    }
10857    pvt->mwisendactive = 1;
10858 #endif
10859 
10860    if (pvt->cidspill) {
10861       ast_log(LOG_WARNING, "cidspill already exists when trying to send FSK MWI\n");
10862       ast_free(pvt->cidspill);
10863       pvt->cidspill = NULL;
10864       pvt->cidpos = 0;
10865       pvt->cidlen = 0;
10866    }
10867    pvt->cidspill = ast_calloc(1, MAX_CALLERID_SIZE);
10868    if (!pvt->cidspill) {
10869       pvt->mwisendactive = 0;
10870       return -1;
10871    }
10872    x = DAHDI_FLUSH_BOTH;
10873    res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
10874    x = 3000;
10875    ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_ONHOOKTRANSFER, &x);
10876 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
10877    if (pvt->mwisend_fsk) {
10878 #endif
10879       pvt->cidlen = ast_callerid_vmwi_generate(pvt->cidspill, has_voicemail(pvt), CID_MWI_TYPE_MDMF_FULL,
10880                       AST_LAW(pvt), pvt->cid_name, pvt->cid_num, 0);
10881       pvt->cidpos = 0;
10882 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
10883    }
10884 #endif
10885    return 0;
10886 }
10887 
10888 static int mwi_send_process_buffer(struct dahdi_pvt * pvt, int num_read)
10889 {
10890    struct timeval    now;
10891    int         res;
10892 
10893    /* sanity check to catch if this had been interrupted previously
10894    *  i.e. state says there is more to do but there is no spill allocated
10895    */
10896    if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current && !pvt->cidspill) {
10897       pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
10898    } else if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current) {
10899       /* Normal processing -- Perform mwi send action */
10900       switch ( pvt->mwisend_data.mwisend_current) {
10901       case MWI_SEND_SA:
10902          /* Send the Ring Pulse Signal Alert */
10903          res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &AS_RP_cadence);
10904          if (res) {
10905             ast_log(LOG_WARNING, "Unable to set RP-AS ring cadence: %s\n", strerror(errno));
10906             goto quit;
10907          }
10908          res = dahdi_set_hook(pvt->subs[SUB_REAL].dfd, DAHDI_RING);
10909          pvt->mwisend_data.mwisend_current = MWI_SEND_SA_WAIT;
10910          break;
10911       case MWI_SEND_SA_WAIT:  /* do nothing until I get RINGEROFF event */
10912          break;
10913       case MWI_SEND_PAUSE:  /* Wait between alert and spill - min of 500 mS*/
10914 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
10915          if (pvt->mwisend_fsk) {
10916 #endif
10917             gettimeofday(&now, NULL);
10918             if ((int)(now.tv_sec - pvt->mwisend_data.pause.tv_sec) * 1000000 + (int)now.tv_usec - (int)pvt->mwisend_data.pause.tv_usec > 500000) {
10919                pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
10920             }
10921 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
10922          } else { /* support for mwisendtype=nofsk */
10923             pvt->mwisend_data.mwisend_current = MWI_SEND_CLEANUP;
10924          }
10925 #endif
10926          break;
10927       case MWI_SEND_SPILL:
10928          /* We read some number of bytes.  Write an equal amount of data */
10929          if(0 < num_read) {
10930             if (num_read > pvt->cidlen - pvt->cidpos)
10931                num_read = pvt->cidlen - pvt->cidpos;
10932             res = write(pvt->subs[SUB_REAL].dfd, pvt->cidspill + pvt->cidpos, num_read);
10933             if (res > 0) {
10934                pvt->cidpos += res;
10935                if (pvt->cidpos >= pvt->cidlen) {
10936                   pvt->mwisend_data.mwisend_current = MWI_SEND_CLEANUP;
10937                }
10938             } else {
10939                ast_log(LOG_WARNING, "MWI FSK Send Write failed: %s\n", strerror(errno));
10940                goto quit;
10941             }
10942          }
10943          break;
10944       case MWI_SEND_CLEANUP:
10945          /* For now, do nothing */
10946          pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
10947          break;
10948       default:
10949          /* Should not get here, punt*/
10950          goto quit;
10951       }
10952    }
10953 
10954    if (MWI_SEND_DONE == pvt->mwisend_data.mwisend_current) {
10955       if (pvt->cidspill) {
10956          ast_free(pvt->cidspill);
10957          pvt->cidspill = NULL;
10958          pvt->cidpos = 0;
10959          pvt->cidlen = 0;
10960       }
10961       pvt->mwisendactive = 0;
10962    }
10963    return 0;
10964 quit:
10965    if (pvt->cidspill) {
10966       ast_free(pvt->cidspill);
10967       pvt->cidspill = NULL;
10968       pvt->cidpos = 0;
10969       pvt->cidlen = 0;
10970    }
10971    pvt->mwisendactive = 0;
10972    return -1;
10973 }
10974 
10975 static int mwi_send_process_event(struct dahdi_pvt * pvt, int event)
10976 {
10977    int handled = 0;
10978 
10979    if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current) {
10980       switch (event) {
10981       case DAHDI_EVENT_RINGEROFF:
10982          if(pvt->mwisend_data.mwisend_current == MWI_SEND_SA_WAIT) {
10983             handled = 1;
10984 
10985             if (dahdi_set_hook(pvt->subs[SUB_REAL].dfd, DAHDI_RINGOFF) ) {
10986                ast_log(LOG_WARNING, "Unable to finish RP-AS: %s mwi send aborted\n", strerror(errno));
10987                ast_free(pvt->cidspill);
10988                pvt->cidspill = NULL;
10989                pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
10990                pvt->mwisendactive = 0;
10991             } else {
10992                pvt->mwisend_data.mwisend_current = MWI_SEND_PAUSE;
10993                gettimeofday(&pvt->mwisend_data.pause, NULL);
10994             }
10995          }
10996          break;
10997       /* Going off hook, I need to punt this spill */
10998       case DAHDI_EVENT_RINGOFFHOOK:
10999          if (pvt->cidspill) {
11000             ast_free(pvt->cidspill);
11001             pvt->cidspill = NULL;
11002             pvt->cidpos = 0;
11003             pvt->cidlen = 0;
11004          }
11005          pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11006          pvt->mwisendactive = 0;
11007          break;
11008       case DAHDI_EVENT_RINGERON:
11009       case DAHDI_EVENT_HOOKCOMPLETE:
11010          break;
11011       default:
11012          break;
11013       }
11014    }
11015    return handled;
11016 }
11017 
11018 /* destroy a DAHDI channel, identified by its number */
11019 static int dahdi_destroy_channel_bynum(int channel)
11020 {
11021    struct dahdi_pvt *cur;
11022 
11023    ast_mutex_lock(&iflock);
11024    for (cur = iflist; cur; cur = cur->next) {
11025       if (cur->channel == channel) {
11026          int x = DAHDI_FLASH;
11027 
11028          /* important to create an event for dahdi_wait_event to register so that all analog_ss_threads terminate */
11029          ioctl(cur->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
11030 
11031          destroy_channel(cur, 1);
11032          ast_mutex_unlock(&iflock);
11033          ast_module_unref(ast_module_info->self);
11034          return RESULT_SUCCESS;
11035       }
11036    }
11037    ast_mutex_unlock(&iflock);
11038    return RESULT_FAILURE;
11039 }
11040 
11041 static struct dahdi_pvt *handle_init_event(struct dahdi_pvt *i, int event)
11042 {
11043    int res;
11044    pthread_t threadid;
11045    struct ast_channel *chan;
11046 
11047    /* Handle an event on a given channel for the monitor thread. */
11048 
11049    switch (event) {
11050    case DAHDI_EVENT_NONE:
11051    case DAHDI_EVENT_BITSCHANGED:
11052       break;
11053    case DAHDI_EVENT_WINKFLASH:
11054    case DAHDI_EVENT_RINGOFFHOOK:
11055       if (i->inalarm) break;
11056       if (i->radio) break;
11057       /* Got a ring/answer.  What kind of channel are we? */
11058       switch (i->sig) {
11059       case SIG_FXOLS:
11060       case SIG_FXOGS:
11061       case SIG_FXOKS:
11062          res = dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
11063          if (res && (errno == EBUSY))
11064             break;
11065 
11066          /* Cancel VMWI spill */
11067          ast_free(i->cidspill);
11068          i->cidspill = NULL;
11069          restore_conference(i);
11070 
11071          if (i->immediate) {
11072             dahdi_enable_ec(i);
11073             /* The channel is immediately up.  Start right away */
11074             res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
11075             chan = dahdi_new(i, AST_STATE_RING, 1, SUB_REAL, 0, NULL);
11076             if (!chan) {
11077                ast_log(LOG_WARNING, "Unable to start PBX on channel %d\n", i->channel);
11078                res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11079                if (res < 0)
11080                   ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11081             }
11082          } else {
11083             /* Check for callerid, digits, etc */
11084             chan = dahdi_new(i, AST_STATE_RESERVED, 0, SUB_REAL, 0, NULL);
11085             if (chan) {
11086                if (has_voicemail(i))
11087                   res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
11088                else
11089                   res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
11090                if (res < 0)
11091                   ast_log(LOG_WARNING, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i->channel);
11092                if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
11093                   ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11094                   res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11095                   if (res < 0)
11096                      ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11097                   ast_hangup(chan);
11098                }
11099             } else
11100                ast_log(LOG_WARNING, "Unable to create channel\n");
11101          }
11102          break;
11103       case SIG_FXSLS:
11104       case SIG_FXSGS:
11105       case SIG_FXSKS:
11106             i->ringt = i->ringt_base;
11107             /* Fall through */
11108       case SIG_EMWINK:
11109       case SIG_FEATD:
11110       case SIG_FEATDMF:
11111       case SIG_FEATDMF_TA:
11112       case SIG_E911:
11113       case SIG_FGC_CAMA:
11114       case SIG_FGC_CAMAMF:
11115       case SIG_FEATB:
11116       case SIG_EM:
11117       case SIG_EM_E1:
11118       case SIG_SFWINK:
11119       case SIG_SF_FEATD:
11120       case SIG_SF_FEATDMF:
11121       case SIG_SF_FEATB:
11122       case SIG_SF:
11123          /* Check for callerid, digits, etc */
11124          if (i->cid_start == CID_START_POLARITY_IN) {
11125             chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL);
11126          } else {
11127             chan = dahdi_new(i, AST_STATE_RING, 0, SUB_REAL, 0, NULL);
11128          }
11129 
11130          if (!chan) {
11131             ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
11132          } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
11133             ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11134             res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11135             if (res < 0) {
11136                ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11137             }
11138             ast_hangup(chan);
11139          }
11140          break;
11141       default:
11142          ast_log(LOG_WARNING, "Don't know how to handle ring/answer with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
11143          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11144          if (res < 0)
11145             ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11146          return NULL;
11147       }
11148       break;
11149    case DAHDI_EVENT_NOALARM:
11150       switch (i->sig) {
11151 #if defined(HAVE_PRI)
11152       case SIG_PRI_LIB_HANDLE_CASES:
11153          sig_pri_chan_alarm_notify(i->sig_pvt, 1);
11154          break;
11155 #endif   /* defined(HAVE_PRI) */
11156 #if defined(HAVE_SS7)
11157       case SIG_SS7:
11158          sig_ss7_set_alarm(i->sig_pvt, 0);
11159          break;
11160 #endif   /* defined(HAVE_SS7) */
11161       default:
11162          i->inalarm = 0;
11163          break;
11164       }
11165       handle_clear_alarms(i);
11166       break;
11167    case DAHDI_EVENT_ALARM:
11168       switch (i->sig) {
11169 #if defined(HAVE_PRI)
11170       case SIG_PRI_LIB_HANDLE_CASES:
11171          sig_pri_chan_alarm_notify(i->sig_pvt, 0);
11172          break;
11173 #endif   /* defined(HAVE_PRI) */
11174 #if defined(HAVE_SS7)
11175       case SIG_SS7:
11176          sig_ss7_set_alarm(i->sig_pvt, 1);
11177          break;
11178 #endif   /* defined(HAVE_SS7) */
11179       default:
11180          i->inalarm = 1;
11181          break;
11182       }
11183       res = get_alarms(i);
11184       handle_alarms(i, res);
11185       /* fall thru intentionally */
11186    case DAHDI_EVENT_ONHOOK:
11187       if (i->radio)
11188          break;
11189       /* Back on hook.  Hang up. */
11190       switch (i->sig) {
11191       case SIG_FXOLS:
11192       case SIG_FXOGS:
11193       case SIG_FEATD:
11194       case SIG_FEATDMF:
11195       case SIG_FEATDMF_TA:
11196       case SIG_E911:
11197       case SIG_FGC_CAMA:
11198       case SIG_FGC_CAMAMF:
11199       case SIG_FEATB:
11200       case SIG_EM:
11201       case SIG_EM_E1:
11202       case SIG_EMWINK:
11203       case SIG_SF_FEATD:
11204       case SIG_SF_FEATDMF:
11205       case SIG_SF_FEATB:
11206       case SIG_SF:
11207       case SIG_SFWINK:
11208       case SIG_FXSLS:
11209       case SIG_FXSGS:
11210       case SIG_FXSKS:
11211       case SIG_FXOKS:
11212          dahdi_disable_ec(i);
11213          /* Diddle the battery for the zhone */
11214 #ifdef ZHONE_HACK
11215          dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
11216          usleep(1);
11217 #endif
11218          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
11219          dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
11220          break;
11221       case SIG_SS7:
11222       case SIG_PRI_LIB_HANDLE_CASES:
11223          dahdi_disable_ec(i);
11224          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
11225          break;
11226       default:
11227          ast_log(LOG_WARNING, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
11228          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
11229          return NULL;
11230       }
11231       break;
11232    case DAHDI_EVENT_POLARITY:
11233       switch (i->sig) {
11234       case SIG_FXSLS:
11235       case SIG_FXSKS:
11236       case SIG_FXSGS:
11237          /* We have already got a PR before the channel was
11238             created, but it wasn't handled. We need polarity
11239             to be REV for remote hangup detection to work.
11240             At least in Spain */
11241          if (i->hanguponpolarityswitch)
11242             i->polarity = POLARITY_REV;
11243          if (i->cid_start == CID_START_POLARITY || i->cid_start == CID_START_POLARITY_IN) {
11244             i->polarity = POLARITY_REV;
11245             ast_verb(2, "Starting post polarity "
11246                "CID detection on channel %d\n",
11247                i->channel);
11248             chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL);
11249             if (!chan) {
11250                ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
11251             } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
11252                ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11253             }
11254          }
11255          break;
11256       default:
11257          ast_log(LOG_WARNING, "handle_init_event detected "
11258             "polarity reversal on non-FXO (SIG_FXS) "
11259             "interface %d\n", i->channel);
11260       }
11261       break;
11262    case DAHDI_EVENT_REMOVED: /* destroy channel, will actually do so in do_monitor */
11263       ast_log(LOG_NOTICE,
11264             "Got DAHDI_EVENT_REMOVED. Destroying channel %d\n",
11265             i->channel);
11266       return i;
11267    case DAHDI_EVENT_NEONMWI_ACTIVE:
11268       if (i->mwimonitor_neon) {
11269          notify_message(i->mailbox, 1);
11270          ast_log(LOG_NOTICE, "NEON MWI set for channel %d, mailbox %s \n", i->channel, i->mailbox);
11271       }
11272       break;
11273    case DAHDI_EVENT_NEONMWI_INACTIVE:
11274       if (i->mwimonitor_neon) {
11275          notify_message(i->mailbox, 0);
11276          ast_log(LOG_NOTICE, "NEON MWI cleared for channel %d, mailbox %s\n", i->channel, i->mailbox);
11277       }
11278       break;
11279    }
11280    return NULL;
11281 }
11282 
11283 static void *do_monitor(void *data)
11284 {
11285    int count, res, res2, spoint, pollres=0;
11286    struct dahdi_pvt *i;
11287    struct dahdi_pvt *last = NULL;
11288    struct dahdi_pvt *doomed;
11289    time_t thispass = 0, lastpass = 0;
11290    int found;
11291    char buf[1024];
11292    struct pollfd *pfds=NULL;
11293    int lastalloc = -1;
11294    /* This thread monitors all the frame relay interfaces which are not yet in use
11295       (and thus do not have a separate thread) indefinitely */
11296    /* From here on out, we die whenever asked */
11297 #if 0
11298    if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) {
11299       ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n");
11300       return NULL;
11301    }
11302    ast_debug(1, "Monitor starting...\n");
11303 #endif
11304    pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
11305 
11306    for (;;) {
11307       /* Lock the interface list */
11308       ast_mutex_lock(&iflock);
11309       if (!pfds || (lastalloc != ifcount)) {
11310          if (pfds) {
11311             ast_free(pfds);
11312             pfds = NULL;
11313          }
11314          if (ifcount) {
11315             if (!(pfds = ast_calloc(1, ifcount * sizeof(*pfds)))) {
11316                ast_mutex_unlock(&iflock);
11317                return NULL;
11318             }
11319          }
11320          lastalloc = ifcount;
11321       }
11322       /* Build the stuff we're going to poll on, that is the socket of every
11323          dahdi_pvt that does not have an associated owner channel */
11324       count = 0;
11325       for (i = iflist; i; i = i->next) {
11326          ast_mutex_lock(&i->lock);
11327          if ((i->subs[SUB_REAL].dfd > -1) && i->sig && (!i->radio) && !(i->sig & SIG_MFCR2)) {
11328             if (analog_lib_handles(i->sig, i->radio, i->oprmode)) {
11329                struct analog_pvt *p = i->sig_pvt;
11330 
11331                if (!p)
11332                   ast_log(LOG_ERROR, "No sig_pvt?\n");
11333 
11334                if (!p->owner && !p->subs[SUB_REAL].owner) {
11335                   /* This needs to be watched, as it lacks an owner */
11336                   pfds[count].fd = i->subs[SUB_REAL].dfd;
11337                   pfds[count].events = POLLPRI;
11338                   pfds[count].revents = 0;
11339                   /* Message waiting or r2 channels also get watched for reading */
11340                   if (i->cidspill || i->mwisendactive || i->mwimonitor_fsk || 
11341                      (i->cid_start == CID_START_DTMF_NOALERT && (i->sig == SIG_FXSLS || i->sig == SIG_FXSGS || i->sig == SIG_FXSKS))) {
11342                      pfds[count].events |= POLLIN;
11343                   }
11344                   count++;
11345                }
11346             } else {
11347                if (!i->owner && !i->subs[SUB_REAL].owner && !i->mwimonitoractive ) {
11348                   /* This needs to be watched, as it lacks an owner */
11349                   pfds[count].fd = i->subs[SUB_REAL].dfd;
11350                   pfds[count].events = POLLPRI;
11351                   pfds[count].revents = 0;
11352                   /* If we are monitoring for VMWI or sending CID, we need to
11353                      read from the channel as well */
11354                   if (i->cidspill || i->mwisendactive || i->mwimonitor_fsk ||
11355                      (i->cid_start == CID_START_DTMF_NOALERT && (i->sig == SIG_FXSLS || i->sig == SIG_FXSGS || i->sig == SIG_FXSKS))) {
11356                      pfds[count].events |= POLLIN;
11357                   }
11358                   count++;
11359                }
11360             }
11361          }
11362          ast_mutex_unlock(&i->lock);
11363       }
11364       /* Okay, now that we know what to do, release the interface lock */
11365       ast_mutex_unlock(&iflock);
11366 
11367       pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
11368       pthread_testcancel();
11369       /* Wait at least a second for something to happen */
11370       res = poll(pfds, count, 1000);
11371       pthread_testcancel();
11372       pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
11373 
11374       /* Okay, poll has finished.  Let's see what happened.  */
11375       if (res < 0) {
11376          if ((errno != EAGAIN) && (errno != EINTR))
11377             ast_log(LOG_WARNING, "poll return %d: %s\n", res, strerror(errno));
11378          continue;
11379       }
11380       /* Alright, lock the interface list again, and let's look and see what has
11381          happened */
11382       ast_mutex_lock(&iflock);
11383       found = 0;
11384       spoint = 0;
11385       lastpass = thispass;
11386       thispass = time(NULL);
11387       doomed = NULL;
11388       for (i = iflist;; i = i->next) {
11389          if (doomed) {
11390             int res;
11391             res = dahdi_destroy_channel_bynum(doomed->channel);
11392             if (res != RESULT_SUCCESS) {
11393                ast_log(LOG_WARNING, "Couldn't find channel to destroy, hopefully another destroy operation just happened.\n");
11394             }
11395             doomed = NULL;
11396          }
11397          if (!i) {
11398             break;
11399          }
11400 
11401          if (thispass != lastpass) {
11402             if (!found && ((i == last) || ((i == iflist) && !last))) {
11403                last = i;
11404                if (last) {
11405                   struct analog_pvt *analog_p = last->sig_pvt;
11406                   /* Only allow MWI to be initiated on a quiescent fxs port */
11407                   if (analog_p
11408                      && !last->mwisendactive
11409                      && (last->sig & __DAHDI_SIG_FXO)
11410                      && !analog_p->fxsoffhookstate
11411                      && !last->owner
11412                      && !ast_strlen_zero(last->mailbox)
11413                      && (thispass - analog_p->onhooktime > 3)) {
11414                      res = has_voicemail(last);
11415                      if (analog_p->msgstate != res) {
11416                         /* Set driver resources for signalling VMWI */
11417                         res2 = ioctl(last->subs[SUB_REAL].dfd, DAHDI_VMWI, &res);
11418                         if (res2) {
11419                            /* TODO: This message will ALWAYS be generated on some cards; any way to restrict it to those cards where it is interesting? */
11420                            ast_debug(3, "Unable to control message waiting led on channel %d: %s\n", last->channel, strerror(errno));
11421                         }
11422                         /* If enabled for FSK spill then initiate it */
11423                         if (mwi_send_init(last)) {
11424                            ast_log(LOG_WARNING, "Unable to initiate mwi send sequence on channel %d\n", last->channel);
11425                         }
11426                         analog_p->msgstate = res;
11427                         found ++;
11428                      }
11429                   }
11430                   last = last->next;
11431                }
11432             }
11433          }
11434          if ((i->subs[SUB_REAL].dfd > -1) && i->sig) {
11435             if (i->radio && !i->owner)
11436             {
11437                res = dahdi_get_event(i->subs[SUB_REAL].dfd);
11438                if (res)
11439                {
11440                   ast_debug(1, "Monitor doohicky got event %s on radio channel %d\n", event2str(res), i->channel);
11441                   /* Don't hold iflock while handling init events */
11442                   ast_mutex_unlock(&iflock);
11443                   if (analog_lib_handles(i->sig, i->radio, i->oprmode))
11444                      doomed = (struct dahdi_pvt *) analog_handle_init_event(i->sig_pvt, dahdievent_to_analogevent(res));
11445                   else
11446                      doomed = handle_init_event(i, res);
11447                   ast_mutex_lock(&iflock);
11448                }
11449                continue;
11450             }
11451             pollres = ast_fdisset(pfds, i->subs[SUB_REAL].dfd, count, &spoint);
11452             if (pollres & POLLIN) {
11453                if (i->owner || i->subs[SUB_REAL].owner) {
11454 #ifdef HAVE_PRI
11455                   if (!i->pri)
11456 #endif
11457                      ast_log(LOG_WARNING, "Whoa....  I'm owned but found (%d) in read...\n", i->subs[SUB_REAL].dfd);
11458                   continue;
11459                }
11460                if (!i->mwimonitor_fsk && !i->mwisendactive  && i->cid_start != CID_START_DTMF_NOALERT) {
11461                   ast_log(LOG_WARNING, "Whoa....  I'm not looking for MWI or sending MWI but am reading (%d)...\n", i->subs[SUB_REAL].dfd);
11462                   continue;
11463                }
11464                res = read(i->subs[SUB_REAL].dfd, buf, sizeof(buf));
11465                if (res > 0) {
11466                   if (i->mwimonitor_fsk) {
11467                      if (calc_energy((unsigned char *) buf, res, AST_LAW(i)) > mwilevel) {
11468                         pthread_attr_t attr;
11469                         pthread_t threadid;
11470                         struct mwi_thread_data *mtd;
11471 
11472                         pthread_attr_init(&attr);
11473                         pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
11474 
11475                         ast_log(LOG_DEBUG, "Maybe some MWI on port %d!\n", i->channel);
11476                         if ((mtd = ast_calloc(1, sizeof(*mtd)))) {
11477                            mtd->pvt = i;
11478                            memcpy(mtd->buf, buf, res);
11479                            mtd->len = res;
11480                            if (ast_pthread_create_background(&threadid, &attr, mwi_thread, mtd)) {
11481                               ast_log(LOG_WARNING, "Unable to start mwi thread on channel %d\n", i->channel);
11482                               ast_free(mtd);
11483                            }
11484                            i->mwimonitoractive = 1;
11485                         }
11486                      }
11487                   /* If configured to check for a DTMF CID spill that comes without alert (e.g no polarity reversal) */
11488                   } else if (i->cid_start == CID_START_DTMF_NOALERT) {
11489                      int energy;
11490                      struct timeval now;
11491                      /* State machine dtmfcid_holdoff_state allows for the line to settle
11492                       * before checking agin for dtmf energy.  Presently waits for 500 mS before checking again 
11493                      */
11494                      if (1 == i->dtmfcid_holdoff_state) {
11495                         gettimeofday(&i->dtmfcid_delay, NULL);
11496                         i->dtmfcid_holdoff_state = 2;
11497                      } else if (2 == i->dtmfcid_holdoff_state) {
11498                         gettimeofday(&now, NULL);
11499                         if ((int)(now.tv_sec - i->dtmfcid_delay.tv_sec) * 1000000 + (int)now.tv_usec - (int)i->dtmfcid_delay.tv_usec > 500000) {
11500                            i->dtmfcid_holdoff_state = 0;
11501                         }
11502                      } else {
11503                         energy = calc_energy((unsigned char *) buf, res, AST_LAW(i));
11504                         if (!i->mwisendactive && energy > dtmfcid_level) {
11505                            pthread_t threadid;
11506                            struct ast_channel *chan;
11507                            ast_mutex_unlock(&iflock);
11508                            if (analog_lib_handles(i->sig, i->radio, i->oprmode)) {
11509                               /* just in case this event changes or somehow destroys a channel, set doomed here too */
11510                               doomed = analog_handle_init_event(i->sig_pvt, ANALOG_EVENT_DTMFCID);  
11511                               i->dtmfcid_holdoff_state = 1;
11512                            } else {
11513                               chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL);
11514                               if (!chan) {
11515                                  ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
11516                               } else {
11517                                  res = ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan);
11518                                  if (res) {
11519                                     ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11520                                  } else {
11521                                     i->dtmfcid_holdoff_state = 1;
11522                                  }
11523                               }
11524                            }
11525                            ast_mutex_lock(&iflock);
11526                         }
11527                      }
11528                   }
11529                   if (i->mwisendactive) {
11530                      mwi_send_process_buffer(i, res);
11531                   }
11532                } else {
11533                   ast_log(LOG_WARNING, "Read failed with %d: %s\n", res, strerror(errno));
11534                }
11535             }
11536             if (pollres & POLLPRI) {
11537                if (i->owner || i->subs[SUB_REAL].owner) {
11538 #ifdef HAVE_PRI
11539                   if (!i->pri)
11540 #endif
11541                      ast_log(LOG_WARNING, "Whoa....  I'm owned but found (%d)...\n", i->subs[SUB_REAL].dfd);
11542                   continue;
11543                }
11544                res = dahdi_get_event(i->subs[SUB_REAL].dfd);
11545                ast_debug(1, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel);
11546                /* Don't hold iflock while handling init events */
11547                ast_mutex_unlock(&iflock);
11548                if (0 == i->mwisendactive || 0 == mwi_send_process_event(i, res)) {
11549                   if (analog_lib_handles(i->sig, i->radio, i->oprmode))
11550                      doomed = (struct dahdi_pvt *) analog_handle_init_event(i->sig_pvt, dahdievent_to_analogevent(res));
11551                   else
11552                      doomed = handle_init_event(i, res);
11553                }
11554                ast_mutex_lock(&iflock);
11555             }
11556          }
11557       }
11558       ast_mutex_unlock(&iflock);
11559    }
11560    /* Never reached */
11561    return NULL;
11562 
11563 }
11564 
11565 static int restart_monitor(void)
11566 {
11567    /* If we're supposed to be stopped -- stay stopped */
11568    if (monitor_thread == AST_PTHREADT_STOP)
11569       return 0;
11570    ast_mutex_lock(&monlock);
11571    if (monitor_thread == pthread_self()) {
11572       ast_mutex_unlock(&monlock);
11573       ast_log(LOG_WARNING, "Cannot kill myself\n");
11574       return -1;
11575    }
11576    if (monitor_thread != AST_PTHREADT_NULL) {
11577       /* Wake up the thread */
11578       pthread_kill(monitor_thread, SIGURG);
11579    } else {
11580       /* Start a new monitor */
11581       if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) {
11582          ast_mutex_unlock(&monlock);
11583          ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
11584          return -1;
11585       }
11586    }
11587    ast_mutex_unlock(&monlock);
11588    return 0;
11589 }
11590 
11591 #if defined(HAVE_PRI)
11592 static int pri_resolve_span(int *span, int channel, int offset, struct dahdi_spaninfo *si)
11593 {
11594    int x;
11595    int trunkgroup;
11596    /* Get appropriate trunk group if there is one */
11597    trunkgroup = pris[*span].mastertrunkgroup;
11598    if (trunkgroup) {
11599       /* Select a specific trunk group */
11600       for (x = 0; x < NUM_SPANS; x++) {
11601          if (pris[x].pri.trunkgroup == trunkgroup) {
11602             *span = x;
11603             return 0;
11604          }
11605       }
11606       ast_log(LOG_WARNING, "Channel %d on span %d configured to use nonexistent trunk group %d\n", channel, *span, trunkgroup);
11607       *span = -1;
11608    } else {
11609       if (pris[*span].pri.trunkgroup) {
11610          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);
11611          *span = -1;
11612       } else if (pris[*span].mastertrunkgroup) {
11613          ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is already part of trunk group %d\n", *span, pris[*span].mastertrunkgroup);
11614          *span = -1;
11615       } else {
11616          if (si->totalchans == 31) {
11617             /* E1 */
11618             pris[*span].dchannels[0] = 16 + offset;
11619          } else if (si->totalchans == 24) {
11620             /* T1 or J1 */
11621             pris[*span].dchannels[0] = 24 + offset;
11622          } else if (si->totalchans == 3) {
11623             /* BRI */
11624             pris[*span].dchannels[0] = 3 + offset;
11625          } else {
11626             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);
11627             *span = -1;
11628             return 0;
11629          }
11630          pris[*span].pri.span = *span + 1;
11631       }
11632    }
11633    return 0;
11634 }
11635 #endif   /* defined(HAVE_PRI) */
11636 
11637 #if defined(HAVE_PRI)
11638 static int pri_create_trunkgroup(int trunkgroup, int *channels)
11639 {
11640    struct dahdi_spaninfo si;
11641    struct dahdi_params p;
11642    int fd;
11643    int span;
11644    int ospan=0;
11645    int x,y;
11646    for (x = 0; x < NUM_SPANS; x++) {
11647       if (pris[x].pri.trunkgroup == trunkgroup) {
11648          ast_log(LOG_WARNING, "Trunk group %d already exists on span %d, Primary d-channel %d\n", trunkgroup, x + 1, pris[x].dchannels[0]);
11649          return -1;
11650       }
11651    }
11652    for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
11653       if (!channels[y])
11654          break;
11655       memset(&si, 0, sizeof(si));
11656       memset(&p, 0, sizeof(p));
11657       fd = open("/dev/dahdi/channel", O_RDWR);
11658       if (fd < 0) {
11659          ast_log(LOG_WARNING, "Failed to open channel: %s\n", strerror(errno));
11660          return -1;
11661       }
11662       x = channels[y];
11663       if (ioctl(fd, DAHDI_SPECIFY, &x)) {
11664          ast_log(LOG_WARNING, "Failed to specify channel %d: %s\n", channels[y], strerror(errno));
11665          close(fd);
11666          return -1;
11667       }
11668       if (ioctl(fd, DAHDI_GET_PARAMS, &p)) {
11669          ast_log(LOG_WARNING, "Failed to get channel parameters for channel %d: %s\n", channels[y], strerror(errno));
11670          return -1;
11671       }
11672       if (ioctl(fd, DAHDI_SPANSTAT, &si)) {
11673          ast_log(LOG_WARNING, "Failed go get span information on channel %d (span %d): %s\n", channels[y], p.spanno, strerror(errno));
11674          close(fd);
11675          return -1;
11676       }
11677       span = p.spanno - 1;
11678       if (pris[span].pri.trunkgroup) {
11679          ast_log(LOG_WARNING, "Span %d is already provisioned for trunk group %d\n", span + 1, pris[span].pri.trunkgroup);
11680          close(fd);
11681          return -1;
11682       }
11683       if (pris[span].pri.pvts[0]) {
11684          ast_log(LOG_WARNING, "Span %d is already provisioned with channels (implicit PRI maybe?)\n", span + 1);
11685          close(fd);
11686          return -1;
11687       }
11688       if (!y) {
11689          pris[span].pri.trunkgroup = trunkgroup;
11690          ospan = span;
11691       }
11692       pris[ospan].dchannels[y] = channels[y];
11693       pris[span].pri.span = span + 1;
11694       close(fd);
11695    }
11696    return 0;
11697 }
11698 #endif   /* defined(HAVE_PRI) */
11699 
11700 #if defined(HAVE_PRI)
11701 static int pri_create_spanmap(int span, int trunkgroup, int logicalspan)
11702 {
11703    if (pris[span].mastertrunkgroup) {
11704       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);
11705       return -1;
11706    }
11707    pris[span].mastertrunkgroup = trunkgroup;
11708    pris[span].prilogicalspan = logicalspan;
11709    return 0;
11710 }
11711 #endif   /* defined(HAVE_PRI) */
11712 
11713 #if defined(HAVE_SS7)
11714 static unsigned int parse_pointcode(const char *pcstring)
11715 {
11716    unsigned int code1, code2, code3;
11717    int numvals;
11718 
11719    numvals = sscanf(pcstring, "%30d-%30d-%30d", &code1, &code2, &code3);
11720    if (numvals == 1)
11721       return code1;
11722    if (numvals == 3)
11723       return (code1 << 16) | (code2 << 8) | code3;
11724 
11725    return 0;
11726 }
11727 #endif   /* defined(HAVE_SS7) */
11728 
11729 #if defined(HAVE_SS7)
11730 static struct dahdi_ss7 * ss7_resolve_linkset(int linkset)
11731 {
11732    if ((linkset < 0) || (linkset >= NUM_SPANS))
11733       return NULL;
11734    else
11735       return &linksets[linkset - 1];
11736 }
11737 #endif   /* defined(HAVE_SS7) */
11738 
11739 #ifdef HAVE_OPENR2
11740 static void dahdi_r2_destroy_links(void)
11741 {
11742    int i = 0;
11743    if (!r2links) {
11744       return;
11745    }
11746    for (; i < r2links_count; i++) {
11747       if (r2links[i]->r2master != AST_PTHREADT_NULL) {
11748          pthread_cancel(r2links[i]->r2master);
11749          pthread_join(r2links[i]->r2master, NULL);
11750          openr2_context_delete(r2links[i]->protocol_context);
11751       }
11752       ast_free(r2links[i]);
11753    }
11754    ast_free(r2links);
11755    r2links = NULL;
11756    r2links_count = 0;
11757 }
11758 
11759 #define R2_LINK_CAPACITY 10
11760 static struct dahdi_mfcr2 *dahdi_r2_get_link(void)
11761 {
11762    struct dahdi_mfcr2 *new_r2link = NULL;
11763    struct dahdi_mfcr2 **new_r2links = NULL;
11764    /* this function is called just when starting up and no monitor threads have been launched,
11765       no need to lock monitored_count member */
11766    if (!r2links_count || (r2links[r2links_count - 1]->monitored_count == R2_LINK_CAPACITY)) {
11767       new_r2link = ast_calloc(1, sizeof(**r2links));
11768       if (!new_r2link) {
11769          ast_log(LOG_ERROR, "Cannot allocate R2 link!\n");
11770          return NULL;
11771       }
11772       new_r2links = ast_realloc(r2links, ((r2links_count + 1) * sizeof(*r2links)));
11773       if (!new_r2links) {
11774          ast_log(LOG_ERROR, "Cannot allocate R2 link!\n");
11775          ast_free(new_r2link);
11776          return NULL;
11777       }
11778       r2links = new_r2links;
11779       new_r2link->r2master = AST_PTHREADT_NULL;
11780       r2links[r2links_count] = new_r2link;
11781       r2links_count++;
11782       ast_log(LOG_DEBUG, "Created new R2 link!\n");
11783    }
11784    return r2links[r2links_count - 1];
11785 }
11786 
11787 static int dahdi_r2_set_context(struct dahdi_mfcr2 *r2_link, const struct dahdi_chan_conf *conf)
11788 {
11789    char tmplogdir[] = "/tmp";
11790    char logdir[OR2_MAX_PATH];
11791    int threshold = 0;
11792    int snres = 0;
11793    r2_link->protocol_context = openr2_context_new(NULL, &dahdi_r2_event_iface,
11794          &dahdi_r2_transcode_iface, conf->mfcr2.variant, conf->mfcr2.max_ani,
11795          conf->mfcr2.max_dnis);
11796    if (!r2_link->protocol_context) {
11797       return -1;
11798    }
11799    openr2_context_set_log_level(r2_link->protocol_context, conf->mfcr2.loglevel);
11800    openr2_context_set_ani_first(r2_link->protocol_context, conf->mfcr2.get_ani_first);
11801 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
11802    openr2_context_set_skip_category_request(r2_link->protocol_context, conf->mfcr2.skip_category_request);
11803 #endif
11804    openr2_context_set_mf_threshold(r2_link->protocol_context, threshold);
11805    openr2_context_set_mf_back_timeout(r2_link->protocol_context, conf->mfcr2.mfback_timeout);
11806    openr2_context_set_metering_pulse_timeout(r2_link->protocol_context, conf->mfcr2.metering_pulse_timeout);
11807    openr2_context_set_double_answer(r2_link->protocol_context, conf->mfcr2.double_answer);
11808    openr2_context_set_immediate_accept(r2_link->protocol_context, conf->mfcr2.immediate_accept);
11809    if (ast_strlen_zero(conf->mfcr2.logdir)) {
11810       if (openr2_context_set_log_directory(r2_link->protocol_context, tmplogdir)) {
11811          ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir);
11812       }
11813    } else {
11814       snres = snprintf(logdir, sizeof(logdir), "%s/%s/%s", ast_config_AST_LOG_DIR, "mfcr2", conf->mfcr2.logdir);
11815       if (snres >= sizeof(logdir)) {
11816          ast_log(LOG_ERROR, "MFC/R2 logging directory truncated, using %s\n", tmplogdir);
11817          if (openr2_context_set_log_directory(r2_link->protocol_context, tmplogdir)) {
11818             ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir);
11819          }
11820       } else {
11821          if (openr2_context_set_log_directory(r2_link->protocol_context, logdir)) {
11822             ast_log(LOG_ERROR, "Failed setting MFC/R2 log directory %s\n", logdir);
11823          }
11824       }
11825    }
11826    if (!ast_strlen_zero(conf->mfcr2.r2proto_file)) {
11827       if (openr2_context_configure_from_advanced_file(r2_link->protocol_context, conf->mfcr2.r2proto_file)) {
11828          ast_log(LOG_ERROR, "Failed to configure r2context from advanced configuration file %s\n", conf->mfcr2.r2proto_file);
11829       }
11830    }
11831    r2_link->monitored_count = 0;
11832    return 0;
11833 }
11834 #endif
11835 
11836 /* converts a DAHDI sigtype to signalling as can be configured from
11837  * chan_dahdi.conf.
11838  * While both have basically the same values, this will later be the
11839  * place to add filters and sanity checks
11840  */
11841 static int sigtype_to_signalling(int sigtype)
11842 {
11843    return sigtype;
11844 }
11845 
11846 /*!
11847  * \internal
11848  * \brief Get file name and channel number from (subdir,number)
11849  *
11850  * \param subdir name of the subdirectory under /dev/dahdi/
11851  * \param channel name of device file under /dev/dahdi/<subdir>/
11852  * \param path buffer to put file name in
11853  * \param pathlen maximal length of path
11854  *
11855  * \retval minor number of dahdi channel.
11856  * \retval -errno on error.
11857  */
11858 static int device2chan(const char *subdir, int channel, char *path, int pathlen)
11859 {
11860    struct stat stbuf;
11861    int      num;
11862 
11863    snprintf(path, pathlen, "/dev/dahdi/%s/%d", subdir, channel);
11864    if (stat(path, &stbuf) < 0) {
11865       ast_log(LOG_ERROR, "stat(%s) failed: %s\n", path, strerror(errno));
11866       return -errno;
11867    }
11868    if (!S_ISCHR(stbuf.st_mode)) {
11869       ast_log(LOG_ERROR, "%s: Not a character device file\n", path);
11870       return -EINVAL;
11871    }
11872    num = minor(stbuf.st_rdev);
11873    ast_log(LOG_DEBUG, "%s -> %d\n", path, num);
11874    return num;
11875 
11876 }
11877 
11878 /*!
11879  * \internal
11880  * \brief Initialize/create a channel interface.
11881  *
11882  * \param channel Channel interface number to initialize/create.
11883  * \param conf Configuration parameters to initialize interface with.
11884  * \param reloading What we are doing now:
11885  * 0 - initial module load,
11886  * 1 - module reload,
11887  * 2 - module restart
11888  *
11889  * \retval Interface-pointer initialized/created
11890  * \retval NULL if error
11891  */
11892 static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf, int reloading)
11893 {
11894    /* Make a dahdi_pvt structure for this interface */
11895    struct dahdi_pvt *tmp;/*!< Current channel structure initializing */
11896    char fn[80];
11897    struct dahdi_bufferinfo bi;
11898 
11899    int res;
11900    int span = 0;
11901    int here = 0;/*!< TRUE if the channel interface already exists. */
11902    int x;
11903    struct analog_pvt *analog_p = NULL;
11904    struct dahdi_params p;
11905 #if defined(HAVE_PRI)
11906    struct dahdi_spaninfo si;
11907    struct sig_pri_chan *pri_chan = NULL;
11908 #endif   /* defined(HAVE_PRI) */
11909 #if defined(HAVE_SS7)
11910    struct sig_ss7_chan *ss7_chan = NULL;
11911 #endif   /* defined(HAVE_SS7) */
11912 
11913    /* Search channel interface list to see if it already exists. */
11914    for (tmp = iflist; tmp; tmp = tmp->next) {
11915       if (!tmp->destroy) {
11916          if (tmp->channel == channel) {
11917             /* The channel interface already exists. */
11918             here = 1;
11919             break;
11920          }
11921          if (tmp->channel > channel) {
11922             /* No way it can be in the sorted list. */
11923             tmp = NULL;
11924             break;
11925          }
11926       }
11927    }
11928 
11929    if (!here && reloading != 1) {
11930       tmp = ast_calloc(1, sizeof(*tmp));
11931       if (!tmp) {
11932          return NULL;
11933       }
11934       tmp->cc_params = ast_cc_config_params_init();
11935       if (!tmp->cc_params) {
11936          ast_free(tmp);
11937          return NULL;
11938       }
11939       ast_mutex_init(&tmp->lock);
11940       ifcount++;
11941       for (x = 0; x < 3; x++)
11942          tmp->subs[x].dfd = -1;
11943       tmp->channel = channel;
11944       tmp->priindication_oob = conf->chan.priindication_oob;
11945    }
11946 
11947    if (tmp) {
11948       int chan_sig = conf->chan.sig;
11949 
11950       if (!here) {
11951          /* Can only get here if this is a new channel interface being created. */
11952          if ((channel != CHAN_PSEUDO)) {
11953             int count = 0;
11954 
11955             snprintf(fn, sizeof(fn), "%d", channel);
11956             /* Open non-blocking */
11957             tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
11958             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 */
11959                usleep(1);
11960                tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
11961                count++;
11962             }
11963             /* Allocate a DAHDI structure */
11964             if (tmp->subs[SUB_REAL].dfd < 0) {
11965                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);
11966                destroy_dahdi_pvt(tmp);
11967                return NULL;
11968             }
11969             memset(&p, 0, sizeof(p));
11970             res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
11971             if (res < 0) {
11972                ast_log(LOG_ERROR, "Unable to get parameters: %s\n", strerror(errno));
11973                destroy_dahdi_pvt(tmp);
11974                return NULL;
11975             }
11976             if (conf->is_sig_auto)
11977                chan_sig = sigtype_to_signalling(p.sigtype);
11978             if (p.sigtype != (chan_sig & 0x3ffff)) {
11979                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));
11980                destroy_dahdi_pvt(tmp);
11981                return NULL;
11982             }
11983             tmp->law_default = p.curlaw;
11984             tmp->law = p.curlaw;
11985             tmp->span = p.spanno;
11986             span = p.spanno - 1;
11987          } else {
11988             chan_sig = 0;
11989          }
11990          tmp->sig = chan_sig;
11991          tmp->outsigmod = conf->chan.outsigmod;
11992 
11993          if (analog_lib_handles(chan_sig, tmp->radio, tmp->oprmode)) {
11994             analog_p = analog_new(dahdisig_to_analogsig(chan_sig), &dahdi_analog_callbacks, tmp);
11995             if (!analog_p) {
11996                destroy_dahdi_pvt(tmp);
11997                return NULL;
11998             }
11999             tmp->sig_pvt = analog_p;
12000          }
12001 #if defined(HAVE_SS7)
12002          if (chan_sig == SIG_SS7) {
12003             struct dahdi_ss7 *ss7;
12004             int clear = 0;
12005 
12006             if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &clear)) {
12007                ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
12008                destroy_dahdi_pvt(tmp);
12009                return NULL;
12010             }
12011 
12012             ss7 = ss7_resolve_linkset(cur_linkset);
12013             if (!ss7) {
12014                ast_log(LOG_ERROR, "Unable to find linkset %d\n", cur_linkset);
12015                destroy_dahdi_pvt(tmp);
12016                return NULL;
12017             }
12018             ss7->ss7.span = cur_linkset;
12019             if (cur_cicbeginswith < 0) {
12020                ast_log(LOG_ERROR, "Need to set cicbeginswith for the channels!\n");
12021                destroy_dahdi_pvt(tmp);
12022                return NULL;
12023             }
12024             ss7_chan = sig_ss7_chan_new(tmp, &dahdi_ss7_callbacks, &ss7->ss7);
12025             if (!ss7_chan) {
12026                destroy_dahdi_pvt(tmp);
12027                return NULL;
12028             }
12029             tmp->sig_pvt = ss7_chan;
12030             tmp->ss7 = &ss7->ss7;
12031 
12032             ss7_chan->channel = tmp->channel;
12033             ss7_chan->cic = cur_cicbeginswith++;
12034 
12035             /* DB: Add CIC's DPC information */
12036             ss7_chan->dpc = cur_defaultdpc;
12037 
12038             ss7->ss7.pvts[ss7->ss7.numchans++] = ss7_chan;
12039 
12040             ast_copy_string(ss7->ss7.internationalprefix, conf->ss7.ss7.internationalprefix, sizeof(ss7->ss7.internationalprefix));
12041             ast_copy_string(ss7->ss7.nationalprefix, conf->ss7.ss7.nationalprefix, sizeof(ss7->ss7.nationalprefix));
12042             ast_copy_string(ss7->ss7.subscriberprefix, conf->ss7.ss7.subscriberprefix, sizeof(ss7->ss7.subscriberprefix));
12043             ast_copy_string(ss7->ss7.unknownprefix, conf->ss7.ss7.unknownprefix, sizeof(ss7->ss7.unknownprefix));
12044 
12045             ss7->ss7.called_nai = conf->ss7.ss7.called_nai;
12046             ss7->ss7.calling_nai = conf->ss7.ss7.calling_nai;
12047          }
12048 #endif   /* defined(HAVE_SS7) */
12049 #ifdef HAVE_OPENR2
12050          if (chan_sig == SIG_MFCR2) {
12051             struct dahdi_mfcr2 *r2_link;
12052             r2_link = dahdi_r2_get_link();
12053             if (!r2_link) {
12054                ast_log(LOG_WARNING, "Cannot get another R2 DAHDI context!\n");
12055                destroy_dahdi_pvt(tmp);
12056                return NULL;
12057             }
12058             if (!r2_link->protocol_context && dahdi_r2_set_context(r2_link, conf)) {
12059                ast_log(LOG_ERROR, "Cannot create OpenR2 protocol context.\n");
12060                destroy_dahdi_pvt(tmp);
12061                return NULL;
12062             }
12063             if (r2_link->numchans == ARRAY_LEN(r2_link->pvts)) {
12064                ast_log(LOG_ERROR, "Cannot add more channels to this link!\n");
12065                destroy_dahdi_pvt(tmp);
12066                return NULL;
12067             }
12068             r2_link->pvts[r2_link->numchans++] = tmp;
12069             tmp->r2chan = openr2_chan_new_from_fd(r2_link->protocol_context,
12070                                         tmp->subs[SUB_REAL].dfd,
12071                                         NULL, NULL);
12072             if (!tmp->r2chan) {
12073                openr2_liberr_t err = openr2_context_get_last_error(r2_link->protocol_context);
12074                ast_log(LOG_ERROR, "Cannot create OpenR2 channel: %s\n", openr2_context_error_string(err));
12075                destroy_dahdi_pvt(tmp);
12076                return NULL;
12077             }
12078             tmp->mfcr2 = r2_link;
12079             if (conf->mfcr2.call_files) {
12080                openr2_chan_enable_call_files(tmp->r2chan);
12081             }
12082             openr2_chan_set_client_data(tmp->r2chan, tmp);
12083             /* cast seems to be needed to get rid of the annoying warning regarding format attribute  */
12084             openr2_chan_set_logging_func(tmp->r2chan, (openr2_logging_func_t)dahdi_r2_on_chan_log);
12085             openr2_chan_set_log_level(tmp->r2chan, conf->mfcr2.loglevel);
12086             tmp->mfcr2_category = conf->mfcr2.category;
12087             tmp->mfcr2_charge_calls = conf->mfcr2.charge_calls;
12088             tmp->mfcr2_allow_collect_calls = conf->mfcr2.allow_collect_calls;
12089             tmp->mfcr2_forced_release = conf->mfcr2.forced_release;
12090             tmp->mfcr2_accept_on_offer = conf->mfcr2.accept_on_offer;
12091             tmp->mfcr2call = 0;
12092             tmp->mfcr2_dnis_index = 0;
12093             tmp->mfcr2_ani_index = 0;
12094             r2_link->monitored_count++;
12095          }
12096 #endif
12097 #ifdef HAVE_PRI
12098          if (dahdi_sig_pri_lib_handles(chan_sig)) {
12099             int offset;
12100             int matchesdchan;
12101             int x,y;
12102             int myswitchtype = 0;
12103 
12104             offset = 0;
12105             if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &offset)) {
12106                ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
12107                destroy_dahdi_pvt(tmp);
12108                return NULL;
12109             }
12110             if (span >= NUM_SPANS) {
12111                ast_log(LOG_ERROR, "Channel %d does not lie on a span I know of (%d)\n", channel, span);
12112                destroy_dahdi_pvt(tmp);
12113                return NULL;
12114             } else {
12115                si.spanno = 0;
12116                if (ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SPANSTAT,&si) == -1) {
12117                   ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno));
12118                   destroy_dahdi_pvt(tmp);
12119                   return NULL;
12120                }
12121                /* Store the logical span first based upon the real span */
12122                tmp->logicalspan = pris[span].prilogicalspan;
12123                pri_resolve_span(&span, channel, (channel - p.chanpos), &si);
12124                if (span < 0) {
12125                   ast_log(LOG_WARNING, "Channel %d: Unable to find locate channel/trunk group!\n", channel);
12126                   destroy_dahdi_pvt(tmp);
12127                   return NULL;
12128                }
12129                myswitchtype = conf->pri.pri.switchtype;
12130                /* Make sure this isn't a d-channel */
12131                matchesdchan=0;
12132                for (x = 0; x < NUM_SPANS; x++) {
12133                   for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
12134                      if (pris[x].dchannels[y] == tmp->channel) {
12135                         matchesdchan = 1;
12136                         break;
12137                      }
12138                   }
12139                }
12140                if (!matchesdchan) {
12141                   if (pris[span].pri.nodetype && (pris[span].pri.nodetype != conf->pri.pri.nodetype)) {
12142                      ast_log(LOG_ERROR, "Span %d is already a %s node\n", span + 1, pri_node2str(pris[span].pri.nodetype));
12143                      destroy_dahdi_pvt(tmp);
12144                      return NULL;
12145                   }
12146                   if (pris[span].pri.switchtype && (pris[span].pri.switchtype != myswitchtype)) {
12147                      ast_log(LOG_ERROR, "Span %d is already a %s switch\n", span + 1, pri_switch2str(pris[span].pri.switchtype));
12148                      destroy_dahdi_pvt(tmp);
12149                      return NULL;
12150                   }
12151                   if ((pris[span].pri.dialplan) && (pris[span].pri.dialplan != conf->pri.pri.dialplan)) {
12152                      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));
12153                      destroy_dahdi_pvt(tmp);
12154                      return NULL;
12155                   }
12156                   if (!ast_strlen_zero(pris[span].pri.idledial) && strcmp(pris[span].pri.idledial, conf->pri.pri.idledial)) {
12157                      ast_log(LOG_ERROR, "Span %d already has idledial '%s'.\n", span + 1, conf->pri.pri.idledial);
12158                      destroy_dahdi_pvt(tmp);
12159                      return NULL;
12160                   }
12161                   if (!ast_strlen_zero(pris[span].pri.idleext) && strcmp(pris[span].pri.idleext, conf->pri.pri.idleext)) {
12162                      ast_log(LOG_ERROR, "Span %d already has idleext '%s'.\n", span + 1, conf->pri.pri.idleext);
12163                      destroy_dahdi_pvt(tmp);
12164                      return NULL;
12165                   }
12166                   if (pris[span].pri.minunused && (pris[span].pri.minunused != conf->pri.pri.minunused)) {
12167                      ast_log(LOG_ERROR, "Span %d already has minunused of %d.\n", span + 1, conf->pri.pri.minunused);
12168                      destroy_dahdi_pvt(tmp);
12169                      return NULL;
12170                   }
12171                   if (pris[span].pri.minidle && (pris[span].pri.minidle != conf->pri.pri.minidle)) {
12172                      ast_log(LOG_ERROR, "Span %d already has minidle of %d.\n", span + 1, conf->pri.pri.minidle);
12173                      destroy_dahdi_pvt(tmp);
12174                      return NULL;
12175                   }
12176                   if (pris[span].pri.numchans >= ARRAY_LEN(pris[span].pri.pvts)) {
12177                      ast_log(LOG_ERROR, "Unable to add channel %d: Too many channels in trunk group %d!\n", channel,
12178                         pris[span].pri.trunkgroup);
12179                      destroy_dahdi_pvt(tmp);
12180                      return NULL;
12181                   }
12182 
12183                   ast_debug(4, "Adding callbacks %p to chan %d\n", &dahdi_pri_callbacks, tmp->channel);
12184                   pri_chan = sig_pri_chan_new(tmp, &dahdi_pri_callbacks, &pris[span].pri, tmp->logicalspan, p.chanpos, pris[span].mastertrunkgroup);
12185                   if (!pri_chan) {
12186                      destroy_dahdi_pvt(tmp);
12187                      return NULL;
12188                   }
12189                   tmp->sig_pvt = pri_chan;
12190                   tmp->pri = &pris[span].pri;
12191 
12192                   tmp->priexclusive = conf->chan.priexclusive;
12193 
12194                   if (!tmp->pri->cc_params) {
12195                      tmp->pri->cc_params = ast_cc_config_params_init();
12196                      if (!tmp->pri->cc_params) {
12197                         destroy_dahdi_pvt(tmp);
12198                         return NULL;
12199                      }
12200                   }
12201                   ast_cc_copy_config_params(tmp->pri->cc_params,
12202                      conf->chan.cc_params);
12203 
12204                   pris[span].pri.sig = chan_sig;
12205                   pris[span].pri.nodetype = conf->pri.pri.nodetype;
12206                   pris[span].pri.switchtype = myswitchtype;
12207                   pris[span].pri.nsf = conf->pri.pri.nsf;
12208                   pris[span].pri.dialplan = conf->pri.pri.dialplan;
12209                   pris[span].pri.localdialplan = conf->pri.pri.localdialplan;
12210                   pris[span].pri.pvts[pris[span].pri.numchans++] = tmp->sig_pvt;
12211                   pris[span].pri.minunused = conf->pri.pri.minunused;
12212                   pris[span].pri.minidle = conf->pri.pri.minidle;
12213                   pris[span].pri.overlapdial = conf->pri.pri.overlapdial;
12214                   pris[span].pri.qsigchannelmapping = conf->pri.pri.qsigchannelmapping;
12215                   pris[span].pri.discardremoteholdretrieval = conf->pri.pri.discardremoteholdretrieval;
12216 #if defined(HAVE_PRI_SERVICE_MESSAGES)
12217                   pris[span].pri.enable_service_message_support = conf->pri.pri.enable_service_message_support;
12218 #endif   /* defined(HAVE_PRI_SERVICE_MESSAGES) */
12219 #ifdef HAVE_PRI_INBANDDISCONNECT
12220                   pris[span].pri.inbanddisconnect = conf->pri.pri.inbanddisconnect;
12221 #endif
12222 #if defined(HAVE_PRI_CALL_HOLD)
12223                   pris[span].pri.hold_disconnect_transfer =
12224                      conf->pri.pri.hold_disconnect_transfer;
12225 #endif   /* defined(HAVE_PRI_CALL_HOLD) */
12226 #if defined(HAVE_PRI_CCSS)
12227                   pris[span].pri.cc_ptmp_recall_mode =
12228                      conf->pri.pri.cc_ptmp_recall_mode;
12229                   pris[span].pri.cc_qsig_signaling_link_req =
12230                      conf->pri.pri.cc_qsig_signaling_link_req;
12231                   pris[span].pri.cc_qsig_signaling_link_rsp =
12232                      conf->pri.pri.cc_qsig_signaling_link_rsp;
12233 #endif   /* defined(HAVE_PRI_CCSS) */
12234 #if defined(HAVE_PRI_CALL_WAITING)
12235                   pris[span].pri.max_call_waiting_calls =
12236                      conf->pri.pri.max_call_waiting_calls;
12237                   pris[span].pri.allow_call_waiting_calls =
12238                      conf->pri.pri.allow_call_waiting_calls;
12239 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
12240                   pris[span].pri.transfer = conf->chan.transfer;
12241                   pris[span].pri.facilityenable = conf->pri.pri.facilityenable;
12242 #if defined(HAVE_PRI_AOC_EVENTS)
12243                   pris[span].pri.aoc_passthrough_flag = conf->pri.pri.aoc_passthrough_flag;
12244                   pris[span].pri.aoce_delayhangup = conf->pri.pri.aoce_delayhangup;
12245 #endif   /* defined(HAVE_PRI_AOC_EVENTS) */
12246                   pris[span].pri.append_msn_to_user_tag = conf->pri.pri.append_msn_to_user_tag;
12247                   ast_copy_string(pris[span].pri.initial_user_tag, conf->chan.cid_tag, sizeof(pris[span].pri.initial_user_tag));
12248                   ast_copy_string(pris[span].pri.msn_list, conf->pri.pri.msn_list, sizeof(pris[span].pri.msn_list));
12249 #if defined(HAVE_PRI_MWI)
12250                   ast_copy_string(pris[span].pri.mwi_mailboxes,
12251                      conf->pri.pri.mwi_mailboxes,
12252                      sizeof(pris[span].pri.mwi_mailboxes));
12253 #endif   /* defined(HAVE_PRI_MWI) */
12254                   ast_copy_string(pris[span].pri.idledial, conf->pri.pri.idledial, sizeof(pris[span].pri.idledial));
12255                   ast_copy_string(pris[span].pri.idleext, conf->pri.pri.idleext, sizeof(pris[span].pri.idleext));
12256                   ast_copy_string(pris[span].pri.internationalprefix, conf->pri.pri.internationalprefix, sizeof(pris[span].pri.internationalprefix));
12257                   ast_copy_string(pris[span].pri.nationalprefix, conf->pri.pri.nationalprefix, sizeof(pris[span].pri.nationalprefix));
12258                   ast_copy_string(pris[span].pri.localprefix, conf->pri.pri.localprefix, sizeof(pris[span].pri.localprefix));
12259                   ast_copy_string(pris[span].pri.privateprefix, conf->pri.pri.privateprefix, sizeof(pris[span].pri.privateprefix));
12260                   ast_copy_string(pris[span].pri.unknownprefix, conf->pri.pri.unknownprefix, sizeof(pris[span].pri.unknownprefix));
12261                   pris[span].pri.resetinterval = conf->pri.pri.resetinterval;
12262 
12263                   for (x = 0; x < PRI_MAX_TIMERS; x++) {
12264                      pris[span].pri.pritimers[x] = conf->pri.pri.pritimers[x];
12265                   }
12266 
12267 #if defined(HAVE_PRI_CALL_WAITING)
12268                   /* Channel initial config parameters. */
12269                   pris[span].pri.ch_cfg.stripmsd = conf->chan.stripmsd;
12270                   pris[span].pri.ch_cfg.hidecallerid = conf->chan.hidecallerid;
12271                   pris[span].pri.ch_cfg.hidecalleridname = conf->chan.hidecalleridname;
12272                   pris[span].pri.ch_cfg.immediate = conf->chan.immediate;
12273                   pris[span].pri.ch_cfg.priexclusive = conf->chan.priexclusive;
12274                   pris[span].pri.ch_cfg.priindication_oob = conf->chan.priindication_oob;
12275                   pris[span].pri.ch_cfg.use_callerid = conf->chan.use_callerid;
12276                   pris[span].pri.ch_cfg.use_callingpres = conf->chan.use_callingpres;
12277                   ast_copy_string(pris[span].pri.ch_cfg.context, conf->chan.context, sizeof(pris[span].pri.ch_cfg.context));
12278                   ast_copy_string(pris[span].pri.ch_cfg.mohinterpret, conf->chan.mohinterpret, sizeof(pris[span].pri.ch_cfg.mohinterpret));
12279 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
12280                } else {
12281                   ast_log(LOG_ERROR, "Channel %d is reserved for D-channel.\n", p.chanpos);
12282                   destroy_dahdi_pvt(tmp);
12283                   return NULL;
12284                }
12285             }
12286          }
12287 #endif
12288       } else {
12289          /* already exists in interface list */
12290          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));
12291          chan_sig = tmp->sig;
12292          if (tmp->subs[SUB_REAL].dfd > -1) {
12293             memset(&p, 0, sizeof(p));
12294             res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
12295          }
12296       }
12297       /* Adjust starttime on loopstart and kewlstart trunks to reasonable values */
12298       switch (chan_sig) {
12299       case SIG_FXSKS:
12300       case SIG_FXSLS:
12301       case SIG_EM:
12302       case SIG_EM_E1:
12303       case SIG_EMWINK:
12304       case SIG_FEATD:
12305       case SIG_FEATDMF:
12306       case SIG_FEATDMF_TA:
12307       case SIG_FEATB:
12308       case SIG_E911:
12309       case SIG_SF:
12310       case SIG_SFWINK:
12311       case SIG_FGC_CAMA:
12312       case SIG_FGC_CAMAMF:
12313       case SIG_SF_FEATD:
12314       case SIG_SF_FEATDMF:
12315       case SIG_SF_FEATB:
12316          p.starttime = 250;
12317          break;
12318       }
12319 
12320       if (tmp->radio) {
12321          /* XXX Waiting to hear back from Jim if these should be adjustable XXX */
12322          p.channo = channel;
12323          p.rxwinktime = 1;
12324          p.rxflashtime = 1;
12325          p.starttime = 1;
12326          p.debouncetime = 5;
12327       } else {
12328          p.channo = channel;
12329          /* Override timing settings based on config file */
12330          if (conf->timing.prewinktime >= 0)
12331             p.prewinktime = conf->timing.prewinktime;
12332          if (conf->timing.preflashtime >= 0)
12333             p.preflashtime = conf->timing.preflashtime;
12334          if (conf->timing.winktime >= 0)
12335             p.winktime = conf->timing.winktime;
12336          if (conf->timing.flashtime >= 0)
12337             p.flashtime = conf->timing.flashtime;
12338          if (conf->timing.starttime >= 0)
12339             p.starttime = conf->timing.starttime;
12340          if (conf->timing.rxwinktime >= 0)
12341             p.rxwinktime = conf->timing.rxwinktime;
12342          if (conf->timing.rxflashtime >= 0)
12343             p.rxflashtime = conf->timing.rxflashtime;
12344          if (conf->timing.debouncetime >= 0)
12345             p.debouncetime = conf->timing.debouncetime;
12346       }
12347 
12348       /* don't set parms on a pseudo-channel */
12349       if (tmp->subs[SUB_REAL].dfd >= 0)
12350       {
12351          res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_PARAMS, &p);
12352          if (res < 0) {
12353             ast_log(LOG_ERROR, "Unable to set parameters: %s\n", strerror(errno));
12354             destroy_dahdi_pvt(tmp);
12355             return NULL;
12356          }
12357       }
12358 #if 1
12359       if (!here && (tmp->subs[SUB_REAL].dfd > -1)) {
12360          memset(&bi, 0, sizeof(bi));
12361          res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
12362          if (!res) {
12363             bi.txbufpolicy = conf->chan.buf_policy;
12364             bi.rxbufpolicy = conf->chan.buf_policy;
12365             bi.numbufs = conf->chan.buf_no;
12366             res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
12367             if (res < 0) {
12368                ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", channel, strerror(errno));
12369             }
12370          } else {
12371             ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", channel, strerror(errno));
12372          }
12373          tmp->buf_policy = conf->chan.buf_policy;
12374          tmp->buf_no = conf->chan.buf_no;
12375          tmp->usefaxbuffers = conf->chan.usefaxbuffers;
12376          tmp->faxbuf_policy = conf->chan.faxbuf_policy;
12377          tmp->faxbuf_no = conf->chan.faxbuf_no;
12378          /* This is not as gnarly as it may first appear.  If the ioctl above failed, we'd be setting
12379           * tmp->bufsize to zero which would cause subsequent faxbuffer-related ioctl calls to fail.
12380           * The reason the ioctl call above failed should to be determined before worrying about the
12381           * faxbuffer-related ioctl calls */
12382          tmp->bufsize = bi.bufsize;
12383       }
12384 #endif
12385       tmp->immediate = conf->chan.immediate;
12386       tmp->transfertobusy = conf->chan.transfertobusy;
12387       if (chan_sig & __DAHDI_SIG_FXS) {
12388          tmp->mwimonitor_fsk = conf->chan.mwimonitor_fsk;
12389          tmp->mwimonitor_neon = conf->chan.mwimonitor_neon;
12390          tmp->mwimonitor_rpas = conf->chan.mwimonitor_rpas;
12391       }
12392       tmp->ringt_base = ringt_base;
12393       tmp->firstradio = 0;
12394       if ((chan_sig == SIG_FXOKS) || (chan_sig == SIG_FXOLS) || (chan_sig == SIG_FXOGS))
12395          tmp->permcallwaiting = conf->chan.callwaiting;
12396       else
12397          tmp->permcallwaiting = 0;
12398       /* Flag to destroy the channel must be cleared on new mkif.  Part of changes for reload to work */
12399       tmp->destroy = 0;
12400       tmp->drings = conf->chan.drings;
12401 
12402       /* 10 is a nice default. */
12403       if (tmp->drings.ringnum[0].range == 0)
12404          tmp->drings.ringnum[0].range = 10;
12405       if (tmp->drings.ringnum[1].range == 0)
12406          tmp->drings.ringnum[1].range = 10;
12407       if (tmp->drings.ringnum[2].range == 0)
12408          tmp->drings.ringnum[2].range = 10;
12409 
12410       tmp->usedistinctiveringdetection = usedistinctiveringdetection;
12411       tmp->callwaitingcallerid = conf->chan.callwaitingcallerid;
12412       tmp->threewaycalling = conf->chan.threewaycalling;
12413       tmp->adsi = conf->chan.adsi;
12414       tmp->use_smdi = conf->chan.use_smdi;
12415       tmp->permhidecallerid = conf->chan.hidecallerid;
12416       tmp->hidecalleridname = conf->chan.hidecalleridname;
12417       tmp->callreturn = conf->chan.callreturn;
12418       tmp->echocancel = conf->chan.echocancel;
12419       tmp->echotraining = conf->chan.echotraining;
12420       tmp->pulse = conf->chan.pulse;
12421       if (tmp->echocancel.head.tap_length) {
12422          tmp->echocanbridged = conf->chan.echocanbridged;
12423       } else {
12424          if (conf->chan.echocanbridged)
12425             ast_log(LOG_NOTICE, "echocancelwhenbridged requires echocancel to be enabled; ignoring\n");
12426          tmp->echocanbridged = 0;
12427       }
12428       tmp->busydetect = conf->chan.busydetect;
12429       tmp->busycount = conf->chan.busycount;
12430       tmp->busy_tonelength = conf->chan.busy_tonelength;
12431       tmp->busy_quietlength = conf->chan.busy_quietlength;
12432       tmp->callprogress = conf->chan.callprogress;
12433       tmp->waitfordialtone = conf->chan.waitfordialtone;
12434       tmp->cancallforward = conf->chan.cancallforward;
12435       tmp->dtmfrelax = conf->chan.dtmfrelax;
12436       tmp->callwaiting = tmp->permcallwaiting;
12437       tmp->hidecallerid = tmp->permhidecallerid;
12438       tmp->channel = channel;
12439       tmp->stripmsd = conf->chan.stripmsd;
12440       tmp->use_callerid = conf->chan.use_callerid;
12441       tmp->cid_signalling = conf->chan.cid_signalling;
12442       tmp->cid_start = conf->chan.cid_start;
12443       tmp->dahditrcallerid = conf->chan.dahditrcallerid;
12444       tmp->restrictcid = conf->chan.restrictcid;
12445       tmp->use_callingpres = conf->chan.use_callingpres;
12446       if (tmp->usedistinctiveringdetection) {
12447          if (!tmp->use_callerid) {
12448             ast_log(LOG_NOTICE, "Distinctive Ring detect requires 'usecallerid' be on\n");
12449             tmp->use_callerid = 1;
12450          }
12451       }
12452 
12453       if (tmp->cid_signalling == CID_SIG_SMDI) {
12454          if (!tmp->use_smdi) {
12455             ast_log(LOG_WARNING, "SMDI callerid requires SMDI to be enabled, enabling...\n");
12456             tmp->use_smdi = 1;
12457          }
12458       }
12459       if (tmp->use_smdi) {
12460          tmp->smdi_iface = ast_smdi_interface_find(conf->smdi_port);
12461          if (!(tmp->smdi_iface)) {
12462             ast_log(LOG_ERROR, "Invalid SMDI port specfied, disabling SMDI support\n");
12463             tmp->use_smdi = 0;
12464          }
12465       }
12466 
12467       ast_copy_string(tmp->accountcode, conf->chan.accountcode, sizeof(tmp->accountcode));
12468       tmp->amaflags = conf->chan.amaflags;
12469       if (!here) {
12470          tmp->confno = -1;
12471          tmp->propconfno = -1;
12472       }
12473       tmp->canpark = conf->chan.canpark;
12474       tmp->transfer = conf->chan.transfer;
12475       ast_copy_string(tmp->defcontext,conf->chan.context,sizeof(tmp->defcontext));
12476       ast_copy_string(tmp->language, conf->chan.language, sizeof(tmp->language));
12477       ast_copy_string(tmp->mohinterpret, conf->chan.mohinterpret, sizeof(tmp->mohinterpret));
12478       ast_copy_string(tmp->mohsuggest, conf->chan.mohsuggest, sizeof(tmp->mohsuggest));
12479       ast_copy_string(tmp->context, conf->chan.context, sizeof(tmp->context));
12480       ast_copy_string(tmp->parkinglot, conf->chan.parkinglot, sizeof(tmp->parkinglot));
12481       tmp->cid_ton = 0;
12482       if (analog_lib_handles(tmp->sig, tmp->radio, tmp->oprmode)) {
12483          ast_copy_string(tmp->cid_num, conf->chan.cid_num, sizeof(tmp->cid_num));
12484          ast_copy_string(tmp->cid_name, conf->chan.cid_name, sizeof(tmp->cid_name));
12485       } else {
12486          tmp->cid_num[0] = '\0';
12487          tmp->cid_name[0] = '\0';
12488       }
12489 #if defined(HAVE_PRI)
12490       if (dahdi_sig_pri_lib_handles(tmp->sig)) {
12491          tmp->cid_tag[0] = '\0';
12492       } else
12493 #endif   /* defined(HAVE_PRI) */
12494       {
12495          ast_copy_string(tmp->cid_tag, conf->chan.cid_tag, sizeof(tmp->cid_tag));
12496       }
12497       tmp->cid_subaddr[0] = '\0';
12498       ast_copy_string(tmp->mailbox, conf->chan.mailbox, sizeof(tmp->mailbox));
12499       if (channel != CHAN_PSEUDO && !ast_strlen_zero(tmp->mailbox)) {
12500          char *mailbox, *context;
12501          mailbox = context = ast_strdupa(tmp->mailbox);
12502          strsep(&context, "@");
12503          if (ast_strlen_zero(context))
12504             context = "default";
12505          tmp->mwi_event_sub = ast_event_subscribe(AST_EVENT_MWI, mwi_event_cb, "Dahdi MWI subscription", NULL,
12506             AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
12507             AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
12508             AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS,
12509             AST_EVENT_IE_END);
12510       }
12511 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
12512       tmp->mwisend_setting = conf->chan.mwisend_setting;
12513       tmp->mwisend_fsk  = conf->chan.mwisend_fsk;
12514       tmp->mwisend_rpas = conf->chan.mwisend_rpas;
12515 #endif
12516 
12517       tmp->group = conf->chan.group;
12518       tmp->callgroup = conf->chan.callgroup;
12519       tmp->pickupgroup= conf->chan.pickupgroup;
12520       if (conf->chan.vars) {
12521          struct ast_variable *v, *tmpvar;
12522                    for (v = conf->chan.vars ; v ; v = v->next) {
12523                          if ((tmpvar = ast_variable_new(v->name, v->value, v->file))) {
12524                                   tmpvar->next = tmp->vars;
12525                                    tmp->vars = tmpvar;
12526                            }
12527                   }
12528       }
12529       tmp->cid_rxgain = conf->chan.cid_rxgain;
12530       tmp->rxgain = conf->chan.rxgain;
12531       tmp->txgain = conf->chan.txgain;
12532       tmp->txdrc = conf->chan.txdrc;
12533       tmp->rxdrc = conf->chan.rxdrc;
12534       tmp->tonezone = conf->chan.tonezone;
12535       if (tmp->subs[SUB_REAL].dfd > -1) {
12536          set_actual_gain(tmp->subs[SUB_REAL].dfd, tmp->rxgain, tmp->txgain, tmp->rxdrc, tmp->txdrc, tmp->law);
12537          if (tmp->dsp)
12538             ast_dsp_set_digitmode(tmp->dsp, DSP_DIGITMODE_DTMF | tmp->dtmfrelax);
12539          update_conf(tmp);
12540          if (!here) {
12541             switch (chan_sig) {
12542             case SIG_PRI_LIB_HANDLE_CASES:
12543             case SIG_SS7:
12544             case SIG_MFCR2:
12545                break;
12546             default:
12547                /* Hang it up to be sure it's good */
12548                dahdi_set_hook(tmp->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
12549                break;
12550             }
12551          }
12552          ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SETTONEZONE,&tmp->tonezone);
12553 #ifdef HAVE_PRI
12554          memset(&si, 0, sizeof(si));
12555          if (ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SPANSTAT,&si) == -1) {
12556             ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno));
12557             destroy_dahdi_pvt(tmp);
12558             return NULL;
12559          }
12560 #endif
12561          if ((res = get_alarms(tmp)) != DAHDI_ALARM_NONE) {
12562             /* the dchannel is down so put the channel in alarm */
12563             switch (tmp->sig) {
12564 #ifdef HAVE_PRI
12565             case SIG_PRI_LIB_HANDLE_CASES:
12566                sig_pri_chan_alarm_notify(tmp->sig_pvt, si.alarms);
12567                break;
12568 #endif
12569 #if defined(HAVE_SS7)
12570             case SIG_SS7:
12571                sig_ss7_set_alarm(tmp->sig_pvt, 1);
12572                break;
12573 #endif   /* defined(HAVE_SS7) */
12574             default:
12575                /* The only sig submodule left should be sig_analog. */
12576                analog_p = tmp->sig_pvt;
12577                if (analog_p) {
12578                   analog_p->inalarm = 1;
12579                }
12580                tmp->inalarm = 1;
12581                break;
12582             }
12583             handle_alarms(tmp, res);
12584          }
12585       }
12586 
12587       tmp->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
12588       tmp->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
12589       tmp->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
12590       tmp->sendcalleridafter = conf->chan.sendcalleridafter;
12591       ast_cc_copy_config_params(tmp->cc_params, conf->chan.cc_params);
12592 
12593       if (!here) {
12594          tmp->locallyblocked = 0;
12595          tmp->remotelyblocked = 0;
12596          switch (tmp->sig) {
12597 #if defined(HAVE_PRI)
12598          case SIG_PRI_LIB_HANDLE_CASES:
12599             tmp->inservice = 1;/* Inservice until actually implemented. */
12600 #if defined(HAVE_PRI_SERVICE_MESSAGES)
12601             ((struct sig_pri_chan *) tmp->sig_pvt)->service_status = 0;
12602             if (chan_sig == SIG_PRI) {
12603                char db_chan_name[20];
12604                char db_answer[5];
12605 
12606                /*
12607                 * Initialize the active out-of-service status
12608                 * and delete any record if the feature is not enabled.
12609                 */
12610                snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, tmp->span, tmp->channel);
12611                if (!ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) {
12612                   unsigned *why;
12613 
12614                   why = &((struct sig_pri_chan *) tmp->sig_pvt)->service_status;
12615                   if (tmp->pri->enable_service_message_support) {
12616                      char state;
12617 
12618                      sscanf(db_answer, "%1c:%30u", &state, why);
12619 
12620                      /* Ensure that only the implemented bits could be set.*/
12621                      *why &= (SRVST_NEAREND | SRVST_FAREND);
12622                   }
12623                   if (!*why) {
12624                      ast_db_del(db_chan_name, SRVST_DBKEY);
12625                   }
12626                }
12627             }
12628 #endif   /* defined(HAVE_PRI_SERVICE_MESSAGES) */
12629             break;
12630 #endif   /* defined(HAVE_PRI) */
12631 #if defined(HAVE_SS7)
12632          case SIG_SS7:
12633             tmp->inservice = 0;
12634             break;
12635 #endif   /* defined(HAVE_SS7) */
12636          default:
12637              /* We default to in service on protocols that don't have a reset */
12638             tmp->inservice = 1;
12639             break;
12640          }
12641       }
12642 
12643       switch (tmp->sig) {
12644 #if defined(HAVE_PRI)
12645       case SIG_PRI_LIB_HANDLE_CASES:
12646          if (pri_chan) {
12647             pri_chan->channel = tmp->channel;
12648             pri_chan->hidecallerid = tmp->hidecallerid;
12649             pri_chan->hidecalleridname = tmp->hidecalleridname;
12650             pri_chan->immediate = tmp->immediate;
12651             pri_chan->inalarm = tmp->inalarm;
12652             pri_chan->priexclusive = tmp->priexclusive;
12653             pri_chan->priindication_oob = tmp->priindication_oob;
12654             pri_chan->use_callerid = tmp->use_callerid;
12655             pri_chan->use_callingpres = tmp->use_callingpres;
12656             ast_copy_string(pri_chan->context, tmp->context,
12657                sizeof(pri_chan->context));
12658             ast_copy_string(pri_chan->mohinterpret, tmp->mohinterpret,
12659                sizeof(pri_chan->mohinterpret));
12660             pri_chan->stripmsd = tmp->stripmsd;
12661          }
12662          break;
12663 #endif   /* defined(HAVE_PRI) */
12664 #if defined(HAVE_SS7)
12665       case SIG_SS7:
12666          if (ss7_chan) {
12667             ss7_chan->inalarm = tmp->inalarm;
12668 
12669             ss7_chan->stripmsd = tmp->stripmsd;
12670             ss7_chan->hidecallerid = tmp->hidecallerid;
12671             ss7_chan->use_callerid = tmp->use_callerid;
12672             ss7_chan->use_callingpres = tmp->use_callingpres;
12673             ss7_chan->immediate = tmp->immediate;
12674             ss7_chan->locallyblocked = tmp->locallyblocked;
12675             ss7_chan->remotelyblocked = tmp->remotelyblocked;
12676             ast_copy_string(ss7_chan->context, tmp->context,
12677                sizeof(ss7_chan->context));
12678             ast_copy_string(ss7_chan->mohinterpret, tmp->mohinterpret,
12679                sizeof(ss7_chan->mohinterpret));
12680          }
12681          break;
12682 #endif   /* defined(HAVE_SS7) */
12683       default:
12684          /* The only sig submodule left should be sig_analog. */
12685          analog_p = tmp->sig_pvt;
12686          if (analog_p) {
12687             analog_p->channel = tmp->channel;
12688             analog_p->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
12689             analog_p->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
12690             analog_p->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
12691             analog_p->permcallwaiting = conf->chan.callwaiting; /* permcallwaiting possibly modified in analog_config_complete */
12692             analog_p->callreturn = conf->chan.callreturn;
12693             analog_p->cancallforward = conf->chan.cancallforward;
12694             analog_p->canpark = conf->chan.canpark;
12695             analog_p->dahditrcallerid = conf->chan.dahditrcallerid;
12696             analog_p->immediate = conf->chan.immediate;
12697             analog_p->permhidecallerid = conf->chan.permhidecallerid;
12698             analog_p->pulse = conf->chan.pulse;
12699             analog_p->threewaycalling = conf->chan.threewaycalling;
12700             analog_p->transfer = conf->chan.transfer;
12701             analog_p->transfertobusy = conf->chan.transfertobusy;
12702             analog_p->use_callerid = tmp->use_callerid;
12703             analog_p->use_smdi = tmp->use_smdi;
12704             analog_p->smdi_iface = tmp->smdi_iface;
12705             analog_p->outsigmod = ANALOG_SIG_NONE;
12706             analog_p->echotraining = conf->chan.echotraining;
12707             analog_p->cid_signalling = conf->chan.cid_signalling;
12708             analog_p->stripmsd = conf->chan.stripmsd;
12709             switch (conf->chan.cid_start) {
12710             case CID_START_POLARITY:
12711                analog_p->cid_start = ANALOG_CID_START_POLARITY;
12712                break;
12713             case CID_START_POLARITY_IN:
12714                analog_p->cid_start = ANALOG_CID_START_POLARITY_IN;
12715                break;
12716             case CID_START_DTMF_NOALERT:
12717                analog_p->cid_start = ANALOG_CID_START_DTMF_NOALERT;
12718                break;
12719             default:
12720                analog_p->cid_start = ANALOG_CID_START_RING;
12721                break;
12722             }
12723             analog_p->callwaitingcallerid = conf->chan.callwaitingcallerid;
12724             analog_p->ringt = conf->chan.ringt;
12725             analog_p->ringt_base = ringt_base;
12726             analog_p->chan_tech = &dahdi_tech;
12727             analog_p->onhooktime = time(NULL);
12728             if (chan_sig & __DAHDI_SIG_FXO) {
12729                memset(&p, 0, sizeof(p));
12730                res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
12731                if (!res) {
12732                   analog_p->fxsoffhookstate = p.rxisoffhook;
12733                }
12734 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
12735                res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_VMWI_CONFIG, &tmp->mwisend_setting);
12736 #endif
12737             }
12738             analog_p->msgstate = -1;
12739 
12740             ast_copy_string(analog_p->mohsuggest, conf->chan.mohsuggest, sizeof(analog_p->mohsuggest));
12741             ast_copy_string(analog_p->cid_num, conf->chan.cid_num, sizeof(analog_p->cid_num));
12742             ast_copy_string(analog_p->cid_name, conf->chan.cid_name, sizeof(analog_p->cid_name));
12743 
12744             analog_config_complete(analog_p);
12745          }
12746          break;
12747       }
12748 #if defined(HAVE_PRI)
12749       if (tmp->channel == CHAN_PSEUDO) {
12750          /*
12751           * Save off pseudo channel buffer policy values for dynamic creation of
12752           * no B channel interfaces.
12753           */
12754          dahdi_pseudo_parms.buf_no = tmp->buf_no;
12755          dahdi_pseudo_parms.buf_policy = tmp->buf_policy;
12756          dahdi_pseudo_parms.faxbuf_no = tmp->faxbuf_no;
12757          dahdi_pseudo_parms.faxbuf_policy = tmp->faxbuf_policy;
12758       }
12759 #endif   /* defined(HAVE_PRI) */
12760    }
12761    if (tmp && !here) {
12762       /* Add the new channel interface to the sorted channel interface list. */
12763       dahdi_iflist_insert(tmp);
12764    }
12765    return tmp;
12766 }
12767 
12768 static int is_group_or_channel_match(struct dahdi_pvt *p, int span, ast_group_t groupmatch, int *groupmatched, int channelmatch, int *channelmatched)
12769 {
12770 #if defined(HAVE_PRI)
12771    if (0 < span) {
12772       /* The channel must be on the specified PRI span. */
12773       if (!p->pri || p->pri->span != span) {
12774          return 0;
12775       }
12776       if (!groupmatch && channelmatch == -1) {
12777          /* Match any group since it only needs to be on the PRI span. */
12778          *groupmatched = 1;
12779          return 1;
12780       }
12781    }
12782 #endif   /* defined(HAVE_PRI) */
12783    /* check group matching */
12784    if (groupmatch) {
12785       if ((p->group & groupmatch) != groupmatch)
12786          /* Doesn't match the specified group, try the next one */
12787          return 0;
12788       *groupmatched = 1;
12789    }
12790    /* Check to see if we have a channel match */
12791    if (channelmatch != -1) {
12792       if (p->channel != channelmatch)
12793          /* Doesn't match the specified channel, try the next one */
12794          return 0;
12795       *channelmatched = 1;
12796    }
12797 
12798    return 1;
12799 }
12800 
12801 static int available(struct dahdi_pvt **pvt, int is_specific_channel)
12802 {
12803    struct dahdi_pvt *p = *pvt;
12804 
12805    if (p->inalarm)
12806       return 0;
12807 
12808    if (analog_lib_handles(p->sig, p->radio, p->oprmode))
12809       return analog_available(p->sig_pvt);
12810 
12811    switch (p->sig) {
12812 #if defined(HAVE_PRI)
12813    case SIG_PRI_LIB_HANDLE_CASES:
12814       {
12815          struct sig_pri_chan *pvt_chan;
12816          int res;
12817 
12818          pvt_chan = p->sig_pvt;
12819          res = sig_pri_available(&pvt_chan, is_specific_channel);
12820          *pvt = pvt_chan->chan_pvt;
12821          return res;
12822       }
12823 #endif   /* defined(HAVE_PRI) */
12824 #if defined(HAVE_SS7)
12825    case SIG_SS7:
12826       return sig_ss7_available(p->sig_pvt);
12827 #endif   /* defined(HAVE_SS7) */
12828    default:
12829       break;
12830    }
12831 
12832    if (p->locallyblocked || p->remotelyblocked) {
12833       return 0;
12834    }
12835 
12836    /* If no owner definitely available */
12837    if (!p->owner) {
12838 #ifdef HAVE_OPENR2
12839       /* Trust MFC/R2 */
12840       if (p->mfcr2) {
12841          if (p->mfcr2call) {
12842             return 0;
12843          } else {
12844             return 1;
12845          }
12846       }
12847 #endif
12848       return 1;
12849    }
12850 
12851    return 0;
12852 }
12853 
12854 #if defined(HAVE_PRI)
12855 #if defined(HAVE_PRI_CALL_WAITING)
12856 /*!
12857  * \internal
12858  * \brief Init the private channel configuration using the span controller.
12859  * \since 1.8
12860  *
12861  * \param priv Channel to init the configuration.
12862  * \param pri sig_pri PRI control structure.
12863  *
12864  * \note Assumes the pri->lock is already obtained.
12865  *
12866  * \return Nothing
12867  */
12868 static void my_pri_init_config(void *priv, struct sig_pri_span *pri)
12869 {
12870    struct dahdi_pvt *pvt = priv;
12871 
12872    pvt->stripmsd = pri->ch_cfg.stripmsd;
12873    pvt->hidecallerid = pri->ch_cfg.hidecallerid;
12874    pvt->hidecalleridname = pri->ch_cfg.hidecalleridname;
12875    pvt->immediate = pri->ch_cfg.immediate;
12876    pvt->priexclusive = pri->ch_cfg.priexclusive;
12877    pvt->priindication_oob = pri->ch_cfg.priindication_oob;
12878    pvt->use_callerid = pri->ch_cfg.use_callerid;
12879    pvt->use_callingpres = pri->ch_cfg.use_callingpres;
12880    ast_copy_string(pvt->context, pri->ch_cfg.context, sizeof(pvt->context));
12881    ast_copy_string(pvt->mohinterpret, pri->ch_cfg.mohinterpret, sizeof(pvt->mohinterpret));
12882 }
12883 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
12884 #endif   /* defined(HAVE_PRI) */
12885 
12886 #if defined(HAVE_PRI)
12887 /*!
12888  * \internal
12889  * \brief Create a no B channel interface.
12890  * \since 1.8
12891  *
12892  * \param pri sig_pri span controller to add interface.
12893  *
12894  * \note Assumes the pri->lock is already obtained.
12895  *
12896  * \retval array-index into private pointer array on success.
12897  * \retval -1 on error.
12898  */
12899 static int dahdi_new_pri_nobch_channel(struct sig_pri_span *pri)
12900 {
12901    int pvt_idx;
12902    int res;
12903    unsigned idx;
12904    struct dahdi_pvt *pvt;
12905    struct sig_pri_chan *chan;
12906    struct dahdi_bufferinfo bi;
12907 
12908    static int nobch_channel = CHAN_PSEUDO;
12909 
12910    /* Find spot in the private pointer array for new interface. */
12911    for (pvt_idx = 0; pvt_idx < pri->numchans; ++pvt_idx) {
12912       if (!pri->pvts[pvt_idx]) {
12913          break;
12914       }
12915    }
12916    if (pri->numchans == pvt_idx) {
12917       if (ARRAY_LEN(pri->pvts) <= pvt_idx) {
12918          ast_log(LOG_ERROR, "Unable to add a no-B-channel interface!\n");
12919          return -1;
12920       }
12921 
12922       /* Add new spot to the private pointer array. */
12923       pri->pvts[pvt_idx] = NULL;
12924       ++pri->numchans;
12925    }
12926 
12927    pvt = ast_calloc(1, sizeof(*pvt));
12928    if (!pvt) {
12929       return -1;
12930    }
12931    pvt->cc_params = ast_cc_config_params_init();
12932    if (!pvt->cc_params) {
12933       ast_free(pvt);
12934       return -1;
12935    }
12936    ast_mutex_init(&pvt->lock);
12937    for (idx = 0; idx < ARRAY_LEN(pvt->subs); ++idx) {
12938       pvt->subs[idx].dfd = -1;
12939    }
12940    pvt->buf_no = dahdi_pseudo_parms.buf_no;
12941    pvt->buf_policy = dahdi_pseudo_parms.buf_policy;
12942    pvt->faxbuf_no = dahdi_pseudo_parms.faxbuf_no;
12943    pvt->faxbuf_policy = dahdi_pseudo_parms.faxbuf_policy;
12944 
12945    chan = sig_pri_chan_new(pvt, &dahdi_pri_callbacks, pri, 0, 0, 0);
12946    if (!chan) {
12947       destroy_dahdi_pvt(pvt);
12948       return -1;
12949    }
12950    chan->no_b_channel = 1;
12951 
12952    /*
12953     * Pseudo channel companding law.
12954     * Needed for outgoing call waiting calls.
12955     * XXX May need to make this determined by switchtype or user option.
12956     */
12957    pvt->law_default = DAHDI_LAW_ALAW;
12958 
12959    pvt->sig = pri->sig;
12960    pvt->outsigmod = -1;
12961    pvt->pri = pri;
12962    pvt->sig_pvt = chan;
12963    pri->pvts[pvt_idx] = chan;
12964 
12965    pvt->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo");
12966    if (pvt->subs[SUB_REAL].dfd < 0) {
12967       ast_log(LOG_ERROR, "Unable to open no B channel interface pseudo channel: %s\n",
12968          strerror(errno));
12969       destroy_dahdi_pvt(pvt);
12970       return -1;
12971    }
12972    memset(&bi, 0, sizeof(bi));
12973    res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
12974    if (!res) {
12975       pvt->bufsize = bi.bufsize;
12976       bi.txbufpolicy = pvt->buf_policy;
12977       bi.rxbufpolicy = pvt->buf_policy;
12978       bi.numbufs = pvt->buf_no;
12979       res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
12980       if (res < 0) {
12981          ast_log(LOG_WARNING,
12982             "Unable to set buffer policy on no B channel interface: %s\n",
12983             strerror(errno));
12984       }
12985    } else
12986       ast_log(LOG_WARNING,
12987          "Unable to check buffer policy on no B channel interface: %s\n",
12988          strerror(errno));
12989 
12990    --nobch_channel;
12991    if (CHAN_PSEUDO < nobch_channel) {
12992       nobch_channel = CHAN_PSEUDO - 1;
12993    }
12994    pvt->channel = nobch_channel;
12995    chan->channel = pvt->channel;
12996 
12997    dahdi_nobch_insert(pri, pvt);
12998 
12999    return pvt_idx;
13000 }
13001 #endif   /* defined(HAVE_PRI) */
13002 
13003 /* This function can *ONLY* be used for copying pseudo (CHAN_PSEUDO) private
13004    structures; it makes no attempt to safely copy regular channel private
13005    structures that might contain reference-counted object pointers and other
13006    scary bits
13007 */
13008 static struct dahdi_pvt *duplicate_pseudo(struct dahdi_pvt *src)
13009 {
13010    struct dahdi_pvt *p;
13011    struct dahdi_bufferinfo bi;
13012    int res;
13013 
13014    p = ast_malloc(sizeof(*p));
13015    if (!p) {
13016       return NULL;
13017    }
13018    *p = *src;
13019 
13020    /* Must deep copy the cc_params. */
13021    p->cc_params = ast_cc_config_params_init();
13022    if (!p->cc_params) {
13023       ast_free(p);
13024       return NULL;
13025    }
13026    ast_cc_copy_config_params(p->cc_params, src->cc_params);
13027 
13028    p->which_iflist = DAHDI_IFLIST_NONE;
13029    p->next = NULL;
13030    p->prev = NULL;
13031    ast_mutex_init(&p->lock);
13032    p->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo");
13033    if (p->subs[SUB_REAL].dfd < 0) {
13034       ast_log(LOG_ERROR, "Unable to dup channel: %s\n", strerror(errno));
13035       destroy_dahdi_pvt(p);
13036       return NULL;
13037    }
13038    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
13039    if (!res) {
13040       bi.txbufpolicy = src->buf_policy;
13041       bi.rxbufpolicy = src->buf_policy;
13042       bi.numbufs = src->buf_no;
13043       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
13044       if (res < 0) {
13045          ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel: %s\n", strerror(errno));
13046       }
13047    } else
13048       ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel: %s\n", strerror(errno));
13049    p->destroy = 1;
13050    dahdi_iflist_insert(p);
13051    return p;
13052 }
13053 
13054 struct dahdi_starting_point {
13055    /*! Group matching mask.  Zero if not specified. */
13056    ast_group_t groupmatch;
13057    /*! DAHDI channel to match with.  -1 if not specified. */
13058    int channelmatch;
13059    /*! Round robin saved search location index. (Valid if roundrobin TRUE) */
13060    int rr_starting_point;
13061    /*! ISDN span where channels can be picked (Zero if not specified) */
13062    int span;
13063    /*! Analog channel distinctive ring cadance index. */
13064    int cadance;
13065    /*! Dialing option. c/r/d if present and valid. */
13066    char opt;
13067    /*! TRUE if to search the channel list backwards. */
13068    char backwards;
13069    /*! TRUE if search is done with round robin sequence. */
13070    char roundrobin;
13071 };
13072 static struct dahdi_pvt *determine_starting_point(const char *data, struct dahdi_starting_point *param)
13073 {
13074    char *dest;
13075    char *s;
13076    int x;
13077    int res = 0;
13078    struct dahdi_pvt *p;
13079    char *subdir = NULL;
13080    AST_DECLARE_APP_ARGS(args,
13081       AST_APP_ARG(group);  /* channel/group token */
13082       //AST_APP_ARG(ext);  /* extension token */
13083       //AST_APP_ARG(opts); /* options token */
13084       AST_APP_ARG(other);  /* Any remining unused arguments */
13085    );
13086 
13087    /*
13088     * data is ---v
13089     * Dial(DAHDI/pseudo[/extension[/options]])
13090     * Dial(DAHDI/<channel#>[c|r<cadance#>|d][/extension[/options]])
13091     * Dial(DAHDI/<subdir>!<channel#>[c|r<cadance#>|d][/extension[/options]])
13092     * Dial(DAHDI/i<span>[/extension[/options]])
13093     * Dial(DAHDI/[i<span>-](g|G|r|R)<group#(0-63)>[c|r<cadance#>|d][/extension[/options]])
13094     *
13095     * i - ISDN span channel restriction.
13096     *     Used by CC to ensure that the CC recall goes out the same span.
13097     *     Also to make ISDN channel names dialable when the sequence number
13098     *     is stripped off.  (Used by DTMF attended transfer feature.)
13099     *
13100     * g - channel group allocation search forward
13101     * G - channel group allocation search backward
13102     * r - channel group allocation round robin search forward
13103     * R - channel group allocation round robin search backward
13104     *
13105     * c - Wait for DTMF digit to confirm answer
13106     * r<cadance#> - Set distintive ring cadance number
13107     * d - Force bearer capability for ISDN/SS7 call to digital.
13108     */
13109 
13110    if (data) {
13111       dest = ast_strdupa(data);
13112    } else {
13113       ast_log(LOG_WARNING, "Channel requested with no data\n");
13114       return NULL;
13115    }
13116    AST_NONSTANDARD_APP_ARGS(args, dest, '/');
13117    if (!args.argc || ast_strlen_zero(args.group)) {
13118       ast_log(LOG_WARNING, "No channel/group specified\n");
13119       return NULL;
13120    }
13121 
13122    /* Initialize the output parameters */
13123    memset(param, 0, sizeof(*param));
13124    param->channelmatch = -1;
13125 
13126    if (strchr(args.group, '!') != NULL) {
13127       char *prev = args.group;
13128       while ((s = strchr(prev, '!')) != NULL) {
13129          *s++ = '/';
13130          prev = s;
13131       }
13132       *(prev - 1) = '\0';
13133       subdir = args.group;
13134       args.group = prev;
13135    } else if (args.group[0] == 'i') {
13136       /* Extract the ISDN span channel restriction specifier. */
13137       res = sscanf(args.group + 1, "%30d", &x);
13138       if (res < 1) {
13139          ast_log(LOG_WARNING, "Unable to determine ISDN span for data %s\n", data);
13140          return NULL;
13141       }
13142       param->span = x;
13143 
13144       /* Remove the ISDN span channel restriction specifier. */
13145       s = strchr(args.group, '-');
13146       if (!s) {
13147          /* Search all groups since we are ISDN span restricted. */
13148          return iflist;
13149       }
13150       args.group = s + 1;
13151       res = 0;
13152    }
13153    if (toupper(args.group[0]) == 'G' || toupper(args.group[0])=='R') {
13154       /* Retrieve the group number */
13155       s = args.group + 1;
13156       res = sscanf(s, "%30d%1c%30d", &x, &param->opt, &param->cadance);
13157       if (res < 1) {
13158          ast_log(LOG_WARNING, "Unable to determine group for data %s\n", data);
13159          return NULL;
13160       }
13161       param->groupmatch = ((ast_group_t) 1 << x);
13162 
13163       if (toupper(args.group[0]) == 'G') {
13164          if (args.group[0] == 'G') {
13165             param->backwards = 1;
13166             p = ifend;
13167          } else
13168             p = iflist;
13169       } else {
13170          if (ARRAY_LEN(round_robin) <= x) {
13171             ast_log(LOG_WARNING, "Round robin index %d out of range for data %s\n",
13172                x, data);
13173             return NULL;
13174          }
13175          if (args.group[0] == 'R') {
13176             param->backwards = 1;
13177             p = round_robin[x] ? round_robin[x]->prev : ifend;
13178             if (!p)
13179                p = ifend;
13180          } else {
13181             p = round_robin[x] ? round_robin[x]->next : iflist;
13182             if (!p)
13183                p = iflist;
13184          }
13185          param->roundrobin = 1;
13186          param->rr_starting_point = x;
13187       }
13188    } else {
13189       s = args.group;
13190       if (!strcasecmp(s, "pseudo")) {
13191          /* Special case for pseudo */
13192          x = CHAN_PSEUDO;
13193          param->channelmatch = x;
13194       } else {
13195          res = sscanf(s, "%30d%1c%30d", &x, &param->opt, &param->cadance);
13196          if (res < 1) {
13197             ast_log(LOG_WARNING, "Unable to determine channel for data %s\n", data);
13198             return NULL;
13199          } else {
13200             param->channelmatch = x;
13201          }
13202       }
13203       if (subdir) {
13204          char path[PATH_MAX];
13205          struct stat stbuf;
13206 
13207          snprintf(path, sizeof(path), "/dev/dahdi/%s/%d",
13208                subdir, param->channelmatch);
13209          if (stat(path, &stbuf) < 0) {
13210             ast_log(LOG_WARNING, "stat(%s) failed: %s\n",
13211                   path, strerror(errno));
13212             return NULL;
13213          }
13214          if (!S_ISCHR(stbuf.st_mode)) {
13215             ast_log(LOG_ERROR, "%s: Not a character device file\n",
13216                   path);
13217             return NULL;
13218          }
13219          param->channelmatch = minor(stbuf.st_rdev);
13220       }
13221 
13222       p = iflist;
13223    }
13224 
13225    if (param->opt == 'r' && res < 3) {
13226       ast_log(LOG_WARNING, "Distinctive ring missing identifier in '%s'\n", data);
13227       param->opt = '\0';
13228    }
13229 
13230    return p;
13231 }
13232 
13233 static struct ast_channel *dahdi_request(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause)
13234 {
13235    int callwait = 0;
13236    struct dahdi_pvt *p;
13237    struct ast_channel *tmp = NULL;
13238    struct dahdi_pvt *exitpvt;
13239    int channelmatched = 0;
13240    int groupmatched = 0;
13241    int transcapdigital = 0;
13242    struct dahdi_starting_point start;
13243 
13244    ast_mutex_lock(&iflock);
13245    p = determine_starting_point(data, &start);
13246    if (!p) {
13247       /* We couldn't determine a starting point, which likely means badly-formatted channel name. Abort! */
13248       ast_mutex_unlock(&iflock);
13249       return NULL;
13250    }
13251 
13252    /* Search for an unowned channel */
13253    exitpvt = p;
13254    while (p && !tmp) {
13255       if (start.roundrobin)
13256          round_robin[start.rr_starting_point] = p;
13257 
13258       if (is_group_or_channel_match(p, start.span, start.groupmatch, &groupmatched, start.channelmatch, &channelmatched)
13259          && available(&p, channelmatched)) {
13260          ast_debug(1, "Using channel %d\n", p->channel);
13261 
13262          callwait = (p->owner != NULL);
13263 #ifdef HAVE_OPENR2
13264          if (p->mfcr2) {
13265             ast_mutex_lock(&p->lock);
13266             if (p->mfcr2call) {
13267                ast_mutex_unlock(&p->lock);
13268                ast_log(LOG_DEBUG, "Yay!, someone just beat us in the race for channel %d.\n", p->channel);
13269                goto next;
13270             }
13271             p->mfcr2call = 1;
13272             ast_mutex_unlock(&p->lock);
13273          }
13274 #endif
13275          if (p->channel == CHAN_PSEUDO) {
13276             p = duplicate_pseudo(p);
13277             if (!p) {
13278                break;
13279             }
13280          }
13281 
13282          /* Make special notes */
13283          switch (start.opt) {
13284          case '\0':
13285             /* No option present. */
13286             break;
13287          case 'c':
13288             /* Confirm answer */
13289             p->confirmanswer = 1;
13290             break;
13291          case 'r':
13292             /* Distinctive ring */
13293             p->distinctivering = start.cadance;
13294             break;
13295          case 'd':
13296             /* If this is an ISDN call, make it digital */
13297             transcapdigital = AST_TRANS_CAP_DIGITAL;
13298             break;
13299          default:
13300             ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", start.opt, (char *)data);
13301             break;
13302          }
13303 
13304          p->outgoing = 1;
13305          if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
13306             tmp = analog_request(p->sig_pvt, &callwait, requestor);
13307 #ifdef HAVE_PRI
13308          } else if (dahdi_sig_pri_lib_handles(p->sig)) {
13309             sig_pri_extract_called_num_subaddr(p->sig_pvt, data, p->dnid,
13310                sizeof(p->dnid));
13311             tmp = sig_pri_request(p->sig_pvt, SIG_PRI_DEFLAW, requestor, transcapdigital);
13312 #endif
13313 #if defined(HAVE_SS7)
13314          } else if (p->sig == SIG_SS7) {
13315             tmp = sig_ss7_request(p->sig_pvt, SIG_SS7_DEFLAW, requestor, transcapdigital);
13316 #endif   /* defined(HAVE_SS7) */
13317          } else {
13318             tmp = dahdi_new(p, AST_STATE_RESERVED, 0, p->owner ? SUB_CALLWAIT : SUB_REAL, 0, requestor ? requestor->linkedid : "");
13319          }
13320          if (!tmp) {
13321             p->outgoing = 0;
13322 #if defined(HAVE_PRI)
13323 #if defined(HAVE_PRI_CALL_WAITING)
13324             switch (p->sig) {
13325             case SIG_PRI_LIB_HANDLE_CASES:
13326                if (((struct sig_pri_chan *) p->sig_pvt)->is_call_waiting) {
13327                   ((struct sig_pri_chan *) p->sig_pvt)->is_call_waiting = 0;
13328                   ast_atomic_fetchadd_int(&p->pri->num_call_waiting_calls, -1);
13329                }
13330                break;
13331             default:
13332                break;
13333             }
13334 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
13335 #endif   /* defined(HAVE_PRI) */
13336          } else {
13337             snprintf(p->dialstring, sizeof(p->dialstring), "DAHDI/%s", (char *) data);
13338          }
13339          break;
13340       }
13341 #ifdef HAVE_OPENR2
13342 next:
13343 #endif
13344       if (start.backwards) {
13345          p = p->prev;
13346          if (!p)
13347             p = ifend;
13348       } else {
13349          p = p->next;
13350          if (!p)
13351             p = iflist;
13352       }
13353       /* stop when you roll to the one that we started from */
13354       if (p == exitpvt)
13355          break;
13356    }
13357    ast_mutex_unlock(&iflock);
13358    restart_monitor();
13359    if (cause && !tmp) {
13360       if (callwait || channelmatched) {
13361          *cause = AST_CAUSE_BUSY;
13362       } else if (groupmatched) {
13363          *cause = AST_CAUSE_CONGESTION;
13364       } else {
13365          /*
13366           * We did not match any channel requested.
13367           * Dialplan error requesting non-existant channel?
13368           */
13369       }
13370    }
13371 
13372    return tmp;
13373 }
13374 
13375 /*!
13376  * \internal
13377  * \brief Determine the device state for a given DAHDI device if we can.
13378  * \since 1.8
13379  *
13380  * \param data DAHDI device name after "DAHDI/".
13381  *
13382  * \retval device_state enum ast_device_state value.
13383  * \retval AST_DEVICE_UNKNOWN if we could not determine the device's state.
13384  */
13385 static int dahdi_devicestate(void *data)
13386 {
13387 #if defined(HAVE_PRI)
13388    char *device;
13389    unsigned span;
13390    int res;
13391 
13392    device = data;
13393 
13394    if (*device != 'I') {
13395       /* The request is not for an ISDN span device. */
13396       return AST_DEVICE_UNKNOWN;
13397    }
13398    res = sscanf(device, "I%30u", &span);
13399    if (res != 1 || !span || NUM_SPANS < span) {
13400       /* Bad format for ISDN span device name. */
13401       return AST_DEVICE_UNKNOWN;
13402    }
13403    device = strchr(device, '/');
13404    if (!device) {
13405       /* Bad format for ISDN span device name. */
13406       return AST_DEVICE_UNKNOWN;
13407    }
13408 
13409    /*
13410     * Since there are currently no other span devstate's defined,
13411     * it must be congestion.
13412     */
13413 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
13414    ++device;
13415    if (!strcmp(device, "congestion"))
13416 #endif   /* defined(THRESHOLD_DEVSTATE_PLACEHOLDER) */
13417    {
13418       return pris[span - 1].pri.congestion_devstate;
13419    }
13420 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
13421    else if (!strcmp(device, "threshold")) {
13422       return pris[span - 1].pri.threshold_devstate;
13423    }
13424    return AST_DEVICE_UNKNOWN;
13425 #endif   /* defined(THRESHOLD_DEVSTATE_PLACEHOLDER) */
13426 #else
13427    return AST_DEVICE_UNKNOWN;
13428 #endif   /* defined(HAVE_PRI) */
13429 }
13430 
13431 /*!
13432  * \brief Callback made when dial failed to get a channel out of dahdi_request().
13433  * \since 1.8
13434  *
13435  * \param inbound Incoming asterisk channel.
13436  * \param dest Same dial string passed to dahdi_request().
13437  * \param callback Callback into CC core to announce a busy channel available for CC.
13438  *
13439  * \details
13440  * This callback acts like a forked dial with all prongs of the fork busy.
13441  * Essentially, for each channel that could have taken the call, indicate that
13442  * it is busy.
13443  *
13444  * \retval 0 on success.
13445  * \retval -1 on error.
13446  */
13447 static int dahdi_cc_callback(struct ast_channel *inbound, const char *dest, ast_cc_callback_fn callback)
13448 {
13449    struct dahdi_pvt *p;
13450    struct dahdi_pvt *exitpvt;
13451    struct dahdi_starting_point start;
13452    int groupmatched = 0;
13453    int channelmatched = 0;
13454 
13455    ast_mutex_lock(&iflock);
13456    p = determine_starting_point(dest, &start);
13457    if (!p) {
13458       ast_mutex_unlock(&iflock);
13459       return -1;
13460    }
13461    exitpvt = p;
13462    for (;;) {
13463       if (is_group_or_channel_match(p, start.span, start.groupmatch, &groupmatched, start.channelmatch, &channelmatched)) {
13464          /* We found a potential match. call the callback */
13465          struct ast_str *device_name;
13466          char *dash;
13467          const char *monitor_type;
13468          char dialstring[AST_CHANNEL_NAME];
13469          char full_device_name[AST_CHANNEL_NAME];
13470 
13471          switch (ast_get_cc_monitor_policy(p->cc_params)) {
13472          case AST_CC_MONITOR_NEVER:
13473             break;
13474          case AST_CC_MONITOR_NATIVE:
13475          case AST_CC_MONITOR_ALWAYS:
13476          case AST_CC_MONITOR_GENERIC:
13477 #if defined(HAVE_PRI)
13478             if (dahdi_sig_pri_lib_handles(p->sig)) {
13479                /*
13480                 * ISDN is in a trunk busy condition so we need to monitor
13481                 * the span congestion device state.
13482                 */
13483                snprintf(full_device_name, sizeof(full_device_name),
13484                   "DAHDI/I%d/congestion", p->pri->span);
13485             } else
13486 #endif   /* defined(HAVE_PRI) */
13487             {
13488 #if defined(HAVE_PRI)
13489                device_name = create_channel_name(p, 1, "");
13490 #else
13491                device_name = create_channel_name(p);
13492 #endif   /* defined(HAVE_PRI) */
13493                snprintf(full_device_name, sizeof(full_device_name), "DAHDI/%s",
13494                   device_name ? ast_str_buffer(device_name) : "");
13495                ast_free(device_name);
13496                /*
13497                 * The portion after the '-' in the channel name is either a random
13498                 * number, a sequence number, or a subchannel number. None are
13499                 * necessary so strip them off.
13500                 */
13501                dash = strrchr(full_device_name, '-');
13502                if (dash) {
13503                   *dash = '\0';
13504                }
13505             }
13506             snprintf(dialstring, sizeof(dialstring), "DAHDI/%s", dest);
13507 
13508             /*
13509              * Analog can only do generic monitoring.
13510              * ISDN is in a trunk busy condition and any "device" is going
13511              * to be busy until a B channel becomes available.  The generic
13512              * monitor can do this task.
13513              */
13514             monitor_type = AST_CC_GENERIC_MONITOR_TYPE;
13515             callback(inbound,
13516 #if defined(HAVE_PRI)
13517                p->pri ? p->pri->cc_params : p->cc_params,
13518 #else
13519                p->cc_params,
13520 #endif   /* defined(HAVE_PRI) */
13521                monitor_type, full_device_name, dialstring, NULL);
13522             break;
13523          }
13524       }
13525       p = start.backwards ? p->prev : p->next;
13526       if (!p) {
13527          p = start.backwards ? ifend : iflist;
13528       }
13529       if (p == exitpvt) {
13530          break;
13531       }
13532    }
13533    ast_mutex_unlock(&iflock);
13534    return 0;
13535 }
13536 
13537 #if defined(HAVE_SS7)
13538 static void dahdi_ss7_message(struct ss7 *ss7, char *s)
13539 {
13540    int i;
13541 
13542    if (ss7) {
13543       for (i = 0; i < NUM_SPANS; i++) {
13544          if (linksets[i].ss7.ss7 == ss7) {
13545             ast_verbose("[%d] %s", i + 1, s);
13546             return;
13547          }
13548       }
13549    }
13550    ast_verbose("%s", s);
13551 }
13552 #endif   /* defined(HAVE_SS7) */
13553 
13554 #if defined(HAVE_SS7)
13555 static void dahdi_ss7_error(struct ss7 *ss7, char *s)
13556 {
13557    int i;
13558 
13559    if (ss7) {
13560       for (i = 0; i < NUM_SPANS; i++) {
13561          if (linksets[i].ss7.ss7 == ss7) {
13562             ast_log(LOG_ERROR, "[%d] %s", i + 1, s);
13563             return;
13564          }
13565       }
13566    }
13567    ast_log(LOG_ERROR, "%s", s);
13568 }
13569 #endif   /* defined(HAVE_SS7) */
13570 
13571 #if defined(HAVE_OPENR2)
13572 static void *mfcr2_monitor(void *data)
13573 {
13574    struct dahdi_mfcr2 *mfcr2 = data;
13575    /* we should be using pthread_key_create
13576       and allocate pollers dynamically.
13577       I think do_monitor() could be leaking, since it
13578       could be cancelled at any time and is not
13579       using thread keys, why?, */
13580    struct pollfd pollers[ARRAY_LEN(mfcr2->pvts)];
13581    int res = 0;
13582    int i = 0;
13583    int oldstate = 0;
13584    int quit_loop = 0;
13585    int maxsleep = 20;
13586    int was_idle = 0;
13587    int pollsize = 0;
13588    /* now that we're ready to get calls, unblock our side and
13589       get current line state */
13590    for (i = 0; i < mfcr2->numchans; i++) {
13591       openr2_chan_set_idle(mfcr2->pvts[i]->r2chan);
13592       openr2_chan_handle_cas(mfcr2->pvts[i]->r2chan);
13593    }
13594    while (1) {
13595       /* we trust here that the mfcr2 channel list will not ever change once
13596          the module is loaded */
13597       pollsize = 0;
13598       for (i = 0; i < mfcr2->numchans; i++) {
13599          pollers[i].revents = 0;
13600          pollers[i].events = 0;
13601          if (mfcr2->pvts[i]->owner) {
13602             continue;
13603          }
13604          if (!mfcr2->pvts[i]->r2chan) {
13605             ast_log(LOG_DEBUG, "Wow, no r2chan on channel %d\n", mfcr2->pvts[i]->channel);
13606             quit_loop = 1;
13607             break;
13608          }
13609          openr2_chan_enable_read(mfcr2->pvts[i]->r2chan);
13610          pollers[i].events = POLLIN | POLLPRI;
13611          pollers[i].fd = mfcr2->pvts[i]->subs[SUB_REAL].dfd;
13612          pollsize++;
13613       }
13614       if (quit_loop) {
13615          break;
13616       }
13617       if (pollsize == 0) {
13618          if (!was_idle) {
13619             ast_log(LOG_DEBUG, "Monitor thread going idle since everybody has an owner\n");
13620             was_idle = 1;
13621          }
13622          poll(NULL, 0, maxsleep);
13623          continue;
13624       }
13625       was_idle = 0;
13626       /* probably poll() is a valid cancel point, lets just be on the safe side
13627          by calling pthread_testcancel */
13628       pthread_testcancel();
13629       res = poll(pollers, mfcr2->numchans, maxsleep);
13630       pthread_testcancel();
13631       if ((res < 0) && (errno != EINTR)) {
13632          ast_log(LOG_ERROR, "going out, poll failed: %s\n", strerror(errno));
13633          break;
13634       }
13635       /* do we want to allow to cancel while processing events? */
13636       pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate);
13637       for (i = 0; i < mfcr2->numchans; i++) {
13638          if (pollers[i].revents & POLLPRI || pollers[i].revents & POLLIN) {
13639             openr2_chan_process_event(mfcr2->pvts[i]->r2chan);
13640          }
13641       }
13642       pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
13643    }
13644    ast_log(LOG_NOTICE, "Quitting MFC/R2 monitor thread\n");
13645    return 0;
13646 }
13647 #endif /* HAVE_OPENR2 */
13648 
13649 #if defined(HAVE_PRI)
13650 #ifndef PRI_RESTART
13651 #error "Upgrade your libpri"
13652 #endif
13653 static void dahdi_pri_message(struct pri *pri, char *s)
13654 {
13655    int x, y;
13656    int dchan = -1, span = -1, dchancount = 0;
13657 
13658    if (pri) {
13659       for (x = 0; x < NUM_SPANS; x++) {
13660          for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
13661             if (pris[x].pri.dchans[y])
13662                dchancount++;
13663 
13664             if (pris[x].pri.dchans[y] == pri)
13665                dchan = y;
13666          }
13667          if (dchan >= 0) {
13668             span = x;
13669             break;
13670          }
13671          dchancount = 0;
13672       }
13673       if (dchancount > 1 && (span > -1))
13674          ast_verbose("[Span %d D-Channel %d]%s", span, dchan, s);
13675       else if (span > -1)
13676          ast_verbose("%d %s", span+1, s);
13677       else
13678          ast_verbose("%s", s);
13679    } else
13680       ast_verbose("%s", s);
13681 
13682    ast_mutex_lock(&pridebugfdlock);
13683 
13684    if (pridebugfd >= 0) {
13685       if (write(pridebugfd, s, strlen(s)) < 0) {
13686          ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
13687       }
13688    }
13689 
13690    ast_mutex_unlock(&pridebugfdlock);
13691 }
13692 #endif   /* defined(HAVE_PRI) */
13693 
13694 #if defined(HAVE_PRI)
13695 static void dahdi_pri_error(struct pri *pri, char *s)
13696 {
13697    int x, y;
13698    int dchan = -1, span = -1;
13699    int dchancount = 0;
13700 
13701    if (pri) {
13702       for (x = 0; x < NUM_SPANS; x++) {
13703          for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
13704             if (pris[x].pri.dchans[y])
13705                dchancount++;
13706 
13707             if (pris[x].pri.dchans[y] == pri)
13708                dchan = y;
13709          }
13710          if (dchan >= 0) {
13711             span = x;
13712             break;
13713          }
13714          dchancount = 0;
13715       }
13716       if ((dchancount > 1) && (span > -1))
13717          ast_log(LOG_ERROR, "[Span %d D-Channel %d] PRI: %s", span, dchan, s);
13718       else if (span > -1)
13719          ast_log(LOG_ERROR, "%d %s", span+1, s);
13720       else
13721          ast_log(LOG_ERROR, "%s", s);
13722    } else
13723       ast_log(LOG_ERROR, "%s", s);
13724 
13725    ast_mutex_lock(&pridebugfdlock);
13726 
13727    if (pridebugfd >= 0) {
13728       if (write(pridebugfd, s, strlen(s)) < 0) {
13729          ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
13730       }
13731    }
13732 
13733    ast_mutex_unlock(&pridebugfdlock);
13734 }
13735 #endif   /* defined(HAVE_PRI) */
13736 
13737 #if defined(HAVE_PRI)
13738 static int prepare_pri(struct dahdi_pri *pri)
13739 {
13740    int i, res, x;
13741    struct dahdi_params p;
13742    struct dahdi_bufferinfo bi;
13743    struct dahdi_spaninfo si;
13744 
13745    pri->pri.calls = &dahdi_pri_callbacks;
13746 
13747    for (i = 0; i < SIG_PRI_NUM_DCHANS; i++) {
13748       if (!pri->dchannels[i])
13749          break;
13750       pri->pri.fds[i] = open("/dev/dahdi/channel", O_RDWR);
13751       x = pri->dchannels[i];
13752       if ((pri->pri.fds[i] < 0) || (ioctl(pri->pri.fds[i],DAHDI_SPECIFY,&x) == -1)) {
13753          ast_log(LOG_ERROR, "Unable to open D-channel %d (%s)\n", x, strerror(errno));
13754          return -1;
13755       }
13756       memset(&p, 0, sizeof(p));
13757       res = ioctl(pri->pri.fds[i], DAHDI_GET_PARAMS, &p);
13758       if (res) {
13759          dahdi_close_pri_fd(pri, i);
13760          ast_log(LOG_ERROR, "Unable to get parameters for D-channel %d (%s)\n", x, strerror(errno));
13761          return -1;
13762       }
13763       if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC)) {
13764          dahdi_close_pri_fd(pri, i);
13765          ast_log(LOG_ERROR, "D-channel %d is not in HDLC/FCS mode.\n", x);
13766          return -1;
13767       }
13768       memset(&si, 0, sizeof(si));
13769       res = ioctl(pri->pri.fds[i], DAHDI_SPANSTAT, &si);
13770       if (res) {
13771          dahdi_close_pri_fd(pri, i);
13772          ast_log(LOG_ERROR, "Unable to get span state for D-channel %d (%s)\n", x, strerror(errno));
13773       }
13774       if (!si.alarms) {
13775          pri_event_noalarm(&pri->pri, i, 1);
13776       } else {
13777          pri_event_alarm(&pri->pri, i, 1);
13778       }
13779       memset(&bi, 0, sizeof(bi));
13780       bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
13781       bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
13782       bi.numbufs = 32;
13783       bi.bufsize = 1024;
13784       if (ioctl(pri->pri.fds[i], DAHDI_SET_BUFINFO, &bi)) {
13785          ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", x, strerror(errno));
13786          dahdi_close_pri_fd(pri, i);
13787          return -1;
13788       }
13789       pri->pri.dchan_logical_span[i] = pris[p.spanno - 1].prilogicalspan;
13790    }
13791    return 0;
13792 }
13793 #endif   /* defined(HAVE_PRI) */
13794 
13795 #if defined(HAVE_PRI)
13796 static char *complete_span_helper(const char *line, const char *word, int pos, int state, int rpos)
13797 {
13798    int which, span;
13799    char *ret = NULL;
13800 
13801    if (pos != rpos)
13802       return ret;
13803 
13804    for (which = span = 0; span < NUM_SPANS; span++) {
13805       if (pris[span].pri.pri && ++which > state) {
13806          if (asprintf(&ret, "%d", span + 1) < 0) { /* user indexes start from 1 */
13807             ast_log(LOG_WARNING, "asprintf() failed: %s\n", strerror(errno));
13808          }
13809          break;
13810       }
13811    }
13812    return ret;
13813 }
13814 #endif   /* defined(HAVE_PRI) */
13815 
13816 #if defined(HAVE_PRI)
13817 static char *complete_span_4(const char *line, const char *word, int pos, int state)
13818 {
13819    return complete_span_helper(line,word,pos,state,3);
13820 }
13821 #endif   /* defined(HAVE_PRI) */
13822 
13823 #if defined(HAVE_PRI)
13824 static char *handle_pri_set_debug_file(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13825 {
13826    int myfd;
13827    switch (cmd) {
13828    case CLI_INIT:
13829       e->command = "pri set debug file";
13830       e->usage = "Usage: pri set debug file [output-file]\n"
13831          "       Sends PRI debug output to the specified output file\n";
13832       return NULL;
13833    case CLI_GENERATE:
13834       return NULL;
13835    }
13836    if (a->argc < 5)
13837       return CLI_SHOWUSAGE;
13838 
13839    if (ast_strlen_zero(a->argv[4]))
13840       return CLI_SHOWUSAGE;
13841 
13842    myfd = open(a->argv[4], O_CREAT|O_WRONLY, AST_FILE_MODE);
13843    if (myfd < 0) {
13844       ast_cli(a->fd, "Unable to open '%s' for writing\n", a->argv[4]);
13845       return CLI_SUCCESS;
13846    }
13847 
13848    ast_mutex_lock(&pridebugfdlock);
13849 
13850    if (pridebugfd >= 0)
13851       close(pridebugfd);
13852 
13853    pridebugfd = myfd;
13854    ast_copy_string(pridebugfilename,a->argv[4],sizeof(pridebugfilename));
13855    ast_mutex_unlock(&pridebugfdlock);
13856    ast_cli(a->fd, "PRI debug output will be sent to '%s'\n", a->argv[4]);
13857    return CLI_SUCCESS;
13858 }
13859 #endif   /* defined(HAVE_PRI) */
13860 
13861 #if defined(HAVE_PRI)
13862 static char *handle_pri_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13863 {
13864    int span;
13865    int x;
13866    int level = 0;
13867    switch (cmd) {
13868    case CLI_INIT:
13869       e->command = "pri set debug {on|off|0|1|2} span";
13870       e->usage =
13871          "Usage: pri set debug {<level>|on|off} span <span>\n"
13872          "       Enables debugging on a given PRI span\n";
13873       return NULL;
13874    case CLI_GENERATE:
13875       return complete_span_4(a->line, a->word, a->pos, a->n);
13876    }
13877    if (a->argc < 6) {
13878       return CLI_SHOWUSAGE;
13879    }
13880 
13881    if (!strcasecmp(a->argv[3], "on")) {
13882       level = 1;
13883    } else if (!strcasecmp(a->argv[3], "off")) {
13884       level = 0;
13885    } else {
13886       level = atoi(a->argv[3]);
13887    }
13888    span = atoi(a->argv[5]);
13889    if ((span < 1) || (span > NUM_SPANS)) {
13890       ast_cli(a->fd, "Invalid span %s.  Should be a number %d to %d\n", a->argv[5], 1, NUM_SPANS);
13891       return CLI_SUCCESS;
13892    }
13893    if (!pris[span-1].pri.pri) {
13894       ast_cli(a->fd, "No PRI running on span %d\n", span);
13895       return CLI_SUCCESS;
13896    }
13897 
13898    /* Set debug level in libpri */
13899    for (x = 0; x < SIG_PRI_NUM_DCHANS; x++) {
13900       if (pris[span - 1].pri.dchans[x]) {
13901          switch (level) {
13902          case 0:
13903             pri_set_debug(pris[span - 1].pri.dchans[x], 0);
13904             break;
13905          case 1:
13906             pri_set_debug(pris[span - 1].pri.dchans[x], SIG_PRI_DEBUG_NORMAL);
13907             break;
13908          default:
13909             pri_set_debug(pris[span - 1].pri.dchans[x], SIG_PRI_DEBUG_INTENSE);
13910             break;
13911          }
13912       }
13913    }
13914    if (level == 0) {
13915       /* Close the debugging file if it's set */
13916       ast_mutex_lock(&pridebugfdlock);
13917       if (0 <= pridebugfd) {
13918          close(pridebugfd);
13919          pridebugfd = -1;
13920          ast_cli(a->fd, "Disabled PRI debug output to file '%s'\n",
13921             pridebugfilename);
13922       }
13923       ast_mutex_unlock(&pridebugfdlock);
13924    }
13925    pris[span - 1].pri.debug = (level) ? 1 : 0;
13926    ast_cli(a->fd, "%s debugging on span %d\n", (level) ? "Enabled" : "Disabled", span);
13927    return CLI_SUCCESS;
13928 }
13929 #endif   /* defined(HAVE_PRI) */
13930 
13931 #if defined(HAVE_PRI_SERVICE_MESSAGES)
13932 static char *handle_pri_service_generic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a, int changestatus)
13933 {
13934    unsigned *why;
13935    int channel;
13936    int trunkgroup;
13937    int x, y, fd = a->fd;
13938    int interfaceid = 0;
13939    char *c;
13940    char db_chan_name[20], db_answer[5];
13941    struct dahdi_pvt *tmp;
13942    struct dahdi_pri *pri;
13943 
13944    if (a->argc < 5 || a->argc > 6)
13945       return CLI_SHOWUSAGE;
13946    if ((c = strchr(a->argv[4], ':'))) {
13947       if (sscanf(a->argv[4], "%30d:%30d", &trunkgroup, &channel) != 2)
13948          return CLI_SHOWUSAGE;
13949       if ((trunkgroup < 1) || (channel < 1))
13950          return CLI_SHOWUSAGE;
13951       pri = NULL;
13952       for (x=0;x<NUM_SPANS;x++) {
13953          if (pris[x].pri.trunkgroup == trunkgroup) {
13954             pri = pris + x;
13955             break;
13956          }
13957       }
13958       if (!pri) {
13959          ast_cli(fd, "No such trunk group %d\n", trunkgroup);
13960          return CLI_FAILURE;
13961       }
13962    } else
13963       channel = atoi(a->argv[4]);
13964 
13965    if (a->argc == 6)
13966       interfaceid = atoi(a->argv[5]);
13967 
13968    /* either servicing a D-Channel */
13969    for (x = 0; x < NUM_SPANS; x++) {
13970       for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
13971          if (pris[x].dchannels[y] == channel) {
13972             pri = pris + x;
13973             if (pri->pri.enable_service_message_support) {
13974                ast_mutex_lock(&pri->pri.lock);
13975                pri_maintenance_service(pri->pri.pri, interfaceid, -1, changestatus);
13976                ast_mutex_unlock(&pri->pri.lock);
13977             } else {
13978                ast_cli(fd,
13979                   "\n\tThis operation has not been enabled in chan_dahdi.conf, set 'service_message_support=yes' to use this operation.\n"
13980                   "\tNote only 4ESS, 5ESS, and NI2 switch types are supported.\n\n");
13981             }
13982             return CLI_SUCCESS;
13983          }
13984       }
13985    }
13986 
13987    /* or servicing a B-Channel */
13988    ast_mutex_lock(&iflock);
13989    for (tmp = iflist; tmp; tmp = tmp->next) {
13990       if (tmp->pri && tmp->channel == channel) {
13991          ast_mutex_unlock(&iflock);
13992          ast_mutex_lock(&tmp->pri->lock);
13993          if (!tmp->pri->enable_service_message_support) {
13994             ast_mutex_unlock(&tmp->pri->lock);
13995             ast_cli(fd,
13996                "\n\tThis operation has not been enabled in chan_dahdi.conf, set 'service_message_support=yes' to use this operation.\n"
13997                "\tNote only 4ESS, 5ESS, and NI2 switch types are supported.\n\n");
13998             return CLI_SUCCESS;
13999          }
14000          snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, tmp->span, channel);
14001          why = &((struct sig_pri_chan *) tmp->sig_pvt)->service_status;
14002          switch(changestatus) {
14003          case 0: /* enable */
14004             /* Near end wants to be in service now. */
14005             ast_db_del(db_chan_name, SRVST_DBKEY);
14006             *why &= ~SRVST_NEAREND;
14007             if (*why) {
14008                snprintf(db_answer, sizeof(db_answer), "%s:%u", SRVST_TYPE_OOS, *why);
14009                ast_db_put(db_chan_name, SRVST_DBKEY, db_answer);
14010             } else {
14011                dahdi_pri_update_span_devstate(tmp->pri);
14012             }
14013             break;
14014          /* case 1:  -- loop */
14015          case 2: /* disable */
14016             /* Near end wants to be out-of-service now. */
14017             ast_db_del(db_chan_name, SRVST_DBKEY);
14018             *why |= SRVST_NEAREND;
14019             snprintf(db_answer, sizeof(db_answer), "%s:%u", SRVST_TYPE_OOS, *why);
14020             ast_db_put(db_chan_name, SRVST_DBKEY, db_answer);
14021             dahdi_pri_update_span_devstate(tmp->pri);
14022             break;
14023          /* case 3:  -- continuity */
14024          /* case 4:  -- shutdown */
14025          default:
14026             ast_log(LOG_WARNING, "Unsupported changestatus: '%d'\n", changestatus);
14027             break;
14028          }
14029          pri_maintenance_bservice(tmp->pri->pri, tmp->sig_pvt, changestatus);
14030          ast_mutex_unlock(&tmp->pri->lock);
14031          return CLI_SUCCESS;
14032       }
14033    }
14034    ast_mutex_unlock(&iflock);
14035 
14036    ast_cli(fd, "Unable to find given channel %d, possibly not a PRI\n", channel);
14037    return CLI_FAILURE;
14038 }
14039 
14040 static char *handle_pri_service_enable_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14041 {
14042    switch (cmd) {
14043    case CLI_INIT:
14044       e->command = "pri service enable channel";
14045       e->usage =
14046          "Usage: pri service enable channel <channel> [<interface id>]\n"
14047          "       Send an AT&T / NFAS / CCS ANSI T1.607 maintenance message\n"
14048          "  to restore a channel to service, with optional interface id\n"
14049          "  as agreed upon with remote switch operator\n";
14050       return NULL;
14051    case CLI_GENERATE:
14052       return NULL;
14053    }
14054    return handle_pri_service_generic(e, cmd, a, 0);
14055 }
14056 
14057 static char *handle_pri_service_disable_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14058 {
14059    switch (cmd) {
14060    case CLI_INIT:
14061       e->command = "pri service disable channel";
14062       e->usage =
14063          "Usage: pri service disable channel <chan num> [<interface id>]\n"
14064          "  Send an AT&T / NFAS / CCS ANSI T1.607 maintenance message\n"
14065          "  to remove a channel from service, with optional interface id\n"
14066          "  as agreed upon with remote switch operator\n";
14067       return NULL;
14068    case CLI_GENERATE:
14069       return NULL;
14070    }
14071    return handle_pri_service_generic(e, cmd, a, 2);
14072 }
14073 #endif   /* defined(HAVE_PRI_SERVICE_MESSAGES) */
14074 
14075 #if defined(HAVE_PRI)
14076 static char *handle_pri_show_spans(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14077 {
14078    int span;
14079 
14080    switch (cmd) {
14081    case CLI_INIT:
14082       e->command = "pri show spans";
14083       e->usage =
14084          "Usage: pri show spans\n"
14085          "       Displays PRI Information\n";
14086       return NULL;
14087    case CLI_GENERATE:
14088       return NULL;
14089    }
14090 
14091    if (a->argc != 3)
14092       return CLI_SHOWUSAGE;
14093 
14094    for (span = 0; span < NUM_SPANS; span++) {
14095       if (pris[span].pri.pri) {
14096          sig_pri_cli_show_spans(a->fd, span + 1, &pris[span].pri);
14097       }
14098    }
14099    return CLI_SUCCESS;
14100 }
14101 #endif   /* defined(HAVE_PRI) */
14102 
14103 #if defined(HAVE_PRI)
14104 static char *handle_pri_show_span(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14105 {
14106    int span;
14107 
14108    switch (cmd) {
14109    case CLI_INIT:
14110       e->command = "pri show span";
14111       e->usage =
14112          "Usage: pri show span <span>\n"
14113          "       Displays PRI Information on a given PRI span\n";
14114       return NULL;
14115    case CLI_GENERATE:
14116       return complete_span_4(a->line, a->word, a->pos, a->n);
14117    }
14118 
14119    if (a->argc < 4)
14120       return CLI_SHOWUSAGE;
14121    span = atoi(a->argv[3]);
14122    if ((span < 1) || (span > NUM_SPANS)) {
14123       ast_cli(a->fd, "Invalid span '%s'.  Should be a number from %d to %d\n", a->argv[3], 1, NUM_SPANS);
14124       return CLI_SUCCESS;
14125    }
14126    if (!pris[span-1].pri.pri) {
14127       ast_cli(a->fd, "No PRI running on span %d\n", span);
14128       return CLI_SUCCESS;
14129    }
14130 
14131    sig_pri_cli_show_span(a->fd, pris[span-1].dchannels, &pris[span-1].pri);
14132 
14133    return CLI_SUCCESS;
14134 }
14135 #endif   /* defined(HAVE_PRI) */
14136 
14137 #if defined(HAVE_PRI)
14138 static char *handle_pri_show_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14139 {
14140    int x;
14141    int span;
14142    int count=0;
14143    int debug;
14144 
14145    switch (cmd) {
14146    case CLI_INIT:
14147       e->command = "pri show debug";
14148       e->usage =
14149          "Usage: pri show debug\n"
14150          "  Show the debug state of pri spans\n";
14151       return NULL;
14152    case CLI_GENERATE:
14153       return NULL;
14154    }
14155 
14156    for (span = 0; span < NUM_SPANS; span++) {
14157       if (pris[span].pri.pri) {
14158          for (x = 0; x < SIG_PRI_NUM_DCHANS; x++) {
14159             if (pris[span].pri.dchans[x]) {
14160                debug = pri_get_debug(pris[span].pri.dchans[x]);
14161                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" );
14162                count++;
14163             }
14164          }
14165       }
14166 
14167    }
14168    ast_mutex_lock(&pridebugfdlock);
14169    if (pridebugfd >= 0)
14170       ast_cli(a->fd, "Logging PRI debug to file %s\n", pridebugfilename);
14171    ast_mutex_unlock(&pridebugfdlock);
14172 
14173    if (!count)
14174       ast_cli(a->fd, "No PRI running\n");
14175    return CLI_SUCCESS;
14176 }
14177 #endif   /* defined(HAVE_PRI) */
14178 
14179 #if defined(HAVE_PRI)
14180 static char *handle_pri_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14181 {
14182    switch (cmd) {
14183    case CLI_INIT:
14184       e->command = "pri show version";
14185       e->usage =
14186          "Usage: pri show version\n"
14187          "Show libpri version information\n";
14188       return NULL;
14189    case CLI_GENERATE:
14190       return NULL;
14191    }
14192 
14193    ast_cli(a->fd, "libpri version: %s\n", pri_get_version());
14194 
14195    return CLI_SUCCESS;
14196 }
14197 #endif   /* defined(HAVE_PRI) */
14198 
14199 #if defined(HAVE_PRI)
14200 static struct ast_cli_entry dahdi_pri_cli[] = {
14201    AST_CLI_DEFINE(handle_pri_debug, "Enables PRI debugging on a span"),
14202 #if defined(HAVE_PRI_SERVICE_MESSAGES)
14203    AST_CLI_DEFINE(handle_pri_service_enable_channel, "Return a channel to service"),
14204    AST_CLI_DEFINE(handle_pri_service_disable_channel, "Remove a channel from service"),
14205 #endif   /* defined(HAVE_PRI_SERVICE_MESSAGES) */
14206    AST_CLI_DEFINE(handle_pri_show_spans, "Displays PRI Information"),
14207    AST_CLI_DEFINE(handle_pri_show_span, "Displays PRI Information"),
14208    AST_CLI_DEFINE(handle_pri_show_debug, "Displays current PRI debug settings"),
14209    AST_CLI_DEFINE(handle_pri_set_debug_file, "Sends PRI debug output to the specified file"),
14210    AST_CLI_DEFINE(handle_pri_version, "Displays libpri version"),
14211 };
14212 #endif   /* defined(HAVE_PRI) */
14213 
14214 #ifdef HAVE_OPENR2
14215 
14216 static char *handle_mfcr2_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14217 {
14218    switch (cmd) {
14219    case CLI_INIT:
14220       e->command = "mfcr2 show version";
14221       e->usage =
14222          "Usage: mfcr2 show version\n"
14223          "       Shows the version of the OpenR2 library being used.\n";
14224       return NULL;
14225    case CLI_GENERATE:
14226       return NULL;
14227    }
14228    ast_cli(a->fd, "OpenR2 version: %s, revision: %s\n", openr2_get_version(), openr2_get_revision());
14229    return CLI_SUCCESS;
14230 }
14231 
14232 static char *handle_mfcr2_show_variants(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14233 {
14234 #define FORMAT "%4s %40s\n"
14235    int i = 0;
14236    int numvariants = 0;
14237    const openr2_variant_entry_t *variants;
14238    switch (cmd) {
14239    case CLI_INIT:
14240       e->command = "mfcr2 show variants";
14241       e->usage =
14242          "Usage: mfcr2 show variants\n"
14243          "       Shows the list of MFC/R2 variants supported.\n";
14244       return NULL;
14245    case CLI_GENERATE:
14246       return NULL;
14247    }
14248    if (!(variants = openr2_proto_get_variant_list(&numvariants))) {
14249       ast_cli(a->fd, "Failed to get list of variants.\n");
14250       return CLI_FAILURE;
14251    }
14252    ast_cli(a->fd, FORMAT, "Variant Code", "Country");
14253    for (i = 0; i < numvariants; i++) {
14254       ast_cli(a->fd, FORMAT, variants[i].name, variants[i].country);
14255    }
14256    return CLI_SUCCESS;
14257 #undef FORMAT
14258 }
14259 
14260 static char *handle_mfcr2_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14261 {
14262 #define FORMAT "%4s %-7.7s %-7.7s %-8.8s %-9.9s %-16.16s %-8.8s %-8.8s\n"
14263    int filtertype = 0;
14264    int targetnum = 0;
14265    char channo[5];
14266    char anino[5];
14267    char dnisno[5];
14268    struct dahdi_pvt *p;
14269    openr2_context_t *r2context;
14270    openr2_variant_t r2variant;
14271    switch (cmd) {
14272    case CLI_INIT:
14273       e->command = "mfcr2 show channels [group|context]";
14274       e->usage =
14275          "Usage: mfcr2 show channels [group <group> | context <context>]\n"
14276          "       Shows the DAHDI channels configured with MFC/R2 signaling.\n";
14277       return NULL;
14278    case CLI_GENERATE:
14279       return NULL;
14280    }
14281    if (!((a->argc == 3) || (a->argc == 5))) {
14282       return CLI_SHOWUSAGE;
14283    }
14284    if (a->argc == 5) {
14285       if (!strcasecmp(a->argv[3], "group")) {
14286          targetnum = atoi(a->argv[4]);
14287          if ((targetnum < 0) || (targetnum > 63))
14288             return CLI_SHOWUSAGE;
14289          targetnum = 1 << targetnum;
14290          filtertype = 1;
14291       } else if (!strcasecmp(a->argv[3], "context")) {
14292          filtertype = 2;
14293       } else {
14294          return CLI_SHOWUSAGE;
14295       }
14296    }
14297    ast_cli(a->fd, FORMAT, "Chan", "Variant", "Max ANI", "Max DNIS", "ANI First", "Immediate Accept", "Tx CAS", "Rx CAS");
14298    ast_mutex_lock(&iflock);
14299    for (p = iflist; p; p = p->next) {
14300       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14301          continue;
14302       }
14303       if (filtertype) {
14304          switch(filtertype) {
14305          case 1: /* mfcr2 show channels group <group> */
14306             if (p->group != targetnum) {
14307                continue;
14308             }
14309             break;
14310          case 2: /* mfcr2 show channels context <context> */
14311             if (strcasecmp(p->context, a->argv[4])) {
14312                continue;
14313             }
14314             break;
14315          default:
14316             ;
14317          }
14318       }
14319       r2context = openr2_chan_get_context(p->r2chan);
14320       r2variant = openr2_context_get_variant(r2context);
14321       snprintf(channo, sizeof(channo), "%d", p->channel);
14322       snprintf(anino, sizeof(anino), "%d", openr2_context_get_max_ani(r2context));
14323       snprintf(dnisno, sizeof(dnisno), "%d", openr2_context_get_max_dnis(r2context));
14324       ast_cli(a->fd, FORMAT, channo, openr2_proto_get_variant_string(r2variant),
14325             anino, dnisno, openr2_context_get_ani_first(r2context) ? "Yes" : "No",
14326             openr2_context_get_immediate_accept(r2context) ? "Yes" : "No",
14327             openr2_chan_get_tx_cas_string(p->r2chan), openr2_chan_get_rx_cas_string(p->r2chan));
14328    }
14329    ast_mutex_unlock(&iflock);
14330    return CLI_SUCCESS;
14331 #undef FORMAT
14332 }
14333 
14334 static char *handle_mfcr2_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14335 {
14336    struct dahdi_pvt *p = NULL;
14337    int channo = 0;
14338    char *toklevel = NULL;
14339    char *saveptr = NULL;
14340    char *logval = NULL;
14341    openr2_log_level_t loglevel = OR2_LOG_NOTHING;
14342    openr2_log_level_t tmplevel = OR2_LOG_NOTHING;
14343    switch (cmd) {
14344    case CLI_INIT:
14345       e->command = "mfcr2 set debug";
14346       e->usage =
14347          "Usage: mfcr2 set debug <loglevel> <channel>\n"
14348          "       Set a new logging level for the specified channel.\n"
14349          "       If no channel is specified the logging level will be applied to all channels.\n";
14350       return NULL;
14351    case CLI_GENERATE:
14352       return NULL;
14353    }
14354    if (a->argc < 4) {
14355       return CLI_SHOWUSAGE;
14356    }
14357    channo = (a->argc == 5) ? atoi(a->argv[4]) : -1;
14358    logval = ast_strdupa(a->argv[3]);
14359    toklevel = strtok_r(logval, ",", &saveptr);
14360    if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
14361       ast_cli(a->fd, "Invalid MFC/R2 logging level '%s'.\n", a->argv[3]);
14362       return CLI_FAILURE;
14363    } else if (OR2_LOG_NOTHING == tmplevel) {
14364       loglevel = tmplevel;
14365    } else {
14366       loglevel |= tmplevel;
14367       while ((toklevel = strtok_r(NULL, ",", &saveptr))) {
14368          if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
14369             ast_cli(a->fd, "Ignoring invalid logging level: '%s'.\n", toklevel);
14370             continue;
14371          }
14372          loglevel |= tmplevel;
14373       }
14374    }
14375    ast_mutex_lock(&iflock);
14376    for (p = iflist; p; p = p->next) {
14377       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14378          continue;
14379       }
14380       if ((channo != -1) && (p->channel != channo )) {
14381          continue;
14382       }
14383       openr2_chan_set_log_level(p->r2chan, loglevel);
14384       if (channo != -1) {
14385          ast_cli(a->fd, "MFC/R2 debugging set to '%s' for channel %d.\n", a->argv[3], p->channel);
14386          break;
14387       }
14388    }
14389    if ((channo != -1) && !p) {
14390       ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
14391    }
14392    if (channo == -1) {
14393       ast_cli(a->fd, "MFC/R2 debugging set to '%s' for all channels.\n", a->argv[3]);
14394    }
14395    ast_mutex_unlock(&iflock);
14396    return CLI_SUCCESS;
14397 }
14398 
14399 static char *handle_mfcr2_call_files(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14400 {
14401    struct dahdi_pvt *p = NULL;
14402    int channo = 0;
14403    switch (cmd) {
14404    case CLI_INIT:
14405       e->command = "mfcr2 call files [on|off]";
14406       e->usage =
14407          "Usage: mfcr2 call files [on|off] <channel>\n"
14408          "       Enable call files creation on the specified channel.\n"
14409          "       If no channel is specified call files creation policy will be applied to all channels.\n";
14410       return NULL;
14411    case CLI_GENERATE:
14412       return NULL;
14413    }
14414    if (a->argc < 4) {
14415       return CLI_SHOWUSAGE;
14416    }
14417    channo = (a->argc == 5) ? atoi(a->argv[4]) : -1;
14418    ast_mutex_lock(&iflock);
14419    for (p = iflist; p; p = p->next) {
14420       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14421          continue;
14422       }
14423       if ((channo != -1) && (p->channel != channo )) {
14424          continue;
14425       }
14426       if (ast_true(a->argv[3])) {
14427          openr2_chan_enable_call_files(p->r2chan);
14428       } else {
14429          openr2_chan_disable_call_files(p->r2chan);
14430       }
14431       if (channo != -1) {
14432          if (ast_true(a->argv[3])) {
14433             ast_cli(a->fd, "MFC/R2 call files enabled for channel %d.\n", p->channel);
14434          } else {
14435             ast_cli(a->fd, "MFC/R2 call files disabled for channel %d.\n", p->channel);
14436          }
14437          break;
14438       }
14439    }
14440    if ((channo != -1) && !p) {
14441       ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
14442    }
14443    if (channo == -1) {
14444       if (ast_true(a->argv[3])) {
14445          ast_cli(a->fd, "MFC/R2 Call files enabled for all channels.\n");
14446       } else {
14447          ast_cli(a->fd, "MFC/R2 Call files disabled for all channels.\n");
14448       }
14449    }
14450    ast_mutex_unlock(&iflock);
14451    return CLI_SUCCESS;
14452 }
14453 
14454 static char *handle_mfcr2_set_idle(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14455 {
14456    struct dahdi_pvt *p = NULL;
14457    int channo = 0;
14458    switch (cmd) {
14459    case CLI_INIT:
14460       e->command = "mfcr2 set idle";
14461       e->usage =
14462          "Usage: mfcr2 set idle <channel>\n"
14463          "       DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n"
14464          "       Force the given channel into IDLE state.\n"
14465          "       If no channel is specified, all channels will be set to IDLE.\n";
14466       return NULL;
14467    case CLI_GENERATE:
14468       return NULL;
14469    }
14470    channo = (a->argc == 4) ? atoi(a->argv[3]) : -1;
14471    ast_mutex_lock(&iflock);
14472    for (p = iflist; p; p = p->next) {
14473       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14474          continue;
14475       }
14476       if ((channo != -1) && (p->channel != channo )) {
14477          continue;
14478       }
14479       openr2_chan_set_idle(p->r2chan);
14480       ast_mutex_lock(&p->lock);
14481       p->locallyblocked = 0;
14482       p->mfcr2call = 0;
14483       ast_mutex_unlock(&p->lock);
14484       if (channo != -1) {
14485          break;
14486       }
14487    }
14488    if ((channo != -1) && !p) {
14489       ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
14490    }
14491    ast_mutex_unlock(&iflock);
14492    return CLI_SUCCESS;
14493 }
14494 
14495 static char *handle_mfcr2_set_blocked(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14496 {
14497    struct dahdi_pvt *p = NULL;
14498    int channo = 0;
14499    switch (cmd) {
14500    case CLI_INIT:
14501       e->command = "mfcr2 set blocked";
14502       e->usage =
14503          "Usage: mfcr2 set blocked <channel>\n"
14504          "       DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n"
14505          "       Force the given channel into BLOCKED state.\n"
14506          "       If no channel is specified, all channels will be set to BLOCKED.\n";
14507       return NULL;
14508    case CLI_GENERATE:
14509       return NULL;
14510    }
14511    channo = (a->argc == 4) ? atoi(a->argv[3]) : -1;
14512    ast_mutex_lock(&iflock);
14513    for (p = iflist; p; p = p->next) {
14514       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14515          continue;
14516       }
14517       if ((channo != -1) && (p->channel != channo )) {
14518          continue;
14519       }
14520       openr2_chan_set_blocked(p->r2chan);
14521       ast_mutex_lock(&p->lock);
14522       p->locallyblocked = 1;
14523       ast_mutex_unlock(&p->lock);
14524       if (channo != -1) {
14525          break;
14526       }
14527    }
14528    if ((channo != -1) && !p) {
14529       ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
14530    }
14531    ast_mutex_unlock(&iflock);
14532    return CLI_SUCCESS;
14533 }
14534 
14535 static struct ast_cli_entry dahdi_mfcr2_cli[] = {
14536    AST_CLI_DEFINE(handle_mfcr2_version, "Show OpenR2 library version"),
14537    AST_CLI_DEFINE(handle_mfcr2_show_variants, "Show supported MFC/R2 variants"),
14538    AST_CLI_DEFINE(handle_mfcr2_show_channels, "Show MFC/R2 channels"),
14539    AST_CLI_DEFINE(handle_mfcr2_set_debug, "Set MFC/R2 channel logging level"),
14540    AST_CLI_DEFINE(handle_mfcr2_call_files, "Enable/Disable MFC/R2 call files"),
14541    AST_CLI_DEFINE(handle_mfcr2_set_idle, "Reset MFC/R2 channel forcing it to IDLE"),
14542    AST_CLI_DEFINE(handle_mfcr2_set_blocked, "Reset MFC/R2 channel forcing it to BLOCKED"),
14543 };
14544 
14545 #endif /* HAVE_OPENR2 */
14546 
14547 static char *dahdi_destroy_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14548 {
14549    int channel;
14550    int ret;
14551    switch (cmd) {
14552    case CLI_INIT:
14553       e->command = "dahdi destroy channel";
14554       e->usage =
14555          "Usage: dahdi destroy channel <chan num>\n"
14556          "  DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.  Immediately removes a given channel, whether it is in use or not\n";
14557       return NULL;
14558    case CLI_GENERATE:
14559       return NULL;
14560    }
14561    if (a->argc != 4)
14562       return CLI_SHOWUSAGE;
14563 
14564    channel = atoi(a->argv[3]);
14565    ret = dahdi_destroy_channel_bynum(channel);
14566    return ( RESULT_SUCCESS == ret ) ? CLI_SUCCESS : CLI_FAILURE;
14567 }
14568 
14569 static void dahdi_softhangup_all(void)
14570 {
14571    struct dahdi_pvt *p;
14572 retry:
14573    ast_mutex_lock(&iflock);
14574    for (p = iflist; p; p = p->next) {
14575       ast_mutex_lock(&p->lock);
14576       if (p->owner && !p->restartpending) {
14577          if (ast_channel_trylock(p->owner)) {
14578             if (option_debug > 2)
14579                ast_verbose("Avoiding deadlock\n");
14580             /* Avoid deadlock since you're not supposed to lock iflock or pvt before a channel */
14581             ast_mutex_unlock(&p->lock);
14582             ast_mutex_unlock(&iflock);
14583             goto retry;
14584          }
14585          if (option_debug > 2)
14586             ast_verbose("Softhanging up on %s\n", p->owner->name);
14587          ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_EXPLICIT);
14588          p->restartpending = 1;
14589          num_restart_pending++;
14590          ast_channel_unlock(p->owner);
14591       }
14592       ast_mutex_unlock(&p->lock);
14593    }
14594    ast_mutex_unlock(&iflock);
14595 }
14596 
14597 static int setup_dahdi(int reload);
14598 static int dahdi_restart(void)
14599 {
14600 #if defined(HAVE_PRI) || defined(HAVE_SS7)
14601    int i, j;
14602 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
14603    int cancel_code;
14604    struct dahdi_pvt *p;
14605 
14606    ast_mutex_lock(&restart_lock);
14607    ast_verb(1, "Destroying channels and reloading DAHDI configuration.\n");
14608    dahdi_softhangup_all();
14609    ast_verb(4, "Initial softhangup of all DAHDI channels complete.\n");
14610 #ifdef HAVE_OPENR2
14611    dahdi_r2_destroy_links();
14612 #endif
14613 
14614 #if defined(HAVE_PRI)
14615    for (i = 0; i < NUM_SPANS; i++) {
14616       if (pris[i].pri.master && (pris[i].pri.master != AST_PTHREADT_NULL)) {
14617          cancel_code = pthread_cancel(pris[i].pri.master);
14618          pthread_kill(pris[i].pri.master, SIGURG);
14619          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);
14620          pthread_join(pris[i].pri.master, NULL);
14621          ast_debug(4, "Joined thread of span %d\n", i);
14622       }
14623    }
14624 #endif
14625 
14626 #if defined(HAVE_SS7)
14627    for (i = 0; i < NUM_SPANS; i++) {
14628       if (linksets[i].ss7.master && (linksets[i].ss7.master != AST_PTHREADT_NULL)) {
14629          cancel_code = pthread_cancel(linksets[i].ss7.master);
14630          pthread_kill(linksets[i].ss7.master, SIGURG);
14631          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);
14632          pthread_join(linksets[i].ss7.master, NULL);
14633          ast_debug(4, "Joined thread of span %d\n", i);
14634       }
14635    }
14636 #endif   /* defined(HAVE_SS7) */
14637 
14638    ast_mutex_lock(&monlock);
14639    if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
14640       cancel_code = pthread_cancel(monitor_thread);
14641       pthread_kill(monitor_thread, SIGURG);
14642       ast_debug(4, "Waiting to join monitor thread with pid=%p, cancel_code=%d\n", (void *) monitor_thread, cancel_code);
14643       pthread_join(monitor_thread, NULL);
14644       ast_debug(4, "Joined monitor thread\n");
14645    }
14646    monitor_thread = AST_PTHREADT_NULL; /* prepare to restart thread in setup_dahdi once channels are reconfigured */
14647 
14648    ast_mutex_lock(&ss_thread_lock);
14649    while (ss_thread_count > 0) { /* let ss_threads finish and run dahdi_hangup before dahvi_pvts are destroyed */
14650       int x = DAHDI_FLASH;
14651       ast_debug(3, "Waiting on %d analog_ss_thread(s) to finish\n", ss_thread_count);
14652 
14653       ast_mutex_lock(&iflock);
14654       for (p = iflist; p; p = p->next) {
14655          if (p->owner) {
14656             /* important to create an event for dahdi_wait_event to register so that all analog_ss_threads terminate */
14657             ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
14658          }
14659       }
14660       ast_mutex_unlock(&iflock);
14661       ast_cond_wait(&ss_thread_complete, &ss_thread_lock);
14662    }
14663 
14664    /* ensure any created channels before monitor threads were stopped are hungup */
14665    dahdi_softhangup_all();
14666    ast_verb(4, "Final softhangup of all DAHDI channels complete.\n");
14667    destroy_all_channels();
14668    ast_debug(1, "Channels destroyed. Now re-reading config. %d active channels remaining.\n", ast_active_channels());
14669 
14670    ast_mutex_unlock(&monlock);
14671 
14672 #ifdef HAVE_PRI
14673    for (i = 0; i < NUM_SPANS; i++) {
14674       for (j = 0; j < SIG_PRI_NUM_DCHANS; j++)
14675          dahdi_close_pri_fd(&(pris[i]), j);
14676    }
14677 
14678    memset(pris, 0, sizeof(pris));
14679    for (i = 0; i < NUM_SPANS; i++) {
14680       sig_pri_init_pri(&pris[i].pri);
14681    }
14682    pri_set_error(dahdi_pri_error);
14683    pri_set_message(dahdi_pri_message);
14684 #endif
14685 #if defined(HAVE_SS7)
14686    for (i = 0; i < NUM_SPANS; i++) {
14687       for (j = 0; j < SIG_SS7_NUM_DCHANS; j++)
14688          dahdi_close_ss7_fd(&(linksets[i]), j);
14689    }
14690 
14691    memset(linksets, 0, sizeof(linksets));
14692    for (i = 0; i < NUM_SPANS; i++) {
14693       sig_ss7_init_linkset(&linksets[i].ss7);
14694    }
14695    ss7_set_error(dahdi_ss7_error);
14696    ss7_set_message(dahdi_ss7_message);
14697 #endif   /* defined(HAVE_SS7) */
14698 
14699    if (setup_dahdi(2) != 0) {
14700       ast_log(LOG_WARNING, "Reload channels from dahdi config failed!\n");
14701       ast_mutex_unlock(&ss_thread_lock);
14702       return 1;
14703    }
14704    ast_mutex_unlock(&ss_thread_lock);
14705    ast_mutex_unlock(&restart_lock);
14706    return 0;
14707 }
14708 
14709 static char *dahdi_restart_cmd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14710 {
14711    switch (cmd) {
14712    case CLI_INIT:
14713       e->command = "dahdi restart";
14714       e->usage =
14715          "Usage: dahdi restart\n"
14716          "  Restarts the DAHDI channels: destroys them all and then\n"
14717          "  re-reads them from chan_dahdi.conf.\n"
14718          "  Note that this will STOP any running CALL on DAHDI channels.\n"
14719          "";
14720       return NULL;
14721    case CLI_GENERATE:
14722       return NULL;
14723    }
14724    if (a->argc != 2)
14725       return CLI_SHOWUSAGE;
14726 
14727    if (dahdi_restart() != 0)
14728       return CLI_FAILURE;
14729    return CLI_SUCCESS;
14730 }
14731 
14732 static int action_dahdirestart(struct mansession *s, const struct message *m)
14733 {
14734    if (dahdi_restart() != 0) {
14735       astman_send_error(s, m, "Failed rereading DAHDI configuration");
14736       return 1;
14737    }
14738    astman_send_ack(s, m, "DAHDIRestart: Success");
14739    return 0;
14740 }
14741 
14742 static char *dahdi_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14743 {
14744 #define FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
14745 #define FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
14746    unsigned int targetnum = 0;
14747    int filtertype = 0;
14748    struct dahdi_pvt *tmp = NULL;
14749    char tmps[20] = "";
14750    char statestr[20] = "";
14751    char blockstr[20] = "";
14752 
14753    switch (cmd) {
14754    case CLI_INIT:
14755       e->command = "dahdi show channels [group|context]";
14756       e->usage =
14757          "Usage: dahdi show channels [ group <group> | context <context> ]\n"
14758          "  Shows a list of available channels with optional filtering\n"
14759          "  <group> must be a number between 0 and 63\n";
14760       return NULL;
14761    case CLI_GENERATE:
14762       return NULL;
14763    }
14764 
14765    /* syntax: dahdi show channels [ group <group> | context <context> ] */
14766 
14767    if (!((a->argc == 3) || (a->argc == 5)))
14768       return CLI_SHOWUSAGE;
14769 
14770    if (a->argc == 5) {
14771       if (!strcasecmp(a->argv[3], "group")) {
14772          targetnum = atoi(a->argv[4]);
14773          if ((targetnum < 0) || (targetnum > 63))
14774             return CLI_SHOWUSAGE;
14775          targetnum = 1 << targetnum;
14776          filtertype = 1;
14777       } else if (!strcasecmp(a->argv[3], "context")) {
14778          filtertype = 2;
14779       }
14780    }
14781 
14782    ast_cli(a->fd, FORMAT2, "Chan", "Extension", "Context", "Language", "MOH Interpret", "Blocked", "State");
14783    ast_mutex_lock(&iflock);
14784    for (tmp = iflist; tmp; tmp = tmp->next) {
14785       if (filtertype) {
14786          switch(filtertype) {
14787          case 1: /* dahdi show channels group <group> */
14788             if (!(tmp->group & targetnum)) {
14789                continue;
14790             }
14791             break;
14792          case 2: /* dahdi show channels context <context> */
14793             if (strcasecmp(tmp->context, a->argv[4])) {
14794                continue;
14795             }
14796             break;
14797          default:
14798             ;
14799          }
14800       }
14801       if (tmp->channel > 0) {
14802          snprintf(tmps, sizeof(tmps), "%d", tmp->channel);
14803       } else
14804          ast_copy_string(tmps, "pseudo", sizeof(tmps));
14805 
14806       if (tmp->locallyblocked)
14807          blockstr[0] = 'L';
14808       else
14809          blockstr[0] = ' ';
14810 
14811       if (tmp->remotelyblocked)
14812          blockstr[1] = 'R';
14813       else
14814          blockstr[1] = ' ';
14815 
14816       blockstr[2] = '\0';
14817 
14818       snprintf(statestr, sizeof(statestr), "%s", "In Service");
14819 
14820       ast_cli(a->fd, FORMAT, tmps, tmp->exten, tmp->context, tmp->language, tmp->mohinterpret, blockstr, statestr);
14821    }
14822    ast_mutex_unlock(&iflock);
14823    return CLI_SUCCESS;
14824 #undef FORMAT
14825 #undef FORMAT2
14826 }
14827 
14828 static char *dahdi_show_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14829 {
14830    int channel;
14831    struct dahdi_pvt *tmp = NULL;
14832    struct dahdi_confinfo ci;
14833    struct dahdi_params ps;
14834    int x;
14835 
14836    switch (cmd) {
14837    case CLI_INIT:
14838       e->command = "dahdi show channel";
14839       e->usage =
14840          "Usage: dahdi show channel <chan num>\n"
14841          "  Detailed information about a given channel\n";
14842       return NULL;
14843    case CLI_GENERATE:
14844       return NULL;
14845    }
14846 
14847    if (a->argc != 4)
14848       return CLI_SHOWUSAGE;
14849 
14850    channel = atoi(a->argv[3]);
14851 
14852    ast_mutex_lock(&iflock);
14853    for (tmp = iflist; tmp; tmp = tmp->next) {
14854       if (tmp->channel == channel) {
14855          ast_cli(a->fd, "Channel: %d\n", tmp->channel);
14856          ast_cli(a->fd, "File Descriptor: %d\n", tmp->subs[SUB_REAL].dfd);
14857          ast_cli(a->fd, "Span: %d\n", tmp->span);
14858          ast_cli(a->fd, "Extension: %s\n", tmp->exten);
14859          ast_cli(a->fd, "Dialing: %s\n", tmp->dialing ? "yes" : "no");
14860          ast_cli(a->fd, "Context: %s\n", tmp->context);
14861          ast_cli(a->fd, "Caller ID: %s\n", tmp->cid_num);
14862          ast_cli(a->fd, "Calling TON: %d\n", tmp->cid_ton);
14863 #if defined(HAVE_PRI)
14864 #if defined(HAVE_PRI_SUBADDR)
14865          ast_cli(a->fd, "Caller ID subaddress: %s\n", tmp->cid_subaddr);
14866 #endif   /* defined(HAVE_PRI_SUBADDR) */
14867 #endif   /* defined(HAVE_PRI) */
14868          ast_cli(a->fd, "Caller ID name: %s\n", tmp->cid_name);
14869          ast_cli(a->fd, "Mailbox: %s\n", S_OR(tmp->mailbox, "none"));
14870          if (tmp->vars) {
14871             struct ast_variable *v;
14872             ast_cli(a->fd, "Variables:\n");
14873             for (v = tmp->vars ; v ; v = v->next)
14874                ast_cli(a->fd, "       %s = %s\n", v->name, v->value);
14875          }
14876          ast_cli(a->fd, "Destroy: %d\n", tmp->destroy);
14877          ast_cli(a->fd, "InAlarm: %d\n", tmp->inalarm);
14878          ast_cli(a->fd, "Signalling Type: %s\n", sig2str(tmp->sig));
14879          ast_cli(a->fd, "Radio: %d\n", tmp->radio);
14880          ast_cli(a->fd, "Owner: %s\n", tmp->owner ? tmp->owner->name : "<None>");
14881          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)" : "");
14882          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)" : "");
14883          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)" : "");
14884          ast_cli(a->fd, "Confno: %d\n", tmp->confno);
14885          ast_cli(a->fd, "Propagated Conference: %d\n", tmp->propconfno);
14886          ast_cli(a->fd, "Real in conference: %d\n", tmp->inconference);
14887          ast_cli(a->fd, "DSP: %s\n", tmp->dsp ? "yes" : "no");
14888          ast_cli(a->fd, "Busy Detection: %s\n", tmp->busydetect ? "yes" : "no");
14889          if (tmp->busydetect) {
14890 #if defined(BUSYDETECT_TONEONLY)
14891             ast_cli(a->fd, "    Busy Detector Helper: BUSYDETECT_TONEONLY\n");
14892 #elif defined(BUSYDETECT_COMPARE_TONE_AND_SILENCE)
14893             ast_cli(a->fd, "    Busy Detector Helper: BUSYDETECT_COMPARE_TONE_AND_SILENCE\n");
14894 #endif
14895 #ifdef BUSYDETECT_DEBUG
14896             ast_cli(a->fd, "    Busy Detector Debug: Enabled\n");
14897 #endif
14898             ast_cli(a->fd, "    Busy Count: %d\n", tmp->busycount);
14899             ast_cli(a->fd, "    Busy Pattern: %d,%d\n", tmp->busy_tonelength, tmp->busy_quietlength);
14900          }
14901          ast_cli(a->fd, "TDD: %s\n", tmp->tdd ? "yes" : "no");
14902          ast_cli(a->fd, "Relax DTMF: %s\n", tmp->dtmfrelax ? "yes" : "no");
14903          ast_cli(a->fd, "Dialing/CallwaitCAS: %d/%d\n", tmp->dialing, tmp->callwaitcas);
14904          ast_cli(a->fd, "Default law: %s\n", tmp->law_default == DAHDI_LAW_MULAW ? "ulaw" : tmp->law_default == DAHDI_LAW_ALAW ? "alaw" : "unknown");
14905          ast_cli(a->fd, "Fax Handled: %s\n", tmp->faxhandled ? "yes" : "no");
14906          ast_cli(a->fd, "Pulse phone: %s\n", tmp->pulsedial ? "yes" : "no");
14907          ast_cli(a->fd, "Gains (RX/TX): %.2f/%.2f\n", tmp->rxgain, tmp->txgain);
14908          ast_cli(a->fd, "Dynamic Range Compression (RX/TX): %.2f/%.2f\n", tmp->rxdrc, tmp->txdrc);
14909          ast_cli(a->fd, "DND: %s\n", dahdi_dnd(tmp, -1) ? "yes" : "no");
14910          ast_cli(a->fd, "Echo Cancellation:\n");
14911 
14912          if (tmp->echocancel.head.tap_length) {
14913             ast_cli(a->fd, "\t%d taps\n", tmp->echocancel.head.tap_length);
14914             for (x = 0; x < tmp->echocancel.head.param_count; x++) {
14915                ast_cli(a->fd, "\t\t%s: %ud\n", tmp->echocancel.params[x].name, tmp->echocancel.params[x].value);
14916             }
14917             ast_cli(a->fd, "\t%scurrently %s\n", tmp->echocanbridged ? "" : "(unless TDM bridged) ", tmp->echocanon ? "ON" : "OFF");
14918          } else {
14919             ast_cli(a->fd, "\tnone\n");
14920          }
14921          ast_cli(a->fd, "Wait for dialtone: %dms\n", tmp->waitfordialtone);
14922          if (tmp->master)
14923             ast_cli(a->fd, "Master Channel: %d\n", tmp->master->channel);
14924          for (x = 0; x < MAX_SLAVES; x++) {
14925             if (tmp->slaves[x])
14926                ast_cli(a->fd, "Slave Channel: %d\n", tmp->slaves[x]->channel);
14927          }
14928 #ifdef HAVE_OPENR2
14929          if (tmp->mfcr2) {
14930             char calldir[OR2_MAX_PATH];
14931             openr2_context_t *r2context = openr2_chan_get_context(tmp->r2chan);
14932             openr2_variant_t r2variant = openr2_context_get_variant(r2context);
14933             ast_cli(a->fd, "MFC/R2 MF State: %s\n", openr2_chan_get_mf_state_string(tmp->r2chan));
14934             ast_cli(a->fd, "MFC/R2 MF Group: %s\n", openr2_chan_get_mf_group_string(tmp->r2chan));
14935             ast_cli(a->fd, "MFC/R2 State: %s\n", openr2_chan_get_r2_state_string(tmp->r2chan));
14936             ast_cli(a->fd, "MFC/R2 Call State: %s\n", openr2_chan_get_call_state_string(tmp->r2chan));
14937             ast_cli(a->fd, "MFC/R2 Call Files Enabled: %s\n", openr2_chan_get_call_files_enabled(tmp->r2chan) ? "Yes" : "No");
14938             ast_cli(a->fd, "MFC/R2 Variant: %s\n", openr2_proto_get_variant_string(r2variant));
14939             ast_cli(a->fd, "MFC/R2 Max ANI: %d\n", openr2_context_get_max_ani(r2context));
14940             ast_cli(a->fd, "MFC/R2 Max DNIS: %d\n", openr2_context_get_max_dnis(r2context));
14941             ast_cli(a->fd, "MFC/R2 Get ANI First: %s\n", openr2_context_get_ani_first(r2context) ? "Yes" : "No");
14942 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
14943             ast_cli(a->fd, "MFC/R2 Skip Category Request: %s\n", openr2_context_get_skip_category_request(r2context) ? "Yes" : "No");
14944 #endif
14945             ast_cli(a->fd, "MFC/R2 Immediate Accept: %s\n", openr2_context_get_immediate_accept(r2context) ? "Yes" : "No");
14946             ast_cli(a->fd, "MFC/R2 Accept on Offer: %s\n", tmp->mfcr2_accept_on_offer ? "Yes" : "No");
14947             ast_cli(a->fd, "MFC/R2 Charge Calls: %s\n", tmp->mfcr2_charge_calls ? "Yes" : "No");
14948             ast_cli(a->fd, "MFC/R2 Allow Collect Calls: %s\n", tmp->mfcr2_allow_collect_calls ? "Yes" : "No");
14949             ast_cli(a->fd, "MFC/R2 Forced Release: %s\n", tmp->mfcr2_forced_release ? "Yes" : "No");
14950             ast_cli(a->fd, "MFC/R2 MF Back Timeout: %dms\n", openr2_context_get_mf_back_timeout(r2context));
14951             ast_cli(a->fd, "MFC/R2 R2 Metering Pulse Timeout: %dms\n", openr2_context_get_metering_pulse_timeout(r2context));
14952             ast_cli(a->fd, "MFC/R2 Rx CAS: %s\n", openr2_chan_get_rx_cas_string(tmp->r2chan));
14953             ast_cli(a->fd, "MFC/R2 Tx CAS: %s\n", openr2_chan_get_tx_cas_string(tmp->r2chan));
14954             ast_cli(a->fd, "MFC/R2 MF Tx Signal: %d\n", openr2_chan_get_tx_mf_signal(tmp->r2chan));
14955             ast_cli(a->fd, "MFC/R2 MF Rx Signal: %d\n", openr2_chan_get_rx_mf_signal(tmp->r2chan));
14956             ast_cli(a->fd, "MFC/R2 Call Files Directory: %s\n", openr2_context_get_log_directory(r2context, calldir, sizeof(calldir)));
14957          }
14958 #endif
14959 #if defined(HAVE_SS7)
14960          if (tmp->ss7) {
14961             struct sig_ss7_chan *chan = tmp->sig_pvt;
14962 
14963             ast_cli(a->fd, "CIC: %d\n", chan->cic);
14964          }
14965 #endif   /* defined(HAVE_SS7) */
14966 #ifdef HAVE_PRI
14967          if (tmp->pri) {
14968             struct sig_pri_chan *chan = tmp->sig_pvt;
14969 
14970             ast_cli(a->fd, "PRI Flags: ");
14971             if (chan->resetting)
14972                ast_cli(a->fd, "Resetting ");
14973             if (chan->call)
14974                ast_cli(a->fd, "Call ");
14975             ast_cli(a->fd, "\n");
14976             if (tmp->logicalspan)
14977                ast_cli(a->fd, "PRI Logical Span: %d\n", tmp->logicalspan);
14978             else
14979                ast_cli(a->fd, "PRI Logical Span: Implicit\n");
14980          }
14981 #endif
14982          memset(&ci, 0, sizeof(ci));
14983          ps.channo = tmp->channel;
14984          if (tmp->subs[SUB_REAL].dfd > -1) {
14985             memset(&ci, 0, sizeof(ci));
14986             if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
14987                ast_cli(a->fd, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci.confno, ci.confmode);
14988             }
14989             if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONFMUTE, &x)) {
14990                ast_cli(a->fd, "Actual Confmute: %s\n", x ? "Yes" : "No");
14991             }
14992             memset(&ps, 0, sizeof(ps));
14993             if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
14994                ast_log(LOG_WARNING, "Failed to get parameters on channel %d: %s\n", tmp->channel, strerror(errno));
14995             } else {
14996                ast_cli(a->fd, "Hookstate (FXS only): %s\n", ps.rxisoffhook ? "Offhook" : "Onhook");
14997             }
14998          }
14999          ast_mutex_unlock(&iflock);
15000          return CLI_SUCCESS;
15001       }
15002    }
15003    ast_mutex_unlock(&iflock);
15004 
15005    ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15006    return CLI_FAILURE;
15007 }
15008 
15009 static char *handle_dahdi_show_cadences(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15010 {
15011    int i, j;
15012    switch (cmd) {
15013    case CLI_INIT:
15014       e->command = "dahdi show cadences";
15015       e->usage =
15016          "Usage: dahdi show cadences\n"
15017          "       Shows all cadences currently defined\n";
15018       return NULL;
15019    case CLI_GENERATE:
15020       return NULL;
15021    }
15022    for (i = 0; i < num_cadence; i++) {
15023       char output[1024];
15024       char tmp[16], tmp2[64];
15025       snprintf(tmp, sizeof(tmp), "r%d: ", i + 1);
15026       term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output));
15027 
15028       for (j = 0; j < 16; j++) {
15029          if (cadences[i].ringcadence[j] == 0)
15030             break;
15031          snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]);
15032          if (cidrings[i] * 2 - 1 == j)
15033             term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1);
15034          else
15035             term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1);
15036          if (j != 0)
15037             strncat(output, ",", sizeof(output) - strlen(output) - 1);
15038          strncat(output, tmp2, sizeof(output) - strlen(output) - 1);
15039       }
15040       ast_cli(a->fd,"%s\n",output);
15041    }
15042    return CLI_SUCCESS;
15043 }
15044 
15045 /* Based on irqmiss.c */
15046 static char *dahdi_show_status(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15047 {
15048    #define FORMAT "%-40.40s %-7.7s %-6d %-6d %-6d %-3.3s %-4.4s %-8.8s %s\n"
15049    #define FORMAT2 "%-40.40s %-7.7s %-6.6s %-6.6s %-6.6s %-3.3s %-4.4s %-8.8s %s\n"
15050    int span;
15051    int res;
15052    char alarmstr[50];
15053 
15054    int ctl;
15055    struct dahdi_spaninfo s;
15056 
15057    switch (cmd) {
15058    case CLI_INIT:
15059       e->command = "dahdi show status";
15060       e->usage =
15061          "Usage: dahdi show status\n"
15062          "       Shows a list of DAHDI cards with status\n";
15063       return NULL;
15064    case CLI_GENERATE:
15065       return NULL;
15066    }
15067    ctl = open("/dev/dahdi/ctl", O_RDWR);
15068    if (ctl < 0) {
15069       ast_cli(a->fd, "No DAHDI found. Unable to open /dev/dahdi/ctl: %s\n", strerror(errno));
15070       return CLI_FAILURE;
15071    }
15072    ast_cli(a->fd, FORMAT2, "Description", "Alarms", "IRQ", "bpviol", "CRC4", "Framing", "Coding", "Options", "LBO");
15073 
15074    for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
15075       s.spanno = span;
15076       res = ioctl(ctl, DAHDI_SPANSTAT, &s);
15077       if (res) {
15078          continue;
15079       }
15080       alarmstr[0] = '\0';
15081       if (s.alarms > 0) {
15082          if (s.alarms & DAHDI_ALARM_BLUE)
15083             strcat(alarmstr, "BLU/");
15084          if (s.alarms & DAHDI_ALARM_YELLOW)
15085             strcat(alarmstr, "YEL/");
15086          if (s.alarms & DAHDI_ALARM_RED)
15087             strcat(alarmstr, "RED/");
15088          if (s.alarms & DAHDI_ALARM_LOOPBACK)
15089             strcat(alarmstr, "LB/");
15090          if (s.alarms & DAHDI_ALARM_RECOVER)
15091             strcat(alarmstr, "REC/");
15092          if (s.alarms & DAHDI_ALARM_NOTOPEN)
15093             strcat(alarmstr, "NOP/");
15094          if (!strlen(alarmstr))
15095             strcat(alarmstr, "UUU/");
15096          if (strlen(alarmstr)) {
15097             /* Strip trailing / */
15098             alarmstr[strlen(alarmstr) - 1] = '\0';
15099          }
15100       } else {
15101          if (s.numchans)
15102             strcpy(alarmstr, "OK");
15103          else
15104             strcpy(alarmstr, "UNCONFIGURED");
15105       }
15106 
15107       ast_cli(a->fd, FORMAT, s.desc, alarmstr, s.irqmisses, s.bpvcount, s.crc4count,
15108          s.lineconfig & DAHDI_CONFIG_D4 ? "D4" :
15109          s.lineconfig & DAHDI_CONFIG_ESF ? "ESF" :
15110          s.lineconfig & DAHDI_CONFIG_CCS ? "CCS" :
15111          "CAS",
15112          s.lineconfig & DAHDI_CONFIG_B8ZS ? "B8ZS" :
15113          s.lineconfig & DAHDI_CONFIG_HDB3 ? "HDB3" :
15114          s.lineconfig & DAHDI_CONFIG_AMI ? "AMI" :
15115          "Unk",
15116          s.lineconfig & DAHDI_CONFIG_CRC4 ?
15117             s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" :
15118             s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "YEL" : "",
15119          lbostr[s.lbo]
15120          );
15121    }
15122    close(ctl);
15123 
15124    return CLI_SUCCESS;
15125 #undef FORMAT
15126 #undef FORMAT2
15127 }
15128 
15129 static char *dahdi_show_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15130 {
15131    int pseudo_fd = -1;
15132    struct dahdi_versioninfo vi;
15133 
15134    switch (cmd) {
15135    case CLI_INIT:
15136       e->command = "dahdi show version";
15137       e->usage =
15138          "Usage: dahdi show version\n"
15139          "       Shows the DAHDI version in use\n";
15140       return NULL;
15141    case CLI_GENERATE:
15142       return NULL;
15143    }
15144    if ((pseudo_fd = open("/dev/dahdi/ctl", O_RDONLY)) < 0) {
15145       ast_cli(a->fd, "Failed to open control file to get version.\n");
15146       return CLI_SUCCESS;
15147    }
15148 
15149    strcpy(vi.version, "Unknown");
15150    strcpy(vi.echo_canceller, "Unknown");
15151 
15152    if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi))
15153       ast_cli(a->fd, "Failed to get DAHDI version: %s\n", strerror(errno));
15154    else
15155       ast_cli(a->fd, "DAHDI Version: %s Echo Canceller: %s\n", vi.version, vi.echo_canceller);
15156 
15157    close(pseudo_fd);
15158 
15159    return CLI_SUCCESS;
15160 }
15161 
15162 static char *dahdi_set_hwgain(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15163 {
15164    int channel;
15165    int gain;
15166    int tx;
15167    struct dahdi_hwgain hwgain;
15168    struct dahdi_pvt *tmp = NULL;
15169 
15170    switch (cmd) {
15171    case CLI_INIT:
15172       e->command = "dahdi set hwgain";
15173       e->usage =
15174          "Usage: dahdi set hwgain <rx|tx> <chan#> <gain>\n"
15175          "  Sets the hardware gain on a a given channel, overriding the\n"
15176          "   value provided at module loadtime, whether the channel is in\n"
15177          "   use or not.  Changes take effect immediately.\n"
15178          "   <rx|tx> which direction do you want to change (relative to our module)\n"
15179          "   <chan num> is the channel number relative to the device\n"
15180          "   <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
15181       return NULL;
15182    case CLI_GENERATE:
15183       return NULL;
15184    }
15185 
15186    if (a->argc != 6)
15187       return CLI_SHOWUSAGE;
15188 
15189    if (!strcasecmp("rx", a->argv[3]))
15190       tx = 0; /* rx */
15191    else if (!strcasecmp("tx", a->argv[3]))
15192       tx = 1; /* tx */
15193    else
15194       return CLI_SHOWUSAGE;
15195 
15196    channel = atoi(a->argv[4]);
15197    gain = atof(a->argv[5])*10.0;
15198 
15199    ast_mutex_lock(&iflock);
15200 
15201    for (tmp = iflist; tmp; tmp = tmp->next) {
15202 
15203       if (tmp->channel != channel)
15204          continue;
15205 
15206       if (tmp->subs[SUB_REAL].dfd == -1)
15207          break;
15208 
15209       hwgain.newgain = gain;
15210       hwgain.tx = tx;
15211       if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_HWGAIN, &hwgain) < 0) {
15212          ast_cli(a->fd, "Unable to set the hardware gain for channel %d: %s\n", channel, strerror(errno));
15213          ast_mutex_unlock(&iflock);
15214          return CLI_FAILURE;
15215       }
15216       ast_cli(a->fd, "hardware %s gain set to %d (%.1f dB) on channel %d\n",
15217          tx ? "tx" : "rx", gain, (float)gain/10.0, channel);
15218       break;
15219    }
15220 
15221    ast_mutex_unlock(&iflock);
15222 
15223    if (tmp)
15224       return CLI_SUCCESS;
15225 
15226    ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15227    return CLI_FAILURE;
15228 
15229 }
15230 
15231 static char *dahdi_set_swgain(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15232 {
15233    int channel;
15234    float gain;
15235    int tx;
15236    int res;
15237    struct dahdi_pvt *tmp = NULL;
15238 
15239    switch (cmd) {
15240    case CLI_INIT:
15241       e->command = "dahdi set swgain";
15242       e->usage =
15243          "Usage: dahdi set swgain <rx|tx> <chan#> <gain>\n"
15244          "  Sets the software gain on a a given channel, overriding the\n"
15245          "   value provided at module loadtime, whether the channel is in\n"
15246          "   use or not.  Changes take effect immediately.\n"
15247          "   <rx|tx> which direction do you want to change (relative to our module)\n"
15248          "   <chan num> is the channel number relative to the device\n"
15249          "   <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
15250       return NULL;
15251    case CLI_GENERATE:
15252       return NULL;
15253    }
15254 
15255    if (a->argc != 6)
15256       return CLI_SHOWUSAGE;
15257 
15258    if (!strcasecmp("rx", a->argv[3]))
15259       tx = 0; /* rx */
15260    else if (!strcasecmp("tx", a->argv[3]))
15261       tx = 1; /* tx */
15262    else
15263       return CLI_SHOWUSAGE;
15264 
15265    channel = atoi(a->argv[4]);
15266    gain = atof(a->argv[5]);
15267 
15268    ast_mutex_lock(&iflock);
15269    for (tmp = iflist; tmp; tmp = tmp->next) {
15270 
15271       if (tmp->channel != channel)
15272          continue;
15273 
15274       if (tmp->subs[SUB_REAL].dfd == -1)
15275          break;
15276 
15277       if (tx)
15278          res = set_actual_txgain(tmp->subs[SUB_REAL].dfd, gain, tmp->txdrc, tmp->law);
15279       else
15280          res = set_actual_rxgain(tmp->subs[SUB_REAL].dfd, gain, tmp->rxdrc, tmp->law);
15281 
15282       if (res) {
15283          ast_cli(a->fd, "Unable to set the software gain for channel %d\n", channel);
15284          ast_mutex_unlock(&iflock);
15285          return CLI_FAILURE;
15286       }
15287 
15288       ast_cli(a->fd, "software %s gain set to %.1f on channel %d\n",
15289          tx ? "tx" : "rx", gain, channel);
15290       break;
15291    }
15292    ast_mutex_unlock(&iflock);
15293 
15294    if (tmp)
15295       return CLI_SUCCESS;
15296 
15297    ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15298    return CLI_FAILURE;
15299 
15300 }
15301 
15302 static char *dahdi_set_dnd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15303 {
15304    int channel;
15305    int on;
15306    struct dahdi_pvt *dahdi_chan = NULL;
15307 
15308    switch (cmd) {
15309    case CLI_INIT:
15310       e->command = "dahdi set dnd";
15311       e->usage =
15312          "Usage: dahdi set dnd <chan#> <on|off>\n"
15313          "  Sets/resets DND (Do Not Disturb) mode on a channel.\n"
15314          "  Changes take effect immediately.\n"
15315          "  <chan num> is the channel number\n"
15316          "  <on|off> Enable or disable DND mode?\n"
15317          ;
15318       return NULL;
15319    case CLI_GENERATE:
15320       return NULL;
15321    }
15322 
15323    if (a->argc != 5)
15324       return CLI_SHOWUSAGE;
15325 
15326    if ((channel = atoi(a->argv[3])) <= 0) {
15327       ast_cli(a->fd, "Expected channel number, got '%s'\n", a->argv[3]);
15328       return CLI_SHOWUSAGE;
15329    }
15330 
15331    if (ast_true(a->argv[4]))
15332       on = 1;
15333    else if (ast_false(a->argv[4]))
15334       on = 0;
15335    else {
15336       ast_cli(a->fd, "Expected 'on' or 'off', got '%s'\n", a->argv[4]);
15337       return CLI_SHOWUSAGE;
15338    }
15339 
15340    ast_mutex_lock(&iflock);
15341    for (dahdi_chan = iflist; dahdi_chan; dahdi_chan = dahdi_chan->next) {
15342       if (dahdi_chan->channel != channel)
15343          continue;
15344 
15345       /* Found the channel. Actually set it */
15346       dahdi_dnd(dahdi_chan, on);
15347       break;
15348    }
15349    ast_mutex_unlock(&iflock);
15350 
15351    if (!dahdi_chan) {
15352       ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15353       return CLI_FAILURE;
15354    }
15355 
15356    return CLI_SUCCESS;
15357 }
15358 
15359 static struct ast_cli_entry dahdi_cli[] = {
15360    AST_CLI_DEFINE(handle_dahdi_show_cadences, "List cadences"),
15361    AST_CLI_DEFINE(dahdi_show_channels, "Show active DAHDI channels"),
15362    AST_CLI_DEFINE(dahdi_show_channel, "Show information on a channel"),
15363    AST_CLI_DEFINE(dahdi_destroy_channel, "Destroy a channel"),
15364    AST_CLI_DEFINE(dahdi_restart_cmd, "Fully restart DAHDI channels"),
15365    AST_CLI_DEFINE(dahdi_show_status, "Show all DAHDI cards status"),
15366    AST_CLI_DEFINE(dahdi_show_version, "Show the DAHDI version in use"),
15367    AST_CLI_DEFINE(dahdi_set_hwgain, "Set hardware gain on a channel"),
15368    AST_CLI_DEFINE(dahdi_set_swgain, "Set software gain on a channel"),
15369    AST_CLI_DEFINE(dahdi_set_dnd, "Sets/resets DND (Do Not Disturb) mode on a channel"),
15370 };
15371 
15372 #define TRANSFER  0
15373 #define HANGUP    1
15374 
15375 static int dahdi_fake_event(struct dahdi_pvt *p, int mode)
15376 {
15377    if (p) {
15378       switch (mode) {
15379       case TRANSFER:
15380          p->fake_event = DAHDI_EVENT_WINKFLASH;
15381          break;
15382       case HANGUP:
15383          p->fake_event = DAHDI_EVENT_ONHOOK;
15384          break;
15385       default:
15386          ast_log(LOG_WARNING, "I don't know how to handle transfer event with this: %d on channel %s\n",mode, p->owner->name);
15387       }
15388    }
15389    return 0;
15390 }
15391 static struct dahdi_pvt *find_channel(int channel)
15392 {
15393    struct dahdi_pvt *p;
15394 
15395    ast_mutex_lock(&iflock);
15396    for (p = iflist; p; p = p->next) {
15397       if (p->channel == channel) {
15398          break;
15399       }
15400    }
15401    ast_mutex_unlock(&iflock);
15402    return p;
15403 }
15404 
15405 static int action_dahdidndon(struct mansession *s, const struct message *m)
15406 {
15407    struct dahdi_pvt *p = NULL;
15408    const char *channel = astman_get_header(m, "DAHDIChannel");
15409 
15410    if (ast_strlen_zero(channel)) {
15411       astman_send_error(s, m, "No channel specified");
15412       return 0;
15413    }
15414    p = find_channel(atoi(channel));
15415    if (!p) {
15416       astman_send_error(s, m, "No such channel");
15417       return 0;
15418    }
15419    dahdi_dnd(p, 1);
15420    astman_send_ack(s, m, "DND Enabled");
15421    return 0;
15422 }
15423 
15424 static int action_dahdidndoff(struct mansession *s, const struct message *m)
15425 {
15426    struct dahdi_pvt *p = NULL;
15427    const char *channel = astman_get_header(m, "DAHDIChannel");
15428 
15429    if (ast_strlen_zero(channel)) {
15430       astman_send_error(s, m, "No channel specified");
15431       return 0;
15432    }
15433    p = find_channel(atoi(channel));
15434    if (!p) {
15435       astman_send_error(s, m, "No such channel");
15436       return 0;
15437    }
15438    dahdi_dnd(p, 0);
15439    astman_send_ack(s, m, "DND Disabled");
15440    return 0;
15441 }
15442 
15443 static int action_transfer(struct mansession *s, const struct message *m)
15444 {
15445    struct dahdi_pvt *p = NULL;
15446    const char *channel = astman_get_header(m, "DAHDIChannel");
15447 
15448    if (ast_strlen_zero(channel)) {
15449       astman_send_error(s, m, "No channel specified");
15450       return 0;
15451    }
15452    p = find_channel(atoi(channel));
15453    if (!p) {
15454       astman_send_error(s, m, "No such channel");
15455       return 0;
15456    }
15457    dahdi_fake_event(p,TRANSFER);
15458    astman_send_ack(s, m, "DAHDITransfer");
15459    return 0;
15460 }
15461 
15462 static int action_transferhangup(struct mansession *s, const struct message *m)
15463 {
15464    struct dahdi_pvt *p = NULL;
15465    const char *channel = astman_get_header(m, "DAHDIChannel");
15466 
15467    if (ast_strlen_zero(channel)) {
15468       astman_send_error(s, m, "No channel specified");
15469       return 0;
15470    }
15471    p = find_channel(atoi(channel));
15472    if (!p) {
15473       astman_send_error(s, m, "No such channel");
15474       return 0;
15475    }
15476    dahdi_fake_event(p,HANGUP);
15477    astman_send_ack(s, m, "DAHDIHangup");
15478    return 0;
15479 }
15480 
15481 static int action_dahdidialoffhook(struct mansession *s, const struct message *m)
15482 {
15483    struct dahdi_pvt *p = NULL;
15484    const char *channel = astman_get_header(m, "DAHDIChannel");
15485    const char *number = astman_get_header(m, "Number");
15486    int i;
15487 
15488    if (ast_strlen_zero(channel)) {
15489       astman_send_error(s, m, "No channel specified");
15490       return 0;
15491    }
15492    if (ast_strlen_zero(number)) {
15493       astman_send_error(s, m, "No number specified");
15494       return 0;
15495    }
15496    p = find_channel(atoi(channel));
15497    if (!p) {
15498       astman_send_error(s, m, "No such channel");
15499       return 0;
15500    }
15501    if (!p->owner) {
15502       astman_send_error(s, m, "Channel does not have it's owner");
15503       return 0;
15504    }
15505    for (i = 0; i < strlen(number); i++) {
15506       struct ast_frame f = { AST_FRAME_DTMF, .subclass.integer = number[i] };
15507       dahdi_queue_frame(p, &f);
15508    }
15509    astman_send_ack(s, m, "DAHDIDialOffhook");
15510    return 0;
15511 }
15512 
15513 static int action_dahdishowchannels(struct mansession *s, const struct message *m)
15514 {
15515    struct dahdi_pvt *tmp = NULL;
15516    const char *id = astman_get_header(m, "ActionID");
15517    const char *dahdichannel = astman_get_header(m, "DAHDIChannel");
15518    char idText[256] = "";
15519    int channels = 0;
15520    int dahdichanquery = -1;
15521    if (!ast_strlen_zero(dahdichannel)) {
15522       dahdichanquery = atoi(dahdichannel);
15523    }
15524 
15525    astman_send_ack(s, m, "DAHDI channel status will follow");
15526    if (!ast_strlen_zero(id))
15527       snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
15528 
15529    ast_mutex_lock(&iflock);
15530 
15531    for (tmp = iflist; tmp; tmp = tmp->next) {
15532       if (tmp->channel > 0) {
15533          int alm;
15534 
15535          /* If a specific channel is queried for, only deliver status for that channel */
15536          if (dahdichanquery > 0 && tmp->channel != dahdichanquery)
15537             continue;
15538 
15539          alm = get_alarms(tmp);
15540          channels++;
15541          if (tmp->owner) {
15542             /* Add data if we have a current call */
15543             astman_append(s,
15544                "Event: DAHDIShowChannels\r\n"
15545                "DAHDIChannel: %d\r\n"
15546                "Channel: %s\r\n"
15547                "Uniqueid: %s\r\n"
15548                "AccountCode: %s\r\n"
15549                "Signalling: %s\r\n"
15550                "SignallingCode: %d\r\n"
15551                "Context: %s\r\n"
15552                "DND: %s\r\n"
15553                "Alarm: %s\r\n"
15554                "%s"
15555                "\r\n",
15556                tmp->channel,
15557                tmp->owner->name,
15558                tmp->owner->uniqueid,
15559                tmp->owner->accountcode,
15560                sig2str(tmp->sig),
15561                tmp->sig,
15562                tmp->context,
15563                dahdi_dnd(tmp, -1) ? "Enabled" : "Disabled",
15564                alarm2str(alm), idText);
15565          } else {
15566             astman_append(s,
15567                "Event: DAHDIShowChannels\r\n"
15568                "DAHDIChannel: %d\r\n"
15569                "Signalling: %s\r\n"
15570                "SignallingCode: %d\r\n"
15571                "Context: %s\r\n"
15572                "DND: %s\r\n"
15573                "Alarm: %s\r\n"
15574                "%s"
15575                "\r\n",
15576                tmp->channel, sig2str(tmp->sig), tmp->sig,
15577                tmp->context,
15578                dahdi_dnd(tmp, -1) ? "Enabled" : "Disabled",
15579                alarm2str(alm), idText);
15580          }
15581       }
15582    }
15583 
15584    ast_mutex_unlock(&iflock);
15585 
15586    astman_append(s,
15587       "Event: DAHDIShowChannelsComplete\r\n"
15588       "%s"
15589       "Items: %d\r\n"
15590       "\r\n",
15591       idText,
15592       channels);
15593    return 0;
15594 }
15595 
15596 #if defined(HAVE_SS7)
15597 static int linkset_addsigchan(int sigchan)
15598 {
15599    struct dahdi_ss7 *link;
15600    int res;
15601    int curfd;
15602    struct dahdi_params params;
15603    struct dahdi_bufferinfo bi;
15604    struct dahdi_spaninfo si;
15605 
15606    if (sigchan < 0) {
15607       ast_log(LOG_ERROR, "Invalid sigchan!\n");
15608       return -1;
15609    }
15610    if (cur_ss7type < 0) {
15611       ast_log(LOG_ERROR, "Unspecified or invalid ss7type\n");
15612       return -1;
15613    }
15614    if (cur_pointcode < 0) {
15615       ast_log(LOG_ERROR, "Unspecified pointcode!\n");
15616       return -1;
15617    }
15618    if (cur_adjpointcode < 0) {
15619       ast_log(LOG_ERROR, "Unspecified adjpointcode!\n");
15620       return -1;
15621    }
15622    if (cur_defaultdpc < 0) {
15623       ast_log(LOG_ERROR, "Unspecified defaultdpc!\n");
15624       return -1;
15625    }
15626    if (cur_networkindicator < 0) {
15627       ast_log(LOG_ERROR, "Invalid networkindicator!\n");
15628       return -1;
15629    }
15630    link = ss7_resolve_linkset(cur_linkset);
15631    if (!link) {
15632       ast_log(LOG_ERROR, "Invalid linkset number.  Must be between 1 and %d\n", NUM_SPANS + 1);
15633       return -1;
15634    }
15635    if (link->ss7.numsigchans >= SIG_SS7_NUM_DCHANS) {
15636       ast_log(LOG_ERROR, "Too many sigchans on linkset %d\n", cur_linkset);
15637       return -1;
15638    }
15639 
15640    curfd = link->ss7.numsigchans;
15641 
15642    /* Open signaling channel */
15643    link->ss7.fds[curfd] = open("/dev/dahdi/channel", O_RDWR, 0600);
15644    if (link->ss7.fds[curfd] < 0) {
15645       ast_log(LOG_ERROR, "Unable to open SS7 sigchan %d (%s)\n", sigchan,
15646          strerror(errno));
15647       return -1;
15648    }
15649    if (ioctl(link->ss7.fds[curfd], DAHDI_SPECIFY, &sigchan) == -1) {
15650       dahdi_close_ss7_fd(link, curfd);
15651       ast_log(LOG_ERROR, "Unable to specify SS7 sigchan %d (%s)\n", sigchan,
15652          strerror(errno));
15653       return -1;
15654    }
15655 
15656    /* Get signaling channel parameters */
15657    memset(&params, 0, sizeof(params));
15658    res = ioctl(link->ss7.fds[curfd], DAHDI_GET_PARAMS, &params);
15659    if (res) {
15660       dahdi_close_ss7_fd(link, curfd);
15661       ast_log(LOG_ERROR, "Unable to get parameters for sigchan %d (%s)\n", sigchan,
15662          strerror(errno));
15663       return -1;
15664    }
15665    if (params.sigtype != DAHDI_SIG_HDLCFCS
15666       && params.sigtype != DAHDI_SIG_HARDHDLC
15667       && params.sigtype != DAHDI_SIG_MTP2) {
15668       dahdi_close_ss7_fd(link, curfd);
15669       ast_log(LOG_ERROR, "sigchan %d is not in HDLC/FCS mode.\n", sigchan);
15670       return -1;
15671    }
15672 
15673    /* Set signaling channel buffer policy. */
15674    memset(&bi, 0, sizeof(bi));
15675    bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
15676    bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
15677    bi.numbufs = 32;
15678    bi.bufsize = 512;
15679    if (ioctl(link->ss7.fds[curfd], DAHDI_SET_BUFINFO, &bi)) {
15680       ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n",
15681          sigchan, strerror(errno));
15682       dahdi_close_ss7_fd(link, curfd);
15683       return -1;
15684    }
15685 
15686    /* Get current signaling channel alarm status. */
15687    memset(&si, 0, sizeof(si));
15688    res = ioctl(link->ss7.fds[curfd], DAHDI_SPANSTAT, &si);
15689    if (res) {
15690       dahdi_close_ss7_fd(link, curfd);
15691       ast_log(LOG_ERROR, "Unable to get span state for sigchan %d (%s)\n", sigchan,
15692          strerror(errno));
15693    }
15694 
15695    res = sig_ss7_add_sigchan(&link->ss7, curfd, cur_ss7type,
15696       (params.sigtype == DAHDI_SIG_MTP2)
15697          ? SS7_TRANSPORT_DAHDIMTP2
15698          : SS7_TRANSPORT_DAHDIDCHAN,
15699       si.alarms, cur_networkindicator, cur_pointcode, cur_adjpointcode);
15700    if (res) {
15701       dahdi_close_ss7_fd(link, curfd);
15702       return -1;
15703    }
15704 
15705    ++link->ss7.numsigchans;
15706 
15707    return 0;
15708 }
15709 #endif   /* defined(HAVE_SS7) */
15710 
15711 #if defined(HAVE_SS7)
15712 static char *handle_ss7_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15713 {
15714    int span;
15715    switch (cmd) {
15716    case CLI_INIT:
15717       e->command = "ss7 set debug {on|off} linkset";
15718       e->usage =
15719          "Usage: ss7 set debug {on|off} linkset <linkset>\n"
15720          "       Enables debugging on a given SS7 linkset\n";
15721       return NULL;
15722    case CLI_GENERATE:
15723       return NULL;
15724    }
15725    if (a->argc < 6)
15726       return CLI_SHOWUSAGE;
15727    span = atoi(a->argv[5]);
15728    if ((span < 1) || (span > NUM_SPANS)) {
15729       ast_cli(a->fd, "Invalid linkset %s.  Should be a number from %d to %d\n", a->argv[5], 1, NUM_SPANS);
15730       return CLI_SUCCESS;
15731    }
15732    if (!linksets[span-1].ss7.ss7) {
15733       ast_cli(a->fd, "No SS7 running on linkset %d\n", span);
15734    } else {
15735       if (!strcasecmp(a->argv[3], "on")) {
15736          ss7_set_debug(linksets[span-1].ss7.ss7, SIG_SS7_DEBUG);
15737          ast_cli(a->fd, "Enabled debugging on linkset %d\n", span);
15738       } else {
15739          ss7_set_debug(linksets[span-1].ss7.ss7, 0);
15740          ast_cli(a->fd, "Disabled debugging on linkset %d\n", span);
15741       }
15742    }
15743 
15744    return CLI_SUCCESS;
15745 }
15746 #endif   /* defined(HAVE_SS7) */
15747 
15748 #if defined(HAVE_SS7)
15749 static char *handle_ss7_block_cic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15750 {
15751    int linkset, cic;
15752    int blocked = -1, i;
15753    switch (cmd) {
15754    case CLI_INIT:
15755       e->command = "ss7 block cic";
15756       e->usage =
15757          "Usage: ss7 block cic <linkset> <CIC>\n"
15758          "       Sends a remote blocking request for the given CIC on the specified linkset\n";
15759       return NULL;
15760    case CLI_GENERATE:
15761       return NULL;
15762    }
15763    if (a->argc == 5)
15764       linkset = atoi(a->argv[3]);
15765    else
15766       return CLI_SHOWUSAGE;
15767 
15768    if ((linkset < 1) || (linkset > NUM_SPANS)) {
15769       ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
15770       return CLI_SUCCESS;
15771    }
15772 
15773    if (!linksets[linkset-1].ss7.ss7) {
15774       ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
15775       return CLI_SUCCESS;
15776    }
15777 
15778    cic = atoi(a->argv[4]);
15779 
15780    if (cic < 1) {
15781       ast_cli(a->fd, "Invalid CIC specified!\n");
15782       return CLI_SUCCESS;
15783    }
15784 
15785    for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
15786       if (linksets[linkset-1].ss7.pvts[i]->cic == cic) {
15787          blocked = linksets[linkset-1].ss7.pvts[i]->locallyblocked;
15788          if (!blocked) {
15789             ast_mutex_lock(&linksets[linkset-1].ss7.lock);
15790             isup_blo(linksets[linkset-1].ss7.ss7, cic, linksets[linkset-1].ss7.pvts[i]->dpc);
15791             ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
15792          }
15793       }
15794    }
15795 
15796    if (blocked < 0) {
15797       ast_cli(a->fd, "Invalid CIC specified!\n");
15798       return CLI_SUCCESS;
15799    }
15800 
15801    if (!blocked)
15802       ast_cli(a->fd, "Sent blocking request for linkset %d on CIC %d\n", linkset, cic);
15803    else
15804       ast_cli(a->fd, "CIC %d already locally blocked\n", cic);
15805 
15806    /* Break poll on the linkset so it sends our messages */
15807    pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
15808 
15809    return CLI_SUCCESS;
15810 }
15811 #endif   /* defined(HAVE_SS7) */
15812 
15813 #if defined(HAVE_SS7)
15814 static char *handle_ss7_block_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15815 {
15816    int linkset;
15817    int i;
15818    switch (cmd) {
15819    case CLI_INIT:
15820       e->command = "ss7 block linkset";
15821       e->usage =
15822          "Usage: ss7 block linkset <linkset number>\n"
15823          "       Sends a remote blocking request for all CICs on the given linkset\n";
15824       return NULL;
15825    case CLI_GENERATE:
15826       return NULL;
15827    }
15828    if (a->argc == 4)
15829       linkset = atoi(a->argv[3]);
15830    else
15831       return CLI_SHOWUSAGE;
15832 
15833    if ((linkset < 1) || (linkset > NUM_SPANS)) {
15834       ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
15835       return CLI_SUCCESS;
15836    }
15837 
15838    if (!linksets[linkset-1].ss7.ss7) {
15839       ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
15840       return CLI_SUCCESS;
15841    }
15842 
15843    for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
15844       ast_cli(a->fd, "Sending remote blocking request on CIC %d\n", linksets[linkset-1].ss7.pvts[i]->cic);
15845       ast_mutex_lock(&linksets[linkset-1].ss7.lock);
15846       isup_blo(linksets[linkset-1].ss7.ss7, linksets[linkset-1].ss7.pvts[i]->cic, linksets[linkset-1].ss7.pvts[i]->dpc);
15847       ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
15848    }
15849 
15850    /* Break poll on the linkset so it sends our messages */
15851    pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
15852 
15853    return CLI_SUCCESS;
15854 }
15855 #endif   /* defined(HAVE_SS7) */
15856 
15857 #if defined(HAVE_SS7)
15858 static char *handle_ss7_unblock_cic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15859 {
15860    int linkset, cic;
15861    int i, blocked = -1;
15862    switch (cmd) {
15863    case CLI_INIT:
15864       e->command = "ss7 unblock cic";
15865       e->usage =
15866          "Usage: ss7 unblock cic <linkset> <CIC>\n"
15867          "       Sends a remote unblocking request for the given CIC on the specified linkset\n";
15868       return NULL;
15869    case CLI_GENERATE:
15870       return NULL;
15871    }
15872 
15873    if (a->argc == 5)
15874       linkset = atoi(a->argv[3]);
15875    else
15876       return CLI_SHOWUSAGE;
15877 
15878    if ((linkset < 1) || (linkset > NUM_SPANS)) {
15879       ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
15880       return CLI_SUCCESS;
15881    }
15882 
15883    if (!linksets[linkset-1].ss7.ss7) {
15884       ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
15885       return CLI_SUCCESS;
15886    }
15887 
15888    cic = atoi(a->argv[4]);
15889 
15890    if (cic < 1) {
15891       ast_cli(a->fd, "Invalid CIC specified!\n");
15892       return CLI_SUCCESS;
15893    }
15894 
15895    for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
15896       if (linksets[linkset-1].ss7.pvts[i]->cic == cic) {
15897          blocked = linksets[linkset-1].ss7.pvts[i]->locallyblocked;
15898          if (blocked) {
15899             ast_mutex_lock(&linksets[linkset-1].ss7.lock);
15900             isup_ubl(linksets[linkset-1].ss7.ss7, cic, linksets[linkset-1].ss7.pvts[i]->dpc);
15901             ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
15902          }
15903       }
15904    }
15905 
15906    if (blocked > 0)
15907       ast_cli(a->fd, "Sent unblocking request for linkset %d on CIC %d\n", linkset, cic);
15908 
15909    /* Break poll on the linkset so it sends our messages */
15910    pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
15911 
15912    return CLI_SUCCESS;
15913 }
15914 #endif   /* defined(HAVE_SS7) */
15915 
15916 #if defined(HAVE_SS7)
15917 static char *handle_ss7_unblock_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15918 {
15919    int linkset;
15920    int i;
15921    switch (cmd) {
15922    case CLI_INIT:
15923       e->command = "ss7 unblock linkset";
15924       e->usage =
15925          "Usage: ss7 unblock linkset <linkset number>\n"
15926          "       Sends a remote unblocking request for all CICs on the specified linkset\n";
15927       return NULL;
15928    case CLI_GENERATE:
15929       return NULL;
15930    }
15931 
15932    if (a->argc == 4)
15933       linkset = atoi(a->argv[3]);
15934    else
15935       return CLI_SHOWUSAGE;
15936 
15937    if ((linkset < 1) || (linkset > NUM_SPANS)) {
15938       ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
15939       return CLI_SUCCESS;
15940    }
15941 
15942    if (!linksets[linkset-1].ss7.ss7) {
15943       ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
15944       return CLI_SUCCESS;
15945    }
15946 
15947    for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
15948       ast_cli(a->fd, "Sending remote unblock request on CIC %d\n", linksets[linkset-1].ss7.pvts[i]->cic);
15949       ast_mutex_lock(&linksets[linkset-1].ss7.lock);
15950       isup_ubl(linksets[linkset-1].ss7.ss7, linksets[linkset-1].ss7.pvts[i]->cic, linksets[linkset-1].ss7.pvts[i]->dpc);
15951       ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
15952    }
15953 
15954    /* Break poll on the linkset so it sends our messages */
15955    pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
15956 
15957    return CLI_SUCCESS;
15958 }
15959 #endif   /* defined(HAVE_SS7) */
15960 
15961 #if defined(HAVE_SS7)
15962 static char *handle_ss7_show_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15963 {
15964    int linkset;
15965    struct sig_ss7_linkset *ss7;
15966    switch (cmd) {
15967    case CLI_INIT:
15968       e->command = "ss7 show linkset";
15969       e->usage =
15970          "Usage: ss7 show linkset <span>\n"
15971          "       Shows the status of an SS7 linkset.\n";
15972       return NULL;
15973    case CLI_GENERATE:
15974       return NULL;
15975    }
15976 
15977    if (a->argc < 4)
15978       return CLI_SHOWUSAGE;
15979    linkset = atoi(a->argv[3]);
15980    if ((linkset < 1) || (linkset > NUM_SPANS)) {
15981       ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
15982       return CLI_SUCCESS;
15983    }
15984    ss7 = &linksets[linkset - 1].ss7;
15985    if (!ss7->ss7) {
15986       ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
15987       return CLI_SUCCESS;
15988    }
15989 
15990    ast_cli(a->fd, "SS7 linkset %d status: %s\n", linkset, (ss7->state == LINKSET_STATE_UP) ? "Up" : "Down");
15991 
15992    return CLI_SUCCESS;
15993 }
15994 #endif   /* defined(HAVE_SS7) */
15995 
15996 #if defined(HAVE_SS7)
15997 static char *handle_ss7_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15998 {
15999    switch (cmd) {
16000    case CLI_INIT:
16001       e->command = "ss7 show version";
16002       e->usage =
16003          "Usage: ss7 show version\n"
16004          "  Show the libss7 version\n";
16005       return NULL;
16006    case CLI_GENERATE:
16007       return NULL;
16008    }
16009 
16010    ast_cli(a->fd, "libss7 version: %s\n", ss7_get_version());
16011 
16012    return CLI_SUCCESS;
16013 }
16014 #endif   /* defined(HAVE_SS7) */
16015 
16016 #if defined(HAVE_SS7)
16017 static struct ast_cli_entry dahdi_ss7_cli[] = {
16018    AST_CLI_DEFINE(handle_ss7_debug, "Enables SS7 debugging on a linkset"),
16019    AST_CLI_DEFINE(handle_ss7_block_cic, "Blocks the given CIC"),
16020    AST_CLI_DEFINE(handle_ss7_unblock_cic, "Unblocks the given CIC"),
16021    AST_CLI_DEFINE(handle_ss7_block_linkset, "Blocks all CICs on a linkset"),
16022    AST_CLI_DEFINE(handle_ss7_unblock_linkset, "Unblocks all CICs on a linkset"),
16023    AST_CLI_DEFINE(handle_ss7_show_linkset, "Shows the status of a linkset"),
16024    AST_CLI_DEFINE(handle_ss7_version, "Displays libss7 version"),
16025 };
16026 #endif   /* defined(HAVE_SS7) */
16027 
16028 #if defined(HAVE_PRI)
16029 #if defined(HAVE_PRI_CCSS)
16030 /*!
16031  * \internal
16032  * \brief CC agent initialization.
16033  * \since 1.8
16034  *
16035  * \param agent CC core agent control.
16036  * \param chan Original channel the agent will attempt to recall.
16037  *
16038  * \details
16039  * This callback is called when the CC core is initialized.  Agents should allocate
16040  * any private data necessary for the call and assign it to the private_data
16041  * on the agent.  Additionally, if any ast_cc_agent_flags are pertinent to the
16042  * specific agent type, they should be set in this function as well.
16043  *
16044  * \retval 0 on success.
16045  * \retval -1 on error.
16046  */
16047 static int dahdi_pri_cc_agent_init(struct ast_cc_agent *agent, struct ast_channel *chan)
16048 {
16049    struct dahdi_pvt *pvt;
16050    struct sig_pri_chan *pvt_chan;
16051    int res;
16052 
16053    ast_assert(!strcmp(chan->tech->type, "DAHDI"));
16054 
16055    pvt = chan->tech_pvt;
16056    if (dahdi_sig_pri_lib_handles(pvt->sig)) {
16057       pvt_chan = pvt->sig_pvt;
16058    } else {
16059       pvt_chan = NULL;
16060    }
16061    if (!pvt_chan) {
16062       return -1;
16063    }
16064 
16065    ast_module_ref(ast_module_info->self);
16066 
16067    res = sig_pri_cc_agent_init(agent, pvt_chan);
16068    if (res) {
16069       ast_module_unref(ast_module_info->self);
16070    }
16071    return res;
16072 }
16073 #endif   /* defined(HAVE_PRI_CCSS) */
16074 #endif   /* defined(HAVE_PRI) */
16075 
16076 #if defined(HAVE_PRI)
16077 #if defined(HAVE_PRI_CCSS)
16078 /*!
16079  * \internal
16080  * \brief Destroy private data on the agent.
16081  * \since 1.8
16082  *
16083  * \param agent CC core agent control.
16084  *
16085  * \details
16086  * The core will call this function upon completion
16087  * or failure of CC.
16088  *
16089  * \return Nothing
16090  */
16091 static void dahdi_pri_cc_agent_destructor(struct ast_cc_agent *agent)
16092 {
16093    sig_pri_cc_agent_destructor(agent);
16094 
16095    ast_module_unref(ast_module_info->self);
16096 }
16097 #endif   /* defined(HAVE_PRI_CCSS) */
16098 #endif   /* defined(HAVE_PRI) */
16099 
16100 #if defined(HAVE_PRI)
16101 #if defined(HAVE_PRI_CCSS)
16102 static struct ast_cc_agent_callbacks dahdi_pri_cc_agent_callbacks = {
16103    .type = dahdi_pri_cc_type,
16104    .init = dahdi_pri_cc_agent_init,
16105    .start_offer_timer = sig_pri_cc_agent_start_offer_timer,
16106    .stop_offer_timer = sig_pri_cc_agent_stop_offer_timer,
16107    .ack = sig_pri_cc_agent_req_ack,
16108    .status_request = sig_pri_cc_agent_status_req,
16109    .stop_ringing = sig_pri_cc_agent_stop_ringing,
16110    .party_b_free = sig_pri_cc_agent_party_b_free,
16111    .start_monitoring = sig_pri_cc_agent_start_monitoring,
16112    .callee_available = sig_pri_cc_agent_callee_available,
16113    .destructor = dahdi_pri_cc_agent_destructor,
16114 };
16115 #endif   /* defined(HAVE_PRI_CCSS) */
16116 #endif   /* defined(HAVE_PRI) */
16117 
16118 #if defined(HAVE_PRI)
16119 #if defined(HAVE_PRI_CCSS)
16120 static struct ast_cc_monitor_callbacks dahdi_pri_cc_monitor_callbacks = {
16121    .type = dahdi_pri_cc_type,
16122    .request_cc = sig_pri_cc_monitor_req_cc,
16123    .suspend = sig_pri_cc_monitor_suspend,
16124    .unsuspend = sig_pri_cc_monitor_unsuspend,
16125    .status_response = sig_pri_cc_monitor_status_rsp,
16126    .cancel_available_timer = sig_pri_cc_monitor_cancel_available_timer,
16127    .destructor = sig_pri_cc_monitor_destructor,
16128 };
16129 #endif   /* defined(HAVE_PRI_CCSS) */
16130 #endif   /* defined(HAVE_PRI) */
16131 
16132 static int __unload_module(void)
16133 {
16134    struct dahdi_pvt *p;
16135 #if defined(HAVE_PRI) || defined(HAVE_SS7)
16136    int i, j;
16137 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
16138 
16139 #ifdef HAVE_PRI
16140    for (i = 0; i < NUM_SPANS; i++) {
16141       if (pris[i].pri.master != AST_PTHREADT_NULL)
16142          pthread_cancel(pris[i].pri.master);
16143    }
16144    ast_cli_unregister_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
16145    ast_unregister_application(dahdi_send_keypad_facility_app);
16146 #ifdef HAVE_PRI_PROG_W_CAUSE
16147    ast_unregister_application(dahdi_send_callrerouting_facility_app);
16148 #endif
16149 #endif
16150 #if defined(HAVE_SS7)
16151    for (i = 0; i < NUM_SPANS; i++) {
16152       if (linksets[i].ss7.master != AST_PTHREADT_NULL)
16153          pthread_cancel(linksets[i].ss7.master);
16154       }
16155    ast_cli_unregister_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
16156 #endif   /* defined(HAVE_SS7) */
16157 #if defined(HAVE_OPENR2)
16158    dahdi_r2_destroy_links();
16159    ast_cli_unregister_multiple(dahdi_mfcr2_cli, ARRAY_LEN(dahdi_mfcr2_cli));
16160    ast_unregister_application(dahdi_accept_r2_call_app);
16161 #endif
16162 
16163    ast_cli_unregister_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli));
16164    ast_manager_unregister("DAHDIDialOffhook");
16165    ast_manager_unregister("DAHDIHangup");
16166    ast_manager_unregister("DAHDITransfer");
16167    ast_manager_unregister("DAHDIDNDoff");
16168    ast_manager_unregister("DAHDIDNDon");
16169    ast_manager_unregister("DAHDIShowChannels");
16170    ast_manager_unregister("DAHDIRestart");
16171    ast_data_unregister(NULL);
16172    ast_channel_unregister(&dahdi_tech);
16173 
16174    /* Hangup all interfaces if they have an owner */
16175    ast_mutex_lock(&iflock);
16176    for (p = iflist; p; p = p->next) {
16177       if (p->owner)
16178          ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
16179    }
16180    ast_mutex_unlock(&iflock);
16181 
16182    ast_mutex_lock(&monlock);
16183    if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
16184       pthread_cancel(monitor_thread);
16185       pthread_kill(monitor_thread, SIGURG);
16186       pthread_join(monitor_thread, NULL);
16187    }
16188    monitor_thread = AST_PTHREADT_STOP;
16189    ast_mutex_unlock(&monlock);
16190 
16191    destroy_all_channels();
16192 
16193 #if defined(HAVE_PRI)
16194    for (i = 0; i < NUM_SPANS; i++) {
16195       if (pris[i].pri.master && (pris[i].pri.master != AST_PTHREADT_NULL))
16196          pthread_join(pris[i].pri.master, NULL);
16197       for (j = 0; j < SIG_PRI_NUM_DCHANS; j++) {
16198          dahdi_close_pri_fd(&(pris[i]), j);
16199       }
16200       sig_pri_stop_pri(&pris[i].pri);
16201    }
16202 #if defined(HAVE_PRI_CCSS)
16203    ast_cc_agent_unregister(&dahdi_pri_cc_agent_callbacks);
16204    ast_cc_monitor_unregister(&dahdi_pri_cc_monitor_callbacks);
16205 #endif   /* defined(HAVE_PRI_CCSS) */
16206    sig_pri_unload();
16207 #endif
16208 
16209 #if defined(HAVE_SS7)
16210    for (i = 0; i < NUM_SPANS; i++) {
16211       if (linksets[i].ss7.master && (linksets[i].ss7.master != AST_PTHREADT_NULL))
16212          pthread_join(linksets[i].ss7.master, NULL);
16213       for (j = 0; j < SIG_SS7_NUM_DCHANS; j++) {
16214          dahdi_close_ss7_fd(&(linksets[i]), j);
16215       }
16216    }
16217 #endif   /* defined(HAVE_SS7) */
16218    ast_cond_destroy(&ss_thread_complete);
16219    return 0;
16220 }
16221 
16222 static int unload_module(void)
16223 {
16224 #if defined(HAVE_PRI) || defined(HAVE_SS7)
16225    int y;
16226 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
16227 #ifdef HAVE_PRI
16228    for (y = 0; y < NUM_SPANS; y++)
16229       ast_mutex_destroy(&pris[y].pri.lock);
16230 #endif
16231 #if defined(HAVE_SS7)
16232    for (y = 0; y < NUM_SPANS; y++)
16233       ast_mutex_destroy(&linksets[y].ss7.lock);
16234 #endif   /* defined(HAVE_SS7) */
16235    return __unload_module();
16236 }
16237 
16238 static void string_replace(char *str, int char1, int char2)
16239 {
16240    for (; *str; str++) {
16241       if (*str == char1) {
16242          *str = char2;
16243       }
16244    }
16245 }
16246 
16247 static char *parse_spanchan(char *chanstr, char **subdir)
16248 {
16249    char *p;
16250 
16251    if ((p = strrchr(chanstr, '!')) == NULL) {
16252       *subdir = NULL;
16253       return chanstr;
16254    }
16255    *p++ = '\0';
16256    string_replace(chanstr, '!', '/');
16257    *subdir = chanstr;
16258    return p;
16259 }
16260 
16261 static int build_channels(struct dahdi_chan_conf *conf, const char *value, int reload, int lineno, int *found_pseudo)
16262 {
16263    char *c, *chan;
16264    char *subdir;
16265    int x, start, finish;
16266    struct dahdi_pvt *tmp;
16267 
16268    if ((reload == 0) && (conf->chan.sig < 0) && !conf->is_sig_auto) {
16269       ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n");
16270       return -1;
16271    }
16272 
16273    c = ast_strdupa(value);
16274    c = parse_spanchan(c, &subdir);
16275 
16276    while ((chan = strsep(&c, ","))) {
16277       if (sscanf(chan, "%30d-%30d", &start, &finish) == 2) {
16278          /* Range */
16279       } else if (sscanf(chan, "%30d", &start)) {
16280          /* Just one */
16281          finish = start;
16282       } else if (!strcasecmp(chan, "pseudo")) {
16283          finish = start = CHAN_PSEUDO;
16284          if (found_pseudo)
16285             *found_pseudo = 1;
16286       } else {
16287          ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan);
16288          return -1;
16289       }
16290       if (finish < start) {
16291          ast_log(LOG_WARNING, "Sillyness: %d < %d\n", start, finish);
16292          x = finish;
16293          finish = start;
16294          start = x;
16295       }
16296 
16297       for (x = start; x <= finish; x++) {
16298          char fn[PATH_MAX];
16299          int real_channel = x;
16300 
16301          if (!ast_strlen_zero(subdir)) {
16302             real_channel = device2chan(subdir, x, fn, sizeof(fn));
16303             if (real_channel < 0) {
16304                if (conf->ignore_failed_channels) {
16305                   ast_log(LOG_WARNING, "Failed configuring %s!%d, (got %d). But moving on to others.\n",
16306                         subdir, x, real_channel);
16307                   continue;
16308                } else {
16309                   ast_log(LOG_ERROR, "Failed configuring %s!%d, (got %d).\n",
16310                         subdir, x, real_channel);
16311                   return -1;
16312                }
16313             }
16314          }
16315          tmp = mkintf(real_channel, conf, reload);
16316 
16317          if (tmp) {
16318             ast_verb(3, "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", real_channel, sig2str(tmp->sig));
16319          } else {
16320             ast_log(LOG_ERROR, "Unable to %s channel '%s'\n",
16321                   (reload == 1) ? "reconfigure" : "register", value);
16322             return -1;
16323          }
16324       }
16325    }
16326 
16327    return 0;
16328 }
16329 
16330 /** The length of the parameters list of 'dahdichan'.
16331  * \todo Move definition of MAX_CHANLIST_LEN to a proper place. */
16332 #define MAX_CHANLIST_LEN 80
16333 
16334 static void process_echocancel(struct dahdi_chan_conf *confp, const char *data, unsigned int line)
16335 {
16336    char *parse = ast_strdupa(data);
16337    char *params[DAHDI_MAX_ECHOCANPARAMS + 1];
16338    unsigned int param_count;
16339    unsigned int x;
16340 
16341    if (!(param_count = ast_app_separate_args(parse, ',', params, ARRAY_LEN(params))))
16342       return;
16343 
16344    memset(&confp->chan.echocancel, 0, sizeof(confp->chan.echocancel));
16345 
16346    /* first parameter is tap length, process it here */
16347 
16348    x = ast_strlen_zero(params[0]) ? 0 : atoi(params[0]);
16349 
16350    if ((x == 32) || (x == 64) || (x == 128) || (x == 256) || (x == 512) || (x == 1024))
16351       confp->chan.echocancel.head.tap_length = x;
16352    else if ((confp->chan.echocancel.head.tap_length = ast_true(params[0])))
16353       confp->chan.echocancel.head.tap_length = 128;
16354 
16355    /* now process any remaining parameters */
16356 
16357    for (x = 1; x < param_count; x++) {
16358       struct {
16359          char *name;
16360          char *value;
16361       } param;
16362 
16363       if (ast_app_separate_args(params[x], '=', (char **) &param, 2) < 1) {
16364          ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, params[x]);
16365          continue;
16366       }
16367 
16368       if (ast_strlen_zero(param.name) || (strlen(param.name) > sizeof(confp->chan.echocancel.params[0].name)-1)) {
16369          ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, param.name);
16370          continue;
16371       }
16372 
16373       strcpy(confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].name, param.name);
16374 
16375       if (param.value) {
16376          if (sscanf(param.value, "%30d", &confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].value) != 1) {
16377             ast_log(LOG_WARNING, "Invalid echocancel parameter value supplied at line %d: '%s'\n", line, param.value);
16378             continue;
16379          }
16380       }
16381       confp->chan.echocancel.head.param_count++;
16382    }
16383 }
16384 
16385 /*! process_dahdi() - ignore keyword 'channel' and similar */
16386 #define PROC_DAHDI_OPT_NOCHAN  (1 << 0)
16387 /*! process_dahdi() - No warnings on non-existing cofiguration keywords */
16388 #define PROC_DAHDI_OPT_NOWARN  (1 << 1)
16389 
16390 static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct ast_variable *v, int reload, int options)
16391 {
16392    struct dahdi_pvt *tmp;
16393    int y;
16394    int found_pseudo = 0;
16395    char dahdichan[MAX_CHANLIST_LEN] = {};
16396 
16397    for (; v; v = v->next) {
16398       if (!ast_jb_read_conf(&global_jbconf, v->name, v->value))
16399          continue;
16400 
16401       /* must have parkinglot in confp before build_channels is called */
16402       if (!strcasecmp(v->name, "parkinglot")) {
16403          ast_copy_string(confp->chan.parkinglot, v->value, sizeof(confp->chan.parkinglot));
16404       }
16405 
16406       /* Create the interface list */
16407       if (!strcasecmp(v->name, "channel") || !strcasecmp(v->name, "channels")) {
16408          if (options & PROC_DAHDI_OPT_NOCHAN) {
16409             ast_log(LOG_WARNING, "Channel '%s' ignored.\n", v->value);
16410             continue;
16411          }
16412          if (build_channels(confp, v->value, reload, v->lineno, &found_pseudo)) {
16413             if (confp->ignore_failed_channels) {
16414                ast_log(LOG_WARNING, "Channel '%s' failure ignored: ignore_failed_channels.\n", v->value);
16415                continue;
16416             } else {
16417                return -1;
16418             }
16419          }
16420          ast_log(LOG_DEBUG, "Channel '%s' configured.\n", v->value);
16421       } else if (!strcasecmp(v->name, "ignore_failed_channels")) {
16422          confp->ignore_failed_channels = ast_true(v->value);
16423       } else if (!strcasecmp(v->name, "buffers")) {
16424          if (parse_buffers_policy(v->value, &confp->chan.buf_no, &confp->chan.buf_policy)) {
16425             ast_log(LOG_WARNING, "Using default buffer policy.\n");
16426             confp->chan.buf_no = numbufs;
16427             confp->chan.buf_policy = DAHDI_POLICY_IMMEDIATE;
16428          }
16429       } else if (!strcasecmp(v->name, "faxbuffers")) {
16430          if (!parse_buffers_policy(v->value, &confp->chan.faxbuf_no, &confp->chan.faxbuf_policy)) {
16431             confp->chan.usefaxbuffers = 1;
16432          }
16433       } else if (!strcasecmp(v->name, "dahdichan")) {
16434          ast_copy_string(dahdichan, v->value, sizeof(dahdichan));
16435       } else if (!strcasecmp(v->name, "usedistinctiveringdetection")) {
16436          usedistinctiveringdetection = ast_true(v->value);
16437       } else if (!strcasecmp(v->name, "distinctiveringaftercid")) {
16438          distinctiveringaftercid = ast_true(v->value);
16439       } else if (!strcasecmp(v->name, "dring1context")) {
16440          ast_copy_string(confp->chan.drings.ringContext[0].contextData,v->value,sizeof(confp->chan.drings.ringContext[0].contextData));
16441       } else if (!strcasecmp(v->name, "dring2context")) {
16442          ast_copy_string(confp->chan.drings.ringContext[1].contextData,v->value,sizeof(confp->chan.drings.ringContext[1].contextData));
16443       } else if (!strcasecmp(v->name, "dring3context")) {
16444          ast_copy_string(confp->chan.drings.ringContext[2].contextData,v->value,sizeof(confp->chan.drings.ringContext[2].contextData));
16445       } else if (!strcasecmp(v->name, "dring1range")) {
16446          confp->chan.drings.ringnum[0].range = atoi(v->value);
16447       } else if (!strcasecmp(v->name, "dring2range")) {
16448          confp->chan.drings.ringnum[1].range = atoi(v->value);
16449       } else if (!strcasecmp(v->name, "dring3range")) {
16450          confp->chan.drings.ringnum[2].range = atoi(v->value);
16451       } else if (!strcasecmp(v->name, "dring1")) {
16452          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]);
16453       } else if (!strcasecmp(v->name, "dring2")) {
16454          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]);
16455       } else if (!strcasecmp(v->name, "dring3")) {
16456          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]);
16457       } else if (!strcasecmp(v->name, "usecallerid")) {
16458          confp->chan.use_callerid = ast_true(v->value);
16459       } else if (!strcasecmp(v->name, "cidsignalling")) {
16460          if (!strcasecmp(v->value, "bell"))
16461             confp->chan.cid_signalling = CID_SIG_BELL;
16462          else if (!strcasecmp(v->value, "v23"))
16463             confp->chan.cid_signalling = CID_SIG_V23;
16464          else if (!strcasecmp(v->value, "dtmf"))
16465             confp->chan.cid_signalling = CID_SIG_DTMF;
16466          else if (!strcasecmp(v->value, "smdi"))
16467             confp->chan.cid_signalling = CID_SIG_SMDI;
16468          else if (!strcasecmp(v->value, "v23_jp"))
16469             confp->chan.cid_signalling = CID_SIG_V23_JP;
16470          else if (ast_true(v->value))
16471             confp->chan.cid_signalling = CID_SIG_BELL;
16472       } else if (!strcasecmp(v->name, "cidstart")) {
16473          if (!strcasecmp(v->value, "ring"))
16474             confp->chan.cid_start = CID_START_RING;
16475          else if (!strcasecmp(v->value, "polarity_in"))
16476             confp->chan.cid_start = CID_START_POLARITY_IN;
16477          else if (!strcasecmp(v->value, "polarity"))
16478             confp->chan.cid_start = CID_START_POLARITY;
16479          else if (!strcasecmp(v->value, "dtmf"))
16480             confp->chan.cid_start = CID_START_DTMF_NOALERT;
16481          else if (ast_true(v->value))
16482             confp->chan.cid_start = CID_START_RING;
16483       } else if (!strcasecmp(v->name, "threewaycalling")) {
16484          confp->chan.threewaycalling = ast_true(v->value);
16485       } else if (!strcasecmp(v->name, "cancallforward")) {
16486          confp->chan.cancallforward = ast_true(v->value);
16487       } else if (!strcasecmp(v->name, "relaxdtmf")) {
16488          if (ast_true(v->value))
16489             confp->chan.dtmfrelax = DSP_DIGITMODE_RELAXDTMF;
16490          else
16491             confp->chan.dtmfrelax = 0;
16492       } else if (!strcasecmp(v->name, "mailbox")) {
16493          ast_copy_string(confp->chan.mailbox, v->value, sizeof(confp->chan.mailbox));
16494       } else if (!strcasecmp(v->name, "hasvoicemail")) {
16495          if (ast_true(v->value) && ast_strlen_zero(confp->chan.mailbox)) {
16496             ast_copy_string(confp->chan.mailbox, cat, sizeof(confp->chan.mailbox));
16497          }
16498       } else if (!strcasecmp(v->name, "adsi")) {
16499          confp->chan.adsi = ast_true(v->value);
16500       } else if (!strcasecmp(v->name, "usesmdi")) {
16501          confp->chan.use_smdi = ast_true(v->value);
16502       } else if (!strcasecmp(v->name, "smdiport")) {
16503          ast_copy_string(confp->smdi_port, v->value, sizeof(confp->smdi_port));
16504       } else if (!strcasecmp(v->name, "transfer")) {
16505          confp->chan.transfer = ast_true(v->value);
16506       } else if (!strcasecmp(v->name, "canpark")) {
16507          confp->chan.canpark = ast_true(v->value);
16508       } else if (!strcasecmp(v->name, "echocancelwhenbridged")) {
16509          confp->chan.echocanbridged = ast_true(v->value);
16510       } else if (!strcasecmp(v->name, "busydetect")) {
16511          confp->chan.busydetect = ast_true(v->value);
16512       } else if (!strcasecmp(v->name, "busycount")) {
16513          confp->chan.busycount = atoi(v->value);
16514       } else if (!strcasecmp(v->name, "busypattern")) {
16515          if (sscanf(v->value, "%30d,%30d", &confp->chan.busy_tonelength, &confp->chan.busy_quietlength) != 2) {
16516             ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength,quietlength at line %d.\n", v->lineno);
16517          }
16518       } else if (!strcasecmp(v->name, "callprogress")) {
16519          confp->chan.callprogress &= ~CALLPROGRESS_PROGRESS;
16520          if (ast_true(v->value))
16521             confp->chan.callprogress |= CALLPROGRESS_PROGRESS;
16522       } else if (!strcasecmp(v->name, "waitfordialtone")) {
16523          confp->chan.waitfordialtone = atoi(v->value);
16524       } else if (!strcasecmp(v->name, "faxdetect")) {
16525          confp->chan.callprogress &= ~CALLPROGRESS_FAX;
16526          if (!strcasecmp(v->value, "incoming")) {
16527             confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING;
16528          } else if (!strcasecmp(v->value, "outgoing")) {
16529             confp->chan.callprogress |= CALLPROGRESS_FAX_OUTGOING;
16530          } else if (!strcasecmp(v->value, "both") || ast_true(v->value))
16531             confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING;
16532       } else if (!strcasecmp(v->name, "echocancel")) {
16533          process_echocancel(confp, v->value, v->lineno);
16534       } else if (!strcasecmp(v->name, "echotraining")) {
16535          if (sscanf(v->value, "%30d", &y) == 1) {
16536             if ((y < 10) || (y > 4000)) {
16537                ast_log(LOG_WARNING, "Echo training time must be within the range of 10 to 4000 ms at line %d.\n", v->lineno);
16538             } else {
16539                confp->chan.echotraining = y;
16540             }
16541          } else if (ast_true(v->value)) {
16542             confp->chan.echotraining = 400;
16543          } else
16544             confp->chan.echotraining = 0;
16545       } else if (!strcasecmp(v->name, "hidecallerid")) {
16546          confp->chan.hidecallerid = ast_true(v->value);
16547       } else if (!strcasecmp(v->name, "hidecalleridname")) {
16548          confp->chan.hidecalleridname = ast_true(v->value);
16549       } else if (!strcasecmp(v->name, "pulsedial")) {
16550          confp->chan.pulse = ast_true(v->value);
16551       } else if (!strcasecmp(v->name, "callreturn")) {
16552          confp->chan.callreturn = ast_true(v->value);
16553       } else if (!strcasecmp(v->name, "callwaiting")) {
16554          confp->chan.callwaiting = ast_true(v->value);
16555       } else if (!strcasecmp(v->name, "callwaitingcallerid")) {
16556          confp->chan.callwaitingcallerid = ast_true(v->value);
16557       } else if (!strcasecmp(v->name, "context")) {
16558          ast_copy_string(confp->chan.context, v->value, sizeof(confp->chan.context));
16559       } else if (!strcasecmp(v->name, "language")) {
16560          ast_copy_string(confp->chan.language, v->value, sizeof(confp->chan.language));
16561       } else if (!strcasecmp(v->name, "progzone")) {
16562          ast_copy_string(progzone, v->value, sizeof(progzone));
16563       } else if (!strcasecmp(v->name, "mohinterpret")
16564          ||!strcasecmp(v->name, "musiconhold") || !strcasecmp(v->name, "musicclass")) {
16565          ast_copy_string(confp->chan.mohinterpret, v->value, sizeof(confp->chan.mohinterpret));
16566       } else if (!strcasecmp(v->name, "mohsuggest")) {
16567          ast_copy_string(confp->chan.mohsuggest, v->value, sizeof(confp->chan.mohsuggest));
16568       } else if (!strcasecmp(v->name, "parkinglot")) {
16569          ast_copy_string(parkinglot, v->value, sizeof(parkinglot));
16570       } else if (!strcasecmp(v->name, "stripmsd")) {
16571          ast_log(LOG_NOTICE, "Configuration option \"%s\" has been deprecated. Please use dialplan instead\n", v->name);
16572          confp->chan.stripmsd = atoi(v->value);
16573       } else if (!strcasecmp(v->name, "jitterbuffers")) {
16574          numbufs = atoi(v->value);
16575       } else if (!strcasecmp(v->name, "group")) {
16576          confp->chan.group = ast_get_group(v->value);
16577       } else if (!strcasecmp(v->name, "callgroup")) {
16578          if (!strcasecmp(v->value, "none"))
16579             confp->chan.callgroup = 0;
16580          else
16581             confp->chan.callgroup = ast_get_group(v->value);
16582       } else if (!strcasecmp(v->name, "pickupgroup")) {
16583          if (!strcasecmp(v->value, "none"))
16584             confp->chan.pickupgroup = 0;
16585          else
16586             confp->chan.pickupgroup = ast_get_group(v->value);
16587       } else if (!strcasecmp(v->name, "setvar")) {
16588          char *varname = ast_strdupa(v->value), *varval = NULL;
16589          struct ast_variable *tmpvar;
16590          if (varname && (varval = strchr(varname, '='))) {
16591             *varval++ = '\0';
16592             if ((tmpvar = ast_variable_new(varname, varval, ""))) {
16593                tmpvar->next = confp->chan.vars;
16594                confp->chan.vars = tmpvar;
16595             }
16596          }
16597       } else if (!strcasecmp(v->name, "immediate")) {
16598          confp->chan.immediate = ast_true(v->value);
16599       } else if (!strcasecmp(v->name, "transfertobusy")) {
16600          confp->chan.transfertobusy = ast_true(v->value);
16601       } else if (!strcasecmp(v->name, "mwimonitor")) {
16602          confp->chan.mwimonitor_neon = 0;
16603          confp->chan.mwimonitor_fsk = 0;
16604          confp->chan.mwimonitor_rpas = 0;
16605          if (strcasestr(v->value, "fsk")) {
16606             confp->chan.mwimonitor_fsk = 1;
16607          }
16608          if (strcasestr(v->value, "rpas")) {
16609             confp->chan.mwimonitor_rpas = 1;
16610          }
16611          if (strcasestr(v->value, "neon")) {
16612             confp->chan.mwimonitor_neon = 1;
16613          }
16614          /* If set to true or yes, assume that simple fsk is desired */
16615          if (ast_true(v->value)) {
16616             confp->chan.mwimonitor_fsk = 1;
16617          }
16618       } else if (!strcasecmp(v->name, "cid_rxgain")) {
16619          if (sscanf(v->value, "%30f", &confp->chan.cid_rxgain) != 1) {
16620             ast_log(LOG_WARNING, "Invalid cid_rxgain: %s at line %d.\n", v->value, v->lineno);
16621          }
16622       } else if (!strcasecmp(v->name, "rxgain")) {
16623          if (sscanf(v->value, "%30f", &confp->chan.rxgain) != 1) {
16624             ast_log(LOG_WARNING, "Invalid rxgain: %s at line %d.\n", v->value, v->lineno);
16625          }
16626       } else if (!strcasecmp(v->name, "txgain")) {
16627          if (sscanf(v->value, "%30f", &confp->chan.txgain) != 1) {
16628             ast_log(LOG_WARNING, "Invalid txgain: %s at line %d.\n", v->value, v->lineno);
16629          }
16630       } else if (!strcasecmp(v->name, "txdrc")) {
16631          if (sscanf(v->value, "%f", &confp->chan.txdrc) != 1) {
16632             ast_log(LOG_WARNING, "Invalid txdrc: %s\n", v->value);
16633          }
16634       } else if (!strcasecmp(v->name, "rxdrc")) {
16635          if (sscanf(v->value, "%f", &confp->chan.rxdrc) != 1) {
16636             ast_log(LOG_WARNING, "Invalid rxdrc: %s\n", v->value);
16637          }
16638       } else if (!strcasecmp(v->name, "tonezone")) {
16639          if (sscanf(v->value, "%30d", &confp->chan.tonezone) != 1) {
16640             ast_log(LOG_WARNING, "Invalid tonezone: %s at line %d.\n", v->value, v->lineno);
16641          }
16642       } else if (!strcasecmp(v->name, "callerid")) {
16643          if (!strcasecmp(v->value, "asreceived")) {
16644             confp->chan.cid_num[0] = '\0';
16645             confp->chan.cid_name[0] = '\0';
16646          } else {
16647             ast_callerid_split(v->value, confp->chan.cid_name, sizeof(confp->chan.cid_name), confp->chan.cid_num, sizeof(confp->chan.cid_num));
16648          }
16649       } else if (!strcasecmp(v->name, "fullname")) {
16650          ast_copy_string(confp->chan.cid_name, v->value, sizeof(confp->chan.cid_name));
16651       } else if (!strcasecmp(v->name, "cid_number")) {
16652          ast_copy_string(confp->chan.cid_num, v->value, sizeof(confp->chan.cid_num));
16653       } else if (!strcasecmp(v->name, "cid_tag")) {
16654          ast_copy_string(confp->chan.cid_tag, v->value, sizeof(confp->chan.cid_tag));
16655       } else if (!strcasecmp(v->name, "useincomingcalleridondahditransfer")) {
16656          confp->chan.dahditrcallerid = ast_true(v->value);
16657       } else if (!strcasecmp(v->name, "restrictcid")) {
16658          confp->chan.restrictcid = ast_true(v->value);
16659       } else if (!strcasecmp(v->name, "usecallingpres")) {
16660          confp->chan.use_callingpres = ast_true(v->value);
16661       } else if (!strcasecmp(v->name, "accountcode")) {
16662          ast_copy_string(confp->chan.accountcode, v->value, sizeof(confp->chan.accountcode));
16663       } else if (!strcasecmp(v->name, "amaflags")) {
16664          y = ast_cdr_amaflags2int(v->value);
16665          if (y < 0)
16666             ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d.\n", v->value, v->lineno);
16667          else
16668             confp->chan.amaflags = y;
16669       } else if (!strcasecmp(v->name, "polarityonanswerdelay")) {
16670          confp->chan.polarityonanswerdelay = atoi(v->value);
16671       } else if (!strcasecmp(v->name, "answeronpolarityswitch")) {
16672          confp->chan.answeronpolarityswitch = ast_true(v->value);
16673       } else if (!strcasecmp(v->name, "hanguponpolarityswitch")) {
16674          confp->chan.hanguponpolarityswitch = ast_true(v->value);
16675       } else if (!strcasecmp(v->name, "sendcalleridafter")) {
16676          confp->chan.sendcalleridafter = atoi(v->value);
16677       } else if (!strcasecmp(v->name, "mwimonitornotify")) {
16678          ast_copy_string(mwimonitornotify, v->value, sizeof(mwimonitornotify));
16679       } else if (ast_cc_is_config_param(v->name)) {
16680          ast_cc_set_param(confp->chan.cc_params, v->name, v->value);
16681       } else if (!strcasecmp(v->name, "mwisendtype")) {
16682 #ifndef HAVE_DAHDI_LINEREVERSE_VMWI  /* backward compatibility for older dahdi VMWI implementation */
16683          if (!strcasecmp(v->value, "rpas")) { /* Ring Pulse Alert Signal */
16684             mwisend_rpas = 1;
16685          } else {
16686             mwisend_rpas = 0;
16687          }
16688 #else
16689          /* Default is fsk, to turn it off you must specify nofsk */
16690          memset(&confp->chan.mwisend_setting, 0, sizeof(confp->chan.mwisend_setting));
16691          if (strcasestr(v->value, "nofsk")) {      /* NoFSK */
16692             confp->chan.mwisend_fsk = 0;
16693          } else {             /* Default FSK */
16694             confp->chan.mwisend_fsk = 1;
16695          }
16696          if (strcasestr(v->value, "rpas")) {       /* Ring Pulse Alert Signal, normally followed by FSK */
16697             confp->chan.mwisend_rpas = 1;
16698          } else {
16699             confp->chan.mwisend_rpas = 0;
16700          }
16701          if (strcasestr(v->value, "lrev")) {       /* Line Reversal */
16702             confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_LREV;
16703          }
16704          if (strcasestr(v->value, "hvdc")) {       /* HV 90VDC */
16705             confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_HVDC;
16706          }
16707          if ( (strcasestr(v->value, "neon")) || (strcasestr(v->value, "hvac")) ){   /* 90V DC pulses */
16708             confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_HVAC;
16709          }
16710 #endif
16711       } else if (reload != 1) {
16712           if (!strcasecmp(v->name, "signalling") || !strcasecmp(v->name, "signaling")) {
16713             int orig_radio = confp->chan.radio;
16714             int orig_outsigmod = confp->chan.outsigmod;
16715             int orig_auto = confp->is_sig_auto;
16716 
16717             confp->chan.radio = 0;
16718             confp->chan.outsigmod = -1;
16719             confp->is_sig_auto = 0;
16720             if (!strcasecmp(v->value, "em")) {
16721                confp->chan.sig = SIG_EM;
16722             } else if (!strcasecmp(v->value, "em_e1")) {
16723                confp->chan.sig = SIG_EM_E1;
16724             } else if (!strcasecmp(v->value, "em_w")) {
16725                confp->chan.sig = SIG_EMWINK;
16726             } else if (!strcasecmp(v->value, "fxs_ls")) {
16727                confp->chan.sig = SIG_FXSLS;
16728             } else if (!strcasecmp(v->value, "fxs_gs")) {
16729                confp->chan.sig = SIG_FXSGS;
16730             } else if (!strcasecmp(v->value, "fxs_ks")) {
16731                confp->chan.sig = SIG_FXSKS;
16732             } else if (!strcasecmp(v->value, "fxo_ls")) {
16733                confp->chan.sig = SIG_FXOLS;
16734             } else if (!strcasecmp(v->value, "fxo_gs")) {
16735                confp->chan.sig = SIG_FXOGS;
16736             } else if (!strcasecmp(v->value, "fxo_ks")) {
16737                confp->chan.sig = SIG_FXOKS;
16738             } else if (!strcasecmp(v->value, "fxs_rx")) {
16739                confp->chan.sig = SIG_FXSKS;
16740                confp->chan.radio = 1;
16741             } else if (!strcasecmp(v->value, "fxo_rx")) {
16742                confp->chan.sig = SIG_FXOLS;
16743                confp->chan.radio = 1;
16744             } else if (!strcasecmp(v->value, "fxs_tx")) {
16745                confp->chan.sig = SIG_FXSLS;
16746                confp->chan.radio = 1;
16747             } else if (!strcasecmp(v->value, "fxo_tx")) {
16748                confp->chan.sig = SIG_FXOGS;
16749                confp->chan.radio = 1;
16750             } else if (!strcasecmp(v->value, "em_rx")) {
16751                confp->chan.sig = SIG_EM;
16752                confp->chan.radio = 1;
16753             } else if (!strcasecmp(v->value, "em_tx")) {
16754                confp->chan.sig = SIG_EM;
16755                confp->chan.radio = 1;
16756             } else if (!strcasecmp(v->value, "em_rxtx")) {
16757                confp->chan.sig = SIG_EM;
16758                confp->chan.radio = 2;
16759             } else if (!strcasecmp(v->value, "em_txrx")) {
16760                confp->chan.sig = SIG_EM;
16761                confp->chan.radio = 2;
16762             } else if (!strcasecmp(v->value, "sf")) {
16763                confp->chan.sig = SIG_SF;
16764             } else if (!strcasecmp(v->value, "sf_w")) {
16765                confp->chan.sig = SIG_SFWINK;
16766             } else if (!strcasecmp(v->value, "sf_featd")) {
16767                confp->chan.sig = SIG_FEATD;
16768             } else if (!strcasecmp(v->value, "sf_featdmf")) {
16769                confp->chan.sig = SIG_FEATDMF;
16770             } else if (!strcasecmp(v->value, "sf_featb")) {
16771                confp->chan.sig = SIG_SF_FEATB;
16772             } else if (!strcasecmp(v->value, "sf")) {
16773                confp->chan.sig = SIG_SF;
16774             } else if (!strcasecmp(v->value, "sf_rx")) {
16775                confp->chan.sig = SIG_SF;
16776                confp->chan.radio = 1;
16777             } else if (!strcasecmp(v->value, "sf_tx")) {
16778                confp->chan.sig = SIG_SF;
16779                confp->chan.radio = 1;
16780             } else if (!strcasecmp(v->value, "sf_rxtx")) {
16781                confp->chan.sig = SIG_SF;
16782                confp->chan.radio = 2;
16783             } else if (!strcasecmp(v->value, "sf_txrx")) {
16784                confp->chan.sig = SIG_SF;
16785                confp->chan.radio = 2;
16786             } else if (!strcasecmp(v->value, "featd")) {
16787                confp->chan.sig = SIG_FEATD;
16788             } else if (!strcasecmp(v->value, "featdmf")) {
16789                confp->chan.sig = SIG_FEATDMF;
16790             } else if (!strcasecmp(v->value, "featdmf_ta")) {
16791                confp->chan.sig = SIG_FEATDMF_TA;
16792             } else if (!strcasecmp(v->value, "e911")) {
16793                confp->chan.sig = SIG_E911;
16794             } else if (!strcasecmp(v->value, "fgccama")) {
16795                confp->chan.sig = SIG_FGC_CAMA;
16796             } else if (!strcasecmp(v->value, "fgccamamf")) {
16797                confp->chan.sig = SIG_FGC_CAMAMF;
16798             } else if (!strcasecmp(v->value, "featb")) {
16799                confp->chan.sig = SIG_FEATB;
16800 #ifdef HAVE_PRI
16801             } else if (!strcasecmp(v->value, "pri_net")) {
16802                confp->chan.sig = SIG_PRI;
16803                confp->pri.pri.nodetype = PRI_NETWORK;
16804             } else if (!strcasecmp(v->value, "pri_cpe")) {
16805                confp->chan.sig = SIG_PRI;
16806                confp->pri.pri.nodetype = PRI_CPE;
16807             } else if (!strcasecmp(v->value, "bri_cpe")) {
16808                confp->chan.sig = SIG_BRI;
16809                confp->pri.pri.nodetype = PRI_CPE;
16810             } else if (!strcasecmp(v->value, "bri_net")) {
16811                confp->chan.sig = SIG_BRI;
16812                confp->pri.pri.nodetype = PRI_NETWORK;
16813             } else if (!strcasecmp(v->value, "bri_cpe_ptmp")) {
16814                confp->chan.sig = SIG_BRI_PTMP;
16815                confp->pri.pri.nodetype = PRI_CPE;
16816             } else if (!strcasecmp(v->value, "bri_net_ptmp")) {
16817 #if defined(HAVE_PRI_CALL_HOLD)
16818                confp->chan.sig = SIG_BRI_PTMP;
16819                confp->pri.pri.nodetype = PRI_NETWORK;
16820 #else
16821                ast_log(LOG_WARNING, "How cool would it be if someone implemented this mode!  For now, sucks for you. (line %d)\n", v->lineno);
16822 #endif   /* !defined(HAVE_PRI_CALL_HOLD) */
16823 #endif
16824 #if defined(HAVE_SS7)
16825             } else if (!strcasecmp(v->value, "ss7")) {
16826                confp->chan.sig = SIG_SS7;
16827 #endif   /* defined(HAVE_SS7) */
16828 #ifdef HAVE_OPENR2
16829             } else if (!strcasecmp(v->value, "mfcr2")) {
16830                confp->chan.sig = SIG_MFCR2;
16831 #endif
16832             } else if (!strcasecmp(v->value, "auto")) {
16833                confp->is_sig_auto = 1;
16834             } else {
16835                confp->chan.outsigmod = orig_outsigmod;
16836                confp->chan.radio = orig_radio;
16837                confp->is_sig_auto = orig_auto;
16838                ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
16839             }
16840           } else if (!strcasecmp(v->name, "outsignalling") || !strcasecmp(v->name, "outsignaling")) {
16841             if (!strcasecmp(v->value, "em")) {
16842                confp->chan.outsigmod = SIG_EM;
16843             } else if (!strcasecmp(v->value, "em_e1")) {
16844                confp->chan.outsigmod = SIG_EM_E1;
16845             } else if (!strcasecmp(v->value, "em_w")) {
16846                confp->chan.outsigmod = SIG_EMWINK;
16847             } else if (!strcasecmp(v->value, "sf")) {
16848                confp->chan.outsigmod = SIG_SF;
16849             } else if (!strcasecmp(v->value, "sf_w")) {
16850                confp->chan.outsigmod = SIG_SFWINK;
16851             } else if (!strcasecmp(v->value, "sf_featd")) {
16852                confp->chan.outsigmod = SIG_FEATD;
16853             } else if (!strcasecmp(v->value, "sf_featdmf")) {
16854                confp->chan.outsigmod = SIG_FEATDMF;
16855             } else if (!strcasecmp(v->value, "sf_featb")) {
16856                confp->chan.outsigmod = SIG_SF_FEATB;
16857             } else if (!strcasecmp(v->value, "sf")) {
16858                confp->chan.outsigmod = SIG_SF;
16859             } else if (!strcasecmp(v->value, "featd")) {
16860                confp->chan.outsigmod = SIG_FEATD;
16861             } else if (!strcasecmp(v->value, "featdmf")) {
16862                confp->chan.outsigmod = SIG_FEATDMF;
16863             } else if (!strcasecmp(v->value, "featdmf_ta")) {
16864                confp->chan.outsigmod = SIG_FEATDMF_TA;
16865             } else if (!strcasecmp(v->value, "e911")) {
16866                confp->chan.outsigmod = SIG_E911;
16867             } else if (!strcasecmp(v->value, "fgccama")) {
16868                confp->chan.outsigmod = SIG_FGC_CAMA;
16869             } else if (!strcasecmp(v->value, "fgccamamf")) {
16870                confp->chan.outsigmod = SIG_FGC_CAMAMF;
16871             } else if (!strcasecmp(v->value, "featb")) {
16872                confp->chan.outsigmod = SIG_FEATB;
16873             } else {
16874                ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
16875             }
16876 #ifdef HAVE_PRI
16877          } else if (!strcasecmp(v->name, "pridialplan")) {
16878             if (!strcasecmp(v->value, "national")) {
16879                confp->pri.pri.dialplan = PRI_NATIONAL_ISDN + 1;
16880             } else if (!strcasecmp(v->value, "unknown")) {
16881                confp->pri.pri.dialplan = PRI_UNKNOWN + 1;
16882             } else if (!strcasecmp(v->value, "private")) {
16883                confp->pri.pri.dialplan = PRI_PRIVATE + 1;
16884             } else if (!strcasecmp(v->value, "international")) {
16885                confp->pri.pri.dialplan = PRI_INTERNATIONAL_ISDN + 1;
16886             } else if (!strcasecmp(v->value, "local")) {
16887                confp->pri.pri.dialplan = PRI_LOCAL_ISDN + 1;
16888             } else if (!strcasecmp(v->value, "dynamic")) {
16889                confp->pri.pri.dialplan = -1;
16890             } else if (!strcasecmp(v->value, "redundant")) {
16891                confp->pri.pri.dialplan = -2;
16892             } else {
16893                ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno);
16894             }
16895          } else if (!strcasecmp(v->name, "prilocaldialplan")) {
16896             if (!strcasecmp(v->value, "national")) {
16897                confp->pri.pri.localdialplan = PRI_NATIONAL_ISDN + 1;
16898             } else if (!strcasecmp(v->value, "unknown")) {
16899                confp->pri.pri.localdialplan = PRI_UNKNOWN + 1;
16900             } else if (!strcasecmp(v->value, "private")) {
16901                confp->pri.pri.localdialplan = PRI_PRIVATE + 1;
16902             } else if (!strcasecmp(v->value, "international")) {
16903                confp->pri.pri.localdialplan = PRI_INTERNATIONAL_ISDN + 1;
16904             } else if (!strcasecmp(v->value, "local")) {
16905                confp->pri.pri.localdialplan = PRI_LOCAL_ISDN + 1;
16906             } else if (!strcasecmp(v->value, "dynamic")) {
16907                confp->pri.pri.localdialplan = -1;
16908             } else if (!strcasecmp(v->value, "redundant")) {
16909                confp->pri.pri.localdialplan = -2;
16910             } else {
16911                ast_log(LOG_WARNING, "Unknown PRI localdialplan '%s' at line %d.\n", v->value, v->lineno);
16912             }
16913          } else if (!strcasecmp(v->name, "switchtype")) {
16914             if (!strcasecmp(v->value, "national"))
16915                confp->pri.pri.switchtype = PRI_SWITCH_NI2;
16916             else if (!strcasecmp(v->value, "ni1"))
16917                confp->pri.pri.switchtype = PRI_SWITCH_NI1;
16918             else if (!strcasecmp(v->value, "dms100"))
16919                confp->pri.pri.switchtype = PRI_SWITCH_DMS100;
16920             else if (!strcasecmp(v->value, "4ess"))
16921                confp->pri.pri.switchtype = PRI_SWITCH_ATT4ESS;
16922             else if (!strcasecmp(v->value, "5ess"))
16923                confp->pri.pri.switchtype = PRI_SWITCH_LUCENT5E;
16924             else if (!strcasecmp(v->value, "euroisdn"))
16925                confp->pri.pri.switchtype = PRI_SWITCH_EUROISDN_E1;
16926             else if (!strcasecmp(v->value, "qsig"))
16927                confp->pri.pri.switchtype = PRI_SWITCH_QSIG;
16928             else {
16929                ast_log(LOG_ERROR, "Unknown switchtype '%s' at line %d.\n", v->value, v->lineno);
16930                return -1;
16931             }
16932          } else if (!strcasecmp(v->name, "msn")) {
16933             ast_copy_string(confp->pri.pri.msn_list, v->value,
16934                sizeof(confp->pri.pri.msn_list));
16935          } else if (!strcasecmp(v->name, "nsf")) {
16936             if (!strcasecmp(v->value, "sdn"))
16937                confp->pri.pri.nsf = PRI_NSF_SDN;
16938             else if (!strcasecmp(v->value, "megacom"))
16939                confp->pri.pri.nsf = PRI_NSF_MEGACOM;
16940             else if (!strcasecmp(v->value, "tollfreemegacom"))
16941                confp->pri.pri.nsf = PRI_NSF_TOLL_FREE_MEGACOM;
16942             else if (!strcasecmp(v->value, "accunet"))
16943                confp->pri.pri.nsf = PRI_NSF_ACCUNET;
16944             else if (!strcasecmp(v->value, "none"))
16945                confp->pri.pri.nsf = PRI_NSF_NONE;
16946             else {
16947                ast_log(LOG_WARNING, "Unknown network-specific facility '%s' at line %d.\n", v->value, v->lineno);
16948                confp->pri.pri.nsf = PRI_NSF_NONE;
16949             }
16950          } else if (!strcasecmp(v->name, "priindication")) {
16951             if (!strcasecmp(v->value, "outofband"))
16952                confp->chan.priindication_oob = 1;
16953             else if (!strcasecmp(v->value, "inband"))
16954                confp->chan.priindication_oob = 0;
16955             else
16956                ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d.\n",
16957                   v->value, v->lineno);
16958          } else if (!strcasecmp(v->name, "priexclusive")) {
16959             confp->chan.priexclusive = ast_true(v->value);
16960          } else if (!strcasecmp(v->name, "internationalprefix")) {
16961             ast_copy_string(confp->pri.pri.internationalprefix, v->value, sizeof(confp->pri.pri.internationalprefix));
16962          } else if (!strcasecmp(v->name, "nationalprefix")) {
16963             ast_copy_string(confp->pri.pri.nationalprefix, v->value, sizeof(confp->pri.pri.nationalprefix));
16964          } else if (!strcasecmp(v->name, "localprefix")) {
16965             ast_copy_string(confp->pri.pri.localprefix, v->value, sizeof(confp->pri.pri.localprefix));
16966          } else if (!strcasecmp(v->name, "privateprefix")) {
16967             ast_copy_string(confp->pri.pri.privateprefix, v->value, sizeof(confp->pri.pri.privateprefix));
16968          } else if (!strcasecmp(v->name, "unknownprefix")) {
16969             ast_copy_string(confp->pri.pri.unknownprefix, v->value, sizeof(confp->pri.pri.unknownprefix));
16970          } else if (!strcasecmp(v->name, "resetinterval")) {
16971             if (!strcasecmp(v->value, "never"))
16972                confp->pri.pri.resetinterval = -1;
16973             else if (atoi(v->value) >= 60)
16974                confp->pri.pri.resetinterval = atoi(v->value);
16975             else
16976                ast_log(LOG_WARNING, "'%s' is not a valid reset interval, should be >= 60 seconds or 'never' at line %d.\n",
16977                   v->value, v->lineno);
16978          } else if (!strcasecmp(v->name, "minunused")) {
16979             confp->pri.pri.minunused = atoi(v->value);
16980          } else if (!strcasecmp(v->name, "minidle")) {
16981             confp->pri.pri.minidle = atoi(v->value);
16982          } else if (!strcasecmp(v->name, "idleext")) {
16983             ast_copy_string(confp->pri.pri.idleext, v->value, sizeof(confp->pri.pri.idleext));
16984          } else if (!strcasecmp(v->name, "idledial")) {
16985             ast_copy_string(confp->pri.pri.idledial, v->value, sizeof(confp->pri.pri.idledial));
16986          } else if (!strcasecmp(v->name, "overlapdial")) {
16987             if (ast_true(v->value)) {
16988                confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
16989             } else if (!strcasecmp(v->value, "incoming")) {
16990                confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_INCOMING;
16991             } else if (!strcasecmp(v->value, "outgoing")) {
16992                confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_OUTGOING;
16993             } else if (!strcasecmp(v->value, "both") || ast_true(v->value)) {
16994                confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
16995             } else {
16996                confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_NONE;
16997             }
16998 #ifdef HAVE_PRI_PROG_W_CAUSE
16999          } else if (!strcasecmp(v->name, "qsigchannelmapping")) {
17000             if (!strcasecmp(v->value, "logical")) {
17001                confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_LOGICAL;
17002             } else if (!strcasecmp(v->value, "physical")) {
17003                confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL;
17004             } else {
17005                confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL;
17006             }
17007 #endif
17008          } else if (!strcasecmp(v->name, "discardremoteholdretrieval")) {
17009             confp->pri.pri.discardremoteholdretrieval = ast_true(v->value);
17010 #if defined(HAVE_PRI_SERVICE_MESSAGES)
17011          } else if (!strcasecmp(v->name, "service_message_support")) {
17012             /* assuming switchtype for this channel group has been configured already */
17013             if ((confp->pri.pri.switchtype == PRI_SWITCH_ATT4ESS 
17014                || confp->pri.pri.switchtype == PRI_SWITCH_LUCENT5E
17015                || confp->pri.pri.switchtype == PRI_SWITCH_NI2) && ast_true(v->value)) {
17016                confp->pri.pri.enable_service_message_support = 1;
17017             } else {
17018                confp->pri.pri.enable_service_message_support = 0;
17019             }
17020 #endif   /* defined(HAVE_PRI_SERVICE_MESSAGES) */
17021 #ifdef HAVE_PRI_INBANDDISCONNECT
17022          } else if (!strcasecmp(v->name, "inbanddisconnect")) {
17023             confp->pri.pri.inbanddisconnect = ast_true(v->value);
17024 #endif
17025          } else if (!strcasecmp(v->name, "pritimer")) {
17026 #ifdef PRI_GETSET_TIMERS
17027             char tmp[20];
17028             char *timerc;
17029             char *c;
17030             int timer;
17031             int timeridx;
17032 
17033             ast_copy_string(tmp, v->value, sizeof(tmp));
17034             c = tmp;
17035             timerc = strsep(&c, ",");
17036             if (!ast_strlen_zero(timerc) && !ast_strlen_zero(c)) {
17037                timeridx = pri_timer2idx(timerc);
17038                timer = atoi(c);
17039                if (timeridx < 0 || PRI_MAX_TIMERS <= timeridx) {
17040                   ast_log(LOG_WARNING,
17041                      "'%s' is not a valid ISDN timer at line %d.\n", timerc,
17042                      v->lineno);
17043                } else if (!timer) {
17044                   ast_log(LOG_WARNING,
17045                      "'%s' is not a valid value for ISDN timer '%s' at line %d.\n",
17046                      c, timerc, v->lineno);
17047                } else {
17048                   confp->pri.pri.pritimers[timeridx] = timer;
17049                }
17050             } else {
17051                ast_log(LOG_WARNING,
17052                   "'%s' is not a valid ISDN timer configuration string at line %d.\n",
17053                   v->value, v->lineno);
17054             }
17055 #endif /* PRI_GETSET_TIMERS */
17056          } else if (!strcasecmp(v->name, "facilityenable")) {
17057             confp->pri.pri.facilityenable = ast_true(v->value);
17058 #if defined(HAVE_PRI_AOC_EVENTS)
17059          } else if (!strcasecmp(v->name, "aoc_enable")) {
17060             confp->pri.pri.aoc_passthrough_flag = 0;
17061             if (strchr(v->value, 's') || strchr(v->value, 'S')) {
17062                confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_S;
17063             }
17064             if (strchr(v->value, 'd') || strchr(v->value, 'D')) {
17065                confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_D;
17066             }
17067             if (strchr(v->value, 'e') || strchr(v->value, 'E')) {
17068                confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_E;
17069             }
17070          } else if (!strcasecmp(v->name, "aoce_delayhangup")) {
17071             confp->pri.pri.aoce_delayhangup = ast_true(v->value);
17072 #endif   /* defined(HAVE_PRI_AOC_EVENTS) */
17073 #if defined(HAVE_PRI_CALL_HOLD)
17074          } else if (!strcasecmp(v->name, "hold_disconnect_transfer")) {
17075             confp->pri.pri.hold_disconnect_transfer = ast_true(v->value);
17076 #endif   /* defined(HAVE_PRI_CALL_HOLD) */
17077 #if defined(HAVE_PRI_CCSS)
17078          } else if (!strcasecmp(v->name, "cc_ptmp_recall_mode")) {
17079             if (!strcasecmp(v->value, "global")) {
17080                confp->pri.pri.cc_ptmp_recall_mode = 0;/* globalRecall */
17081             } else if (!strcasecmp(v->value, "specific")) {
17082                confp->pri.pri.cc_ptmp_recall_mode = 1;/* specificRecall */
17083             } else {
17084                confp->pri.pri.cc_ptmp_recall_mode = 1;/* specificRecall */
17085             }
17086          } else if (!strcasecmp(v->name, "cc_qsig_signaling_link_req")) {
17087             if (!strcasecmp(v->value, "release")) {
17088                confp->pri.pri.cc_qsig_signaling_link_req = 0;/* release */
17089             } else if (!strcasecmp(v->value, "retain")) {
17090                confp->pri.pri.cc_qsig_signaling_link_req = 1;/* retain */
17091             } else if (!strcasecmp(v->value, "do_not_care")) {
17092                confp->pri.pri.cc_qsig_signaling_link_req = 2;/* do-not-care */
17093             } else {
17094                confp->pri.pri.cc_qsig_signaling_link_req = 1;/* retain */
17095             }
17096          } else if (!strcasecmp(v->name, "cc_qsig_signaling_link_rsp")) {
17097             if (!strcasecmp(v->value, "release")) {
17098                confp->pri.pri.cc_qsig_signaling_link_rsp = 0;/* release */
17099             } else if (!strcasecmp(v->value, "retain")) {
17100                confp->pri.pri.cc_qsig_signaling_link_rsp = 1;/* retain */
17101             } else {
17102                confp->pri.pri.cc_qsig_signaling_link_rsp = 1;/* retain */
17103             }
17104 #endif   /* defined(HAVE_PRI_CCSS) */
17105 #if defined(HAVE_PRI_CALL_WAITING)
17106          } else if (!strcasecmp(v->name, "max_call_waiting_calls")) {
17107             confp->pri.pri.max_call_waiting_calls = atoi(v->value);
17108             if (confp->pri.pri.max_call_waiting_calls < 0) {
17109                /* Negative values are not allowed. */
17110                confp->pri.pri.max_call_waiting_calls = 0;
17111             }
17112          } else if (!strcasecmp(v->name, "allow_call_waiting_calls")) {
17113             confp->pri.pri.allow_call_waiting_calls = ast_true(v->value);
17114 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
17115 #if defined(HAVE_PRI_MWI)
17116          } else if (!strcasecmp(v->name, "mwi_mailboxes")) {
17117             ast_copy_string(confp->pri.pri.mwi_mailboxes, v->value,
17118                sizeof(confp->pri.pri.mwi_mailboxes));
17119 #endif   /* defined(HAVE_PRI_MWI) */
17120          } else if (!strcasecmp(v->name, "append_msn_to_cid_tag")) {
17121             confp->pri.pri.append_msn_to_user_tag = ast_true(v->value);
17122 #endif /* HAVE_PRI */
17123 #if defined(HAVE_SS7)
17124          } else if (!strcasecmp(v->name, "ss7type")) {
17125             if (!strcasecmp(v->value, "itu")) {
17126                cur_ss7type = SS7_ITU;
17127             } else if (!strcasecmp(v->value, "ansi")) {
17128                cur_ss7type = SS7_ANSI;
17129             } else
17130                ast_log(LOG_WARNING, "'%s' is an unknown ss7 switch type at line %d.!\n", v->value, v->lineno);
17131          } else if (!strcasecmp(v->name, "linkset")) {
17132             cur_linkset = atoi(v->value);
17133          } else if (!strcasecmp(v->name, "pointcode")) {
17134             cur_pointcode = parse_pointcode(v->value);
17135          } else if (!strcasecmp(v->name, "adjpointcode")) {
17136             cur_adjpointcode = parse_pointcode(v->value);
17137          } else if (!strcasecmp(v->name, "defaultdpc")) {
17138             cur_defaultdpc = parse_pointcode(v->value);
17139          } else if (!strcasecmp(v->name, "cicbeginswith")) {
17140             cur_cicbeginswith = atoi(v->value);
17141          } else if (!strcasecmp(v->name, "networkindicator")) {
17142             if (!strcasecmp(v->value, "national"))
17143                cur_networkindicator = SS7_NI_NAT;
17144             else if (!strcasecmp(v->value, "national_spare"))
17145                cur_networkindicator = SS7_NI_NAT_SPARE;
17146             else if (!strcasecmp(v->value, "international"))
17147                cur_networkindicator = SS7_NI_INT;
17148             else if (!strcasecmp(v->value, "international_spare"))
17149                cur_networkindicator = SS7_NI_INT_SPARE;
17150             else
17151                cur_networkindicator = -1;
17152          } else if (!strcasecmp(v->name, "ss7_internationalprefix")) {
17153             ast_copy_string(confp->ss7.ss7.internationalprefix, v->value, sizeof(confp->ss7.ss7.internationalprefix));
17154          } else if (!strcasecmp(v->name, "ss7_nationalprefix")) {
17155             ast_copy_string(confp->ss7.ss7.nationalprefix, v->value, sizeof(confp->ss7.ss7.nationalprefix));
17156          } else if (!strcasecmp(v->name, "ss7_subscriberprefix")) {
17157             ast_copy_string(confp->ss7.ss7.subscriberprefix, v->value, sizeof(confp->ss7.ss7.subscriberprefix));
17158          } else if (!strcasecmp(v->name, "ss7_unknownprefix")) {
17159             ast_copy_string(confp->ss7.ss7.unknownprefix, v->value, sizeof(confp->ss7.ss7.unknownprefix));
17160          } else if (!strcasecmp(v->name, "ss7_called_nai")) {
17161             if (!strcasecmp(v->value, "national")) {
17162                confp->ss7.ss7.called_nai = SS7_NAI_NATIONAL;
17163             } else if (!strcasecmp(v->value, "international")) {
17164                confp->ss7.ss7.called_nai = SS7_NAI_INTERNATIONAL;
17165             } else if (!strcasecmp(v->value, "subscriber")) {
17166                confp->ss7.ss7.called_nai = SS7_NAI_SUBSCRIBER;
17167             } else if (!strcasecmp(v->value, "unknown")) {
17168                confp->ss7.ss7.called_nai = SS7_NAI_UNKNOWN;
17169             } else if (!strcasecmp(v->value, "dynamic")) {
17170                confp->ss7.ss7.called_nai = SS7_NAI_DYNAMIC;
17171             } else {
17172                ast_log(LOG_WARNING, "Unknown SS7 called_nai '%s' at line %d.\n", v->value, v->lineno);
17173             }
17174          } else if (!strcasecmp(v->name, "ss7_calling_nai")) {
17175             if (!strcasecmp(v->value, "national")) {
17176                confp->ss7.ss7.calling_nai = SS7_NAI_NATIONAL;
17177             } else if (!strcasecmp(v->value, "international")) {
17178                confp->ss7.ss7.calling_nai = SS7_NAI_INTERNATIONAL;
17179             } else if (!strcasecmp(v->value, "subscriber")) {
17180                confp->ss7.ss7.calling_nai = SS7_NAI_SUBSCRIBER;
17181             } else if (!strcasecmp(v->value, "unknown")) {
17182                confp->ss7.ss7.calling_nai = SS7_NAI_UNKNOWN;
17183             } else if (!strcasecmp(v->value, "dynamic")) {
17184                confp->ss7.ss7.calling_nai = SS7_NAI_DYNAMIC;
17185             } else {
17186                ast_log(LOG_WARNING, "Unknown SS7 calling_nai '%s' at line %d.\n", v->value, v->lineno);
17187             }
17188          } else if (!strcasecmp(v->name, "sigchan")) {
17189             int sigchan, res;
17190             sigchan = atoi(v->value);
17191             res = linkset_addsigchan(sigchan);
17192             if (res < 0)
17193                return -1;
17194 
17195          } else if (!strcasecmp(v->name, "ss7_explicitacm")) {
17196             struct dahdi_ss7 *link;
17197             link = ss7_resolve_linkset(cur_linkset);
17198             if (!link) {
17199                ast_log(LOG_ERROR, "Invalid linkset number.  Must be between 1 and %d\n", NUM_SPANS + 1);
17200                return -1;
17201             }
17202             if (ast_true(v->value))
17203                link->ss7.flags |= LINKSET_FLAG_EXPLICITACM;
17204 #endif   /* defined(HAVE_SS7) */
17205 #ifdef HAVE_OPENR2
17206          } else if (!strcasecmp(v->name, "mfcr2_advanced_protocol_file")) {
17207             ast_copy_string(confp->mfcr2.r2proto_file, v->value, sizeof(confp->mfcr2.r2proto_file));
17208             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);
17209          } else if (!strcasecmp(v->name, "mfcr2_logdir")) {
17210             ast_copy_string(confp->mfcr2.logdir, v->value, sizeof(confp->mfcr2.logdir));
17211          } else if (!strcasecmp(v->name, "mfcr2_variant")) {
17212             confp->mfcr2.variant = openr2_proto_get_variant(v->value);
17213             if (OR2_VAR_UNKNOWN == confp->mfcr2.variant) {
17214                ast_log(LOG_WARNING, "Unknown MFC/R2 variant '%s' at line %d, defaulting to ITU.\n", v->value, v->lineno);
17215                confp->mfcr2.variant = OR2_VAR_ITU;
17216             }
17217          } else if (!strcasecmp(v->name, "mfcr2_mfback_timeout")) {
17218             confp->mfcr2.mfback_timeout = atoi(v->value);
17219             if (!confp->mfcr2.mfback_timeout) {
17220                ast_log(LOG_WARNING, "MF timeout of 0? hum, I will protect you from your ignorance. Setting default.\n");
17221                confp->mfcr2.mfback_timeout = -1;
17222             } else if (confp->mfcr2.mfback_timeout > 0 && confp->mfcr2.mfback_timeout < 500) {
17223                ast_log(LOG_WARNING, "MF timeout less than 500ms is not recommended, you have been warned!\n");
17224             }
17225          } else if (!strcasecmp(v->name, "mfcr2_metering_pulse_timeout")) {
17226             confp->mfcr2.metering_pulse_timeout = atoi(v->value);
17227             if (confp->mfcr2.metering_pulse_timeout > 500) {
17228                ast_log(LOG_WARNING, "Metering pulse timeout greater than 500ms is not recommended, you have been warned!\n");
17229             }
17230          } else if (!strcasecmp(v->name, "mfcr2_get_ani_first")) {
17231             confp->mfcr2.get_ani_first = ast_true(v->value) ? 1 : 0;
17232          } else if (!strcasecmp(v->name, "mfcr2_double_answer")) {
17233             confp->mfcr2.double_answer = ast_true(v->value) ? 1 : 0;
17234          } else if (!strcasecmp(v->name, "mfcr2_charge_calls")) {
17235             confp->mfcr2.charge_calls = ast_true(v->value) ? 1 : 0;
17236          } else if (!strcasecmp(v->name, "mfcr2_accept_on_offer")) {
17237             confp->mfcr2.accept_on_offer = ast_true(v->value) ? 1 : 0;
17238          } else if (!strcasecmp(v->name, "mfcr2_allow_collect_calls")) {
17239             confp->mfcr2.allow_collect_calls = ast_true(v->value) ? 1 : 0;
17240          } else if (!strcasecmp(v->name, "mfcr2_forced_release")) {
17241             confp->mfcr2.forced_release = ast_true(v->value) ? 1 : 0;
17242          } else if (!strcasecmp(v->name, "mfcr2_immediate_accept")) {
17243             confp->mfcr2.immediate_accept = ast_true(v->value) ? 1 : 0;
17244 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
17245          } else if (!strcasecmp(v->name, "mfcr2_skip_category")) {
17246             confp->mfcr2.skip_category_request = ast_true(v->value) ? 1 : 0;
17247 #endif
17248          } else if (!strcasecmp(v->name, "mfcr2_call_files")) {
17249             confp->mfcr2.call_files = ast_true(v->value) ? 1 : 0;
17250          } else if (!strcasecmp(v->name, "mfcr2_max_ani")) {
17251             confp->mfcr2.max_ani = atoi(v->value);
17252             if (confp->mfcr2.max_ani >= AST_MAX_EXTENSION){
17253                confp->mfcr2.max_ani = AST_MAX_EXTENSION - 1;
17254             }
17255          } else if (!strcasecmp(v->name, "mfcr2_max_dnis")) {
17256             confp->mfcr2.max_dnis = atoi(v->value);
17257             if (confp->mfcr2.max_dnis >= AST_MAX_EXTENSION){
17258                confp->mfcr2.max_dnis = AST_MAX_EXTENSION - 1;
17259             }
17260          } else if (!strcasecmp(v->name, "mfcr2_category")) {
17261             confp->mfcr2.category = openr2_proto_get_category(v->value);
17262             if (OR2_CALLING_PARTY_CATEGORY_UNKNOWN == confp->mfcr2.category) {
17263                confp->mfcr2.category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER;
17264                ast_log(LOG_WARNING, "Invalid MFC/R2 caller category '%s' at line %d. Using national subscriber as default.\n",
17265                      v->value, v->lineno);
17266             }
17267          } else if (!strcasecmp(v->name, "mfcr2_logging")) {
17268             openr2_log_level_t tmplevel;
17269             char *clevel;
17270             char *logval = ast_strdupa(v->value);
17271             while (logval) {
17272                clevel = strsep(&logval,",");
17273                if (-1 == (tmplevel = openr2_log_get_level(clevel))) {
17274                   ast_log(LOG_WARNING, "Ignoring invalid logging level: '%s' at line %d.\n", clevel, v->lineno);
17275                   continue;
17276                }
17277                confp->mfcr2.loglevel |= tmplevel;
17278             }
17279 #endif /* HAVE_OPENR2 */
17280          } else if (!strcasecmp(v->name, "cadence")) {
17281             /* setup to scan our argument */
17282             int element_count, c[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
17283             int i;
17284             struct dahdi_ring_cadence new_cadence;
17285             int cid_location = -1;
17286             int firstcadencepos = 0;
17287             char original_args[80];
17288             int cadence_is_ok = 1;
17289 
17290             ast_copy_string(original_args, v->value, sizeof(original_args));
17291             /* 16 cadences allowed (8 pairs) */
17292             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]);
17293 
17294             /* Cadence must be even (on/off) */
17295             if (element_count % 2 == 1) {
17296                ast_log(LOG_ERROR, "Must be a silence duration for each ring duration: %s at line %d.\n", original_args, v->lineno);
17297                cadence_is_ok = 0;
17298             }
17299 
17300             /* Ring cadences cannot be negative */
17301             for (i = 0; i < element_count; i++) {
17302                if (c[i] == 0) {
17303                   ast_log(LOG_ERROR, "Ring or silence duration cannot be zero: %s at line %d.\n", original_args, v->lineno);
17304                   cadence_is_ok = 0;
17305                   break;
17306                } else if (c[i] < 0) {
17307                   if (i % 2 == 1) {
17308                      /* Silence duration, negative possibly okay */
17309                      if (cid_location == -1) {
17310                         cid_location = i;
17311                         c[i] *= -1;
17312                      } else {
17313                         ast_log(LOG_ERROR, "CID location specified twice: %s at line %d.\n", original_args, v->lineno);
17314                         cadence_is_ok = 0;
17315                         break;
17316                      }
17317                   } else {
17318                      if (firstcadencepos == 0) {
17319                         firstcadencepos = i; /* only recorded to avoid duplicate specification */
17320                                  /* duration will be passed negative to the DAHDI driver */
17321                      } else {
17322                          ast_log(LOG_ERROR, "First cadence position specified twice: %s at line %d.\n", original_args, v->lineno);
17323                         cadence_is_ok = 0;
17324                         break;
17325                      }
17326                   }
17327                }
17328             }
17329 
17330             /* Substitute our scanned cadence */
17331             for (i = 0; i < 16; i++) {
17332                new_cadence.ringcadence[i] = c[i];
17333             }
17334 
17335             if (cadence_is_ok) {
17336                /* ---we scanned it without getting annoyed; now some sanity checks--- */
17337                if (element_count < 2) {
17338                   ast_log(LOG_ERROR, "Minimum cadence is ring,pause: %s at line %d.\n", original_args, v->lineno);
17339                } else {
17340                   if (cid_location == -1) {
17341                      /* user didn't say; default to first pause */
17342                      cid_location = 1;
17343                   } else {
17344                      /* convert element_index to cidrings value */
17345                      cid_location = (cid_location + 1) / 2;
17346                   }
17347                   /* ---we like their cadence; try to install it--- */
17348                   if (!user_has_defined_cadences++)
17349                      /* this is the first user-defined cadence; clear the default user cadences */
17350                      num_cadence = 0;
17351                   if ((num_cadence+1) >= NUM_CADENCE_MAX)
17352                      ast_log(LOG_ERROR, "Already %d cadences; can't add another: %s at line %d.\n", NUM_CADENCE_MAX, original_args, v->lineno);
17353                   else {
17354                      cadences[num_cadence] = new_cadence;
17355                      cidrings[num_cadence++] = cid_location;
17356                      ast_verb(3, "cadence 'r%d' added: %s\n",num_cadence,original_args);
17357                   }
17358                }
17359             }
17360          } else if (!strcasecmp(v->name, "ringtimeout")) {
17361             ringt_base = (atoi(v->value) * 8) / READ_SIZE;
17362          } else if (!strcasecmp(v->name, "prewink")) {
17363             confp->timing.prewinktime = atoi(v->value);
17364          } else if (!strcasecmp(v->name, "preflash")) {
17365             confp->timing.preflashtime = atoi(v->value);
17366          } else if (!strcasecmp(v->name, "wink")) {
17367             confp->timing.winktime = atoi(v->value);
17368          } else if (!strcasecmp(v->name, "flash")) {
17369             confp->timing.flashtime = atoi(v->value);
17370          } else if (!strcasecmp(v->name, "start")) {
17371             confp->timing.starttime = atoi(v->value);
17372          } else if (!strcasecmp(v->name, "rxwink")) {
17373             confp->timing.rxwinktime = atoi(v->value);
17374          } else if (!strcasecmp(v->name, "rxflash")) {
17375             confp->timing.rxflashtime = atoi(v->value);
17376          } else if (!strcasecmp(v->name, "debounce")) {
17377             confp->timing.debouncetime = atoi(v->value);
17378          } else if (!strcasecmp(v->name, "toneduration")) {
17379             int toneduration;
17380             int ctlfd;
17381             int res;
17382             struct dahdi_dialparams dps;
17383 
17384             ctlfd = open("/dev/dahdi/ctl", O_RDWR);
17385             if (ctlfd == -1) {
17386                ast_log(LOG_ERROR, "Unable to open /dev/dahdi/ctl to set toneduration at line %d.\n", v->lineno);
17387                return -1;
17388             }
17389 
17390             toneduration = atoi(v->value);
17391             if (toneduration > -1) {
17392                memset(&dps, 0, sizeof(dps));
17393 
17394                dps.dtmf_tonelen = dps.mfv1_tonelen = toneduration;
17395                res = ioctl(ctlfd, DAHDI_SET_DIALPARAMS, &dps);
17396                if (res < 0) {
17397                   ast_log(LOG_ERROR, "Invalid tone duration: %d ms at line %d: %s\n", toneduration, v->lineno, strerror(errno));
17398                   close(ctlfd);
17399                   return -1;
17400                }
17401             }
17402             close(ctlfd);
17403          } else if (!strcasecmp(v->name, "defaultcic")) {
17404             ast_copy_string(defaultcic, v->value, sizeof(defaultcic));
17405          } else if (!strcasecmp(v->name, "defaultozz")) {
17406             ast_copy_string(defaultozz, v->value, sizeof(defaultozz));
17407          } else if (!strcasecmp(v->name, "mwilevel")) {
17408             mwilevel = atoi(v->value);
17409          } else if (!strcasecmp(v->name, "dtmfcidlevel")) {
17410             dtmfcid_level = atoi(v->value);
17411          } else if (!strcasecmp(v->name, "reportalarms")) {
17412             if (!strcasecmp(v->value, "all"))
17413                report_alarms = REPORT_CHANNEL_ALARMS | REPORT_SPAN_ALARMS;
17414             if (!strcasecmp(v->value, "none"))
17415                report_alarms = 0;
17416             else if (!strcasecmp(v->value, "channels"))
17417                report_alarms = REPORT_CHANNEL_ALARMS;
17418             else if (!strcasecmp(v->value, "spans"))
17419                report_alarms = REPORT_SPAN_ALARMS;
17420           }
17421       } else if (!(options & PROC_DAHDI_OPT_NOWARN) )
17422          ast_log(LOG_WARNING, "Ignoring any changes to '%s' (on reload) at line %d.\n", v->name, v->lineno);
17423    }
17424    if (dahdichan[0]) {
17425       /* The user has set 'dahdichan' */
17426       /*< \todo pass proper line number instead of 0 */
17427       if (build_channels(confp, dahdichan, reload, 0, &found_pseudo)) {
17428          return -1;
17429       }
17430    }
17431 
17432    /* mark the first channels of each DAHDI span to watch for their span alarms */
17433    for (tmp = iflist, y=-1; tmp; tmp = tmp->next) {
17434       if (!tmp->destroy && tmp->span != y) {
17435          tmp->manages_span_alarms = 1;
17436          y = tmp->span; 
17437       } else {
17438          tmp->manages_span_alarms = 0;
17439       }
17440    }
17441 
17442    /*< \todo why check for the pseudo in the per-channel section.
17443     * Any actual use for manual setup of the pseudo channel? */
17444    if (!found_pseudo && reload != 1) {
17445       /* use the default configuration for a channel, so
17446          that any settings from real configured channels
17447          don't "leak" into the pseudo channel config
17448       */
17449       struct dahdi_chan_conf conf = dahdi_chan_conf_default();
17450 
17451       if (conf.chan.cc_params) {
17452          tmp = mkintf(CHAN_PSEUDO, &conf, reload);
17453       } else {
17454          tmp = NULL;
17455       }
17456       if (tmp) {
17457          ast_verb(3, "Automatically generated pseudo channel\n");
17458       } else {
17459          ast_log(LOG_WARNING, "Unable to register pseudo channel!\n");
17460       }
17461       ast_cc_config_params_destroy(conf.chan.cc_params);
17462    }
17463    return 0;
17464 }
17465 
17466 /*!
17467  * \internal
17468  * \brief Deep copy struct dahdi_chan_conf.
17469  * \since 1.8
17470  *
17471  * \param dest Destination.
17472  * \param src Source.
17473  *
17474  * \return Nothing
17475  */
17476 static void deep_copy_dahdi_chan_conf(struct dahdi_chan_conf *dest, const struct dahdi_chan_conf *src)
17477 {
17478    struct ast_cc_config_params *cc_params;
17479 
17480    cc_params = dest->chan.cc_params;
17481    *dest = *src;
17482    dest->chan.cc_params = cc_params;
17483    ast_cc_copy_config_params(dest->chan.cc_params, src->chan.cc_params);
17484 }
17485 
17486 /*!
17487  * \internal
17488  * \brief Setup DAHDI channel driver.
17489  *
17490  * \param reload enum: load_module(0), reload(1), restart(2).
17491  * \param base_conf Default config parameters.  So cc_params can be properly destroyed.
17492  * \param conf Local config parameters.  So cc_params can be properly destroyed.
17493  *
17494  * \retval 0 on success.
17495  * \retval -1 on error.
17496  */
17497 static int setup_dahdi_int(int reload, struct dahdi_chan_conf *base_conf, struct dahdi_chan_conf *conf)
17498 {
17499    struct ast_config *cfg;
17500    struct ast_config *ucfg;
17501    struct ast_variable *v;
17502    struct ast_flags config_flags = { reload == 1 ? CONFIG_FLAG_FILEUNCHANGED : 0 };
17503    const char *cat;
17504    int res;
17505 
17506 #ifdef HAVE_PRI
17507    char *c;
17508    int spanno;
17509    int i;
17510    int logicalspan;
17511    int trunkgroup;
17512    int dchannels[SIG_PRI_NUM_DCHANS];
17513 #endif
17514 
17515    cfg = ast_config_load(config, config_flags);
17516 
17517    /* Error if we have no config file */
17518    if (!cfg) {
17519       ast_log(LOG_ERROR, "Unable to load config %s\n", config);
17520       return 0;
17521    } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
17522       ucfg = ast_config_load("users.conf", config_flags);
17523       if (ucfg == CONFIG_STATUS_FILEUNCHANGED) {
17524          return 0;
17525       } else if (ucfg == CONFIG_STATUS_FILEINVALID) {
17526          ast_log(LOG_ERROR, "File users.conf cannot be parsed.  Aborting.\n");
17527          return 0;
17528       }
17529       ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
17530       if ((cfg = ast_config_load(config, config_flags)) == CONFIG_STATUS_FILEINVALID) {
17531          ast_log(LOG_ERROR, "File %s cannot be parsed.  Aborting.\n", config);
17532          ast_config_destroy(ucfg);
17533          return 0;
17534       }
17535    } else if (cfg == CONFIG_STATUS_FILEINVALID) {
17536       ast_log(LOG_ERROR, "File %s cannot be parsed.  Aborting.\n", config);
17537       return 0;
17538    } else {
17539       ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
17540       if ((ucfg = ast_config_load("users.conf", config_flags)) == CONFIG_STATUS_FILEINVALID) {
17541          ast_log(LOG_ERROR, "File users.conf cannot be parsed.  Aborting.\n");
17542          ast_config_destroy(cfg);
17543          return 0;
17544       }
17545    }
17546 
17547    /* It's a little silly to lock it, but we might as well just to be sure */
17548    ast_mutex_lock(&iflock);
17549 #ifdef HAVE_PRI
17550    if (reload != 1) {
17551       /* Process trunkgroups first */
17552       v = ast_variable_browse(cfg, "trunkgroups");
17553       while (v) {
17554          if (!strcasecmp(v->name, "trunkgroup")) {
17555             trunkgroup = atoi(v->value);
17556             if (trunkgroup > 0) {
17557                if ((c = strchr(v->value, ','))) {
17558                   i = 0;
17559                   memset(dchannels, 0, sizeof(dchannels));
17560                   while (c && (i < SIG_PRI_NUM_DCHANS)) {
17561                      dchannels[i] = atoi(c + 1);
17562                      if (dchannels[i] < 0) {
17563                         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);
17564                      } else
17565                         i++;
17566                      c = strchr(c + 1, ',');
17567                   }
17568                   if (i) {
17569                      if (pri_create_trunkgroup(trunkgroup, dchannels)) {
17570                         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);
17571                   } else
17572                         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");
17573                   } else
17574                      ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
17575                } else
17576                   ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
17577             } else
17578                ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of chan_dahdi.conf\n", v->lineno);
17579          } else if (!strcasecmp(v->name, "spanmap")) {
17580             spanno = atoi(v->value);
17581             if (spanno > 0) {
17582                if ((c = strchr(v->value, ','))) {
17583                   trunkgroup = atoi(c + 1);
17584                   if (trunkgroup > 0) {
17585                      if ((c = strchr(c + 1, ',')))
17586                         logicalspan = atoi(c + 1);
17587                      else
17588                         logicalspan = 0;
17589                      if (logicalspan >= 0) {
17590                         if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) {
17591                            ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
17592                      } else
17593                            ast_verb(2, "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
17594                      } else
17595                         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);
17596                   } else
17597                      ast_log(LOG_WARNING, "Trunk group must be a postive number at line %d of chan_dahdi.conf\n", v->lineno);
17598                } else
17599                   ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of chan_dahdi.conf\n", v->lineno);
17600             } else
17601                ast_log(LOG_WARNING, "Span number must be a postive integer at line %d of chan_dahdi.conf\n", v->lineno);
17602          } else {
17603             ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name);
17604          }
17605          v = v->next;
17606       }
17607    }
17608 #endif
17609 
17610    /* Copy the default jb config over global_jbconf */
17611    memcpy(&global_jbconf, &default_jbconf, sizeof(global_jbconf));
17612 
17613    mwimonitornotify[0] = '\0';
17614 
17615    v = ast_variable_browse(cfg, "channels");
17616    if ((res = process_dahdi(base_conf, "", v, reload, 0))) {
17617       ast_mutex_unlock(&iflock);
17618       ast_config_destroy(cfg);
17619       if (ucfg) {
17620          ast_config_destroy(ucfg);
17621       }
17622       return res;
17623    }
17624 
17625    /* Now get configuration from all normal sections in chan_dahdi.conf: */
17626    for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) {
17627       /* [channels] and [trunkgroups] are used. Let's also reserve
17628        * [globals] and [general] for future use
17629        */
17630       if (!strcasecmp(cat, "general") ||
17631          !strcasecmp(cat, "trunkgroups") ||
17632          !strcasecmp(cat, "globals") ||
17633          !strcasecmp(cat, "channels")) {
17634          continue;
17635       }
17636 
17637       /* Copy base_conf to conf. */
17638       deep_copy_dahdi_chan_conf(conf, base_conf);
17639 
17640       if ((res = process_dahdi(conf, cat, ast_variable_browse(cfg, cat), reload, PROC_DAHDI_OPT_NOCHAN))) {
17641          ast_mutex_unlock(&iflock);
17642          ast_config_destroy(cfg);
17643          if (ucfg) {
17644             ast_config_destroy(ucfg);
17645          }
17646          return res;
17647       }
17648    }
17649 
17650    ast_config_destroy(cfg);
17651 
17652    if (ucfg) {
17653       const char *chans;
17654 
17655       process_dahdi(base_conf, "", ast_variable_browse(ucfg, "general"), 1, 0);
17656 
17657       for (cat = ast_category_browse(ucfg, NULL); cat ; cat = ast_category_browse(ucfg, cat)) {
17658          if (!strcasecmp(cat, "general")) {
17659             continue;
17660          }
17661 
17662          chans = ast_variable_retrieve(ucfg, cat, "dahdichan");
17663 
17664          if (ast_strlen_zero(chans)) {
17665             continue;
17666          }
17667 
17668          /* Copy base_conf to conf. */
17669          deep_copy_dahdi_chan_conf(conf, base_conf);
17670 
17671          if ((res = process_dahdi(conf, cat, ast_variable_browse(ucfg, cat), reload, PROC_DAHDI_OPT_NOCHAN | PROC_DAHDI_OPT_NOWARN))) {
17672             ast_config_destroy(ucfg);
17673             ast_mutex_unlock(&iflock);
17674             return res;
17675          }
17676       }
17677       ast_config_destroy(ucfg);
17678    }
17679    ast_mutex_unlock(&iflock);
17680 
17681 #ifdef HAVE_PRI
17682    if (reload != 1) {
17683       int x;
17684       for (x = 0; x < NUM_SPANS; x++) {
17685          if (pris[x].pri.pvts[0]) {
17686             prepare_pri(pris + x);
17687             if (sig_pri_start_pri(&pris[x].pri)) {
17688                ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1);
17689                return -1;
17690             } else
17691                ast_verb(2, "Starting D-Channel on span %d\n", x + 1);
17692          }
17693       }
17694    }
17695 #endif
17696 #if defined(HAVE_SS7)
17697    if (reload != 1) {
17698       int x;
17699       for (x = 0; x < NUM_SPANS; x++) {
17700          if (linksets[x].ss7.ss7) {
17701             linksets[x].ss7.calls = &dahdi_ss7_callbacks;
17702             if (ast_pthread_create(&linksets[x].ss7.master, NULL, ss7_linkset, &linksets[x].ss7)) {
17703                ast_log(LOG_ERROR, "Unable to start SS7 linkset on span %d\n", x + 1);
17704                return -1;
17705             } else
17706                ast_verb(2, "Starting SS7 linkset on span %d\n", x + 1);
17707          }
17708       }
17709    }
17710 #endif   /* defined(HAVE_SS7) */
17711 #ifdef HAVE_OPENR2
17712    if (reload != 1) {
17713       int x;
17714       for (x = 0; x < r2links_count; x++) {
17715          if (ast_pthread_create(&r2links[x]->r2master, NULL, mfcr2_monitor, r2links[x])) {
17716             ast_log(LOG_ERROR, "Unable to start R2 monitor on channel group %d\n", x + 1);
17717             return -1;
17718          } else {
17719             ast_verb(2, "Starting R2 monitor on channel group %d\n", x + 1);
17720          }
17721       }
17722    }
17723 #endif
17724    /* And start the monitor for the first time */
17725    restart_monitor();
17726    return 0;
17727 }
17728 
17729 /*!
17730  * \internal
17731  * \brief Setup DAHDI channel driver.
17732  *
17733  * \param reload enum: load_module(0), reload(1), restart(2).
17734  *
17735  * \retval 0 on success.
17736  * \retval -1 on error.
17737  */
17738 static int setup_dahdi(int reload)
17739 {
17740    int res;
17741    struct dahdi_chan_conf base_conf = dahdi_chan_conf_default();
17742    struct dahdi_chan_conf conf = dahdi_chan_conf_default();
17743 
17744    if (base_conf.chan.cc_params && conf.chan.cc_params) {
17745       res = setup_dahdi_int(reload, &base_conf, &conf);
17746    } else {
17747       res = -1;
17748    }
17749    ast_cc_config_params_destroy(base_conf.chan.cc_params);
17750    ast_cc_config_params_destroy(conf.chan.cc_params);
17751 
17752    return res;
17753 }
17754 
17755 /*!
17756  * \internal
17757  * \brief Callback used to generate the dahdi status tree.
17758  * \param[in] search The search pattern tree.
17759  * \retval NULL on error.
17760  * \retval non-NULL The generated tree.
17761  */
17762 static int dahdi_status_data_provider_get(const struct ast_data_search *search,
17763       struct ast_data *data_root)
17764 {
17765    int ctl, res, span;
17766    struct ast_data *data_span, *data_alarms;
17767    struct dahdi_spaninfo s;
17768 
17769    ctl = open("/dev/dahdi/ctl", O_RDWR);
17770    if (ctl < 0) {
17771       ast_log(LOG_ERROR, "No DAHDI found. Unable to open /dev/dahdi/ctl: %s\n", strerror(errno));
17772       return -1;
17773    }
17774    for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
17775       s.spanno = span;
17776       res = ioctl(ctl, DAHDI_SPANSTAT, &s);
17777       if (res) {
17778          continue;
17779       }
17780 
17781       data_span = ast_data_add_node(data_root, "span");
17782       if (!data_span) {
17783          continue;
17784       }
17785       ast_data_add_str(data_span, "description", s.desc);
17786 
17787       /* insert the alarms status */
17788       data_alarms = ast_data_add_node(data_span, "alarms");
17789       if (!data_alarms) {
17790          continue;
17791       }
17792 
17793       ast_data_add_bool(data_alarms, "BLUE", s.alarms & DAHDI_ALARM_BLUE);
17794       ast_data_add_bool(data_alarms, "YELLOW", s.alarms & DAHDI_ALARM_YELLOW);
17795       ast_data_add_bool(data_alarms, "RED", s.alarms & DAHDI_ALARM_RED);
17796       ast_data_add_bool(data_alarms, "LOOPBACK", s.alarms & DAHDI_ALARM_LOOPBACK);
17797       ast_data_add_bool(data_alarms, "RECOVER", s.alarms & DAHDI_ALARM_RECOVER);
17798       ast_data_add_bool(data_alarms, "NOTOPEN", s.alarms & DAHDI_ALARM_NOTOPEN);
17799 
17800       ast_data_add_int(data_span, "irqmisses", s.irqmisses);
17801       ast_data_add_int(data_span, "bpviol", s.bpvcount);
17802       ast_data_add_int(data_span, "crc4", s.crc4count);
17803       ast_data_add_str(data_span, "framing", s.lineconfig & DAHDI_CONFIG_D4 ? "D4" :
17804                      s.lineconfig & DAHDI_CONFIG_ESF ? "ESF" :
17805                      s.lineconfig & DAHDI_CONFIG_CCS ? "CCS" :
17806                      "CAS");
17807       ast_data_add_str(data_span, "coding",  s.lineconfig & DAHDI_CONFIG_B8ZS ? "B8ZS" :
17808                      s.lineconfig & DAHDI_CONFIG_HDB3 ? "HDB3" :
17809                      s.lineconfig & DAHDI_CONFIG_AMI ? "AMI" :
17810                      "Unknown");
17811       ast_data_add_str(data_span, "options", s.lineconfig & DAHDI_CONFIG_CRC4 ?
17812                      s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" :
17813                      s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "YEL" : "");
17814       ast_data_add_str(data_span, "lbo", lbostr[s.lbo]);
17815 
17816       /* if this span doesn't match remove it. */
17817       if (!ast_data_search_match(search, data_span)) {
17818          ast_data_remove_node(data_root, data_span);
17819       }
17820    }
17821    close(ctl);
17822 
17823    return 0;
17824 }
17825 
17826 /*!
17827  * \internal
17828  * \brief Callback used to generate the dahdi channels tree.
17829  * \param[in] search The search pattern tree.
17830  * \retval NULL on error.
17831  * \retval non-NULL The generated tree.
17832  */
17833 static int dahdi_channels_data_provider_get(const struct ast_data_search *search,
17834       struct ast_data *data_root)
17835 {
17836    struct dahdi_pvt *tmp;
17837    struct ast_data *data_channel;
17838 
17839    ast_mutex_lock(&iflock);
17840    for (tmp = iflist; tmp; tmp = tmp->next) {
17841       data_channel = ast_data_add_node(data_root, "channel");
17842       if (!data_channel) {
17843          continue;
17844       }
17845 
17846       ast_data_add_structure(dahdi_pvt, data_channel, tmp);
17847 
17848       /* if this channel doesn't match remove it. */
17849       if (!ast_data_search_match(search, data_channel)) {
17850          ast_data_remove_node(data_root, data_channel);
17851       }
17852    }
17853    ast_mutex_unlock(&iflock);
17854 
17855    return 0;
17856 }
17857 
17858 /*!
17859  * \internal
17860  * \brief Callback used to generate the dahdi channels tree.
17861  * \param[in] search The search pattern tree.
17862  * \retval NULL on error.
17863  * \retval non-NULL The generated tree.
17864  */
17865 static int dahdi_version_data_provider_get(const struct ast_data_search *search,
17866       struct ast_data *data_root)
17867 {
17868    int pseudo_fd = -1;
17869    struct dahdi_versioninfo vi = {
17870       .version = "Unknown",
17871       .echo_canceller = "Unknown"
17872    };
17873 
17874    if ((pseudo_fd = open("/dev/dahdi/ctl", O_RDONLY)) < 0) {
17875       ast_log(LOG_ERROR, "Failed to open control file to get version.\n");
17876       return -1;
17877    }
17878 
17879    if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi)) {
17880       ast_log(LOG_ERROR, "Failed to get DAHDI version: %s\n", strerror(errno));
17881    }
17882 
17883    close(pseudo_fd);
17884 
17885    ast_data_add_str(data_root, "value", vi.version);
17886    ast_data_add_str(data_root, "echocanceller", vi.echo_canceller);
17887 
17888    return 0;
17889 }
17890 
17891 static const struct ast_data_handler dahdi_status_data_provider = {
17892    .version = AST_DATA_HANDLER_VERSION,
17893    .get = dahdi_status_data_provider_get
17894 };
17895 
17896 static const struct ast_data_handler dahdi_channels_data_provider = {
17897    .version = AST_DATA_HANDLER_VERSION,
17898    .get = dahdi_channels_data_provider_get
17899 };
17900 
17901 static const struct ast_data_handler dahdi_version_data_provider = {
17902    .version = AST_DATA_HANDLER_VERSION,
17903    .get = dahdi_version_data_provider_get
17904 };
17905 
17906 static const struct ast_data_entry dahdi_data_providers[] = {
17907    AST_DATA_ENTRY("asterisk/channel/dahdi/status", &dahdi_status_data_provider),
17908    AST_DATA_ENTRY("asterisk/channel/dahdi/channels", &dahdi_channels_data_provider),
17909    AST_DATA_ENTRY("asterisk/channel/dahdi/version", &dahdi_version_data_provider)
17910 };
17911 
17912 static int load_module(void)
17913 {
17914    int res;
17915 #if defined(HAVE_PRI) || defined(HAVE_SS7)
17916    int y;
17917 #endif   /* defined(HAVE_PRI) || defined(HAVE_SS7) */
17918 
17919 #ifdef HAVE_PRI
17920    memset(pris, 0, sizeof(pris));
17921    for (y = 0; y < NUM_SPANS; y++) {
17922       sig_pri_init_pri(&pris[y].pri);
17923    }
17924    pri_set_error(dahdi_pri_error);
17925    pri_set_message(dahdi_pri_message);
17926    ast_register_application_xml(dahdi_send_keypad_facility_app, dahdi_send_keypad_facility_exec);
17927 #ifdef HAVE_PRI_PROG_W_CAUSE
17928    ast_register_application_xml(dahdi_send_callrerouting_facility_app, dahdi_send_callrerouting_facility_exec);
17929 #endif
17930 #if defined(HAVE_PRI_CCSS)
17931    if (ast_cc_agent_register(&dahdi_pri_cc_agent_callbacks)
17932       || ast_cc_monitor_register(&dahdi_pri_cc_monitor_callbacks)) {
17933       __unload_module();
17934       return AST_MODULE_LOAD_FAILURE;
17935    }
17936 #endif   /* defined(HAVE_PRI_CCSS) */
17937    if (sig_pri_load(
17938 #if defined(HAVE_PRI_CCSS)
17939       dahdi_pri_cc_type
17940 #else
17941       NULL
17942 #endif   /* defined(HAVE_PRI_CCSS) */
17943       )) {
17944       __unload_module();
17945       return AST_MODULE_LOAD_FAILURE;
17946    }
17947 #endif
17948 #if defined(HAVE_SS7)
17949    memset(linksets, 0, sizeof(linksets));
17950    for (y = 0; y < NUM_SPANS; y++) {
17951       sig_ss7_init_linkset(&linksets[y].ss7);
17952    }
17953    ss7_set_error(dahdi_ss7_error);
17954    ss7_set_message(dahdi_ss7_message);
17955 #endif   /* defined(HAVE_SS7) */
17956    res = setup_dahdi(0);
17957    /* Make sure we can register our DAHDI channel type */
17958    if (res)
17959       return AST_MODULE_LOAD_DECLINE;
17960    if (ast_channel_register(&dahdi_tech)) {
17961       ast_log(LOG_ERROR, "Unable to register channel class 'DAHDI'\n");
17962       __unload_module();
17963       return AST_MODULE_LOAD_FAILURE;
17964    }
17965 #ifdef HAVE_PRI
17966    ast_cli_register_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
17967 #endif
17968 #if defined(HAVE_SS7)
17969    ast_cli_register_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
17970 #endif   /* defined(HAVE_SS7) */
17971 #ifdef HAVE_OPENR2
17972    ast_cli_register_multiple(dahdi_mfcr2_cli, ARRAY_LEN(dahdi_mfcr2_cli));
17973    ast_register_application_xml(dahdi_accept_r2_call_app, dahdi_accept_r2_call_exec);
17974 #endif
17975 
17976    ast_cli_register_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli));
17977    /* register all the data providers */
17978    ast_data_register_multiple(dahdi_data_providers, ARRAY_LEN(dahdi_data_providers));
17979    memset(round_robin, 0, sizeof(round_robin));
17980    ast_manager_register_xml("DAHDITransfer", 0, action_transfer);
17981    ast_manager_register_xml("DAHDIHangup", 0, action_transferhangup);
17982    ast_manager_register_xml("DAHDIDialOffhook", 0, action_dahdidialoffhook);
17983    ast_manager_register_xml("DAHDIDNDon", 0, action_dahdidndon);
17984    ast_manager_register_xml("DAHDIDNDoff", 0, action_dahdidndoff);
17985    ast_manager_register_xml("DAHDIShowChannels", 0, action_dahdishowchannels);
17986    ast_manager_register_xml("DAHDIRestart", 0, action_dahdirestart);
17987 
17988    ast_cond_init(&ss_thread_complete, NULL);
17989 
17990    return res;
17991 }
17992 
17993 static int dahdi_sendtext(struct ast_channel *c, const char *text)
17994 {
17995 #define  END_SILENCE_LEN 400
17996 #define  HEADER_MS 50
17997 #define  TRAILER_MS 5
17998 #define  HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8)
17999 #define  ASCII_BYTES_PER_CHAR 80
18000 
18001    unsigned char *buf,*mybuf;
18002    struct dahdi_pvt *p = c->tech_pvt;
18003    struct pollfd fds[1];
18004    int size,res,fd,len,x;
18005    int bytes=0;
18006    /* Initial carrier (imaginary) */
18007    float cr = 1.0;
18008    float ci = 0.0;
18009    float scont = 0.0;
18010    int idx;
18011 
18012    idx = dahdi_get_index(c, p, 0);
18013    if (idx < 0) {
18014       ast_log(LOG_WARNING, "Huh?  I don't exist?\n");
18015       return -1;
18016    }
18017    if (!text[0]) return(0); /* if nothing to send, don't */
18018    if ((!p->tdd) && (!p->mate)) return(0);  /* if not in TDD mode, just return */
18019    if (p->mate)
18020       buf = ast_malloc(((strlen(text) + 1) * ASCII_BYTES_PER_CHAR) + END_SILENCE_LEN + HEADER_LEN);
18021    else
18022       buf = ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN);
18023    if (!buf)
18024       return -1;
18025    mybuf = buf;
18026    if (p->mate) {
18027       int codec = AST_LAW(p);
18028       for (x = 0; x < HEADER_MS; x++) {   /* 50 ms of Mark */
18029          PUT_CLID_MARKMS;
18030       }
18031       /* Put actual message */
18032       for (x = 0; text[x]; x++) {
18033          PUT_CLID(text[x]);
18034       }
18035       for (x = 0; x < TRAILER_MS; x++) {  /* 5 ms of Mark */
18036          PUT_CLID_MARKMS;
18037       }
18038       len = bytes;
18039       buf = mybuf;
18040    } else {
18041       len = tdd_generate(p->tdd, buf, text);
18042       if (len < 1) {
18043          ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text));
18044          ast_free(mybuf);
18045          return -1;
18046       }
18047    }
18048    memset(buf + len, 0x7f, END_SILENCE_LEN);
18049    len += END_SILENCE_LEN;
18050    fd = p->subs[idx].dfd;
18051    while (len) {
18052       if (ast_check_hangup(c)) {
18053          ast_free(mybuf);
18054          return -1;
18055       }
18056       size = len;
18057       if (size > READ_SIZE)
18058          size = READ_SIZE;
18059       fds[0].fd = fd;
18060       fds[0].events = POLLOUT | POLLPRI;
18061       fds[0].revents = 0;
18062       res = poll(fds, 1, -1);
18063       if (!res) {
18064          ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
18065          continue;
18066       }
18067       /* if got exception */
18068       if (fds[0].revents & POLLPRI) {
18069          ast_free(mybuf);
18070          return -1;
18071       }
18072       if (!(fds[0].revents & POLLOUT)) {
18073          ast_debug(1, "write fd not ready on channel %d\n", p->channel);
18074          continue;
18075       }
18076       res = write(fd, buf, size);
18077       if (res != size) {
18078          if (res == -1) {
18079             ast_free(mybuf);
18080             return -1;
18081          }
18082          ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
18083          break;
18084       }
18085       len -= size;
18086       buf += size;
18087    }
18088    ast_free(mybuf);
18089    return(0);
18090 }
18091 
18092 
18093 static int reload(void)
18094 {
18095    int res = 0;
18096 
18097    res = setup_dahdi(1);
18098    if (res) {
18099       ast_log(LOG_WARNING, "Reload of chan_dahdi.so is unsuccessful!\n");
18100       return -1;
18101    }
18102    return 0;
18103 }
18104 
18105 /* This is a workaround so that menuselect displays a proper description
18106  * AST_MODULE_INFO(, , "DAHDI Telephony"
18107  */
18108 
18109 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, tdesc,
18110    .load = load_module,
18111    .unload = unload_module,
18112    .reload = reload,
18113    .load_pri = AST_MODPRI_CHANNEL_DRIVER,
18114       .nonoptreq = "res_smdi",
18115    );