Asterisk - The Open Source Telephony Project  18.5.0
chan_dahdi.c
Go to the documentation of this file.
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 1999 - 2008, Digium, Inc.
5  *
6  * Mark Spencer <[email protected]>
7  *
8  * See http://www.asterisk.org for more information about
9  * the Asterisk project. Please do not directly contact
10  * any of the maintainers of this project for assistance;
11  * the project provides a web site, mailing lists and IRC
12  * channels for your use.
13  *
14  * This program is free software, distributed under the terms of
15  * the GNU General Public License Version 2. See the LICENSE file
16  * at the top of the source tree.
17  */
18 
19 /*! \file
20  *
21  * \brief DAHDI for Pseudo TDM
22  *
23  * \author Mark Spencer <[email protected]>
24  *
25  * Connects to the DAHDI telephony library as well as
26  * libpri. Libpri is optional and needed only if you are
27  * going to use ISDN connections.
28  *
29  * You need to install libraries before you attempt to compile
30  * and install the DAHDI channel.
31  *
32  * \ingroup channel_drivers
33  *
34  * \todo Deprecate the "musiconhold" configuration option post 1.4
35  */
36 
37 /*! \li \ref chan_dahdi.c uses the configuration file \ref chan_dahdi.conf
38  * \addtogroup configuration_file
39  */
40 
41 /*! \page chan_dahdi.conf chan_dahdi.conf
42  * \verbinclude chan_dahdi.conf.sample
43  */
44 
45 /*** MODULEINFO
46  <depend>dahdi</depend>
47  <depend>tonezone</depend>
48  <use type="module">res_smdi</use>
49  <use type="external">pri</use>
50  <use type="external">ss7</use>
51  <use type="external">openr2</use>
52  <support_level>core</support_level>
53  ***/
54 
55 #include "asterisk.h"
56 
57 #if defined(__NetBSD__) || defined(__FreeBSD__)
58 #include <pthread.h>
59 #else
60 #include <sys/sysmacros.h>
61 #endif
62 #include <signal.h>
63 #include <sys/stat.h>
64 #include <math.h>
65 
66 #include "sig_analog.h"
67 /* Analog signaling is currently still present in chan_dahdi for use with
68  * radio. Sig_analog does not currently handle any radio operations. If
69  * radio only uses analog signaling, then the radio handling logic could
70  * be placed in sig_analog and the duplicated code could be removed.
71  */
72 
73 #if defined(HAVE_PRI)
74 #include "sig_pri.h"
75 #ifndef PRI_RESTART
76 #error "Upgrade your libpri"
77 #endif
78 #endif /* defined(HAVE_PRI) */
79 
80 #if defined(HAVE_SS7)
81 #include "sig_ss7.h"
82 #if !defined(LIBSS7_ABI_COMPATIBILITY)
83 #error "Upgrade your libss7"
84 #elif LIBSS7_ABI_COMPATIBILITY != 2
85 #error "Your installed libss7 is not compatible"
86 #endif
87 #endif /* defined(HAVE_SS7) */
88 
89 #if defined(HAVE_OPENR2)
90 /* put this here until sig_mfcr2 comes along */
91 #define SIG_MFCR2_MAX_CHANNELS 672 /*!< No more than a DS3 per trunk group */
92 #endif /* defined(HAVE_OPENR2) */
93 
94 #include "asterisk/lock.h"
95 #include "asterisk/channel.h"
96 #include "asterisk/config.h"
97 #include "asterisk/module.h"
98 #include "asterisk/pbx.h"
99 #include "asterisk/file.h"
100 #include "asterisk/ulaw.h"
101 #include "asterisk/alaw.h"
102 #include "asterisk/callerid.h"
103 #include "asterisk/adsi.h"
104 #include "asterisk/cli.h"
105 #include "asterisk/pickup.h"
106 #include "asterisk/features.h"
107 #include "asterisk/musiconhold.h"
108 #include "asterisk/say.h"
109 #include "asterisk/tdd.h"
110 #include "asterisk/mwi.h"
111 #include "asterisk/dsp.h"
112 #include "asterisk/astdb.h"
113 #include "asterisk/manager.h"
114 #include "asterisk/causes.h"
115 #include "asterisk/term.h"
116 #include "asterisk/utils.h"
117 #include "asterisk/transcap.h"
118 #include "asterisk/stringfields.h"
119 #include "asterisk/abstract_jb.h"
120 #include "asterisk/smdi.h"
121 #include "asterisk/devicestate.h"
122 #include "asterisk/paths.h"
123 #include "asterisk/ccss.h"
125 #include "asterisk/bridge.h"
127 #include "asterisk/parking.h"
128 #include "asterisk/format_cache.h"
129 #include "chan_dahdi.h"
131 
132 /*** DOCUMENTATION
133  <application name="DAHDISendKeypadFacility" language="en_US">
134  <synopsis>
135  Send digits out of band over a PRI.
136  </synopsis>
137  <syntax>
138  <parameter name="digits" required="true" />
139  </syntax>
140  <description>
141  <para>This application will send the given string of digits in a Keypad
142  Facility IE over the current channel.</para>
143  </description>
144  </application>
145  <application name="DAHDISendCallreroutingFacility" language="en_US">
146  <synopsis>
147  Send an ISDN call rerouting/deflection facility message.
148  </synopsis>
149  <syntax argsep=",">
150  <parameter name="destination" required="true">
151  <para>Destination number.</para>
152  </parameter>
153  <parameter name="original">
154  <para>Original called number.</para>
155  </parameter>
156  <parameter name="reason">
157  <para>Diversion reason, if not specified defaults to <literal>unknown</literal></para>
158  </parameter>
159  </syntax>
160  <description>
161  <para>This application will send an ISDN switch specific call
162  rerouting/deflection facility message over the current channel.
163  Supported switches depend upon the version of libpri in use.</para>
164  </description>
165  </application>
166  <application name="DAHDIAcceptR2Call" language="en_US">
167  <synopsis>
168  Accept an R2 call if its not already accepted (you still need to answer it)
169  </synopsis>
170  <syntax>
171  <parameter name="charge" required="true">
172  <para>Yes or No.</para>
173  <para>Whether you want to accept the call with charge or without charge.</para>
174  </parameter>
175  </syntax>
176  <description>
177  <para>This application will Accept the R2 call either with charge or no charge.</para>
178  </description>
179  </application>
180  <info name="CHANNEL" language="en_US" tech="DAHDI">
181  <enumlist>
182  <enum name="dahdi_channel">
183  <para>R/O DAHDI channel related to this channel.</para>
184  </enum>
185  <enum name="dahdi_span">
186  <para>R/O DAHDI span related to this channel.</para>
187  </enum>
188  <enum name="dahdi_group">
189  <para>R/O DAHDI logical group related to this channel.</para>
190  </enum>
191  <enum name="dahdi_type">
192  <para>R/O DAHDI channel type, one of:</para>
193  <enumlist>
194  <enum name="analog" />
195  <enum name="mfc/r2" />
196  <enum name="pri" />
197  <enum name="pseudo" />
198  <enum name="ss7" />
199  </enumlist>
200  </enum>
201  <enum name="keypad_digits">
202  <para>R/O PRI Keypad digits that came in with the SETUP message.</para>
203  </enum>
204  <enum name="reversecharge">
205  <para>R/O PRI Reverse Charging Indication, one of:</para>
206  <enumlist>
207  <enum name="-1"> <para>None</para></enum>
208  <enum name=" 1"> <para>Reverse Charging Requested</para></enum>
209  </enumlist>
210  </enum>
211  <enum name="no_media_path">
212  <para>R/O PRI Nonzero if the channel has no B channel.
213  The channel is either on hold or a call waiting call.</para>
214  </enum>
215  <enum name="buffers">
216  <para>W/O Change the channel's buffer policy (for the current call only)</para>
217  <para>This option takes two arguments:</para>
218  <para> Number of buffers,</para>
219  <para> Buffer policy being one of:</para>
220  <para> <literal>full</literal></para>
221  <para> <literal>immediate</literal></para>
222  <para> <literal>half</literal></para>
223  </enum>
224  <enum name="echocan_mode">
225  <para>W/O Change the configuration of the active echo
226  canceller on the channel (if any), for the current call
227  only.</para>
228  <para>Possible values are:</para>
229  <para> <literal>on</literal> Normal mode (the echo canceller is actually reinitalized)</para>
230  <para> <literal>off</literal> Disabled</para>
231  <para> <literal>fax</literal> FAX/data mode (NLP disabled if possible, otherwise
232  completely disabled)</para>
233  <para> <literal>voice</literal> Voice mode (returns from FAX mode, reverting the changes that were made)</para>
234  </enum>
235  </enumlist>
236  </info>
237  <manager name="DAHDITransfer" language="en_US">
238  <synopsis>
239  Transfer DAHDI Channel.
240  </synopsis>
241  <syntax>
242  <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
243  <parameter name="DAHDIChannel" required="true">
244  <para>DAHDI channel number to transfer.</para>
245  </parameter>
246  </syntax>
247  <description>
248  <para>Simulate a flash hook event by the user connected to the channel.</para>
249  <note><para>Valid only for analog channels.</para></note>
250  </description>
251  </manager>
252  <manager name="DAHDIHangup" language="en_US">
253  <synopsis>
254  Hangup DAHDI Channel.
255  </synopsis>
256  <syntax>
257  <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
258  <parameter name="DAHDIChannel" required="true">
259  <para>DAHDI channel number to hangup.</para>
260  </parameter>
261  </syntax>
262  <description>
263  <para>Simulate an on-hook event by the user connected to the channel.</para>
264  <note><para>Valid only for analog channels.</para></note>
265  </description>
266  </manager>
267  <manager name="DAHDIDialOffhook" language="en_US">
268  <synopsis>
269  Dial over DAHDI channel while offhook.
270  </synopsis>
271  <syntax>
272  <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
273  <parameter name="DAHDIChannel" required="true">
274  <para>DAHDI channel number to dial digits.</para>
275  </parameter>
276  <parameter name="Number" required="true">
277  <para>Digits to dial.</para>
278  </parameter>
279  </syntax>
280  <description>
281  <para>Generate DTMF control frames to the bridged peer.</para>
282  </description>
283  </manager>
284  <manager name="DAHDIDNDon" language="en_US">
285  <synopsis>
286  Toggle DAHDI channel Do Not Disturb status ON.
287  </synopsis>
288  <syntax>
289  <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
290  <parameter name="DAHDIChannel" required="true">
291  <para>DAHDI channel number to set DND on.</para>
292  </parameter>
293  </syntax>
294  <description>
295  <para>Equivalent to the CLI command "dahdi set dnd <variable>channel</variable> on".</para>
296  <note><para>Feature only supported by analog channels.</para></note>
297  </description>
298  </manager>
299  <manager name="DAHDIDNDoff" language="en_US">
300  <synopsis>
301  Toggle DAHDI channel Do Not Disturb status OFF.
302  </synopsis>
303  <syntax>
304  <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
305  <parameter name="DAHDIChannel" required="true">
306  <para>DAHDI channel number to set DND off.</para>
307  </parameter>
308  </syntax>
309  <description>
310  <para>Equivalent to the CLI command "dahdi set dnd <variable>channel</variable> off".</para>
311  <note><para>Feature only supported by analog channels.</para></note>
312  </description>
313  </manager>
314  <manager name="DAHDIShowChannels" language="en_US">
315  <synopsis>
316  Show status of DAHDI channels.
317  </synopsis>
318  <syntax>
319  <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
320  <parameter name="DAHDIChannel">
321  <para>Specify the specific channel number to show. Show all channels if zero or not present.</para>
322  </parameter>
323  </syntax>
324  <description>
325  <para>Similar to the CLI command "dahdi show channels".</para>
326  </description>
327  </manager>
328  <manager name="DAHDIRestart" language="en_US">
329  <synopsis>
330  Fully Restart DAHDI channels (terminates calls).
331  </synopsis>
332  <syntax>
333  <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
334  </syntax>
335  <description>
336  <para>Equivalent to the CLI command "dahdi restart".</para>
337  </description>
338  </manager>
339  <manager name="PRIShowSpans" language="en_US">
340  <synopsis>
341  Show status of PRI spans.
342  </synopsis>
343  <syntax>
344  <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
345  <parameter name="Span">
346  <para>Specify the specific span to show. Show all spans if zero or not present.</para>
347  </parameter>
348  </syntax>
349  <description>
350  <para>Similar to the CLI command "pri show spans".</para>
351  </description>
352  </manager>
353  <manager name="PRIDebugSet" language="en_US">
354  <synopsis>
355  Set PRI debug levels for a span
356  </synopsis>
357  <syntax>
358  <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
359  <parameter name="Span" required="true">
360  <para>Which span to affect.</para>
361  </parameter>
362  <parameter name="Level" required="true">
363  <para>What debug level to set. May be a numerical value or a text value from the list below</para>
364  <enumlist>
365  <enum name="off" />
366  <enum name="on" />
367  <enum name="hex" />
368  <enum name="intense" />
369  </enumlist>
370  </parameter>
371  </syntax>
372  <description>
373  <para>Equivalent to the CLI command "pri set debug &lt;level&gt; span &lt;span&gt;".</para>
374  </description>
375  </manager>
376  <manager name="PRIDebugFileSet" language="en_US">
377  <synopsis>
378  Set the file used for PRI debug message output
379  </synopsis>
380  <syntax>
381  <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
382  <parameter name="File" required="true">
383  <para>Path of file to write debug output.</para>
384  </parameter>
385  </syntax>
386  <description>
387  <para>Equivalent to the CLI command "pri set debug file &lt;output-file&gt;"</para>
388  </description>
389  </manager>
390  <manager name="PRIDebugFileUnset" language="en_US">
391  <synopsis>
392  Disables file output for PRI debug messages
393  </synopsis>
394  <syntax>
395  <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
396  </syntax>
397  </manager>
398  <managerEvent language="en_US" name="AlarmClear">
399  <managerEventInstance class="EVENT_FLAG_SYSTEM">
400  <synopsis>Raised when an alarm is cleared on a DAHDI channel.</synopsis>
401  <syntax>
402  <parameter name="DAHDIChannel">
403  <para>The DAHDI channel on which the alarm was cleared.</para>
404  <note><para>This is not an Asterisk channel identifier.</para></note>
405  </parameter>
406  </syntax>
407  </managerEventInstance>
408  </managerEvent>
409  <managerEvent language="en_US" name="SpanAlarmClear">
410  <managerEventInstance class="EVENT_FLAG_SYSTEM">
411  <synopsis>Raised when an alarm is cleared on a DAHDI span.</synopsis>
412  <syntax>
413  <parameter name="Span">
414  <para>The span on which the alarm was cleared.</para>
415  </parameter>
416  </syntax>
417  </managerEventInstance>
418  </managerEvent>
419  <managerEvent language="en_US" name="DNDState">
420  <managerEventInstance class="EVENT_FLAG_SYSTEM">
421  <synopsis>Raised when the Do Not Disturb state is changed on a DAHDI channel.</synopsis>
422  <syntax>
423  <parameter name="DAHDIChannel">
424  <para>The DAHDI channel on which DND status changed.</para>
425  <note><para>This is not an Asterisk channel identifier.</para></note>
426  </parameter>
427  <parameter name="Status">
428  <enumlist>
429  <enum name="enabled"/>
430  <enum name="disabled"/>
431  </enumlist>
432  </parameter>
433  </syntax>
434  </managerEventInstance>
435  </managerEvent>
436  <managerEvent language="en_US" name="Alarm">
437  <managerEventInstance class="EVENT_FLAG_SYSTEM">
438  <synopsis>Raised when an alarm is set on a DAHDI channel.</synopsis>
439  <syntax>
440  <parameter name="DAHDIChannel">
441  <para>The channel on which the alarm occurred.</para>
442  <note><para>This is not an Asterisk channel identifier.</para></note>
443  </parameter>
444  <parameter name="Alarm">
445  <para>A textual description of the alarm that occurred.</para>
446  </parameter>
447  </syntax>
448  </managerEventInstance>
449  </managerEvent>
450  <managerEvent language="en_US" name="SpanAlarm">
451  <managerEventInstance class="EVENT_FLAG_SYSTEM">
452  <synopsis>Raised when an alarm is set on a DAHDI span.</synopsis>
453  <syntax>
454  <parameter name="Span">
455  <para>The span on which the alarm occurred.</para>
456  </parameter>
457  <parameter name="Alarm">
458  <para>A textual description of the alarm that occurred.</para>
459  </parameter>
460  </syntax>
461  </managerEventInstance>
462  </managerEvent>
463  <managerEvent language="en_US" name="DAHDIChannel">
464  <managerEventInstance class="EVENT_FLAG_CALL">
465  <synopsis>Raised when a DAHDI channel is created or an underlying technology is associated with a DAHDI channel.</synopsis>
466  <syntax>
467  <channel_snapshot/>
468  <parameter name="DAHDIGroup">
469  <para>The DAHDI logical group associated with this channel.</para>
470  </parameter>
471  <parameter name="DAHDISpan">
472  <para>The DAHDI span associated with this channel.</para>
473  </parameter>
474  <parameter name="DAHDIChannel">
475  <para>The DAHDI channel associated with this channel.</para>
476  </parameter>
477  </syntax>
478  </managerEventInstance>
479  </managerEvent>
480  ***/
481 
482 #define SMDI_MD_WAIT_TIMEOUT 1500 /* 1.5 seconds */
483 
484 static const char * const lbostr[] = {
485 "0 db (CSU)/0-133 feet (DSX-1)",
486 "133-266 feet (DSX-1)",
487 "266-399 feet (DSX-1)",
488 "399-533 feet (DSX-1)",
489 "533-655 feet (DSX-1)",
490 "-7.5db (CSU)",
491 "-15db (CSU)",
492 "-22.5db (CSU)"
493 };
494 
495 /*! Global jitterbuffer configuration - by default, jb is disabled
496  * \note Values shown here match the defaults shown in chan_dahdi.conf.sample */
498 {
499  .flags = 0,
500  .max_size = 200,
501  .resync_threshold = 1000,
502  .impl = "fixed",
503  .target_extra = 40,
504 };
506 
507 /*!
508  * \note Define ZHONE_HACK to cause us to go off hook and then back on hook when
509  * the user hangs up to reset the state machine so ring works properly.
510  * This is used to be able to support kewlstart by putting the zhone in
511  * groundstart mode since their forward disconnect supervision is entirely
512  * broken even though their documentation says it isn't and their support
513  * is entirely unwilling to provide any assistance with their channel banks
514  * even though their web site says they support their products for life.
515  */
516 /* #define ZHONE_HACK */
517 
518 /*! \brief Typically, how many rings before we should send Caller*ID */
519 #define DEFAULT_CIDRINGS 1
520 
521 #define AST_LAW(p) (((p)->law == DAHDI_LAW_ALAW) ? ast_format_alaw : ast_format_ulaw)
522 
523 
524 /*! \brief Signaling types that need to use MF detection should be placed in this macro */
525 #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))
526 
527 static const char tdesc[] = "DAHDI Telephony"
528 #if defined(HAVE_PRI) || defined(HAVE_SS7) || defined(HAVE_OPENR2)
529  " w/"
530  #if defined(HAVE_PRI)
531  "PRI"
532  #endif /* defined(HAVE_PRI) */
533  #if defined(HAVE_SS7)
534  #if defined(HAVE_PRI)
535  " & "
536  #endif /* defined(HAVE_PRI) */
537  "SS7"
538  #endif /* defined(HAVE_SS7) */
539  #if defined(HAVE_OPENR2)
540  #if defined(HAVE_PRI) || defined(HAVE_SS7)
541  " & "
542  #endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */
543  "MFC/R2"
544  #endif /* defined(HAVE_OPENR2) */
545 #endif /* defined(HAVE_PRI) || defined(HAVE_SS7) || defined(HAVE_OPENR2) */
546 ;
547 
548 static const char config[] = "chan_dahdi.conf";
549 
550 #ifdef LOTS_OF_SPANS
551 #define NUM_SPANS DAHDI_MAX_SPANS
552 #else
553 #define NUM_SPANS 32
554 #endif
555 
556 #define CHAN_PSEUDO -2
557 
558 #define CALLPROGRESS_PROGRESS 1
559 #define CALLPROGRESS_FAX_OUTGOING 2
560 #define CALLPROGRESS_FAX_INCOMING 4
561 #define CALLPROGRESS_FAX (CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING)
562 
563 #define NUM_CADENCE_MAX 25
564 static int num_cadence = 4;
566 
567 static int has_pseudo;
568 
569 static struct dahdi_ring_cadence cadences[NUM_CADENCE_MAX] = {
570  { { 125, 125, 2000, 4000 } }, /*!< Quick chirp followed by normal ring */
571  { { 250, 250, 500, 1000, 250, 250, 500, 4000 } }, /*!< British style ring */
572  { { 125, 125, 125, 125, 125, 4000 } }, /*!< Three short bursts */
573  { { 1000, 500, 2500, 5000 } }, /*!< Long ring */
574 };
575 
576 /*! \brief cidrings says in which pause to transmit the cid information, where the first pause
577  * is 1, the second pause is 2 and so on.
578  */
579 
580 static int cidrings[NUM_CADENCE_MAX] = {
581  2, /*!< Right after first long ring */
582  4, /*!< Right after long part */
583  3, /*!< After third chirp */
584  2, /*!< Second spell */
585 };
586 
587 /* ETSI EN300 659-1 specifies the ring pulse between 200 and 300 mS */
588 static struct dahdi_ring_cadence AS_RP_cadence = {{250, 10000}};
589 
590 #define ISTRUNK(p) ((p->sig == SIG_FXSLS) || (p->sig == SIG_FXSKS) || \
591  (p->sig == SIG_FXSGS) || (p->sig == SIG_PRI))
592 
593 #define CANBUSYDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */)
594 #define CANPROGRESSDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */)
595 
596 static char defaultcic[64] = "";
597 static char defaultozz[64] = "";
598 
599 /*! Run this script when the MWI state changes on an FXO line, if mwimonitor is enabled */
600 static char mwimonitornotify[PATH_MAX] = "";
601 #ifndef HAVE_DAHDI_LINEREVERSE_VMWI
602 static int mwisend_rpas = 0;
603 #endif
604 
605 static char progzone[10] = "";
606 
608 static int distinctiveringaftercid = 0;
609 
610 static int numbufs = 4;
611 
612 static int mwilevel = 512;
613 static int dtmfcid_level = 256;
614 
615 #define REPORT_CHANNEL_ALARMS 1
616 #define REPORT_SPAN_ALARMS 2
618 
619 #ifdef HAVE_PRI
620 static int pridebugfd = -1;
621 static char pridebugfilename[1024] = "";
622 #endif
623 
624 /*! \brief Protect the interface list (of dahdi_pvt's) */
626 
627 
628 static int ifcount = 0;
629 
630 #ifdef HAVE_PRI
631 AST_MUTEX_DEFINE_STATIC(pridebugfdlock);
632 #endif
633 
634 /*! \brief Protect the monitoring thread, so only one process can kill or start it, and not
635  when it's doing something critical. */
637 
638 /*! \brief This is the thread for the monitor which checks for input on the channels
639  which are not currently in use. */
644 static int ss_thread_count = 0;
645 static int num_restart_pending = 0;
646 
647 static int restart_monitor(void);
648 
649 static int dahdi_sendtext(struct ast_channel *c, const char *text);
650 
651 /*! \brief Avoid the silly dahdi_getevent which ignores a bunch of events */
652 static inline int dahdi_get_event(int fd)
653 {
654  int j;
655  if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
656  return -1;
657  return j;
658 }
659 
660 /*! \brief Avoid the silly dahdi_waitevent which ignores a bunch of events */
661 static inline int dahdi_wait_event(int fd)
662 {
663  int i, j = 0;
664  i = DAHDI_IOMUX_SIGEVENT;
665  if (ioctl(fd, DAHDI_IOMUX, &i) == -1)
666  return -1;
667  if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
668  return -1;
669  return j;
670 }
671 
672 /*! Chunk size to read -- we use 20ms chunks to make things happy. */
673 #define READ_SIZE 160
674 
675 #define MASK_AVAIL (1 << 0) /*!< Channel available for PRI use */
676 #define MASK_INUSE (1 << 1) /*!< Channel currently in use */
677 
678 #define CALLWAITING_SILENT_SAMPLES ((300 * 8) / READ_SIZE) /*!< 300 ms */
679 #define CALLWAITING_REPEAT_SAMPLES ((10000 * 8) / READ_SIZE) /*!< 10,000 ms */
680 #define CALLWAITING_SUPPRESS_SAMPLES ((100 * 8) / READ_SIZE) /*!< 100 ms */
681 #define CIDCW_EXPIRE_SAMPLES ((500 * 8) / READ_SIZE) /*!< 500 ms */
682 #define MIN_MS_SINCE_FLASH ((2000) ) /*!< 2000 ms */
683 #define DEFAULT_RINGT ((8000 * 8) / READ_SIZE) /*!< 8,000 ms */
684 #define DEFAULT_DIALTONE_DETECT_TIMEOUT ((10000 * 8) / READ_SIZE) /*!< 10,000 ms */
685 
686 /*!
687  * \brief Configured ring timeout base.
688  * \note Value computed from "ringtimeout" read in from chan_dahdi.conf if it exists.
689  */
691 
692 #if defined(HAVE_SS7)
693 
694 struct dahdi_ss7 {
695  struct sig_ss7_linkset ss7;
696 };
697 
698 static struct dahdi_ss7 linksets[NUM_SPANS];
699 
700 static int cur_ss7type = -1;
701 static int cur_slc = -1;
702 static int cur_linkset = -1;
703 static int cur_pointcode = -1;
704 static int cur_cicbeginswith = -1;
705 static int cur_adjpointcode = -1;
706 static int cur_networkindicator = -1;
707 static int cur_defaultdpc = -1;
708 #endif /* defined(HAVE_SS7) */
709 
710 #ifdef HAVE_OPENR2
711 struct dahdi_mfcr2_conf {
712  openr2_variant_t variant;
713  int mfback_timeout;
714  int metering_pulse_timeout;
715  int max_ani;
716  int max_dnis;
717 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2
718  int dtmf_time_on;
719  int dtmf_time_off;
720 #endif
721 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 3
722  int dtmf_end_timeout;
723 #endif
724  signed int get_ani_first:2;
725 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
726  signed int skip_category_request:2;
727 #endif
728  unsigned int call_files:1;
729  unsigned int allow_collect_calls:1;
730  unsigned int charge_calls:1;
731  unsigned int accept_on_offer:1;
732  unsigned int forced_release:1;
733  unsigned int double_answer:1;
734  signed int immediate_accept:2;
735 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2
736  signed int dtmf_dialing:2;
737  signed int dtmf_detection:2;
738 #endif
739  char logdir[OR2_MAX_PATH];
740  char r2proto_file[OR2_MAX_PATH];
741  openr2_log_level_t loglevel;
742  openr2_calling_party_category_t category;
743 };
744 
745 /* MFC-R2 pseudo-link structure */
746 struct dahdi_mfcr2 {
747  int index; /*!< Unique index for CLI */
748  pthread_t r2master; /*!< Thread of master */
749  openr2_context_t *protocol_context; /*!< OpenR2 context handle */
750  struct dahdi_pvt *pvts[SIG_MFCR2_MAX_CHANNELS]; /*!< Member channel pvt structs */
751  int numchans; /*!< Number of channels in this R2 block */
752  int live_chans; /*!< Number of unremoved channels in this R2 block */
753  int nodev; /*!< Link disconnected? */
754  struct dahdi_mfcr2_conf conf; /*!< Configuration used to setup this pseudo-link */
755 };
756 
757 struct r2link_entry {
758  struct dahdi_mfcr2 mfcr2;
759  AST_LIST_ENTRY(r2link_entry) list;
760 };
761 static AST_LIST_HEAD_STATIC(r2links, r2link_entry);
762 static struct r2links nodev_r2links = AST_LIST_HEAD_INIT_VALUE;
763 
764 
765 /* how many r2links have been malloc'd */
766 static int r2links_count = 0;
767 
768 #endif /* HAVE_OPENR2 */
769 
770 #ifdef HAVE_PRI
771 
772 struct dahdi_pri {
773  int dchannels[SIG_PRI_NUM_DCHANS]; /*!< What channel are the dchannels on */
774  int mastertrunkgroup; /*!< What trunk group is our master */
775  int prilogicalspan; /*!< Logical span number within trunk group */
776  struct sig_pri_span pri;
777 };
778 
779 static struct dahdi_pri pris[NUM_SPANS];
780 
781 #if defined(HAVE_PRI_CCSS)
782 /*! DAHDI PRI CCSS agent and monitor type name. */
783 static const char dahdi_pri_cc_type[] = "DAHDI/PRI";
784 #endif /* defined(HAVE_PRI_CCSS) */
785 
786 #else
787 /*! Shut up the compiler */
788 struct dahdi_pri;
789 #endif
790 
791 /* Polarity states */
792 #define POLARITY_IDLE 0
793 #define POLARITY_REV 1
794 
795 const char * const subnames[] = {
796  "Real",
797  "Callwait",
798  "Threeway"
799 };
800 
801 static struct dahdi_pvt *iflist = NULL; /*!< Main interface list start */
802 static struct dahdi_pvt *ifend = NULL; /*!< Main interface list end */
803 
804 #if defined(HAVE_PRI)
805 struct doomed_pri {
806  struct sig_pri_span *pri;
807  AST_LIST_ENTRY(doomed_pri) list;
808 };
809 static AST_LIST_HEAD_STATIC(doomed_pris, doomed_pri);
810 
811 static void pri_destroy_span(struct sig_pri_span *pri);
812 
813 static struct dahdi_parms_pseudo {
814  int buf_no; /*!< Number of buffers */
815  int buf_policy; /*!< Buffer policy */
816  int faxbuf_no; /*!< Number of Fax buffers */
817  int faxbuf_policy; /*!< Fax buffer policy */
818 } dahdi_pseudo_parms;
819 #endif /* defined(HAVE_PRI) */
820 
821 /*! \brief Channel configuration from chan_dahdi.conf .
822  * This struct is used for parsing the [channels] section of chan_dahdi.conf.
823  * Generally there is a field here for every possible configuration item.
824  *
825  * The state of fields is saved along the parsing and whenever a 'channel'
826  * statement is reached, the current dahdi_chan_conf is used to configure the
827  * channel (struct dahdi_pvt)
828  *
829  * \see dahdi_chan_init for the default values.
830  */
832  struct dahdi_pvt chan;
833 #ifdef HAVE_PRI
834  struct dahdi_pri pri;
835 #endif
836 
837 #if defined(HAVE_SS7)
838  struct dahdi_ss7 ss7;
839 #endif /* defined(HAVE_SS7) */
840 
841 #ifdef HAVE_OPENR2
842  struct dahdi_mfcr2_conf mfcr2;
843 #endif
844  struct dahdi_params timing;
845  int is_sig_auto; /*!< Use channel signalling from DAHDI? */
846  /*! Continue configuration even if a channel is not there. */
848 
849  /*!
850  * \brief The serial port to listen for SMDI data on
851  * \note Set from the "smdiport" string read in from chan_dahdi.conf
852  */
853  char smdi_port[SMDI_MAX_FILENAME_LEN];
854 
855  /*!
856  * \brief Don't create channels below this number
857  * \note by default is 0 (no limit)
858  */
860 
861  /*!
862  * \brief Don't create channels above this number (infinity by default)
863  * \note by default is 0 (special value that means "no limit").
864  */
866 };
867 
868 /*! returns a new dahdi_chan_conf with default values (by-value) */
870 {
871  /* recall that if a field is not included here it is initialized
872  * to 0 or equivalent
873  */
874  struct dahdi_chan_conf conf = {
875 #ifdef HAVE_PRI
876  .pri.pri = {
877  .nsf = PRI_NSF_NONE,
878  .switchtype = PRI_SWITCH_NI2,
879  .dialplan = PRI_UNKNOWN + 1,
880  .localdialplan = PRI_NATIONAL_ISDN + 1,
881  .nodetype = PRI_CPE,
882  .qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL,
883 
884 #if defined(HAVE_PRI_CCSS)
885  .cc_ptmp_recall_mode = 1,/* specificRecall */
886  .cc_qsig_signaling_link_req = 1,/* retain */
887  .cc_qsig_signaling_link_rsp = 1,/* retain */
888 #endif /* defined(HAVE_PRI_CCSS) */
889 
890  .minunused = 2,
891  .idleext = "",
892  .idledial = "",
893  .internationalprefix = "",
894  .nationalprefix = "",
895  .localprefix = "",
896  .privateprefix = "",
897  .unknownprefix = "",
898  .colp_send = SIG_PRI_COLP_UPDATE,
899  .resetinterval = -1,
900  },
901 #endif
902 #if defined(HAVE_SS7)
903  .ss7.ss7 = {
904  .called_nai = SS7_NAI_NATIONAL,
905  .calling_nai = SS7_NAI_NATIONAL,
906  .internationalprefix = "",
907  .nationalprefix = "",
908  .subscriberprefix = "",
909  .unknownprefix = "",
910  .networkroutedprefix = ""
911  },
912 #endif /* defined(HAVE_SS7) */
913 #ifdef HAVE_OPENR2
914  .mfcr2 = {
915  .variant = OR2_VAR_ITU,
916  .mfback_timeout = -1,
917  .metering_pulse_timeout = -1,
918  .max_ani = 10,
919  .max_dnis = 4,
920  .get_ani_first = -1,
921 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
922  .skip_category_request = -1,
923 #endif
924  .call_files = 0,
925  .allow_collect_calls = 0,
926  .charge_calls = 1,
927  .accept_on_offer = 1,
928  .forced_release = 0,
929  .double_answer = 0,
930  .immediate_accept = -1,
931 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2
932  .dtmf_dialing = -1,
933  .dtmf_detection = -1,
934  .dtmf_time_on = OR2_DEFAULT_DTMF_ON,
935  .dtmf_time_off = OR2_DEFAULT_DTMF_OFF,
936 #endif
937 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 3
938  .dtmf_end_timeout = -1,
939 #endif
940  .logdir = "",
941  .r2proto_file = "",
942  .loglevel = OR2_LOG_ERROR | OR2_LOG_WARNING,
943  .category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER
944  },
945 #endif
946  .chan = {
947  .context = "default",
948  .cid_num = "",
949  .cid_name = "",
950  .cid_tag = "",
951  .mohinterpret = "default",
952  .mohsuggest = "",
953  .parkinglot = "",
954  .transfertobusy = 1,
955 
956  .cid_signalling = CID_SIG_BELL,
957  .cid_start = CID_START_RING,
958  .dahditrcallerid = 0,
959  .use_callerid = 1,
960  .sig = -1,
961  .outsigmod = -1,
962 
963  .cid_rxgain = +5.0,
964 
965  .tonezone = -1,
966 
967  .echocancel.head.tap_length = 1,
968 
969  .busycount = 3,
970 
971  .accountcode = "",
972 
973  .mailbox = "",
974 
975 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
976  .mwisend_fsk = 1,
977 #endif
978  .polarityonanswerdelay = 600,
979 
980  .sendcalleridafter = DEFAULT_CIDRINGS,
981 
982  .buf_policy = DAHDI_POLICY_IMMEDIATE,
983  .buf_no = numbufs,
984  .usefaxbuffers = 0,
985  .cc_params = ast_cc_config_params_init(),
986  .firstdigit_timeout = ANALOG_FIRST_DIGIT_TIMEOUT,
987  .interdigit_timeout = ANALOG_INTER_DIGIT_TIMEOUT,
988  .matchdigit_timeout = ANALOG_MATCH_DIGIT_TIMEOUT,
989  },
990  .timing = {
991  .prewinktime = -1,
992  .preflashtime = -1,
993  .winktime = -1,
994  .flashtime = -1,
995  .starttime = -1,
996  .rxwinktime = -1,
997  .rxflashtime = -1,
998  .debouncetime = -1
999  },
1000  .is_sig_auto = 1,
1001  .ignore_failed_channels = 1,
1002  .smdi_port = "/dev/ttyS0",
1003  };
1004 
1005  return conf;
1006 }
1007 
1008 
1009 static struct ast_channel *dahdi_request(const char *type, struct ast_format_cap *cap,
1010  const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor,
1011  const char *data, int *cause);
1012 static int dahdi_digit_begin(struct ast_channel *ast, char digit);
1013 static int dahdi_digit_end(struct ast_channel *ast, char digit, unsigned int duration);
1014 static int dahdi_sendtext(struct ast_channel *c, const char *text);
1015 static int dahdi_call(struct ast_channel *ast, const char *rdest, int timeout);
1016 static int dahdi_hangup(struct ast_channel *ast);
1017 static int dahdi_answer(struct ast_channel *ast);
1018 static struct ast_frame *dahdi_read(struct ast_channel *ast);
1019 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame);
1020 static struct ast_frame *dahdi_exception(struct ast_channel *ast);
1021 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen);
1022 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
1023 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen);
1024 static int dahdi_queryoption(struct ast_channel *chan, int option, void *data, int *datalen);
1025 static int dahdi_func_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len);
1026 static int dahdi_func_write(struct ast_channel *chan, const char *function, char *data, const char *value);
1027 static int dahdi_devicestate(const char *data);
1028 static int dahdi_cc_callback(struct ast_channel *inbound, const char *dest, ast_cc_callback_fn callback);
1029 
1030 static struct ast_channel_tech dahdi_tech = {
1031  .type = "DAHDI",
1032  .description = tdesc,
1033  .requester = dahdi_request,
1034  .send_digit_begin = dahdi_digit_begin,
1035  .send_digit_end = dahdi_digit_end,
1036  .send_text = dahdi_sendtext,
1037  .call = dahdi_call,
1038  .hangup = dahdi_hangup,
1039  .answer = dahdi_answer,
1040  .read = dahdi_read,
1041  .write = dahdi_write,
1042  .exception = dahdi_exception,
1043  .indicate = dahdi_indicate,
1044  .fixup = dahdi_fixup,
1045  .setoption = dahdi_setoption,
1046  .queryoption = dahdi_queryoption,
1047  .func_channel_read = dahdi_func_read,
1048  .func_channel_write = dahdi_func_write,
1049  .devicestate = dahdi_devicestate,
1050  .cc_callback = dahdi_cc_callback,
1051 };
1052 
1053 #define GET_CHANNEL(p) ((p)->channel)
1054 
1056 {
1057  switch (sig) {
1058  case SIG_FXOLS:
1059  return ANALOG_SIG_FXOLS;
1060  case SIG_FXOGS:
1061  return ANALOG_SIG_FXOGS;
1062  case SIG_FXOKS:
1063  return ANALOG_SIG_FXOKS;
1064  case SIG_FXSLS:
1065  return ANALOG_SIG_FXSLS;
1066  case SIG_FXSGS:
1067  return ANALOG_SIG_FXSGS;
1068  case SIG_FXSKS:
1069  return ANALOG_SIG_FXSKS;
1070  case SIG_EMWINK:
1071  return ANALOG_SIG_EMWINK;
1072  case SIG_EM:
1073  return ANALOG_SIG_EM;
1074  case SIG_EM_E1:
1075  return ANALOG_SIG_EM_E1;
1076  case SIG_FEATD:
1077  return ANALOG_SIG_FEATD;
1078  case SIG_FEATDMF:
1079  return ANALOG_SIG_FEATDMF;
1080  case SIG_E911:
1081  return SIG_E911;
1082  case SIG_FGC_CAMA:
1083  return ANALOG_SIG_FGC_CAMA;
1084  case SIG_FGC_CAMAMF:
1085  return ANALOG_SIG_FGC_CAMAMF;
1086  case SIG_FEATB:
1087  return ANALOG_SIG_FEATB;
1088  case SIG_SFWINK:
1089  return ANALOG_SIG_SFWINK;
1090  case SIG_SF:
1091  return ANALOG_SIG_SF;
1092  case SIG_SF_FEATD:
1093  return ANALOG_SIG_SF_FEATD;
1094  case SIG_SF_FEATDMF:
1095  return ANALOG_SIG_SF_FEATDMF;
1096  case SIG_FEATDMF_TA:
1097  return ANALOG_SIG_FEATDMF_TA;
1098  case SIG_SF_FEATB:
1099  return ANALOG_SIG_FEATB;
1100  default:
1101  return -1;
1102  }
1103 }
1104 
1105 
1107 {
1108  switch (tone) {
1109  case ANALOG_TONE_RINGTONE:
1110  return DAHDI_TONE_RINGTONE;
1111  case ANALOG_TONE_STUTTER:
1112  return DAHDI_TONE_STUTTER;
1114  return DAHDI_TONE_CONGESTION;
1115  case ANALOG_TONE_DIALTONE:
1116  return DAHDI_TONE_DIALTONE;
1118  return DAHDI_TONE_DIALRECALL;
1119  case ANALOG_TONE_INFO:
1120  return DAHDI_TONE_INFO;
1121  default:
1122  return -1;
1123  }
1124 }
1125 
1126 static int analogsub_to_dahdisub(enum analog_sub analogsub)
1127 {
1128  int index;
1129 
1130  switch (analogsub) {
1131  case ANALOG_SUB_REAL:
1132  index = SUB_REAL;
1133  break;
1134  case ANALOG_SUB_CALLWAIT:
1135  index = SUB_CALLWAIT;
1136  break;
1137  case ANALOG_SUB_THREEWAY:
1138  index = SUB_THREEWAY;
1139  break;
1140  default:
1141  ast_log(LOG_ERROR, "Unidentified sub!\n");
1142  index = SUB_REAL;
1143  }
1144 
1145  return index;
1146 }
1147 
1148 /*!
1149  * \internal
1150  * \brief release all members on the doomed pris list
1151  * \since 13.0
1152  *
1153  * Called priodically by the monitor threads to release spans marked for
1154  * removal.
1155  */
1156 static void release_doomed_pris(void)
1157 {
1158 #ifdef HAVE_PRI
1159  struct doomed_pri *entry;
1160 
1161  AST_LIST_LOCK(&doomed_pris);
1162  while ((entry = AST_LIST_REMOVE_HEAD(&doomed_pris, list))) {
1163  /* The span destruction must be done with this lock not held */
1164  AST_LIST_UNLOCK(&doomed_pris);
1165  ast_debug(4, "Destroying span %d from doomed queue.\n",
1166  entry->pri->span);
1167  pri_destroy_span(entry->pri);
1168  ast_free(entry);
1169  AST_LIST_LOCK(&doomed_pris);
1170  }
1171  AST_LIST_UNLOCK(&doomed_pris);
1172 #endif
1173 }
1174 
1175 #ifdef HAVE_PRI
1176 /*!
1177  * \brief Queue a span for destruction
1178  * \since 13.0
1179  *
1180  * \param pri the span to destroy
1181  *
1182  * Add a span to the list of spans to be destroyed later on
1183  * by the monitor thread. Allows destroying a span while holding its
1184  * lock.
1185  */
1186 static void pri_queue_for_destruction(struct sig_pri_span *pri)
1187 {
1188  struct doomed_pri *entry;
1189 
1190  AST_LIST_LOCK(&doomed_pris);
1191  AST_LIST_TRAVERSE(&doomed_pris, entry, list) {
1192  if (entry->pri == pri) {
1193  AST_LIST_UNLOCK(&doomed_pris);
1194  return;
1195  }
1196  }
1197  entry = ast_calloc(sizeof(struct doomed_pri), 1);
1198  if (!entry) {
1199  /* Nothing useful to do here. Panic? */
1200  ast_log(LOG_WARNING, "Failed allocating memory for a doomed_pri.\n");
1201  AST_LIST_UNLOCK(&doomed_pris);
1202  return;
1203  }
1204  entry->pri = pri;
1205  ast_debug(4, "Queue span %d for destruction.\n", pri->span);
1206  AST_LIST_INSERT_TAIL(&doomed_pris, entry, list);
1207  AST_LIST_UNLOCK(&doomed_pris);
1208 }
1209 #endif
1210 
1211 /*!
1212  * \internal
1213  * \brief Send a dial string to DAHDI.
1214  * \since 12.0.0
1215  *
1216  * \param pvt DAHDI private pointer
1217  * \param operation DAHDI dial operation to do to string
1218  * \param dial_str Dial string to send
1219  *
1220  * \retval 0 on success.
1221  * \retval non-zero on error.
1222  */
1223 static int dahdi_dial_str(struct dahdi_pvt *pvt, int operation, const char *dial_str)
1224 {
1225  int res;
1226  int offset;
1227  const char *pos;
1228  struct dahdi_dialoperation zo = {
1229  .op = operation,
1230  };
1231 
1232  /* Convert the W's to ww. */
1233  pos = dial_str;
1234  for (offset = 0; offset < sizeof(zo.dialstr) - 1; ++offset) {
1235  if (!*pos) {
1236  break;
1237  }
1238  if (*pos == 'W') {
1239  /* Convert 'W' to "ww" */
1240  ++pos;
1241  if (offset >= sizeof(zo.dialstr) - 3) {
1242  /* No room to expand */
1243  break;
1244  }
1245  zo.dialstr[offset] = 'w';
1246  ++offset;
1247  zo.dialstr[offset] = 'w';
1248  continue;
1249  }
1250  zo.dialstr[offset] = *pos++;
1251  }
1252  /* The zo initialization has already terminated the dialstr. */
1253 
1254  ast_debug(1, "Channel %d: Dial str '%s' expanded to '%s' sent to DAHDI_DIAL.\n",
1255  pvt->channel, dial_str, zo.dialstr);
1256  res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo);
1257  if (res) {
1258  ast_log(LOG_WARNING, "Channel %d: Couldn't dial '%s': %s\n",
1259  pvt->channel, dial_str, strerror(errno));
1260  }
1261 
1262  return res;
1263 }
1264 
1266 static int bump_gains(struct dahdi_pvt *p);
1267 static int dahdi_setlinear(int dfd, int linear);
1268 
1269 static int my_start_cid_detect(void *pvt, int cid_signalling)
1270 {
1271  struct dahdi_pvt *p = pvt;
1272  int index = SUB_REAL;
1273  p->cs = callerid_new(cid_signalling);
1274  if (!p->cs) {
1275  ast_log(LOG_ERROR, "Unable to alloc callerid\n");
1276  return -1;
1277  }
1278  bump_gains(p);
1279  dahdi_setlinear(p->subs[index].dfd, 0);
1280 
1281  return 0;
1282 }
1283 
1284 static int restore_gains(struct dahdi_pvt *p);
1285 
1286 static int my_stop_cid_detect(void *pvt)
1287 {
1288  struct dahdi_pvt *p = pvt;
1289  int index = SUB_REAL;
1290 
1291  if (p->cs) {
1292  callerid_free(p->cs);
1293  }
1294 
1295  /* Restore linear mode after Caller*ID processing */
1296  dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
1297  restore_gains(p);
1298 
1299  return 0;
1300 }
1301 
1302 static int my_get_callerid(void *pvt, char *namebuf, char *numbuf, enum analog_event *ev, size_t timeout)
1303 {
1304  struct dahdi_pvt *p = pvt;
1305  struct analog_pvt *analog_p = p->sig_pvt;
1306  struct pollfd poller;
1307  char *name, *num;
1308  int index = SUB_REAL;
1309  int res;
1310  unsigned char buf[256];
1311  int flags;
1312 
1313  poller.fd = p->subs[SUB_REAL].dfd;
1314  poller.events = POLLPRI | POLLIN;
1315  poller.revents = 0;
1316 
1317  res = poll(&poller, 1, timeout);
1318 
1319  if (poller.revents & POLLPRI) {
1321  return 1;
1322  }
1323 
1324  if (poller.revents & POLLIN) {
1325  /*** NOTES ***/
1326  /* Change API: remove cid_signalling from get_callerid, add a new start_cid_detect and stop_cid_detect function
1327  * to enable slin mode and allocate cid detector. get_callerid should be able to be called any number of times until
1328  * either a timeout occurs or CID is detected (returns 0). returning 1 should be event received, and -1 should be
1329  * a failure and die, and returning 2 means no event was received. */
1330  res = read(p->subs[index].dfd, buf, sizeof(buf));
1331  if (res < 0) {
1332  ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
1333  return -1;
1334  }
1335 
1336  if (analog_p->ringt > 0) {
1337  if (!(--analog_p->ringt)) {
1338  /* only return if we timeout from a ring event */
1339  return -1;
1340  }
1341  }
1342 
1343  if (p->cid_signalling == CID_SIG_V23_JP) {
1344  res = callerid_feed_jp(p->cs, buf, res, AST_LAW(p));
1345  } else {
1346  res = callerid_feed(p->cs, buf, res, AST_LAW(p));
1347  }
1348  if (res < 0) {
1349  /*
1350  * The previous diagnostic message output likely
1351  * explains why it failed.
1352  */
1353  ast_log(LOG_WARNING, "Failed to decode CallerID\n");
1354  return -1;
1355  }
1356 
1357  if (res == 1) {
1358  callerid_get(p->cs, &name, &num, &flags);
1359  if (name)
1360  ast_copy_string(namebuf, name, ANALOG_MAX_CID);
1361  if (num)
1362  ast_copy_string(numbuf, num, ANALOG_MAX_CID);
1363 
1364  ast_debug(1, "CallerID number: %s, name: %s, flags=%d\n", num, name, flags);
1365  return 0;
1366  }
1367  }
1368 
1369  *ev = ANALOG_EVENT_NONE;
1370  return 2;
1371 }
1372 
1373 static const char *event2str(int event);
1374 
1375 static int my_distinctive_ring(struct ast_channel *chan, void *pvt, int idx, int *ringdata)
1376 {
1377  unsigned char buf[256];
1378  int distMatches;
1379  int curRingData[RING_PATTERNS];
1380  int receivedRingT;
1381  int counter1;
1382  int counter;
1383  int i;
1384  int res;
1385  int checkaftercid = 0;
1386  const char *matched_context;
1387  struct dahdi_pvt *p = pvt;
1388  struct analog_pvt *analog_p = p->sig_pvt;
1389 
1390  if (ringdata == NULL) {
1391  ringdata = curRingData;
1392  } else {
1393  checkaftercid = 1;
1394  }
1395 
1396  /* We must have a ring by now so lets try to listen for distinctive ringing */
1397  if ((checkaftercid && distinctiveringaftercid) || !checkaftercid) {
1398  /* Clear the current ring data array so we don't have old data in it. */
1399  for (receivedRingT = 0; receivedRingT < RING_PATTERNS; receivedRingT++)
1400  ringdata[receivedRingT] = 0;
1401  receivedRingT = 0;
1402 
1403  if (checkaftercid && distinctiveringaftercid) {
1404  ast_verb(3, "Detecting post-CID distinctive ring\n");
1405  }
1406 
1407  for (;;) {
1408  i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
1409  res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i);
1410  if (res) {
1411  ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
1412  ast_hangup(chan);
1413  return 1;
1414  }
1415  if (i & DAHDI_IOMUX_SIGEVENT) {
1416  res = dahdi_get_event(p->subs[idx].dfd);
1417  ast_debug(3, "Got event %d (%s)...\n", res, event2str(res));
1418  if (res == DAHDI_EVENT_NOALARM) {
1419  p->inalarm = 0;
1420  analog_p->inalarm = 0;
1421  } else if (res == DAHDI_EVENT_RINGOFFHOOK) {
1422  /* Let us detect distinctive ring */
1423  ringdata[receivedRingT] = analog_p->ringt;
1424 
1425  if (analog_p->ringt < analog_p->ringt_base / 2) {
1426  break;
1427  }
1428  /* Increment the ringT counter so we can match it against
1429  values in chan_dahdi.conf for distinctive ring */
1430  if (++receivedRingT == RING_PATTERNS) {
1431  break;
1432  }
1433  }
1434  } else if (i & DAHDI_IOMUX_READ) {
1435  res = read(p->subs[idx].dfd, buf, sizeof(buf));
1436  if (res < 0) {
1437  if (errno != ELAST) {
1438  ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
1439  ast_hangup(chan);
1440  return 1;
1441  }
1442  break;
1443  }
1444  if (analog_p->ringt > 0) {
1445  if (!(--analog_p->ringt)) {
1446  break;
1447  }
1448  }
1449  }
1450  }
1451  }
1452 
1453  /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this channel */
1454  ast_verb(3, "Detected ring pattern: %d,%d,%d\n", ringdata[0], ringdata[1], ringdata[2]);
1455  matched_context = p->defcontext;
1456  for (counter = 0; counter < 3; counter++) {
1457  int range = p->drings.ringnum[counter].range;
1458 
1459  distMatches = 0;
1460  ast_verb(3, "Checking %d,%d,%d with +/- %d range\n",
1461  p->drings.ringnum[counter].ring[0],
1462  p->drings.ringnum[counter].ring[1],
1463  p->drings.ringnum[counter].ring[2],
1464  range);
1465  for (counter1 = 0; counter1 < 3; counter1++) {
1466  int ring = p->drings.ringnum[counter].ring[counter1];
1467 
1468  if (ring == -1) {
1469  ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
1470  ringdata[counter1]);
1471  distMatches++;
1472  } else if (ring - range <= ringdata[counter1] && ringdata[counter1] <= ring + range) {
1473  ast_verb(3, "Ring pattern %d is in range: %d to %d\n",
1474  ringdata[counter1], ring - range, ring + range);
1475  distMatches++;
1476  } else {
1477  /* The current dring pattern cannot match. */
1478  break;
1479  }
1480  }
1481 
1482  if (distMatches == 3) {
1483  /* The ring matches, set the context to whatever is for distinctive ring.. */
1484  matched_context = S_OR(p->drings.ringContext[counter].contextData, p->defcontext);
1485  ast_verb(3, "Matched Distinctive Ring context %s\n", matched_context);
1486  break;
1487  }
1488  }
1489 
1490  /* Set selected distinctive ring context if not already set. */
1491  if (strcmp(p->context, matched_context) != 0) {
1492  ast_copy_string(p->context, matched_context, sizeof(p->context));
1493  ast_channel_context_set(chan, matched_context);
1494  }
1495 
1496  return 0;
1497 }
1498 
1499 static int my_stop_callwait(void *pvt)
1500 {
1501  struct dahdi_pvt *p = pvt;
1502  p->callwaitingrepeat = 0;
1503  p->cidcwexpire = 0;
1504  p->cid_suppress_expire = 0;
1505 
1506  return 0;
1507 }
1508 
1509 static int send_callerid(struct dahdi_pvt *p);
1510 static int save_conference(struct dahdi_pvt *p);
1511 static int restore_conference(struct dahdi_pvt *p);
1512 
1513 static int my_callwait(void *pvt)
1514 {
1515  struct dahdi_pvt *p = pvt;
1516 
1518  if (p->cidspill) {
1519  ast_log(LOG_WARNING, "Spill already exists?!?\n");
1520  ast_free(p->cidspill);
1521  }
1522 
1523  /*
1524  * SAS: Subscriber Alert Signal, 440Hz for 300ms
1525  * CAS: CPE Alert Signal, 2130Hz * 2750Hz sine waves
1526  */
1527  if (!(p->cidspill = ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE * 4)))
1528  return -1;
1529  save_conference(p);
1530  /* Silence */
1531  memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
1532  if (!p->callwaitrings && p->callwaitingcallerid) {
1533  ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
1534  p->callwaitcas = 1;
1535  p->cidlen = 2400 + 680 + READ_SIZE * 4;
1536  } else {
1537  ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
1538  p->callwaitcas = 0;
1539  p->cidlen = 2400 + READ_SIZE * 4;
1540  }
1541  p->cidpos = 0;
1542  send_callerid(p);
1543 
1544  return 0;
1545 }
1546 
1547 static int my_send_callerid(void *pvt, int cwcid, struct ast_party_caller *caller)
1548 {
1549  struct dahdi_pvt *p = pvt;
1550 
1551  ast_debug(2, "Starting cid spill\n");
1552 
1553  if (p->cidspill) {
1554  ast_log(LOG_WARNING, "cidspill already exists??\n");
1555  ast_free(p->cidspill);
1556  }
1557 
1558  if ((p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) {
1559  if (cwcid == 0) {
1561  caller->id.name.str,
1562  caller->id.number.str,
1563  AST_LAW(p));
1564  } else {
1565  ast_verb(3, "CPE supports Call Waiting Caller*ID. Sending '%s/%s'\n",
1566  caller->id.name.str, caller->id.number.str);
1567  p->callwaitcas = 0;
1568  p->cidcwexpire = 0;
1570  caller->id.name.str,
1571  caller->id.number.str,
1572  AST_LAW(p));
1573  p->cidlen += READ_SIZE * 4;
1574  }
1575  p->cidpos = 0;
1576  p->cid_suppress_expire = 0;
1577  send_callerid(p);
1578  }
1579  return 0;
1580 }
1581 
1582 static int my_dsp_reset_and_flush_digits(void *pvt)
1583 {
1584  struct dahdi_pvt *p = pvt;
1585  if (p->dsp)
1586  ast_dsp_digitreset(p->dsp);
1587 
1588  return 0;
1589 }
1590 
1591 static int my_dsp_set_digitmode(void *pvt, enum analog_dsp_digitmode mode)
1592 {
1593  struct dahdi_pvt *p = pvt;
1594 
1595  if (p->channel == CHAN_PSEUDO)
1596  ast_log(LOG_ERROR, "You have assumed incorrectly sir!\n");
1597 
1598  if (mode == ANALOG_DIGITMODE_DTMF) {
1599  /* If we do hardware dtmf, no need for a DSP */
1600  if (p->hardwaredtmf) {
1601  if (p->dsp) {
1602  ast_dsp_free(p->dsp);
1603  p->dsp = NULL;
1604  }
1605  return 0;
1606  }
1607 
1608  if (!p->dsp) {
1609  p->dsp = ast_dsp_new();
1610  if (!p->dsp) {
1611  ast_log(LOG_ERROR, "Unable to allocate DSP\n");
1612  return -1;
1613  }
1614  }
1615 
1617  } else if (mode == ANALOG_DIGITMODE_MF) {
1618  if (!p->dsp) {
1619  p->dsp = ast_dsp_new();
1620  if (!p->dsp) {
1621  ast_log(LOG_ERROR, "Unable to allocate DSP\n");
1622  return -1;
1623  }
1624  }
1626  }
1627  return 0;
1628 }
1629 
1630 static int dahdi_wink(struct dahdi_pvt *p, int index);
1631 
1632 static int my_wink(void *pvt, enum analog_sub sub)
1633 {
1634  struct dahdi_pvt *p = pvt;
1635  int index = analogsub_to_dahdisub(sub);
1636  if (index != SUB_REAL) {
1637  ast_log(LOG_ERROR, "We used a sub other than SUB_REAL (incorrect assumption sir)\n");
1638  }
1639  return dahdi_wink(p, index);
1640 }
1641 
1642 static void wakeup_sub(struct dahdi_pvt *p, int a);
1643 
1644 static int reset_conf(struct dahdi_pvt *p);
1645 
1646 static inline int dahdi_confmute(struct dahdi_pvt *p, int muted);
1647 
1648 static void my_handle_dtmf(void *pvt, struct ast_channel *ast, enum analog_sub analog_index, struct ast_frame **dest)
1649 {
1650  struct ast_frame *f = *dest;
1651  struct dahdi_pvt *p = pvt;
1652  int idx = analogsub_to_dahdisub(analog_index);
1653 
1654  ast_debug(1, "%s DTMF digit: 0x%02X '%c' on %s\n",
1655  f->frametype == AST_FRAME_DTMF_BEGIN ? "Begin" : "End",
1656  (unsigned)f->subclass.integer, f->subclass.integer, ast_channel_name(ast));
1657 
1658  if (f->subclass.integer == 'f') {
1659  if (f->frametype == AST_FRAME_DTMF_END) {
1660  /* Fax tone -- Handle and return NULL */
1661  if ((p->callprogress & CALLPROGRESS_FAX) && !p->faxhandled) {
1662  /* If faxbuffers are configured, use them for the fax transmission */
1663  if (p->usefaxbuffers && !p->bufferoverrideinuse) {
1664  struct dahdi_bufferinfo bi = {
1665  .txbufpolicy = p->faxbuf_policy,
1666  .bufsize = p->bufsize,
1667  .numbufs = p->faxbuf_no
1668  };
1669  int res;
1670 
1671  if ((res = ioctl(p->subs[idx].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
1672  ast_log(LOG_WARNING, "Channel '%s' unable to set buffer policy, reason: %s\n", ast_channel_name(ast), strerror(errno));
1673  } else {
1674  p->bufferoverrideinuse = 1;
1675  }
1676  }
1677  p->faxhandled = 1;
1678  if (p->dsp) {
1681  ast_debug(1, "Disabling FAX tone detection on %s after tone received\n", ast_channel_name(ast));
1682  }
1683  if (strcmp(ast_channel_exten(ast), "fax")) {
1684  const char *target_context = S_OR(ast_channel_macrocontext(ast), ast_channel_context(ast));
1685 
1686  /*
1687  * We need to unlock 'ast' here because ast_exists_extension has the
1688  * potential to start autoservice on the channel. Such action is prone
1689  * to deadlock if the channel is locked.
1690  *
1691  * ast_async_goto() has its own restriction on not holding the
1692  * channel lock.
1693  */
1694  ast_mutex_unlock(&p->lock);
1695  ast_channel_unlock(ast);
1696  if (ast_exists_extension(ast, target_context, "fax", 1,
1697  S_COR(ast_channel_caller(ast)->id.number.valid, ast_channel_caller(ast)->id.number.str, NULL))) {
1698  ast_verb(3, "Redirecting %s to fax extension\n", ast_channel_name(ast));
1699  /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
1700  pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast_channel_exten(ast));
1701  if (ast_async_goto(ast, target_context, "fax", 1))
1702  ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast_channel_name(ast), target_context);
1703  } else {
1704  ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
1705  }
1706  ast_channel_lock(ast);
1707  ast_mutex_lock(&p->lock);
1708  } else {
1709  ast_debug(1, "Already in a fax extension, not redirecting\n");
1710  }
1711  } else {
1712  ast_debug(1, "Fax already handled\n");
1713  }
1714  dahdi_confmute(p, 0);
1715  }
1716  p->subs[idx].f.frametype = AST_FRAME_NULL;
1717  p->subs[idx].f.subclass.integer = 0;
1718  *dest = &p->subs[idx].f;
1719  }
1720 }
1721 
1722 static void my_lock_private(void *pvt)
1723 {
1724  struct dahdi_pvt *p = pvt;
1725  ast_mutex_lock(&p->lock);
1726 }
1727 
1728 static void my_unlock_private(void *pvt)
1729 {
1730  struct dahdi_pvt *p = pvt;
1731  ast_mutex_unlock(&p->lock);
1732 }
1733 
1734 static void my_deadlock_avoidance_private(void *pvt)
1735 {
1736  struct dahdi_pvt *p = pvt;
1737 
1738  DEADLOCK_AVOIDANCE(&p->lock);
1739 }
1740 
1742 {
1743  RAII_VAR(struct ast_str *, channel_string, NULL, ast_free);
1744  struct ast_channel_blob *obj = stasis_message_data(msg);
1745  struct ast_json *group, *span, *channel;
1746 
1747  channel_string = ast_manager_build_channel_state_string(obj->snapshot);
1748  if (!channel_string) {
1749  return NULL;
1750  }
1751 
1752  group = ast_json_object_get(obj->blob, "group");
1753  span = ast_json_object_get(obj->blob, "span");
1754  channel = ast_json_object_get(obj->blob, "channel");
1755 
1756  return ast_manager_event_blob_create(EVENT_FLAG_CALL, "DAHDIChannel",
1757  "%s"
1758  "DAHDIGroup: %llu\r\n"
1759  "DAHDISpan: %u\r\n"
1760  "DAHDIChannel: %s\r\n",
1761  ast_str_buffer(channel_string),
1763  (unsigned int)ast_json_integer_get(span),
1764  ast_json_string_get(channel));
1765 }
1766 
1767 STASIS_MESSAGE_TYPE_DEFN_LOCAL(dahdichannel_type,
1769  );
1770 
1771 /*! \brief Sends a DAHDIChannel channel blob used to produce DAHDIChannel AMI messages */
1772 static void publish_dahdichannel(struct ast_channel *chan, ast_group_t group, int span, const char *dahdi_channel)
1773 {
1774  RAII_VAR(struct ast_json *, blob, NULL, ast_json_unref);
1775 
1776  ast_assert(dahdi_channel != NULL);
1777 
1778  blob = ast_json_pack("{s: I, s: i, s: s}",
1779  "group", (ast_json_int_t)group,
1780  "span", span,
1781  "channel", dahdi_channel);
1782  if (!blob) {
1783  return;
1784  }
1785 
1786  ast_channel_lock(chan);
1787  ast_channel_publish_blob(chan, dahdichannel_type(), blob);
1788  ast_channel_unlock(chan);
1789 }
1790 
1791 /*!
1792  * \internal
1793  * \brief Post an AMI DAHDI channel association event.
1794  * \since 1.8
1795  *
1796  * \param p DAHDI private pointer
1797  * \param chan Channel associated with the private pointer
1798  *
1799  * \return Nothing
1800  */
1801 static void dahdi_ami_channel_event(struct dahdi_pvt *p, struct ast_channel *chan)
1802 {
1803  char ch_name[23];
1804 
1805  if (p->channel < CHAN_PSEUDO) {
1806  /* No B channel */
1807  snprintf(ch_name, sizeof(ch_name), "no-media (%d)", p->channel);
1808  } else if (p->channel == CHAN_PSEUDO) {
1809  /* Pseudo channel */
1810  strcpy(ch_name, "pseudo");
1811  } else {
1812  /* Real channel */
1813  snprintf(ch_name, sizeof(ch_name), "%d", p->channel);
1814  }
1815  publish_dahdichannel(chan, p->group, p->span, ch_name);
1816 }
1817 
1818 #ifdef HAVE_PRI
1819 /*!
1820  * \internal
1821  * \brief Post an AMI DAHDI channel association event.
1822  * \since 1.8
1823  *
1824  * \param pvt DAHDI private pointer
1825  * \param chan Channel associated with the private pointer
1826  *
1827  * \return Nothing
1828  */
1829 static void my_ami_channel_event(void *pvt, struct ast_channel *chan)
1830 {
1831  struct dahdi_pvt *p = pvt;
1832 
1833  dahdi_ami_channel_event(p, chan);
1834 }
1835 #endif
1836 
1837 /* linear_mode = 0 - turn linear mode off, >0 - turn linear mode on
1838 * returns the last value of the linear setting
1839 */
1840 static int my_set_linear_mode(void *pvt, enum analog_sub sub, int linear_mode)
1841 {
1842  struct dahdi_pvt *p = pvt;
1843  int oldval;
1844  int idx = analogsub_to_dahdisub(sub);
1845 
1846  dahdi_setlinear(p->subs[idx].dfd, linear_mode);
1847  oldval = p->subs[idx].linear;
1848  p->subs[idx].linear = linear_mode ? 1 : 0;
1849  return oldval;
1850 }
1851 
1852 static void my_set_inthreeway(void *pvt, enum analog_sub sub, int inthreeway)
1853 {
1854  struct dahdi_pvt *p = pvt;
1855  int idx = analogsub_to_dahdisub(sub);
1856 
1857  p->subs[idx].inthreeway = inthreeway;
1858 }
1859 
1860 static int get_alarms(struct dahdi_pvt *p);
1861 static void handle_alarms(struct dahdi_pvt *p, int alms);
1862 static void my_get_and_handle_alarms(void *pvt)
1863 {
1864  int res;
1865  struct dahdi_pvt *p = pvt;
1866 
1867  res = get_alarms(p);
1868  handle_alarms(p, res);
1869 }
1870 
1871 static void *my_get_sigpvt_bridged_channel(struct ast_channel *chan)
1872 {
1874 
1875  if (bridged && ast_channel_tech(bridged) == &dahdi_tech) {
1876  struct dahdi_pvt *p = ast_channel_tech_pvt(bridged);
1877 
1878  if (dahdi_analog_lib_handles(p->sig, p->radio, p->oprmode)) {
1879  return p->sig_pvt;
1880  }
1881  }
1882  return NULL;
1883 }
1884 
1885 static int my_get_sub_fd(void *pvt, enum analog_sub sub)
1886 {
1887  struct dahdi_pvt *p = pvt;
1888  int dahdi_sub = analogsub_to_dahdisub(sub);
1889  return p->subs[dahdi_sub].dfd;
1890 }
1891 
1892 static void my_set_cadence(void *pvt, int *cid_rings, struct ast_channel *ast)
1893 {
1894  struct dahdi_pvt *p = pvt;
1895 
1896  /* Choose proper cadence */
1897  if ((p->distinctivering > 0) && (p->distinctivering <= num_cadence)) {
1898  if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &cadences[p->distinctivering - 1]))
1899  ast_log(LOG_WARNING, "Unable to set distinctive ring cadence %d on '%s': %s\n", p->distinctivering, ast_channel_name(ast), strerror(errno));
1900  *cid_rings = cidrings[p->distinctivering - 1];
1901  } else {
1902  if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, NULL))
1903  ast_log(LOG_WARNING, "Unable to reset default ring on '%s': %s\n", ast_channel_name(ast), strerror(errno));
1904  *cid_rings = p->sendcalleridafter;
1905  }
1906 }
1907 
1908 static void my_set_alarm(void *pvt, int in_alarm)
1909 {
1910  struct dahdi_pvt *p = pvt;
1911 
1912  p->inalarm = in_alarm;
1913 }
1914 
1915 static void my_set_dialing(void *pvt, int is_dialing)
1916 {
1917  struct dahdi_pvt *p = pvt;
1918 
1919  p->dialing = is_dialing;
1920 }
1921 
1922 static void my_set_outgoing(void *pvt, int is_outgoing)
1923 {
1924  struct dahdi_pvt *p = pvt;
1925 
1926  p->outgoing = is_outgoing;
1927 }
1928 
1929 #if defined(HAVE_PRI) || defined(HAVE_SS7)
1930 static void my_set_digital(void *pvt, int is_digital)
1931 {
1932  struct dahdi_pvt *p = pvt;
1933 
1934  p->digital = is_digital;
1935 }
1936 #endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */
1937 
1938 #if defined(HAVE_SS7)
1939 static void my_set_inservice(void *pvt, int is_inservice)
1940 {
1941  struct dahdi_pvt *p = pvt;
1942 
1943  p->inservice = is_inservice;
1944 }
1945 #endif /* defined(HAVE_SS7) */
1946 
1947 #if defined(HAVE_SS7)
1948 static void my_set_locallyblocked(void *pvt, int is_blocked)
1949 {
1950  struct dahdi_pvt *p = pvt;
1951 
1952  p->locallyblocked = is_blocked;
1953 }
1954 #endif /* defined(HAVE_SS7) */
1955 
1956 #if defined(HAVE_SS7)
1957 static void my_set_remotelyblocked(void *pvt, int is_blocked)
1958 {
1959  struct dahdi_pvt *p = pvt;
1960 
1961  p->remotelyblocked = is_blocked;
1962 }
1963 #endif /* defined(HAVE_SS7) */
1964 
1965 static void my_set_ringtimeout(void *pvt, int ringt)
1966 {
1967  struct dahdi_pvt *p = pvt;
1968  p->ringt = ringt;
1969 }
1970 
1971 static void my_set_waitingfordt(void *pvt, struct ast_channel *ast)
1972 {
1973  struct dahdi_pvt *p = pvt;
1974 
1975  if (p->waitfordialtone && CANPROGRESSDETECT(p) && p->dsp) {
1976  ast_debug(1, "Defer dialing for %dms or dialtone\n", p->waitfordialtone);
1977  gettimeofday(&p->waitingfordt, NULL);
1979  }
1980 }
1981 
1982 static int my_check_waitingfordt(void *pvt)
1983 {
1984  struct dahdi_pvt *p = pvt;
1985 
1986  if (p->waitingfordt.tv_sec) {
1987  return 1;
1988  }
1989 
1990  return 0;
1991 }
1992 
1993 static void my_set_confirmanswer(void *pvt, int flag)
1994 {
1995  struct dahdi_pvt *p = pvt;
1996  p->confirmanswer = flag;
1997 }
1998 
1999 static int my_check_confirmanswer(void *pvt)
2000 {
2001  struct dahdi_pvt *p = pvt;
2002  if (p->confirmanswer) {
2003  return 1;
2004  }
2005 
2006  return 0;
2007 }
2008 
2009 static void my_set_callwaiting(void *pvt, int callwaiting_enable)
2010 {
2011  struct dahdi_pvt *p = pvt;
2012 
2013  p->callwaiting = callwaiting_enable;
2014 }
2015 
2016 static void my_cancel_cidspill(void *pvt)
2017 {
2018  struct dahdi_pvt *p = pvt;
2019 
2020  ast_free(p->cidspill);
2021  p->cidspill = NULL;
2022  restore_conference(p);
2023 }
2024 
2025 static int my_confmute(void *pvt, int mute)
2026 {
2027  struct dahdi_pvt *p = pvt;
2028  return dahdi_confmute(p, mute);
2029 }
2030 
2031 static void my_set_pulsedial(void *pvt, int flag)
2032 {
2033  struct dahdi_pvt *p = pvt;
2034  p->pulsedial = flag;
2035 }
2036 
2037 static void my_set_new_owner(void *pvt, struct ast_channel *new_owner)
2038 {
2039  struct dahdi_pvt *p = pvt;
2040 
2041  p->owner = new_owner;
2042 }
2043 
2044 static const char *my_get_orig_dialstring(void *pvt)
2045 {
2046  struct dahdi_pvt *p = pvt;
2047 
2048  return p->dialstring;
2049 }
2050 
2051 static void my_increase_ss_count(void)
2052 {
2054  ss_thread_count++;
2056 }
2057 
2058 static void my_decrease_ss_count(void)
2059 {
2061  ss_thread_count--;
2064 }
2065 
2066 static void my_all_subchannels_hungup(void *pvt)
2067 {
2068  struct dahdi_pvt *p = pvt;
2069  int res, law;
2070 
2071  p->faxhandled = 0;
2072  p->didtdd = 0;
2073 
2074  if (p->dsp) {
2075  ast_dsp_free(p->dsp);
2076  p->dsp = NULL;
2077  }
2078 
2079  p->law = p->law_default;
2080  law = p->law_default;
2081  res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
2082  if (res < 0)
2083  ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
2084 
2085  dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
2086 
2087 #if 1
2088  {
2089  int i;
2090  p->owner = NULL;
2091  /* Cleanup owners here */
2092  for (i = 0; i < 3; i++) {
2093  p->subs[i].owner = NULL;
2094  }
2095  }
2096 #endif
2097 
2098  reset_conf(p);
2099  if (num_restart_pending == 0) {
2100  restart_monitor();
2101  }
2102 }
2103 
2104 static int conf_del(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index);
2105 
2106 static int my_conf_del(void *pvt, enum analog_sub sub)
2107 {
2108  struct dahdi_pvt *p = pvt;
2109  int x = analogsub_to_dahdisub(sub);
2110 
2111  return conf_del(p, &p->subs[x], x);
2112 }
2113 
2114 static int conf_add(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index, int slavechannel);
2115 
2116 static int my_conf_add(void *pvt, enum analog_sub sub)
2117 {
2118  struct dahdi_pvt *p = pvt;
2119  int x = analogsub_to_dahdisub(sub);
2120 
2121  return conf_add(p, &p->subs[x], x, 0);
2122 }
2123 
2124 static int isslavenative(struct dahdi_pvt *p, struct dahdi_pvt **out);
2125 
2126 static int my_complete_conference_update(void *pvt, int needconference)
2127 {
2128  struct dahdi_pvt *p = pvt;
2129  int needconf = needconference;
2130  int x;
2131  int useslavenative;
2132  struct dahdi_pvt *slave = NULL;
2133 
2134  useslavenative = isslavenative(p, &slave);
2135 
2136  /* If we have a slave, add him to our conference now. or DAX
2137  if this is slave native */
2138  for (x = 0; x < MAX_SLAVES; x++) {
2139  if (p->slaves[x]) {
2140  if (useslavenative)
2141  conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
2142  else {
2143  conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
2144  needconf++;
2145  }
2146  }
2147  }
2148  /* If we're supposed to be in there, do so now */
2149  if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
2150  if (useslavenative)
2151  conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
2152  else {
2153  conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
2154  needconf++;
2155  }
2156  }
2157  /* If we have a master, add ourselves to his conference */
2158  if (p->master) {
2159  if (isslavenative(p->master, NULL)) {
2161  } else {
2162  conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
2163  }
2164  }
2165  if (!needconf) {
2166  /* Nobody is left (or should be left) in our conference.
2167  Kill it. */
2168  p->confno = -1;
2169  }
2170 
2171  return 0;
2172 }
2173 
2174 static int check_for_conference(struct dahdi_pvt *p);
2175 
2176 static int my_check_for_conference(void *pvt)
2177 {
2178  struct dahdi_pvt *p = pvt;
2179  return check_for_conference(p);
2180 }
2181 
2182 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)
2183 {
2184  struct dahdi_pvt *p = pvt;
2185  int da, db;
2186  int tchan;
2187  int tinthreeway;
2188 
2189  da = analogsub_to_dahdisub(a);
2190  db = analogsub_to_dahdisub(b);
2191 
2192  tchan = p->subs[da].chan;
2193  p->subs[da].chan = p->subs[db].chan;
2194  p->subs[db].chan = tchan;
2195 
2196  tinthreeway = p->subs[da].inthreeway;
2197  p->subs[da].inthreeway = p->subs[db].inthreeway;
2198  p->subs[db].inthreeway = tinthreeway;
2199 
2200  p->subs[da].owner = ast_a;
2201  p->subs[db].owner = ast_b;
2202 
2203  if (ast_a)
2204  ast_channel_set_fd(ast_a, 0, p->subs[da].dfd);
2205  if (ast_b)
2206  ast_channel_set_fd(ast_b, 0, p->subs[db].dfd);
2207 
2208  wakeup_sub(p, a);
2209  wakeup_sub(p, b);
2210 
2211  return;
2212 }
2213 
2214 /*!
2215  * \internal
2216  * \brief performs duties of dahdi_new, but also removes and possibly unbinds (if callid_created is 1) before returning
2217  * \note this variant of dahdi should only be used in conjunction with ast_callid_threadstorage_auto()
2218  *
2219  * \param callid_created value returned from ast_callid_threadstorage_auto()
2220  */
2221 static struct ast_channel *dahdi_new_callid_clean(struct dahdi_pvt *i, int state, int startpbx, int idx, int law, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, ast_callid callid, int callid_created);
2222 
2223 static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpbx, int idx, int law, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, ast_callid callid);
2224 
2225 static struct ast_channel *my_new_analog_ast_channel(void *pvt, int state, int startpbx, enum analog_sub sub, const struct ast_channel *requestor)
2226 {
2227  ast_callid callid = 0;
2228  int callid_created = ast_callid_threadstorage_auto(&callid);
2229  struct dahdi_pvt *p = pvt;
2230  int dsub = analogsub_to_dahdisub(sub);
2231 
2232  return dahdi_new_callid_clean(p, state, startpbx, dsub, 0, NULL, requestor, callid, callid_created);
2233 }
2234 
2235 #if defined(HAVE_PRI) || defined(HAVE_SS7)
2236 static int dahdi_setlaw(int dfd, int law)
2237 {
2238  int res;
2239  res = ioctl(dfd, DAHDI_SETLAW, &law);
2240  if (res)
2241  return res;
2242  return 0;
2243 }
2244 #endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */
2245 
2246 #if defined(HAVE_PRI)
2247 static struct ast_channel *my_new_pri_ast_channel(void *pvt, int state,
2248  enum sig_pri_law law, char *exten, const struct ast_assigned_ids *assignedids,
2249  const struct ast_channel *requestor)
2250 {
2251  struct dahdi_pvt *p = pvt;
2252  int audio;
2253  int newlaw = -1;
2254  ast_callid callid = 0;
2255  int callid_created = ast_callid_threadstorage_auto(&callid);
2256 
2257  switch (p->sig) {
2259  if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
2260  /* PRI nobch pseudo channel. Does not handle ioctl(DAHDI_AUDIOMODE) */
2261  break;
2262  }
2263  /* Fall through */
2264  default:
2265  /* Set to audio mode at this point */
2266  audio = 1;
2267  if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &audio) == -1) {
2268  ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n",
2269  p->channel, audio, strerror(errno));
2270  }
2271  break;
2272  }
2273 
2274  if (law != SIG_PRI_DEFLAW) {
2275  dahdi_setlaw(p->subs[SUB_REAL].dfd, (law == SIG_PRI_ULAW) ? DAHDI_LAW_MULAW : DAHDI_LAW_ALAW);
2276  }
2277 
2278  ast_copy_string(p->exten, exten, sizeof(p->exten));
2279 
2280  switch (law) {
2281  case SIG_PRI_DEFLAW:
2282  newlaw = 0;
2283  break;
2284  case SIG_PRI_ALAW:
2285  newlaw = DAHDI_LAW_ALAW;
2286  break;
2287  case SIG_PRI_ULAW:
2288  newlaw = DAHDI_LAW_MULAW;
2289  break;
2290  }
2291 
2292  return dahdi_new_callid_clean(p, state, 0, SUB_REAL, newlaw, assignedids, requestor, callid, callid_created);
2293 }
2294 #endif /* defined(HAVE_PRI) */
2295 
2296 static int set_actual_gain(int fd, float rxgain, float txgain, float rxdrc, float txdrc, int law);
2297 
2298 #if defined(HAVE_PRI) || defined(HAVE_SS7)
2299 /*!
2300  * \internal
2301  * \brief Open the PRI/SS7 channel media path.
2302  * \since 1.8
2303  *
2304  * \param p Channel private control structure.
2305  *
2306  * \return Nothing
2307  */
2308 static void my_pri_ss7_open_media(void *p)
2309 {
2310  struct dahdi_pvt *pvt = p;
2311  int res;
2312  int dfd;
2313  int set_val;
2314 
2315  dfd = pvt->subs[SUB_REAL].dfd;
2316 
2317  /* Open the media path. */
2318  set_val = 1;
2319  res = ioctl(dfd, DAHDI_AUDIOMODE, &set_val);
2320  if (res < 0) {
2321  ast_log(LOG_WARNING, "Unable to enable audio mode on channel %d (%s)\n",
2322  pvt->channel, strerror(errno));
2323  }
2324 
2325  /* Set correct companding law for this call. */
2326  res = dahdi_setlaw(dfd, pvt->law);
2327  if (res < 0) {
2328  ast_log(LOG_WARNING, "Unable to set law on channel %d\n", pvt->channel);
2329  }
2330 
2331  /* Set correct gain for this call. */
2332  if (pvt->digital) {
2333  res = set_actual_gain(dfd, 0, 0, pvt->rxdrc, pvt->txdrc, pvt->law);
2334  } else {
2335  res = set_actual_gain(dfd, pvt->rxgain, pvt->txgain, pvt->rxdrc, pvt->txdrc,
2336  pvt->law);
2337  }
2338  if (res < 0) {
2339  ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", pvt->channel);
2340  }
2341 
2342  if (pvt->dsp_features && pvt->dsp) {
2344  }
2345 }
2346 #endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */
2347 
2348 #if defined(HAVE_PRI)
2349 /*!
2350  * \internal
2351  * \brief Ask DAHDI to dial the given dial string.
2352  * \since 1.8.11
2353  *
2354  * \param p Channel private control structure.
2355  * \param dial_string String to pass to DAHDI to dial.
2356  *
2357  * \note The channel private lock needs to be held when calling.
2358  *
2359  * \return Nothing
2360  */
2361 static void my_pri_dial_digits(void *p, const char *dial_string)
2362 {
2363  char dial_str[DAHDI_MAX_DTMF_BUF];
2364  struct dahdi_pvt *pvt = p;
2365  int res;
2366 
2367  snprintf(dial_str, sizeof(dial_str), "T%s", dial_string);
2368  res = dahdi_dial_str(pvt, DAHDI_DIAL_OP_APPEND, dial_str);
2369  if (!res) {
2370  pvt->dialing = 1;
2371  }
2372 }
2373 #endif /* defined(HAVE_PRI) */
2374 
2375 static int unalloc_sub(struct dahdi_pvt *p, int x);
2376 
2377 static int my_unallocate_sub(void *pvt, enum analog_sub analogsub)
2378 {
2379  struct dahdi_pvt *p = pvt;
2380 
2381  return unalloc_sub(p, analogsub_to_dahdisub(analogsub));
2382 }
2383 
2384 static int alloc_sub(struct dahdi_pvt *p, int x);
2385 
2386 static int my_allocate_sub(void *pvt, enum analog_sub analogsub)
2387 {
2388  struct dahdi_pvt *p = pvt;
2389 
2390  return alloc_sub(p, analogsub_to_dahdisub(analogsub));
2391 }
2392 
2393 static int has_voicemail(struct dahdi_pvt *p);
2394 
2395 static int my_has_voicemail(void *pvt)
2396 {
2397  struct dahdi_pvt *p = pvt;
2398 
2399  return has_voicemail(p);
2400 }
2401 
2402 static int my_play_tone(void *pvt, enum analog_sub sub, enum analog_tone tone)
2403 {
2404  struct dahdi_pvt *p = pvt;
2405  int index;
2406 
2407  index = analogsub_to_dahdisub(sub);
2408 
2409  return tone_zone_play_tone(p->subs[index].dfd, analog_tone_to_dahditone(tone));
2410 }
2411 
2413 {
2414  enum analog_event res;
2415 
2416  switch (event) {
2417  case DAHDI_EVENT_ONHOOK:
2418  res = ANALOG_EVENT_ONHOOK;
2419  break;
2420  case DAHDI_EVENT_RINGOFFHOOK:
2422  break;
2423  case DAHDI_EVENT_WINKFLASH:
2424  res = ANALOG_EVENT_WINKFLASH;
2425  break;
2426  case DAHDI_EVENT_ALARM:
2427  res = ANALOG_EVENT_ALARM;
2428  break;
2429  case DAHDI_EVENT_NOALARM:
2430  res = ANALOG_EVENT_NOALARM;
2431  break;
2432  case DAHDI_EVENT_DIALCOMPLETE:
2434  break;
2435  case DAHDI_EVENT_RINGERON:
2436  res = ANALOG_EVENT_RINGERON;
2437  break;
2438  case DAHDI_EVENT_RINGEROFF:
2439  res = ANALOG_EVENT_RINGEROFF;
2440  break;
2441  case DAHDI_EVENT_HOOKCOMPLETE:
2443  break;
2444  case DAHDI_EVENT_PULSE_START:
2446  break;
2447  case DAHDI_EVENT_POLARITY:
2448  res = ANALOG_EVENT_POLARITY;
2449  break;
2450  case DAHDI_EVENT_RINGBEGIN:
2451  res = ANALOG_EVENT_RINGBEGIN;
2452  break;
2453  case DAHDI_EVENT_EC_DISABLED:
2455  break;
2456  case DAHDI_EVENT_REMOVED:
2457  res = ANALOG_EVENT_REMOVED;
2458  break;
2459  case DAHDI_EVENT_NEONMWI_ACTIVE:
2461  break;
2462  case DAHDI_EVENT_NEONMWI_INACTIVE:
2464  break;
2465 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
2466  case DAHDI_EVENT_TX_CED_DETECTED:
2468  break;
2469  case DAHDI_EVENT_RX_CED_DETECTED:
2471  break;
2472  case DAHDI_EVENT_EC_NLP_DISABLED:
2474  break;
2475  case DAHDI_EVENT_EC_NLP_ENABLED:
2477  break;
2478 #endif
2479  case DAHDI_EVENT_PULSEDIGIT:
2481  break;
2482  case DAHDI_EVENT_DTMFDOWN:
2483  res = ANALOG_EVENT_DTMFDOWN;
2484  break;
2485  case DAHDI_EVENT_DTMFUP:
2486  res = ANALOG_EVENT_DTMFUP;
2487  break;
2488  default:
2489  switch(event & 0xFFFF0000) {
2490  case DAHDI_EVENT_PULSEDIGIT:
2491  case DAHDI_EVENT_DTMFDOWN:
2492  case DAHDI_EVENT_DTMFUP:
2493  /* The event includes a digit number in the low word.
2494  * Converting it to a 'enum analog_event' would remove
2495  * that information. Thus it is returned as-is.
2496  */
2497  return event;
2498  }
2499 
2500  res = ANALOG_EVENT_ERROR;
2501  break;
2502  }
2503 
2504  return res;
2505 }
2506 
2507 static inline int dahdi_wait_event(int fd);
2508 
2509 static int my_wait_event(void *pvt)
2510 {
2511  struct dahdi_pvt *p = pvt;
2512 
2513  return dahdi_wait_event(p->subs[SUB_REAL].dfd);
2514 }
2515 
2516 static int my_get_event(void *pvt)
2517 {
2518  struct dahdi_pvt *p = pvt;
2519  int res;
2520 
2521  if (p->fake_event) {
2522  res = p->fake_event;
2523  p->fake_event = 0;
2524  } else
2525  res = dahdi_get_event(p->subs[SUB_REAL].dfd);
2526 
2527  return dahdievent_to_analogevent(res);
2528 }
2529 
2530 static int my_is_off_hook(void *pvt)
2531 {
2532  struct dahdi_pvt *p = pvt;
2533  int res;
2534  struct dahdi_params par;
2535 
2536  memset(&par, 0, sizeof(par));
2537 
2538  if (p->subs[SUB_REAL].dfd > -1)
2539  res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
2540  else {
2541  /* Assume not off hook on CVRS */
2542  res = 0;
2543  par.rxisoffhook = 0;
2544  }
2545  if (res) {
2546  ast_log(LOG_WARNING, "Unable to check hook state on channel %d: %s\n", p->channel, strerror(errno));
2547  }
2548 
2549  if ((p->sig == SIG_FXSKS) || (p->sig == SIG_FXSGS)) {
2550  /* When "onhook" that means no battery on the line, and thus
2551  it is out of service..., if it's on a TDM card... If it's a channel
2552  bank, there is no telling... */
2553  return (par.rxbits > -1) || par.rxisoffhook;
2554  }
2555 
2556  return par.rxisoffhook;
2557 }
2558 
2559 static int my_set_echocanceller(void *pvt, int enable)
2560 {
2561  struct dahdi_pvt *p = pvt;
2562 
2563  if (enable)
2564  dahdi_ec_enable(p);
2565  else
2566  dahdi_ec_disable(p);
2567 
2568  return 0;
2569 }
2570 
2571 static int dahdi_ring_phone(struct dahdi_pvt *p);
2572 
2573 static int my_ring(void *pvt)
2574 {
2575  struct dahdi_pvt *p = pvt;
2576 
2577  return dahdi_ring_phone(p);
2578 }
2579 
2580 static int my_flash(void *pvt)
2581 {
2582  struct dahdi_pvt *p = pvt;
2583  int func = DAHDI_FLASH;
2584  return ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &func);
2585 }
2586 
2587 static inline int dahdi_set_hook(int fd, int hs);
2588 
2589 static int my_off_hook(void *pvt)
2590 {
2591  struct dahdi_pvt *p = pvt;
2592  return dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
2593 }
2594 
2595 static void my_set_needringing(void *pvt, int value)
2596 {
2597  struct dahdi_pvt *p = pvt;
2599 }
2600 
2601 static void my_set_polarity(void *pvt, int value)
2602 {
2603  struct dahdi_pvt *p = pvt;
2604 
2605  if (p->channel == CHAN_PSEUDO) {
2606  return;
2607  }
2608  p->polarity = value;
2609  ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETPOLARITY, &value);
2610 }
2611 
2612 static void my_start_polarityswitch(void *pvt)
2613 {
2614  struct dahdi_pvt *p = pvt;
2615 
2617  my_set_polarity(pvt, 0);
2618  }
2619 }
2620 
2621 static void my_answer_polarityswitch(void *pvt)
2622 {
2623  struct dahdi_pvt *p = pvt;
2624 
2625  if (!p->answeronpolarityswitch) {
2626  return;
2627  }
2628 
2629  my_set_polarity(pvt, 1);
2630 }
2631 
2632 static void my_hangup_polarityswitch(void *pvt)
2633 {
2634  struct dahdi_pvt *p = pvt;
2635 
2636  if (!p->hanguponpolarityswitch) {
2637  return;
2638  }
2639 
2640  if (p->answeronpolarityswitch) {
2641  my_set_polarity(pvt, 0);
2642  } else {
2643  my_set_polarity(pvt, 1);
2644  }
2645 }
2646 
2647 static int my_start(void *pvt)
2648 {
2649  struct dahdi_pvt *p = pvt;
2650  int x = DAHDI_START;
2651 
2652  return ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
2653 }
2654 
2655 static int my_dial_digits(void *pvt, enum analog_sub sub, struct analog_dialoperation *dop)
2656 {
2657  struct dahdi_pvt *p = pvt;
2658 
2659  if (dop->op != ANALOG_DIAL_OP_REPLACE) {
2660  ast_log(LOG_ERROR, "Fix the dial_digits callback!\n");
2661  return -1;
2662  }
2663 
2664  if (sub != ANALOG_SUB_REAL) {
2665  ast_log(LOG_ERROR, "Trying to dial_digits '%s' on channel %d subchannel %u\n",
2666  dop->dialstr, p->channel, sub);
2667  return -1;
2668  }
2669 
2670  return dahdi_dial_str(p, DAHDI_DIAL_OP_REPLACE, dop->dialstr);
2671 }
2672 
2673 static void dahdi_train_ec(struct dahdi_pvt *p);
2674 
2675 static int my_train_echocanceller(void *pvt)
2676 {
2677  struct dahdi_pvt *p = pvt;
2678 
2679  dahdi_train_ec(p);
2680 
2681  return 0;
2682 }
2683 
2684 static int my_is_dialing(void *pvt, enum analog_sub sub)
2685 {
2686  struct dahdi_pvt *p = pvt;
2687  int index;
2688  int x;
2689 
2690  index = analogsub_to_dahdisub(sub);
2691 
2692  if (ioctl(p->subs[index].dfd, DAHDI_DIALING, &x)) {
2693  ast_debug(1, "DAHDI_DIALING ioctl failed!\n");
2694  return -1;
2695  }
2696 
2697  return x;
2698 }
2699 
2700 static int my_on_hook(void *pvt)
2701 {
2702  struct dahdi_pvt *p = pvt;
2703  return dahdi_set_hook(p->subs[ANALOG_SUB_REAL].dfd, DAHDI_ONHOOK);
2704 }
2705 
2706 #if defined(HAVE_PRI)
2707 static void my_pri_fixup_chans(void *chan_old, void *chan_new)
2708 {
2709  struct dahdi_pvt *old_chan = chan_old;
2710  struct dahdi_pvt *new_chan = chan_new;
2711 
2712  new_chan->owner = old_chan->owner;
2713  old_chan->owner = NULL;
2714  if (new_chan->owner) {
2715  ast_channel_tech_pvt_set(new_chan->owner, new_chan);
2716  ast_channel_internal_fd_set(new_chan->owner, 0, new_chan->subs[SUB_REAL].dfd);
2717  new_chan->subs[SUB_REAL].owner = old_chan->subs[SUB_REAL].owner;
2718  old_chan->subs[SUB_REAL].owner = NULL;
2719  }
2720  /* Copy any DSP that may be present */
2721  new_chan->dsp = old_chan->dsp;
2722  new_chan->dsp_features = old_chan->dsp_features;
2723  old_chan->dsp = NULL;
2724  old_chan->dsp_features = 0;
2725 
2726  /* Transfer flags from the old channel. */
2727  new_chan->dialing = old_chan->dialing;
2728  new_chan->digital = old_chan->digital;
2729  new_chan->outgoing = old_chan->outgoing;
2730  old_chan->dialing = 0;
2731  old_chan->digital = 0;
2732  old_chan->outgoing = 0;
2733 
2734  /* More stuff to transfer to the new channel. */
2735  new_chan->law = old_chan->law;
2736  strcpy(new_chan->dialstring, old_chan->dialstring);
2737 }
2738 #endif /* defined(HAVE_PRI) */
2739 
2740 #if defined(HAVE_PRI)
2741 static int sig_pri_tone_to_dahditone(enum sig_pri_tone tone)
2742 {
2743  switch (tone) {
2744  case SIG_PRI_TONE_RINGTONE:
2745  return DAHDI_TONE_RINGTONE;
2746  case SIG_PRI_TONE_STUTTER:
2747  return DAHDI_TONE_STUTTER;
2749  return DAHDI_TONE_CONGESTION;
2750  case SIG_PRI_TONE_DIALTONE:
2751  return DAHDI_TONE_DIALTONE;
2753  return DAHDI_TONE_DIALRECALL;
2754  case SIG_PRI_TONE_INFO:
2755  return DAHDI_TONE_INFO;
2756  case SIG_PRI_TONE_BUSY:
2757  return DAHDI_TONE_BUSY;
2758  default:
2759  return -1;
2760  }
2761 }
2762 #endif /* defined(HAVE_PRI) */
2763 
2764 #if defined(HAVE_PRI)
2765 static void my_handle_dchan_exception(struct sig_pri_span *pri, int index)
2766 {
2767  int x;
2768 
2769  ioctl(pri->fds[index], DAHDI_GETEVENT, &x);
2770  switch (x) {
2771  case DAHDI_EVENT_NONE:
2772  break;
2773  case DAHDI_EVENT_ALARM:
2774  case DAHDI_EVENT_NOALARM:
2775  if (sig_pri_is_alarm_ignored(pri)) {
2776  break;
2777  }
2778  /* Fall through */
2779  default:
2780  ast_log(LOG_NOTICE, "Got DAHDI event: %s (%d) on D-channel of span %d\n",
2781  event2str(x), x, pri->span);
2782  break;
2783  }
2784  /* Keep track of alarm state */
2785  switch (x) {
2786  case DAHDI_EVENT_ALARM:
2787  pri_event_alarm(pri, index, 0);
2788  break;
2789  case DAHDI_EVENT_NOALARM:
2790  pri_event_noalarm(pri, index, 0);
2791  break;
2792  case DAHDI_EVENT_REMOVED:
2793  pri_queue_for_destruction(pri);
2794  break;
2795  default:
2796  break;
2797  }
2798 }
2799 #endif /* defined(HAVE_PRI) */
2800 
2801 #if defined(HAVE_PRI)
2802 static int my_pri_play_tone(void *pvt, enum sig_pri_tone tone)
2803 {
2804  struct dahdi_pvt *p = pvt;
2805 
2806  return tone_zone_play_tone(p->subs[SUB_REAL].dfd, sig_pri_tone_to_dahditone(tone));
2807 }
2808 #endif /* defined(HAVE_PRI) */
2809 
2810 #if defined(HAVE_PRI) || defined(HAVE_SS7)
2811 /*!
2812  * \internal
2813  * \brief Set the caller id information.
2814  * \since 1.8
2815  *
2816  * \param pvt DAHDI private structure
2817  * \param caller Caller-id information to set.
2818  *
2819  * \return Nothing
2820  */
2821 static void my_set_callerid(void *pvt, const struct ast_party_caller *caller)
2822 {
2823  struct dahdi_pvt *p = pvt;
2824 
2826  S_COR(caller->id.number.valid, caller->id.number.str, ""),
2827  sizeof(p->cid_num));
2829  S_COR(caller->id.name.valid, caller->id.name.str, ""),
2830  sizeof(p->cid_name));
2832  S_COR(caller->id.subaddress.valid, caller->id.subaddress.str, ""),
2833  sizeof(p->cid_subaddr));
2834  p->cid_ton = caller->id.number.plan;
2835  p->callingpres = ast_party_id_presentation(&caller->id);
2836  if (caller->id.tag) {
2837  ast_copy_string(p->cid_tag, caller->id.tag, sizeof(p->cid_tag));
2838  }
2839  ast_copy_string(p->cid_ani,
2840  S_COR(caller->ani.number.valid, caller->ani.number.str, ""),
2841  sizeof(p->cid_ani));
2842  p->cid_ani2 = caller->ani2;
2843 }
2844 #endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */
2845 
2846 #if defined(HAVE_PRI) || defined(HAVE_SS7)
2847 /*!
2848  * \internal
2849  * \brief Set the Dialed Number Identifier.
2850  * \since 1.8
2851  *
2852  * \param pvt DAHDI private structure
2853  * \param dnid Dialed Number Identifier string.
2854  *
2855  * \return Nothing
2856  */
2857 static void my_set_dnid(void *pvt, const char *dnid)
2858 {
2859  struct dahdi_pvt *p = pvt;
2860 
2861  ast_copy_string(p->dnid, dnid, sizeof(p->dnid));
2862 }
2863 #endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */
2864 
2865 #if defined(HAVE_PRI)
2866 /*!
2867  * \internal
2868  * \brief Set the Redirecting Directory Number Information Service (RDNIS).
2869  * \since 1.8
2870  *
2871  * \param pvt DAHDI private structure
2872  * \param rdnis Redirecting Directory Number Information Service (RDNIS) string.
2873  *
2874  * \return Nothing
2875  */
2876 static void my_set_rdnis(void *pvt, const char *rdnis)
2877 {
2878  struct dahdi_pvt *p = pvt;
2879 
2880  ast_copy_string(p->rdnis, rdnis, sizeof(p->rdnis));
2881 }
2882 #endif /* defined(HAVE_PRI) */
2883 
2884 #if defined(HAVE_PRI)
2885 /*!
2886  * \internal
2887  * \brief Make a dialstring for native ISDN CC to recall properly.
2888  * \since 1.8
2889  *
2890  * \param priv Channel private control structure.
2891  * \param buf Where to put the modified dialstring.
2892  * \param buf_size Size of modified dialstring buffer.
2893  *
2894  * \details
2895  * original dialstring:
2896  * DAHDI/[i<span>-](g|G|r|R)<group#(0-63)>[c|r<cadance#>|d][/extension[/options]]
2897  *
2898  * The modified dialstring will have prefixed the channel-group section
2899  * with the ISDN channel restriction.
2900  *
2901  * buf:
2902  * DAHDI/i<span>-(g|G|r|R)<group#(0-63)>[c|r<cadance#>|d][/extension[/options]]
2903  *
2904  * The routine will check to see if the ISDN channel restriction is already
2905  * in the original dialstring.
2906  *
2907  * \return Nothing
2908  */
2909 static void my_pri_make_cc_dialstring(void *priv, char *buf, size_t buf_size)
2910 {
2911  char *dial;
2912  struct dahdi_pvt *pvt;
2914  AST_APP_ARG(tech); /* channel technology token */
2915  AST_APP_ARG(group); /* channel/group token */
2916  //AST_APP_ARG(ext); /* extension token */
2917  //AST_APP_ARG(opts); /* options token */
2918  //AST_APP_ARG(other); /* Any remining unused arguments */
2919  );
2920 
2921  pvt = priv;
2922  dial = ast_strdupa(pvt->dialstring);
2923  AST_NONSTANDARD_APP_ARGS(args, dial, '/');
2924  if (!args.tech) {
2925  ast_copy_string(buf, pvt->dialstring, buf_size);
2926  return;
2927  }
2928  if (!args.group) {
2929  /* Append the ISDN span channel restriction to the dialstring. */
2930  snprintf(buf, buf_size, "%s/i%d-", args.tech, pvt->pri->span);
2931  return;
2932  }
2933  if (isdigit(args.group[0]) || args.group[0] == 'i' || strchr(args.group, '!')) {
2934  /* The ISDN span channel restriction is not needed or already
2935  * in the dialstring. */
2936  ast_copy_string(buf, pvt->dialstring, buf_size);
2937  return;
2938  }
2939  /* Insert the ISDN span channel restriction into the dialstring. */
2940  snprintf(buf, buf_size, "%s/i%d-%s", args.tech, pvt->pri->span, args.group);
2941 }
2942 #endif /* defined(HAVE_PRI) */
2943 
2944 #if defined(HAVE_PRI)
2945 /*!
2946  * \internal
2947  * \brief Reevaluate the PRI span device state.
2948  * \since 1.8
2949  *
2950  * \param pri Asterisk D channel control structure.
2951  *
2952  * \return Nothing
2953  *
2954  * \note Assumes the pri->lock is already obtained.
2955  */
2956 static void dahdi_pri_update_span_devstate(struct sig_pri_span *pri)
2957 {
2958  unsigned idx;
2959  unsigned num_b_chans; /* Number of B channels provisioned on the span. */
2960  unsigned in_use; /* Number of B channels in use on the span. */
2961  unsigned in_alarm; /* TRUE if the span is in alarm condition. */
2962  enum ast_device_state new_state;
2963 
2964  /* Count the number of B channels and the number of B channels in use. */
2965  num_b_chans = 0;
2966  in_use = 0;
2967  in_alarm = 1;
2968  for (idx = pri->numchans; idx--;) {
2969  if (pri->pvts[idx] && !pri->pvts[idx]->no_b_channel) {
2970  /* This is a B channel interface. */
2971  ++num_b_chans;
2972  if (!sig_pri_is_chan_available(pri->pvts[idx])) {
2973  ++in_use;
2974  }
2975  if (!pri->pvts[idx]->inalarm) {
2976  /* There is a channel that is not in alarm. */
2977  in_alarm = 0;
2978  }
2979  }
2980  }
2981 
2982  /* Update the span congestion device state and report any change. */
2983  if (in_alarm) {
2984  new_state = AST_DEVICE_UNAVAILABLE;
2985  } else {
2986  new_state = num_b_chans == in_use ? AST_DEVICE_BUSY : AST_DEVICE_NOT_INUSE;
2987  }
2988  if (pri->congestion_devstate != new_state) {
2989  pri->congestion_devstate = new_state;
2991  }
2992 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
2993  /* Update the span threshold device state and report any change. */
2994  if (in_alarm) {
2995  new_state = AST_DEVICE_UNAVAILABLE;
2996  } else if (!in_use) {
2997  new_state = AST_DEVICE_NOT_INUSE;
2998  } else if (!pri->user_busy_threshold) {
2999  new_state = in_use < num_b_chans ? AST_DEVICE_INUSE : AST_DEVICE_BUSY;
3000  } else {
3001  new_state = in_use < pri->user_busy_threshold ? AST_DEVICE_INUSE
3002  : AST_DEVICE_BUSY;
3003  }
3004  if (pri->threshold_devstate != new_state) {
3005  pri->threshold_devstate = new_state;
3007  }
3008 #endif /* defined(THRESHOLD_DEVSTATE_PLACEHOLDER) */
3009 }
3010 #endif /* defined(HAVE_PRI) */
3011 
3012 #if defined(HAVE_PRI)
3013 /*!
3014  * \internal
3015  * \brief Reference this module.
3016  * \since 1.8
3017  *
3018  * \return Nothing
3019  */
3020 static void my_module_ref(void)
3021 {
3023 }
3024 #endif /* defined(HAVE_PRI) */
3025 
3026 #if defined(HAVE_PRI)
3027 /*!
3028  * \internal
3029  * \brief Unreference this module.
3030  * \since 1.8
3031  *
3032  * \return Nothing
3033  */
3034 static void my_module_unref(void)
3035 {
3037 }
3038 #endif /* defined(HAVE_PRI) */
3039 
3040 #if defined(HAVE_PRI)
3041 #if defined(HAVE_PRI_CALL_WAITING)
3042 static void my_pri_init_config(void *priv, struct sig_pri_span *pri);
3043 #endif /* defined(HAVE_PRI_CALL_WAITING) */
3044 static int dahdi_new_pri_nobch_channel(struct sig_pri_span *pri);
3045 
3046 struct sig_pri_callback sig_pri_callbacks =
3047 {
3048  .handle_dchan_exception = my_handle_dchan_exception,
3049  .play_tone = my_pri_play_tone,
3050  .set_echocanceller = my_set_echocanceller,
3051  .dsp_reset_and_flush_digits = my_dsp_reset_and_flush_digits,
3052  .lock_private = my_lock_private,
3053  .unlock_private = my_unlock_private,
3054  .deadlock_avoidance_private = my_deadlock_avoidance_private,
3055  .new_ast_channel = my_new_pri_ast_channel,
3056  .fixup_chans = my_pri_fixup_chans,
3057  .set_alarm = my_set_alarm,
3058  .set_dialing = my_set_dialing,
3059  .set_outgoing = my_set_outgoing,
3060  .set_digital = my_set_digital,
3061  .set_callerid = my_set_callerid,
3062  .set_dnid = my_set_dnid,
3063  .set_rdnis = my_set_rdnis,
3064  .new_nobch_intf = dahdi_new_pri_nobch_channel,
3065 #if defined(HAVE_PRI_CALL_WAITING)
3066  .init_config = my_pri_init_config,
3067 #endif /* defined(HAVE_PRI_CALL_WAITING) */
3068  .get_orig_dialstring = my_get_orig_dialstring,
3069  .make_cc_dialstring = my_pri_make_cc_dialstring,
3070  .update_span_devstate = dahdi_pri_update_span_devstate,
3071  .module_ref = my_module_ref,
3072  .module_unref = my_module_unref,
3073  .dial_digits = my_pri_dial_digits,
3074  .open_media = my_pri_ss7_open_media,
3075  .ami_channel_event = my_ami_channel_event,
3076  .destroy_later = pri_queue_for_destruction,
3077 };
3078 #endif /* defined(HAVE_PRI) */
3079 
3080 #if defined(HAVE_SS7)
3081 /*!
3082  * \internal
3083  * \brief Handle the SS7 link exception.
3084  * \since 1.8
3085  *
3086  * \param linkset Controlling linkset for the channel.
3087  * \param which Link index of the signaling channel.
3088  *
3089  * \return Nothing
3090  */
3091 static void my_handle_link_exception(struct sig_ss7_linkset *linkset, int which)
3092 {
3093  int event;
3094 
3095  if (ioctl(linkset->fds[which], DAHDI_GETEVENT, &event)) {
3096  ast_log(LOG_ERROR, "SS7: Error in exception retrieval on span %d/%d!\n",
3097  linkset->span, which);
3098  return;
3099  }
3100  switch (event) {
3101  case DAHDI_EVENT_NONE:
3102  break;
3103  case DAHDI_EVENT_ALARM:
3104  ast_log(LOG_ERROR, "SS7 got event: %s(%d) on span %d/%d\n",
3105  event2str(event), event, linkset->span, which);
3106  sig_ss7_link_alarm(linkset, which);
3107  break;
3108  case DAHDI_EVENT_NOALARM:
3109  ast_log(LOG_ERROR, "SS7 got event: %s(%d) on span %d/%d\n",
3110  event2str(event), event, linkset->span, which);
3111  sig_ss7_link_noalarm(linkset, which);
3112  break;
3113  default:
3114  ast_log(LOG_NOTICE, "SS7 got event: %s(%d) on span %d/%d\n",
3115  event2str(event), event, linkset->span, which);
3116  break;
3117  }
3118 }
3119 #endif /* defined(HAVE_SS7) */
3120 
3121 #if defined(HAVE_SS7)
3122 static void my_ss7_set_loopback(void *pvt, int enable)
3123 {
3124  struct dahdi_pvt *p = pvt;
3125 
3126  if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_LOOPBACK, &enable)) {
3127  ast_log(LOG_WARNING, "Unable to set loopback on channel %d: %s\n", p->channel,
3128  strerror(errno));
3129  }
3130 }
3131 #endif /* defined(HAVE_SS7) */
3132 
3133 #if defined(HAVE_SS7)
3134 /*!
3135  * \internal
3136  * \brief Find the linkset to which SS7 belongs.
3137  * \since 11.0
3138  *
3139  * \param ss7 structure to match on.
3140  *
3141  * \retval linkset if found.
3142  * \retval NULL if not found.
3143  */
3144 static struct sig_ss7_linkset *my_ss7_find_linkset(struct ss7 *ss7)
3145 {
3146  int idx;
3147 
3148  if (!ss7) {
3149  return NULL;
3150  }
3151 
3152  for (idx = 0; idx < NUM_SPANS; ++idx) {
3153  if (linksets[idx].ss7.ss7 == ss7) {
3154  return &linksets[idx].ss7;
3155  }
3156  }
3157  return NULL;
3158 }
3159 #endif /* defined(HAVE_SS7) */
3160 
3161 #if defined(HAVE_SS7)
3162 /*!
3163  * \internal
3164  * \brief Create a new asterisk channel structure for SS7.
3165  * \since 1.8
3166  *
3167  * \param pvt Private channel structure.
3168  * \param state Initial state of new channel.
3169  * \param law Combanding law to use.
3170  * \param exten Dialplan extension for incoming call.
3171  * \param requestor Channel requesting this new channel.
3172  *
3173  * \retval ast_channel on success.
3174  * \retval NULL on error.
3175  */
3176 static struct ast_channel *my_new_ss7_ast_channel(void *pvt, int state, enum sig_ss7_law law, char *exten, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor)
3177 {
3178  struct dahdi_pvt *p = pvt;
3179  int audio;
3180  int newlaw;
3181  ast_callid callid = 0;
3182  int callid_created = ast_callid_threadstorage_auto(&callid);
3183 
3184  /* Set to audio mode at this point */
3185  audio = 1;
3186  if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &audio) == -1)
3187  ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n",
3188  p->channel, audio, strerror(errno));
3189 
3190  if (law != SIG_SS7_DEFLAW) {
3191  dahdi_setlaw(p->subs[SUB_REAL].dfd,
3192  (law == SIG_SS7_ULAW) ? DAHDI_LAW_MULAW : DAHDI_LAW_ALAW);
3193  }
3194 
3195  ast_copy_string(p->exten, exten, sizeof(p->exten));
3196 
3197  newlaw = -1;
3198  switch (law) {
3199  case SIG_SS7_DEFLAW:
3200  newlaw = 0;
3201  break;
3202  case SIG_SS7_ALAW:
3203  newlaw = DAHDI_LAW_ALAW;
3204  break;
3205  case SIG_SS7_ULAW:
3206  newlaw = DAHDI_LAW_MULAW;
3207  break;
3208  }
3209  return dahdi_new_callid_clean(p, state, 0, SUB_REAL, newlaw, assignedids, requestor, callid, callid_created);
3210 }
3211 #endif /* defined(HAVE_SS7) */
3212 
3213 #if defined(HAVE_SS7)
3214 static int sig_ss7_tone_to_dahditone(enum sig_ss7_tone tone)
3215 {
3216  switch (tone) {
3217  case SIG_SS7_TONE_RINGTONE:
3218  return DAHDI_TONE_RINGTONE;
3219  case SIG_SS7_TONE_STUTTER:
3220  return DAHDI_TONE_STUTTER;
3222  return DAHDI_TONE_CONGESTION;
3223  case SIG_SS7_TONE_DIALTONE:
3224  return DAHDI_TONE_DIALTONE;
3226  return DAHDI_TONE_DIALRECALL;
3227  case SIG_SS7_TONE_INFO:
3228  return DAHDI_TONE_INFO;
3229  case SIG_SS7_TONE_BUSY:
3230  return DAHDI_TONE_BUSY;
3231  default:
3232  return -1;
3233  }
3234 }
3235 #endif /* defined(HAVE_SS7) */
3236 
3237 #if defined(HAVE_SS7)
3238 static int my_ss7_play_tone(void *pvt, enum sig_ss7_tone tone)
3239 {
3240  struct dahdi_pvt *p = pvt;
3241 
3242  return tone_zone_play_tone(p->subs[SUB_REAL].dfd, sig_ss7_tone_to_dahditone(tone));
3243 }
3244 #endif /* defined(HAVE_SS7) */
3245 
3246 #if defined(HAVE_SS7)
3247 struct sig_ss7_callback sig_ss7_callbacks =
3248 {
3250  .unlock_private = my_unlock_private,
3251  .deadlock_avoidance_private = my_deadlock_avoidance_private,
3252 
3253  .set_echocanceller = my_set_echocanceller,
3254  .set_loopback = my_ss7_set_loopback,
3255 
3256  .new_ast_channel = my_new_ss7_ast_channel,
3257  .play_tone = my_ss7_play_tone,
3258 
3259  .handle_link_exception = my_handle_link_exception,
3260  .set_alarm = my_set_alarm,
3261  .set_dialing = my_set_dialing,
3262  .set_outgoing = my_set_outgoing,
3263  .set_digital = my_set_digital,
3264  .set_inservice = my_set_inservice,
3265  .set_locallyblocked = my_set_locallyblocked,
3266  .set_remotelyblocked = my_set_remotelyblocked,
3267  .set_callerid = my_set_callerid,
3268  .set_dnid = my_set_dnid,
3269  .open_media = my_pri_ss7_open_media,
3270  .find_linkset = my_ss7_find_linkset,
3271 };
3272 #endif /* defined(HAVE_SS7) */
3273 
3274 /*!
3275  * \brief Send MWI state change
3276  *
3277  * \param mailbox This is the mailbox associated with the FXO line that the
3278  * MWI state has changed on.
3279  * \param thereornot This argument should simply be set to 1 or 0, to indicate
3280  * whether there are messages waiting or not.
3281  *
3282  * \return nothing
3283  *
3284  * This function does two things:
3285  *
3286  * 1) It generates an internal Asterisk event notifying any other module that
3287  * cares about MWI that the state of a mailbox has changed.
3288  *
3289  * 2) It runs the script specified by the mwimonitornotify option to allow
3290  * some custom handling of the state change.
3291  */
3292 static void notify_message(char *mailbox, int thereornot)
3293 {
3294  char s[sizeof(mwimonitornotify) + 80];
3295 
3296  if (ast_strlen_zero(mailbox)) {
3297  return;
3298  }
3299 
3300  ast_publish_mwi_state(mailbox, NULL, thereornot, thereornot);
3302  snprintf(s, sizeof(s), "%s %s %d", mwimonitornotify, mailbox, thereornot);
3303  ast_safe_system(s);
3304  }
3305 }
3306 
3307 static void my_handle_notify_message(struct ast_channel *chan, void *pvt, int cid_flags, int neon_mwievent)
3308 {
3309  struct dahdi_pvt *p = pvt;
3310 
3311  if (neon_mwievent > -1 && !p->mwimonitor_neon)
3312  return;
3313 
3314  if (neon_mwievent == ANALOG_EVENT_NEONMWI_ACTIVE || cid_flags & CID_MSGWAITING) {
3315  ast_log(LOG_NOTICE, "MWI: Channel %d message waiting, mailbox %s\n", p->channel, p->mailbox);
3316  notify_message(p->mailbox, 1);
3317  } else if (neon_mwievent == ANALOG_EVENT_NEONMWI_INACTIVE || cid_flags & CID_NOMSGWAITING) {
3318  ast_log(LOG_NOTICE, "MWI: Channel %d no message waiting, mailbox %s\n", p->channel, p->mailbox);
3319  notify_message(p->mailbox, 0);
3320  }
3321  /* If the CID had Message waiting payload, assume that this for MWI only and hangup the call */
3322  /* If generated using Ring Pulse Alert, then ring has been answered as a call and needs to be hungup */
3323  if (neon_mwievent == -1 && p->mwimonitor_rpas) {
3324  ast_hangup(chan);
3325  return;
3326  }
3327 }
3328 
3329 static int my_have_progressdetect(void *pvt)
3330 {
3331  struct dahdi_pvt *p = pvt;
3332 
3334  && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
3335  return 1;
3336  } else {
3337  /* Don't have progress detection. */
3338  return 0;
3339  }
3340 }
3341 
3342 #define gen_pvt_field_callback(type, field) \
3343  static type my_get_##field(void *pvt) \
3344  { \
3345  struct dahdi_pvt *p = pvt; \
3346  return p->field; \
3347  }
3348 
3352 
3353 #undef gen_pvt_field_callback
3354 
3356 {
3358  .get_event = my_get_event,
3359  .wait_event = my_wait_event,
3360  .is_off_hook = my_is_off_hook,
3361  .set_echocanceller = my_set_echocanceller,
3362  .ring = my_ring,
3363  .flash = my_flash,
3364  .off_hook = my_off_hook,
3365  .dial_digits = my_dial_digits,
3366  .train_echocanceller = my_train_echocanceller,
3367  .on_hook = my_on_hook,
3368  .is_dialing = my_is_dialing,
3369  .allocate_sub = my_allocate_sub,
3370  .unallocate_sub = my_unallocate_sub,
3371  .swap_subs = my_swap_subchannels,
3372  .has_voicemail = my_has_voicemail,
3373  .check_for_conference = my_check_for_conference,
3374  .conf_add = my_conf_add,
3375  .conf_del = my_conf_del,
3376  .complete_conference_update = my_complete_conference_update,
3377  .start = my_start,
3378  .all_subchannels_hungup = my_all_subchannels_hungup,
3379  .lock_private = my_lock_private,
3380  .unlock_private = my_unlock_private,
3381  .deadlock_avoidance_private = my_deadlock_avoidance_private,
3382  .handle_dtmf = my_handle_dtmf,
3383  .wink = my_wink,
3384  .new_ast_channel = my_new_analog_ast_channel,
3385  .dsp_set_digitmode = my_dsp_set_digitmode,
3386  .dsp_reset_and_flush_digits = my_dsp_reset_and_flush_digits,
3387  .send_callerid = my_send_callerid,
3388  .callwait = my_callwait,
3389  .stop_callwait = my_stop_callwait,
3390  .get_callerid = my_get_callerid,
3391  .start_cid_detect = my_start_cid_detect,
3392  .stop_cid_detect = my_stop_cid_detect,
3393  .handle_notify_message = my_handle_notify_message,
3394  .increase_ss_count = my_increase_ss_count,
3395  .decrease_ss_count = my_decrease_ss_count,
3396  .distinctive_ring = my_distinctive_ring,
3397  .set_linear_mode = my_set_linear_mode,
3398  .set_inthreeway = my_set_inthreeway,
3399  .get_and_handle_alarms = my_get_and_handle_alarms,
3400  .get_sigpvt_bridged_channel = my_get_sigpvt_bridged_channel,
3401  .get_sub_fd = my_get_sub_fd,
3402  .set_cadence = my_set_cadence,
3403  .set_alarm = my_set_alarm,
3404  .set_dialing = my_set_dialing,
3405  .set_outgoing = my_set_outgoing,
3406  .set_ringtimeout = my_set_ringtimeout,
3407  .set_waitingfordt = my_set_waitingfordt,
3408  .check_waitingfordt = my_check_waitingfordt,
3409  .set_confirmanswer = my_set_confirmanswer,
3410  .check_confirmanswer = my_check_confirmanswer,
3411  .set_callwaiting = my_set_callwaiting,
3412  .cancel_cidspill = my_cancel_cidspill,
3413  .confmute = my_confmute,
3414  .set_pulsedial = my_set_pulsedial,
3415  .set_new_owner = my_set_new_owner,
3416  .get_orig_dialstring = my_get_orig_dialstring,
3417  .set_needringing = my_set_needringing,
3418  .set_polarity = my_set_polarity,
3419  .start_polarityswitch = my_start_polarityswitch,
3420  .answer_polarityswitch = my_answer_polarityswitch,
3421  .hangup_polarityswitch = my_hangup_polarityswitch,
3422  .have_progressdetect = my_have_progressdetect,
3423  .get_firstdigit_timeout = my_get_firstdigit_timeout,
3424  .get_matchdigit_timeout = my_get_matchdigit_timeout,
3425  .get_interdigit_timeout = my_get_interdigit_timeout,
3426 };
3427 
3428 /*! Round robin search locations. */
3429 static struct dahdi_pvt *round_robin[32];
3430 
3431 int _dahdi_get_index(struct ast_channel *ast, struct dahdi_pvt *p, int nullok, const char *fname, unsigned long line)
3432 {
3433  int res;
3434  if (p->subs[SUB_REAL].owner == ast)
3435  res = 0;
3436  else if (p->subs[SUB_CALLWAIT].owner == ast)
3437  res = 1;
3438  else if (p->subs[SUB_THREEWAY].owner == ast)
3439  res = 2;
3440  else {
3441  res = -1;
3442  if (!nullok)
3444  "Unable to get index for '%s' on channel %d (%s(), line %lu)\n",
3445  ast ? ast_channel_name(ast) : "", p->channel, fname, line);
3446  }
3447  return res;
3448 }
3449 
3450 /*!
3451  * \internal
3452  * \brief Obtain the specified subchannel owner lock if the owner exists.
3453  *
3454  * \param pvt Channel private struct.
3455  * \param sub_idx Subchannel owner to lock.
3456  *
3457  * \note Assumes the pvt->lock is already obtained.
3458  *
3459  * \note
3460  * Because deadlock avoidance may have been necessary, you need to confirm
3461  * the state of things before continuing.
3462  *
3463  * \return Nothing
3464  */
3465 static void dahdi_lock_sub_owner(struct dahdi_pvt *pvt, int sub_idx)
3466 {
3467  for (;;) {
3468  if (!pvt->subs[sub_idx].owner) {
3469  /* No subchannel owner pointer */
3470  break;
3471  }
3472  if (!ast_channel_trylock(pvt->subs[sub_idx].owner)) {
3473  /* Got subchannel owner lock */
3474  break;
3475  }
3476  /* We must unlock the private to avoid the possibility of a deadlock */
3477  DEADLOCK_AVOIDANCE(&pvt->lock);
3478  }
3479 }
3480 
3481 static void wakeup_sub(struct dahdi_pvt *p, int a)
3482 {
3483  dahdi_lock_sub_owner(p, a);
3484  if (p->subs[a].owner) {
3486  ast_channel_unlock(p->subs[a].owner);
3487  }
3488 }
3489 
3490 static void dahdi_queue_frame(struct dahdi_pvt *p, struct ast_frame *f)
3491 {
3492  for (;;) {
3493  if (p->owner) {
3494  if (ast_channel_trylock(p->owner)) {
3495  DEADLOCK_AVOIDANCE(&p->lock);
3496  } else {
3497  ast_queue_frame(p->owner, f);
3499  break;
3500  }
3501  } else
3502  break;
3503  }
3504 }
3505 
3507 {
3508  RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
3509  RAII_VAR(struct ast_str *, dahdi_chan, ast_str_create(32), ast_free);
3510  if (!dahdi_chan) {
3511  return;
3512  }
3513 
3514  ast_str_set(&dahdi_chan, 0, "%d", channel);
3515  ast_log(LOG_NOTICE, "Alarm cleared on channel DAHDI/%d\n", channel);
3516  body = ast_json_pack("{s: s}", "DAHDIChannel", ast_str_buffer(dahdi_chan));
3517  if (!body) {
3518  return;
3519  }
3520 
3521  ast_manager_publish_event("AlarmClear", EVENT_FLAG_SYSTEM, body);
3522 }
3523 
3525 {
3526  RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
3527 
3528  ast_log(LOG_NOTICE, "Alarm cleared on span %d\n", span);
3529  body = ast_json_pack("{s: i}", "Span", span);
3530  if (!body) {
3531  return;
3532  }
3533 
3534  ast_manager_publish_event("SpanAlarmClear", EVENT_FLAG_SYSTEM, body);
3535 }
3536 
3537 static void handle_clear_alarms(struct dahdi_pvt *p)
3538 {
3539 #if defined(HAVE_PRI)
3541  return;
3542  }
3543 #endif /* defined(HAVE_PRI) */
3544 
3547  }
3550  }
3551 }
3552 
3553 #ifdef HAVE_OPENR2
3554 static void mfcr2_queue_for_destruction(const struct dahdi_pvt *p)
3555 {
3556  const struct dahdi_mfcr2 *r2link = p->mfcr2;
3557  struct r2link_entry *cur;
3558  AST_LIST_LOCK(&r2links);
3559  AST_LIST_TRAVERSE_SAFE_BEGIN(&r2links, cur, list) {
3560  if (r2link == &cur->mfcr2) {
3561  ast_debug(3, "MFC/R2 channel %d queued for destruction\n", p->channel);
3562  AST_LIST_MOVE_CURRENT(&nodev_r2links, list);
3563  break;
3564  }
3565  }
3567  AST_LIST_UNLOCK(&r2links);
3568 }
3569 
3570 static int dahdi_r2_answer(struct dahdi_pvt *p)
3571 {
3572  int res = 0;
3573  /* openr2 1.1.0 and older does not even define OR2_LIB_INTERFACE
3574  * and does not has support for openr2_chan_answer_call_with_mode
3575  * */
3576 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
3577  const char *double_answer = pbx_builtin_getvar_helper(p->owner, "MFCR2_DOUBLE_ANSWER");
3578  int wants_double_answer = ast_true(double_answer) ? 1 : 0;
3579  if (!double_answer) {
3580  /* this still can result in double answer if the channel context
3581  * was configured that way */
3582  res = openr2_chan_answer_call(p->r2chan);
3583  } else if (wants_double_answer) {
3584  res = openr2_chan_answer_call_with_mode(p->r2chan, OR2_ANSWER_DOUBLE);
3585  } else {
3586  res = openr2_chan_answer_call_with_mode(p->r2chan, OR2_ANSWER_SIMPLE);
3587  }
3588 #else
3589  res = openr2_chan_answer_call(p->r2chan);
3590 #endif
3591  return res;
3592 }
3593 
3594 
3595 
3596 /* should be called with the ast_channel locked */
3597 static openr2_calling_party_category_t dahdi_r2_get_channel_category(struct ast_channel *c)
3598 {
3599  openr2_calling_party_category_t cat;
3600  const char *catstr = pbx_builtin_getvar_helper(c, "MFCR2_CATEGORY");
3601  struct dahdi_pvt *p = ast_channel_tech_pvt(c);
3602  if (ast_strlen_zero(catstr)) {
3603  ast_debug(1, "No MFC/R2 category specified for chan %s, using default %s\n",
3604  ast_channel_name(c), openr2_proto_get_category_string(p->mfcr2_category));
3605  return p->mfcr2_category;
3606  }
3607  if ((cat = openr2_proto_get_category(catstr)) == OR2_CALLING_PARTY_CATEGORY_UNKNOWN) {
3608  ast_log(LOG_WARNING, "Invalid category specified '%s' for chan %s, using default %s\n",
3609  catstr, ast_channel_name(c), openr2_proto_get_category_string(p->mfcr2_category));
3610  return p->mfcr2_category;
3611  }
3612  ast_debug(1, "Using category %s\n", catstr);
3613  return cat;
3614 }
3615 
3616 static void dahdi_r2_on_call_init(openr2_chan_t *r2chan)
3617 {
3618  struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
3619  ast_mutex_lock(&p->lock);
3620  if (p->mfcr2call) {
3621  ast_mutex_unlock(&p->lock);
3622  /* TODO: This can happen when some other thread just finished dahdi_request requesting this very same
3623  interface but has not yet seized the line (dahdi_call), and the far end wins and seize the line,
3624  can we avoid this somehow?, at this point when dahdi_call send the seize, it is likely that since
3625  the other end will see our seize as a forced release and drop the call, we will see an invalid
3626  pattern that will be seen and treated as protocol error. */
3627  ast_log(LOG_ERROR, "Collision of calls on chan %d detected!.\n", openr2_chan_get_number(r2chan));
3628  return;
3629  }
3630  p->mfcr2call = 1;
3631  /* better safe than sorry ... */
3632  p->cid_name[0] = '\0';
3633  p->cid_num[0] = '\0';
3634  p->cid_subaddr[0] = '\0';
3635  p->rdnis[0] = '\0';
3636  p->exten[0] = '\0';
3637  p->mfcr2_ani_index = '\0';
3638  p->mfcr2_dnis_index = '\0';
3639  p->mfcr2_dnis_matched = 0;
3640  p->mfcr2_answer_pending = 0;
3641  p->mfcr2_call_accepted = 0;
3642  ast_mutex_unlock(&p->lock);
3643  ast_verbose("New MFC/R2 call detected on chan %d.\n", openr2_chan_get_number(r2chan));
3644 }
3645 
3646 static void dahdi_r2_on_hardware_alarm(openr2_chan_t *r2chan, int alarm)
3647 {
3648  int res;
3649  struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
3650  ast_mutex_lock(&p->lock);
3651  p->inalarm = alarm ? 1 : 0;
3652  if (p->inalarm) {
3653  res = get_alarms(p);
3654  if (res == DAHDI_ALARM_NOTOPEN) {
3655  mfcr2_queue_for_destruction(p);
3656  }
3657  handle_alarms(p, res);
3658  } else {
3660  }
3661  ast_mutex_unlock(&p->lock);
3662 }
3663 
3664 static void dahdi_r2_on_os_error(openr2_chan_t *r2chan, int errorcode)
3665 {
3666  struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
3667 
3668  ast_log(LOG_ERROR, "OS error on chan %d: %s\n", openr2_chan_get_number(r2chan), strerror(errorcode));
3669  ast_mutex_lock(&p->lock);
3670  /* Disconnected? */
3671  if (errorcode == ENODEV) {
3672  struct dahdi_mfcr2 *r2link = p->mfcr2;
3673  p->mfcr2call = 0;
3674  if (r2link) {
3675  r2link->nodev = 1;
3676  }
3677  }
3678  ast_mutex_unlock(&p->lock);
3679 }
3680 
3681 static void dahdi_r2_on_protocol_error(openr2_chan_t *r2chan, openr2_protocol_error_t reason)
3682 {
3683  struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
3684  ast_log(LOG_ERROR, "MFC/R2 protocol error on chan %d: %s\n", openr2_chan_get_number(r2chan), openr2_proto_get_error(reason));
3685  if (p->owner) {
3688  }
3689  ast_mutex_lock(&p->lock);
3690  p->mfcr2call = 0;
3691  ast_mutex_unlock(&p->lock);
3692 }
3693 
3694 static void dahdi_r2_disconnect_call(struct dahdi_pvt *p, openr2_call_disconnect_cause_t cause)
3695 {
3696  if (openr2_chan_disconnect_call(p->r2chan, cause)) {
3697  ast_log(LOG_NOTICE, "Bad! failed to disconnect call on channel %d with reason %s, hope for the best!\n",
3698  p->channel, openr2_proto_get_disconnect_string(cause));
3699  /* force the chan to idle and release the call flag now since we will not see a clean on_call_end */
3700  openr2_chan_set_idle(p->r2chan);
3701  ast_mutex_lock(&p->lock);
3702  p->mfcr2call = 0;
3703  ast_mutex_unlock(&p->lock);
3704  }
3705 }
3706 
3707 static void dahdi_r2_on_call_offered(openr2_chan_t *r2chan, const char *ani, const char *dnis, openr2_calling_party_category_t category)
3708 {
3709  struct dahdi_pvt *p;
3710  struct ast_channel *c;
3711  ast_callid callid = 0;
3712  int callid_created = ast_callid_threadstorage_auto(&callid);
3713  ast_verbose("MFC/R2 call offered on chan %d. ANI = %s, DNIS = %s, Category = %s\n",
3714  openr2_chan_get_number(r2chan), ani ? ani : "(restricted)", dnis,
3715  openr2_proto_get_category_string(category));
3716  p = openr2_chan_get_client_data(r2chan);
3717  /* if collect calls are not allowed and this is a collect call, reject it! */
3718  if (!p->mfcr2_allow_collect_calls && category == OR2_CALLING_PARTY_CATEGORY_COLLECT_CALL) {
3719  ast_log(LOG_NOTICE, "Rejecting MFC/R2 collect call\n");
3720  dahdi_r2_disconnect_call(p, OR2_CAUSE_COLLECT_CALL_REJECTED);
3721  goto dahdi_r2_on_call_offered_cleanup;
3722  }
3723  ast_mutex_lock(&p->lock);
3724  p->mfcr2_recvd_category = category;
3725  /* if we're not supposed to use CID, clear whatever we have */
3726  if (!p->use_callerid) {
3727  ast_debug(1, "No CID allowed in configuration, CID is being cleared!\n");
3728  p->cid_num[0] = 0;
3729  p->cid_name[0] = 0;
3730  }
3731  /* if we're supposed to answer immediately, clear DNIS and set 's' exten */
3732  if (p->immediate || !openr2_context_get_max_dnis(openr2_chan_get_context(r2chan))) {
3733  ast_debug(1, "Setting exten => s because of immediate or 0 DNIS configured\n");
3734  p->exten[0] = 's';
3735  p->exten[1] = 0;
3736  }
3737  ast_mutex_unlock(&p->lock);
3738  if (!ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
3739  ast_log(LOG_NOTICE, "MFC/R2 call on channel %d requested non-existent extension '%s' in context '%s'. Rejecting call.\n",
3740  p->channel, p->exten, p->context);
3741  dahdi_r2_disconnect_call(p, OR2_CAUSE_UNALLOCATED_NUMBER);
3742  goto dahdi_r2_on_call_offered_cleanup;
3743  }
3744  if (!p->mfcr2_accept_on_offer) {
3745  /* The user wants us to start the PBX thread right away without accepting the call first */
3746  c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, NULL, NULL, callid);
3747  if (c) {
3748  /* Done here, don't disable reading now since we still need to generate MF tones to accept
3749  the call or reject it and detect the tone off condition of the other end, all of this
3750  will be done in the PBX thread now */
3751  goto dahdi_r2_on_call_offered_cleanup;
3752  }
3753  ast_log(LOG_WARNING, "Unable to create PBX channel in DAHDI channel %d\n", p->channel);
3754  dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER);
3755  } else if (p->mfcr2_charge_calls) {
3756  ast_debug(1, "Accepting MFC/R2 call with charge on chan %d\n", p->channel);
3757  openr2_chan_accept_call(r2chan, OR2_CALL_WITH_CHARGE);
3758  } else {
3759  ast_debug(1, "Accepting MFC/R2 call with no charge on chan %d\n", p->channel);
3760  openr2_chan_accept_call(r2chan, OR2_CALL_NO_CHARGE);
3761  }
3762 
3763 dahdi_r2_on_call_offered_cleanup:
3764  ast_callid_threadstorage_auto_clean(callid, callid_created);
3765 }
3766 
3767 static void dahdi_r2_on_call_end(openr2_chan_t *r2chan)
3768 {
3769  struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
3770  ast_verbose("MFC/R2 call end on channel %d\n", p->channel);
3771  ast_mutex_lock(&p->lock);
3772  p->mfcr2call = 0;
3773  ast_mutex_unlock(&p->lock);
3774 }
3775 
3776 static void dahdi_r2_on_call_accepted(openr2_chan_t *r2chan, openr2_call_mode_t mode)
3777 {
3778  struct dahdi_pvt *p = NULL;
3779  struct ast_channel *c = NULL;
3780  ast_callid callid = 0;
3781  int callid_created = ast_callid_threadstorage_auto(&callid);
3782  p = openr2_chan_get_client_data(r2chan);
3783  dahdi_ec_enable(p);
3784  p->mfcr2_call_accepted = 1;
3785  /* if it's an incoming call ... */
3786  if (OR2_DIR_BACKWARD == openr2_chan_get_direction(r2chan)) {
3787  ast_verbose("MFC/R2 call has been accepted on backward channel %d\n", openr2_chan_get_number(r2chan));
3788  /* If accept on offer is not set, it means at this point the PBX thread is already
3789  launched (was launched in the 'on call offered' handler) and therefore this callback
3790  is being executed already in the PBX thread rather than the monitor thread, don't launch
3791  any other thread, just disable the openr2 reading and answer the call if needed */
3792  if (!p->mfcr2_accept_on_offer) {
3793  openr2_chan_disable_read(r2chan);
3794  if (p->mfcr2_answer_pending) {
3795  ast_debug(1, "Answering MFC/R2 call after accepting it on chan %d\n", openr2_chan_get_number(r2chan));
3796  dahdi_r2_answer(p);
3797  }
3798  goto dahdi_r2_on_call_accepted_cleanup;
3799  }
3800  c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, NULL, NULL, callid);
3801  if (c) {
3802  /* chan_dahdi will take care of reading from now on in the PBX thread, tell the
3803  library to forget about it */
3804  openr2_chan_disable_read(r2chan);
3805  goto dahdi_r2_on_call_accepted_cleanup;
3806  }
3807  ast_log(LOG_WARNING, "Unable to create PBX channel in DAHDI channel %d\n", p->channel);
3808  /* failed to create the channel, bail out and report it as an out of order line */
3809  dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER);
3810  goto dahdi_r2_on_call_accepted_cleanup;
3811  }
3812  /* this is an outgoing call, no need to launch the PBX thread, most likely we're in one already */
3813  ast_verbose("MFC/R2 call has been accepted on forward channel %d\n", p->channel);
3814  p->subs[SUB_REAL].needringing = 1;
3815  p->dialing = 0;
3816  /* chan_dahdi will take care of reading from now on in the PBX thread, tell the library to forget about it */
3817  openr2_chan_disable_read(r2chan);
3818 
3819 dahdi_r2_on_call_accepted_cleanup:
3820  ast_callid_threadstorage_auto_clean(callid, callid_created);
3821 }
3822 
3823 static void dahdi_r2_on_call_answered(openr2_chan_t *r2chan)
3824 {
3825  struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
3826  ast_verbose("MFC/R2 call has been answered on channel %d\n", openr2_chan_get_number(r2chan));
3827  p->subs[SUB_REAL].needanswer = 1;
3828 }
3829 
3830 static void dahdi_r2_on_call_read(openr2_chan_t *r2chan, const unsigned char *buf, int buflen)
3831 {
3832  /*ast_debug(1, "Read data from dahdi channel %d\n", openr2_chan_get_number(r2chan));*/
3833 }
3834 
3835 static int dahdi_r2_cause_to_ast_cause(openr2_call_disconnect_cause_t cause)
3836 {
3837  switch (cause) {
3838  case OR2_CAUSE_BUSY_NUMBER:
3839  return AST_CAUSE_BUSY;
3840  case OR2_CAUSE_NETWORK_CONGESTION:
3841  return AST_CAUSE_CONGESTION;
3842  case OR2_CAUSE_OUT_OF_ORDER:
3844  case OR2_CAUSE_UNALLOCATED_NUMBER:
3845  return AST_CAUSE_UNREGISTERED;
3846  case OR2_CAUSE_NO_ANSWER:
3847  return AST_CAUSE_NO_ANSWER;
3848  case OR2_CAUSE_NORMAL_CLEARING:
3850  case OR2_CAUSE_UNSPECIFIED:
3851  default:
3852  return AST_CAUSE_NOTDEFINED;
3853  }
3854 }
3855 
3856 static void dahdi_r2_on_call_disconnect(openr2_chan_t *r2chan, openr2_call_disconnect_cause_t cause)
3857 {
3858  struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
3859  char cause_str[50];
3860  struct ast_control_pvt_cause_code *cause_code;
3861  int datalen = sizeof(*cause_code);
3862 
3863  ast_verbose("MFC/R2 call disconnected on channel %d\n", openr2_chan_get_number(r2chan));
3864  ast_mutex_lock(&p->lock);
3865  if (!p->owner) {
3866  ast_mutex_unlock(&p->lock);
3867  /* no owner, therefore we can't use dahdi_hangup to disconnect, do it right now */
3868  dahdi_r2_disconnect_call(p, OR2_CAUSE_NORMAL_CLEARING);
3869  return;
3870  }
3871 
3872  snprintf(cause_str, sizeof(cause_str), "R2 DISCONNECT (%s)", openr2_proto_get_disconnect_string(cause));
3873  datalen += strlen(cause_str);
3874  cause_code = ast_alloca(datalen);
3875  memset(cause_code, 0, datalen);
3876  cause_code->ast_cause = dahdi_r2_cause_to_ast_cause(cause);
3878  ast_copy_string(cause_code->code, cause_str, datalen + 1 - sizeof(*cause_code));
3879  ast_queue_control_data(p->owner, AST_CONTROL_PVT_CAUSE_CODE, cause_code, datalen);
3880  ast_channel_hangupcause_hash_set(p->owner, cause_code, datalen);
3881  ast_channel_hangupcause_set(p->owner, cause_code->ast_cause);
3882 
3883  /* when we have an owner we don't call dahdi_r2_disconnect_call here, that will
3884  be done in dahdi_hangup */
3885  if (ast_channel_state(p->owner) == AST_STATE_UP) {
3887  ast_mutex_unlock(&p->lock);
3888  } else if (openr2_chan_get_direction(r2chan) == OR2_DIR_FORWARD) {
3889  /* being the forward side we must report what happened to the call to whoever requested it */
3890  switch (cause) {
3891  case OR2_CAUSE_BUSY_NUMBER:
3892  p->subs[SUB_REAL].needbusy = 1;
3893  break;
3894  case OR2_CAUSE_NETWORK_CONGESTION:
3895  case OR2_CAUSE_OUT_OF_ORDER:
3896  case OR2_CAUSE_UNALLOCATED_NUMBER:
3897  case OR2_CAUSE_NO_ANSWER:
3898  case OR2_CAUSE_UNSPECIFIED:
3899  case OR2_CAUSE_NORMAL_CLEARING:
3900  p->subs[SUB_REAL].needcongestion = 1;
3901  break;
3902  default:
3904  }
3905  ast_mutex_unlock(&p->lock);
3906  } else {
3907  ast_mutex_unlock(&p->lock);
3908  /* being the backward side and not UP yet, we only need to request hangup */
3909  /* TODO: what about doing this same thing when were AST_STATE_UP? */
3910  ast_queue_hangup_with_cause(p->owner, dahdi_r2_cause_to_ast_cause(cause));
3911  }
3912 }
3913 
3914 static void dahdi_r2_write_log(openr2_log_level_t level, char *logmessage)
3915 {
3916  switch (level) {
3917  case OR2_LOG_NOTICE:
3918  ast_verbose("%s", logmessage);
3919  break;
3920  case OR2_LOG_WARNING:
3921  ast_log(LOG_WARNING, "%s", logmessage);
3922  break;
3923  case OR2_LOG_ERROR:
3924  ast_log(LOG_ERROR, "%s", logmessage);
3925  break;
3926  case OR2_LOG_STACK_TRACE:
3927  case OR2_LOG_MF_TRACE:
3928  case OR2_LOG_CAS_TRACE:
3929  case OR2_LOG_DEBUG:
3930  case OR2_LOG_EX_DEBUG:
3931  ast_debug(1, "%s", logmessage);
3932  break;
3933  default:
3934  ast_log(LOG_WARNING, "We should handle logging level %d here.\n", level);
3935  ast_debug(1, "%s", logmessage);
3936  break;
3937  }
3938 }
3939 
3940 static void dahdi_r2_on_line_blocked(openr2_chan_t *r2chan)
3941 {
3942  struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
3943  ast_mutex_lock(&p->lock);
3944  p->remotelyblocked = 1;
3945  ast_mutex_unlock(&p->lock);
3946  ast_log(LOG_NOTICE, "Far end blocked on chan %d\n", openr2_chan_get_number(r2chan));
3947 }
3948 
3949 static void dahdi_r2_on_line_idle(openr2_chan_t *r2chan)
3950 {
3951  struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
3952  ast_mutex_lock(&p->lock);
3953  p->remotelyblocked = 0;
3954  ast_mutex_unlock(&p->lock);
3955  ast_log(LOG_NOTICE, "Far end unblocked on chan %d\n", openr2_chan_get_number(r2chan));
3956 }
3957 
3958 static void dahdi_r2_on_context_log(openr2_context_t *r2context, openr2_log_level_t level, const char *fmt, va_list ap)
3959  __attribute__((format (printf, 3, 0)));
3960 static void dahdi_r2_on_context_log(openr2_context_t *r2context, openr2_log_level_t level, const char *fmt, va_list ap)
3961 {
3962 #define CONTEXT_TAG "Context - "
3963  char logmsg[256];
3964  char completemsg[sizeof(logmsg) + sizeof(CONTEXT_TAG) - 1];
3965  vsnprintf(logmsg, sizeof(logmsg), fmt, ap);
3966  snprintf(completemsg, sizeof(completemsg), CONTEXT_TAG "%s", logmsg);
3967  dahdi_r2_write_log(level, completemsg);
3968 #undef CONTEXT_TAG
3969 }
3970 
3971 static void dahdi_r2_on_chan_log(openr2_chan_t *r2chan, openr2_log_level_t level, const char *fmt, va_list ap)
3972  __attribute__((format (printf, 3, 0)));
3973 static void dahdi_r2_on_chan_log(openr2_chan_t *r2chan, openr2_log_level_t level, const char *fmt, va_list ap)
3974 {
3975 #define CHAN_TAG "Chan "
3976  char logmsg[256];
3977  char completemsg[sizeof(logmsg) + sizeof(CHAN_TAG) - 1];
3978  vsnprintf(logmsg, sizeof(logmsg), fmt, ap);
3979  snprintf(completemsg, sizeof(completemsg), CHAN_TAG "%d - %s", openr2_chan_get_number(r2chan), logmsg);
3980  dahdi_r2_write_log(level, completemsg);
3981 }
3982 
3983 static int dahdi_r2_on_dnis_digit_received(openr2_chan_t *r2chan, char digit)
3984 {
3985  struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
3986  /* if 'immediate' is set, let's stop requesting DNIS */
3987  if (p->immediate) {
3988  return 0;
3989  }
3990  p->exten[p->mfcr2_dnis_index] = digit;
3991  p->rdnis[p->mfcr2_dnis_index] = digit;
3992  p->mfcr2_dnis_index++;
3993  p->exten[p->mfcr2_dnis_index] = 0;
3994  p->rdnis[p->mfcr2_dnis_index] = 0;
3995  /* if the DNIS is a match and cannot match more, stop requesting DNIS */
3996  if ((p->mfcr2_dnis_matched ||
3997  (ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num) && (p->mfcr2_dnis_matched = 1))) &&
3998  !ast_matchmore_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
3999  return 0;
4000  }
4001  /* otherwise keep going */
4002  return 1;
4003 }
4004 
4005 static void dahdi_r2_on_ani_digit_received(openr2_chan_t *r2chan, char digit)
4006 {
4007  struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
4008  p->cid_num[p->mfcr2_ani_index] = digit;
4009  p->cid_name[p->mfcr2_ani_index] = digit;
4010  p->mfcr2_ani_index++;
4011  p->cid_num[p->mfcr2_ani_index] = 0;
4012  p->cid_name[p->mfcr2_ani_index] = 0;
4013 }
4014 
4015 static void dahdi_r2_on_billing_pulse_received(openr2_chan_t *r2chan)
4016 {
4017  ast_verbose("MFC/R2 billing pulse received on channel %d\n", openr2_chan_get_number(r2chan));
4018 }
4019 
4020 static openr2_event_interface_t dahdi_r2_event_iface = {
4021  .on_call_init = dahdi_r2_on_call_init,
4022  .on_call_offered = dahdi_r2_on_call_offered,
4023  .on_call_accepted = dahdi_r2_on_call_accepted,
4024  .on_call_answered = dahdi_r2_on_call_answered,
4025  .on_call_disconnect = dahdi_r2_on_call_disconnect,
4026  .on_call_end = dahdi_r2_on_call_end,
4027  .on_call_read = dahdi_r2_on_call_read,
4028  .on_hardware_alarm = dahdi_r2_on_hardware_alarm,
4029  .on_os_error = dahdi_r2_on_os_error,
4030  .on_protocol_error = dahdi_r2_on_protocol_error,
4031  .on_line_blocked = dahdi_r2_on_line_blocked,
4032  .on_line_idle = dahdi_r2_on_line_idle,
4033  /* cast seems to be needed to get rid of the annoying warning regarding format attribute */
4034  .on_context_log = (openr2_handle_context_logging_func)dahdi_r2_on_context_log,
4035  .on_dnis_digit_received = dahdi_r2_on_dnis_digit_received,
4036  .on_ani_digit_received = dahdi_r2_on_ani_digit_received,
4037  /* so far we do nothing with billing pulses */
4038  .on_billing_pulse_received = dahdi_r2_on_billing_pulse_received
4039 };
4040 
4041 static inline int16_t dahdi_r2_alaw_to_linear(uint8_t sample)
4042 {
4043  return AST_ALAW(sample);
4044 }
4045 
4046 static inline uint8_t dahdi_r2_linear_to_alaw(int sample)
4047 {
4048  return AST_LIN2A(sample);
4049 }
4050 
4051 static openr2_transcoder_interface_t dahdi_r2_transcode_iface = {
4052  dahdi_r2_alaw_to_linear,
4053  dahdi_r2_linear_to_alaw
4054 };
4055 
4056 #endif /* HAVE_OPENR2 */
4057 
4058 static void swap_subs(struct dahdi_pvt *p, int a, int b)
4059 {
4060  int tchan;
4061  int tinthreeway;
4062  struct ast_channel *towner;
4063 
4064  ast_debug(1, "Swapping %d and %d\n", a, b);
4065 
4066  tchan = p->subs[a].chan;
4067  towner = p->subs[a].owner;
4068  tinthreeway = p->subs[a].inthreeway;
4069 
4070  p->subs[a].chan = p->subs[b].chan;
4071  p->subs[a].owner = p->subs[b].owner;
4072  p->subs[a].inthreeway = p->subs[b].inthreeway;
4073 
4074  p->subs[b].chan = tchan;
4075  p->subs[b].owner = towner;
4076  p->subs[b].inthreeway = tinthreeway;
4077 
4078  if (p->subs[a].owner)
4079  ast_channel_set_fd(p->subs[a].owner, 0, p->subs[a].dfd);
4080  if (p->subs[b].owner)
4081  ast_channel_set_fd(p->subs[b].owner, 0, p->subs[b].dfd);
4082  wakeup_sub(p, a);
4083  wakeup_sub(p, b);
4084 }
4085 
4086 static int dahdi_open(char *fn)
4087 {
4088  int fd;
4089  int isnum;
4090  int chan = 0;
4091  int bs;
4092  int x;
4093  isnum = 1;
4094  for (x = 0; x < strlen(fn); x++) {
4095  if (!isdigit(fn[x])) {
4096  isnum = 0;
4097  break;
4098  }
4099  }
4100  if (isnum) {
4101  chan = atoi(fn);
4102  if (chan < 1) {
4103  ast_log(LOG_WARNING, "Invalid channel number '%s'\n", fn);
4104  return -1;
4105  }
4106  fn = "/dev/dahdi/channel";
4107  }
4108  fd = open(fn, O_RDWR | O_NONBLOCK);
4109  if (fd < 0) {
4110  ast_log(LOG_WARNING, "Unable to open '%s': %s\n", fn, strerror(errno));
4111  return -1;
4112  }
4113  if (chan) {
4114  if (ioctl(fd, DAHDI_SPECIFY, &chan)) {
4115  x = errno;
4116  close(fd);
4117  errno = x;
4118  ast_log(LOG_WARNING, "Unable to specify channel %d: %s\n", chan, strerror(errno));
4119  return -1;
4120  }
4121  }
4122  bs = READ_SIZE;
4123  if (ioctl(fd, DAHDI_SET_BLOCKSIZE, &bs) == -1) {
4124  ast_log(LOG_WARNING, "Unable to set blocksize '%d': %s\n", bs, strerror(errno));
4125  x = errno;
4126  close(fd);
4127  errno = x;
4128  return -1;
4129  }
4130  return fd;
4131 }
4132 
4133 static void dahdi_close(int fd)
4134 {
4135  if (fd > 0)
4136  close(fd);
4137 }
4138 
4139 static void dahdi_close_sub(struct dahdi_pvt *chan_pvt, int sub_num)
4140 {
4141  dahdi_close(chan_pvt->subs[sub_num].dfd);
4142  chan_pvt->subs[sub_num].dfd = -1;
4143 }
4144 
4145 #if defined(HAVE_PRI)
4146 static void dahdi_close_pri_fd(struct dahdi_pri *pri, int fd_num)
4147 {
4148  dahdi_close(pri->pri.fds[fd_num]);
4149  pri->pri.fds[fd_num] = -1;
4150 }
4151 #endif /* defined(HAVE_PRI) */
4152 
4153 #if defined(HAVE_SS7)
4154 static void dahdi_close_ss7_fd(struct dahdi_ss7 *ss7, int fd_num)
4155 {
4156  dahdi_close(ss7->ss7.fds[fd_num]);
4157  ss7->ss7.fds[fd_num] = -1;
4158 }
4159 #endif /* defined(HAVE_SS7) */
4160 
4161 static int dahdi_setlinear(int dfd, int linear)
4162 {
4163  return ioctl(dfd, DAHDI_SETLINEAR, &linear);
4164 }
4165 
4166 
4167 static int alloc_sub(struct dahdi_pvt *p, int x)
4168 {
4169  struct dahdi_bufferinfo bi;
4170  int res;
4171  if (p->subs[x].dfd >= 0) {
4172  ast_log(LOG_WARNING, "%s subchannel of %d already in use\n", subnames[x], p->channel);
4173  return -1;
4174  }
4175 
4176  p->subs[x].dfd = dahdi_open("/dev/dahdi/pseudo");
4177  if (p->subs[x].dfd <= -1) {
4178  ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno));
4179  return -1;
4180  }
4181 
4182  res = ioctl(p->subs[x].dfd, DAHDI_GET_BUFINFO, &bi);
4183  if (!res) {
4184  bi.txbufpolicy = p->buf_policy;
4185  bi.rxbufpolicy = p->buf_policy;
4186  bi.numbufs = p->buf_no;
4187  res = ioctl(p->subs[x].dfd, DAHDI_SET_BUFINFO, &bi);
4188  if (res < 0) {
4189  ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", x, strerror(errno));
4190  }
4191  } else
4192  ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", x, strerror(errno));
4193 
4194  if (ioctl(p->subs[x].dfd, DAHDI_CHANNO, &p->subs[x].chan) == 1) {
4195  ast_log(LOG_WARNING, "Unable to get channel number for pseudo channel on FD %d: %s\n", p->subs[x].dfd, strerror(errno));
4196  dahdi_close_sub(p, x);
4197  p->subs[x].dfd = -1;
4198  return -1;
4199  }
4200  ast_debug(1, "Allocated %s subchannel on FD %d channel %d\n", subnames[x], p->subs[x].dfd, p->subs[x].chan);
4201  return 0;
4202 }
4203 
4204 static int unalloc_sub(struct dahdi_pvt *p, int x)
4205 {
4206  if (!x) {
4207  ast_log(LOG_WARNING, "Trying to unalloc the real channel %d?!?\n", p->channel);
4208  return -1;
4209  }
4210  ast_debug(1, "Released sub %d of channel %d\n", x, p->channel);
4211  dahdi_close_sub(p, x);
4212  p->subs[x].linear = 0;
4213  p->subs[x].chan = 0;
4214  p->subs[x].owner = NULL;
4215  p->subs[x].inthreeway = 0;
4216  p->polarity = POLARITY_IDLE;
4217  memset(&p->subs[x].curconf, 0, sizeof(p->subs[x].curconf));
4218  return 0;
4219 }
4220 
4221 static int digit_to_dtmfindex(char digit)
4222 {
4223  if (isdigit(digit))
4224  return DAHDI_TONE_DTMF_BASE + (digit - '0');
4225  else if (digit >= 'A' && digit <= 'D')
4226  return DAHDI_TONE_DTMF_A + (digit - 'A');
4227  else if (digit >= 'a' && digit <= 'd')
4228  return DAHDI_TONE_DTMF_A + (digit - 'a');
4229  else if (digit == '*')
4230  return DAHDI_TONE_DTMF_s;
4231  else if (digit == '#')
4232  return DAHDI_TONE_DTMF_p;
4233  else
4234  return -1;
4235 }
4236 
4237 static int dahdi_digit_begin(struct ast_channel *chan, char digit)
4238 {
4239  struct dahdi_pvt *pvt;
4240  int idx;
4241  int dtmf;
4242  int res;
4243 
4244  pvt = ast_channel_tech_pvt(chan);
4245 
4246  ast_mutex_lock(&pvt->lock);
4247 
4248  idx = dahdi_get_index(chan, pvt, 0);
4249 
4250  if ((idx != SUB_REAL) || !pvt->owner)
4251  goto out;
4252 
4253 #ifdef HAVE_PRI
4254  switch (pvt->sig) {
4256  res = sig_pri_digit_begin(pvt->sig_pvt, chan, digit);
4257  if (!res)
4258  goto out;
4259  break;
4260  default:
4261  break;
4262  }
4263 #endif
4264  dtmf = digit_to_dtmfindex(digit);
4265  if (dtmf == -1) {
4266  /* Not a valid DTMF digit */
4267  goto out;
4268  }
4269 
4270  if (pvt->pulse || ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &dtmf)) {
4271  char dial_str[] = { 'T', digit, '\0' };
4272 
4273  res = dahdi_dial_str(pvt, DAHDI_DIAL_OP_APPEND, dial_str);
4274  if (!res) {
4275  pvt->dialing = 1;
4276  }
4277  } else {
4278  pvt->dialing = 1;
4279  pvt->begindigit = digit;
4280 
4281  /* Flush the write buffer in DAHDI to start sending the digit immediately. */
4282  dtmf = DAHDI_FLUSH_WRITE;
4283  res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_FLUSH, &dtmf);
4284  if (res) {
4285  ast_log(LOG_WARNING, "Unable to flush the DAHDI write buffer to send DTMF on channel %d: %s\n",
4286  pvt->channel, strerror(errno));
4287  }
4288 
4289  ast_debug(1, "Channel %s started VLDTMF digit '%c'\n",
4290  ast_channel_name(chan), digit);
4291  }
4292 
4293 out:
4294  ast_mutex_unlock(&pvt->lock);
4295 
4296  return 0;
4297 }
4298 
4299 static int dahdi_digit_end(struct ast_channel *chan, char digit, unsigned int duration)
4300 {
4301  struct dahdi_pvt *pvt;
4302  int res = 0;
4303  int idx;
4304  int x;
4305 
4306  pvt = ast_channel_tech_pvt(chan);
4307 
4308  ast_mutex_lock(&pvt->lock);
4309 
4310  idx = dahdi_get_index(chan, pvt, 0);
4311 
4312  if ((idx != SUB_REAL) || !pvt->owner || pvt->pulse)
4313  goto out;
4314 
4315 #ifdef HAVE_PRI
4316  /* This means that the digit was already sent via PRI signalling */
4317  if (dahdi_sig_pri_lib_handles(pvt->sig) && !pvt->begindigit) {
4318  goto out;
4319  }
4320 #endif
4321 
4322  if (pvt->begindigit) {
4323  x = -1;
4324  ast_debug(1, "Channel %s ending VLDTMF digit '%c'\n",
4325  ast_channel_name(chan), digit);
4326  res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &x);
4327  pvt->dialing = 0;
4328  pvt->begindigit = 0;
4329  }
4330 
4331 out:
4332  ast_mutex_unlock(&pvt->lock);
4333 
4334  return res;
4335 }
4336 
4337 static const char * const events[] = {
4338  "No event",
4339  "On hook",
4340  "Ring/Answered",
4341  "Wink/Flash",
4342  "Alarm",
4343  "No more alarm",
4344  "HDLC Abort",
4345  "HDLC Overrun",
4346  "HDLC Bad FCS",
4347  "Dial Complete",
4348  "Ringer On",
4349  "Ringer Off",
4350  "Hook Transition Complete",
4351  "Bits Changed",
4352  "Pulse Start",
4353  "Timer Expired",
4354  "Timer Ping",
4355  "Polarity Reversal",
4356  "Ring Begin",
4357 };
4358 
4359 static struct {
4360  int alarm;
4361  char *name;
4362 } alarms[] = {
4363  { DAHDI_ALARM_RED, "Red Alarm" },
4364  { DAHDI_ALARM_YELLOW, "Yellow Alarm" },
4365  { DAHDI_ALARM_BLUE, "Blue Alarm" },
4366  { DAHDI_ALARM_RECOVER, "Recovering" },
4367  { DAHDI_ALARM_LOOPBACK, "Loopback" },
4368  { DAHDI_ALARM_NOTOPEN, "Not Open" },
4369  { DAHDI_ALARM_NONE, "None" },
4370 };
4371 
4372 static char *alarm2str(int alm)
4373 {
4374  int x;
4375  for (x = 0; x < ARRAY_LEN(alarms); x++) {
4376  if (alarms[x].alarm & alm)
4377  return alarms[x].name;
4378  }
4379  return alm ? "Unknown Alarm" : "No Alarm";
4380 }
4381 
4382 static const char *event2str(int event)
4383 {
4384  static char buf[256];
4385  if ((event > -1) && (event < (ARRAY_LEN(events))) )
4386  return events[event];
4387  sprintf(buf, "Event %d", event); /* safe */
4388  return buf;
4389 }
4390 
4391 static char *dahdi_sig2str(int sig)
4392 {
4393  static char buf[256];
4394  switch (sig) {
4395  case SIG_EM:
4396  return "E & M Immediate";
4397  case SIG_EMWINK:
4398  return "E & M Wink";
4399  case SIG_EM_E1:
4400  return "E & M E1";
4401  case SIG_FEATD:
4402  return "Feature Group D (DTMF)";
4403  case SIG_FEATDMF:
4404  return "Feature Group D (MF)";
4405  case SIG_FEATDMF_TA:
4406  return "Feature Groud D (MF) Tandem Access";
4407  case SIG_FEATB:
4408  return "Feature Group B (MF)";
4409  case SIG_E911:
4410  return "E911 (MF)";
4411  case SIG_FGC_CAMA:
4412  return "FGC/CAMA (Dialpulse)";
4413  case SIG_FGC_CAMAMF:
4414  return "FGC/CAMA (MF)";
4415  case SIG_FXSLS:
4416  return "FXS Loopstart";
4417  case SIG_FXSGS:
4418  return "FXS Groundstart";
4419  case SIG_FXSKS:
4420  return "FXS Kewlstart";
4421  case SIG_FXOLS:
4422  return "FXO Loopstart";
4423  case SIG_FXOGS:
4424  return "FXO Groundstart";
4425  case SIG_FXOKS:
4426  return "FXO Kewlstart";
4427  case SIG_PRI:
4428  return "ISDN PRI";
4429  case SIG_BRI:
4430  return "ISDN BRI Point to Point";
4431  case SIG_BRI_PTMP:
4432  return "ISDN BRI Point to MultiPoint";
4433  case SIG_SS7:
4434  return "SS7";
4435  case SIG_MFCR2:
4436  return "MFC/R2";
4437  case SIG_SF:
4438  return "SF (Tone) Immediate";
4439  case SIG_SFWINK:
4440  return "SF (Tone) Wink";
4441  case SIG_SF_FEATD:
4442  return "SF (Tone) with Feature Group D (DTMF)";
4443  case SIG_SF_FEATDMF:
4444  return "SF (Tone) with Feature Group D (MF)";
4445  case SIG_SF_FEATB:
4446  return "SF (Tone) with Feature Group B (MF)";
4447  case 0:
4448  return "Pseudo";
4449  default:
4450  snprintf(buf, sizeof(buf), "Unknown signalling %d", sig);
4451  return buf;
4452  }
4453 }
4454 
4455 #define sig2str dahdi_sig2str
4456 
4457 static int conf_add(struct dahdi_pvt *p, struct dahdi_subchannel *c, int idx, int slavechannel)
4458 {
4459  /* If the conference already exists, and we're already in it
4460  don't bother doing anything */
4461  struct dahdi_confinfo zi;
4462 
4463  memset(&zi, 0, sizeof(zi));
4464  zi.chan = 0;
4465 
4466  if (slavechannel > 0) {
4467  /* If we have only one slave, do a digital mon */
4468  zi.confmode = DAHDI_CONF_DIGITALMON;
4469  zi.confno = slavechannel;
4470  } else {
4471  if (!idx) {
4472  /* Real-side and pseudo-side both participate in conference */
4473  zi.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER |
4474  DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER;
4475  } else
4476  zi.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER;
4477  zi.confno = p->confno;
4478  }
4479  if ((zi.confno == c->curconf.confno) && (zi.confmode == c->curconf.confmode))
4480  return 0;
4481  if (c->dfd < 0)
4482  return 0;
4483  if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
4484  ast_log(LOG_WARNING, "Failed to add %d to conference %d/%d: %s\n", c->dfd, zi.confmode, zi.confno, strerror(errno));
4485  return -1;
4486  }
4487  if (slavechannel < 1) {
4488  p->confno = zi.confno;
4489  }
4490  c->curconf = zi;
4491  ast_debug(1, "Added %d to conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
4492  return 0;
4493 }
4494 
4495 static int isourconf(struct dahdi_pvt *p, struct dahdi_subchannel *c)
4496 {
4497  /* If they're listening to our channel, they're ours */
4498  if ((p->channel == c->curconf.confno) && (c->curconf.confmode == DAHDI_CONF_DIGITALMON))
4499  return 1;
4500  /* If they're a talker on our (allocated) conference, they're ours */
4501  if ((p->confno > 0) && (p->confno == c->curconf.confno) && (c->curconf.confmode & DAHDI_CONF_TALKER))
4502  return 1;
4503  return 0;
4504 }
4505 
4506 static int conf_del(struct dahdi_pvt *p, struct dahdi_subchannel *c, int idx)
4507 {
4508  struct dahdi_confinfo zi;
4509  if (/* Can't delete if there's no dfd */
4510  (c->dfd < 0) ||
4511  /* Don't delete from the conference if it's not our conference */
4512  !isourconf(p, c)
4513  /* Don't delete if we don't think it's conferenced at all (implied) */
4514  ) return 0;
4515  memset(&zi, 0, sizeof(zi));
4516  if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
4517  ast_log(LOG_WARNING, "Failed to drop %d from conference %d/%d: %s\n", c->dfd, c->curconf.confmode, c->curconf.confno, strerror(errno));
4518  return -1;
4519  }
4520  ast_debug(1, "Removed %d from conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
4521  memcpy(&c->curconf, &zi, sizeof(c->curconf));
4522  return 0;
4523 }
4524 
4525 static int isslavenative(struct dahdi_pvt *p, struct dahdi_pvt **out)
4526 {
4527  int x;
4528  int useslavenative;
4529  struct dahdi_pvt *slave = NULL;
4530  /* Start out optimistic */
4531  useslavenative = 1;
4532  /* Update conference state in a stateless fashion */
4533  for (x = 0; x < 3; x++) {
4534  /* Any three-way calling makes slave native mode *definitely* out
4535  of the question */
4536  if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway)
4537  useslavenative = 0;
4538  }
4539  /* If we don't have any 3-way calls, check to see if we have
4540  precisely one slave */
4541  if (useslavenative) {
4542  for (x = 0; x < MAX_SLAVES; x++) {
4543  if (p->slaves[x]) {
4544  if (slave) {
4545  /* Whoops already have a slave! No
4546  slave native and stop right away */
4547  slave = NULL;
4548  useslavenative = 0;
4549  break;
4550  } else {
4551  /* We have one slave so far */
4552  slave = p->slaves[x];
4553  }
4554  }
4555  }
4556  }
4557  /* If no slave, slave native definitely out */
4558  if (!slave)
4559  useslavenative = 0;
4560  else if (slave->law != p->law) {
4561  useslavenative = 0;
4562  slave = NULL;
4563  }
4564  if (out)
4565  *out = slave;
4566  return useslavenative;
4567 }
4568 
4569 static int reset_conf(struct dahdi_pvt *p)
4570 {
4571  p->confno = -1;
4572  memset(&p->subs[SUB_REAL].curconf, 0, sizeof(p->subs[SUB_REAL].curconf));
4573  if (p->subs[SUB_REAL].dfd > -1) {
4574  struct dahdi_confinfo zi;
4575 
4576  memset(&zi, 0, sizeof(zi));
4577  if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &zi))
4578  ast_log(LOG_WARNING, "Failed to reset conferencing on channel %d: %s\n", p->channel, strerror(errno));
4579  }
4580  return 0;
4581 }
4582 
4584 {
4585  int needconf = 0;
4586  int x;
4587  int useslavenative;
4588  struct dahdi_pvt *slave = NULL;
4589 
4590  useslavenative = isslavenative(p, &slave);
4591  /* Start with the obvious, general stuff */
4592  for (x = 0; x < 3; x++) {
4593  /* Look for three way calls */
4594  if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) {
4595  conf_add(p, &p->subs[x], x, 0);
4596  needconf++;
4597  } else {
4598  conf_del(p, &p->subs[x], x);
4599  }
4600  }
4601  /* If we have a slave, add him to our conference now. or DAX
4602  if this is slave native */
4603  for (x = 0; x < MAX_SLAVES; x++) {
4604  if (p->slaves[x]) {
4605  if (useslavenative)
4606  conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
4607  else {
4608  conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
4609  needconf++;
4610  }
4611  }
4612  }
4613  /* If we're supposed to be in there, do so now */
4614  if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
4615  if (useslavenative)
4616  conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
4617  else {
4618  conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
4619  needconf++;
4620  }
4621  }
4622  /* If we have a master, add ourselves to his conference */
4623  if (p->master) {
4624  if (isslavenative(p->master, NULL)) {
4626  } else {
4627  conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
4628  }
4629  }
4630  if (!needconf) {
4631  /* Nobody is left (or should be left) in our conference.
4632  Kill it. */
4633  p->confno = -1;
4634  }
4635  ast_debug(1, "Updated conferencing on %d, with %d conference users\n", p->channel, needconf);
4636 }
4637 
4639 {
4640  int res;
4641  if (!p)
4642  return;
4643  if (p->echocanon) {
4644  ast_debug(1, "Echo cancellation already on\n");
4645  return;
4646  }
4647  if (p->digital) {
4648  ast_debug(1, "Echo cancellation isn't required on digital connection\n");
4649  return;
4650  }
4651  if (p->echocancel.head.tap_length) {
4652 #if defined(HAVE_PRI) || defined(HAVE_SS7)
4653  switch (p->sig) {
4654 #if defined(HAVE_PRI)
4656  if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
4657  /*
4658  * PRI nobch pseudo channel. Does not need ec anyway.
4659  * Does not handle ioctl(DAHDI_AUDIOMODE)
4660  */
4661  return;
4662  }
4663  /* Fall through */
4664 #endif /* defined(HAVE_PRI) */
4665 #if defined(HAVE_SS7)
4666  case SIG_SS7:
4667 #endif /* defined(HAVE_SS7) */
4668  {
4669  int x = 1;
4670 
4671  res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x);
4672  if (res)
4674  "Unable to enable audio mode on channel %d (%s)\n",
4675  p->channel, strerror(errno));
4676  }
4677  break;
4678  default:
4679  break;
4680  }
4681 #endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */
4682  res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &p->echocancel);
4683  if (res) {
4684  ast_log(LOG_WARNING, "Unable to enable echo cancellation on channel %d (%s)\n", p->channel, strerror(errno));
4685  } else {
4686  p->echocanon = 1;
4687  ast_debug(1, "Enabled echo cancellation on channel %d\n", p->channel);
4688  }
4689  } else
4690  ast_debug(1, "No echo cancellation requested\n");
4691 }
4692 
4693 static void dahdi_train_ec(struct dahdi_pvt *p)
4694 {
4695  int x;
4696  int res;
4697 
4698  if (p && p->echocanon && p->echotraining) {
4699  x = p->echotraining;
4700  res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOTRAIN, &x);
4701  if (res)
4702  ast_log(LOG_WARNING, "Unable to request echo training on channel %d: %s\n", p->channel, strerror(errno));
4703  else
4704  ast_debug(1, "Engaged echo training on channel %d\n", p->channel);
4705  } else {
4706  ast_debug(1, "No echo training requested\n");
4707  }
4708 }
4709 
4711 {
4712  int res;
4713 
4714  if (p->echocanon) {
4715  struct dahdi_echocanparams ecp = { .tap_length = 0 };
4716 
4717  res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &ecp);
4718 
4719  if (res)
4720  ast_log(LOG_WARNING, "Unable to disable echo cancellation on channel %d: %s\n", p->channel, strerror(errno));
4721  else
4722  ast_debug(1, "Disabled echo cancellation on channel %d\n", p->channel);
4723  }
4724 
4725  p->echocanon = 0;
4726 }
4727 
4728 static int set_hwgain(int fd, float gain, int tx_direction)
4729 {
4730  struct dahdi_hwgain hwgain;
4731 
4732  hwgain.newgain = gain * 10.0;
4733  hwgain.tx = tx_direction;
4734  return ioctl(fd, DAHDI_SET_HWGAIN, &hwgain) < 0;
4735 }
4736 
4737 /* perform a dynamic range compression transform on the given sample */
4738 static int drc_sample(int sample, float drc)
4739 {
4740  float neg;
4741  float shallow, steep;
4742  float max = SHRT_MAX;
4743 
4744  neg = (sample < 0 ? -1 : 1);
4745  steep = drc*sample;
4746  shallow = neg*(max-max/drc)+(float)sample/drc;
4747  if (fabsf(steep) < fabsf(shallow)) {
4748  sample = steep;
4749  }
4750  else {
4751  sample = shallow;
4752  }
4753 
4754  return sample;
4755 }
4756 
4757 
4758 static void fill_txgain(struct dahdi_gains *g, float gain, float drc, int law)
4759 {
4760  int j;
4761  int k;
4762 
4763  float linear_gain = pow(10.0, gain / 20.0);
4764 
4765  switch (law) {
4766  case DAHDI_LAW_ALAW:
4767  for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
4768  if (gain || drc) {
4769  k = AST_ALAW(j);
4770  if (drc) {
4771  k = drc_sample(k, drc);
4772  }
4773  k = (float)k * linear_gain;
4774  if (k > 32767) {
4775  k = 32767;
4776  } else if (k < -32768) {
4777  k = -32768;
4778  }
4779  g->txgain[j] = AST_LIN2A(k);
4780  } else {
4781  g->txgain[j] = j;
4782  }
4783  }
4784  break;
4785  case DAHDI_LAW_MULAW:
4786  for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
4787  if (gain || drc) {
4788  k = AST_MULAW(j);
4789  if (drc) {
4790  k = drc_sample(k, drc);
4791  }
4792  k = (float)k * linear_gain;
4793  if (k > 32767) {
4794  k = 32767;
4795  } else if (k < -32768) {
4796  k = -32768;
4797  }
4798  g->txgain[j] = AST_LIN2MU(k);
4799 
4800  } else {
4801  g->txgain[j] = j;
4802  }
4803  }
4804  break;
4805  }
4806 }
4807 
4808 static void fill_rxgain(struct dahdi_gains *g, float gain, float drc, int law)
4809 {
4810  int j;
4811  int k;
4812  float linear_gain = pow(10.0, gain / 20.0);
4813 
4814  switch (law) {
4815  case DAHDI_LAW_ALAW:
4816  for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
4817  if (gain || drc) {
4818  k = AST_ALAW(j);
4819  if (drc) {
4820  k = drc_sample(k, drc);
4821  }
4822  k = (float)k * linear_gain;
4823  if (k > 32767) {
4824  k = 32767;
4825  } else if (k < -32768) {
4826  k = -32768;
4827  }
4828  g->rxgain[j] = AST_LIN2A(k);
4829  } else {
4830  g->rxgain[j] = j;
4831  }
4832  }
4833  break;
4834  case DAHDI_LAW_MULAW:
4835  for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
4836  if (gain || drc) {
4837  k = AST_MULAW(j);
4838  if (drc) {
4839  k = drc_sample(k, drc);
4840  }
4841  k = (float)k * linear_gain;
4842  if (k > 32767) {
4843  k = 32767;
4844  } else if (k < -32768) {
4845  k = -32768;
4846  }
4847  g->rxgain[j] = AST_LIN2MU(k);
4848  } else {
4849  g->rxgain[j] = j;
4850  }
4851  }
4852  break;
4853  }
4854 }
4855 
4856 static int set_actual_txgain(int fd, float gain, float drc, int law)
4857 {
4858  struct dahdi_gains g;
4859  int res;
4860 
4861  memset(&g, 0, sizeof(g));
4862  res = ioctl(fd, DAHDI_GETGAINS, &g);
4863  if (res) {
4864  ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
4865  return res;
4866  }
4867 
4868  fill_txgain(&g, gain, drc, law);
4869 
4870  return ioctl(fd, DAHDI_SETGAINS, &g);
4871 }
4872 
4873 static int set_actual_rxgain(int fd, float gain, float drc, int law)
4874 {
4875  struct dahdi_gains g;
4876  int res;
4877 
4878  memset(&g, 0, sizeof(g));
4879  res = ioctl(fd, DAHDI_GETGAINS, &g);
4880  if (res) {
4881  ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
4882  return res;
4883  }
4884 
4885  fill_rxgain(&g, gain, drc, law);
4886 
4887  return ioctl(fd, DAHDI_SETGAINS, &g);
4888 }
4889 
4890 static int set_actual_gain(int fd, float rxgain, float txgain, float rxdrc, float txdrc, int law)
4891 {
4892  return set_actual_txgain(fd, txgain, txdrc, law) | set_actual_rxgain(fd, rxgain, rxdrc, law);
4893 }
4894 
4895 static int bump_gains(struct dahdi_pvt *p)
4896 {
4897  int res;
4898 
4899  /* Bump receive gain by value stored in cid_rxgain */
4900  res = set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain + p->cid_rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
4901  if (res) {
4902  ast_log(LOG_WARNING, "Unable to bump gain: %s\n", strerror(errno));
4903  return -1;
4904  }
4905 
4906  return 0;
4907 }
4908 
4909 static int restore_gains(struct dahdi_pvt *p)
4910 {
4911  int res;
4912 
4913  res = set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
4914  if (res) {
4915  ast_log(LOG_WARNING, "Unable to restore gains: %s\n", strerror(errno));
4916  return -1;
4917  }
4918 
4919  return 0;
4920 }
4921 
4922 static inline int dahdi_set_hook(int fd, int hs)
4923 {
4924  int x, res;
4925 
4926  x = hs;
4927  res = ioctl(fd, DAHDI_HOOK, &x);
4928 
4929  if (res < 0) {
4930  if (errno == EINPROGRESS)
4931  return 0;
4932  ast_log(LOG_WARNING, "DAHDI hook failed returned %d (trying %d): %s\n", res, hs, strerror(errno));
4933  /* will expectedly fail if phone is off hook during operation, such as during a restart */
4934  }
4935 
4936  return res;
4937 }
4938 
4939 static inline int dahdi_confmute(struct dahdi_pvt *p, int muted)
4940 {
4941  int x, res;
4942 
4943  x = muted;
4944 #if defined(HAVE_PRI) || defined(HAVE_SS7)
4945  switch (p->sig) {
4946 #if defined(HAVE_PRI)
4948  if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
4949  /* PRI nobch pseudo channel. Does not handle ioctl(DAHDI_AUDIOMODE) */
4950  break;
4951  }
4952  /* Fall through */
4953 #endif /* defined(HAVE_PRI) */
4954 #if defined(HAVE_SS7)
4955  case SIG_SS7:
4956 #endif /* defined(HAVE_SS7) */
4957  {
4958  int y = 1;
4959 
4960  res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &y);
4961  if (res)
4962  ast_log(LOG_WARNING, "Unable to set audio mode on %d: %s\n",
4963  p->channel, strerror(errno));
4964  }
4965  break;
4966  default:
4967  break;
4968  }
4969 #endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */
4970  res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_CONFMUTE, &x);
4971  if (res < 0)
4972  ast_log(LOG_WARNING, "DAHDI confmute(%d) failed on channel %d: %s\n", muted, p->channel, strerror(errno));
4973  return res;
4974 }
4975 
4976 static int save_conference(struct dahdi_pvt *p)
4977 {
4978  struct dahdi_confinfo c;
4979  int res;
4980  if (p->saveconf.confmode) {
4981  ast_log(LOG_WARNING, "Can't save conference -- already in use\n");
4982  return -1;
4983  }
4984  p->saveconf.chan = 0;
4985  res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &p->saveconf);
4986  if (res) {
4987  ast_log(LOG_WARNING, "Unable to get conference info: %s\n", strerror(errno));
4988  p->saveconf.confmode = 0;
4989  return -1;
4990  }
4991  memset(&c, 0, sizeof(c));
4992  c.confmode = DAHDI_CONF_NORMAL;
4993  res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &c);
4994  if (res) {
4995  ast_log(LOG_WARNING, "Unable to set conference info: %s\n", strerror(errno));
4996  return -1;
4997  }
4998  ast_debug(1, "Disabled conferencing\n");
4999  return 0;
5000 }
5001 
5002 static int restore_conference(struct dahdi_pvt *p)
5003 {
5004  int res;
5005  if (p->saveconf.confmode) {
5006  res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &p->saveconf);
5007  p->saveconf.confmode = 0;
5008  if (res) {
5009  ast_log(LOG_WARNING, "Unable to restore conference info: %s\n", strerror(errno));
5010  return -1;
5011  }
5012  ast_debug(1, "Restored conferencing\n");
5013  }
5014  return 0;
5015 }
5016 
5017 static int send_cwcidspill(struct dahdi_pvt *p)
5018 {
5019  p->callwaitcas = 0;
5020  p->cidcwexpire = 0;
5021  p->cid_suppress_expire = 0;
5022  if (!(p->cidspill = ast_malloc(MAX_CALLERID_SIZE)))
5023  return -1;
5025  /* Make sure we account for the end */
5026  p->cidlen += READ_SIZE * 4;
5027  p->cidpos = 0;
5028  send_callerid(p);
5029  ast_verb(3, "CPE supports Call Waiting Caller*ID. Sending '%s/%s'\n", p->callwait_name, p->callwait_num);
5030  return 0;
5031 }
5032 
5033 static int has_voicemail(struct dahdi_pvt *p)
5034 {
5035  int new_msgs;
5036  RAII_VAR(struct stasis_message *, mwi_message, NULL, ao2_cleanup);
5037 
5039  if (mwi_message) {
5040  struct ast_mwi_state *mwi_state = stasis_message_data(mwi_message);
5041  new_msgs = mwi_state->new_msgs;
5042  } else {
5043  new_msgs = ast_app_has_voicemail(p->mailbox, NULL);
5044  }
5045 
5046  return new_msgs;
5047 }
5048 
5049 
5050 
5051 static int send_callerid(struct dahdi_pvt *p)
5052 {
5053  /* Assumes spill in p->cidspill, p->cidlen in length and we're p->cidpos into it */
5054  int res;
5055  /* Take out of linear mode if necessary */
5056  if (p->subs[SUB_REAL].linear) {
5057  p->subs[SUB_REAL].linear = 0;
5058  dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
5059  }
5060  while (p->cidpos < p->cidlen) {
5061  res = write(p->subs[SUB_REAL].dfd, p->cidspill + p->cidpos, p->cidlen - p->cidpos);
5062  ast_debug(4, "writing callerid at pos %d of %d, res = %d\n", p->cidpos, p->cidlen, res);
5063  if (res < 0) {
5064  if (errno == EAGAIN)
5065  return 0;
5066  else {
5067  ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
5068  return -1;
5069  }
5070  }
5071  if (!res)
5072  return 0;
5073  p->cidpos += res;
5074  }
5076  ast_free(p->cidspill);
5077  p->cidspill = NULL;
5078  if (p->callwaitcas) {
5079  /* Wait for CID/CW to expire */
5082  } else
5083  restore_conference(p);
5084  return 0;
5085 }
5086 
5087 static int dahdi_callwait(struct ast_channel *ast)
5088 {
5089  struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
5090 
5092  if (p->cidspill) {
5093  ast_log(LOG_WARNING, "Spill already exists?!?\n");
5094  ast_free(p->cidspill);
5095  }
5096 
5097  /*
5098  * SAS: Subscriber Alert Signal, 440Hz for 300ms
5099  * CAS: CPE Alert Signal, 2130Hz * 2750Hz sine waves
5100  */
5101  if (!(p->cidspill = ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE * 4)))
5102  return -1;
5103  save_conference(p);
5104  /* Silence */
5105  memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
5106  if (!p->callwaitrings && p->callwaitingcallerid) {
5107  ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
5108  p->callwaitcas = 1;
5109  p->cidlen = 2400 + 680 + READ_SIZE * 4;
5110  } else {
5111  ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
5112  p->callwaitcas = 0;
5113  p->cidlen = 2400 + READ_SIZE * 4;
5114  }
5115  p->cidpos = 0;
5116  send_callerid(p);
5117 
5118  return 0;
5119 }
5120 
5121 static int dahdi_call(struct ast_channel *ast, const char *rdest, int timeout)
5122 {
5123  struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
5124  int x, res, mysig;
5125  char *dest;
5127  AST_APP_ARG(group); /* channel/group token */
5128  AST_APP_ARG(ext); /* extension token */
5129  //AST_APP_ARG(opts); /* options token */
5130  AST_APP_ARG(other); /* Any remining unused arguments */
5131  );
5132 
5133  ast_mutex_lock(&p->lock);
5134  ast_copy_string(p->dialdest, rdest, sizeof(p->dialdest));
5135 
5136  /* Split the dialstring */
5137  dest = ast_strdupa(rdest);
5138  AST_NONSTANDARD_APP_ARGS(args, dest, '/');
5139  if (!args.ext) {
5140  args.ext = "";
5141  }
5142 
5143 #if defined(HAVE_PRI)
5144  if (dahdi_sig_pri_lib_handles(p->sig)) {
5145  char *subaddr;
5146 
5147  sig_pri_extract_called_num_subaddr(p->sig_pvt, rdest, p->exten, sizeof(p->exten));
5148 
5149  /* Remove any subaddress for uniformity with incoming calls. */
5150  subaddr = strchr(p->exten, ':');
5151  if (subaddr) {
5152  *subaddr = '\0';
5153  }
5154  } else
5155 #endif /* defined(HAVE_PRI) */
5156  {
5157  ast_copy_string(p->exten, args.ext, sizeof(p->exten));
5158  }
5159 
5160  if ((ast_channel_state(ast) == AST_STATE_BUSY)) {
5161  p->subs[SUB_REAL].needbusy = 1;
5162  ast_mutex_unlock(&p->lock);
5163  return 0;
5164  }
5166  ast_log(LOG_WARNING, "dahdi_call called on %s, neither down nor reserved\n", ast_channel_name(ast));
5167  ast_mutex_unlock(&p->lock);
5168  return -1;
5169  }
5170  p->waitingfordt.tv_sec = 0;
5171  p->dialednone = 0;
5172  if ((p->radio || (p->oprmode < 0))) /* if a radio channel, up immediately */
5173  {
5174  /* Special pseudo -- automatically up */
5175  ast_setstate(ast, AST_STATE_UP);
5176  ast_mutex_unlock(&p->lock);
5177  return 0;
5178  }
5179  x = DAHDI_FLUSH_READ | DAHDI_FLUSH_WRITE;
5180  res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
5181  if (res)
5182  ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", p->channel, strerror(errno));
5183  p->outgoing = 1;
5184 
5186  set_actual_gain(p->subs[SUB_REAL].dfd, 0, 0, p->rxdrc, p->txdrc, p->law);
5187  } else {
5188  set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
5189  }
5190 
5191 #ifdef HAVE_PRI
5192  if (dahdi_sig_pri_lib_handles(p->sig)) {
5193  res = sig_pri_call(p->sig_pvt, ast, rdest, timeout,
5194  (p->law == DAHDI_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW);
5195  ast_mutex_unlock(&p->lock);
5196  return res;
5197  }
5198 #endif
5199 
5200 #if defined(HAVE_SS7)
5201  if (p->sig == SIG_SS7) {
5202  res = sig_ss7_call(p->sig_pvt, ast, rdest);
5203  ast_mutex_unlock(&p->lock);
5204  return res;
5205  }
5206 #endif /* defined(HAVE_SS7) */
5207 
5208  /* If this is analog signalling we can exit here */
5209  if (dahdi_analog_lib_handles(p->sig, p->radio, p->oprmode)) {
5210  p->callwaitrings = 0;
5211  res = analog_call(p->sig_pvt, ast, rdest, timeout);
5212  ast_mutex_unlock(&p->lock);
5213  return res;
5214  }
5215 
5216  mysig = p->outsigmod > -1 ? p->outsigmod : p->sig;
5217  switch (mysig) {
5218  case 0:
5219  /* Special pseudo -- automatically up*/
5220  ast_setstate(ast, AST_STATE_UP);
5221  break;
5222  case SIG_MFCR2:
5223  break;
5224  default:
5225  ast_debug(1, "not yet implemented\n");
5226  ast_mutex_unlock(&p->lock);
5227  return -1;
5228  }
5229 
5230 #ifdef HAVE_OPENR2
5231  if (p->mfcr2) {
5232  openr2_calling_party_category_t chancat;
5233  int callres = 0;
5234  char *c, *l;
5235 
5236  /* We'll get it in a moment -- but use dialdest to store pre-setup_ack digits */
5237  p->dialdest[0] = '\0';
5238 
5239  c = args.ext;
5240  if (!p->hidecallerid) {
5242  } else {
5243  l = NULL;
5244  }
5245  if (strlen(c) < p->stripmsd) {
5246  ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
5247  ast_mutex_unlock(&p->lock);
5248  return -1;
5249  }
5250  p->dialing = 1;
5251  chancat = dahdi_r2_get_channel_category(ast);
5252  callres = openr2_chan_make_call(p->r2chan, l, (c + p->stripmsd), chancat);
5253  if (-1 == callres) {
5254  ast_mutex_unlock(&p->lock);
5255  ast_log(LOG_ERROR, "unable to make new MFC/R2 call!\n");
5256  return -1;
5257  }
5258  p->mfcr2_call_accepted = 0;
5259  p->mfcr2_progress_sent = 0;
5261  }
5262 #endif /* HAVE_OPENR2 */
5263  ast_mutex_unlock(&p->lock);
5264  return 0;
5265 }
5266 
5267 /*!
5268  * \internal
5269  * \brief Insert the given chan_dahdi interface structure into the interface list.
5270  * \since 1.8
5271  *
5272  * \param pvt chan_dahdi private interface structure to insert.
5273  *
5274  * \details
5275  * The interface list is a doubly linked list sorted by the chan_dahdi channel number.
5276  * Any duplicates are inserted after the existing entries.
5277  *
5278  * \note The new interface must not already be in the list.
5279  *
5280  * \return Nothing
5281  */
5282 static void dahdi_iflist_insert(struct dahdi_pvt *pvt)
5283 {
5284  struct dahdi_pvt *cur;
5285 
5287 
5288  /* Find place in middle of list for the new interface. */
5289  for (cur = iflist; cur; cur = cur->next) {
5290  if (pvt->channel < cur->channel) {
5291  /* New interface goes before the current interface. */
5292  pvt->prev = cur->prev;
5293  pvt->next = cur;
5294  if (cur->prev) {
5295  /* Insert into the middle of the list. */
5296  cur->prev->next = pvt;
5297  } else {
5298  /* Insert at head of list. */
5299  iflist = pvt;
5300  }
5301  cur->prev = pvt;
5302  return;
5303  }
5304  }
5305 
5306  /* New interface goes onto the end of the list */
5307  pvt->prev = ifend;
5308  pvt->next = NULL;
5309  if (ifend) {
5310  ifend->next = pvt;
5311  }
5312  ifend = pvt;
5313  if (!iflist) {
5314  /* List was empty */
5315  iflist = pvt;
5316  }
5317 }
5318 
5319 /*!
5320  * \internal
5321  * \brief Extract the given chan_dahdi interface structure from the interface list.
5322  * \since 1.8
5323  *
5324  * \param pvt chan_dahdi private interface structure to extract.
5325  *
5326  * \note
5327  * The given interface structure can be either in the interface list or a stand alone
5328  * structure that has not been put in the list if the next and prev pointers are NULL.
5329  *
5330  * \return Nothing
5331  */
5332 static void dahdi_iflist_extract(struct dahdi_pvt *pvt)
5333 {
5334  /* Extract from the forward chain. */
5335  if (pvt->prev) {
5336  pvt->prev->next = pvt->next;
5337  } else if (iflist == pvt) {
5338  /* Node is at the head of the list. */
5339  iflist = pvt->next;
5340  }
5341 
5342  /* Extract from the reverse chain. */
5343  if (pvt->next) {
5344  pvt->next->prev = pvt->prev;
5345  } else if (ifend == pvt) {
5346  /* Node is at the end of the list. */
5347  ifend = pvt->prev;
5348  }
5349 
5350  /* Node is no longer in the list. */
5352  pvt->prev = NULL;
5353  pvt->next = NULL;
5354 }
5355 
5356 #if defined(HAVE_PRI)
5357 /*!
5358  * \internal
5359  * \brief Insert the given chan_dahdi interface structure into the no B channel list.
5360  * \since 1.8
5361  *
5362  * \param pri sig_pri span control structure holding no B channel list.
5363  * \param pvt chan_dahdi private interface structure to insert.
5364  *
5365  * \details
5366  * The interface list is a doubly linked list sorted by the chan_dahdi channel number.
5367  * Any duplicates are inserted after the existing entries.
5368  *
5369  * \note The new interface must not already be in the list.
5370  *
5371  * \return Nothing
5372  */
5373 static void dahdi_nobch_insert(struct sig_pri_span *pri, struct dahdi_pvt *pvt)
5374 {
5375  struct dahdi_pvt *cur;
5376 
5377  pvt->which_iflist = DAHDI_IFLIST_NO_B_CHAN;
5378 
5379  /* Find place in middle of list for the new interface. */
5380  for (cur = pri->no_b_chan_iflist; cur; cur = cur->next) {
5381  if (pvt->channel < cur->channel) {
5382  /* New interface goes before the current interface. */
5383  pvt->prev = cur->prev;
5384  pvt->next = cur;
5385  if (cur->prev) {
5386  /* Insert into the middle of the list. */
5387  cur->prev->next = pvt;
5388  } else {
5389  /* Insert at head of list. */
5390  pri->no_b_chan_iflist = pvt;
5391  }
5392  cur->prev = pvt;
5393  return;
5394  }
5395  }
5396 
5397  /* New interface goes onto the end of the list */
5398  pvt->prev = pri->no_b_chan_end;
5399  pvt->next = NULL;
5400  if (pri->no_b_chan_end) {
5401  ((struct dahdi_pvt *) pri->no_b_chan_end)->next = pvt;
5402  }
5403  pri->no_b_chan_end = pvt;
5404  if (!pri->no_b_chan_iflist) {
5405  /* List was empty */
5406  pri->no_b_chan_iflist = pvt;
5407  }
5408 }
5409 #endif /* defined(HAVE_PRI) */
5410 
5411 #if defined(HAVE_PRI)
5412 /*!
5413  * \internal
5414  * \brief Extract the given chan_dahdi interface structure from the no B channel list.
5415  * \since 1.8
5416  *
5417  * \param pri sig_pri span control structure holding no B channel list.
5418  * \param pvt chan_dahdi private interface structure to extract.
5419  *
5420  * \note
5421  * The given interface structure can be either in the interface list or a stand alone
5422  * structure that has not been put in the list if the next and prev pointers are NULL.
5423  *
5424  * \return Nothing
5425  */
5426 static void dahdi_nobch_extract(struct sig_pri_span *pri, struct dahdi_pvt *pvt)
5427 {
5428  /* Extract from the forward chain. */
5429  if (pvt->prev) {
5430  pvt->prev->next = pvt->next;
5431  } else if (pri->no_b_chan_iflist == pvt) {
5432  /* Node is at the head of the list. */
5433  pri->no_b_chan_iflist = pvt->next;
5434  }
5435 
5436  /* Extract from the reverse chain. */
5437  if (pvt->next) {
5438  pvt->next->prev = pvt->prev;
5439  } else if (pri->no_b_chan_end == pvt) {
5440  /* Node is at the end of the list. */
5441  pri->no_b_chan_end = pvt->prev;
5442  }
5443 
5444  /* Node is no longer in the list. */
5446  pvt->prev = NULL;
5447  pvt->next = NULL;
5448 }
5449 #endif /* defined(HAVE_PRI) */
5450 
5451 #if defined(HAVE_PRI)
5452 /*!
5453  * \internal
5454  * \brief Unlink the channel interface from the PRI private pointer array.
5455  * \since 1.8
5456  *
5457  * \param pvt chan_dahdi private interface structure to unlink.
5458  *
5459  * \return Nothing
5460  */
5461 static void dahdi_unlink_pri_pvt(struct dahdi_pvt *pvt)
5462 {
5463  unsigned idx;
5464  struct sig_pri_span *pri;
5465 
5466  pri = pvt->pri;
5467  if (!pri) {
5468  /* Not PRI signaling so cannot be in a PRI private pointer array. */
5469  return;
5470  }
5471  ast_mutex_lock(&pri->lock);
5472  for (idx = 0; idx < pri->numchans; ++idx) {
5473  if (pri->pvts[idx] == pvt->sig_pvt) {
5474  pri->pvts[idx] = NULL;
5475  ast_mutex_unlock(&pri->lock);
5476  return;
5477  }
5478  }
5479  ast_mutex_unlock(&pri->lock);
5480 }
5481 #endif /* defined(HAVE_PRI) */
5482 
5483 #if defined(HAVE_SS7)
5484 /*!
5485  * \internal
5486  * \brief Unlink the channel interface from the SS7 private pointer array.
5487  * \since 1.8
5488  *
5489  * \param pvt chan_dahdi private interface structure to unlink.
5490  *
5491  * \return Nothing
5492  */
5493 static void dahdi_unlink_ss7_pvt(struct dahdi_pvt *pvt)
5494 {
5495  unsigned idx;
5496  struct sig_ss7_linkset *ss7;
5497 
5498  ss7 = pvt->ss7;
5499  if (!ss7) {
5500  /* Not SS7 signaling so cannot be in a SS7 private pointer array. */
5501  return;
5502  }
5503  ast_mutex_lock(&ss7->lock);
5504  for (idx = 0; idx < ss7->numchans; ++idx) {
5505  if (ss7->pvts[idx] == pvt->sig_pvt) {
5506  ss7->pvts[idx] = NULL;
5507  ast_mutex_unlock(&ss7->lock);
5508  return;
5509  }
5510  }
5511  ast_mutex_unlock(&ss7->lock);
5512 }
5513 #endif /* defined(HAVE_SS7) */
5514 
5515 #if defined(HAVE_OPENR2)
5516 /*!
5517  * \internal
5518  * \brief Unlink the channel interface from the MFC/R2 private pointer array.
5519  *
5520  * \param pvt chan_dahdi private interface structure to unlink.
5521  *
5522  * \return Nothing
5523  */
5524 static void dahdi_unlink_mfcr2_pvt(struct dahdi_pvt *pvt)
5525 {
5526  unsigned idx;
5527  struct dahdi_mfcr2 *mfcr2;
5528  int should_destroy_link = 0;
5529 
5530  ast_mutex_lock(&pvt->lock);
5531  if (pvt->r2chan) {
5532  ast_debug(1, "Disable MFC/R2 channel %d read\n", pvt->channel);
5533  openr2_chan_disable_read(pvt->r2chan);
5534  }
5535  mfcr2 = pvt->mfcr2;
5536  if (mfcr2) {
5537  for (idx = 0; idx < mfcr2->numchans; ++idx) {
5538  if (mfcr2->pvts[idx] == pvt) {
5539  ast_debug(1, "Removing MFC/R2 channel %d from the mfcr2 link\n", pvt->channel);
5540  mfcr2->pvts[idx] = NULL;
5541  mfcr2->live_chans--;
5542  break;
5543  }
5544  }
5545  if (!mfcr2->live_chans) {
5546  ast_debug(1, "MFC/R2 link is now empty\n");
5547  should_destroy_link = 1;
5548  }
5549  }
5550  ast_mutex_unlock(&pvt->lock);
5551  if (should_destroy_link) {
5552  ast_debug(1, "MFC/R2 link is now empty\n");
5553  mfcr2_queue_for_destruction(pvt);
5554  }
5555 }
5556 #endif /* defined(HAVE_OPENR2) */
5557 
5558 static struct dahdi_pvt *find_next_iface_in_span(struct dahdi_pvt *cur)
5559 {
5560  if (cur->next && cur->next->span == cur->span) {
5561  return cur->next;
5562  } else if (cur->prev && cur->prev->span == cur->span) {
5563  return cur->prev;
5564  }
5565 
5566  return NULL;
5567 }
5568 
5569 static void destroy_dahdi_pvt(struct dahdi_pvt *pvt)
5570 {
5571  struct dahdi_pvt *p = pvt;
5572 
5573  if (p->manages_span_alarms) {
5574  struct dahdi_pvt *next = find_next_iface_in_span(p);
5575  if (next) {
5576  next->manages_span_alarms = 1;
5577  }
5578  }
5579 
5580  /* Remove channel from the list */
5581 #if defined(HAVE_PRI)
5582  dahdi_unlink_pri_pvt(p);
5583 #endif /* defined(HAVE_PRI) */
5584 #if defined(HAVE_SS7)
5585  dahdi_unlink_ss7_pvt(p);
5586 #endif /* defined(HAVE_SS7) */
5587 #if defined(HAVE_OPENR2)
5588  dahdi_unlink_mfcr2_pvt(p);
5589 #endif /* defined(HAVE_SS7) */
5590  switch (pvt->which_iflist) {
5591  case DAHDI_IFLIST_NONE:
5592  break;
5593  case DAHDI_IFLIST_MAIN:
5595  break;
5596 #if defined(HAVE_PRI)
5597  case DAHDI_IFLIST_NO_B_CHAN:
5598  if (p->pri) {
5599  dahdi_nobch_extract(p->pri, p);
5600  }
5601  break;
5602 #endif /* defined(HAVE_PRI) */
5603  }
5604 
5605  if (p->sig_pvt) {
5606  if (dahdi_analog_lib_handles(p->sig, 0, 0)) {
5607  analog_delete(p->sig_pvt);
5608  }
5609  switch (p->sig) {
5610 #if defined(HAVE_PRI)
5613  break;
5614 #endif /* defined(HAVE_PRI) */
5615 #if defined(HAVE_SS7)
5616  case SIG_SS7:
5618  break;
5619 #endif /* defined(HAVE_SS7) */
5620  default:
5621  break;
5622  }
5623  }
5624  ast_free(p->cidspill);
5625  if (p->use_smdi) {
5626  ao2_cleanup(p->smdi_iface);
5627  }
5628  if (p->mwi_event_sub) {
5630  }
5631  if (p->vars) {
5633  }
5634  if (p->cc_params) {
5636  }
5637 
5640 
5641  ast_mutex_destroy(&p->lock);
5643  if (p->owner) {
5645  }
5646  ast_free(p);
5647 }
5648 
5649 static void destroy_channel(struct dahdi_pvt *cur, int now)
5650 {
5651  int i;
5652 
5653  if (!now) {
5654  /* Do not destroy the channel now if it is owned by someone. */
5655  if (cur->owner) {
5656  return;
5657  }
5658  for (i = 0; i < 3; i++) {
5659  if (cur->subs[i].owner) {
5660  return;
5661  }
5662  }
5663  }
5664  destroy_dahdi_pvt(cur);
5665 }
5666 
5667 static void destroy_all_channels(void)
5668 {
5669  int chan;
5670 #if defined(HAVE_PRI)
5671  unsigned span;
5672  struct sig_pri_span *pri;
5673 #endif /* defined(HAVE_PRI) */
5674  struct dahdi_pvt *p;
5675 
5676  while (num_restart_pending) {
5677  usleep(1);
5678  }
5679 
5681  /* Destroy all the interfaces and free their memory */
5682  while (iflist) {
5683  p = iflist;
5684 
5685  chan = p->channel;
5686 #if defined(HAVE_PRI_SERVICE_MESSAGES)
5687  {
5688  char db_chan_name[20];
5689  char db_answer[5];
5690  char state;
5691  int why = -1;
5692 
5693  snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, p->span, chan);
5694  if (!ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) {
5695  sscanf(db_answer, "%1c:%30d", &state, &why);
5696  }
5697  if (!why) {
5698  /* SRVST persistence is not required */
5699  ast_db_del(db_chan_name, SRVST_DBKEY);
5700  }
5701  }
5702 #endif /* defined(HAVE_PRI_SERVICE_MESSAGES) */
5703  /* Free associated memory */
5704  destroy_dahdi_pvt(p);
5705  ast_verb(3, "Unregistered channel %d\n", chan);
5706  }
5707  ifcount = 0;
5709 
5710 #if defined(HAVE_PRI)
5711  /* Destroy all of the no B channel interface lists */
5712  for (span = 0; span < NUM_SPANS; ++span) {
5713  if (!pris[span].dchannels[0]) {
5714  break;
5715  }
5716  pri = &pris[span].pri;
5717  ast_mutex_lock(&pri->lock);
5718  while (pri->no_b_chan_iflist) {
5719  p = pri->no_b_chan_iflist;
5720 
5721  /* Free associated memory */
5722  destroy_dahdi_pvt(p);
5723  }
5724  ast_mutex_unlock(&pri->lock);
5725  }
5726 #endif /* defined(HAVE_PRI) */
5727 }
5728 
5729 #if defined(HAVE_PRI)
5730 static char *dahdi_send_keypad_facility_app = "DAHDISendKeypadFacility";
5731 
5732 static int dahdi_send_keypad_facility_exec(struct ast_channel *chan, const char *digits)
5733 {
5734  /* Data will be our digit string */
5735  struct dahdi_pvt *p;
5736 
5737  if (ast_strlen_zero(digits)) {
5738  ast_debug(1, "No digit string sent to application!\n");
5739  return -1;
5740  }
5741 
5742  p = (struct dahdi_pvt *)ast_channel_tech_pvt(chan);
5743 
5744  if (!p) {
5745  ast_debug(1, "Unable to find technology private\n");
5746  return -1;
5747  }
5748 
5750 
5751  return 0;
5752 }
5753 #endif /* defined(HAVE_PRI) */
5754 
5755 #if defined(HAVE_PRI)
5756 #if defined(HAVE_PRI_PROG_W_CAUSE)
5757 static char *dahdi_send_callrerouting_facility_app = "DAHDISendCallreroutingFacility";
5758 
5759 static int dahdi_send_callrerouting_facility_exec(struct ast_channel *chan, const char *data)
5760 {
5761  /* Data will be our digit string */
5762  struct dahdi_pvt *pvt;
5763  char *parse;
5764  int res;
5766  AST_APP_ARG(destination);
5767  AST_APP_ARG(original);
5768  AST_APP_ARG(reason);
5769  );
5770 
5771  if (ast_strlen_zero(data)) {
5772  ast_debug(1, "No data sent to application!\n");
5773  return -1;
5774  }
5775  if (ast_channel_tech(chan) != &dahdi_tech) {
5776  ast_debug(1, "Only DAHDI technology accepted!\n");
5777  return -1;
5778  }
5779  pvt = (struct dahdi_pvt *) ast_channel_tech_pvt(chan);
5780  if (!pvt) {
5781  ast_debug(1, "Unable to find technology private\n");
5782  return -1;
5783  }
5784  switch (pvt->sig) {
5786  break;
5787  default:
5788  ast_debug(1, "callrerouting attempted on non-ISDN channel %s\n",
5789  ast_channel_name(chan));
5790  return -1;
5791  }
5792 
5793  parse = ast_strdupa(data);
5794  AST_STANDARD_APP_ARGS(args, parse);
5795 
5796  if (ast_strlen_zero(args.destination)) {
5797  ast_log(LOG_WARNING, "callrerouting facility requires at least destination number argument\n");
5798  return -1;
5799  }
5800 
5801  if (ast_strlen_zero(args.original)) {
5802  ast_log(LOG_WARNING, "Callrerouting Facility without original called number argument\n");
5803  args.original = NULL;
5804  }
5805 
5806  if (ast_strlen_zero(args.reason)) {
5807  ast_log(LOG_NOTICE, "Callrerouting Facility without diversion reason argument, defaulting to unknown\n");
5808  args.reason = NULL;
5809  }
5810 
5812  args.destination, args.original, args.reason);
5813  if (!res) {
5814  /*
5815  * Wait up to 5 seconds for a reply before hanging up this call
5816  * leg if the peer does not disconnect first.
5817  */
5818  ast_safe_sleep(chan, 5000);
5819  }
5820 
5821  return -1;
5822 }
5823 #endif /* defined(HAVE_PRI_PROG_W_CAUSE) */
5824 #endif /* defined(HAVE_PRI) */
5825 
5826 #if defined(HAVE_OPENR2)
5827 static const char * const dahdi_accept_r2_call_app = "DAHDIAcceptR2Call";
5828 
5829 static int dahdi_accept_r2_call_exec(struct ast_channel *chan, const char *data)
5830 {
5831  /* data is whether to accept with charge or no charge */
5832  openr2_call_mode_t accept_mode;
5833  int res, timeout, maxloops;
5834  struct ast_frame *f;
5835  struct dahdi_pvt *p;
5836  char *parse;
5838  AST_APP_ARG(charge);
5839  );
5840 
5841  if (ast_strlen_zero(data)) {
5842  ast_debug(1, "No data sent to application!\n");
5843  return -1;
5844  }
5845 
5846  if (ast_channel_tech(chan) != &dahdi_tech) {
5847  ast_debug(1, "Only DAHDI technology accepted!\n");
5848  return -1;
5849  }
5850 
5851  p = (struct dahdi_pvt *)ast_channel_tech_pvt(chan);
5852  if (!p) {
5853  ast_debug(1, "Unable to find technology private!\n");
5854  return -1;
5855  }
5856 
5857  parse = ast_strdupa(data);
5858  AST_STANDARD_APP_ARGS(args, parse);
5859 
5860  if (ast_strlen_zero(args.charge)) {
5861  ast_log(LOG_WARNING, "DAHDIAcceptR2Call requires 'yes' or 'no' for the charge parameter\n");
5862  return -1;
5863  }
5864 
5865  ast_mutex_lock(&p->lock);
5866  if (!p->mfcr2 || !p->mfcr2call) {
5867  ast_mutex_unlock(&p->lock);
5868  ast_debug(1, "Channel %s does not seems to be an R2 active channel!\n", ast_channel_name(chan));
5869  return -1;
5870  }
5871 
5872  if (p->mfcr2_call_accepted) {
5873  ast_mutex_unlock(&p->lock);
5874  ast_debug(1, "MFC/R2 call already accepted on channel %s!\n", ast_channel_name(chan));
5875  return 0;
5876  }
5877  accept_mode = ast_true(args.charge) ? OR2_CALL_WITH_CHARGE : OR2_CALL_NO_CHARGE;
5878  if (openr2_chan_accept_call(p->r2chan, accept_mode)) {
5879  ast_mutex_unlock(&p->lock);
5880  ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n");
5881  return -1;
5882  }
5883  ast_mutex_unlock(&p->lock);
5884 
5885  res = 0;
5886  timeout = 100;
5887  maxloops = 50; /* wait up to 5 seconds */
5888  /* we need to read() until the call is accepted */
5889  while (maxloops > 0) {
5890  maxloops--;
5891  if (ast_check_hangup(chan)) {
5892  break;
5893  }
5894  res = ast_waitfor(chan, timeout);
5895  if (res < 0) {
5896  ast_debug(1, "ast_waitfor failed on channel %s, going out ...\n", ast_channel_name(chan));
5897  res = -1;
5898  break;
5899  }
5900  if (res == 0) {
5901  continue;
5902  }
5903  res = 0;
5904  f = ast_read(chan);
5905  if (!f) {
5906  ast_debug(1, "No frame read on channel %s, going out ...\n", ast_channel_name(chan));
5907  res = -1;
5908  break;
5909  }
5911  ast_debug(1, "Got HANGUP frame on channel %s, going out ...\n", ast_channel_name(chan));
5912  ast_frfree(f);
5913  res = -1;
5914  break;
5915  }
5916  ast_frfree(f);
5917  ast_mutex_lock(&p->lock);
5918  if (p->mfcr2_call_accepted) {
5919  ast_mutex_unlock(&p->lock);
5920  ast_debug(1, "Accepted MFC/R2 call!\n");
5921  break;
5922  }
5923  ast_mutex_unlock(&p->lock);
5924  }
5925  if (res == -1) {
5926  ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n");
5927  }
5928  return res;
5929 }
5930 
5931 static openr2_call_disconnect_cause_t dahdi_ast_cause_to_r2_cause(int cause)
5932 {
5933  openr2_call_disconnect_cause_t r2cause = OR2_CAUSE_NORMAL_CLEARING;
5934  switch (cause) {
5935  case AST_CAUSE_USER_BUSY:
5937  case AST_CAUSE_INTERWORKING: /* I don't know wtf is this but is used sometimes when ekiga rejects a call */
5938  r2cause = OR2_CAUSE_BUSY_NUMBER;
5939  break;
5940 
5943  r2cause = OR2_CAUSE_NETWORK_CONGESTION;
5944  break;
5945 
5946  case AST_CAUSE_UNALLOCATED:
5947  r2cause = OR2_CAUSE_UNALLOCATED_NUMBER;
5948  break;
5949 
5952  r2cause = OR2_CAUSE_OUT_OF_ORDER;
5953  break;
5954 
5955  case AST_CAUSE_NO_ANSWER:
5957  r2cause = OR2_CAUSE_NO_ANSWER;
5958  break;
5959 
5960  default:
5961  r2cause = OR2_CAUSE_NORMAL_CLEARING;
5962  break;
5963  }
5964  ast_debug(1, "ast cause %d resulted in openr2 cause %d/%s\n",
5965  cause, r2cause, openr2_proto_get_disconnect_string(r2cause));
5966  return r2cause;
5967 }
5968 #endif
5969 
5970 static int revert_fax_buffers(struct dahdi_pvt *p, struct ast_channel *ast)
5971 {
5972  if (p->bufferoverrideinuse) {
5973  /* faxbuffers are in use, revert them */
5974  struct dahdi_bufferinfo bi = {
5975  .txbufpolicy = p->buf_policy,
5976  .rxbufpolicy = p->buf_policy,
5977  .bufsize = p->bufsize,
5978  .numbufs = p->buf_no
5979  };
5980  int bpres;
5981 
5982  if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
5983  ast_log(LOG_WARNING, "Channel '%s' unable to revert buffer policy: %s\n", ast_channel_name(ast), strerror(errno));
5984  }
5985  p->bufferoverrideinuse = 0;
5986  return bpres;
5987  }
5988 
5989  return -1;
5990 }
5991 
5992 static int dahdi_hangup(struct ast_channel *ast)
5993 {
5994  int res = 0;
5995  int idx,x;
5996  int law;
5997  /*static int restore_gains(struct dahdi_pvt *p);*/
5998  struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
5999  struct dahdi_params par;
6000 
6001  ast_debug(1, "dahdi_hangup(%s)\n", ast_channel_name(ast));
6002  if (!ast_channel_tech_pvt(ast)) {
6003  ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
6004  return 0;
6005  }
6006 
6007  ast_mutex_lock(&p->lock);
6008  p->exten[0] = '\0';
6009  if (dahdi_analog_lib_handles(p->sig, p->radio, p->oprmode)) {
6010  dahdi_confmute(p, 0);
6011  restore_gains(p);
6012  p->ignoredtmf = 0;
6013  p->waitingfordt.tv_sec = 0;
6014 
6015  res = analog_hangup(p->sig_pvt, ast);
6016  revert_fax_buffers(p, ast);
6017 
6018  goto hangup_out;
6019  } else {
6020  p->cid_num[0] = '\0';
6021  p->cid_name[0] = '\0';
6022  p->cid_subaddr[0] = '\0';
6023  }
6024 
6025 #if defined(HAVE_PRI)
6026  if (dahdi_sig_pri_lib_handles(p->sig)) {
6027  x = 1;
6028  ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
6029 
6030  dahdi_confmute(p, 0);
6031  p->muting = 0;
6032  restore_gains(p);
6033  if (p->dsp) {
6034  ast_dsp_free(p->dsp);
6035  p->dsp = NULL;
6036  }
6037  p->ignoredtmf = 0;
6038 
6039  /* Real channel, do some fixup */
6040  p->subs[SUB_REAL].owner = NULL;
6041  p->subs[SUB_REAL].needbusy = 0;
6042  dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
6043 
6044  p->owner = NULL;
6045  p->cid_tag[0] = '\0';
6046  p->ringt = 0;/* Probably not used in this mode. Reset anyway. */
6047  p->distinctivering = 0;/* Probably not used in this mode. Reset anyway. */
6048  p->confirmanswer = 0;/* Probably not used in this mode. Reset anyway. */
6049  p->outgoing = 0;
6050  p->digital = 0;
6051  p->faxhandled = 0;
6052  p->pulsedial = 0;/* Probably not used in this mode. Reset anyway. */
6053 
6054  revert_fax_buffers(p, ast);
6055 
6056  p->law = p->law_default;
6057  law = p->law_default;
6058  res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
6059  if (res < 0) {
6060  ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n",
6061  p->channel, strerror(errno));
6062  }
6063 
6064  sig_pri_hangup(p->sig_pvt, ast);
6065 
6066  tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
6067  dahdi_ec_disable(p);
6068 
6069  x = 0;
6070  ast_channel_setoption(ast, AST_OPTION_TDD, &x, sizeof(char), 0);
6071  p->didtdd = 0;/* Probably not used in this mode. Reset anyway. */
6072 
6073  p->rdnis[0] = '\0';
6074  dahdi_conf_update(p);
6075  reset_conf(p);
6076 
6077  /* Restore data mode */
6078  x = 0;
6079  ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
6080 
6081  if (num_restart_pending == 0) {
6082  restart_monitor();
6083  }
6084  goto hangup_out;
6085  }
6086 #endif /* defined(HAVE_PRI) */
6087 
6088 #if defined(HAVE_SS7)
6089  if (p->sig == SIG_SS7) {
6090  x = 1;
6091  ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
6092 
6093  dahdi_confmute(p, 0);
6094  p->muting = 0;
6095  restore_gains(p);
6096  if (p->dsp) {
6097  ast_dsp_free(p->dsp);
6098  p->dsp = NULL;
6099  }
6100  p->ignoredtmf = 0;
6101 
6102  /* Real channel, do some fixup */
6103  p->subs[SUB_REAL].owner = NULL;
6104  p->subs[SUB_REAL].needbusy = 0;
6105  dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
6106 
6107  p->owner = NULL;
6108  p->ringt = 0;/* Probably not used in this mode. Reset anyway. */
6109  p->distinctivering = 0;/* Probably not used in this mode. Reset anyway. */
6110  p->confirmanswer = 0;/* Probably not used in this mode. Reset anyway. */
6111  p->outgoing = 0;
6112  p->digital = 0;
6113  p->faxhandled = 0;
6114  p->pulsedial = 0;/* Probably not used in this mode. Reset anyway. */
6115 
6116  revert_fax_buffers(p, ast);
6117 
6118  p->law = p->law_default;
6119  law = p->law_default;
6120  res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
6121  if (res < 0) {
6122  ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n",
6123  p->channel, strerror(errno));
6124  }
6125 
6126  sig_ss7_hangup(p->sig_pvt, ast);
6127 
6128  tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
6129  dahdi_ec_disable(p);
6130 
6131  x = 0;
6132  ast_channel_setoption(ast, AST_OPTION_TDD, &x, sizeof(char), 0);
6133  p->didtdd = 0;/* Probably not used in this mode. Reset anyway. */
6134 
6135  dahdi_conf_update(p);
6136  reset_conf(p);
6137 
6138  /* Restore data mode */
6139  x = 0;
6140  ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
6141 
6142  if (num_restart_pending == 0) {
6143  restart_monitor();
6144  }
6145  goto hangup_out;
6146  }
6147 #endif /* defined(HAVE_SS7) */
6148 
6149  idx = dahdi_get_index(ast, p, 1);
6150 
6151  dahdi_confmute(p, 0);
6152  p->muting = 0;
6153  restore_gains(p);
6154  if (p->origcid_num) {
6155  ast_copy_string(p->cid_num, p->origcid_num, sizeof(p->cid_num));
6156  ast_free(p->origcid_num);
6157  p->origcid_num = NULL;
6158  }
6159  if (p->origcid_name) {
6160  ast_copy_string(p->cid_name, p->origcid_name, sizeof(p->cid_name));
6161  ast_free(p->origcid_name);
6162  p->origcid_name = NULL;
6163  }
6164  if (p->dsp)
6166 
6167  ast_debug(1, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n",
6168  p->channel, idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
6169  p->ignoredtmf = 0;
6170 
6171  if (idx > -1) {
6172  /* Real channel, do some fixup */
6173  p->subs[idx].owner = NULL;
6174  p->subs[idx].needanswer = 0;
6175  p->subs[idx].needflash = 0;
6176  p->subs[idx].needringing = 0;
6177  p->subs[idx].needbusy = 0;
6178  p->subs[idx].needcongestion = 0;
6179  p->subs[idx].linear = 0;
6180  p->polarity = POLARITY_IDLE;
6181  dahdi_setlinear(p->subs[idx].dfd, 0);
6182  if (idx == SUB_REAL) {
6183  if ((p->subs[SUB_CALLWAIT].dfd > -1) && (p->subs[SUB_THREEWAY].dfd > -1)) {
6184  ast_debug(1, "Normal call hung up with both three way call and a call waiting call in place?\n");
6185  if (p->subs[SUB_CALLWAIT].inthreeway) {
6186  /* We had flipped over to answer a callwait and now it's gone */
6187  ast_debug(1, "We were flipped over to the callwait, moving back and unowning.\n");
6188  /* Move to the call-wait, but un-own us until they flip back. */
6191  p->owner = NULL;
6192  } else {
6193  /* The three way hung up, but we still have a call wait */
6194  ast_debug(1, "We were in the threeway and have a callwait still. Ditching the threeway.\n");
6197  if (p->subs[SUB_REAL].inthreeway) {
6198  /* This was part of a three way call. Immediately make way for
6199  another call */
6200  ast_debug(1, "Call was complete, setting owner to former third call\n");
6201  p->owner = p->subs[SUB_REAL].owner;
6202  } else {
6203  /* This call hasn't been completed yet... Set owner to NULL */
6204  ast_debug(1, "Call was incomplete, setting owner to NULL\n");
6205  p->owner = NULL;
6206  }
6207  p->subs[SUB_REAL].inthreeway = 0;
6208  }
6209  } else if (p->subs[SUB_CALLWAIT].dfd > -1) {
6210  /* Move to the call-wait and switch back to them. */
6213  p->owner = p->subs[SUB_REAL].owner;
6215  p->subs[SUB_REAL].needanswer = 1;
6217  } else if (p->subs[SUB_THREEWAY].dfd > -1) {
6220  if (p->subs[SUB_REAL].inthreeway) {
6221  /* This was part of a three way call. Immediately make way for
6222  another call */
6223  ast_debug(1, "Call was complete, setting owner to former third call\n");
6224  p->owner = p->subs[SUB_REAL].owner;
6225  } else {
6226  /* This call hasn't been completed yet... Set owner to NULL */
6227  ast_debug(1, "Call was incomplete, setting owner to NULL\n");
6228  p->owner = NULL;
6229  }
6230  p->subs[SUB_REAL].inthreeway = 0;
6231  }
6232  } else if (idx == SUB_CALLWAIT) {
6233  /* Ditch the holding callwait call, and immediately make it availabe */
6234  if (p->subs[SUB_CALLWAIT].inthreeway) {
6235  /* This is actually part of a three way, placed on hold. Place the third part
6236  on music on hold now */
6237  if (p->subs[SUB_THREEWAY].owner) {
6239  }
6240  p->subs[SUB_THREEWAY].inthreeway = 0;
6241  /* Make it the call wait now */
6244  } else
6246  } else if (idx == SUB_THREEWAY) {
6247  if (p->subs[SUB_CALLWAIT].inthreeway) {
6248  /* The other party of the three way call is currently in a call-wait state.
6249  Start music on hold for them, and take the main guy out of the third call */
6250  if (p->subs[SUB_CALLWAIT].owner) {
6252  }
6253  p->subs[SUB_CALLWAIT].inthreeway = 0;
6254  }
6255  p->subs[SUB_REAL].inthreeway = 0;
6256  /* If this was part of a three way call index, let us make
6257  another three way call */
6259  } else {
6260  /* This wasn't any sort of call, but how are we an index? */
6261  ast_log(LOG_WARNING, "Index found but not any type of call?\n");
6262  }
6263  }
6264 
6265  if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) {
6266  p->owner = NULL;
6267  p->ringt = 0;
6268  p->distinctivering = 0;
6269  p->confirmanswer = 0;
6270  p->outgoing = 0;
6271  p->digital = 0;
6272  p->faxhandled = 0;
6273  p->pulsedial = 0;
6274  if (p->dsp) {
6275  ast_dsp_free(p->dsp);
6276  p->dsp = NULL;
6277  }
6278 
6279  revert_fax_buffers(p, ast);
6280 
6281  p->law = p->law_default;
6282  law = p->law_default;
6283  res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
6284  if (res < 0)
6285  ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
6286  /* Perform low level hangup if no owner left */
6287 #ifdef HAVE_OPENR2
6288  if (p->mfcr2 && p->mfcr2call && openr2_chan_get_direction(p->r2chan) != OR2_DIR_STOPPED) {
6289  ast_debug(1, "disconnecting MFC/R2 call on chan %d\n", p->channel);
6290  /* If it's an incoming call, check the mfcr2_forced_release setting */
6291  if (openr2_chan_get_direction(p->r2chan) == OR2_DIR_BACKWARD && p->mfcr2_forced_release) {
6292  dahdi_r2_disconnect_call(p, OR2_CAUSE_FORCED_RELEASE);
6293  } else {
6294  const char *r2causestr = pbx_builtin_getvar_helper(ast, "MFCR2_CAUSE");
6295  int r2cause_user = r2causestr ? atoi(r2causestr) : 0;
6296  openr2_call_disconnect_cause_t r2cause = r2cause_user ? dahdi_ast_cause_to_r2_cause(r2cause_user)
6297  : dahdi_ast_cause_to_r2_cause(ast_channel_hangupcause(ast));
6298  dahdi_r2_disconnect_call(p, r2cause);
6299  }
6300  } else if (p->mfcr2call) {
6301  ast_debug(1, "Clearing call request on channel %d\n", p->channel);
6302  /* since ast_request() was called but not ast_call() we have not yet dialed
6303  and the openr2 stack will not call on_call_end callback, we need to unset
6304  the mfcr2call flag and bump the monitor count so the monitor thread can take
6305  care of this channel events from now on */
6306  p->mfcr2call = 0;
6307  }
6308 #endif
6309  switch (p->sig) {
6310  case SIG_SS7:
6311  case SIG_MFCR2:
6313  case 0:
6314  break;
6315  default:
6316  res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
6317  break;
6318  }
6319  if (res < 0) {
6320  ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast_channel_name(ast));
6321  }
6322  switch (p->sig) {
6323  case SIG_FXOGS:
6324  case SIG_FXOLS:
6325  case SIG_FXOKS:
6326  memset(&par, 0, sizeof(par));
6327  res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
6328  if (!res) {
6329  struct analog_pvt *analog_p = p->sig_pvt;
6330 #if 0
6331  ast_debug(1, "Hanging up channel %d, offhook = %d\n", p->channel, par.rxisoffhook);
6332 #endif
6333  /* If they're off hook, try playing congestion */
6334  if ((par.rxisoffhook) && (!(p->radio || (p->oprmode < 0))))
6335  tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
6336  else
6337  tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
6338  analog_p->fxsoffhookstate = par.rxisoffhook;
6339  }
6340  break;
6341  case SIG_FXSGS:
6342  case SIG_FXSLS:
6343  case SIG_FXSKS:
6344  /* Make sure we're not made available for at least two seconds assuming
6345  we were actually used for an inbound or outbound call. */
6346  if (ast_channel_state(ast) != AST_STATE_RESERVED) {
6347  time(&p->guardtime);
6348  p->guardtime += 2;
6349  }
6350  break;
6351  default:
6352  tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
6353  break;
6354  }
6355  if (p->sig)
6356  dahdi_ec_disable(p);
6357  x = 0;
6358  ast_channel_setoption(ast,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0);
6359  ast_channel_setoption(ast,AST_OPTION_TDD,&x,sizeof(char),0);
6360  p->didtdd = 0;
6361  p->callwaitcas = 0;
6362  p->callwaiting = p->permcallwaiting;
6364  p->waitingfordt.tv_sec = 0;
6365  p->dialing = 0;
6366  p->rdnis[0] = '\0';
6367  dahdi_conf_update(p);
6368  reset_conf(p);
6369  /* Restore data mode */
6370  switch (p->sig) {
6372  case SIG_SS7:
6373  x = 0;
6374  ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
6375  break;
6376  default:
6377  break;
6378  }
6379  if (num_restart_pending == 0)
6380  restart_monitor();
6381  }
6382 
6383  p->callwaitingrepeat = 0;
6384  p->cidcwexpire = 0;
6385  p->cid_suppress_expire = 0;
6386  p->oprmode = 0;
6387 hangup_out:
6389  ast_free(p->cidspill);
6390  p->cidspill = NULL;
6391 
6392  ast_mutex_unlock(&p->lock);
6393  ast_verb(3, "Hungup '%s'\n", ast_channel_name(ast));
6394 
6396  if (p->restartpending) {
6398  }
6399 
6400  if (p->destroy) {
6401  destroy_channel(p, 0);
6402  }
6404 
6406  return 0;
6407 }
6408 
6409 static int dahdi_answer(struct ast_channel *ast)
6410 {
6411  struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
6412  int res = 0;
6413  int idx;
6414  ast_setstate(ast, AST_STATE_UP);/*! \todo XXX this is redundantly set by the analog and PRI submodules! */
6415  ast_mutex_lock(&p->lock);
6416  idx = dahdi_get_index(ast, p, 0);
6417  if (idx < 0)
6418  idx = SUB_REAL;
6419  /* nothing to do if a radio channel */
6420  if ((p->radio || (p->oprmode < 0))) {
6421  ast_mutex_unlock(&p->lock);
6422  return 0;
6423  }
6424 
6425  if (dahdi_analog_lib_handles(p->sig, p->radio, p->oprmode)) {
6426  res = analog_answer(p->sig_pvt, ast);
6427  ast_mutex_unlock(&p->lock);
6428  return res;
6429  }
6430 
6431  switch (p->sig) {
6432 #if defined(HAVE_PRI)
6434  res = sig_pri_answer(p->sig_pvt, ast);
6435  break;
6436 #endif /* defined(HAVE_PRI) */
6437 #if defined(HAVE_SS7)
6438  case SIG_SS7:
6439  res = sig_ss7_answer(p->sig_pvt, ast);
6440  break;
6441 #endif /* defined(HAVE_SS7) */
6442 #ifdef HAVE_OPENR2
6443  case SIG_MFCR2:
6444  if (!p->mfcr2_call_accepted) {
6445  /* The call was not accepted on offer nor the user, so it must be accepted now before answering,
6446  openr2_chan_answer_call will be called when the callback on_call_accepted is executed */
6447  p->mfcr2_answer_pending = 1;
6448  if (p->mfcr2_charge_calls) {
6449  ast_debug(1, "Accepting MFC/R2 call with charge before answering on chan %d\n", p->channel);
6450  openr2_chan_accept_call(p->r2chan, OR2_CALL_WITH_CHARGE);
6451  } else {
6452  ast_debug(1, "Accepting MFC/R2 call with no charge before answering on chan %d\n", p->channel);
6453  openr2_chan_accept_call(p->r2chan, OR2_CALL_NO_CHARGE);
6454  }
6455  } else {
6456  ast_debug(1, "Answering MFC/R2 call on chan %d\n", p->channel);
6457  dahdi_r2_answer(p);
6458  }
6459  break;
6460 #endif
6461  case 0:
6462  ast_mutex_unlock(&p->lock);
6463  return 0;
6464  default:
6465  ast_log(LOG_WARNING, "Don't know how to answer signalling %d (channel %d)\n", p->sig, p->channel);
6466  res = -1;
6467  break;
6468  }
6469  ast_mutex_unlock(&p->lock);
6470  return res;
6471 }
6472 
6474 {
6475  int val = 0;
6476 
6477  p->ignoredtmf = 1;
6478 
6479  ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
6480 
6481  if (!p->hardwaredtmf && p->dsp) {
6484  }
6485 }
6486 
6488 {
6489  int val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
6490 
6491  if (p->channel == CHAN_PSEUDO)
6492  return;
6493 
6494  p->ignoredtmf = 0;
6495 
6496  ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
6497 
6498  if (!p->hardwaredtmf && p->dsp) {
6501  }
6502 }
6503 
6504 static int dahdi_queryoption(struct ast_channel *chan, int option, void *data, int *datalen)
6505 {
6506  char *cp;
6507  struct dahdi_pvt *p = ast_channel_tech_pvt(chan);
6508 
6509  /* all supported options require data */
6510  if (!p || !data || (*datalen < 1)) {
6511  errno = EINVAL;
6512  return -1;
6513  }
6514 
6515  switch (option) {
6517  cp = (char *) data;
6518  *cp = p->ignoredtmf ? 0 : 1;
6519  ast_debug(1, "Reporting digit detection %sabled on %s\n", *cp ? "en" : "dis", ast_channel_name(chan));
6520  break;
6521  case AST_OPTION_FAX_DETECT:
6522  cp = (char *) data;
6523  *cp = (p->dsp_features & DSP_FEATURE_FAX_DETECT) ? 0 : 1;
6524  ast_debug(1, "Reporting fax tone detection %sabled on %s\n", *cp ? "en" : "dis", ast_channel_name(chan));
6525  break;
6527 #if defined(HAVE_PRI)
6528 #if defined(HAVE_PRI_CCSS)
6529  if (dahdi_sig_pri_lib_handles(p->sig)) {
6530  ast_copy_string((char *) data, dahdi_pri_cc_type, *datalen);
6531  break;
6532  }
6533 #endif /* defined(HAVE_PRI_CCSS) */
6534 #endif /* defined(HAVE_PRI) */
6535  return -1;
6536  default:
6537  return -1;
6538  }
6539 
6540  errno = 0;
6541 
6542  return 0;
6543 }
6544 
6545 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen)
6546 {
6547  char *cp;
6548  signed char *scp;
6549  int x;
6550  int idx;
6551  struct dahdi_pvt *p = ast_channel_tech_pvt(chan), *pp;
6552  struct oprmode *oprmode;
6553 
6554 
6555  /* all supported options require data */
6556  if (!p || !data || (datalen < 1)) {
6557  errno = EINVAL;
6558  return -1;
6559  }
6560 
6561  switch (option) {
6562  case AST_OPTION_TXGAIN:
6563  scp = (signed char *) data;
6564  idx = dahdi_get_index(chan, p, 0);
6565  if (idx < 0) {
6566  ast_log(LOG_WARNING, "No index in TXGAIN?\n");
6567  return -1;
6568  }
6569  ast_debug(1, "Setting actual tx gain on %s to %f\n", ast_channel_name(chan), p->txgain + (float) *scp);
6570  return set_actual_txgain(p->subs[idx].dfd, p->txgain + (float) *scp, p->txdrc, p->law);
6571  case AST_OPTION_RXGAIN:
6572  scp = (signed char *) data;
6573  idx = dahdi_get_index(chan, p, 0);
6574  if (idx < 0) {
6575  ast_log(LOG_WARNING, "No index in RXGAIN?\n");
6576  return -1;
6577  }
6578  ast_debug(1, "Setting actual rx gain on %s to %f\n", ast_channel_name(chan), p->rxgain + (float) *scp);
6579  return set_actual_rxgain(p->subs[idx].dfd, p->rxgain + (float) *scp, p->rxdrc, p->law);
6581  if (!p->dsp)
6582  break;
6583  cp = (char *) data;
6584  switch (*cp) {
6585  case 1:
6586  ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",ast_channel_name(chan));
6587  ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | p->dtmfrelax); /* set mute mode if desired */
6588  break;
6589  case 2:
6590  ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",ast_channel_name(chan));
6591  ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX | p->dtmfrelax); /* set mute mode if desired */
6592  break;
6593  default:
6594  ast_debug(1, "Set option TONE VERIFY, mode: OFF(0) on %s\n",ast_channel_name(chan));
6595  ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax); /* set mute mode if desired */
6596  break;
6597  }
6598  break;
6599  case AST_OPTION_TDD:
6600  /* turn on or off TDD */
6601  cp = (char *) data;
6602  p->mate = 0;
6603  if (!*cp) { /* turn it off */
6604  ast_debug(1, "Set option TDD MODE, value: OFF(0) on %s\n",ast_channel_name(chan));
6605  if (p->tdd)
6606  tdd_free(p->tdd);
6607  p->tdd = 0;
6608  break;
6609  }
6610  ast_debug(1, "Set option TDD MODE, value: %s(%d) on %s\n",
6611  (*cp == 2) ? "MATE" : "ON", (int) *cp, ast_channel_name(chan));
6612  dahdi_ec_disable(p);
6613  /* otherwise, turn it on */
6614  if (!p->didtdd) { /* if havent done it yet */
6615  unsigned char mybuf[41000];/*! \todo XXX This is an abuse of the stack!! */
6616  unsigned char *buf;
6617  int size, res, fd, len;
6618  struct pollfd fds[1];
6619 
6620  buf = mybuf;
6621  memset(buf, 0x7f, sizeof(mybuf)); /* set to silence */
6622  ast_tdd_gen_ecdisa(buf + 16000, 16000); /* put in tone */
6623  len = 40000;
6624  idx = dahdi_get_index(chan, p, 0);
6625  if (idx < 0) {
6626  ast_log(LOG_WARNING, "No index in TDD?\n");
6627  return -1;
6628  }
6629  fd = p->subs[idx].dfd;
6630  while (len) {
6631  if (ast_check_hangup(chan))
6632  return -1;
6633  size = len;
6634  if (size > READ_SIZE)
6635  size = READ_SIZE;
6636  fds[0].fd = fd;
6637  fds[0].events = POLLPRI | POLLOUT;
6638  fds[0].revents = 0;
6639  res = poll(fds, 1, -1);
6640  if (!res) {
6641  ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
6642  continue;
6643  }
6644  /* if got exception */
6645  if (fds[0].revents & POLLPRI)
6646  return -1;
6647  if (!(fds[0].revents & POLLOUT)) {
6648  ast_debug(1, "write fd not ready on channel %d\n", p->channel);
6649  continue;
6650  }
6651  res = write(fd, buf, size);
6652  if (res != size) {
6653  if (res == -1) return -1;
6654  ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
6655  break;
6656  }
6657  len -= size;
6658  buf += size;
6659  }
6660  p->didtdd = 1; /* set to have done it now */
6661  }
6662  if (*cp == 2) { /* Mate mode */
6663  if (p->tdd)
6664  tdd_free(p->tdd);
6665  p->tdd = 0;
6666  p->mate = 1;
6667  break;
6668  }
6669  if (!p->tdd) { /* if we don't have one yet */
6670  p->tdd = tdd_new(); /* allocate one */
6671  }
6672  break;
6673  case AST_OPTION_RELAXDTMF: /* Relax DTMF decoding (or not) */
6674  if (!p->dsp)
6675  break;
6676  cp = (char *) data;
6677  ast_debug(1, "Set option RELAX DTMF, value: %s(%d) on %s\n",
6678  *cp ? "ON" : "OFF", (int) *cp, ast_channel_name(chan));
6680  break;
6681  case AST_OPTION_AUDIO_MODE: /* Set AUDIO mode (or not) */
6682 #if defined(HAVE_PRI)
6684  && ((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
6685  /* PRI nobch pseudo channel. Does not handle ioctl(DAHDI_AUDIOMODE) */
6686  break;
6687  }
6688 #endif /* defined(HAVE_PRI) */
6689 
6690  cp = (char *) data;
6691  if (!*cp) {
6692  ast_debug(1, "Set option AUDIO MODE, value: OFF(0) on %s\n", ast_channel_name(chan));
6693  x = 0;
6694  dahdi_ec_disable(p);
6695  } else {
6696  ast_debug(1, "Set option AUDIO MODE, value: ON(1) on %s\n", ast_channel_name(chan));
6697  x = 1;
6698  }
6699  if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x) == -1)
6700  ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, x, strerror(errno));
6701  break;
6702  case AST_OPTION_OPRMODE: /* Operator services mode */
6703  oprmode = (struct oprmode *) data;
6704  /* We don't support operator mode across technologies */
6705  if (strcasecmp(ast_channel_tech(chan)->type, ast_channel_tech(oprmode->peer)->type)) {
6706  ast_log(LOG_NOTICE, "Operator mode not supported on %s to %s calls.\n",
6707  ast_channel_tech(chan)->type, ast_channel_tech(oprmode->peer)->type);
6708  errno = EINVAL;
6709  return -1;
6710  }
6711  pp = ast_channel_tech_pvt(oprmode->peer);
6712  p->oprmode = pp->oprmode = 0;
6713  /* setup peers */
6714  p->oprpeer = pp;
6715  pp->oprpeer = p;
6716  /* setup modes, if any */
6717  if (oprmode->mode)
6718  {
6719  pp->oprmode = oprmode->mode;
6720  p->oprmode = -oprmode->mode;
6721  }
6722  ast_debug(1, "Set Operator Services mode, value: %d on %s/%s\n",
6723  oprmode->mode, ast_channel_name(chan),ast_channel_name(oprmode->peer));
6724  break;
6725  case AST_OPTION_ECHOCAN:
6726  cp = (char *) data;
6727  if (*cp) {
6728  ast_debug(1, "Enabling echo cancellation on %s\n", ast_channel_name(chan));
6729  dahdi_ec_enable(p);
6730  } else {
6731  ast_debug(1, "Disabling echo cancellation on %s\n", ast_channel_name(chan));
6732  dahdi_ec_disable(p);
6733  }
6734  break;
6736  cp = (char *) data;
6737  ast_debug(1, "%sabling digit detection on %s\n", *cp ? "En" : "Dis", ast_channel_name(chan));
6738  if (*cp) {
6740  } else {
6742  }
6743  break;
6744  case AST_OPTION_FAX_DETECT:
6745  cp = (char *) data;
6746  if (p->dsp) {
6747  ast_debug(1, "%sabling fax tone detection on %s\n", *cp ? "En" : "Dis", ast_channel_name(chan));
6748  if (*cp) {
6750  } else {
6752  }
6754  }
6755  break;
6756  default:
6757  return -1;
6758  }
6759  errno = 0;
6760 
6761  return 0;
6762 }
6763 
6764 static int dahdi_func_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len)
6765 {
6766  struct dahdi_pvt *p = ast_channel_tech_pvt(chan);
6767  int res = 0;
6768 
6769  if (!p) {
6770  /* No private structure! */
6771  *buf = '\0';
6772  return -1;
6773  }
6774 
6775  if (!strcasecmp(data, "rxgain")) {
6776  ast_mutex_lock(&p->lock);
6777  snprintf(buf, len, "%f", p->rxgain);
6778  ast_mutex_unlock(&p->lock);
6779  } else if (!strcasecmp(data, "txgain")) {
6780  ast_mutex_lock(&p->lock);
6781  snprintf(buf, len, "%f", p->txgain);
6782  ast_mutex_unlock(&p->lock);
6783  } else if (!strcasecmp(data, "dahdi_channel")) {
6784  ast_mutex_lock(&p->lock);
6785  snprintf(buf, len, "%d", p->channel);
6786  ast_mutex_unlock(&p->lock);
6787  } else if (!strcasecmp(data, "dahdi_span")) {
6788  ast_mutex_lock(&p->lock);
6789  snprintf(buf, len, "%d", p->span);
6790  ast_mutex_unlock(&p->lock);
6791  } else if (!strcasecmp(data, "dahdi_group")) {
6792  ast_mutex_lock(&p->lock);
6793  snprintf(buf, len, "%llu", p->group);
6794  ast_mutex_unlock(&p->lock);
6795  } else if (!strcasecmp(data, "dahdi_type")) {
6796  ast_mutex_lock(&p->lock);
6797  switch (p->sig) {
6798 #if defined(HAVE_OPENR2)
6799  case SIG_MFCR2:
6800  ast_copy_string(buf, "mfc/r2", len);
6801  break;
6802 #endif /* defined(HAVE_OPENR2) */
6803 #if defined(HAVE_PRI)
6805  ast_copy_string(buf, "pri", len);
6806  break;
6807 #endif /* defined(HAVE_PRI) */
6808  case 0:
6809  ast_copy_string(buf, "pseudo", len);
6810  break;
6811 #if defined(HAVE_SS7)
6812  case SIG_SS7:
6813  ast_copy_string(buf, "ss7", len);
6814  break;
6815 #endif /* defined(HAVE_SS7) */
6816  default:
6817  /* The only thing left is analog ports. */
6818  ast_copy_string(buf, "analog", len);
6819  break;
6820  }
6821  ast_mutex_unlock(&p->lock);
6822 #if defined(HAVE_PRI)
6823 #if defined(HAVE_PRI_REVERSE_CHARGE)
6824  } else if (!strcasecmp(data, "reversecharge")) {
6825  ast_mutex_lock(&p->lock);
6826  switch (p->sig) {
6828  snprintf(buf, len, "%d", ((struct sig_pri_chan *) p->sig_pvt)->reverse_charging_indication);
6829  break;
6830  default:
6831  *buf = '\0';
6832  res = -1;
6833  break;
6834  }
6835  ast_mutex_unlock(&p->lock);
6836 #endif
6837 #if defined(HAVE_PRI_SETUP_KEYPAD)
6838  } else if (!strcasecmp(data, "keypad_digits")) {
6839  ast_mutex_lock(&p->lock);
6840  switch (p->sig) {
6842  ast_copy_string(buf, ((struct sig_pri_chan *) p->sig_pvt)->keypad_digits,
6843  len);
6844  break;
6845  default:
6846  *buf = '\0';
6847  res = -1;
6848  break;
6849  }
6850  ast_mutex_unlock(&p->lock);
6851 #endif /* defined(HAVE_PRI_SETUP_KEYPAD) */
6852  } else if (!strcasecmp(data, "no_media_path")) {
6853  ast_mutex_lock(&p->lock);
6854  switch (p->sig) {
6856  /*
6857  * TRUE if the call is on hold or is call waiting because
6858  * there is no media path available.
6859  */
6860  snprintf(buf, len, "%d", ((struct sig_pri_chan *) p->sig_pvt)->no_b_channel);
6861  break;
6862  default:
6863  *buf = '\0';
6864  res = -1;
6865  break;
6866  }
6867  ast_mutex_unlock(&p->lock);
6868 #endif /* defined(HAVE_PRI) */
6869  } else {
6870  *buf = '\0';
6871  res = -1;
6872  }
6873 
6874  return res;
6875 }
6876 
6877 
6878 static int parse_buffers_policy(const char *parse, int *num_buffers, int *policy)
6879 {
6880  int res;
6881  char policy_str[21] = "";
6882 
6883  if ((res = sscanf(parse, "%30d,%20s", num_buffers, policy_str)) != 2) {
6884  ast_log(LOG_WARNING, "Parsing buffer string '%s' failed.\n", parse);
6885  return 1;
6886  }
6887  if (*num_buffers < 0) {
6888  ast_log(LOG_WARNING, "Invalid buffer count given '%d'.\n", *num_buffers);
6889  return -1;
6890  }
6891  if (!strcasecmp(policy_str, "full")) {
6892  *policy = DAHDI_POLICY_WHEN_FULL;
6893  } else if (!strcasecmp(policy_str, "immediate")) {
6894  *policy = DAHDI_POLICY_IMMEDIATE;
6895 #if defined(HAVE_DAHDI_HALF_FULL)
6896  } else if (!strcasecmp(policy_str, "half")) {
6897  *policy = DAHDI_POLICY_HALF_FULL;
6898 #endif
6899  } else {
6900  ast_log(LOG_WARNING, "Invalid policy name given '%s'.\n", policy_str);
6901  return -1;
6902  }
6903 
6904  return 0;
6905 }
6906 
6907 static int dahdi_func_write(struct ast_channel *chan, const char *function, char *data, const char *value)
6908 {
6909  struct dahdi_pvt *p = ast_channel_tech_pvt(chan);
6910  int res = 0;
6911 
6912  if (!p) {
6913  /* No private structure! */
6914  return -1;
6915  }
6916 
6917  if (!strcasecmp(data, "buffers")) {
6918  int num_bufs, policy;
6919 
6920  if (!(parse_buffers_policy(value, &num_bufs, &policy))) {
6921  struct dahdi_bufferinfo bi = {
6922  .txbufpolicy = policy,
6923  .rxbufpolicy = policy,
6924  .bufsize = p->bufsize,
6925  .numbufs = num_bufs,
6926  };
6927  int bpres;
6928 
6929  if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
6930  ast_log(LOG_WARNING, "Channel '%d' unable to override buffer policy: %s\n", p->channel, strerror(errno));
6931  } else {
6932  p->bufferoverrideinuse = 1;
6933  }
6934  } else {
6935  res = -1;
6936  }
6937  } else if (!strcasecmp(data, "echocan_mode")) {
6938  if (!strcasecmp(value, "on")) {
6939  ast_mutex_lock(&p->lock);
6940  dahdi_ec_enable(p);
6941  ast_mutex_unlock(&p->lock);
6942  } else if (!strcasecmp(value, "off")) {
6943  ast_mutex_lock(&p->lock);
6944  dahdi_ec_disable(p);
6945  ast_mutex_unlock(&p->lock);
6946 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
6947  } else if (!strcasecmp(value, "fax")) {
6948  int blah = 1;
6949 
6950  ast_mutex_lock(&p->lock);
6951  if (!p->echocanon) {
6952  dahdi_ec_enable(p);
6953  }
6954  if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_FAX_MODE, &blah)) {
6955  ast_log(LOG_WARNING, "Unable to place echocan into fax mode on channel %d: %s\n", p->channel, strerror(errno));
6956  }
6957  ast_mutex_unlock(&p->lock);
6958  } else if (!strcasecmp(value, "voice")) {
6959  int blah = 0;
6960 
6961  ast_mutex_lock(&p->lock);
6962  if (!p->echocanon) {
6963  dahdi_ec_enable(p);
6964  }
6965  if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_FAX_MODE, &blah)) {
6966  ast_log(LOG_WARNING, "Unable to place echocan into voice mode on channel %d: %s\n", p->channel, strerror(errno));
6967  }
6968  ast_mutex_unlock(&p->lock);
6969 #endif
6970  } else {
6971  ast_log(LOG_WARNING, "Unsupported value '%s' provided for '%s' item.\n", value, data);
6972  res = -1;
6973  }
6974  } else {
6975  res = -1;
6976  }
6977 
6978  return res;
6979 }
6980 
6981 void dahdi_master_slave_unlink(struct dahdi_pvt *slave, struct dahdi_pvt *master, int needlock)
6982 {
6983  /* Unlink a specific slave or all slaves/masters from a given master */
6984  int x;
6985  int hasslaves;
6986  if (!master)
6987  return;
6988  if (needlock) {
6989  ast_mutex_lock(&master->lock);
6990  if (slave) {
6991  while (ast_mutex_trylock(&slave->lock)) {
6992  DEADLOCK_AVOIDANCE(&master->lock);
6993  }
6994  }
6995  }
6996  hasslaves = 0;
6997  for (x = 0; x < MAX_SLAVES; x++) {
6998  if (master->slaves[x]) {
6999  if (!slave || (master->slaves[x] == slave)) {
7000  /* Take slave out of the conference */
7001  ast_debug(1, "Unlinking slave %d from %d\n", master->slaves[x]->channel, master->channel);
7002  conf_del(master, &master->slaves[x]->subs[SUB_REAL], SUB_REAL);
7003  conf_del(master->slaves[x], &master->subs[SUB_REAL], SUB_REAL);
7004  master->slaves[x]->master = NULL;
7005  master->slaves[x] = NULL;
7006  } else
7007  hasslaves = 1;
7008  }
7009  if (!hasslaves)
7010  master->inconference = 0;
7011  }
7012  if (!slave) {
7013  if (master->master) {
7014  /* Take master out of the conference */
7015  conf_del(master->master, &master->subs[SUB_REAL], SUB_REAL);
7016  conf_del(master, &master->master->subs[SUB_REAL], SUB_REAL);
7017  hasslaves = 0;
7018  for (x = 0; x < MAX_SLAVES; x++) {
7019  if (master->master->slaves[x] == master)
7020  master->master->slaves[x] = NULL;
7021  else if (master->master->slaves[x])
7022  hasslaves = 1;
7023  }
7024  if (!hasslaves)
7025  master->master->inconference = 0;
7026  }
7027  master->master = NULL;
7028  }
7029  dahdi_conf_update(master);
7030  if (needlock) {
7031  if (slave)
7032  ast_mutex_unlock(&slave->lock);
7033  ast_mutex_unlock(&master->lock);
7034  }
7035 }
7036 
7037 void dahdi_master_slave_link(struct dahdi_pvt *slave, struct dahdi_pvt *master)
7038 {
7039  int x;
7040  if (!slave || !master) {
7041  ast_log(LOG_WARNING, "Tried to link to/from NULL??\n");
7042  return;
7043  }
7044  for (x = 0; x < MAX_SLAVES; x++) {
7045  if (!master->slaves[x]) {
7046  master->slaves[x] = slave;
7047  break;
7048  }
7049  }
7050  if (x >= MAX_SLAVES) {
7051  ast_log(LOG_WARNING, "Replacing slave %d with new slave, %d\n", master->slaves[MAX_SLAVES - 1]->channel, slave->channel);
7052  master->slaves[MAX_SLAVES - 1] = slave;
7053  }
7054  if (slave->master)
7055  ast_log(LOG_WARNING, "Replacing master %d with new master, %d\n", slave->master->channel, master->channel);
7056  slave->master = master;
7057 
7058  ast_debug(1, "Making %d slave to master %d at %d\n", slave->channel, master->channel, x);
7059 }
7060 
7061 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
7062 {
7063  struct dahdi_pvt *p = ast_channel_tech_pvt(newchan);
7064  int x;
7065 
7066  ast_mutex_lock(&p->lock);
7067 
7068  ast_debug(1, "New owner for channel %d is %s\n", p->channel, ast_channel_name(newchan));
7069  if (p->owner == oldchan) {
7070  p->owner = newchan;
7071  }
7072  for (x = 0; x < 3; x++) {
7073  if (p->subs[x].owner == oldchan) {
7074  if (!x) {
7076  }
7077  p->subs[x].owner = newchan;
7078  }
7079  }
7080  if (dahdi_analog_lib_handles(p->sig, p->radio, p->oprmode)) {
7081  analog_fixup(oldchan, newchan, p->sig_pvt);
7082 #if defined(HAVE_PRI)
7083  } else if (dahdi_sig_pri_lib_handles(p->sig)) {
7084  sig_pri_fixup(oldchan, newchan, p->sig_pvt);
7085 #endif /* defined(HAVE_PRI) */
7086 #if defined(HAVE_SS7)
7087  } else if (p->sig == SIG_SS7) {
7088  sig_ss7_fixup(oldchan, newchan, p->sig_pvt);
7089 #endif /* defined(HAVE_SS7) */
7090  }
7091  dahdi_conf_update(p);
7092 
7093  ast_mutex_unlock(&p->lock);
7094 
7095  if (ast_channel_state(newchan) == AST_STATE_RINGING) {
7096  dahdi_indicate(newchan, AST_CONTROL_RINGING, NULL, 0);
7097  }
7098  return 0;
7099 }
7100 
7101 static int dahdi_ring_phone(struct dahdi_pvt *p)
7102 {
7103  int x;
7104  int res;
7105  /* Make sure our transmit state is on hook */
7106  x = 0;
7107  x = DAHDI_ONHOOK;
7108  res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
7109  do {
7110  x = DAHDI_RING;
7111  res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
7112  if (res) {
7113  switch (errno) {
7114  case EBUSY:
7115  case EINTR:
7116  /* Wait just in case */
7117  usleep(10000);
7118  continue;
7119  case EINPROGRESS:
7120  res = 0;
7121  break;
7122  default:
7123  ast_log(LOG_WARNING, "Couldn't ring the phone: %s\n", strerror(errno));
7124  res = 0;
7125  }
7126  }
7127  } while (res);
7128  return res;
7129 }
7130 
7131 static void *analog_ss_thread(void *data);
7132 
7133 /*!
7134  * \internal
7135  * \brief Attempt to transfer 3-way call.
7136  *
7137  * \param p DAHDI private structure.
7138  *
7139  * \note On entry these locks are held: real-call, private, 3-way call.
7140  * \note On exit these locks are held: real-call, private.
7141  *
7142  * \retval 0 on success.
7143  * \retval -1 on error.
7144  */
7145 static int attempt_transfer(struct dahdi_pvt *p)
7146 {
7147  struct ast_channel *owner_real;
7148  struct ast_channel *owner_3way;
7149  enum ast_transfer_result xfer_res;
7150  int res = 0;
7151 
7152  owner_real = ast_channel_ref(p->subs[SUB_REAL].owner);
7153  owner_3way = ast_channel_ref(p->subs[SUB_THREEWAY].owner);
7154 
7155  ast_verb(3, "TRANSFERRING %s to %s\n",
7156  ast_channel_name(owner_3way), ast_channel_name(owner_real));
7157 
7158  ast_channel_unlock(owner_real);
7159  ast_channel_unlock(owner_3way);
7160  ast_mutex_unlock(&p->lock);
7161 
7162  xfer_res = ast_bridge_transfer_attended(owner_3way, owner_real);
7163  if (xfer_res != AST_BRIDGE_TRANSFER_SUCCESS) {
7164  ast_softhangup(owner_3way, AST_SOFTHANGUP_DEV);
7165  res = -1;
7166  }
7167 
7168  /* Must leave with these locked. */
7169  ast_channel_lock(owner_real);
7170  ast_mutex_lock(&p->lock);
7171 
7172  ast_channel_unref(owner_real);
7173  ast_channel_unref(owner_3way);
7174 
7175  return res;
7176 }
7177 
7178 static int check_for_conference(struct dahdi_pvt *p)
7179 {
7180  struct dahdi_confinfo ci;
7181  /* Fine if we already have a master, etc */
7182  if (p->master || (p->confno > -1))
7183  return 0;
7184  memset(&ci, 0, sizeof(ci));
7185  if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
7186  ast_log(LOG_WARNING, "Failed to get conference info on channel %d: %s\n", p->channel, strerror(errno));
7187  return 0;
7188  }
7189  /* If we have no master and don't have a confno, then
7190  if we're in a conference, it's probably a MeetMe room or
7191  some such, so don't let us 3-way out! */
7192  if ((p->subs[SUB_REAL].curconf.confno != ci.confno) || (p->subs[SUB_REAL].curconf.confmode != ci.confmode)) {
7193  ast_verb(3, "Avoiding 3-way call when in an external conference\n");
7194  return 1;
7195  }
7196  return 0;
7197 }
7198 
7199 /*! Checks channel for alarms
7200  * \param p a channel to check for alarms.
7201  * \returns the alarms on the span to which the channel belongs, or alarms on
7202  * the channel if no span alarms.
7203  */
7204 static int get_alarms(struct dahdi_pvt *p)
7205 {
7206  int res;
7207  struct dahdi_spaninfo zi;
7208  struct dahdi_params params;
7209 
7210  memset(&zi, 0, sizeof(zi));
7211  zi.spanno = p->span;
7212 
7213  if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SPANSTAT, &zi)) >= 0) {
7214  if (zi.alarms != DAHDI_ALARM_NONE)
7215  return zi.alarms;
7216  } else {
7217  ast_log(LOG_WARNING, "Unable to determine alarm on channel %d: %s\n", p->channel, strerror(errno));
7218  return 0;
7219  }
7220 
7221  /* No alarms on the span. Check for channel alarms. */
7222  memset(&params, 0, sizeof(params));
7223  if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &params)) >= 0)
7224  return params.chan_alarms;
7225 
7226  ast_log(LOG_WARNING, "Unable to determine alarm on channel %d\n", p->channel);
7227 
7228  return DAHDI_ALARM_NONE;
7229 }
7230 
7231 static void dahdi_handle_dtmf(struct ast_channel *ast, int idx, struct ast_frame **dest)
7232 {
7233  struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
7234  struct ast_frame *f = *dest;
7235 
7236  ast_debug(1, "%s DTMF digit: 0x%02X '%c' on %s\n",
7237  f->frametype == AST_FRAME_DTMF_BEGIN ? "Begin" : "End",
7238  (unsigned)f->subclass.integer, f->subclass.integer, ast_channel_name(ast));
7239 
7240  if (p->confirmanswer) {
7241  if (f->frametype == AST_FRAME_DTMF_END) {
7242  ast_debug(1, "Confirm answer on %s!\n", ast_channel_name(ast));
7243  /* Upon receiving a DTMF digit, consider this an answer confirmation instead
7244  of a DTMF digit */
7245  p->subs[idx].f.frametype = AST_FRAME_CONTROL;
7247  /* Reset confirmanswer so DTMF's will behave properly for the duration of the call */
7248  p->confirmanswer = 0;
7249  } else {
7250  p->subs[idx].f.frametype = AST_FRAME_NULL;
7251  p->subs[idx].f.subclass.integer = 0;
7252  }
7253  *dest = &p->subs[idx].f;
7254  } else if (p->callwaitcas) {
7255  if (f->frametype == AST_FRAME_DTMF_END) {
7256  if ((f->subclass.integer == 'A') || (f->subclass.integer == 'D')) {
7257  ast_debug(1, "Got some DTMF, but it's for the CAS\n");
7258  ast_free(p->cidspill);
7259  p->cidspill = NULL;
7260  send_cwcidspill(p);
7261  }
7262  p->callwaitcas = 0;
7263  }
7264  p->subs[idx].f.frametype = AST_FRAME_NULL;
7265  p->subs[idx].f.subclass.integer = 0;
7266  *dest = &p->subs[idx].f;
7267  } else if (f->subclass.integer == 'f') {
7268  if (f->frametype == AST_FRAME_DTMF_END) {
7269  /* Fax tone -- Handle and return NULL */
7270  if ((p->callprogress & CALLPROGRESS_FAX) && !p->faxhandled) {
7271  /* If faxbuffers are configured, use them for the fax transmission */
7272  if (p->usefaxbuffers && !p->bufferoverrideinuse) {
7273  struct dahdi_bufferinfo bi = {
7274  .txbufpolicy = p->faxbuf_policy,
7275  .bufsize = p->bufsize,
7276  .numbufs = p->faxbuf_no
7277  };
7278  int res;
7279 
7280  if ((res = ioctl(p->subs[idx].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
7281  ast_log(LOG_WARNING, "Channel '%s' unable to set buffer policy, reason: %s\n", ast_channel_name(ast), strerror(errno));
7282  } else {
7283  p->bufferoverrideinuse = 1;
7284  }
7285  }
7286  p->faxhandled = 1;
7287  if (p->dsp) {
7290  ast_debug(1, "Disabling FAX tone detection on %s after tone received\n", ast_channel_name(ast));
7291  }
7292  if (strcmp(ast_channel_exten(ast), "fax")) {
7293  const char *target_context = S_OR(ast_channel_macrocontext(ast), ast_channel_context(ast));
7294 
7295  /*
7296  * We need to unlock 'ast' here because ast_exists_extension has the
7297  * potential to start autoservice on the channel. Such action is prone
7298  * to deadlock if the channel is locked.
7299  *
7300  * ast_async_goto() has its own restriction on not holding the
7301  * channel lock.
7302  */
7303  ast_mutex_unlock(&p->lock);
7304  ast_channel_unlock(ast);
7305  if (ast_exists_extension(ast, target_context, "fax", 1,
7306  S_COR(ast_channel_caller(ast)->id.number.valid, ast_channel_caller(ast)->id.number.str, NULL))) {
7307  ast_verb(3, "Redirecting %s to fax extension\n", ast_channel_name(ast));
7308  /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
7309  pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast_channel_exten(ast));
7310  if (ast_async_goto(ast, target_context, "fax", 1))
7311  ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast_channel_name(ast), target_context);
7312  } else {
7313  ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
7314  }
7315  ast_channel_lock(ast);
7316  ast_mutex_lock(&p->lock);
7317  } else {
7318  ast_debug(1, "Already in a fax extension, not redirecting\n");
7319  }
7320  } else {
7321  ast_debug(1, "Fax already handled\n");
7322  }
7323  dahdi_confmute(p, 0);
7324  }
7325  p->subs[idx].f.frametype = AST_FRAME_NULL;
7326  p->subs[idx].f.subclass.integer = 0;
7327  *dest = &p->subs[idx].f;
7328  }
7329 }
7330 
7331 static void publish_span_alarm(int span, const char *alarm_txt)
7332 {
7333  RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
7334 
7335  body = ast_json_pack("{s: i, s: s}",
7336  "Span", span,
7337  "Alarm", alarm_txt);
7338  if (!body) {
7339  return;
7340  }
7341 
7342  ast_manager_publish_event("SpanAlarm", EVENT_FLAG_SYSTEM, body);
7343 }
7344 
7345 static void publish_channel_alarm(int channel, const char *alarm_txt)
7346 {
7347  RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
7348  RAII_VAR(struct ast_str *, dahdi_chan, ast_str_create(32), ast_free);
7349  if (!dahdi_chan) {
7350  return;
7351  }
7352 
7353  ast_str_set(&dahdi_chan, 0, "%d", channel);
7354  body = ast_json_pack("{s: s, s: s}",
7355  "DAHDIChannel", ast_str_buffer(dahdi_chan),
7356  "Alarm", alarm_txt);
7357  if (!body) {
7358  return;
7359  }
7360 
7362 }
7363 
7364 static void handle_alarms(struct dahdi_pvt *p, int alms)
7365 {
7366  const char *alarm_str;
7367 
7368 #if defined(HAVE_PRI)
7370  return;
7371  }
7372 #endif /* defined(HAVE_PRI) */
7373 
7374  alarm_str = alarm2str(alms);
7376  ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", p->channel, alarm_str);
7377  publish_channel_alarm(p->channel, alarm_str);
7378  }
7379 
7381  ast_log(LOG_WARNING, "Detected alarm on span %d: %s\n", p->span, alarm_str);
7382  publish_span_alarm(p->span, alarm_str);
7383  }
7384 }
7385 
7386 static struct ast_frame *dahdi_handle_event(struct ast_channel *ast)
7387 {
7388  int res, x;
7389  int idx, mysig;
7390  char *c;
7391  struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
7392  pthread_t threadid;
7393  struct ast_channel *chan;
7394  struct ast_frame *f;
7395 
7396  idx = dahdi_get_index(ast, p, 0);
7397  if (idx < 0) {
7398  return &ast_null_frame;
7399  }
7400  mysig = p->sig;
7401  if (p->outsigmod > -1)
7402  mysig = p->outsigmod;
7403  p->subs[idx].f.frametype = AST_FRAME_NULL;
7404  p->subs[idx].f.subclass.integer = 0;
7405  p->subs[idx].f.datalen = 0;
7406  p->subs[idx].f.samples = 0;
7407  p->subs[idx].f.mallocd = 0;
7408  p->subs[idx].f.offset = 0;
7409  p->subs[idx].f.src = "dahdi_handle_event";
7410  p->subs[idx].f.data.ptr = NULL;
7411  f = &p->subs[idx].f;
7412 
7413  if (p->fake_event) {
7414  res = p->fake_event;
7415  p->fake_event = 0;
7416  } else
7417  res = dahdi_get_event(p->subs[idx].dfd);
7418 
7419  ast_debug(1, "Got event %s(%d) on channel %d (index %d)\n", event2str(res), res, p->channel, idx);
7420 
7421  if (res & (DAHDI_EVENT_PULSEDIGIT | DAHDI_EVENT_DTMFUP)) {
7422  p->pulsedial = (res & DAHDI_EVENT_PULSEDIGIT) ? 1 : 0;
7423  ast_debug(1, "Detected %sdigit '%c'\n", p->pulsedial ? "pulse ": "", res & 0xff);
7424 #if defined(HAVE_PRI)
7426  && ((struct sig_pri_chan *) p->sig_pvt)->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING
7427  && p->pri
7428  && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
7429  /* absorb event */
7430  } else
7431 #endif /* defined(HAVE_PRI) */
7432  {
7433  /* Unmute conference */
7434  dahdi_confmute(p, 0);
7435  p->subs[idx].f.frametype = AST_FRAME_DTMF_END;
7436  p->subs[idx].f.subclass.integer = res & 0xff;
7437  dahdi_handle_dtmf(ast, idx, &f);
7438  }
7439  return f;
7440  }
7441 
7442  if (res & DAHDI_EVENT_DTMFDOWN) {
7443  ast_debug(1, "DTMF Down '%c'\n", res & 0xff);
7444 #if defined(HAVE_PRI)
7446  && ((struct sig_pri_chan *) p->sig_pvt)->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING
7447  && p->pri
7448  && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
7449  /* absorb event */
7450  } else
7451 #endif /* defined(HAVE_PRI) */
7452  {
7453  /* Mute conference */
7454  dahdi_confmute(p, 1);
7456  p->subs[idx].f.subclass.integer = res & 0xff;
7457  dahdi_handle_dtmf(ast, idx, &f);
7458  }
7459  return &p->subs[idx].f;
7460  }
7461 
7462  switch (res) {
7463  case DAHDI_EVENT_EC_DISABLED:
7464  ast_verb(3, "Channel %d echo canceler disabled.\n", p->channel);
7465  p->echocanon = 0;
7466  break;
7467 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
7468  case DAHDI_EVENT_TX_CED_DETECTED:
7469  ast_verb(3, "Channel %d detected a CED tone towards the network.\n", p->channel);
7470  break;
7471  case DAHDI_EVENT_RX_CED_DETECTED:
7472  ast_verb(3, "Channel %d detected a CED tone from the network.\n", p->channel);
7473  break;
7474  case DAHDI_EVENT_EC_NLP_DISABLED:
7475  ast_verb(3, "Channel %d echo canceler disabled its NLP.\n", p->channel);
7476  break;
7477  case DAHDI_EVENT_EC_NLP_ENABLED:
7478  ast_verb(3, "Channel %d echo canceler enabled its NLP.\n", p->channel);
7479  break;
7480 #endif
7481  case DAHDI_EVENT_BITSCHANGED:
7482 #ifdef HAVE_OPENR2
7483  if (p->sig != SIG_MFCR2) {
7484  ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig));
7485  } else {
7486  ast_debug(1, "bits changed in chan %d\n", p->channel);
7487  openr2_chan_handle_cas(p->r2chan);
7488  }
7489 #else
7490  ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig));
7491 #endif
7492  break;
7493  case DAHDI_EVENT_PULSE_START:
7494  /* Stop tone if there's a pulse start and the PBX isn't started */
7495  if (!ast_channel_pbx(ast))
7496  tone_zone_play_tone(p->subs[idx].dfd, -1);
7497  break;
7498  case DAHDI_EVENT_DIALCOMPLETE:
7499  /* DAHDI has completed dialing all digits sent using DAHDI_DIAL. */
7500 #if defined(HAVE_PRI)
7501  if (dahdi_sig_pri_lib_handles(p->sig)) {
7502  if (p->inalarm) {
7503  break;
7504  }
7505  if (ioctl(p->subs[idx].dfd, DAHDI_DIALING, &x) == -1) {
7506  ast_debug(1, "DAHDI_DIALING ioctl failed on %s: %s\n",
7507  ast_channel_name(ast), strerror(errno));
7508  return NULL;
7509  }
7510  if (x) {
7511  /* Still dialing in DAHDI driver */
7512  break;
7513  }
7514  /*
7515  * The ast channel is locked and the private may be locked more
7516  * than once.
7517  */
7518  sig_pri_dial_complete(p->sig_pvt, ast);
7519  break;
7520  }
7521 #endif /* defined(HAVE_PRI) */
7522 #ifdef HAVE_OPENR2
7523  if ((p->sig & SIG_MFCR2) && p->r2chan && ast_channel_state(ast) != AST_STATE_UP) {
7524  /* we don't need to do anything for this event for R2 signaling
7525  if the call is being setup */
7526  break;
7527  }
7528 #endif
7529  if (p->inalarm) break;
7530  if ((p->radio || (p->oprmode < 0))) break;
7531  if (ioctl(p->subs[idx].dfd,DAHDI_DIALING,&x) == -1) {
7532  ast_debug(1, "DAHDI_DIALING ioctl failed on %s: %s\n",ast_channel_name(ast), strerror(errno));
7533  return NULL;
7534  }
7535  if (!x) { /* if not still dialing in driver */
7536  dahdi_ec_enable(p);
7537  if (p->echobreak) {
7538  dahdi_train_ec(p);
7539  ast_copy_string(p->dop.dialstr, p->echorest, sizeof(p->dop.dialstr));
7540  p->dop.op = DAHDI_DIAL_OP_REPLACE;
7541  res = dahdi_dial_str(p, p->dop.op, p->dop.dialstr);
7542  p->echobreak = 0;
7543  } else {
7544  p->dialing = 0;
7545  if ((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) {
7546  /* if thru with dialing after offhook */
7548  ast_setstate(ast, AST_STATE_UP);
7549  p->subs[idx].f.frametype = AST_FRAME_CONTROL;
7551  break;
7552  } else { /* if to state wait for offhook to dial rest */
7553  /* we now wait for off hook */
7555  }
7556  }
7557  if (ast_channel_state(ast) == AST_STATE_DIALING) {
7558  if ((p->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
7559  ast_debug(1, "Done dialing, but waiting for progress detection before doing more...\n");
7560  } else if (p->confirmanswer || (!p->dialednone
7561  && ((mysig == SIG_EM) || (mysig == SIG_EM_E1)
7562  || (mysig == SIG_EMWINK) || (mysig == SIG_FEATD)
7563  || (mysig == SIG_FEATDMF_TA) || (mysig == SIG_FEATDMF)
7564  || (mysig == SIG_E911) || (mysig == SIG_FGC_CAMA)
7565  || (mysig == SIG_FGC_CAMAMF) || (mysig == SIG_FEATB)
7566  || (mysig == SIG_SF) || (mysig == SIG_SFWINK)
7567  || (mysig == SIG_SF_FEATD) || (mysig == SIG_SF_FEATDMF)
7568  || (mysig == SIG_SF_FEATB)))) {
7570  } else if (!p->answeronpolarityswitch) {
7571  ast_setstate(ast, AST_STATE_UP);
7572  p->subs[idx].f.frametype = AST_FRAME_CONTROL;
7574  /* If aops=0 and hops=1, this is necessary */
7575  p->polarity = POLARITY_REV;
7576  } else {
7577  /* Start clean, so we can catch the change to REV polarity when party answers */
7578  p->polarity = POLARITY_IDLE;
7579  }
7580  }
7581  }
7582  }
7583  break;
7584  case DAHDI_EVENT_ALARM:
7585  switch (p->sig) {
7586 #if defined(HAVE_PRI)
7589  break;
7590 #endif /* defined(HAVE_PRI) */
7591 #if defined(HAVE_SS7)
7592  case SIG_SS7:
7593  sig_ss7_set_alarm(p->sig_pvt, 1);
7594  break;
7595 #endif /* defined(HAVE_SS7) */
7596  default:
7597  p->inalarm = 1;
7598  break;
7599  }
7600  res = get_alarms(p);
7601  handle_alarms(p, res);
7602 #ifdef HAVE_PRI
7603  if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
7604  /* fall through intentionally */
7605  } else {
7606  break;
7607  }
7608 #endif
7609 #if defined(HAVE_SS7)
7610  if (p->sig == SIG_SS7)
7611  break;
7612 #endif /* defined(HAVE_SS7) */
7613 #ifdef HAVE_OPENR2
7614  if (p->sig == SIG_MFCR2)
7615  break;
7616 #endif
7617  case DAHDI_EVENT_ONHOOK:
7618  if (p->radio) {
7619  p->subs[idx].f.frametype = AST_FRAME_CONTROL;
7621  break;
7622  }
7623  if (p->oprmode < 0)
7624  {
7625  if (p->oprmode != -1) break;
7626  if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
7627  {
7628  /* Make sure it starts ringing */
7629  dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
7630  dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RING);
7632  tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
7633  }
7634  break;
7635  }
7636  switch (p->sig) {
7637  case SIG_FXOLS:
7638  case SIG_FXOGS:
7639  case SIG_FXOKS:
7640  /* Check for some special conditions regarding call waiting */
7641  if (idx == SUB_REAL) {
7642  /* The normal line was hung up */
7643  if (p->subs[SUB_CALLWAIT].owner) {
7644  /* There's a call waiting call, so ring the phone, but make it unowned in the mean time */
7646  ast_verb(3, "Channel %d still has (callwait) call, ringing phone\n", p->channel);
7648 #if 0
7649  p->subs[idx].needanswer = 0;
7650  p->subs[idx].needringing = 0;
7651 #endif
7652  p->callwaitingrepeat = 0;
7653  p->cidcwexpire = 0;
7654  p->cid_suppress_expire = 0;
7655  p->owner = NULL;
7656  /* Don't start streaming audio yet if the incoming call isn't up yet */
7658  p->dialing = 1;
7659  dahdi_ring_phone(p);
7660  } else if (p->subs[SUB_THREEWAY].owner) {
7661  unsigned int mssinceflash;
7662  /* Here we have to retain the lock on both the main channel, the 3-way channel, and
7663  the private structure -- not especially easy or clean */
7665  /* Yuck, didn't get the lock on the 3-way, gotta release everything and re-grab! */
7666  DLA_UNLOCK(&p->lock);
7668  /* We can grab ast and p in that order, without worry. We should make sure
7669  nothing seriously bad has happened though like some sort of bizarre double
7670  masquerade! */
7671  DLA_LOCK(&p->lock);
7672  if (p->owner != ast) {
7673  ast_log(LOG_WARNING, "This isn't good...\n");
7674  return NULL;
7675  }
7676  }
7677  if (!p->subs[SUB_THREEWAY].owner) {
7678  ast_log(LOG_NOTICE, "Whoa, threeway disappeared kinda randomly.\n");
7679  return NULL;
7680  }
7681  mssinceflash = ast_tvdiff_ms(ast_tvnow(), p->flashtime);
7682  ast_debug(1, "Last flash was %u ms ago\n", mssinceflash);
7683  if (mssinceflash < MIN_MS_SINCE_FLASH) {
7684  /* It hasn't been long enough since the last flashook. This is probably a bounce on
7685  hanging up. Hangup both channels now */
7686  if (p->subs[SUB_THREEWAY].owner)
7689  ast_debug(1, "Looks like a bounced flash, hanging up both calls on %d\n", p->channel);
7691  } else if ((ast_channel_pbx(ast)) || (ast_channel_state(ast) == AST_STATE_UP)) {
7692  if (p->transfer) {
7693  /* In any case this isn't a threeway call anymore */
7694  p->subs[SUB_REAL].inthreeway = 0;
7695  p->subs[SUB_THREEWAY].inthreeway = 0;
7696  /* Only attempt transfer if the phone is ringing; why transfer to busy tone eh? */
7697  if (!p->transfertobusy && ast_channel_state(ast) == AST_STATE_BUSY) {
7699  /* Swap subs and dis-own channel */
7701  p->owner = NULL;
7702  /* Ring the phone */
7703  dahdi_ring_phone(p);
7704  } else if (!attempt_transfer(p)) {
7705  /*
7706  * Transfer successful. Don't actually hang up at this point.
7707  * Let our channel legs of the calls die off as the transfer
7708  * percolates through the core.
7709  */
7710  break;
7711  }
7712  } else {
7714  if (p->subs[SUB_THREEWAY].owner)
7716  }
7717  } else {
7719  /* Swap subs and dis-own channel */
7721  p->owner = NULL;
7722  /* Ring the phone */
7723  dahdi_ring_phone(p);
7724  }
7725  }
7726  } else {
7727  ast_log(LOG_WARNING, "Got a hangup and my index is %d?\n", idx);
7728  }
7729  /* Fall through */
7730  default:
7731  dahdi_ec_disable(p);
7732  return NULL;
7733  }
7734  break;
7735  case DAHDI_EVENT_RINGOFFHOOK:
7736  if (p->inalarm) break;
7737  if (p->oprmode < 0)
7738  {
7739  if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
7740  {
7741  /* Make sure it stops ringing */
7742  dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
7743  tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, -1);
7745  }
7746  break;
7747  }
7748  if (p->radio)
7749  {
7750  p->subs[idx].f.frametype = AST_FRAME_CONTROL;
7752  break;
7753  }
7754  /* for E911, its supposed to wait for offhook then dial
7755  the second half of the dial string */
7756  if (((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) && (ast_channel_state(ast) == AST_STATE_DIALING_OFFHOOK)) {
7757  c = strchr(p->dialdest, '/');
7758  if (c)
7759  c++;
7760  else
7761  c = p->dialdest;
7762 
7763  if (*c) {
7764  int numchars = snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*0%s#", c);
7765  if (numchars >= sizeof(p->dop.dialstr)) {
7766  ast_log(LOG_WARNING, "Dial string '%s' truncated\n", c);
7767  }
7768  } else {
7769  ast_copy_string(p->dop.dialstr,"M*2#", sizeof(p->dop.dialstr));
7770  }
7771 
7772  if (strlen(p->dop.dialstr) > 4) {
7773  memset(p->echorest, 'w', sizeof(p->echorest) - 1);
7774  strcpy(p->echorest + (p->echotraining / 401) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
7775  p->echorest[sizeof(p->echorest) - 1] = '\0';
7776  p->echobreak = 1;
7777  p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
7778  } else
7779  p->echobreak = 0;
7780  if (dahdi_dial_str(p, p->dop.op, p->dop.dialstr)) {
7781  x = DAHDI_ONHOOK;
7782  ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
7783  return NULL;
7784  }
7785  p->dialing = 1;
7786  return &p->subs[idx].f;
7787  }
7788  switch (p->sig) {
7789  case SIG_FXOLS:
7790  case SIG_FXOGS:
7791  case SIG_FXOKS:
7792  switch (ast_channel_state(ast)) {
7793  case AST_STATE_RINGING:
7794  dahdi_ec_enable(p);
7795  dahdi_train_ec(p);
7796  p->subs[idx].f.frametype = AST_FRAME_CONTROL;
7798  /* Make sure it stops ringing */
7799  p->subs[SUB_REAL].needringing = 0;
7800  dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
7801  ast_debug(1, "channel %d answered\n", p->channel);
7802 
7803  /* Cancel any running CallerID spill */
7804  ast_free(p->cidspill);
7805  p->cidspill = NULL;
7806  restore_conference(p);
7807 
7808  p->dialing = 0;
7809  p->callwaitcas = 0;
7810  if (p->confirmanswer) {
7811  /* Ignore answer if "confirm answer" is enabled */
7812  p->subs[idx].f.frametype = AST_FRAME_NULL;
7813  p->subs[idx].f.subclass.integer = 0;
7814  } else if (!ast_strlen_zero(p->dop.dialstr)) {
7815  /* [email protected] 4/3/03 - fxo should be able to do deferred dialing */
7816  res = dahdi_dial_str(p, p->dop.op, p->dop.dialstr);
7817  if (res) {
7818  p->dop.dialstr[0] = '\0';
7819  return NULL;
7820  } else {
7821  ast_debug(1, "Sent FXO deferred digit string: %s\n", p->dop.dialstr);
7822  p->subs[idx].f.frametype = AST_FRAME_NULL;
7823  p->subs[idx].f.subclass.integer = 0;
7824  p->dialing = 1;
7825  }
7826  p->dop.dialstr[0] = '\0';
7828  } else
7829  ast_setstate(ast, AST_STATE_UP);
7830  return &p->subs[idx].f;
7831  case AST_STATE_DOWN:
7833  ast_channel_rings_set(ast, 1);
7834  p->subs[idx].f.frametype = AST_FRAME_CONTROL;
7836  ast_debug(1, "channel %d picked up\n", p->channel);
7837  return &p->subs[idx].f;
7838  case AST_STATE_UP:
7839  /* Make sure it stops ringing */
7840  dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
7841  /* Okay -- probably call waiting*/
7842  ast_queue_unhold(p->owner);
7843  p->subs[idx].needunhold = 1;
7844  break;
7845  case AST_STATE_RESERVED:
7846  /* Start up dialtone */
7847  if (has_voicemail(p))
7848  res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
7849  else
7850  res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
7851  break;
7852  default:
7853  ast_log(LOG_WARNING, "FXO phone off hook in weird state %u??\n", ast_channel_state(ast));
7854  }
7855  break;
7856  case SIG_FXSLS:
7857  case SIG_FXSGS:
7858  case SIG_FXSKS:
7859  if (ast_channel_state(ast) == AST_STATE_RING) {
7860  p->ringt = p->ringt_base;
7861  }
7862 
7863  /* If we get a ring then we cannot be in
7864  * reversed polarity. So we reset to idle */
7865  ast_debug(1, "Setting IDLE polarity due "
7866  "to ring. Old polarity was %d\n",
7867  p->polarity);
7868  p->polarity = POLARITY_IDLE;
7869 
7870  /* Fall through */
7871  case SIG_EM:
7872  case SIG_EM_E1:
7873  case SIG_EMWINK:
7874  case SIG_FEATD:
7875  case SIG_FEATDMF:
7876  case SIG_FEATDMF_TA:
7877  case SIG_E911:
7878  case SIG_FGC_CAMA:
7879  case SIG_FGC_CAMAMF:
7880  case SIG_FEATB:
7881  case SIG_SF:
7882  case SIG_SFWINK:
7883  case SIG_SF_FEATD:
7884  case SIG_SF_FEATDMF:
7885  case SIG_SF_FEATB:
7889  ast_debug(1, "Ring detected\n");
7890  p->subs[idx].f.frametype = AST_FRAME_CONTROL;
7892  } else if (p->outgoing && ((ast_channel_state(ast) == AST_STATE_RINGING) || (ast_channel_state(ast) == AST_STATE_DIALING))) {
7893  ast_debug(1, "Line answered\n");
7894  if (p->confirmanswer) {
7895  p->subs[idx].f.frametype = AST_FRAME_NULL;
7896  p->subs[idx].f.subclass.integer = 0;
7897  } else {
7898  p->subs[idx].f.frametype = AST_FRAME_CONTROL;
7900  ast_setstate(ast, AST_STATE_UP);
7901  }
7902  } else if (ast_channel_state(ast) != AST_STATE_RING)
7903  ast_log(LOG_WARNING, "Ring/Off-hook in strange state %u on channel %d\n", ast_channel_state(ast), p->channel);
7904  break;
7905  default:
7906  ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
7907  }
7908  break;
7909  case DAHDI_EVENT_RINGBEGIN:
7910  switch (p->sig) {
7911  case SIG_FXSLS:
7912  case SIG_FXSGS:
7913  case SIG_FXSKS:
7914  if (ast_channel_state(ast) == AST_STATE_RING) {
7915  p->ringt = p->ringt_base;
7916  }
7917  break;
7918  }
7919  break;
7920  case DAHDI_EVENT_RINGERON:
7921  break;
7922  case DAHDI_EVENT_NOALARM:
7923  switch (p->sig) {
7924 #if defined(HAVE_PRI)
7927  break;
7928 #endif /* defined(HAVE_PRI) */
7929 #if defined(HAVE_SS7)
7930  case SIG_SS7:
7931  sig_ss7_set_alarm(p->sig_pvt, 0);
7932  break;
7933 #endif /* defined(HAVE_SS7) */
7934  default:
7935  p->inalarm = 0;
7936  break;
7937  }
7939  break;
7940  case DAHDI_EVENT_WINKFLASH:
7941  if (p->inalarm) break;
7942  if (p->radio) break;
7943  if (p->oprmode < 0) break;
7944  if (p->oprmode > 1)
7945  {
7946  struct dahdi_params par;
7947 
7948  memset(&par, 0, sizeof(par));
7949  if (ioctl(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par) != -1)
7950  {
7951  if (!par.rxisoffhook)
7952  {
7953  /* Make sure it stops ringing */
7954  dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
7955  dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RING);
7956  save_conference(p);
7957  tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
7958  }
7959  }
7960  break;
7961  }
7962  /* Remember last time we got a flash-hook */
7963  p->flashtime = ast_tvnow();
7964  switch (mysig) {
7965  case SIG_FXOLS:
7966  case SIG_FXOGS:
7967  case SIG_FXOKS:
7968  ast_debug(1, "Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n",
7969  idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
7970 
7971  /* Cancel any running CallerID spill */
7972  ast_free(p->cidspill);
7973  p->cidspill = NULL;
7974  restore_conference(p);
7975  p->callwaitcas = 0;
7976 
7977  if (idx != SUB_REAL) {
7978  ast_log(LOG_WARNING, "Got flash hook with index %d on channel %d?!?\n", idx, p->channel);
7979  goto winkflashdone;
7980  }
7981 
7982  if (p->subs[SUB_CALLWAIT].owner) {
7983  /* Swap to call-wait */
7985  tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
7986  p->owner = p->subs[SUB_REAL].owner;
7987  ast_debug(1, "Making %s the new owner\n", ast_channel_name(p->owner));
7990  p->subs[SUB_REAL].needanswer = 1;
7991  }
7992  p->callwaitingrepeat = 0;
7993  p->cidcwexpire = 0;
7994  p->cid_suppress_expire = 0;
7995  /* Start music on hold if appropriate */
7996  if (!p->subs[SUB_CALLWAIT].inthreeway) {
7998  }
7999  p->subs[SUB_CALLWAIT].needhold = 1;
8001  p->subs[SUB_REAL].needunhold = 1;
8002  } else if (!p->subs[SUB_THREEWAY].owner) {
8003  if (!p->threewaycalling) {
8004  /* Just send a flash if no 3-way calling */
8005  p->subs[SUB_REAL].needflash = 1;
8006  goto winkflashdone;
8007  } else if (!check_for_conference(p)) {
8008  ast_callid callid = 0;
8009  int callid_created;
8010  char cid_num[256];
8011  char cid_name[256];
8012 
8013  cid_num[0] = 0;
8014  cid_name[0] = 0;
8015  if (p->dahditrcallerid && p->owner) {
8017  && ast_channel_caller(p->owner)->id.number.str) {
8019  sizeof(cid_num));
8020  }
8022  && ast_channel_caller(p->owner)->id.name.str) {
8024  sizeof(cid_name));
8025  }
8026  }
8027  /* XXX This section needs much more error checking!!! XXX */
8028  /* Start a 3-way call if feasible */
8029  if (!((ast_channel_pbx(ast)) ||
8030  (ast_channel_state(ast) == AST_STATE_UP) ||
8031  (ast_channel_state(ast) == AST_STATE_RING))) {
8032  ast_debug(1, "Flash when call not up or ringing\n");
8033  goto winkflashdone;
8034  }
8035  if (alloc_sub(p, SUB_THREEWAY)) {
8036  ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n");
8037  goto winkflashdone;
8038  }
8039  callid_created = ast_callid_threadstorage_auto(&callid);
8040  /*
8041  * Make new channel
8042  *
8043  * We cannot hold the p or ast locks while creating a new
8044  * channel.
8045  */
8046  ast_mutex_unlock(&p->lock);
8047  ast_channel_unlock(ast);
8048  chan = dahdi_new(p, AST_STATE_RESERVED, 0, SUB_THREEWAY, 0, NULL, NULL, callid);
8049  ast_channel_lock(ast);
8050  ast_mutex_lock(&p->lock);
8051  if (p->dahditrcallerid) {
8052  if (!p->origcid_num)
8053  p->origcid_num = ast_strdup(p->cid_num);
8054  if (!p->origcid_name)
8055  p->origcid_name = ast_strdup(p->cid_name);
8056  ast_copy_string(p->cid_num, cid_num, sizeof(p->cid_num));
8057  ast_copy_string(p->cid_name, cid_name, sizeof(p->cid_name));
8058  }
8059  /* Swap things around between the three-way and real call */
8061  /* Disable echo canceller for better dialing */
8062  dahdi_ec_disable(p);
8063  res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALRECALL);
8064  if (res)
8065  ast_log(LOG_WARNING, "Unable to start dial recall tone on channel %d\n", p->channel);
8066  p->owner = chan;
8067  if (!chan) {
8068  ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", p->channel);
8069  } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
8070  ast_log(LOG_WARNING, "Unable to start simple switch on channel %d\n", p->channel);
8071  res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
8072  dahdi_ec_enable(p);
8073  ast_hangup(chan);
8074  } else {
8075  ast_verb(3, "Started three way call on channel %d\n", p->channel);
8076 
8077  /* Start music on hold */
8079  p->subs[SUB_THREEWAY].needhold = 1;
8080  }
8081  ast_callid_threadstorage_auto_clean(callid, callid_created);
8082  }
8083  } else {
8084  /* Already have a 3 way call */
8085  if (p->subs[SUB_THREEWAY].inthreeway) {
8086  /* Call is already up, drop the last person */
8087  ast_debug(1, "Got flash with three way call up, dropping last call on %d\n", p->channel);
8088  /* If the primary call isn't answered yet, use it */
8090  /* Swap back -- we're dropping the real 3-way that isn't finished yet*/
8092  p->owner = p->subs[SUB_REAL].owner;
8093  }
8094  /* Drop the last call and stop the conference */
8095  ast_verb(3, "Dropping three-way call on %s\n", ast_channel_name(p->subs[SUB_THREEWAY].owner));
8097  p->subs[SUB_REAL].inthreeway = 0;
8098  p->subs[SUB_THREEWAY].inthreeway = 0;
8099  } else {
8100  /* Lets see what we're up to */
8101  if (((ast_channel_pbx(ast)) || (ast_channel_state(ast) == AST_STATE_UP)) &&
8102  (p->transfertobusy || (ast_channel_state(ast) != AST_STATE_BUSY))) {
8103  int otherindex = SUB_THREEWAY;
8104 
8105  ast_verb(3, "Building conference call with %s and %s\n",
8108  /* Put them in the threeway, and flip */
8109  p->subs[SUB_THREEWAY].inthreeway = 1;
8110  p->subs[SUB_REAL].inthreeway = 1;
8111  if (ast_channel_state(ast) == AST_STATE_UP) {
8113  otherindex = SUB_REAL;
8114  }
8115  if (p->subs[otherindex].owner) {
8116  ast_queue_unhold(p->subs[otherindex].owner);
8117  }
8118  p->subs[otherindex].needunhold = 1;
8119  p->owner = p->subs[SUB_REAL].owner;
8120  } else {
8121  ast_verb(3, "Dumping incomplete call on %s\n", ast_channel_name(p->subs[SUB_THREEWAY].owner));
8124  p->owner = p->subs[SUB_REAL].owner;
8125  if (p->subs[SUB_REAL].owner) {
8127  }
8128  p->subs[SUB_REAL].needunhold = 1;
8129  dahdi_ec_enable(p);
8130  }
8131  }
8132  }
8133 winkflashdone:
8134  dahdi_conf_update(p);
8135  break;
8136  case SIG_EM:
8137  case SIG_EM_E1:
8138  case SIG_FEATD:
8139  case SIG_SF:
8140  case SIG_SFWINK:
8141  case SIG_SF_FEATD:
8142  case SIG_FXSLS:
8143  case SIG_FXSGS:
8144  if (p->dialing)
8145  ast_debug(1, "Ignoring wink on channel %d\n", p->channel);
8146  else
8147  ast_debug(1, "Got wink in weird state %u on channel %d\n", ast_channel_state(ast), p->channel);
8148  break;
8149  case SIG_FEATDMF_TA:
8150  switch (p->whichwink) {
8151  case 0:
8152  ast_debug(1, "ANI2 set to '%d' and ANI is '%s'\n", ast_channel_caller(p->owner)->ani2,
8154  ast_channel_caller(p->owner)->ani.number.str, ""));
8155  snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%d%s#",
8158  ast_channel_caller(p->owner)->ani.number.str, ""));
8159  break;
8160  case 1:
8161  ast_copy_string(p->dop.dialstr, p->finaldial, sizeof(p->dop.dialstr));
8162  break;
8163  case 2:
8164  ast_log(LOG_WARNING, "Received unexpected wink on channel of type SIG_FEATDMF_TA\n");
8165  return NULL;
8166  }
8167  p->whichwink++;
8168  /* Fall through */
8169  case SIG_FEATDMF:
8170  case SIG_E911:
8171  case SIG_FGC_CAMAMF:
8172  case SIG_FGC_CAMA:
8173  case SIG_FEATB:
8174  case SIG_SF_FEATDMF:
8175  case SIG_SF_FEATB:
8176  case SIG_EMWINK:
8177  /* FGD MF and EMWINK *Must* wait for wink */
8178  if (!ast_strlen_zero(p->dop.dialstr)) {
8179  res = dahdi_dial_str(p, p->dop.op, p->dop.dialstr);
8180  if (res) {
8181  p->dop.dialstr[0] = '\0';
8182  return NULL;
8183  } else
8184  ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
8185  }
8186  p->dop.dialstr[0] = '\0';
8187  break;
8188  default:
8189  ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
8190  }
8191  break;
8192  case DAHDI_EVENT_HOOKCOMPLETE:
8193  if (p->inalarm) break;
8194  if ((p->radio || (p->oprmode < 0))) break;
8195  if (p->waitingfordt.tv_sec) break;
8196  switch (mysig) {
8197  case SIG_FXSLS: /* only interesting for FXS */
8198  case SIG_FXSGS:
8199  case SIG_FXSKS:
8200  case SIG_EM:
8201  case SIG_EM_E1:
8202  case SIG_EMWINK:
8203  case SIG_FEATD:
8204  case SIG_SF:
8205  case SIG_SFWINK:
8206  case SIG_SF_FEATD:
8207  if (!ast_strlen_zero(p->dop.dialstr)) {
8208  res = dahdi_dial_str(p, p->dop.op, p->dop.dialstr);
8209  if (res) {
8210  p->dop.dialstr[0] = '\0';
8211  return NULL;
8212  } else
8213  ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
8214  }
8215  p->dop.dialstr[0] = '\0';
8216  p->dop.op = DAHDI_DIAL_OP_REPLACE;
8217  break;
8218  case SIG_FEATDMF:
8219  case SIG_FEATDMF_TA:
8220  case SIG_E911:
8221  case SIG_FGC_CAMA:
8222  case SIG_FGC_CAMAMF:
8223  case SIG_FEATB:
8224  case SIG_SF_FEATDMF:
8225  case SIG_SF_FEATB:
8226  ast_debug(1, "Got hook complete in MF FGD, waiting for wink now on channel %d\n",p->channel);
8227  break;
8228  default:
8229  break;
8230  }
8231  break;
8232  case DAHDI_EVENT_POLARITY:
8233  /*
8234  * If we get a Polarity Switch event, check to see
8235  * if we should change the polarity state and
8236  * mark the channel as UP or if this is an indication
8237  * of remote end disconnect.
8238  */
8239  if (p->polarity == POLARITY_IDLE) {
8240  p->polarity = POLARITY_REV;
8241  if (p->answeronpolarityswitch &&
8242  ((ast_channel_state(ast) == AST_STATE_DIALING) ||
8243  (ast_channel_state(ast) == AST_STATE_RINGING))) {
8244  ast_debug(1, "Answering on polarity switch!\n");
8246  if (p->hanguponpolarityswitch) {
8247  p->polaritydelaytv = ast_tvnow();
8248  }
8249  } else
8250  ast_debug(1, "Ignore switch to REVERSED Polarity on channel %d, state %u\n", p->channel, ast_channel_state(ast));
8251  }
8252  /* Removed else statement from here as it was preventing hangups from ever happening*/
8253  /* Added AST_STATE_RING in if statement below to deal with calling party hangups that take place when ringing */
8254  if (p->hanguponpolarityswitch &&
8255  (p->polarityonanswerdelay > 0) &&
8256  (p->polarity == POLARITY_REV) &&
8257  ((ast_channel_state(ast) == AST_STATE_UP) || (ast_channel_state(ast) == AST_STATE_RING)) ) {
8258  /* Added log_debug information below to provide a better indication of what is going on */
8259  ast_debug(1, "Polarity Reversal event occured - DEBUG 1: channel %d, state %u, pol= %d, aonp= %d, honp= %d, pdelay= %d, tv= %" PRIi64 "\n", p->channel, ast_channel_state(ast), p->polarity, p->answeronpolarityswitch, p->hanguponpolarityswitch, p->polarityonanswerdelay, ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) );
8260 
8262  ast_debug(1, "Polarity Reversal detected and now Hanging up on channel %d\n", p->channel);
8264  p->polarity = POLARITY_IDLE;
8265  } else
8266  ast_debug(1, "Polarity Reversal detected but NOT hanging up (too close to answer event) on channel %d, state %u\n", p->channel, ast_channel_state(ast));
8267 
8268  } else {
8269  p->polarity = POLARITY_IDLE;
8270  ast_debug(1, "Ignoring Polarity switch to IDLE on channel %d, state %u\n", p->channel, ast_channel_state(ast));
8271  }
8272  /* Added more log_debug information below to provide a better indication of what is going on */
8273  ast_debug(1, "Polarity Reversal event occured - DEBUG 2: channel %d, state %u, pol= %d, aonp= %d, honp= %d, pdelay= %d, tv= %" PRIi64 "\n", p->channel, ast_channel_state(ast), p->polarity, p->answeronpolarityswitch, p->hanguponpolarityswitch, p->polarityonanswerdelay, ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) );
8274  break;
8275  default:
8276  ast_debug(1, "Dunno what to do with event %d on channel %d\n", res, p->channel);
8277  }
8278  return &p->subs[idx].f;
8279 }
8280 
8281 static struct ast_frame *__dahdi_exception(struct ast_channel *ast)
8282 {
8283  int res;
8284  int idx;
8285  struct ast_frame *f;
8286  int usedindex = -1;
8287  struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
8288 
8289  if ((idx = dahdi_get_index(ast, p, 0)) < 0) {
8290  idx = SUB_REAL;
8291  }
8292 
8293  p->subs[idx].f.frametype = AST_FRAME_NULL;
8294  p->subs[idx].f.datalen = 0;
8295  p->subs[idx].f.samples = 0;
8296  p->subs[idx].f.mallocd = 0;
8297  p->subs[idx].f.offset = 0;
8298  p->subs[idx].f.subclass.integer = 0;
8299  p->subs[idx].f.delivery = ast_tv(0,0);
8300  p->subs[idx].f.src = "dahdi_exception";
8301  p->subs[idx].f.data.ptr = NULL;
8302 
8303 
8304  if ((!p->owner) && (!(p->radio || (p->oprmode < 0)))) {
8305  /* If nobody owns us, absorb the event appropriately, otherwise
8306  we loop indefinitely. This occurs when, during call waiting, the
8307  other end hangs up our channel so that it no longer exists, but we
8308  have neither FLASH'd nor ONHOOK'd to signify our desire to
8309  change to the other channel. */
8310  if (p->fake_event) {
8311  res = p->fake_event;
8312  p->fake_event = 0;
8313  } else
8314  res = dahdi_get_event(p->subs[SUB_REAL].dfd);
8315  /* Switch to real if there is one and this isn't something really silly... */
8316  if ((res != DAHDI_EVENT_RINGEROFF) && (res != DAHDI_EVENT_RINGERON) &&
8317  (res != DAHDI_EVENT_HOOKCOMPLETE)) {
8318  ast_debug(1, "Restoring owner of channel %d on event %d\n", p->channel, res);
8319  p->owner = p->subs[SUB_REAL].owner;
8320  if (p->owner) {
8321  ast_queue_unhold(p->owner);
8322  }
8323  p->subs[SUB_REAL].needunhold = 1;
8324  }
8325  switch (res) {
8326  case DAHDI_EVENT_ONHOOK:
8327  dahdi_ec_disable(p);
8328  if (p->owner) {
8329  ast_verb(3, "Channel %s still has call, ringing phone\n", ast_channel_name(p->owner));
8330  dahdi_ring_phone(p);
8331  p->callwaitingrepeat = 0;
8332  p->cidcwexpire = 0;
8333  p->cid_suppress_expire = 0;
8334  } else
8335  ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
8336  dahdi_conf_update(p);
8337  break;
8338  case DAHDI_EVENT_RINGOFFHOOK:
8339  dahdi_ec_enable(p);
8340  dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
8341  if (p->owner && (ast_channel_state(p->owner) == AST_STATE_RINGING)) {
8342  p->subs[SUB_REAL].needanswer = 1;
8343  p->dialing = 0;
8344  }
8345  break;
8346  case DAHDI_EVENT_HOOKCOMPLETE:
8347  case DAHDI_EVENT_RINGERON:
8348  case DAHDI_EVENT_RINGEROFF:
8349  /* Do nothing */
8350  break;
8351  case DAHDI_EVENT_WINKFLASH:
8352  p->flashtime = ast_tvnow();
8353  if (p->owner) {
8354  ast_verb(3, "Channel %d flashed to other channel %s\n", p->channel, ast_channel_name(p->owner));
8355  if (ast_channel_state(p->owner) != AST_STATE_UP) {
8356  /* Answer if necessary */
8357  usedindex = dahdi_get_index(p->owner, p, 0);
8358  if (usedindex > -1) {
8359  p->subs[usedindex].needanswer = 1;
8360  }
8362  }
8363  p->callwaitingrepeat = 0;
8364  p->cidcwexpire = 0;
8365  p->cid_suppress_expire = 0;
8366  ast_queue_unhold(p->owner);
8367  p->subs[SUB_REAL].needunhold = 1;
8368  } else
8369  ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
8370  dahdi_conf_update(p);
8371  break;
8372  default:
8373  ast_log(LOG_WARNING, "Don't know how to absorb event %s\n", event2str(res));
8374  }
8375  f = &p->subs[idx].f;
8376  return f;
8377  }
8378  if (!(p->radio || (p->oprmode < 0)))
8379  ast_debug(1, "Exception on %d, channel %d\n", ast_channel_fd(ast, 0), p->channel);
8380  /* If it's not us, return NULL immediately */
8381  if (ast != p->owner) {
8382  if (p->owner) {
8383  ast_log(LOG_WARNING, "We're %s, not %s\n", ast_channel_name(ast), ast_channel_name(p->owner));
8384  }
8385  f = &p->subs[idx].f;
8386  return f;
8387  }
8388 
8389  f = dahdi_handle_event(ast);
8390  if (!f) {
8391  const char *name = ast_strdupa(ast_channel_name(ast));
8392 
8393  /* Tell the CDR this DAHDI device hung up */
8394  ast_mutex_unlock(&p->lock);
8395  ast_channel_unlock(ast);
8396  ast_set_hangupsource(ast, name, 0);
8397  ast_channel_lock(ast);
8398  ast_mutex_lock(&p->lock);
8399  }
8400  return f;
8401 }
8402 
8403 static struct ast_frame *dahdi_exception(struct ast_channel *ast)
8404 {
8405  struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
8406  struct ast_frame *f;
8407  ast_mutex_lock(&p->lock);
8408  if (dahdi_analog_lib_handles(p->sig, p->radio, p->oprmode)) {
8409  struct analog_pvt *analog_p = p->sig_pvt;
8410  f = analog_exception(analog_p, ast);
8411  } else {
8412  f = __dahdi_exception(ast);
8413  }
8414  ast_mutex_unlock(&p->lock);
8415  return f;
8416 }
8417 
8418 static struct ast_frame *dahdi_read(struct ast_channel *ast)
8419 {
8420  struct dahdi_pvt *p;
8421  int res;
8422  int idx;
8423  void *readbuf;
8424  struct ast_frame *f;
8425 
8426  /*
8427  * For analog channels, we must do deadlock avoidance because
8428  * analog ports can have more than one Asterisk channel using
8429  * the same private structure.
8430  */
8431  p = ast_channel_tech_pvt(ast);
8432  while (ast_mutex_trylock(&p->lock)) {
8434 
8435  /*
8436  * Check to see if the channel is still associated with the same
8437  * private structure. While the Asterisk channel was unlocked
8438  * the following events may have occured:
8439  *
8440  * 1) A masquerade may have associated the channel with another
8441  * technology or private structure.
8442  *
8443  * 2) For PRI calls, call signaling could change the channel
8444  * association to another B channel (private structure).
8445  */
8446  if (ast_channel_tech_pvt(ast) != p) {
8447  /* The channel is no longer associated. Quit gracefully. */
8448  return &ast_null_frame;
8449  }
8450  }
8451 
8452  idx = dahdi_get_index(ast, p, 0);
8453 
8454  /* Hang up if we don't really exist */
8455  if (idx < 0) {
8456  ast_log(LOG_WARNING, "We don't exist?\n");
8457  ast_mutex_unlock(&p->lock);
8458  return NULL;
8459  }
8460 
8461  if ((p->radio || (p->oprmode < 0)) && p->inalarm) {
8462  ast_mutex_unlock(&p->lock);
8463  return NULL;
8464  }
8465 
8466  p->subs[idx].f.frametype = AST_FRAME_NULL;
8467  p->subs[idx].f.datalen = 0;
8468  p->subs[idx].f.samples = 0;
8469  p->subs[idx].f.mallocd = 0;
8470  p->subs[idx].f.offset = 0;
8471  p->subs[idx].f.subclass.integer = 0;
8472  p->subs[idx].f.delivery = ast_tv(0,0);
8473  p->subs[idx].f.src = "dahdi_read";
8474  p->subs[idx].f.data.ptr = NULL;
8475 
8476  /* make sure it sends initial key state as first frame */
8477  if ((p->radio || (p->oprmode < 0)) && (!p->firstradio))
8478  {
8479  struct dahdi_params ps;
8480 
8481  memset(&ps, 0, sizeof(ps));
8482  if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
8483  ast_mutex_unlock(&p->lock);
8484  return NULL;
8485  }
8486  p->firstradio = 1;
8487  p->subs[idx].f.frametype = AST_FRAME_CONTROL;
8488  if (ps.rxisoffhook)
8489  {
8491  }
8492  else
8493  {
8495  }
8496  ast_mutex_unlock(&p->lock);
8497  return &p->subs[idx].f;
8498  }
8499  if (p->ringt > 0) {
8500  if (!(--p->ringt)) {
8501  ast_mutex_unlock(&p->lock);
8502  return NULL;
8503  }
8504  }
8505 
8506 #ifdef HAVE_OPENR2
8507  if (p->mfcr2) {
8508  openr2_chan_process_event(p->r2chan);
8509  if (OR2_DIR_FORWARD == openr2_chan_get_direction(p->r2chan)) {
8510  struct ast_frame fr = { AST_FRAME_CONTROL, { AST_CONTROL_PROGRESS } };
8511  /* if the call is already accepted and we already delivered AST_CONTROL_RINGING
8512  * now enqueue a progress frame to bridge the media up */
8513  if (p->mfcr2_call_accepted &&
8514  !p->mfcr2_progress_sent &&
8516  ast_debug(1, "Enqueuing progress frame after R2 accept in chan %d\n", p->channel);
8517  ast_queue_frame(p->owner, &fr);
8518  p->mfcr2_progress_sent = 1;
8519  }
8520  }
8521  }
8522 #endif
8523 
8524  if (p->subs[idx].needringing) {
8525  /* Send ringing frame if requested */
8526  p->subs[idx].needringing = 0;
8527  p->subs[idx].f.frametype = AST_FRAME_CONTROL;
8530  ast_mutex_unlock(&p->lock);
8531  return &p->subs[idx].f;
8532  }
8533 
8534  if (p->subs[idx].needbusy) {
8535  /* Send busy frame if requested */
8536  p->subs[idx].needbusy = 0;
8537  p->subs[idx].f.frametype = AST_FRAME_CONTROL;
8539  ast_mutex_unlock(&p->lock);
8540  return &p->subs[idx].f;
8541  }
8542 
8543  if (p->subs[idx].needcongestion) {
8544  /* Send congestion frame if requested */
8545  p->subs[idx].needcongestion = 0;
8546  p->subs[idx].f.frametype = AST_FRAME_CONTROL;
8548  ast_mutex_unlock(&p->lock);
8549  return &p->subs[idx].f;
8550  }
8551 
8552  if (p->subs[idx].needanswer) {
8553  /* Send answer frame if requested */
8554  p->subs[idx].needanswer = 0;
8555  p->subs[idx].f.frametype = AST_FRAME_CONTROL;
8557  ast_mutex_unlock(&p->lock);
8558  return &p->subs[idx].f;
8559  }
8560 #ifdef HAVE_OPENR2
8561  if (p->mfcr2 && openr2_chan_get_read_enabled(p->r2chan)) {
8562  /* openr2 took care of reading and handling any event
8563  (needanswer, needbusy etc), if we continue we will read()
8564  twice, lets just return a null frame. This should only
8565  happen when openr2 is dialing out */
8566  ast_mutex_unlock(&p->lock);
8567  return &ast_null_frame;
8568  }
8569 #endif
8570 
8571  if (p->subs[idx].needflash) {
8572  /* Send answer frame if requested */
8573  p->subs[idx].needflash = 0;
8574  p->subs[idx].f.frametype = AST_FRAME_CONTROL;
8576  ast_mutex_unlock(&p->lock);
8577  return &p->subs[idx].f;
8578  }
8579 
8580  if (p->subs[idx].needhold) {
8581  /* Send answer frame if requested */
8582  p->subs[idx].needhold = 0;
8583  p->subs[idx].f.frametype = AST_FRAME_CONTROL;
8585  ast_mutex_unlock(&p->lock);
8586  ast_debug(1, "Sending hold on '%s'\n", ast_channel_name(ast));
8587  return &p->subs[idx].f;
8588  }
8589 
8590  if (p->subs[idx].needunhold) {
8591  /* Send answer frame if requested */
8592  p->subs[idx].needunhold = 0;
8593  p->subs[idx].f.frametype = AST_FRAME_CONTROL;
8595  ast_mutex_unlock(&p->lock);
8596  ast_debug(1, "Sending unhold on '%s'\n", ast_channel_name(ast));
8597  return &p->subs[idx].f;
8598  }
8599 
8600  /*
8601  * If we have a fake_event, fake an exception to handle it only
8602  * if this channel owns the private.
8603  */
8604  if (p->fake_event && p->owner == ast) {
8605  if (dahdi_analog_lib_handles(p->sig, p->radio, p->oprmode)) {
8606  struct analog_pvt *analog_p = p->sig_pvt;
8607 
8608  f = analog_exception(analog_p, ast);
8609  } else {
8610  f = __dahdi_exception(ast);
8611  }
8612  ast_mutex_unlock(&p->lock);
8613  return f;
8614  }
8615 
8617  if (!p->subs[idx].linear) {
8618  p->subs[idx].linear = 1;
8619  res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
8620  if (res)
8621  ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to linear mode.\n", p->channel, idx);
8622  }
8623  } else {
8624  if (p->subs[idx].linear) {
8625  p->subs[idx].linear = 0;
8626  res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
8627  if (res)
8628  ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to companded mode.\n", p->channel, idx);
8629  }
8630  }
8631  readbuf = ((unsigned char *)p->subs[idx].buffer) + AST_FRIENDLY_OFFSET;
8632  CHECK_BLOCKING(ast);
8633  res = read(p->subs[idx].dfd, readbuf, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
8635  /* Check for hangup */
8636  if (res < 0) {
8637  f = NULL;
8638  if (res == -1) {
8639  if (errno == EAGAIN) {
8640  /* Return "NULL" frame if there is nobody there */
8641  ast_mutex_unlock(&p->lock);
8642  return &p->subs[idx].f;
8643  } else if (errno == ELAST) {
8644  if (dahdi_analog_lib_handles(p->sig, p->radio, p->oprmode)) {
8645  struct analog_pvt *analog_p = p->sig_pvt;
8646  f = analog_exception(analog_p, ast);
8647  } else {
8648  f = __dahdi_exception(ast);
8649  }
8650  } else
8651  ast_log(LOG_WARNING, "dahdi_rec: %s\n", strerror(errno));
8652  }
8653  ast_mutex_unlock(&p->lock);
8654  return f;
8655  }
8656  if (res != (p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE)) {
8657  ast_debug(1, "Short read (%d/%d), must be an event...\n", res, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
8658  if (dahdi_analog_lib_handles(p->sig, p->radio, p->oprmode)) {
8659  struct analog_pvt *analog_p = p->sig_pvt;
8660  f = analog_exception(analog_p, ast);
8661  } else {
8662  f = __dahdi_exception(ast);
8663  }
8664  ast_mutex_unlock(&p->lock);
8665  return f;
8666  }
8667  if (p->tdd) { /* if in TDD mode, see if we receive that */
8668  int c;
8669 
8670  c = tdd_feed(p->tdd,readbuf,READ_SIZE);
8671  if (c < 0) {
8672  ast_debug(1,"tdd_feed failed\n");
8673  ast_mutex_unlock(&p->lock);
8674  return NULL;
8675  }
8676  if (c) { /* if a char to return */
8677  p->subs[idx].f.subclass.integer = 0;
8678  p->subs[idx].f.frametype = AST_FRAME_TEXT;
8679  p->subs[idx].f.mallocd = 0;
8680  p->subs[idx].f.offset = AST_FRIENDLY_OFFSET;
8681  p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET;
8682  p->subs[idx].f.datalen = 1;
8683  *((char *) p->subs[idx].f.data.ptr) = c;
8684  ast_mutex_unlock(&p->lock);
8685  return &p->subs[idx].f;
8686  }
8687  }
8688  if (idx == SUB_REAL) {
8689  /* Ensure the CW timers decrement only on a single subchannel */
8690  if (p->cidcwexpire) {
8691  if (!--p->cidcwexpire) {
8692  /* Expired CID/CW */
8693  ast_verb(3, "CPE does not support Call Waiting Caller*ID.\n");
8694  restore_conference(p);
8695  }
8696  }
8697  if (p->cid_suppress_expire) {
8698  --p->cid_suppress_expire;
8699  }
8700  if (p->callwaitingrepeat) {
8701  if (!--p->callwaitingrepeat) {
8702  /* Expired, Repeat callwaiting tone */
8703  ++p->callwaitrings;
8704  dahdi_callwait(ast);
8705  }
8706  }
8707  }
8708  if (p->subs[idx].linear) {
8709  p->subs[idx].f.datalen = READ_SIZE * 2;
8710  } else
8711  p->subs[idx].f.datalen = READ_SIZE;
8712 
8713  /* Handle CallerID Transmission */
8714  if ((p->owner == ast) && p->cidspill) {
8715  send_callerid(p);
8716  }
8717 
8718  p->subs[idx].f.frametype = AST_FRAME_VOICE;
8720  p->subs[idx].f.samples = READ_SIZE;
8721  p->subs[idx].f.mallocd = 0;
8722  p->subs[idx].f.offset = AST_FRIENDLY_OFFSET;
8723  p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET / sizeof(p->subs[idx].buffer[0]);
8724 #if 0
8725  ast_debug(1, "Read %d of voice on %s\n", p->subs[idx].f.datalen, ast->name);
8726 #endif
8727  if ((p->dialing && !p->waitingfordt.tv_sec) || p->radio || /* Transmitting something */
8728  (idx && (ast_channel_state(ast) != AST_STATE_UP)) || /* Three-way or callwait that isn't up */
8729  ((idx == SUB_CALLWAIT) && !p->subs[SUB_CALLWAIT].inthreeway) /* Inactive and non-confed call-wait */
8730  ) {
8731  /* Whoops, we're still dialing, or in a state where we shouldn't transmit....
8732  don't send anything */
8733  p->subs[idx].f.frametype = AST_FRAME_NULL;
8734  p->subs[idx].f.subclass.integer = 0;
8735  p->subs[idx].f.samples = 0;
8736  p->subs[idx].f.mallocd = 0;
8737  p->subs[idx].f.offset = 0;
8738  p->subs[idx].f.data.ptr = NULL;
8739  p->subs[idx].f.datalen= 0;
8740  }
8741  if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect || p->callprogress || p->waitingfordt.tv_sec || p->dialtone_detect) && !idx) {
8742  /* Perform busy detection etc on the dahdi line */
8743  int mute;
8744 
8746  && p->faxdetect_timeout
8750  ast_debug(1, "Channel driver fax CNG detection timeout on %s\n",
8751  ast_channel_name(ast));
8752  }
8753 
8754  f = ast_dsp_process(ast, p->dsp, &p->subs[idx].f);
8755 
8756  /* Check if DSP code thinks we should be muting this frame and mute the conference if so */
8757  mute = ast_dsp_was_muted(p->dsp);
8758  if (p->muting != mute) {
8759  p->muting = mute;
8760  dahdi_confmute(p, mute);
8761  }
8762 
8763  if (f) {
8765  && !p->outgoing && ast_channel_state(ast) == AST_STATE_UP) {
8769  }
8770  }
8771  if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass.integer == AST_CONTROL_BUSY)) {
8772  if ((ast_channel_state(ast) == AST_STATE_UP) && !p->outgoing) {
8773  /*
8774  * Treat this as a "hangup" instead of a "busy" on the
8775  * assumption that a busy means the incoming call went away.
8776  */
8777  ast_frfree(f);
8778  f = NULL;
8779  }
8780  } else if (p->dialtone_detect && !p->outgoing && f->frametype == AST_FRAME_VOICE) {
8782  /* Dialtone detected on inbound call; hangup the channel */
8783  ast_frfree(f);
8784  f = NULL;
8785  }
8786  } else if (f->frametype == AST_FRAME_DTMF_BEGIN
8787  || f->frametype == AST_FRAME_DTMF_END) {
8788 #ifdef HAVE_PRI
8790  && ((struct sig_pri_chan *) p->sig_pvt)->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING
8791  && p->pri
8792  && ((!p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING))
8793  || (p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)))) {
8794  /* Don't accept in-band DTMF when in overlap dial mode */
8795  ast_debug(1, "Absorbing inband %s DTMF digit: 0x%02X '%c' on %s\n",
8796  f->frametype == AST_FRAME_DTMF_BEGIN ? "begin" : "end",
8797  (unsigned)f->subclass.integer, f->subclass.integer, ast_channel_name(ast));
8798 
8800  f->subclass.integer = 0;
8801  }
8802 #endif
8803  /* DSP clears us of being pulse */
8804  p->pulsedial = 0;
8805  } else if (p->waitingfordt.tv_sec) {
8807  p->waitingfordt.tv_sec = 0;
8808  ast_log(LOG_WARNING, "Never saw dialtone on channel %d\n", p->channel);
8809  ast_frfree(f);
8810  f = NULL;
8811  } else if (f->frametype == AST_FRAME_VOICE) {
8813  f->subclass.integer = 0;
8815  p->waitingfordt.tv_sec = 0;
8818  ast_debug(1, "Got 10 samples of dialtone!\n");
8819  if (!ast_strlen_zero(p->dop.dialstr)) { /* Dial deferred digits */
8820  res = dahdi_dial_str(p, p->dop.op, p->dop.dialstr);
8821  if (res) {
8822  p->dop.dialstr[0] = '\0';
8823  ast_mutex_unlock(&p->lock);
8824  ast_frfree(f);
8825  return NULL;
8826  } else {
8827  ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
8828  p->dialing = 1;
8829  p->dop.dialstr[0] = '\0';
8830  p->dop.op = DAHDI_DIAL_OP_REPLACE;
8832  }
8833  }
8834  }
8835  }
8836  }
8837  }
8838  } else
8839  f = &p->subs[idx].f;
8840 
8841  if (f) {
8842  switch (f->frametype) {
8843  case AST_FRAME_DTMF_BEGIN:
8844  case AST_FRAME_DTMF_END:
8845  if (dahdi_analog_lib_handles(p->sig, p->radio, p->oprmode)) {
8846  analog_handle_dtmf(p->sig_pvt, ast, idx, &f);
8847  } else {
8848  dahdi_handle_dtmf(ast, idx, &f);
8849  }
8850  break;
8851  case AST_FRAME_VOICE:
8852  if (p->cidspill || p->cid_suppress_expire) {
8853  /* We are/were sending a caller id spill. Suppress any echo. */
8854  p->subs[idx].f.frametype = AST_FRAME_NULL;
8855  p->subs[idx].f.subclass.integer = 0;
8856  p->subs[idx].f.samples = 0;
8857  p->subs[idx].f.mallocd = 0;
8858  p->subs[idx].f.offset = 0;
8859  p->subs[idx].f.data.ptr = NULL;
8860  p->subs[idx].f.datalen= 0;
8861  }
8862  break;
8863  default:
8864  break;
8865  }
8866  }
8867 
8868  ast_mutex_unlock(&p->lock);
8869  return f;
8870 }
8871 
8872 static int my_dahdi_write(struct dahdi_pvt *p, unsigned char *buf, int len, int idx, int linear)
8873 {
8874  int sent=0;
8875  int size;
8876  int res;
8877  int fd;
8878  fd = p->subs[idx].dfd;
8879  while (len) {
8880  size = len;
8881  if (size > (linear ? READ_SIZE * 2 : READ_SIZE))
8882  size = (linear ? READ_SIZE * 2 : READ_SIZE);
8883  res = write(fd, buf, size);
8884  if (res != size) {
8885  ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
8886  return sent;
8887  }
8888  len -= size;
8889  buf += size;
8890  }
8891  return sent;
8892 }
8893 
8894 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame)
8895 {
8896  struct dahdi_pvt *p;
8897  int res;
8898  int idx;
8899 
8900  /* Write a frame of (presumably voice) data */
8901  if (frame->frametype != AST_FRAME_VOICE) {
8902  if (frame->frametype != AST_FRAME_IMAGE) {
8903  ast_log(LOG_WARNING, "Don't know what to do with frame type '%u'\n",
8904  frame->frametype);
8905  }
8906  return 0;
8907  }
8908 
8909  /* Return if it's not valid data */
8910  if (!frame->data.ptr || !frame->datalen) {
8911  return 0;
8912  }
8913 
8914  p = ast_channel_tech_pvt(ast);
8915  ast_mutex_lock(&p->lock);
8916 
8917  idx = dahdi_get_index(ast, p, 0);
8918  if (idx < 0) {
8919  ast_mutex_unlock(&p->lock);
8920  ast_log(LOG_WARNING, "%s doesn't really exist?\n", ast_channel_name(ast));
8921  return -1;
8922  }
8923 
8924  if (p->dialing) {
8925  ast_mutex_unlock(&p->lock);
8926  ast_debug(5, "Dropping frame since I'm still dialing on %s...\n",
8927  ast_channel_name(ast));
8928  return 0;
8929  }
8930  if (!p->owner) {
8931  ast_mutex_unlock(&p->lock);
8932  ast_debug(5, "Dropping frame since there is no active owner on %s...\n",
8933  ast_channel_name(ast));
8934  return 0;
8935  }
8936  if (p->cidspill) {
8937  ast_mutex_unlock(&p->lock);
8938  ast_debug(5, "Dropping frame since I've still got a callerid spill on %s...\n",
8939  ast_channel_name(ast));
8940  return 0;
8941  }
8942 
8944  if (!p->subs[idx].linear) {
8945  p->subs[idx].linear = 1;
8946  res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
8947  if (res)
8948  ast_log(LOG_WARNING, "Unable to set linear mode on channel %d\n", p->channel);
8949  }
8950  res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 1);
8953  /* x-law already */
8954  if (p->subs[idx].linear) {
8955  p->subs[idx].linear = 0;
8956  res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
8957  if (res)
8958  ast_log(LOG_WARNING, "Unable to set companded mode on channel %d\n", p->channel);
8959  }
8960  res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 0);
8961  } else {
8962  ast_mutex_unlock(&p->lock);
8963  ast_log(LOG_WARNING, "Cannot handle frames in %s format\n",
8965  return -1;
8966  }
8967  ast_mutex_unlock(&p->lock);
8968  if (res < 0) {
8969  ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
8970  return -1;
8971  }
8972  return 0;
8973 }
8974 
8975 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen)
8976 {
8977  struct dahdi_pvt *p = ast_channel_tech_pvt(chan);
8978  int res=-1;
8979  int idx;
8980  int func = DAHDI_FLASH;
8981 
8982  ast_mutex_lock(&p->lock);
8983  ast_debug(1, "Requested indication %d on channel %s\n", condition, ast_channel_name(chan));
8984  switch (p->sig) {
8985 #if defined(HAVE_PRI)
8987  res = sig_pri_indicate(p->sig_pvt, chan, condition, data, datalen);
8988  ast_mutex_unlock(&p->lock);
8989  return res;
8990 #endif /* defined(HAVE_PRI) */
8991 #if defined(HAVE_SS7)
8992  case SIG_SS7:
8993  res = sig_ss7_indicate(p->sig_pvt, chan, condition, data, datalen);
8994  ast_mutex_unlock(&p->lock);
8995  return res;
8996 #endif /* defined(HAVE_SS7) */
8997  default:
8998  break;
8999  }
9000 #ifdef HAVE_OPENR2
9001  if (p->mfcr2 && !p->mfcr2_call_accepted) {
9002  ast_mutex_unlock(&p->lock);
9003  /* if this is an R2 call and the call is not yet accepted, we don't want the
9004  tone indications to mess up with the MF tones */
9005  return 0;
9006  }
9007 #endif
9008  idx = dahdi_get_index(chan, p, 0);
9009  if (idx == SUB_REAL) {
9010  switch (condition) {
9011  case AST_CONTROL_BUSY:
9012  res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_BUSY);
9013  break;
9014  case AST_CONTROL_RINGING:
9015  res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_RINGTONE);
9016 
9017  if (ast_channel_state(chan) != AST_STATE_UP) {
9018  if ((ast_channel_state(chan) != AST_STATE_RING) ||
9019  ((p->sig != SIG_FXSKS) &&
9020  (p->sig != SIG_FXSLS) &&
9021  (p->sig != SIG_FXSGS)))
9023  }
9024  break;
9026  ast_debug(1, "Received AST_CONTROL_INCOMPLETE on %s\n", ast_channel_name(chan));
9027  /* act as a progress or proceeding, allowing the caller to enter additional numbers */
9028  res = 0;
9029  break;
9031  ast_debug(1, "Received AST_CONTROL_PROCEEDING on %s\n", ast_channel_name(chan));
9032  /* don't continue in ast_indicate */
9033  res = 0;
9034  break;
9035  case AST_CONTROL_PROGRESS:
9036  ast_debug(1, "Received AST_CONTROL_PROGRESS on %s\n", ast_channel_name(chan));
9037  /* don't continue in ast_indicate */
9038  res = 0;
9039  break;
9041  /* There are many cause codes that generate an AST_CONTROL_CONGESTION. */
9042  switch (ast_channel_hangupcause(chan)) {
9043  case AST_CAUSE_USER_BUSY:
9045  case 0:/* Cause has not been set. */
9046  /* Supply a more appropriate cause. */
9048  break;
9049  default:
9050  break;
9051  }
9052  break;
9053  case AST_CONTROL_HOLD:
9054  ast_moh_start(chan, data, p->mohinterpret);
9055  break;
9056  case AST_CONTROL_UNHOLD:
9057  ast_moh_stop(chan);
9058  break;
9059  case AST_CONTROL_RADIO_KEY:
9060  if (p->radio)
9061  res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
9062  res = 0;
9063  break;
9065  if (p->radio)
9066  res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_RINGOFF);
9067  res = 0;
9068  break;
9069  case AST_CONTROL_FLASH:
9070  /* flash hookswitch */
9071  if (ISTRUNK(p) && (p->sig != SIG_PRI)) {
9072  /* Clear out the dial buffer */
9073  p->dop.dialstr[0] = '\0';
9074  if ((ioctl(p->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
9075  ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
9076  ast_channel_name(chan), strerror(errno));
9077  } else
9078  res = 0;
9079  } else
9080  res = 0;
9081  break;
9082  case AST_CONTROL_SRCUPDATE:
9083  res = 0;
9084  break;
9085  case -1:
9086  res = tone_zone_play_tone(p->subs[idx].dfd, -1);
9087  break;
9088  }
9089  } else {
9090  res = 0;
9091  }
9092  ast_mutex_unlock(&p->lock);
9093  return res;
9094 }
9095 
9096 #if defined(HAVE_PRI)
9097 static struct ast_str *create_channel_name(struct dahdi_pvt *i, int is_outgoing, char *address)
9098 #else
9099 static struct ast_str *create_channel_name(struct dahdi_pvt *i)
9100 #endif /* defined(HAVE_PRI) */
9101 {
9102  struct ast_str *chan_name;
9103  int x, y;
9104 
9105  /* Create the new channel name tail. */
9106  if (!(chan_name = ast_str_create(32))) {
9107  return NULL;
9108  }
9109  if (i->channel == CHAN_PSEUDO) {
9110  ast_str_set(&chan_name, 0, "pseudo-%ld", ast_random());
9111 #if defined(HAVE_PRI)
9112  } else if (i->pri) {
9113  ast_mutex_lock(&i->pri->lock);
9114  y = ++i->pri->new_chan_seq;
9115  if (is_outgoing) {
9116  ast_str_set(&chan_name, 0, "i%d/%s-%x", i->pri->span, address, (unsigned)y);
9117  address[0] = '\0';
9118  } else if (ast_strlen_zero(i->cid_subaddr)) {
9119  /* Put in caller-id number only since there is no subaddress. */
9120  ast_str_set(&chan_name, 0, "i%d/%s-%x", i->pri->span, i->cid_num, (unsigned)y);
9121  } else {
9122  /* Put in caller-id number and subaddress. */
9123  ast_str_set(&chan_name, 0, "i%d/%s:%s-%x", i->pri->span, i->cid_num,
9124  i->cid_subaddr, (unsigned)y);
9125  }
9126  ast_mutex_unlock(&i->pri->lock);
9127 #endif /* defined(HAVE_PRI) */
9128  } else {
9129  y = 1;
9130  do {
9131  ast_str_set(&chan_name, 0, "%d-%d", i->channel, y);
9132  for (x = 0; x < 3; ++x) {
9133  if (i->subs[x].owner && !strcasecmp(ast_str_buffer(chan_name),
9134  ast_channel_name(i->subs[x].owner) + 6)) {
9135  break;
9136  }
9137  }
9138  ++y;
9139  } while (x < 3);
9140  }
9141  return chan_name;
9142 }
9143 
9144 static struct ast_channel *dahdi_new_callid_clean(struct dahdi_pvt *i, int state, int startpbx, int idx, int law, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, ast_callid callid, int callid_created)
9145 {
9146  struct ast_channel *new_channel = dahdi_new(i, state, startpbx, idx, law, assignedids, requestor, callid);
9147 
9148  ast_callid_threadstorage_auto_clean(callid, callid_created);
9149 
9150  return new_channel;
9151 }
9152 
9153 static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpbx, int idx, int law, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, ast_callid callid)
9154 {
9155  struct ast_channel *tmp;
9156  struct ast_format_cap *caps;
9157  struct ast_format *deflaw;
9158  int x;
9159  int features;
9160  struct ast_str *chan_name;
9161  struct ast_variable *v;
9162  char *dashptr;
9163  char device_name[AST_CHANNEL_NAME];
9164 
9165  if (i->subs[idx].owner) {
9166  ast_log(LOG_WARNING, "Channel %d already has a %s call\n", i->channel,subnames[idx]);
9167  return NULL;
9168  }
9169 
9170 #if defined(HAVE_PRI)
9171  /*
9172  * The dnid has been stuffed with the called-number[:subaddress]
9173  * by dahdi_request() for outgoing calls.
9174  */
9175  chan_name = create_channel_name(i, i->outgoing, i->dnid);
9176 #else
9177  chan_name = create_channel_name(i);
9178 #endif /* defined(HAVE_PRI) */
9179  if (!chan_name) {
9180  return NULL;
9181  }
9182 
9184  if (!caps) {
9185  ast_free(chan_name);
9186  return NULL;
9187  }
9188 
9189  tmp = ast_channel_alloc(0, state, i->cid_num, i->cid_name, i->accountcode, i->exten, i->context, assignedids, requestor, i->amaflags, "DAHDI/%s", ast_str_buffer(chan_name));
9190  ast_free(chan_name);
9191  if (!tmp) {
9192  ao2_ref(caps, -1);
9193  return NULL;
9194  }
9195 
9197 
9198  if (callid) {
9199  ast_channel_callid_set(tmp, callid);
9200  }
9201 
9202  ast_channel_tech_set(tmp, &dahdi_tech);
9203 #if defined(HAVE_PRI)
9204  if (i->pri) {
9206  }
9207 #endif /* defined(HAVE_PRI) */
9209  if (law) {
9210  i->law = law;
9211  if (law == DAHDI_LAW_ALAW) {
9212  deflaw = ast_format_alaw;
9213  } else {
9214  deflaw = ast_format_ulaw;
9215  }
9216  } else {
9217  switch (i->sig) {
9219  /* Make sure companding law is known. */
9220  i->law = (i->law_default == DAHDI_LAW_ALAW)
9221  ? DAHDI_LAW_ALAW : DAHDI_LAW_MULAW;
9222  break;
9223  default:
9224  i->law = i->law_default;
9225  break;
9226  }
9227  if (i->law_default == DAHDI_LAW_ALAW) {
9228  deflaw = ast_format_alaw;
9229  } else {
9230  deflaw = ast_format_ulaw;
9231  }
9232  }
9233  ast_channel_set_fd(tmp, 0, i->subs[idx].dfd);
9234  ast_format_cap_append(caps, deflaw, 0);
9235  ast_channel_nativeformats_set(tmp, caps);
9236  ao2_ref(caps, -1);
9237  /* Start out assuming ulaw since it's smaller :) */
9238  ast_channel_set_rawreadformat(tmp, deflaw);
9239  ast_channel_set_readformat(tmp, deflaw);
9240  ast_channel_set_rawwriteformat(tmp, deflaw);
9241  ast_channel_set_writeformat(tmp, deflaw);
9242  i->subs[idx].linear = 0;
9243  dahdi_setlinear(i->subs[idx].dfd, i->subs[idx].linear);
9244  features = 0;
9245  if (idx == SUB_REAL) {
9246  if (i->busydetect && CANBUSYDETECT(i))
9247  features |= DSP_FEATURE_BUSY_DETECT;
9249  features |= DSP_FEATURE_CALL_PROGRESS;
9250  if ((i->waitfordialtone || i->dialtone_detect) && CANPROGRESSDETECT(i))
9251  features |= DSP_FEATURE_WAITDIALTONE;
9252  if ((!i->outgoing && (i->callprogress & CALLPROGRESS_FAX_INCOMING)) ||
9254  features |= DSP_FEATURE_FAX_DETECT;
9255  }
9256  x = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
9257  if (ioctl(i->subs[idx].dfd, DAHDI_TONEDETECT, &x)) {
9258  i->hardwaredtmf = 0;
9259  features |= DSP_FEATURE_DIGIT_DETECT;
9260  } else if (NEED_MFDETECT(i)) {
9261  i->hardwaredtmf = 1;
9262  features |= DSP_FEATURE_DIGIT_DETECT;
9263  }
9264  }
9265  if (features) {
9266  if (i->dsp) {
9267  ast_debug(1, "Already have a dsp on %s?\n", ast_channel_name(tmp));
9268  } else {
9269  if (i->channel != CHAN_PSEUDO)
9270  i->dsp = ast_dsp_new();
9271  else
9272  i->dsp = NULL;
9273  if (i->dsp) {
9274  i->dsp_features = features;
9275 #if defined(HAVE_PRI) || defined(HAVE_SS7)
9276  /* We cannot do progress detection until receive PROGRESS message */
9277  if (i->outgoing && (dahdi_sig_pri_lib_handles(i->sig) || (i->sig == SIG_SS7))) {
9278  /* Remember requested DSP features, don't treat
9279  talking as ANSWER */
9280  i->dsp_features = features & ~DSP_PROGRESS_TALK;
9281  features = 0;
9282  }
9283 #endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */
9284  ast_dsp_set_features(i->dsp, features);
9286  if (!ast_strlen_zero(progzone))
9288  if (i->busydetect && CANBUSYDETECT(i)) {
9291  }
9292  }
9293  }
9294  }
9295 
9297 
9298  if (state == AST_STATE_RING)
9299  ast_channel_rings_set(tmp, 1);
9300  ast_channel_tech_pvt_set(tmp, i);
9301  if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) {
9302  /* Only FXO signalled stuff can be picked up */
9307  }
9308  if (!ast_strlen_zero(i->parkinglot))
9309  ast_channel_parkinglot_set(tmp, i->parkinglot);
9310  if (!ast_strlen_zero(i->language))
9311  ast_channel_language_set(tmp, i->language);
9312  if (!i->owner)
9313  i->owner = tmp;
9314  if (!ast_strlen_zero(i->accountcode))
9315  ast_channel_accountcode_set(tmp, i->accountcode);
9316  if (i->amaflags)
9318  i->subs[idx].owner = tmp;
9320  if (!dahdi_analog_lib_handles(i->sig, i->radio, i->oprmode)) {
9321  ast_channel_call_forward_set(tmp, i->call_forward);
9322  }
9323  /* If we've been told "no ADSI" then enforce it */
9324  if (!i->adsi)
9326  if (!ast_strlen_zero(i->exten))
9327  ast_channel_exten_set(tmp, i->exten);
9328  if (!ast_strlen_zero(i->rdnis)) {
9331  }
9332  if (!ast_strlen_zero(i->dnid)) {
9334  }
9335 
9336  /* Don't use ast_set_callerid() here because it will
9337  * generate a needless NewCallerID event */
9338 #if defined(HAVE_PRI) || defined(HAVE_SS7)
9339  if (!ast_strlen_zero(i->cid_ani)) {
9340  ast_channel_caller(tmp)->ani.number.valid = 1;
9341  ast_channel_caller(tmp)->ani.number.str = ast_strdup(i->cid_ani);
9342  } else if (!ast_strlen_zero(i->cid_num)) {
9343  ast_channel_caller(tmp)->ani.number.valid = 1;
9345  }
9346 #else
9347  if (!ast_strlen_zero(i->cid_num)) {
9348  ast_channel_caller(tmp)->ani.number.valid = 1;
9350  }
9351 #endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */
9355  ast_channel_caller(tmp)->ani2 = i->cid_ani2;
9357  /* clear the fake event in case we posted one before we had ast_channel */
9358  i->fake_event = 0;
9359  /* Assure there is no confmute on this channel */
9360  dahdi_confmute(i, 0);
9361  i->muting = 0;
9362  /* Configure the new channel jb */
9364 
9365  /* Set initial device state */
9366  ast_copy_string(device_name, ast_channel_name(tmp), sizeof(device_name));
9367  dashptr = strrchr(device_name, '-');
9368  if (dashptr) {
9369  *dashptr = '\0';
9370  }
9373 
9374  for (v = i->vars ; v ; v = v->next)
9375  pbx_builtin_setvar_helper(tmp, v->name, v->value);
9376 
9378 
9379  ast_channel_unlock(tmp);
9380 
9382 
9383  dahdi_ami_channel_event(i, tmp);
9384  if (startpbx) {
9385 #ifdef HAVE_OPENR2
9386  if (i->mfcr2call) {
9387  pbx_builtin_setvar_helper(tmp, "MFCR2_CATEGORY", openr2_proto_get_category_string(i->mfcr2_recvd_category));
9388  }
9389 #endif
9390  if (ast_pbx_start(tmp)) {
9391  ast_log(LOG_WARNING, "Unable to start PBX on %s\n", ast_channel_name(tmp));
9392  ast_hangup(tmp);
9393  return NULL;
9394  }
9395  }
9396  return tmp;
9397 }
9398 
9399 
9400 static int my_getsigstr(struct ast_channel *chan, char *str, const char *term, int ms)
9401 {
9402  char c;
9403 
9404  *str = 0; /* start with empty output buffer */
9405  for (;;)
9406  {
9407  /* Wait for the first digit (up to specified ms). */
9408  c = ast_waitfordigit(chan, ms);
9409  /* if timeout, hangup or error, return as such */
9410  if (c < 1)
9411  return c;
9412  *str++ = c;
9413  *str = 0;
9414  if (strchr(term, c))
9415  return 1;
9416  }
9417 }
9418 
9419 static int dahdi_wink(struct dahdi_pvt *p, int idx)
9420 {
9421  int j;
9422  dahdi_set_hook(p->subs[idx].dfd, DAHDI_WINK);
9423  for (;;)
9424  {
9425  /* set bits of interest */
9426  j = DAHDI_IOMUX_SIGEVENT;
9427  /* wait for some happening */
9428  if (ioctl(p->subs[idx].dfd,DAHDI_IOMUX,&j) == -1) return(-1);
9429  /* exit loop if we have it */
9430  if (j & DAHDI_IOMUX_SIGEVENT) break;
9431  }
9432  /* get the event info */
9433  if (ioctl(p->subs[idx].dfd,DAHDI_GETEVENT,&j) == -1) return(-1);
9434  return 0;
9435 }
9436 
9437 static void publish_dnd_state(int channel, const char *status)
9438 {
9439  RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
9440  RAII_VAR(struct ast_str *, dahdichan, ast_str_create(32), ast_free);
9441  if (!dahdichan) {
9442  return;
9443  }
9444 
9445  ast_str_set(&dahdichan, 0, "%d", channel);
9446 
9447  body = ast_json_pack("{s: s, s: s}",
9448  "DAHDIChannel", ast_str_buffer(dahdichan),
9449  "Status", status);
9450  if (!body) {
9451  return;
9452  }
9453 
9454  ast_manager_publish_event("DNDState", EVENT_FLAG_SYSTEM, body);
9455 }
9456 
9457 /*! \brief enable or disable the chan_dahdi Do-Not-Disturb mode for a DAHDI channel
9458  * \param dahdichan "Physical" DAHDI channel (e.g: DAHDI/5)
9459  * \param flag on 1 to enable, 0 to disable, -1 return dnd value
9460  *
9461  * chan_dahdi has a DND (Do Not Disturb) mode for each dahdichan (physical
9462  * DAHDI channel). Use this to enable or disable it.
9463  *
9464  * \bug the use of the word "channel" for those dahdichans is really confusing.
9465  */
9466 static int dahdi_dnd(struct dahdi_pvt *dahdichan, int flag)
9467 {
9468  if (dahdi_analog_lib_handles(dahdichan->sig, dahdichan->radio, dahdichan->oprmode)) {
9469  return analog_dnd(dahdichan->sig_pvt, flag);
9470  }
9471 
9472  if (flag == -1) {
9473  return dahdichan->dnd;
9474  }
9475 
9476  /* Do not disturb */
9477  dahdichan->dnd = flag;
9478  ast_verb(3, "%s DND on channel %d\n",
9479  flag? "Enabled" : "Disabled",
9480  dahdichan->channel);
9481  publish_dnd_state(dahdichan->channel, flag ? "enabled" : "disabled");
9482  return 0;
9483 }
9484 
9485 static int canmatch_featurecode(const char *pickupexten, const char *exten)
9486 {
9487  int extlen = strlen(exten);
9488 
9489  if (!extlen) {
9490  return 1;
9491  }
9492 
9493  if (extlen < strlen(pickupexten) && !strncmp(pickupexten, exten, extlen)) {
9494  return 1;
9495  }
9496  /* hardcoded features are *60, *67, *69, *70, *72, *73, *78, *79, *82, *0 */
9497  if (exten[0] == '*' && extlen < 3) {
9498  if (extlen == 1) {
9499  return 1;
9500  }
9501  /* "*0" should be processed before it gets here */
9502  switch (exten[1]) {
9503  case '6':
9504  case '7':
9505  case '8':
9506  return 1;
9507  }
9508  }
9509  return 0;
9510 }
9511 
9512 static void *analog_ss_thread(void *data)
9513 {
9514  struct ast_channel *chan = data;
9515  struct dahdi_pvt *p = ast_channel_tech_pvt(chan);
9516  char exten[AST_MAX_EXTENSION] = "";
9517  char exten2[AST_MAX_EXTENSION] = "";
9518  unsigned char buf[256];
9519  char dtmfcid[300];
9520  char dtmfbuf[300];
9521  struct callerid_state *cs = NULL;
9522  char *name = NULL, *number = NULL;
9523  int distMatches;
9524  int curRingData[3];
9525  int receivedRingT;
9526  int counter1;
9527  int counter;
9528  int samples = 0;
9529  struct ast_smdi_md_message *smdi_msg = NULL;
9530  int flags = 0;
9531  int i;
9532  int timeout;
9533  int getforward = 0;
9534  char *s1, *s2;
9535  int len = 0;
9536  int res;
9537  int idx;
9538  RAII_VAR(struct ast_features_pickup_config *, pickup_cfg, NULL, ao2_cleanup);
9539  const char *pickupexten;
9540 
9542  ss_thread_count++;
9544  /* in the bizarre case where the channel has become a zombie before we
9545  even get started here, abort safely
9546  */
9547  if (!p) {
9548  ast_log(LOG_WARNING, "Channel became a zombie before simple switch could be started (%s)\n", ast_channel_name(chan));
9549  ast_hangup(chan);
9550  goto quit;
9551  }
9552  ast_verb(3, "Starting simple switch on '%s'\n", ast_channel_name(chan));
9553  idx = dahdi_get_index(chan, p, 1);
9554  if (idx < 0) {
9555  ast_log(LOG_WARNING, "Huh?\n");
9556  ast_hangup(chan);
9557  goto quit;
9558  }
9559 
9560  ast_channel_lock(chan);
9561  pickup_cfg = ast_get_chan_features_pickup_config(chan);
9562  if (!pickup_cfg) {
9563  ast_log(LOG_ERROR, "Unable to retrieve pickup configuration options. Unable to detect call pickup extension\n");
9564  pickupexten = "";
9565  } else {
9566  pickupexten = ast_strdupa(pickup_cfg->pickupexten);
9567  }
9568  ast_channel_unlock(chan);
9569 
9570  if (p->dsp)
9571  ast_dsp_digitreset(p->dsp);
9572  switch (p->sig) {
9573  case SIG_FEATD:
9574  case SIG_FEATDMF:
9575  case SIG_FEATDMF_TA:
9576  case SIG_E911:
9577  case SIG_FGC_CAMAMF:
9578  case SIG_FEATB:
9579  case SIG_EMWINK:
9580  case SIG_SF_FEATD:
9581  case SIG_SF_FEATDMF:
9582  case SIG_SF_FEATB:
9583  case SIG_SFWINK:
9584  if (dahdi_wink(p, idx))
9585  goto quit;
9586  /* Fall through */
9587  case SIG_EM:
9588  case SIG_EM_E1:
9589  case SIG_SF:
9590  case SIG_FGC_CAMA:
9591  res = tone_zone_play_tone(p->subs[idx].dfd, -1);
9592  if (p->dsp)
9593  ast_dsp_digitreset(p->dsp);
9594  /* set digit mode appropriately */
9595  if (p->dsp) {
9596  if (NEED_MFDETECT(p))
9598  else
9600  }
9601  memset(dtmfbuf, 0, sizeof(dtmfbuf));
9602  /* Wait for the first digit only if immediate=no */
9603  if (!p->immediate)
9604  /* Wait for the first digit (up to 5 seconds). */
9605  res = ast_waitfordigit(chan, 5000);
9606  else
9607  res = 0;
9608  if (res > 0) {
9609  /* save first char */
9610  dtmfbuf[0] = res;
9611  switch (p->sig) {
9612  case SIG_FEATD:
9613  case SIG_SF_FEATD:
9614  res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
9615  if (res > 0)
9616  res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
9617  if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
9618  break;
9619  case SIG_FEATDMF_TA:
9620  res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
9621  if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
9622  if (dahdi_wink(p, idx)) goto quit;
9623  dtmfbuf[0] = 0;
9624  /* Wait for the first digit (up to 5 seconds). */
9625  res = ast_waitfordigit(chan, 5000);
9626  if (res <= 0) break;
9627  dtmfbuf[0] = res;
9628  /* fall through intentionally */
9629  case SIG_FEATDMF:
9630  case SIG_E911:
9631  case SIG_FGC_CAMAMF:
9632  case SIG_SF_FEATDMF:
9633  res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
9634  /* if international caca, do it again to get real ANO */
9635  if ((p->sig == SIG_FEATDMF) && (dtmfbuf[1] != '0') && (strlen(dtmfbuf) != 14))
9636  {
9637  if (dahdi_wink(p, idx)) goto quit;
9638  dtmfbuf[0] = 0;
9639  /* Wait for the first digit (up to 5 seconds). */
9640  res = ast_waitfordigit(chan, 5000);
9641  if (res <= 0) break;
9642  dtmfbuf[0] = res;
9643  res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
9644  }
9645  if (res > 0) {
9646  /* if E911, take off hook */
9647  if (p->sig == SIG_E911)
9648  dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
9649  res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "#", 3000);
9650  }
9651  if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
9652  break;
9653  case SIG_FEATB:
9654  case SIG_SF_FEATB:
9655  res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
9656  if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
9657  break;
9658  case SIG_EMWINK:
9659  /* if we received a '*', we are actually receiving Feature Group D
9660  dial syntax, so use that mode; otherwise, fall through to normal
9661  mode
9662  */
9663  if (res == '*') {
9664  res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
9665  if (res > 0)
9666  res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
9667  if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
9668  break;
9669  }
9670  default:
9671  /* If we got the first digit, get the rest */
9672  len = 1;
9673  dtmfbuf[len] = '\0';
9674  while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, ast_channel_context(chan), dtmfbuf, 1, p->cid_num)) {
9675  if (ast_exists_extension(chan, ast_channel_context(chan), dtmfbuf, 1, p->cid_num)) {
9676  timeout = p->matchdigit_timeout;
9677  } else {
9678  timeout = p->interdigit_timeout;
9679  }
9680  res = ast_waitfordigit(chan, timeout);
9681  if (res < 0) {
9682  ast_debug(1, "waitfordigit returned < 0...\n");
9683  ast_hangup(chan);
9684  goto quit;
9685  } else if (res) {
9686  dtmfbuf[len++] = res;
9687  dtmfbuf[len] = '\0';
9688  } else {
9689  break;
9690  }
9691  }
9692  break;
9693  }
9694  }
9695  if (res == -1) {
9696  ast_log(LOG_WARNING, "getdtmf on channel %d: %s\n", p->channel, strerror(errno));
9697  ast_hangup(chan);
9698  goto quit;
9699  } else if (res < 0) {
9700  ast_debug(1, "Got hung up before digits finished\n");
9701  ast_hangup(chan);
9702  goto quit;
9703  }
9704 
9705  if (p->sig == SIG_FGC_CAMA) {
9706  char anibuf[100];
9707 
9708  if (ast_safe_sleep(chan,1000) == -1) {
9709  ast_hangup(chan);
9710  goto quit;
9711  }
9712  dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
9714  res = my_getsigstr(chan, anibuf, "#", 10000);
9715  if ((res > 0) && (strlen(anibuf) > 2)) {
9716  if (anibuf[strlen(anibuf) - 1] == '#')
9717  anibuf[strlen(anibuf) - 1] = 0;
9718  ast_set_callerid(chan, anibuf + 2, NULL, anibuf + 2);
9719  }
9721  }
9722 
9723  ast_copy_string(exten, dtmfbuf, sizeof(exten));
9724  if (ast_strlen_zero(exten))
9725  ast_copy_string(exten, "s", sizeof(exten));
9726  if (p->sig == SIG_FEATD || p->sig == SIG_EMWINK) {
9727  /* Look for Feature Group D on all E&M Wink and Feature Group D trunks */
9728  if (exten[0] == '*') {
9729  char *stringp=NULL;
9730  ast_copy_string(exten2, exten, sizeof(exten2));
9731  /* Parse out extension and callerid */
9732  stringp=exten2 +1;
9733  s1 = strsep(&stringp, "*");
9734  s2 = strsep(&stringp, "*");
9735  if (s2) {
9736  if (!ast_strlen_zero(p->cid_num))
9737  ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
9738  else
9739  ast_set_callerid(chan, s1, NULL, s1);
9740  ast_copy_string(exten, s2, sizeof(exten));
9741  } else
9742  ast_copy_string(exten, s1, sizeof(exten));
9743  } else if (p->sig == SIG_FEATD)
9744  ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel);
9745  }
9746  if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
9747  if (exten[0] == '*') {
9748  char *stringp=NULL;
9749  ast_copy_string(exten2, exten, sizeof(exten2));
9750  /* Parse out extension and callerid */
9751  stringp=exten2 +1;
9752  s1 = strsep(&stringp, "#");
9753  s2 = strsep(&stringp, "#");
9754  if (s2) {
9755  if (!ast_strlen_zero(p->cid_num))
9756  ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
9757  else
9758  if (*(s1 + 2))
9759  ast_set_callerid(chan, s1 + 2, NULL, s1 + 2);
9760  ast_copy_string(exten, s2 + 1, sizeof(exten));
9761  } else
9762  ast_copy_string(exten, s1 + 2, sizeof(exten));
9763  } else
9764  ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel);
9765  }
9766  if ((p->sig == SIG_E911) || (p->sig == SIG_FGC_CAMAMF)) {
9767  if (exten[0] == '*') {
9768  char *stringp=NULL;
9769  ast_copy_string(exten2, exten, sizeof(exten2));
9770  /* Parse out extension and callerid */
9771  stringp=exten2 +1;
9772  s1 = strsep(&stringp, "#");
9773  s2 = strsep(&stringp, "#");
9774  if (s2 && (*(s2 + 1) == '0')) {
9775  if (*(s2 + 2))
9776  ast_set_callerid(chan, s2 + 2, NULL, s2 + 2);
9777  }
9778  if (s1) ast_copy_string(exten, s1, sizeof(exten));
9779  else ast_copy_string(exten, "911", sizeof(exten));
9780  } else
9781  ast_log(LOG_WARNING, "Got a non-E911/FGC CAMA input on channel %d. Assuming E&M Wink instead\n", p->channel);
9782  }
9783  if (p->sig == SIG_FEATB) {
9784  if (exten[0] == '*') {
9785  char *stringp=NULL;
9786  ast_copy_string(exten2, exten, sizeof(exten2));
9787  /* Parse out extension and callerid */
9788  stringp=exten2 +1;
9789  s1 = strsep(&stringp, "#");
9790  ast_copy_string(exten, exten2 + 1, sizeof(exten));
9791  } else
9792  ast_log(LOG_WARNING, "Got a non-Feature Group B input on channel %d. Assuming E&M Wink instead\n", p->channel);
9793  }
9794  if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
9795  dahdi_wink(p, idx);
9796  /* some switches require a minimum guard time between
9797  the last FGD wink and something that answers
9798  immediately. This ensures it */
9799  if (ast_safe_sleep(chan, 100)) {
9800  ast_hangup(chan);
9801  goto quit;
9802  }
9803  }
9804  dahdi_ec_enable(p);
9805  if (NEED_MFDETECT(p)) {
9806  if (p->dsp) {
9807  if (!p->hardwaredtmf)
9809  else {
9810  ast_dsp_free(p->dsp);
9811  p->dsp = NULL;
9812  }
9813  }
9814  }
9815 
9816  if (ast_exists_extension(chan, ast_channel_context(chan), exten, 1,
9817  S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL))) {
9818  ast_channel_exten_set(chan, exten);
9819  if (p->dsp) ast_dsp_digitreset(p->dsp);
9820  res = ast_pbx_run(chan);
9821  if (res) {
9822  ast_log(LOG_WARNING, "PBX exited non-zero\n");
9823  res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
9824  }
9825  goto quit;
9826  } else {
9827  ast_verb(2, "Unknown extension '%s' in context '%s' requested\n", exten, ast_channel_context(chan));
9828  sleep(2);
9829  res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_INFO);
9830  if (res < 0)
9831  ast_log(LOG_WARNING, "Unable to start special tone on %d\n", p->channel);
9832  else
9833  sleep(1);
9834  res = ast_streamfile(chan, "ss-noservice", ast_channel_language(chan));
9835  if (res >= 0)
9836  ast_waitstream(chan, "");
9837  res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
9838  ast_hangup(chan);
9839  goto quit;
9840  }
9841  break;
9842  case SIG_FXOLS:
9843  case SIG_FXOGS:
9844  case SIG_FXOKS:
9845  /* Read the first digit */
9846  timeout = p->firstdigit_timeout;
9847  /* If starting a threeway call, never timeout on the first digit so someone
9848  can use flash-hook as a "hold" feature */
9849  if (p->subs[SUB_THREEWAY].owner)
9850  timeout = INT_MAX;
9851  while (len < AST_MAX_EXTENSION-1) {
9852  int is_exten_parking = 0;
9853 
9854  /* Read digit unless it's supposed to be immediate, in which case the
9855  only answer is 's' */
9856  if (p->immediate)
9857  res = 's';
9858  else
9859  res = ast_waitfordigit(chan, timeout);
9860  timeout = 0;
9861  if (res < 0) {
9862  ast_debug(1, "waitfordigit returned < 0...\n");
9863  res = tone_zone_play_tone(p->subs[idx].dfd, -1);
9864  ast_hangup(chan);
9865  goto quit;
9866  } else if (res) {
9867  ast_debug(1,"waitfordigit returned '%c' (%d), timeout = %d\n", res, res, timeout);
9868  exten[len++]=res;
9869  exten[len] = '\0';
9870  }
9871  if (!ast_ignore_pattern(ast_channel_context(chan), exten)) {
9872  tone_zone_play_tone(p->subs[idx].dfd, -1);
9873  } else {
9874  tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
9875  }
9877  is_exten_parking = ast_parking_is_exten_park(ast_channel_context(chan), exten);
9878  }
9879  if (ast_exists_extension(chan, ast_channel_context(chan), exten, 1, p->cid_num) && !is_exten_parking) {
9880  if (!res || !ast_matchmore_extension(chan, ast_channel_context(chan), exten, 1, p->cid_num)) {
9881  if (getforward) {
9882  /* Record this as the forwarding extension */
9883  ast_copy_string(p->call_forward, exten, sizeof(p->call_forward));
9884  ast_verb(3, "Setting call forward to '%s' on channel %d\n", p->call_forward, p->channel);
9885  res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
9886  if (res)
9887  break;
9888  usleep(500000);
9889  res = tone_zone_play_tone(p->subs[idx].dfd, -1);
9890  sleep(1);
9891  memset(exten, 0, sizeof(exten));
9892  res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
9893  len = 0;
9894  getforward = 0;
9895  } else {
9896  res = tone_zone_play_tone(p->subs[idx].dfd, -1);
9897  ast_channel_lock(chan);
9898  ast_channel_exten_set(chan, exten);
9899  if (!ast_strlen_zero(p->cid_num)) {
9900  if (!p->hidecallerid)
9901  ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
9902  else
9903  ast_set_callerid(chan, NULL, NULL, p->cid_num);
9904  }
9905  if (!ast_strlen_zero(p->cid_name)) {
9906  if (!p->hidecallerid)
9907  ast_set_callerid(chan, NULL, p->cid_name, NULL);
9908  }
9910  ast_channel_unlock(chan);
9911  dahdi_ec_enable(p);
9912  res = ast_pbx_run(chan);
9913  if (res) {
9914  ast_log(LOG_WARNING, "PBX exited non-zero\n");
9915  res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
9916  }
9917  goto quit;
9918  }
9919  } else {
9920  /* It's a match, but they just typed a digit, and there is an ambiguous match,
9921  so just set the timeout to matchdigit_timeout and wait some more */
9922  timeout = p->matchdigit_timeout;
9923  }
9924  } else if (res == 0) {
9925  ast_debug(1, "not enough digits (and no ambiguous match)...\n");
9926  res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
9927  dahdi_wait_event(p->subs[idx].dfd);
9928  ast_hangup(chan);
9929  goto quit;
9930  } else if (p->callwaiting && !strcmp(exten, "*70")) {
9931  ast_verb(3, "Disabling call waiting on %s\n", ast_channel_name(chan));
9932  /* Disable call waiting if enabled */
9933  p->callwaiting = 0;
9934  res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
9935  if (res) {
9936  ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
9937  ast_channel_name(chan), strerror(errno));
9938  }
9939  len = 0;
9940  ioctl(p->subs[idx].dfd,DAHDI_CONFDIAG,&len);
9941  memset(exten, 0, sizeof(exten));
9942  timeout = p->firstdigit_timeout;
9943 
9944  } else if (!strcmp(exten, pickupexten)) {
9945  /* Scan all channels and see if there are any
9946  * ringing channels that have call groups
9947  * that equal this channels pickup group
9948  */
9949  if (idx == SUB_REAL) {
9950  /* Switch us from Third call to Call Wait */
9951  if (p->subs[SUB_THREEWAY].owner) {
9952  /* If you make a threeway call and the *8# a call, it should actually
9953  look like a callwait */
9954  alloc_sub(p, SUB_CALLWAIT);
9957  }
9958  dahdi_ec_enable(p);
9959  if (ast_pickup_call(chan)) {
9960  ast_debug(1, "No call pickup possible...\n");
9961  res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
9962  dahdi_wait_event(p->subs[idx].dfd);
9963  }
9964  ast_hangup(chan);
9965  goto quit;
9966  } else {
9967  ast_log(LOG_WARNING, "Huh? Got *8# on call not on real\n");
9968  ast_hangup(chan);
9969  goto quit;
9970  }
9971 
9972  } else if (!p->hidecallerid && !strcmp(exten, "*67")) {
9973  ast_verb(3, "Disabling Caller*ID on %s\n", ast_channel_name(chan));
9974  /* Disable Caller*ID if enabled */
9975  p->hidecallerid = 1;
9976  ast_party_number_free(&ast_channel_caller(chan)->id.number);
9977  ast_party_number_init(&ast_channel_caller(chan)->id.number);
9978  ast_party_name_free(&ast_channel_caller(chan)->id.name);
9979  ast_party_name_init(&ast_channel_caller(chan)->id.name);
9980  res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
9981  if (res) {
9982  ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
9983  ast_channel_name(chan), strerror(errno));
9984  }
9985  len = 0;
9986  memset(exten, 0, sizeof(exten));
9987  timeout = p->firstdigit_timeout;
9988  } else if (p->callreturn && !strcmp(exten, "*69")) {
9989  res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
9990  break;
9991  } else if (!strcmp(exten, "*78")) {
9992  dahdi_dnd(p, 1);
9993  /* Do not disturb */
9994  res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
9995  getforward = 0;
9996  memset(exten, 0, sizeof(exten));
9997  len = 0;
9998  } else if (!strcmp(exten, "*79")) {
9999  dahdi_dnd(p, 0);
10000  /* Do not disturb */
10001  res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10002  getforward = 0;
10003  memset(exten, 0, sizeof(exten));
10004  len = 0;
10005  } else if (p->cancallforward && !strcmp(exten, "*72")) {
10006  res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10007  getforward = 1;
10008  memset(exten, 0, sizeof(exten));
10009  len = 0;
10010  } else if (p->cancallforward && !strcmp(exten, "*73")) {
10011  ast_verb(3, "Cancelling call forwarding on channel %d\n", p->channel);
10012  res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10013  memset(p->call_forward, 0, sizeof(p->call_forward));
10014  getforward = 0;
10015  memset(exten, 0, sizeof(exten));
10016  len = 0;
10017  } else if ((p->transfer || p->canpark) && is_exten_parking
10018  && p->subs[SUB_THREEWAY].owner) {
10019  struct ast_bridge_channel *bridge_channel;
10020 
10021  /*
10022  * This is a three way call, the main call being a real channel,
10023  * and we're parking the first call.
10024  */
10026  bridge_channel = ast_channel_get_bridge_channel(p->subs[SUB_THREEWAY].owner);
10028  if (bridge_channel) {
10029  if (!ast_parking_blind_transfer_park(bridge_channel, ast_channel_context(chan), exten, NULL, NULL)) {
10030  /*
10031  * Swap things around between the three-way and real call so we
10032  * can hear where the channel got parked.
10033  */
10034  ast_mutex_lock(&p->lock);
10035  p->owner = p->subs[SUB_THREEWAY].owner;
10037  ast_mutex_unlock(&p->lock);
10038 
10039  ast_verb(3, "%s: Parked call\n", ast_channel_name(chan));
10040  ast_hangup(chan);
10041  ao2_ref(bridge_channel, -1);
10042  goto quit;
10043  }
10044  ao2_ref(bridge_channel, -1);
10045  }
10046  break;
10047  } else if (p->hidecallerid && !strcmp(exten, "*82")) {
10048  ast_verb(3, "Enabling Caller*ID on %s\n", ast_channel_name(chan));
10049  /* Enable Caller*ID if enabled */
10050  p->hidecallerid = 0;
10051  ast_set_callerid(chan, p->cid_num, p->cid_name, NULL);
10052  res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10053  if (res) {
10054  ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
10055  ast_channel_name(chan), strerror(errno));
10056  }
10057  len = 0;
10058  memset(exten, 0, sizeof(exten));
10059  timeout = p->firstdigit_timeout;
10060  } else if (!strcmp(exten, "*0")) {
10061  struct ast_channel *nbridge =
10062  p->subs[SUB_THREEWAY].owner;
10063  struct dahdi_pvt *pbridge = NULL;
10064  RAII_VAR(struct ast_channel *, bridged, nbridge ? ast_channel_bridge_peer(nbridge) : NULL, ast_channel_cleanup);
10065 
10066  /* set up the private struct of the bridged one, if any */
10067  if (nbridge && bridged) {
10068  pbridge = ast_channel_tech_pvt(bridged);
10069  }
10070  if (nbridge && pbridge &&
10071  (ast_channel_tech(nbridge) == &dahdi_tech) &&
10072  (ast_channel_tech(bridged) == &dahdi_tech) &&
10073  ISTRUNK(pbridge)) {
10074  int func = DAHDI_FLASH;
10075  /* Clear out the dial buffer */
10076  p->dop.dialstr[0] = '\0';
10077  /* flash hookswitch */
10078  if ((ioctl(pbridge->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
10079  ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
10080  ast_channel_name(nbridge), strerror(errno));
10081  }
10084  p->owner = p->subs[SUB_REAL].owner;
10086  ast_hangup(chan);
10087  goto quit;
10088  } else {
10089  tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10090  dahdi_wait_event(p->subs[idx].dfd);
10091  tone_zone_play_tone(p->subs[idx].dfd, -1);
10094  p->owner = p->subs[SUB_REAL].owner;
10095  ast_hangup(chan);
10096  goto quit;
10097  }
10098  } else if (!ast_canmatch_extension(chan, ast_channel_context(chan), exten, 1,
10099  S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL))
10100  && !canmatch_featurecode(pickupexten, exten)) {
10101  ast_debug(1, "Can't match %s from '%s' in context %s\n", exten,
10102  S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, "<Unknown Caller>"),
10103  ast_channel_context(chan));
10104  break;
10105  }
10106  if (!timeout)
10107  timeout = p->interdigit_timeout;
10108  if (len && !ast_ignore_pattern(ast_channel_context(chan), exten))
10109  tone_zone_play_tone(p->subs[idx].dfd, -1);
10110  }
10111  break;
10112  case SIG_FXSLS:
10113  case SIG_FXSGS:
10114  case SIG_FXSKS:
10115  /* check for SMDI messages */
10116  if (p->use_smdi && p->smdi_iface) {
10118 
10119  if (smdi_msg != NULL) {
10120  ast_channel_exten_set(chan, smdi_msg->fwd_st);
10121 
10122  if (smdi_msg->type == 'B')
10123  pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "b");
10124  else if (smdi_msg->type == 'N')
10125  pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "u");
10126 
10127  ast_debug(1, "Received SMDI message on %s\n", ast_channel_name(chan));
10128  } else {
10129  ast_log(LOG_WARNING, "SMDI enabled but no SMDI message present\n");
10130  }
10131  }
10132 
10133  if (p->use_callerid && (p->cid_signalling == CID_SIG_SMDI && smdi_msg)) {
10134  number = smdi_msg->calling_st;
10135 
10136  /* If we want caller id, we're in a prering state due to a polarity reversal
10137  * and we're set to use a polarity reversal to trigger the start of caller id,
10138  * grab the caller id and wait for ringing to start... */
10139  } else if (p->use_callerid && (ast_channel_state(chan) == AST_STATE_PRERING &&
10141  /* If set to use DTMF CID signalling, listen for DTMF */
10142  if (p->cid_signalling == CID_SIG_DTMF) {
10143  int k = 0;
10144  int off_ms;
10145  struct timeval start = ast_tvnow();
10146  int ms;
10147  cs = NULL;
10148  ast_debug(1, "Receiving DTMF cid on channel %s\n", ast_channel_name(chan));
10149  dahdi_setlinear(p->subs[idx].dfd, 0);
10150  /*
10151  * We are the only party interested in the Rx stream since
10152  * we have not answered yet. We don't need or even want DTMF
10153  * emulation. The DTMF digits can come so fast that emulation
10154  * can drop some of them.
10155  */
10156  ast_channel_lock(chan);
10158  ast_channel_unlock(chan);
10159  off_ms = 4000;/* This is a typical OFF time between rings. */
10160  for (;;) {
10161  struct ast_frame *f;
10162 
10163  ms = ast_remaining_ms(start, off_ms);
10164  res = ast_waitfor(chan, ms);
10165  if (res <= 0) {
10166  /*
10167  * We do not need to restore the dahdi_setlinear()
10168  * or AST_FLAG_END_DTMF_ONLY flag settings since we
10169  * are hanging up the channel.
10170  */
10171  ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
10172  "Exiting simple switch\n");
10173  ast_hangup(chan);
10174  goto quit;
10175  }
10176  f = ast_read(chan);
10177  if (!f)
10178  break;
10179  if (f->frametype == AST_FRAME_DTMF) {
10180  if (k < ARRAY_LEN(dtmfbuf) - 1) {
10181  dtmfbuf[k++] = f->subclass.integer;
10182  }
10183  ast_debug(1, "CID got digit '%c'\n", f->subclass.integer);
10184  start = ast_tvnow();
10185  }
10186  ast_frfree(f);
10187  if (ast_channel_state(chan) == AST_STATE_RING ||
10189  break; /* Got ring */
10190  }
10191  ast_channel_lock(chan);
10193  ast_channel_unlock(chan);
10194  dtmfbuf[k] = '\0';
10195  dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10196  /* Got cid and ring. */
10197  ast_debug(1, "CID got string '%s'\n", dtmfbuf);
10198  callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
10199  ast_debug(1, "CID is '%s', flags %d\n", dtmfcid, flags);
10200  /* If first byte is NULL, we have no cid */
10201  if (!ast_strlen_zero(dtmfcid))
10202  number = dtmfcid;
10203  else
10204  number = NULL;
10205  /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */
10206  } else if ((p->cid_signalling == CID_SIG_V23) || (p->cid_signalling == CID_SIG_V23_JP)) {
10207  cs = callerid_new(p->cid_signalling);
10208  if (cs) {
10209  int off_ms;
10210  struct timeval start;
10211  int ms;
10212  samples = 0;
10213 #if 1
10214  bump_gains(p);
10215 #endif
10216  /* Take out of linear mode for Caller*ID processing */
10217  dahdi_setlinear(p->subs[idx].dfd, 0);
10218 
10219  /* First we wait and listen for the Caller*ID */
10220  for (;;) {
10221  i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10222  if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10223  ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10224  callerid_free(cs);
10225  ast_hangup(chan);
10226  goto quit;
10227  }
10228  if (i & DAHDI_IOMUX_SIGEVENT) {
10229  res = dahdi_get_event(p->subs[idx].dfd);
10230  ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10231  if (res == DAHDI_EVENT_NOALARM) {
10232  p->inalarm = 0;
10233  }
10234 
10235  if (p->cid_signalling == CID_SIG_V23_JP) {
10236  if (res == DAHDI_EVENT_RINGBEGIN) {
10237  res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
10238  usleep(1);
10239  }
10240  } else {
10241  res = 0;
10242  break;
10243  }
10244  } else if (i & DAHDI_IOMUX_READ) {
10245  res = read(p->subs[idx].dfd, buf, sizeof(buf));
10246  if (res < 0) {
10247  if (errno != ELAST) {
10248  ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10249  callerid_free(cs);
10250  ast_hangup(chan);
10251  goto quit;
10252  }
10253  break;
10254  }
10255  samples += res;
10256 
10257  if (p->cid_signalling == CID_SIG_V23_JP) {
10258  res = callerid_feed_jp(cs, buf, res, AST_LAW(p));
10259  } else {
10260  res = callerid_feed(cs, buf, res, AST_LAW(p));
10261  }
10262  if (res < 0) {
10263  /*
10264  * The previous diagnostic message output likely
10265  * explains why it failed.
10266  */
10268  "Failed to decode CallerID on channel '%s'\n",
10269  ast_channel_name(chan));
10270  break;
10271  } else if (res)
10272  break;
10273  else if (samples > (8000 * 10))
10274  break;
10275  }
10276  }
10277  if (res == 1) {
10278  callerid_get(cs, &name, &number, &flags);
10279  ast_log(LOG_NOTICE, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
10280  }
10281 
10282  if (p->cid_signalling == CID_SIG_V23_JP) {
10283  res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
10284  usleep(1);
10285  }
10286 
10287  /* Finished with Caller*ID, now wait for a ring to make sure there really is a call coming */
10288  start = ast_tvnow();
10289  off_ms = 4000;/* This is a typical OFF time between rings. */
10290  for (;;) {
10291  struct ast_frame *f;
10292 
10293  ms = ast_remaining_ms(start, off_ms);
10294  res = ast_waitfor(chan, ms);
10295  if (res <= 0) {
10296  ast_log(LOG_WARNING, "CID timed out waiting for ring. "
10297  "Exiting simple switch\n");
10298  ast_hangup(chan);
10299  goto quit;
10300  }
10301  if (!(f = ast_read(chan))) {
10302  ast_log(LOG_WARNING, "Hangup received waiting for ring. Exiting simple switch\n");
10303  ast_hangup(chan);
10304  goto quit;
10305  }
10306  ast_frfree(f);
10307  if (ast_channel_state(chan) == AST_STATE_RING ||
10309  break; /* Got ring */
10310  }
10311 
10312  /* We must have a ring by now, so, if configured, lets try to listen for
10313  * distinctive ringing */
10314  if (p->usedistinctiveringdetection) {
10315  len = 0;
10316  distMatches = 0;
10317  /* Clear the current ring data array so we don't have old data in it. */
10318  for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
10319  curRingData[receivedRingT] = 0;
10320  receivedRingT = 0;
10321  counter = 0;
10322  counter1 = 0;
10323  /* Check to see if context is what it should be, if not set to be. */
10324  if (strcmp(p->context,p->defcontext) != 0) {
10325  ast_copy_string(p->context, p->defcontext, sizeof(p->context));
10327  }
10328 
10329  for (;;) {
10330  i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10331  if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10332  ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10333  callerid_free(cs);
10334  ast_hangup(chan);
10335  goto quit;
10336  }
10337  if (i & DAHDI_IOMUX_SIGEVENT) {
10338  res = dahdi_get_event(p->subs[idx].dfd);
10339  ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10340  if (res == DAHDI_EVENT_NOALARM) {
10341  p->inalarm = 0;
10342  }
10343  res = 0;
10344  /* Let us detect distinctive ring */
10345 
10346  curRingData[receivedRingT] = p->ringt;
10347 
10348  if (p->ringt < p->ringt_base/2)
10349  break;
10350  /* Increment the ringT counter so we can match it against
10351  values in chan_dahdi.conf for distinctive ring */
10352  if (++receivedRingT == ARRAY_LEN(curRingData))
10353  break;
10354  } else if (i & DAHDI_IOMUX_READ) {
10355  res = read(p->subs[idx].dfd, buf, sizeof(buf));
10356  if (res < 0) {
10357  if (errno != ELAST) {
10358  ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10359  callerid_free(cs);
10360  ast_hangup(chan);
10361  goto quit;
10362  }
10363  break;
10364  }
10365  if (p->ringt > 0) {
10366  if (!(--p->ringt)) {
10367  res = -1;
10368  break;
10369  }
10370  }
10371  }
10372  }
10373  /* this only shows up if you have n of the dring patterns filled in */
10374  ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
10375  for (counter = 0; counter < 3; counter++) {
10376  /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this
10377  channel */
10378  distMatches = 0;
10379  for (counter1 = 0; counter1 < 3; counter1++) {
10380  ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
10381  if (p->drings.ringnum[counter].ring[counter1] == -1) {
10382  ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
10383  curRingData[counter1]);
10384  distMatches++;
10385  } else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
10386  curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
10387  ast_verb(3, "Ring pattern matched in range: %d to %d\n",
10388  (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
10389  (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
10390  distMatches++;
10391  }
10392  }
10393 
10394  if (distMatches == 3) {
10395  /* The ring matches, set the context to whatever is for distinctive ring.. */
10396  ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context));
10398  ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
10399  break;
10400  }
10401  }
10402  }
10403  /* Restore linear mode (if appropriate) for Caller*ID processing */
10404  dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10405 #if 1
10406  restore_gains(p);
10407 #endif
10408  } else
10409  ast_log(LOG_WARNING, "Unable to get caller ID space\n");
10410  } else {
10411  ast_log(LOG_WARNING, "Channel %s in prering "
10412  "state, but I have nothing to do. "
10413  "Terminating simple switch, should be "
10414  "restarted by the actual ring.\n",
10415  ast_channel_name(chan));
10416  ast_hangup(chan);
10417  goto quit;
10418  }
10419  } else if (p->use_callerid && p->cid_start == CID_START_RING) {
10420  if (p->cid_signalling == CID_SIG_DTMF) {
10421  int k = 0;
10422  int off_ms;
10423  struct timeval start;
10424  int ms;
10425  cs = NULL;
10426  dahdi_setlinear(p->subs[idx].dfd, 0);
10427  off_ms = 2000;
10428  start = ast_tvnow();
10429  for (;;) {
10430  struct ast_frame *f;
10431 
10432  ms = ast_remaining_ms(start, off_ms);
10433  res = ast_waitfor(chan, ms);
10434  if (res <= 0) {
10435  ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
10436  "Exiting simple switch\n");
10437  ast_hangup(chan);
10438  goto quit;
10439  }
10440  f = ast_read(chan);
10441  if (!f) {
10442  /* Hangup received waiting for DTMFCID. Exiting simple switch. */
10443  ast_hangup(chan);
10444  goto quit;
10445  }
10446  if (f->frametype == AST_FRAME_DTMF) {
10447  dtmfbuf[k++] = f->subclass.integer;
10448  ast_debug(1, "CID got digit '%c'\n", f->subclass.integer);
10449  start = ast_tvnow();
10450  }
10451  ast_frfree(f);
10452 
10453  if (p->ringt_base == p->ringt)
10454  break;
10455  }
10456  dtmfbuf[k] = '\0';
10457  dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10458  /* Got cid and ring. */
10459  callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
10460  ast_debug(1, "CID is '%s', flags %d\n",
10461  dtmfcid, flags);
10462  /* If first byte is NULL, we have no cid */
10463  if (!ast_strlen_zero(dtmfcid))
10464  number = dtmfcid;
10465  else
10466  number = NULL;
10467  /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */
10468  } else {
10469  /* FSK Bell202 callerID */
10470  cs = callerid_new(p->cid_signalling);
10471  if (cs) {
10472 #if 1
10473  bump_gains(p);
10474 #endif
10475  samples = 0;
10476  len = 0;
10477  distMatches = 0;
10478  /* Clear the current ring data array so we don't have old data in it. */
10479  for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
10480  curRingData[receivedRingT] = 0;
10481  receivedRingT = 0;
10482  counter = 0;
10483  counter1 = 0;
10484  /* Check to see if context is what it should be, if not set to be. */
10485  if (strcmp(p->context,p->defcontext) != 0) {
10486  ast_copy_string(p->context, p->defcontext, sizeof(p->context));
10488  }
10489 
10490  /* Take out of linear mode for Caller*ID processing */
10491  dahdi_setlinear(p->subs[idx].dfd, 0);
10492  for (;;) {
10493  i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10494  if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10495  ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10496  callerid_free(cs);
10497  ast_hangup(chan);
10498  goto quit;
10499  }
10500  if (i & DAHDI_IOMUX_SIGEVENT) {
10501  res = dahdi_get_event(p->subs[idx].dfd);
10502  ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10503  if (res == DAHDI_EVENT_NOALARM) {
10504  p->inalarm = 0;
10505  }
10506  /* If we get a PR event, they hung up while processing calerid */
10507  if ( res == DAHDI_EVENT_POLARITY && p->hanguponpolarityswitch && p->polarity == POLARITY_REV) {
10508  ast_debug(1, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p->channel);
10509  p->polarity = POLARITY_IDLE;
10510  callerid_free(cs);
10511  ast_hangup(chan);
10512  goto quit;
10513  }
10514  res = 0;
10515  /* Let us detect callerid when the telco uses distinctive ring */
10516 
10517  curRingData[receivedRingT] = p->ringt;
10518 
10519  if (p->ringt < p->ringt_base/2)
10520  break;
10521  /* Increment the ringT counter so we can match it against
10522  values in chan_dahdi.conf for distinctive ring */
10523  if (++receivedRingT == ARRAY_LEN(curRingData))
10524  break;
10525  } else if (i & DAHDI_IOMUX_READ) {
10526  res = read(p->subs[idx].dfd, buf, sizeof(buf));
10527  if (res < 0) {
10528  if (errno != ELAST) {
10529  ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10530  callerid_free(cs);
10531  ast_hangup(chan);
10532  goto quit;
10533  }
10534  break;
10535  }
10536  if (p->ringt > 0) {
10537  if (!(--p->ringt)) {
10538  res = -1;
10539  break;
10540  }
10541  }
10542  samples += res;
10543  res = callerid_feed(cs, buf, res, AST_LAW(p));
10544  if (res < 0) {
10545  /*
10546  * The previous diagnostic message output likely
10547  * explains why it failed.
10548  */
10550  "Failed to decode CallerID on channel '%s'\n",
10551  ast_channel_name(chan));
10552  break;
10553  } else if (res)
10554  break;
10555  else if (samples > (8000 * 10))
10556  break;
10557  }
10558  }
10559  if (res == 1) {
10560  callerid_get(cs, &name, &number, &flags);
10561  ast_debug(1, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
10562  }
10563  if (distinctiveringaftercid == 1) {
10564  /* Clear the current ring data array so we don't have old data in it. */
10565  for (receivedRingT = 0; receivedRingT < 3; receivedRingT++) {
10566  curRingData[receivedRingT] = 0;
10567  }
10568  receivedRingT = 0;
10569  ast_verb(3, "Detecting post-CID distinctive ring\n");
10570  for (;;) {
10571  i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10572  if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10573  ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10574  callerid_free(cs);
10575  ast_hangup(chan);
10576  goto quit;
10577  }
10578  if (i & DAHDI_IOMUX_SIGEVENT) {
10579  res = dahdi_get_event(p->subs[idx].dfd);
10580  ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10581  if (res == DAHDI_EVENT_NOALARM) {
10582  p->inalarm = 0;
10583  }
10584  res = 0;
10585  /* Let us detect callerid when the telco uses distinctive ring */
10586 
10587  curRingData[receivedRingT] = p->ringt;
10588 
10589  if (p->ringt < p->ringt_base/2)
10590  break;
10591  /* Increment the ringT counter so we can match it against
10592  values in chan_dahdi.conf for distinctive ring */
10593  if (++receivedRingT == ARRAY_LEN(curRingData))
10594  break;
10595  } else if (i & DAHDI_IOMUX_READ) {
10596  res = read(p->subs[idx].dfd, buf, sizeof(buf));
10597  if (res < 0) {
10598  if (errno != ELAST) {
10599  ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10600  callerid_free(cs);
10601  ast_hangup(chan);
10602  goto quit;
10603  }
10604  break;
10605  }
10606  if (p->ringt > 0) {
10607  if (!(--p->ringt)) {
10608  res = -1;
10609  break;
10610  }
10611  }
10612  }
10613  }
10614  }
10615  if (p->usedistinctiveringdetection) {
10616  /* this only shows up if you have n of the dring patterns filled in */
10617  ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
10618 
10619  for (counter = 0; counter < 3; counter++) {
10620  /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this
10621  channel */
10622  /* this only shows up if you have n of the dring patterns filled in */
10623  ast_verb(3, "Checking %d,%d,%d\n",
10624  p->drings.ringnum[counter].ring[0],
10625  p->drings.ringnum[counter].ring[1],
10626  p->drings.ringnum[counter].ring[2]);
10627  distMatches = 0;
10628  for (counter1 = 0; counter1 < 3; counter1++) {
10629  ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
10630  if (p->drings.ringnum[counter].ring[counter1] == -1) {
10631  ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
10632  curRingData[counter1]);
10633  distMatches++;
10634  }
10635  else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
10636  curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
10637  ast_verb(3, "Ring pattern matched in range: %d to %d\n",
10638  (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
10639  (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
10640  distMatches++;
10641  }
10642  }
10643  if (distMatches == 3) {
10644  /* The ring matches, set the context to whatever is for distinctive ring.. */
10645  ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context));
10647  ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
10648  break;
10649  }
10650  }
10651  }
10652  /* Restore linear mode (if appropriate) for Caller*ID processing */
10653  dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10654 #if 1
10655  restore_gains(p);
10656 #endif
10657  if (res < 0) {
10658  ast_log(LOG_WARNING, "CallerID returned with error on channel '%s'\n", ast_channel_name(chan));
10659  }
10660  } else
10661  ast_log(LOG_WARNING, "Unable to get caller ID space\n");
10662  }
10663  } else
10664  cs = NULL;
10665 
10666  if (number)
10667  ast_shrink_phone_number(number);
10668  ast_set_callerid(chan, number, name, number);
10669 
10670  ao2_cleanup(smdi_msg);
10671 
10672  if (cs)
10673  callerid_free(cs);
10674 
10675  my_handle_notify_message(chan, p, flags, -1);
10676 
10677  ast_channel_lock(chan);
10679  ast_channel_rings_set(chan, 1);
10680  ast_channel_unlock(chan);
10681  p->ringt = p->ringt_base;
10682  res = ast_pbx_run(chan);
10683  if (res) {
10684  ast_hangup(chan);
10685  ast_log(LOG_WARNING, "PBX exited non-zero\n");
10686  }
10687  goto quit;
10688  default:
10689  ast_log(LOG_WARNING, "Don't know how to handle simple switch with signalling %s on channel %d\n", sig2str(p->sig), p->channel);
10690  res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10691  if (res < 0)
10692  ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
10693  }
10694  res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10695  if (res < 0)
10696  ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
10697  ast_hangup(chan);
10698 quit:
10700  ss_thread_count--;
10703  return NULL;
10704 }
10705 
10707  struct dahdi_pvt *pvt;
10708  unsigned char buf[READ_SIZE];
10709  size_t len;
10710 };
10711 
10712 static int calc_energy(const unsigned char *buf, int len, struct ast_format *law)
10713 {
10714  int x;
10715  int sum = 0;
10716 
10717  if (!len)
10718  return 0;
10719 
10720  for (x = 0; x < len; x++)
10721  sum += abs(law == ast_format_ulaw ? AST_MULAW(buf[x]) : AST_ALAW(buf[x]));
10722 
10723  return sum / len;
10724 }
10725 
10726 static void *mwi_thread(void *data)
10727 {
10728  struct mwi_thread_data *mtd = data;
10729  struct callerid_state *cs;
10730  pthread_t threadid;
10731  int samples = 0;
10732  char *name, *number;
10733  int flags;
10734  int i, res;
10735  unsigned int spill_done = 0;
10736  int spill_result = -1;
10737 
10738  if (!(cs = callerid_new(mtd->pvt->cid_signalling))) {
10739  goto quit_no_clean;
10740  }
10741 
10742  callerid_feed(cs, mtd->buf, mtd->len, AST_LAW(mtd->pvt));
10743 
10744  bump_gains(mtd->pvt);
10745 
10746  for (;;) {
10747  i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10748  if ((res = ioctl(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_IOMUX, &i))) {
10749  ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10750  goto quit;
10751  }
10752 
10753  if (i & DAHDI_IOMUX_SIGEVENT) {
10754  struct ast_channel *chan;
10755  ast_callid callid = 0;
10756  int callid_created;
10757 
10758  /* If we get an event, screen out events that we do not act on.
10759  * Otherwise, cancel and go to the simple switch to let it deal with it.
10760  */
10761  res = dahdi_get_event(mtd->pvt->subs[SUB_REAL].dfd);
10762 
10763  switch (res) {
10764  case DAHDI_EVENT_NEONMWI_ACTIVE:
10765  case DAHDI_EVENT_NEONMWI_INACTIVE:
10766  case DAHDI_EVENT_NONE:
10767  case DAHDI_EVENT_BITSCHANGED:
10768  break;
10769  case DAHDI_EVENT_NOALARM:
10770  if (dahdi_analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) {
10771  struct analog_pvt *analog_p = mtd->pvt->sig_pvt;
10772 
10773  analog_p->inalarm = 0;
10774  }
10775  mtd->pvt->inalarm = 0;
10776  handle_clear_alarms(mtd->pvt);
10777  break;
10778  case DAHDI_EVENT_ALARM:
10779  if (dahdi_analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) {
10780  struct analog_pvt *analog_p = mtd->pvt->sig_pvt;
10781 
10782  analog_p->inalarm = 1;
10783  }
10784  mtd->pvt->inalarm = 1;
10785  res = get_alarms(mtd->pvt);
10786  handle_alarms(mtd->pvt, res);
10787  break; /* What to do on channel alarm ???? -- fall thru intentionally?? */
10788  default:
10789  callid_created = ast_callid_threadstorage_auto(&callid);
10790  ast_log(LOG_NOTICE, "Got event %d (%s)... Passing along to analog_ss_thread\n", res, event2str(res));
10791  callerid_free(cs);
10792 
10793  restore_gains(mtd->pvt);
10794  mtd->pvt->ringt = mtd->pvt->ringt_base;
10795 
10796  if ((chan = dahdi_new(mtd->pvt, AST_STATE_RING, 0, SUB_REAL, 0, NULL, NULL, callid))) {
10797  int result;
10798 
10799  if (dahdi_analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) {
10800  result = analog_ss_thread_start(mtd->pvt->sig_pvt, chan);
10801  } else {
10802  result = ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan);
10803  }
10804  if (result) {
10805  ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", mtd->pvt->channel);
10806  res = tone_zone_play_tone(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
10807  if (res < 0)
10808  ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", mtd->pvt->channel);
10809  ast_hangup(chan);
10810  }
10811  } else {
10812  ast_log(LOG_WARNING, "Could not create channel to handle call\n");
10813  }
10814 
10815  ast_callid_threadstorage_auto_clean(callid, callid_created);
10816  goto quit_no_clean;
10817  }
10818  } else if (i & DAHDI_IOMUX_READ) {
10819  if ((res = read(mtd->pvt->subs[SUB_REAL].dfd, mtd->buf, sizeof(mtd->buf))) < 0) {
10820  if (errno != ELAST) {
10821  ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10822  goto quit;
10823  }
10824  break;
10825  }
10826  samples += res;
10827  if (!spill_done) {
10828  if ((spill_result = callerid_feed(cs, mtd->buf, res, AST_LAW(mtd->pvt))) < 0) {
10829  /*
10830  * The previous diagnostic message output likely
10831  * explains why it failed.
10832  */
10833  ast_log(LOG_WARNING, "Failed to decode CallerID\n");
10834  break;
10835  } else if (spill_result) {
10836  spill_done = 1;
10837  }
10838  } else {
10839  /* keep reading data until the energy level drops below the threshold
10840  so we don't get another 'trigger' on the remaining carrier signal
10841  */
10842  if (calc_energy(mtd->buf, res, AST_LAW(mtd->pvt)) <= mwilevel)
10843  break;
10844  }
10845  if (samples > (8000 * 4)) /*Termination case - time to give up*/
10846  break;
10847  }
10848  }
10849 
10850  if (spill_result == 1) {
10851  callerid_get(cs, &name, &number, &flags);
10852  if (flags & CID_MSGWAITING) {
10853  ast_log(LOG_NOTICE, "mwi: Have Messages on channel %d\n", mtd->pvt->channel);
10854  notify_message(mtd->pvt->mailbox, 1);
10855  } else if (flags & CID_NOMSGWAITING) {
10856  ast_log(LOG_NOTICE, "mwi: No Messages on channel %d\n", mtd->pvt->channel);
10857  notify_message(mtd->pvt->mailbox, 0);
10858  } else {
10859  ast_log(LOG_NOTICE, "mwi: Status unknown on channel %d\n", mtd->pvt->channel);
10860  }
10861  }
10862 
10863 
10864 quit:
10865  callerid_free(cs);
10866 
10867  restore_gains(mtd->pvt);
10868 
10869 quit_no_clean:
10870  mtd->pvt->mwimonitoractive = 0;
10871  ast_free(mtd);
10872 
10873  return NULL;
10874 }
10875 
10876 /*
10877 * The following three functions (mwi_send_init, mwi_send_process_buffer,
10878 * mwi_send_process_event) work with the do_monitor thread to generate mwi spills
10879 * that are sent out via FXS port on voicemail state change. The execution of
10880 * the mwi send is state driven and can either generate a ring pulse prior to
10881 * sending the fsk spill or simply send an fsk spill.
10882 */
10883 static int mwi_send_init(struct dahdi_pvt * pvt)
10884 {
10885  int x;
10886 
10887 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
10888  /* Determine how this spill is to be sent */
10889  if (pvt->mwisend_rpas) {
10891  pvt->mwisendactive = 1;
10892  } else if (pvt->mwisend_fsk) {
10894  pvt->mwisendactive = 1;
10895  } else {
10896  pvt->mwisendactive = 0;
10897  return 0;
10898  }
10899 #else
10900  if (mwisend_rpas) {
10902  } else {
10904  }
10905  pvt->mwisendactive = 1;
10906 #endif
10907 
10908  if (pvt->cidspill) {
10909  ast_log(LOG_WARNING, "cidspill already exists when trying to send FSK MWI\n");
10910  ast_free(pvt->cidspill);
10911  pvt->cidspill = NULL;
10912  pvt->cidpos = 0;
10913  pvt->cidlen = 0;
10914  }
10916  if (!pvt->cidspill) {
10917  pvt->mwisendactive = 0;
10918  return -1;
10919  }
10920  x = DAHDI_FLUSH_BOTH;
10921  ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
10922  x = 3000;
10923  ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_ONHOOKTRANSFER, &x);
10924 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
10925  if (pvt->mwisend_fsk) {
10926 #endif
10928  CID_MWI_TYPE_MDMF_FULL, AST_LAW(pvt), pvt->cid_name, pvt->cid_num, 0);
10929  pvt->cidpos = 0;
10930 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
10931  }
10932 #endif
10933  return 0;
10934 }
10935 
10936 static int mwi_send_process_buffer(struct dahdi_pvt * pvt, int num_read)
10937 {
10938  struct timeval now;
10939  int res;
10940 
10941  /* sanity check to catch if this had been interrupted previously
10942  * i.e. state says there is more to do but there is no spill allocated
10943  */
10944  if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current && !pvt->cidspill) {
10946  } else if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current) {
10947  /* Normal processing -- Perform mwi send action */
10948  switch ( pvt->mwisend_data.mwisend_current) {
10949  case MWI_SEND_SA:
10950  /* Send the Ring Pulse Signal Alert */
10951  res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &AS_RP_cadence);
10952  if (res) {
10953  ast_log(LOG_WARNING, "Unable to set RP-AS ring cadence: %s\n", strerror(errno));
10954  goto quit;
10955  }
10956  res = dahdi_set_hook(pvt->subs[SUB_REAL].dfd, DAHDI_RING);
10958  break;
10959  case MWI_SEND_SA_WAIT: /* do nothing until I get RINGEROFF event */
10960  break;
10961  case MWI_SEND_PAUSE: /* Wait between alert and spill - min of 500 mS*/
10962 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
10963  if (pvt->mwisend_fsk) {
10964 #endif
10965  gettimeofday(&now, NULL);
10966  if ((int)(now.tv_sec - pvt->mwisend_data.pause.tv_sec) * 1000000 + (int)now.tv_usec - (int)pvt->mwisend_data.pause.tv_usec > 500000) {
10968  }
10969 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
10970  } else { /* support for mwisendtype=nofsk */
10972  }
10973 #endif
10974  break;
10975  case MWI_SEND_SPILL:
10976  /* We read some number of bytes. Write an equal amount of data */
10977  if (0 < num_read) {
10978  if (num_read > pvt->cidlen - pvt->cidpos) {
10979  num_read = pvt->cidlen - pvt->cidpos;
10980  }
10981  res = write(pvt->subs[SUB_REAL].dfd, pvt->cidspill + pvt->cidpos, num_read);
10982  if (res > 0) {
10983  pvt->cidpos += res;
10984  if (pvt->cidpos >= pvt->cidlen) {
10986  }
10987  } else {
10988  ast_log(LOG_WARNING, "MWI FSK Send Write failed: %s\n", strerror(errno));
10989  goto quit;
10990  }
10991  }
10992  break;
10993  case MWI_SEND_CLEANUP:
10994  /* For now, do nothing */
10996  break;
10997  default:
10998  /* Should not get here, punt*/
10999  goto quit;
11000  }
11001  }
11002 
11004  if (pvt->cidspill) {
11005  ast_free(pvt->cidspill);
11006  pvt->cidspill = NULL;
11007  pvt->cidpos = 0;
11008  pvt->cidlen = 0;
11009  }
11010  pvt->mwisendactive = 0;
11011  }
11012  return 0;
11013 quit:
11014  if (pvt->cidspill) {
11015  ast_free(pvt->cidspill);
11016  pvt->cidspill = NULL;
11017  pvt->cidpos = 0;
11018  pvt->cidlen = 0;
11019  }
11020  pvt->mwisendactive = 0;
11021  return -1;
11022 }
11023 
11024 static int mwi_send_process_event(struct dahdi_pvt * pvt, int event)
11025 {
11026  int handled = 0;
11027 
11029  switch (event) {
11030  case DAHDI_EVENT_RINGEROFF:
11032  handled = 1;
11033 
11034  if (dahdi_set_hook(pvt->subs[SUB_REAL].dfd, DAHDI_RINGOFF) ) {
11035  ast_log(LOG_WARNING, "Unable to finish RP-AS: %s mwi send aborted\n", strerror(errno));
11036  ast_free(pvt->cidspill);
11037  pvt->cidspill = NULL;
11039  pvt->mwisendactive = 0;
11040  } else {
11042  gettimeofday(&pvt->mwisend_data.pause, NULL);
11043  }
11044  }
11045  break;
11046  /* Going off hook, I need to punt this spill */
11047  case DAHDI_EVENT_RINGOFFHOOK:
11048  if (pvt->cidspill) {
11049  ast_free(pvt->cidspill);
11050  pvt->cidspill = NULL;
11051  pvt->cidpos = 0;
11052  pvt->cidlen = 0;
11053  }
11055  pvt->mwisendactive = 0;
11056  break;
11057  case DAHDI_EVENT_RINGERON:
11058  case DAHDI_EVENT_HOOKCOMPLETE:
11059  break;
11060  default:
11061  break;
11062  }
11063  }
11064  return handled;
11065 }
11066 
11067 /* destroy a range DAHDI channels, identified by their number */
11068 static void dahdi_destroy_channel_range(int start, int end)
11069 {
11070  struct dahdi_pvt *cur;
11071  struct dahdi_pvt *next;
11072  int destroyed_first = 0;
11073  int destroyed_last = 0;
11074 
11076  ast_debug(1, "range: %d-%d\n", start, end);
11077  for (cur = iflist; cur; cur = next) {
11078  next = cur->next;
11079  if (cur->channel >= start && cur->channel <= end) {
11080  int x = DAHDI_FLASH;
11081 
11082  if (cur->channel > destroyed_last) {
11083  destroyed_last = cur->channel;
11084  }
11085  if (destroyed_first < 1 || cur->channel < destroyed_first) {
11086  destroyed_first = cur->channel;
11087  }
11088  ast_debug(3, "Destroying %d\n", cur->channel);
11089  /* important to create an event for dahdi_wait_event to register so that all analog_ss_threads terminate */
11090  ioctl(cur->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
11091 
11092  destroy_channel(cur, 1);
11094  }
11095  }
11097  if (destroyed_first > start || destroyed_last < end) {
11098  ast_debug(1, "Asked to destroy %d-%d, destroyed %d-%d,\n",
11099  start, end, destroyed_first, destroyed_last);
11100  }
11101 }
11102 
11103 #ifdef HAVE_OPENR2
11104 static void dahdi_r2_destroy_nodev(void)
11105 {
11106  struct r2link_entry *cur;
11107  AST_LIST_LOCK(&nodev_r2links);
11108  AST_LIST_TRAVERSE_SAFE_BEGIN(&nodev_r2links, cur, list) {
11109  int i;
11110  struct dahdi_mfcr2 *r2 = &cur->mfcr2;
11111  ast_debug(3, "About to destroy %d DAHDI channels of MFC/R2 link.\n", r2->numchans);
11112  for (i = 0; i < r2->numchans; i++) {
11113  int channel;
11114  struct dahdi_pvt *pvt = r2->pvts[i];
11115  if (!pvt) {
11116  continue;
11117  }
11118  channel = pvt->channel;
11119  ast_debug(3, "About to destroy B-channel %d.\n", channel);
11120  dahdi_destroy_channel_range(channel, channel);
11121  }
11122  ast_debug(3, "Destroying R2 link\n");
11123  AST_LIST_REMOVE(&nodev_r2links, cur, list);
11124  if (r2->r2master != AST_PTHREADT_NULL) {
11125  pthread_cancel(r2->r2master);
11126  pthread_join(r2->r2master, NULL);
11127  r2->r2master = AST_PTHREADT_NULL;
11128  openr2_context_delete(r2->protocol_context);
11129  }
11130  ast_free(cur);
11131  }
11133  AST_LIST_UNLOCK(&nodev_r2links);
11134 }
11135 #endif
11136 
11137 static int setup_dahdi(int reload);
11138 static int setup_dahdi_int(int reload, struct dahdi_chan_conf *default_conf, struct dahdi_chan_conf *base_conf, struct dahdi_chan_conf *conf);
11139 
11140 /*!
11141  * \internal
11142  * \brief create a range of new DAHDI channels
11143  *
11144  * \param start first channel in the range
11145  * \param end last channel in the range
11146  *
11147  * \retval RESULT_SUCCESS on success.
11148  * \retval RESULT_FAILURE on error.
11149  */
11150 static int dahdi_create_channel_range(int start, int end)
11151 {
11152  struct dahdi_pvt *cur;
11153  struct dahdi_chan_conf default_conf = dahdi_chan_conf_default();
11154  struct dahdi_chan_conf base_conf = dahdi_chan_conf_default();
11155  struct dahdi_chan_conf conf = dahdi_chan_conf_default();
11156  int ret = RESULT_FAILURE; /* be pessimistic */
11157 
11158  ast_debug(1, "channel range caps: %d - %d\n", start, end);
11160  for (cur = iflist; cur; cur = cur->next) {
11161  if (cur->channel >= start && cur->channel <= end) {
11163  "channel range %d-%d is occupied\n",
11164  start, end);
11165  goto out;
11166  }
11167  }
11168 #ifdef HAVE_PRI
11169  {
11170  int i, x;
11171  for (x = 0; x < NUM_SPANS; x++) {
11172  struct dahdi_pri *pri = pris + x;
11173 
11174  if (!pris[x].pri.pvts[0]) {
11175  break;
11176  }
11177  for (i = 0; i < SIG_PRI_NUM_DCHANS; i++) {
11178  int channo = pri->dchannels[i];
11179 
11180  if (!channo) {
11181  break;
11182  }
11183  if (!pri->pri.fds[i]) {
11184  break;
11185  }
11186  if (channo >= start && channo <= end) {
11188  "channel range %d-%d is occupied by span %d\n",
11189  start, end, x + 1);
11190  goto out;
11191  }
11192  }
11193  }
11194  }
11195 #endif
11196  if (!default_conf.chan.cc_params || !base_conf.chan.cc_params ||
11197  !conf.chan.cc_params) {
11198  goto out;
11199  }
11200  default_conf.wanted_channels_start = start;
11201  base_conf.wanted_channels_start = start;
11202  conf.wanted_channels_start = start;
11203  default_conf.wanted_channels_end = end;
11204  base_conf.wanted_channels_end = end;
11205  conf.wanted_channels_end = end;
11206  if (setup_dahdi_int(0, &default_conf, &base_conf, &conf) == 0) {
11207  ret = RESULT_SUCCESS;
11208  }
11209 out:
11214  return ret;
11215 }
11216 
11217 
11218 static struct dahdi_pvt *handle_init_event(struct dahdi_pvt *i, int event)
11219 {
11220  int res;
11221  pthread_t threadid;
11222  struct ast_channel *chan;
11223  ast_callid callid = 0;
11224  int callid_created;
11225 
11226  /* Handle an event on a given channel for the monitor thread. */
11227 
11228  switch (event) {
11229  case DAHDI_EVENT_NONE:
11230  case DAHDI_EVENT_BITSCHANGED:
11231  break;
11232  case DAHDI_EVENT_WINKFLASH:
11233  case DAHDI_EVENT_RINGOFFHOOK:
11234  if (i->inalarm) break;
11235  if (i->radio) break;
11236  /* Got a ring/answer. What kind of channel are we? */
11237  switch (i->sig) {
11238  case SIG_FXOLS:
11239  case SIG_FXOGS:
11240  case SIG_FXOKS:
11241  res = dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
11242  if (res && (errno == EBUSY)) {
11243  break;
11244  }
11245 
11246  callid_created = ast_callid_threadstorage_auto(&callid);
11247 
11248  /* Cancel VMWI spill */
11249  ast_free(i->cidspill);
11250  i->cidspill = NULL;
11251  restore_conference(i);
11252 
11253  if (i->immediate) {
11254  dahdi_ec_enable(i);
11255  /* The channel is immediately up. Start right away */
11256  res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
11257  chan = dahdi_new(i, AST_STATE_RING, 1, SUB_REAL, 0, NULL, NULL, callid);
11258  if (!chan) {
11259  ast_log(LOG_WARNING, "Unable to start PBX on channel %d\n", i->channel);
11260  res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11261  if (res < 0)
11262  ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11263  }
11264  } else {
11265  /* Check for callerid, digits, etc */
11266  chan = dahdi_new(i, AST_STATE_RESERVED, 0, SUB_REAL, 0, NULL, NULL, callid);
11267  if (chan) {
11268  if (has_voicemail(i))
11269  res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
11270  else
11271  res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
11272  if (res < 0)
11273  ast_log(LOG_WARNING, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i->channel);
11274  if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
11275  ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11276  res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11277  if (res < 0)
11278  ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11279  ast_hangup(chan);
11280  }
11281  } else
11282  ast_log(LOG_WARNING, "Unable to create channel\n");
11283  }
11284 
11285  ast_callid_threadstorage_auto_clean(callid, callid_created);
11286  break;
11287  case SIG_FXSLS:
11288  case SIG_FXSGS:
11289  case SIG_FXSKS:
11290  i->ringt = i->ringt_base;
11291  /* Fall through */
11292  case SIG_EMWINK:
11293  case SIG_FEATD:
11294  case SIG_FEATDMF:
11295  case SIG_FEATDMF_TA:
11296  case SIG_E911:
11297  case SIG_FGC_CAMA:
11298  case SIG_FGC_CAMAMF:
11299  case SIG_FEATB:
11300  case SIG_EM:
11301  case SIG_EM_E1:
11302  case SIG_SFWINK:
11303  case SIG_SF_FEATD:
11304  case SIG_SF_FEATDMF:
11305  case SIG_SF_FEATB:
11306  case SIG_SF:
11307  /* Check for callerid, digits, etc */
11308  callid_created = ast_callid_threadstorage_auto(&callid);
11309  if (i->cid_start == CID_START_POLARITY_IN) {
11310  chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL, NULL, callid);
11311  } else {
11312  chan = dahdi_new(i, AST_STATE_RING, 0, SUB_REAL, 0, NULL, NULL, callid);
11313  }
11314 
11315  if (!chan) {
11316  ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
11317  } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
11318  ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11319  res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11320  if (res < 0) {
11321  ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11322  }
11323  ast_hangup(chan);
11324  }
11325 
11326  ast_callid_threadstorage_auto_clean(callid, callid_created);
11327  break;
11328  default:
11329  ast_log(LOG_WARNING, "Don't know how to handle ring/answer with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
11330  res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11331  if (res < 0)
11332  ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11333  return NULL;
11334  }
11335  break;
11336  case DAHDI_EVENT_NOALARM:
11337  switch (i->sig) {
11338 #if defined(HAVE_PRI)
11340  ast_mutex_lock(&i->lock);
11342  ast_mutex_unlock(&i->lock);
11343  break;
11344 #endif /* defined(HAVE_PRI) */
11345 #if defined(HAVE_SS7)
11346  case SIG_SS7:
11347  sig_ss7_set_alarm(i->sig_pvt, 0);
11348  break;
11349 #endif /* defined(HAVE_SS7) */
11350  default:
11351  i->inalarm = 0;
11352  break;
11353  }
11355  break;
11356  case DAHDI_EVENT_ALARM:
11357  switch (i->sig) {
11358 #if defined(HAVE_PRI)
11360  ast_mutex_lock(&i->lock);
11362  ast_mutex_unlock(&i->lock);
11363  break;
11364 #endif /* defined(HAVE_PRI) */
11365 #if defined(HAVE_SS7)
11366  case SIG_SS7:
11367  sig_ss7_set_alarm(i->sig_pvt, 1);
11368  break;
11369 #endif /* defined(HAVE_SS7) */
11370  default:
11371  i->inalarm = 1;
11372  break;
11373  }
11374  res = get_alarms(i);
11375  handle_alarms(i, res);
11376  /* fall thru intentionally */
11377  case DAHDI_EVENT_ONHOOK:
11378  if (i->radio)
11379  break;
11380  /* Back on hook. Hang up. */
11381  switch (i->sig) {
11382  case SIG_FXOLS:
11383  case SIG_FXOGS:
11384  case SIG_FEATD:
11385  case SIG_FEATDMF:
11386  case SIG_FEATDMF_TA:
11387  case SIG_E911:
11388  case SIG_FGC_CAMA:
11389  case SIG_FGC_CAMAMF:
11390  case SIG_FEATB:
11391  case SIG_EM:
11392  case SIG_EM_E1:
11393  case SIG_EMWINK:
11394  case SIG_SF_FEATD:
11395  case SIG_SF_FEATDMF:
11396  case SIG_SF_FEATB:
11397  case SIG_SF:
11398  case SIG_SFWINK:
11399  case SIG_FXSLS:
11400  case SIG_FXSGS:
11401  case SIG_FXSKS:
11402  case SIG_FXOKS:
11403  dahdi_ec_disable(i);
11404  /* Diddle the battery for the zhone */
11405 #ifdef ZHONE_HACK
11406  dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
11407  usleep(1);
11408 #endif
11409  res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
11410  dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
11411  break;
11412  case SIG_SS7:
11414  dahdi_ec_disable(i);
11415  res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
11416  break;
11417  default:
11418  ast_log(LOG_WARNING, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
11419  res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
11420  return NULL;
11421  }
11422  break;
11423  case DAHDI_EVENT_POLARITY:
11424  switch (i->sig) {
11425  case SIG_FXSLS:
11426  case SIG_FXSKS:
11427  case SIG_FXSGS:
11428  /* We have already got a PR before the channel was
11429  created, but it wasn't handled. We need polarity
11430  to be REV for remote hangup detection to work.
11431  At least in Spain */
11432  callid_created = ast_callid_threadstorage_auto(&callid);
11433  if (i->hanguponpolarityswitch)
11434  i->polarity = POLARITY_REV;
11436  i->polarity = POLARITY_REV;
11437  ast_verb(2, "Starting post polarity "
11438  "CID detection on channel %d\n",
11439  i->channel);
11440  chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL, NULL, callid);
11441  if (!chan) {
11442  ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
11443  } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
11444  ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11445  ast_hangup(chan);
11446  }
11447  }
11448  ast_callid_threadstorage_auto_clean(callid, callid_created);
11449  break;
11450  default:
11451  ast_log(LOG_WARNING, "handle_init_event detected "
11452  "polarity reversal on non-FXO (SIG_FXS) "
11453  "interface %d\n", i->channel);
11454  }
11455  break;
11456  case DAHDI_EVENT_REMOVED: /* destroy channel, will actually do so in do_monitor */
11458  "Got DAHDI_EVENT_REMOVED. Destroying channel %d\n",
11459  i->channel);
11460  return i;
11461  case DAHDI_EVENT_NEONMWI_ACTIVE:
11462  if (i->mwimonitor_neon) {
11463  notify_message(i->mailbox, 1);
11464  ast_log(LOG_NOTICE, "NEON MWI set for channel %d, mailbox %s \n", i->channel, i->mailbox);
11465  }
11466  break;
11467  case DAHDI_EVENT_NEONMWI_INACTIVE:
11468  if (i->mwimonitor_neon) {
11469  notify_message(i->mailbox, 0);
11470  ast_log(LOG_NOTICE, "NEON MWI cleared for channel %d, mailbox %s\n", i->channel, i->mailbox);
11471  }
11472  break;
11473  }
11474  return NULL;
11475 }
11476 
11477 static void monitor_pfds_clean(void *arg) {
11478  struct pollfd **pfds = arg;
11479  ast_free(*pfds);
11480 }
11481 
11482 static void *do_monitor(void *data)
11483 {
11484  int count, res, res2, spoint, pollres=0;
11485  struct dahdi_pvt *i;
11486  struct dahdi_pvt *last = NULL;
11487  struct dahdi_pvt *doomed;
11488  time_t thispass = 0, lastpass = 0;
11489  int found;
11490  char buf[1024];
11491  struct pollfd *pfds=NULL;
11492  int lastalloc = -1;
11493  /* This thread monitors all the frame relay interfaces which are not yet in use
11494  (and thus do not have a separate thread) indefinitely */
11495  /* From here on out, we die whenever asked */
11496 #if 0
11497  if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) {
11498  ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n");
11499  return NULL;
11500  }
11501  ast_debug(1, "Monitor starting...\n");
11502 #endif
11503  pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
11504 
11505  pthread_cleanup_push(monitor_pfds_clean, &pfds);
11506  for (;;) {
11507  /* Lock the interface list */
11509  if (!pfds || (lastalloc != ifcount)) {
11510  if (pfds) {
11511  ast_free(pfds);
11512  pfds = NULL;
11513  }
11514  if (ifcount) {
11515  if (!(pfds = ast_calloc(1, ifcount * sizeof(*pfds)))) {
11517  return NULL;
11518  }
11519  }
11520  lastalloc = ifcount;
11521  }
11522  /* Build the stuff we're going to poll on, that is the socket of every
11523  dahdi_pvt that does not have an associated owner channel */
11524  count = 0;
11525  for (i = iflist; i; i = i->next) {
11526  ast_mutex_lock(&i->lock);
11527  if (pfds && (i->subs[SUB_REAL].dfd > -1) && i->sig && (!i->radio) && !(i->sig & SIG_MFCR2)) {
11528  if (dahdi_analog_lib_handles(i->sig, i->radio, i->oprmode)) {
11529  struct analog_pvt *p = i->sig_pvt;
11530 
11531  if (!p) {
11532  ast_log(LOG_ERROR, "No sig_pvt?\n");
11533  } else if (!p->owner && !p->subs[SUB_REAL].owner) {
11534  /* This needs to be watched, as it lacks an owner */
11535  pfds[count].fd = i->subs[SUB_REAL].dfd;
11536  pfds[count].events = POLLPRI;
11537  pfds[count].revents = 0;
11538  /* Message waiting or r2 channels also get watched for reading */
11539  if (i->cidspill || i->mwisendactive || i->mwimonitor_fsk ||
11540  (i->cid_start == CID_START_DTMF_NOALERT && (i->sig == SIG_FXSLS || i->sig == SIG_FXSGS || i->sig == SIG_FXSKS))) {
11541  pfds[count].events |= POLLIN;
11542  }
11543  count++;
11544  }
11545  } else {
11546  if (!i->owner && !i->subs[SUB_REAL].owner && !i->mwimonitoractive ) {
11547  /* This needs to be watched, as it lacks an owner */
11548  pfds[count].fd = i->subs[SUB_REAL].dfd;
11549  pfds[count].events = POLLPRI;
11550  pfds[count].revents = 0;
11551  /* If we are monitoring for VMWI or sending CID, we need to
11552  read from the channel as well */
11553  if (i->cidspill || i->mwisendactive || i->mwimonitor_fsk ||
11554  (i->cid_start == CID_START_DTMF_NOALERT && (i->sig == SIG_FXSLS || i->sig == SIG_FXSGS || i->sig == SIG_FXSKS))) {
11555  pfds[count].events |= POLLIN;
11556  }
11557  count++;
11558  }
11559  }
11560  }
11561  ast_mutex_unlock(&i->lock);
11562  }
11563  /* Okay, now that we know what to do, release the interface lock */
11565 
11566  pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
11567  pthread_testcancel();
11568  /* Wait at least a second for something to happen */
11569  res = poll(pfds, count, 1000);
11570  pthread_testcancel();
11571  pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
11572 
11573  /* Okay, poll has finished. Let's see what happened. */
11574  if (res < 0) {
11575  if ((errno != EAGAIN) && (errno != EINTR))
11576  ast_log(LOG_WARNING, "poll return %d: %s\n", res, strerror(errno));
11577  continue;
11578  }
11579  /* Alright, lock the interface list again, and let's look and see what has
11580  happened */
11582  found = 0;
11583  spoint = 0;
11584  lastpass = thispass;
11585  thispass = time(NULL);
11586  doomed = NULL;
11587  for (i = iflist;; i = i->next) {
11588  if (doomed) {
11589  dahdi_destroy_channel_range(doomed->channel, doomed->channel);
11590  doomed = NULL;
11591  }
11592  if (!i) {
11593  break;
11594  }
11595 
11596  if (thispass != lastpass) {
11597  if (!found && ((i == last) || ((i == iflist) && !last))) {
11598  last = i;
11599  if (last) {
11600  struct analog_pvt *analog_p = last->sig_pvt;
11601  /* Only allow MWI to be initiated on a quiescent fxs port */
11602  if (analog_p
11603  && !last->mwisendactive
11604  && (last->sig & __DAHDI_SIG_FXO)
11605  && !analog_p->fxsoffhookstate
11606  && !last->owner
11607  && !ast_strlen_zero(last->mailbox)
11608  && (thispass - analog_p->onhooktime > 3)) {
11609  res = has_voicemail(last);
11610  if (analog_p->msgstate != res) {
11611  /* Set driver resources for signalling VMWI */
11612  res2 = ioctl(last->subs[SUB_REAL].dfd, DAHDI_VMWI, &res);
11613  if (res2) {
11614  /* TODO: This message will ALWAYS be generated on some cards; any way to restrict it to those cards where it is interesting? */
11615  ast_debug(3, "Unable to control message waiting led on channel %d: %s\n", last->channel, strerror(errno));
11616  }
11617  /* If enabled for FSK spill then initiate it */
11618  if (mwi_send_init(last)) {
11619  ast_log(LOG_WARNING, "Unable to initiate mwi send sequence on channel %d\n", last->channel);
11620  }
11621  analog_p->msgstate = res;
11622  found ++;
11623  }
11624  }
11625  last = last->next;
11626  }
11627  }
11628  }
11629  if ((i->subs[SUB_REAL].dfd > -1) && i->sig) {
11630  if (i->radio && !i->owner)
11631  {
11632  res = dahdi_get_event(i->subs[SUB_REAL].dfd);
11633  if (res)
11634  {
11635  ast_debug(1, "Monitor doohicky got event %s on radio channel %d\n", event2str(res), i->channel);
11636  /* Don't hold iflock while handling init events */
11638  if (dahdi_analog_lib_handles(i->sig, i->radio, i->oprmode))
11640  else
11641  doomed = handle_init_event(i, res);
11643  }
11644  continue;
11645  }
11646  pollres = ast_fdisset(pfds, i->subs[SUB_REAL].dfd, count, &spoint);
11647  if (pollres & POLLIN) {
11648  if (i->owner || i->subs[SUB_REAL].owner) {
11649 #ifdef HAVE_PRI
11650  if (!i->pri)
11651 #endif
11652  ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d) in read...\n", i->subs[SUB_REAL].dfd);
11653  continue;
11654  }
11656  ast_log(LOG_WARNING, "Whoa.... I'm not looking for MWI or sending MWI but am reading (%d)...\n", i->subs[SUB_REAL].dfd);
11657  continue;
11658  }
11659  res = read(i->subs[SUB_REAL].dfd, buf, sizeof(buf));
11660  if (res > 0) {
11661  if (i->mwimonitor_fsk) {
11662  if (calc_energy((unsigned char *) buf, res, AST_LAW(i)) > mwilevel) {
11663  pthread_attr_t attr;
11664  pthread_t threadid;
11665  struct mwi_thread_data *mtd;
11666 
11667  pthread_attr_init(&attr);
11668  pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
11669 
11670  ast_debug(1, "Maybe some MWI on port %d!\n", i->channel);
11671  if ((mtd = ast_calloc(1, sizeof(*mtd)))) {
11672  mtd->pvt = i;
11673  memcpy(mtd->buf, buf, res);
11674  mtd->len = res;
11675  i->mwimonitoractive = 1;
11676  if (ast_pthread_create_background(&threadid, &attr, mwi_thread, mtd)) {
11677  ast_log(LOG_WARNING, "Unable to start mwi thread on channel %d\n", i->channel);
11678  i->mwimonitoractive = 0;
11679  ast_free(mtd);
11680  }
11681  }
11682  }
11683  /* If configured to check for a DTMF CID spill that comes without alert (e.g no polarity reversal) */
11684  } else if (i->cid_start == CID_START_DTMF_NOALERT) {
11685  int energy;
11686  struct timeval now;
11687  /* State machine dtmfcid_holdoff_state allows for the line to settle
11688  * before checking agin for dtmf energy. Presently waits for 500 mS before checking again
11689  */
11690  if (1 == i->dtmfcid_holdoff_state) {
11691  gettimeofday(&i->dtmfcid_delay, NULL);
11692  i->dtmfcid_holdoff_state = 2;
11693  } else if (2 == i->dtmfcid_holdoff_state) {
11694  gettimeofday(&now, NULL);
11695  if ((int)(now.tv_sec - i->dtmfcid_delay.tv_sec) * 1000000 + (int)now.tv_usec - (int)i->dtmfcid_delay.tv_usec > 500000) {
11696  i->dtmfcid_holdoff_state = 0;
11697  }
11698  } else {
11699  energy = calc_energy((unsigned char *) buf, res, AST_LAW(i));
11700  if (!i->mwisendactive && energy > dtmfcid_level) {
11701  pthread_t threadid;
11702  struct ast_channel *chan;
11704  if (dahdi_analog_lib_handles(i->sig, i->radio, i->oprmode)) {
11705  /* just in case this event changes or somehow destroys a channel, set doomed here too */
11707  i->dtmfcid_holdoff_state = 1;
11708  } else {
11709  ast_callid callid = 0;
11710  int callid_created = ast_callid_threadstorage_auto(&callid);
11711  chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL, NULL, callid);
11712  if (!chan) {
11713  ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
11714  } else {
11715  res = ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan);
11716  if (res) {
11717  ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11718  ast_hangup(chan);
11719  } else {
11720  i->dtmfcid_holdoff_state = 1;
11721  }
11722  }
11723  ast_callid_threadstorage_auto_clean(callid, callid_created);
11724  }
11726  }
11727  }
11728  }
11729  if (i->mwisendactive) {
11730  mwi_send_process_buffer(i, res);
11731  }
11732  } else {
11733  ast_log(LOG_WARNING, "Read failed with %d: %s\n", res, strerror(errno));
11734  }
11735  }
11736  if (pollres & POLLPRI) {
11737  if (i->owner || i->subs[SUB_REAL].owner) {
11738 #ifdef HAVE_PRI
11739  if (!i->pri)
11740 #endif
11741  ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d)...\n", i->subs[SUB_REAL].dfd);
11742  continue;
11743  }
11744  res = dahdi_get_event(i->subs[SUB_REAL].dfd);
11745  ast_debug(1, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel);
11746  /* Don't hold iflock while handling init events */
11748  if (0 == i->mwisendactive || 0 == mwi_send_process_event(i, res)) {
11749  if (dahdi_analog_lib_handles(i->sig, i->radio, i->oprmode))
11751  else
11752  doomed = handle_init_event(i, res);
11753  }
11755  }
11756  }
11757  }
11760 #ifdef HAVE_OPENR2
11761  dahdi_r2_destroy_nodev();
11762 #endif
11763  }
11764  /* Never reached */
11765  pthread_cleanup_pop(1);
11766  return NULL;
11767 
11768 }
11769 
11770 static int restart_monitor(void)
11771 {
11772  /* If we're supposed to be stopped -- stay stopped */
11774  return 0;
11776  if (monitor_thread == pthread_self()) {
11778  ast_log(LOG_WARNING, "Cannot kill myself\n");
11779  return -1;
11780  }
11782  /* Wake up the thread */
11783  pthread_kill(monitor_thread, SIGURG);
11784  } else {
11785  /* Start a new monitor */
11788  ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
11789  return -1;
11790  }
11791  }
11793  return 0;
11794 }
11795 
11796 #if defined(HAVE_PRI)
11797 static int pri_resolve_span(int *span, int channel, int offset, struct dahdi_spaninfo *si)
11798 {
11799  int x;
11800  int trunkgroup;
11801  /* Get appropriate trunk group if there is one */
11802  trunkgroup = pris[*span].mastertrunkgroup;
11803  if (trunkgroup) {
11804  /* Select a specific trunk group */
11805  for (x = 0; x < NUM_SPANS; x++) {
11806  if (pris[x].pri.trunkgroup == trunkgroup) {
11807  *span = x;
11808  return 0;
11809  }
11810  }
11811  ast_log(LOG_WARNING, "Channel %d on span %d configured to use nonexistent trunk group %d\n", channel, *span, trunkgroup);
11812  *span = -1;
11813  } else {
11814  if (pris[*span].pri.trunkgroup) {
11815  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);
11816  *span = -1;
11817  } else if (pris[*span].mastertrunkgroup) {
11818  ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is already part of trunk group %d\n", *span, pris[*span].mastertrunkgroup);
11819  *span = -1;
11820  } else {
11821  if (si->totalchans == 31) {
11822  /* E1 */
11823  pris[*span].dchannels[0] = 16 + offset;
11824  } else if (si->totalchans == 24) {
11825  /* T1 or J1 */
11826  pris[*span].dchannels[0] = 24 + offset;
11827  } else if (si->totalchans == 3) {
11828  /* BRI */
11829  pris[*span].dchannels[0] = 3 + offset;
11830  } else {
11831  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);
11832  *span = -1;
11833  return 0;
11834  }
11835  pris[*span].pri.span = *span + 1;
11836  }
11837  }
11838  return 0;
11839 }
11840 #endif /* defined(HAVE_PRI) */
11841 
11842 #if defined(HAVE_PRI)
11843 static int pri_create_trunkgroup(int trunkgroup, int *channels)
11844 {
11845  struct dahdi_spaninfo si;
11846  struct dahdi_params p;
11847  int fd;
11848  int span;
11849  int ospan=0;
11850  int x,y;
11851  for (x = 0; x < NUM_SPANS; x++) {
11852  if (pris[x].pri.trunkgroup == trunkgroup) {
11853  ast_log(LOG_WARNING, "Trunk group %d already exists on span %d, Primary d-channel %d\n", trunkgroup, x + 1, pris[x].dchannels[0]);
11854  return -1;
11855  }
11856  }
11857  for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
11858  if (!channels[y])
11859  break;
11860  memset(&si, 0, sizeof(si));
11861  memset(&p, 0, sizeof(p));
11862  fd = open("/dev/dahdi/channel", O_RDWR);
11863  if (fd < 0) {
11864  ast_log(LOG_WARNING, "Failed to open channel: %s\n", strerror(errno));
11865  return -1;
11866  }
11867  x = channels[y];
11868  if (ioctl(fd, DAHDI_SPECIFY, &x)) {
11869  ast_log(LOG_WARNING, "Failed to specify channel %d: %s\n", channels[y], strerror(errno));
11870  close(fd);
11871  return -1;
11872  }
11873  if (ioctl(fd, DAHDI_GET_PARAMS, &p)) {
11874  ast_log(LOG_WARNING, "Failed to get channel parameters for channel %d: %s\n", channels[y], strerror(errno));
11875  close(fd);
11876  return -1;
11877  }
11878  if (ioctl(fd, DAHDI_SPANSTAT, &si)) {
11879  ast_log(LOG_WARNING, "Failed go get span information on channel %d (span %d): %s\n", channels[y], p.spanno, strerror(errno));
11880  close(fd);
11881  return -1;
11882  }
11883  span = p.spanno - 1;
11884  if (pris[span].pri.trunkgroup) {
11885  ast_log(LOG_WARNING, "Span %d is already provisioned for trunk group %d\n", span + 1, pris[span].pri.trunkgroup);
11886  close(fd);
11887  return -1;
11888  }
11889  if (pris[span].pri.pvts[0]) {
11890  ast_log(LOG_WARNING, "Span %d is already provisioned with channels (implicit PRI maybe?)\n", span + 1);
11891  close(fd);
11892  return -1;
11893  }
11894  if (!y) {
11895  pris[span].pri.trunkgroup = trunkgroup;
11896  ospan = span;
11897  }
11898  pris[ospan].dchannels[y] = channels[y];
11899  pris[span].pri.span = span + 1;
11900  close(fd);
11901  }
11902  return 0;
11903 }
11904 #endif /* defined(HAVE_PRI) */
11905 
11906 #if defined(HAVE_PRI)
11907 static int pri_create_spanmap(int span, int trunkgroup, int logicalspan)
11908 {
11909  if (pris[span].mastertrunkgroup) {
11910  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);
11911  return -1;
11912  }
11913  pris[span].mastertrunkgroup = trunkgroup;
11914  pris[span].prilogicalspan = logicalspan;
11915  return 0;
11916 }
11917 #endif /* defined(HAVE_PRI) */
11918 
11919 #if defined(HAVE_SS7)
11920 static unsigned int parse_pointcode(const char *pcstring)
11921 {
11922  unsigned int code1, code2, code3;
11923  int numvals;
11924 
11925  numvals = sscanf(pcstring, "%30d-%30d-%30d", &code1, &code2, &code3);
11926  if (numvals == 1)
11927  return code1;
11928  if (numvals == 3)
11929  return (code1 << 16) | (code2 << 8) | code3;
11930 
11931  return 0;
11932 }
11933 #endif /* defined(HAVE_SS7) */
11934 
11935 #if defined(HAVE_SS7)
11936 static struct dahdi_ss7 * ss7_resolve_linkset(int linkset)
11937 {
11938  if ((linkset < 0) || (linkset >= NUM_SPANS))
11939  return NULL;
11940  else
11941  return &linksets[linkset - 1];
11942 }
11943 #endif /* defined(HAVE_SS7) */
11944 
11945 #ifdef HAVE_OPENR2
11946 static void dahdi_r2_destroy_links(void)
11947 {
11948  struct r2link_entry *cur;
11949 
11950  /* Queue everything for removal */
11951  AST_LIST_LOCK(&r2links);
11952  AST_LIST_TRAVERSE_SAFE_BEGIN(&r2links, cur, list) {
11953  ast_debug(3, "MFC/R2 link #%d queued for destruction\n", cur->mfcr2.index);
11954  AST_LIST_MOVE_CURRENT(&nodev_r2links, list);
11955  }
11957  AST_LIST_UNLOCK(&r2links);
11958  /* Now destroy properly */
11959  dahdi_r2_destroy_nodev();
11960 }
11961 
11962 /* This is an artificial convenient capacity, to keep at most a full E1 of channels in a single thread */
11963 #define R2_LINK_CAPACITY 30
11964 static struct r2link_entry *dahdi_r2_get_link(const struct dahdi_chan_conf *conf)
11965 {
11966  struct r2link_entry *cur = NULL;
11967  /* Only create a new R2 link if
11968  1. This is the first link requested
11969  2. Configuration changed
11970  3. We got more channels than supported per link */
11971  AST_LIST_LOCK(&r2links);
11972  if (! AST_LIST_EMPTY(&r2links)) {
11973  cur = AST_LIST_LAST(&r2links);
11974  if (memcmp(&conf->mfcr2, &cur->mfcr2.conf, sizeof(conf->mfcr2))) {
11975  ast_debug(3, "Need new R2 link because of: Configuration change\n");
11976  cur = NULL;
11977  } else if (cur->mfcr2.numchans == R2_LINK_CAPACITY) {
11978  ast_debug(3, "Need new R2 link because of: Capacity (%d)\n", R2_LINK_CAPACITY);
11979  cur = NULL;
11980  }
11981  }
11982  if (!cur) {
11983  struct r2link_entry *tmp = NULL;
11984  int new_idx = r2links_count + 1;
11985  int i;
11986  for (i = 1; i <= r2links_count; i++) {
11987  int i_unused = 1;
11988  AST_LIST_TRAVERSE(&r2links, tmp, list) {
11989  if (i == tmp->mfcr2.index) {
11990  i_unused = 0;
11991  break;
11992  }
11993  }
11994  if (i_unused) {
11995  new_idx = i;
11996  break;
11997  }
11998  }
11999  cur = ast_calloc(1, sizeof(*cur));
12000  if (!cur) {
12001  ast_log(LOG_ERROR, "Cannot allocate R2 link!\n");
12002  return NULL;
12003  }
12004  cur->mfcr2.index = new_idx;
12005  cur->mfcr2.r2master = AST_PTHREADT_NULL;
12006  r2links_count++;
12007  ast_debug(3, "Created new R2 link #%d (now have %d)\n", new_idx, r2links_count);
12008  AST_LIST_INSERT_TAIL(&r2links, cur, list);
12009  }
12010  AST_LIST_UNLOCK(&r2links);
12011  return cur;
12012 }
12013 
12014 static int dahdi_r2_set_context(struct dahdi_mfcr2 *r2_link, const struct dahdi_chan_conf *conf)
12015 {
12016  char tmplogdir[] = "/tmp";
12017  char logdir[OR2_MAX_PATH];
12018  int threshold = 0;
12019  int snres = 0;
12020  r2_link->protocol_context = openr2_context_new(NULL, &dahdi_r2_event_iface,
12021  &dahdi_r2_transcode_iface, conf->mfcr2.variant, conf->mfcr2.max_ani,
12022  conf->mfcr2.max_dnis);
12023  if (!r2_link->protocol_context) {
12024  return -1;
12025  }
12026  openr2_context_set_log_level(r2_link->protocol_context, conf->mfcr2.loglevel);
12027  openr2_context_set_ani_first(r2_link->protocol_context, conf->mfcr2.get_ani_first);
12028 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
12029  openr2_context_set_skip_category_request(r2_link->protocol_context, conf->mfcr2.skip_category_request);
12030 #endif
12031  openr2_context_set_mf_threshold(r2_link->protocol_context, threshold);
12032  openr2_context_set_mf_back_timeout(r2_link->protocol_context, conf->mfcr2.mfback_timeout);
12033  openr2_context_set_metering_pulse_timeout(r2_link->protocol_context, conf->mfcr2.metering_pulse_timeout);
12034  openr2_context_set_double_answer(r2_link->protocol_context, conf->mfcr2.double_answer);
12035  openr2_context_set_immediate_accept(r2_link->protocol_context, conf->mfcr2.immediate_accept);
12036 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2
12037  openr2_context_set_dtmf_dialing(r2_link->protocol_context, conf->mfcr2.dtmf_dialing, conf->mfcr2.dtmf_time_on, conf->mfcr2.dtmf_time_off);
12038  openr2_context_set_dtmf_detection(r2_link->protocol_context, conf->mfcr2.dtmf_detection);
12039 #endif
12040 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 3
12041  openr2_context_set_dtmf_detection_end_timeout(r2_link->protocol_context, conf->mfcr2.dtmf_end_timeout);
12042 #endif
12043  if (ast_strlen_zero(conf->mfcr2.logdir)) {
12044  if (openr2_context_set_log_directory(r2_link->protocol_context, tmplogdir)) {
12045  ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir);
12046  }
12047  } else {
12048  snres = snprintf(logdir, sizeof(logdir), "%s/%s/%s", ast_config_AST_LOG_DIR, "mfcr2", conf->mfcr2.logdir);
12049  if (snres >= sizeof(logdir)) {
12050  ast_log(LOG_ERROR, "MFC/R2 logging directory truncated, using %s\n", tmplogdir);
12051  if (openr2_context_set_log_directory(r2_link->protocol_context, tmplogdir)) {
12052  ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir);
12053  }
12054  } else {
12055  if (openr2_context_set_log_directory(r2_link->protocol_context, logdir)) {
12056  ast_log(LOG_ERROR, "Failed setting MFC/R2 log directory %s\n", logdir);
12057  }
12058  }
12059  }
12060  if (!ast_strlen_zero(conf->mfcr2.r2proto_file)) {
12061  if (openr2_context_configure_from_advanced_file(r2_link->protocol_context, conf->mfcr2.r2proto_file)) {
12062  ast_log(LOG_ERROR, "Failed to configure r2context from advanced configuration file %s\n", conf->mfcr2.r2proto_file);
12063  }
12064  }
12065  /* Save the configuration used to setup this link */
12066  memcpy(&r2_link->conf, &conf->mfcr2, sizeof(r2_link->conf));
12067  return 0;
12068 }
12069 #endif
12070 
12071 /* converts a DAHDI sigtype to signalling as can be configured from
12072  * chan_dahdi.conf.
12073  * While both have basically the same values, this will later be the
12074  * place to add filters and sanity checks
12075  */
12077 {
12078  return sigtype;
12079 }
12080 
12081 /*!
12082  * \internal
12083  * \brief Initialize/create a channel interface.
12084  *
12085  * \param channel Channel interface number to initialize/create.
12086  * \param conf Configuration parameters to initialize interface with.
12087  * \param reloading What we are doing now:
12088  * 0 - initial module load,
12089  * 1 - module reload,
12090  * 2 - module restart
12091  *
12092  * \retval Interface-pointer initialized/created
12093  * \retval NULL if error
12094  */
12095 static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf, int reloading)
12096 {
12097  /* Make a dahdi_pvt structure for this interface */
12098  struct dahdi_pvt *tmp;/*!< Current channel structure initializing */
12099  char fn[80];
12100  struct dahdi_bufferinfo bi;
12101 
12102  int res;
12103 #if defined(HAVE_PRI)
12104  int span = 0;
12105 #endif /* defined(HAVE_PRI) */
12106  int here = 0;/*!< TRUE if the channel interface already exists. */
12107  int x;
12108  struct analog_pvt *analog_p = NULL;
12109  struct dahdi_params p;
12110 #if defined(HAVE_PRI)
12111  struct dahdi_spaninfo si;
12112  struct sig_pri_chan *pri_chan = NULL;
12113 #endif /* defined(HAVE_PRI) */
12114 #if defined(HAVE_SS7)
12115  struct sig_ss7_chan *ss7_chan = NULL;
12116 #endif /* defined(HAVE_SS7) */
12117 
12118  /* Search channel interface list to see if it already exists. */
12119  for (tmp = iflist; tmp; tmp = tmp->next) {
12120  if (!tmp->destroy) {
12121  if (tmp->channel == channel) {
12122  /* The channel interface already exists. */
12123  here = 1;
12124  break;
12125  }
12126  if (tmp->channel > channel) {
12127  /* No way it can be in the sorted list. */
12128  tmp = NULL;
12129  break;
12130  }
12131  }
12132  }
12133 
12134  if (!here && reloading != 1) {
12135  tmp = ast_calloc(1, sizeof(*tmp));
12136  if (!tmp) {
12137  return NULL;
12138  }
12140  if (!tmp->cc_params) {
12141  ast_free(tmp);
12142  return NULL;
12143  }
12144  ast_mutex_init(&tmp->lock);
12145  ifcount++;
12146  for (x = 0; x < 3; x++)
12147  tmp->subs[x].dfd = -1;
12148  tmp->channel = channel;
12150  }
12151 
12152  if (tmp) {
12153  int chan_sig = conf->chan.sig;
12154 
12155  /* If there are variables in tmp before it is updated to match the new config, clear them */
12156  if (reloading && tmp->vars) {
12158  tmp->vars = NULL;
12159  }
12160 
12161  if (!here) {
12162  /* Can only get here if this is a new channel interface being created. */
12163  if ((channel != CHAN_PSEUDO)) {
12164  int count = 0;
12165 
12166  snprintf(fn, sizeof(fn), "%d", channel);
12167  /* Open non-blocking */
12168  tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
12169  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 */
12170  usleep(1);
12171  tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
12172  count++;
12173  }
12174  /* Allocate a DAHDI structure */
12175  if (tmp->subs[SUB_REAL].dfd < 0) {
12176  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);
12177  destroy_dahdi_pvt(tmp);
12178  return NULL;
12179  }
12180  memset(&p, 0, sizeof(p));
12181  res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
12182  if (res < 0) {
12183  ast_log(LOG_ERROR, "Unable to get parameters: %s\n", strerror(errno));
12184  destroy_dahdi_pvt(tmp);
12185  return NULL;
12186  }
12187  if (conf->is_sig_auto)
12188  chan_sig = sigtype_to_signalling(p.sigtype);
12189  if (p.sigtype != (chan_sig & 0x3ffff)) {
12190  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));
12191  destroy_dahdi_pvt(tmp);
12192  return NULL;
12193  }
12194  tmp->law_default = p.curlaw;
12195  tmp->law = p.curlaw;
12196  tmp->span = p.spanno;
12197 #if defined(HAVE_PRI)
12198  span = p.spanno - 1;
12199 #endif /* defined(HAVE_PRI) */
12200  } else {
12201  chan_sig = 0;
12202  }
12203  tmp->sig = chan_sig;
12204  tmp->outsigmod = conf->chan.outsigmod;
12205 
12206  if (dahdi_analog_lib_handles(chan_sig, tmp->radio, tmp->oprmode)) {
12207  analog_p = analog_new(dahdisig_to_analogsig(chan_sig), tmp);
12208  if (!analog_p) {
12209  destroy_dahdi_pvt(tmp);
12210  return NULL;
12211  }
12212  tmp->sig_pvt = analog_p;
12213  }
12214 #if defined(HAVE_SS7)
12215  if (chan_sig == SIG_SS7) {
12216  struct dahdi_ss7 *ss7;
12217  int clear = 0;
12218 
12219  if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &clear)) {
12220  ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
12221  destroy_dahdi_pvt(tmp);
12222  return NULL;
12223  }
12224 
12225  ss7 = ss7_resolve_linkset(cur_linkset);
12226  if (!ss7) {
12227  ast_log(LOG_ERROR, "Unable to find linkset %d\n", cur_linkset);
12228  destroy_dahdi_pvt(tmp);
12229  return NULL;
12230  }
12231  ss7->ss7.span = cur_linkset;
12232  if (cur_cicbeginswith < 0) {
12233  ast_log(LOG_ERROR, "Need to set cicbeginswith for the channels!\n");
12234  destroy_dahdi_pvt(tmp);
12235  return NULL;
12236  }
12237  ss7_chan = sig_ss7_chan_new(tmp, &ss7->ss7);
12238  if (!ss7_chan) {
12239  destroy_dahdi_pvt(tmp);
12240  return NULL;
12241  }
12242  tmp->sig_pvt = ss7_chan;
12243  tmp->ss7 = &ss7->ss7;
12244 
12245  ss7_chan->channel = tmp->channel;
12246  ss7_chan->cic = cur_cicbeginswith++;
12247 
12248  /* DB: Add CIC's DPC information */
12249  ss7_chan->dpc = cur_defaultdpc;
12250 
12251  ss7->ss7.pvts[ss7->ss7.numchans++] = ss7_chan;
12252 
12253  ast_copy_string(ss7->ss7.internationalprefix, conf->ss7.ss7.internationalprefix, sizeof(ss7->ss7.internationalprefix));
12254  ast_copy_string(ss7->ss7.nationalprefix, conf->ss7.ss7.nationalprefix, sizeof(ss7->ss7.nationalprefix));
12255  ast_copy_string(ss7->ss7.subscriberprefix, conf->ss7.ss7.subscriberprefix, sizeof(ss7->ss7.subscriberprefix));
12256  ast_copy_string(ss7->ss7.unknownprefix, conf->ss7.ss7.unknownprefix, sizeof(ss7->ss7.unknownprefix));
12257  ast_copy_string(ss7->ss7.networkroutedprefix, conf->ss7.ss7.networkroutedprefix, sizeof(ss7->ss7.networkroutedprefix));
12258 
12259  ss7->ss7.called_nai = conf->ss7.ss7.called_nai;
12260  ss7->ss7.calling_nai = conf->ss7.ss7.calling_nai;
12261  }
12262 #endif /* defined(HAVE_SS7) */
12263 #ifdef HAVE_OPENR2
12264  if (chan_sig == SIG_MFCR2) {
12265  struct dahdi_mfcr2 *r2_link;
12266  struct r2link_entry *r2_le = dahdi_r2_get_link(conf);
12267  r2_link = &r2_le->mfcr2;
12268  if (!r2_link) {
12269  ast_log(LOG_WARNING, "Cannot get another R2 DAHDI context!\n");
12270  destroy_dahdi_pvt(tmp);
12271  return NULL;
12272  }
12273  if (!r2_link->protocol_context && dahdi_r2_set_context(r2_link, conf)) {
12274  ast_log(LOG_ERROR, "Cannot create OpenR2 protocol context.\n");
12275  destroy_dahdi_pvt(tmp);
12276  return NULL;
12277  }
12278  if (r2_link->numchans == ARRAY_LEN(r2_link->pvts)) {
12279  ast_log(LOG_ERROR, "Cannot add more channels to this link!\n");
12280  destroy_dahdi_pvt(tmp);
12281  return NULL;
12282  }
12283  r2_link->pvts[r2_link->numchans++] = tmp;
12284  tmp->r2chan = openr2_chan_new_from_fd(r2_link->protocol_context,
12285  tmp->subs[SUB_REAL].dfd,
12286  NULL, NULL);
12287  if (!tmp->r2chan) {
12288  openr2_liberr_t err = openr2_context_get_last_error(r2_link->protocol_context);
12289  ast_log(LOG_ERROR, "Cannot create OpenR2 channel: %s\n", openr2_context_error_string(err));
12290  destroy_dahdi_pvt(tmp);
12291  return NULL;
12292  }
12293  r2_link->live_chans++;
12294  tmp->mfcr2 = r2_link;
12295  if (conf->mfcr2.call_files) {
12296  openr2_chan_enable_call_files(tmp->r2chan);
12297  }
12298  openr2_chan_set_client_data(tmp->r2chan, tmp);
12299  /* cast seems to be needed to get rid of the annoying warning regarding format attribute */
12300  openr2_chan_set_logging_func(tmp->r2chan, (openr2_logging_func_t)dahdi_r2_on_chan_log);
12301  openr2_chan_set_log_level(tmp->r2chan, conf->mfcr2.loglevel);
12302  tmp->mfcr2_category = conf->mfcr2.category;
12303  tmp->mfcr2_charge_calls = conf->mfcr2.charge_calls;
12304  tmp->mfcr2_allow_collect_calls = conf->mfcr2.allow_collect_calls;
12305  tmp->mfcr2_forced_release = conf->mfcr2.forced_release;
12306  tmp->mfcr2_accept_on_offer = conf->mfcr2.accept_on_offer;
12307  tmp->mfcr2call = 0;
12308  tmp->mfcr2_dnis_index = 0;
12309  tmp->mfcr2_ani_index = 0;
12310  }
12311 #endif
12312 #ifdef HAVE_PRI
12313  if (dahdi_sig_pri_lib_handles(chan_sig)) {
12314  int offset;
12315  int matchesdchan;
12316  int x,y;
12317  int myswitchtype = 0;
12318 
12319  offset = 0;
12320  if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &offset)) {
12321  ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
12322  destroy_dahdi_pvt(tmp);
12323  return NULL;
12324  }
12325  if (span >= NUM_SPANS) {
12326  ast_log(LOG_ERROR, "Channel %d does not lie on a span I know of (%d)\n", channel, span);
12327  destroy_dahdi_pvt(tmp);
12328  return NULL;
12329  } else {
12330  si.spanno = 0;
12331  if (ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SPANSTAT,&si) == -1) {
12332  ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno));
12333  destroy_dahdi_pvt(tmp);
12334  return NULL;
12335  }
12336  /* Store the logical span first based upon the real span */
12337  tmp->logicalspan = pris[span].prilogicalspan;
12338  pri_resolve_span(&span, channel, (channel - p.chanpos), &si);
12339  if (span < 0) {
12340  ast_log(LOG_WARNING, "Channel %d: Unable to find locate channel/trunk group!\n", channel);
12341  destroy_dahdi_pvt(tmp);
12342  return NULL;
12343  }
12344  myswitchtype = conf->pri.pri.switchtype;
12345  /* Make sure this isn't a d-channel */
12346  matchesdchan=0;
12347  for (x = 0; x < NUM_SPANS; x++) {
12348  for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
12349  if (pris[x].dchannels[y] == tmp->channel) {
12350  matchesdchan = 1;
12351  break;
12352  }
12353  }
12354  }
12355  if (!matchesdchan) {
12356  if (pris[span].pri.nodetype && (pris[span].pri.nodetype != conf->pri.pri.nodetype)) {
12357  ast_log(LOG_ERROR, "Span %d is already a %s node\n", span + 1, pri_node2str(pris[span].pri.nodetype));
12358  destroy_dahdi_pvt(tmp);
12359  return NULL;
12360  }
12361  if (pris[span].pri.switchtype && (pris[span].pri.switchtype != myswitchtype)) {
12362  ast_log(LOG_ERROR, "Span %d is already a %s switch\n", span + 1, pri_switch2str(pris[span].pri.switchtype));
12363  destroy_dahdi_pvt(tmp);
12364  return NULL;
12365  }
12366  if ((pris[span].pri.dialplan) && (pris[span].pri.dialplan != conf->pri.pri.dialplan)) {
12367  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));
12368  destroy_dahdi_pvt(tmp);
12369  return NULL;
12370  }
12371  if (!ast_strlen_zero(pris[span].pri.idledial) && strcmp(pris[span].pri.idledial, conf->pri.pri.idledial)) {
12372  ast_log(LOG_ERROR, "Span %d already has idledial '%s'.\n", span + 1, conf->pri.pri.idledial);
12373  destroy_dahdi_pvt(tmp);
12374  return NULL;
12375  }
12376  if (!ast_strlen_zero(pris[span].pri.idleext) && strcmp(pris[span].pri.idleext, conf->pri.pri.idleext)) {
12377  ast_log(LOG_ERROR, "Span %d already has idleext '%s'.\n", span + 1, conf->pri.pri.idleext);
12378  destroy_dahdi_pvt(tmp);
12379  return NULL;
12380  }
12381  if (pris[span].pri.minunused && (pris[span].pri.minunused != conf->pri.pri.minunused)) {
12382  ast_log(LOG_ERROR, "Span %d already has minunused of %d.\n", span + 1, conf->pri.pri.minunused);
12383  destroy_dahdi_pvt(tmp);
12384  return NULL;
12385  }
12386  if (pris[span].pri.minidle && (pris[span].pri.minidle != conf->pri.pri.minidle)) {
12387  ast_log(LOG_ERROR, "Span %d already has minidle of %d.\n", span + 1, conf->pri.pri.minidle);
12388  destroy_dahdi_pvt(tmp);
12389  return NULL;
12390  }
12391  if (pris[span].pri.numchans >= ARRAY_LEN(pris[span].pri.pvts)) {
12392  ast_log(LOG_ERROR, "Unable to add channel %d: Too many channels in trunk group %d!\n", channel,
12393  pris[span].pri.trunkgroup);
12394  destroy_dahdi_pvt(tmp);
12395  return NULL;
12396  }
12397 
12398  pri_chan = sig_pri_chan_new(tmp, &pris[span].pri, tmp->logicalspan, p.chanpos, pris[span].mastertrunkgroup);
12399  if (!pri_chan) {
12400  destroy_dahdi_pvt(tmp);
12401  return NULL;
12402  }
12403  tmp->sig_pvt = pri_chan;
12404  tmp->pri = &pris[span].pri;
12405 
12406  tmp->priexclusive = conf->chan.priexclusive;
12407 
12408  if (!tmp->pri->cc_params) {
12409  tmp->pri->cc_params = ast_cc_config_params_init();
12410  if (!tmp->pri->cc_params) {
12411  destroy_dahdi_pvt(tmp);
12412  return NULL;
12413  }
12414  }
12416  conf->chan.cc_params);
12417 
12418  pris[span].pri.sig = chan_sig;
12419  pris[span].pri.nodetype = conf->pri.pri.nodetype;
12420  pris[span].pri.switchtype = myswitchtype;
12421  pris[span].pri.nsf = conf->pri.pri.nsf;
12422  pris[span].pri.dialplan = conf->pri.pri.dialplan;
12423  pris[span].pri.localdialplan = conf->pri.pri.localdialplan;
12424  pris[span].pri.cpndialplan = conf->pri.pri.cpndialplan;
12425  pris[span].pri.pvts[pris[span].pri.numchans++] = tmp->sig_pvt;
12426  pris[span].pri.minunused = conf->pri.pri.minunused;
12427  pris[span].pri.minidle = conf->pri.pri.minidle;
12428  pris[span].pri.overlapdial = conf->pri.pri.overlapdial;
12429  pris[span].pri.qsigchannelmapping = conf->pri.pri.qsigchannelmapping;
12430  pris[span].pri.discardremoteholdretrieval = conf->pri.pri.discardremoteholdretrieval;
12431 #if defined(HAVE_PRI_SERVICE_MESSAGES)
12432  pris[span].pri.enable_service_message_support = conf->pri.pri.enable_service_message_support;
12433 #endif /* defined(HAVE_PRI_SERVICE_MESSAGES) */
12434 #ifdef HAVE_PRI_INBANDDISCONNECT
12435  pris[span].pri.inbanddisconnect = conf->pri.pri.inbanddisconnect;
12436 #endif
12437 #if defined(HAVE_PRI_CALL_HOLD)
12438  pris[span].pri.hold_disconnect_transfer =
12439  conf->pri.pri.hold_disconnect_transfer;
12440 #endif /* defined(HAVE_PRI_CALL_HOLD) */
12441 #if defined(HAVE_PRI_CCSS)
12442  pris[span].pri.cc_ptmp_recall_mode =
12443  conf->pri.pri.cc_ptmp_recall_mode;
12444  pris[span].pri.cc_qsig_signaling_link_req =
12445  conf->pri.pri.cc_qsig_signaling_link_req;
12446  pris[span].pri.cc_qsig_signaling_link_rsp =
12447  conf->pri.pri.cc_qsig_signaling_link_rsp;
12448 #endif /* defined(HAVE_PRI_CCSS) */
12449 #if defined(HAVE_PRI_CALL_WAITING)
12450  pris[span].pri.max_call_waiting_calls =
12451  conf->pri.pri.max_call_waiting_calls;
12452  pris[span].pri.allow_call_waiting_calls =
12453  conf->pri.pri.allow_call_waiting_calls;
12454 #endif /* defined(HAVE_PRI_CALL_WAITING) */
12455  pris[span].pri.transfer = conf->chan.transfer;
12456  pris[span].pri.facilityenable = conf->pri.pri.facilityenable;
12457 #if defined(HAVE_PRI_L2_PERSISTENCE)
12458  pris[span].pri.l2_persistence = conf->pri.pri.l2_persistence;
12459 #endif /* defined(HAVE_PRI_L2_PERSISTENCE) */
12460  pris[span].pri.colp_send = conf->pri.pri.colp_send;
12461 #if defined(HAVE_PRI_AOC_EVENTS)
12462  pris[span].pri.aoc_passthrough_flag = conf->pri.pri.aoc_passthrough_flag;
12463  pris[span].pri.aoce_delayhangup = conf->pri.pri.aoce_delayhangup;
12464 #endif /* defined(HAVE_PRI_AOC_EVENTS) */
12465  if (chan_sig == SIG_BRI_PTMP) {
12466  pris[span].pri.layer1_ignored = conf->pri.pri.layer1_ignored;
12467  } else {
12468  /* Option does not apply to this line type. */
12469  pris[span].pri.layer1_ignored = 0;
12470  }
12471  pris[span].pri.append_msn_to_user_tag = conf->pri.pri.append_msn_to_user_tag;
12472  pris[span].pri.inband_on_setup_ack = conf->pri.pri.inband_on_setup_ack;
12473  pris[span].pri.inband_on_proceeding = conf->pri.pri.inband_on_proceeding;
12474  ast_copy_string(pris[span].pri.initial_user_tag, conf->chan.cid_tag, sizeof(pris[span].pri.initial_user_tag));
12475  ast_copy_string(pris[span].pri.msn_list, conf->pri.pri.msn_list, sizeof(pris[span].pri.msn_list));
12476 #if defined(HAVE_PRI_MWI)
12477  ast_copy_string(pris[span].pri.mwi_mailboxes,
12478  conf->pri.pri.mwi_mailboxes,
12479  sizeof(pris[span].pri.mwi_mailboxes));
12480  ast_copy_string(pris[span].pri.mwi_vm_boxes,
12481  conf->pri.pri.mwi_vm_boxes,
12482  sizeof(pris[span].pri.mwi_vm_boxes));
12483  ast_copy_string(pris[span].pri.mwi_vm_numbers,
12484  conf->pri.pri.mwi_vm_numbers,
12485  sizeof(pris[span].pri.mwi_vm_numbers));
12486 #endif /* defined(HAVE_PRI_MWI) */
12487  ast_copy_string(pris[span].pri.idledial, conf->pri.pri.idledial, sizeof(pris[span].pri.idledial));
12488  ast_copy_string(pris[span].pri.idleext, conf->pri.pri.idleext, sizeof(pris[span].pri.idleext));
12489  ast_copy_string(pris[span].pri.internationalprefix, conf->pri.pri.internationalprefix, sizeof(pris[span].pri.internationalprefix));
12490  ast_copy_string(pris[span].pri.nationalprefix, conf->pri.pri.nationalprefix, sizeof(pris[span].pri.nationalprefix));
12491  ast_copy_string(pris[span].pri.localprefix, conf->pri.pri.localprefix, sizeof(pris[span].pri.localprefix));
12492  ast_copy_string(pris[span].pri.privateprefix, conf->pri.pri.privateprefix, sizeof(pris[span].pri.privateprefix));
12493  ast_copy_string(pris[span].pri.unknownprefix, conf->pri.pri.unknownprefix, sizeof(pris[span].pri.unknownprefix));
12494  pris[span].pri.moh_signaling = conf->pri.pri.moh_signaling;
12495  pris[span].pri.resetinterval = conf->pri.pri.resetinterval;
12496 #if defined(HAVE_PRI_DISPLAY_TEXT)
12497  pris[span].pri.display_flags_send = conf->pri.pri.display_flags_send;
12498  pris[span].pri.display_flags_receive = conf->pri.pri.display_flags_receive;
12499 #endif /* defined(HAVE_PRI_DISPLAY_TEXT) */
12500 #if defined(HAVE_PRI_MCID)
12501  pris[span].pri.mcid_send = conf->pri.pri.mcid_send;
12502 #endif /* defined(HAVE_PRI_MCID) */
12503  pris[span].pri.force_restart_unavailable_chans = conf->pri.pri.force_restart_unavailable_chans;
12504 #if defined(HAVE_PRI_DATETIME_SEND)
12505  pris[span].pri.datetime_send = conf->pri.pri.datetime_send;
12506 #endif /* defined(HAVE_PRI_DATETIME_SEND) */
12507 
12508  for (x = 0; x < PRI_MAX_TIMERS; x++) {
12509  pris[span].pri.pritimers[x] = conf->pri.pri.pritimers[x];
12510  }
12511 
12512 #if defined(HAVE_PRI_CALL_WAITING)
12513  /* Channel initial config parameters. */
12514  pris[span].pri.ch_cfg.stripmsd = conf->chan.stripmsd;
12515  pris[span].pri.ch_cfg.hidecallerid = conf->chan.hidecallerid;
12516  pris[span].pri.ch_cfg.hidecalleridname = conf->chan.hidecalleridname;
12517  pris[span].pri.ch_cfg.immediate = conf->chan.immediate;
12518  pris[span].pri.ch_cfg.priexclusive = conf->chan.priexclusive;
12519  pris[span].pri.ch_cfg.priindication_oob = conf->chan.priindication_oob;
12520  pris[span].pri.ch_cfg.use_callerid = conf->chan.use_callerid;
12521  pris[span].pri.ch_cfg.use_callingpres = conf->chan.use_callingpres;
12522  ast_copy_string(pris[span].pri.ch_cfg.context, conf->chan.context, sizeof(pris[span].pri.ch_cfg.context));
12523  ast_copy_string(pris[span].pri.ch_cfg.mohinterpret, conf->chan.mohinterpret, sizeof(pris[span].pri.ch_cfg.mohinterpret));
12524 #endif /* defined(HAVE_PRI_CALL_WAITING) */
12525  } else {
12526  ast_log(LOG_ERROR, "Channel %d is reserved for D-channel.\n", p.chanpos);
12527  destroy_dahdi_pvt(tmp);
12528  return NULL;
12529  }
12530  }
12531  }
12532 #endif
12533  } else {
12534  /* already exists in interface list */
12535  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));
12536  chan_sig = tmp->sig;
12537  if (tmp->subs[SUB_REAL].dfd > -1) {
12538  memset(&p, 0, sizeof(p));
12539  res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
12540  }
12541  }
12542  /* Adjust starttime on loopstart and kewlstart trunks to reasonable values */
12543  switch (chan_sig) {
12544  case SIG_FXSKS:
12545  case SIG_FXSLS:
12546  case SIG_EM:
12547  case SIG_EM_E1:
12548  case SIG_EMWINK:
12549  case SIG_FEATD:
12550  case SIG_FEATDMF:
12551  case SIG_FEATDMF_TA:
12552  case SIG_FEATB:
12553  case SIG_E911:
12554  case SIG_SF:
12555  case SIG_SFWINK:
12556  case SIG_FGC_CAMA:
12557  case SIG_FGC_CAMAMF:
12558  case SIG_SF_FEATD:
12559  case SIG_SF_FEATDMF:
12560  case SIG_SF_FEATB:
12561  p.starttime = 250;
12562  break;
12563  }
12564 
12565  if (tmp->radio) {
12566  /* XXX Waiting to hear back from Jim if these should be adjustable XXX */
12567  p.channo = channel;
12568  p.rxwinktime = 1;
12569  p.rxflashtime = 1;
12570  p.starttime = 1;
12571  p.debouncetime = 5;
12572  } else {
12573  p.channo = channel;
12574  /* Override timing settings based on config file */
12575  if (conf->timing.prewinktime >= 0)
12576  p.prewinktime = conf->timing.prewinktime;
12577  if (conf->timing.preflashtime >= 0)
12578  p.preflashtime = conf->timing.preflashtime;
12579  if (conf->timing.winktime >= 0)
12580  p.winktime = conf->timing.winktime;
12581  if (conf->timing.flashtime >= 0)
12582  p.flashtime = conf->timing.flashtime;
12583  if (conf->timing.starttime >= 0)
12584  p.starttime = conf->timing.starttime;
12585  if (conf->timing.rxwinktime >= 0)
12586  p.rxwinktime = conf->timing.rxwinktime;
12587  if (conf->timing.rxflashtime >= 0)
12588  p.rxflashtime = conf->timing.rxflashtime;
12589  if (conf->timing.debouncetime >= 0)
12590  p.debouncetime = conf->timing.debouncetime;
12591  }
12592 
12593  /* don't set parms on a pseudo-channel */
12594  if (tmp->subs[SUB_REAL].dfd >= 0)
12595  {
12596  res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_PARAMS, &p);
12597  if (res < 0) {
12598  ast_log(LOG_ERROR, "Unable to set parameters: %s\n", strerror(errno));
12599  destroy_dahdi_pvt(tmp);
12600  return NULL;
12601  }
12602  }
12603 #if 1
12604  if (!here && (tmp->subs[SUB_REAL].dfd > -1)) {
12605  memset(&bi, 0, sizeof(bi));
12606  res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
12607  if (!res) {
12608  bi.txbufpolicy = conf->chan.buf_policy;
12609  bi.rxbufpolicy = conf->chan.buf_policy;
12610  bi.numbufs = conf->chan.buf_no;
12611  res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
12612  if (res < 0) {
12613  ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", channel, strerror(errno));
12614  }
12615  } else {
12616  ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", channel, strerror(errno));
12617  }
12618  tmp->buf_policy = conf->chan.buf_policy;
12619  tmp->buf_no = conf->chan.buf_no;
12620  tmp->usefaxbuffers = conf->chan.usefaxbuffers;
12621  tmp->faxbuf_policy = conf->chan.faxbuf_policy;
12622  tmp->faxbuf_no = conf->chan.faxbuf_no;
12623  /* This is not as gnarly as it may first appear. If the ioctl above failed, we'd be setting
12624  * tmp->bufsize to zero which would cause subsequent faxbuffer-related ioctl calls to fail.
12625  * The reason the ioctl call above failed should to be determined before worrying about the
12626  * faxbuffer-related ioctl calls */
12627  tmp->bufsize = bi.bufsize;
12628  }
12629 #endif
12630  tmp->immediate = conf->chan.immediate;
12631  tmp->transfertobusy = conf->chan.transfertobusy;
12632  if (chan_sig & __DAHDI_SIG_FXS) {
12633  tmp->mwimonitor_fsk = conf->chan.mwimonitor_fsk;
12634  tmp->mwimonitor_neon = conf->chan.mwimonitor_neon;
12635  tmp->mwimonitor_rpas = conf->chan.mwimonitor_rpas;
12636  }
12637  tmp->ringt_base = ringt_base;
12638  tmp->firstradio = 0;
12639  if ((chan_sig == SIG_FXOKS) || (chan_sig == SIG_FXOLS) || (chan_sig == SIG_FXOGS))
12640  tmp->permcallwaiting = conf->chan.callwaiting;
12641  else
12642  tmp->permcallwaiting = 0;
12643  /* Flag to destroy the channel must be cleared on new mkif. Part of changes for reload to work */
12644  tmp->destroy = 0;
12645  tmp->drings = conf->chan.drings;
12646 
12647  /* 10 is a nice default. */
12648  if (tmp->drings.ringnum[0].range == 0)
12649  tmp->drings.ringnum[0].range = 10;
12650  if (tmp->drings.ringnum[1].range == 0)
12651  tmp->drings.ringnum[1].range = 10;
12652  if (tmp->drings.ringnum[2].range == 0)
12653  tmp->drings.ringnum[2].range = 10;
12654 
12657  tmp->threewaycalling = conf->chan.threewaycalling;
12658  tmp->adsi = conf->chan.adsi;
12659  tmp->use_smdi = conf->chan.use_smdi;
12660  tmp->permhidecallerid = conf->chan.hidecallerid;
12661  tmp->hidecalleridname = conf->chan.hidecalleridname;
12662  tmp->callreturn = conf->chan.callreturn;
12663  tmp->echocancel = conf->chan.echocancel;
12664  tmp->echotraining = conf->chan.echotraining;
12665  tmp->pulse = conf->chan.pulse;
12666  if (tmp->echocancel.head.tap_length) {
12667  tmp->echocanbridged = conf->chan.echocanbridged;
12668  } else {
12669  if (conf->chan.echocanbridged)
12670  ast_log(LOG_NOTICE, "echocancelwhenbridged requires echocancel to be enabled; ignoring\n");
12671  tmp->echocanbridged = 0;
12672  }
12673  tmp->busydetect = conf->chan.busydetect;
12674  tmp->busycount = conf->chan.busycount;
12675  tmp->busy_cadence = conf->chan.busy_cadence;
12676  tmp->callprogress = conf->chan.callprogress;
12677  tmp->waitfordialtone = conf->chan.waitfordialtone;
12678  tmp->dialtone_detect = conf->chan.dialtone_detect;
12683  tmp->cancallforward = conf->chan.cancallforward;
12684  tmp->dtmfrelax = conf->chan.dtmfrelax;
12685  tmp->callwaiting = tmp->permcallwaiting;
12686  tmp->hidecallerid = tmp->permhidecallerid;
12687  tmp->channel = channel;
12688  tmp->stripmsd = conf->chan.stripmsd;
12689  tmp->use_callerid = conf->chan.use_callerid;
12690  tmp->cid_signalling = conf->chan.cid_signalling;
12691  tmp->cid_start = conf->chan.cid_start;
12692  tmp->dahditrcallerid = conf->chan.dahditrcallerid;
12693  tmp->restrictcid = conf->chan.restrictcid;
12694  tmp->use_callingpres = conf->chan.use_callingpres;
12695  if (tmp->usedistinctiveringdetection) {
12696  if (!tmp->use_callerid) {
12697  ast_log(LOG_NOTICE, "Distinctive Ring detect requires 'usecallerid' be on\n");
12698  tmp->use_callerid = 1;
12699  }
12700  }
12701 
12702  if (tmp->cid_signalling == CID_SIG_SMDI) {
12703  if (!tmp->use_smdi) {
12704  ast_log(LOG_WARNING, "SMDI callerid requires SMDI to be enabled, enabling...\n");
12705  tmp->use_smdi = 1;
12706  }
12707  }
12708  if (tmp->use_smdi) {
12710  if (!(tmp->smdi_iface)) {
12711  ast_log(LOG_ERROR, "Invalid SMDI port specfied, disabling SMDI support\n");
12712  tmp->use_smdi = 0;
12713  }
12714  }
12715 
12716  ast_copy_string(tmp->accountcode, conf->chan.accountcode, sizeof(tmp->accountcode));
12717  tmp->amaflags = conf->chan.amaflags;
12718  if (!here) {
12719  tmp->confno = -1;
12720  tmp->propconfno = -1;
12721  }
12722  tmp->canpark = conf->chan.canpark;
12723  tmp->transfer = conf->chan.transfer;
12724  ast_copy_string(tmp->defcontext,conf->chan.context,sizeof(tmp->defcontext));
12725  ast_copy_string(tmp->language, conf->chan.language, sizeof(tmp->language));
12726  ast_copy_string(tmp->mohinterpret, conf->chan.mohinterpret, sizeof(tmp->mohinterpret));
12727  ast_copy_string(tmp->mohsuggest, conf->chan.mohsuggest, sizeof(tmp->mohsuggest));
12728  ast_copy_string(tmp->context, conf->chan.context, sizeof(tmp->context));
12729  ast_copy_string(tmp->description, conf->chan.description, sizeof(tmp->description));
12730  ast_copy_string(tmp->parkinglot, conf->chan.parkinglot, sizeof(tmp->parkinglot));
12731  tmp->cid_ton = 0;
12732  if (dahdi_analog_lib_handles(tmp->sig, tmp->radio, tmp->oprmode)) {
12733  ast_copy_string(tmp->cid_num, conf->chan.cid_num, sizeof(tmp->cid_num));
12734  ast_copy_string(tmp->cid_name, conf->chan.cid_name, sizeof(tmp->cid_name));
12735  } else {
12736  tmp->cid_num[0] = '\0';
12737  tmp->cid_name[0] = '\0';
12738  }
12739 #if defined(HAVE_PRI)
12740  if (dahdi_sig_pri_lib_handles(tmp->sig)) {
12741  tmp->cid_tag[0] = '\0';
12742  } else
12743 #endif /* defined(HAVE_PRI) */
12744  {
12745  ast_copy_string(tmp->cid_tag, conf->chan.cid_tag, sizeof(tmp->cid_tag));
12746  }
12747  tmp->cid_subaddr[0] = '\0';
12748  ast_copy_string(tmp->mailbox, conf->chan.mailbox, sizeof(tmp->mailbox));
12749  if (channel != CHAN_PSEUDO && !ast_strlen_zero(tmp->mailbox)) {
12750  /* This module does not handle MWI in an event-based manner. However, it
12751  * subscribes to MWI for each mailbox that is configured so that the core
12752  * knows that we care about it. Then, chan_dahdi will get the MWI from the
12753  * event cache instead of checking the mailbox directly. */
12755  }
12756 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
12757  tmp->mwisend_setting = conf->chan.mwisend_setting;
12758  tmp->mwisend_fsk = conf->chan.mwisend_fsk;
12759  tmp->mwisend_rpas = conf->chan.mwisend_rpas;
12760 #endif
12761 
12762  tmp->group = conf->chan.group;
12763  tmp->callgroup = conf->chan.callgroup;
12764  tmp->pickupgroup= conf->chan.pickupgroup;
12769  if (conf->chan.vars) {
12770  struct ast_variable *v, *tmpvar;
12771  for (v = conf->chan.vars ; v ; v = v->next) {
12772  if ((tmpvar = ast_variable_new(v->name, v->value, v->file))) {
12773  if (ast_variable_list_replace(&tmp->vars, tmpvar)) {
12774  tmpvar->next = tmp->vars;
12775  tmp->vars = tmpvar;
12776  }
12777  }
12778  }
12779  }
12780  tmp->hwrxgain_enabled = conf->chan.hwrxgain_enabled;
12781  tmp->hwtxgain_enabled = conf->chan.hwtxgain_enabled;
12782  tmp->hwrxgain = conf->chan.hwrxgain;
12783  tmp->hwtxgain = conf->chan.hwtxgain;
12784  tmp->cid_rxgain = conf->chan.cid_rxgain;
12785  tmp->rxgain = conf->chan.rxgain;
12786  tmp->txgain = conf->chan.txgain;
12787  tmp->txdrc = conf->chan.txdrc;
12788  tmp->rxdrc = conf->chan.rxdrc;
12789  tmp->tonezone = conf->chan.tonezone;
12790  if (tmp->subs[SUB_REAL].dfd > -1) {
12791  if (tmp->hwrxgain_enabled) {
12792  tmp->hwrxgain_enabled = !set_hwgain(tmp->subs[SUB_REAL].dfd, tmp->hwrxgain, 0);
12793  }
12794  if (tmp->hwtxgain_enabled) {
12795  tmp->hwtxgain_enabled = !set_hwgain(tmp->subs[SUB_REAL].dfd, tmp->hwtxgain, 1);
12796  }
12797  set_actual_gain(tmp->subs[SUB_REAL].dfd, tmp->rxgain, tmp->txgain, tmp->rxdrc, tmp->txdrc, tmp->law);
12798  if (tmp->dsp)
12800  dahdi_conf_update(tmp);
12801  if (!here) {
12802  switch (chan_sig) {
12804  case SIG_SS7:
12805  case SIG_MFCR2:
12806  break;
12807  default:
12808  /* Hang it up to be sure it's good */
12809  dahdi_set_hook(tmp->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
12810  break;
12811  }
12812  }
12813  ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SETTONEZONE,&tmp->tonezone);
12814  if ((res = get_alarms(tmp)) != DAHDI_ALARM_NONE) {
12815  /* the dchannel is down so put the channel in alarm */
12816  switch (tmp->sig) {
12817 #ifdef HAVE_PRI
12819  sig_pri_set_alarm(tmp->sig_pvt, 1);
12820  break;
12821 #endif
12822 #if defined(HAVE_SS7)
12823  case SIG_SS7:
12824  sig_ss7_set_alarm(tmp->sig_pvt, 1);
12825  break;
12826 #endif /* defined(HAVE_SS7) */
12827  default:
12828  /* The only sig submodule left should be sig_analog. */
12829  analog_p = tmp->sig_pvt;
12830  if (analog_p) {
12831  analog_p->inalarm = 1;
12832  }
12833  tmp->inalarm = 1;
12834  break;
12835  }
12836  handle_alarms(tmp, res);
12837  }
12838  }
12839 
12845 
12846  if (!here) {
12847  tmp->locallyblocked = 0;
12848  tmp->remotelyblocked = 0;
12849  switch (tmp->sig) {
12850 #if defined(HAVE_PRI)
12852  tmp->inservice = 1;/* Inservice until actually implemented. */
12853 #if defined(HAVE_PRI_SERVICE_MESSAGES)
12854  ((struct sig_pri_chan *) tmp->sig_pvt)->service_status = 0;
12855  if (chan_sig == SIG_PRI) {
12856  char db_chan_name[20];
12857  char db_answer[5];
12858 
12859  /*
12860  * Initialize the active out-of-service status
12861  * and delete any record if the feature is not enabled.
12862  */
12863  snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, tmp->span, tmp->channel);
12864  if (!ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) {
12865  unsigned *why;
12866 
12867  why = &((struct sig_pri_chan *) tmp->sig_pvt)->service_status;
12868  if (tmp->pri->enable_service_message_support) {
12869  char state;
12870 
12871  sscanf(db_answer, "%1c:%30u", &state, why);
12872 
12873  /* Ensure that only the implemented bits could be set.*/
12874  *why &= (SRVST_NEAREND | SRVST_FAREND);
12875  }
12876  if (!*why) {
12877  ast_db_del(db_chan_name, SRVST_DBKEY);
12878  }
12879  }
12880  }
12881 #endif /* defined(HAVE_PRI_SERVICE_MESSAGES) */
12882  break;
12883 #endif /* defined(HAVE_PRI) */
12884 #if defined(HAVE_SS7)
12885  case SIG_SS7:
12886  tmp->inservice = 0;
12887  if (tmp->ss7->flags & LINKSET_FLAG_INITIALHWBLO) {
12889  }
12890  break;
12891 #endif /* defined(HAVE_SS7) */
12892  default:
12893  /* We default to in service on protocols that don't have a reset */
12894  tmp->inservice = 1;
12895  break;
12896  }
12897  }
12898 
12899  switch (tmp->sig) {
12900 #if defined(HAVE_PRI)
12902  if (pri_chan) {
12903  pri_chan->channel = tmp->channel;
12904  pri_chan->hidecallerid = tmp->hidecallerid;
12905  pri_chan->hidecalleridname = tmp->hidecalleridname;
12906  pri_chan->immediate = tmp->immediate;
12907  pri_chan->inalarm = tmp->inalarm;
12908  pri_chan->priexclusive = tmp->priexclusive;
12909  pri_chan->priindication_oob = tmp->priindication_oob;
12910  pri_chan->use_callerid = tmp->use_callerid;
12911  pri_chan->use_callingpres = tmp->use_callingpres;
12912  ast_copy_string(pri_chan->context, tmp->context,
12913  sizeof(pri_chan->context));
12914  ast_copy_string(pri_chan->mohinterpret, tmp->mohinterpret,
12915  sizeof(pri_chan->mohinterpret));
12916  pri_chan->stripmsd = tmp->stripmsd;
12917  }
12918  break;
12919 #endif /* defined(HAVE_PRI) */
12920 #if defined(HAVE_SS7)
12921  case SIG_SS7:
12922  if (ss7_chan) {
12923  ss7_chan->inalarm = tmp->inalarm;
12924  ss7_chan->inservice = tmp->inservice;
12925 
12926  ss7_chan->stripmsd = tmp->stripmsd;
12927  ss7_chan->hidecallerid = tmp->hidecallerid;
12928  ss7_chan->use_callerid = tmp->use_callerid;
12929  ss7_chan->use_callingpres = tmp->use_callingpres;
12930  ss7_chan->immediate = tmp->immediate;
12931  ss7_chan->locallyblocked = tmp->locallyblocked;
12932  ss7_chan->remotelyblocked = tmp->remotelyblocked;
12933  ast_copy_string(ss7_chan->context, tmp->context,
12934  sizeof(ss7_chan->context));
12935  ast_copy_string(ss7_chan->mohinterpret, tmp->mohinterpret,
12936  sizeof(ss7_chan->mohinterpret));
12937  }
12938  break;
12939 #endif /* defined(HAVE_SS7) */
12940  default:
12941  /* The only sig submodule left should be sig_analog. */
12942  analog_p = tmp->sig_pvt;
12943  if (analog_p) {
12944  analog_p->channel = tmp->channel;
12948  analog_p->permcallwaiting = conf->chan.callwaiting; /* permcallwaiting possibly modified in analog_config_complete */
12949  analog_p->callreturn = conf->chan.callreturn;
12950  analog_p->cancallforward = conf->chan.cancallforward;
12951  analog_p->canpark = conf->chan.canpark;
12952  analog_p->dahditrcallerid = conf->chan.dahditrcallerid;
12953  analog_p->immediate = conf->chan.immediate;
12954  analog_p->permhidecallerid = conf->chan.permhidecallerid;
12955  analog_p->pulse = conf->chan.pulse;
12956  analog_p->threewaycalling = conf->chan.threewaycalling;
12957  analog_p->transfer = conf->chan.transfer;
12958  analog_p->transfertobusy = conf->chan.transfertobusy;
12959  analog_p->use_callerid = tmp->use_callerid;
12961  analog_p->use_smdi = tmp->use_smdi;
12962  analog_p->smdi_iface = tmp->smdi_iface;
12963  analog_p->outsigmod = ANALOG_SIG_NONE;
12964  analog_p->echotraining = conf->chan.echotraining;
12965  analog_p->cid_signalling = conf->chan.cid_signalling;
12966  analog_p->stripmsd = conf->chan.stripmsd;
12967  switch (conf->chan.cid_start) {
12968  case CID_START_POLARITY:
12970  break;
12971  case CID_START_POLARITY_IN:
12973  break;
12976  break;
12977  default:
12978  analog_p->cid_start = ANALOG_CID_START_RING;
12979  break;
12980  }
12981  analog_p->callwaitingcallerid = conf->chan.callwaitingcallerid;
12982  analog_p->ringt = conf->chan.ringt;
12983  analog_p->ringt_base = ringt_base;
12984  analog_p->onhooktime = time(NULL);
12985  if (chan_sig & __DAHDI_SIG_FXO) {
12986  memset(&p, 0, sizeof(p));
12987  res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
12988  if (!res) {
12989  analog_p->fxsoffhookstate = p.rxisoffhook;
12990  }
12991 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
12992  res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_VMWI_CONFIG, &tmp->mwisend_setting);
12993 #endif
12994  }
12995  analog_p->msgstate = -1;
12996 
12997  ast_copy_string(analog_p->mohsuggest, conf->chan.mohsuggest, sizeof(analog_p->mohsuggest));
12998  ast_copy_string(analog_p->cid_num, conf->chan.cid_num, sizeof(analog_p->cid_num));
12999  ast_copy_string(analog_p->cid_name, conf->chan.cid_name, sizeof(analog_p->cid_name));
13000 
13001  analog_config_complete(analog_p);
13002  }
13003  break;
13004  }
13005 #if defined(HAVE_PRI)
13006  if (tmp->channel == CHAN_PSEUDO) {
13007  /*
13008  * Save off pseudo channel buffer policy values for dynamic creation of
13009  * no B channel interfaces.
13010  */
13011  dahdi_pseudo_parms.buf_no = tmp->buf_no;
13012  dahdi_pseudo_parms.buf_policy = tmp->buf_policy;
13013  dahdi_pseudo_parms.faxbuf_no = tmp->faxbuf_no;
13014  dahdi_pseudo_parms.faxbuf_policy = tmp->faxbuf_policy;
13015  }
13016 #endif /* defined(HAVE_PRI) */
13017  }
13018  if (tmp && !here) {
13019  /* Add the new channel interface to the sorted channel interface list. */
13020  dahdi_iflist_insert(tmp);
13021  }
13022  return tmp;
13023 }
13024 
13025 static int is_group_or_channel_match(struct dahdi_pvt *p, int span, ast_group_t groupmatch, int *groupmatched, int channelmatch, int *channelmatched)
13026 {
13027 #if defined(HAVE_PRI)
13028  if (0 < span) {
13029  /* The channel must be on the specified PRI span. */
13030  if (!p->pri || p->pri->span != span) {
13031  return 0;
13032  }
13033  if (!groupmatch && channelmatch == -1) {
13034  /* Match any group since it only needs to be on the PRI span. */
13035  *groupmatched = 1;
13036  return 1;
13037  }
13038  }
13039 #endif /* defined(HAVE_PRI) */
13040  /* check group matching */
13041  if (groupmatch) {
13042  if ((p->group & groupmatch) != groupmatch)
13043  /* Doesn't match the specified group, try the next one */
13044  return 0;
13045  *groupmatched = 1;
13046  }
13047  /* Check to see if we have a channel match */
13048  if (channelmatch != -1) {
13049  if (p->channel != channelmatch)
13050  /* Doesn't match the specified channel, try the next one */
13051  return 0;
13052  *channelmatched = 1;
13053  }
13054 
13055  return 1;
13056 }
13057 
13058 static int available(struct dahdi_pvt **pvt, int is_specific_channel)
13059 {
13060  struct dahdi_pvt *p = *pvt;
13061 
13062  if (p->inalarm)
13063  return 0;
13064 
13065  if (dahdi_analog_lib_handles(p->sig, p->radio, p->oprmode))
13066  return analog_available(p->sig_pvt);
13067 
13068  switch (p->sig) {
13069 #if defined(HAVE_PRI)
13071  {
13072  struct sig_pri_chan *pvt_chan;
13073  int res;
13074 
13075  pvt_chan = p->sig_pvt;
13076  res = sig_pri_available(&pvt_chan, is_specific_channel);
13077  *pvt = pvt_chan->chan_pvt;
13078  return res;
13079  }
13080 #endif /* defined(HAVE_PRI) */
13081 #if defined(HAVE_SS7)
13082  case SIG_SS7:
13083  return sig_ss7_available(p->sig_pvt);
13084 #endif /* defined(HAVE_SS7) */
13085  default:
13086  break;
13087  }
13088 
13089  if (p->locallyblocked || p->remotelyblocked) {
13090  return 0;
13091  }
13092 
13093  /* If no owner definitely available */
13094  if (!p->owner) {
13095 #ifdef HAVE_OPENR2
13096  /* Trust MFC/R2 */
13097  if (p->mfcr2) {
13098  if (p->mfcr2call) {
13099  return 0;
13100  } else {
13101  return 1;
13102  }
13103  }
13104 #endif
13105  return 1;
13106  }
13107 
13108  return 0;
13109 }
13110 
13111 #if defined(HAVE_PRI)
13112 #if defined(HAVE_PRI_CALL_WAITING)
13113 /*!
13114  * \internal
13115  * \brief Init the private channel configuration using the span controller.
13116  * \since 1.8
13117  *
13118  * \param priv Channel to init the configuration.
13119  * \param pri sig_pri PRI control structure.
13120  *
13121  * \note Assumes the pri->lock is already obtained.
13122  *
13123  * \return Nothing
13124  */
13125 static void my_pri_init_config(void *priv, struct sig_pri_span *pri)
13126 {
13127  struct dahdi_pvt *pvt = priv;
13128 
13129  pvt->stripmsd = pri->ch_cfg.stripmsd;
13130  pvt->hidecallerid = pri->ch_cfg.hidecallerid;
13131  pvt->hidecalleridname = pri->ch_cfg.hidecalleridname;
13132  pvt->immediate = pri->ch_cfg.immediate;
13133  pvt->priexclusive = pri->ch_cfg.priexclusive;
13134  pvt->priindication_oob = pri->ch_cfg.priindication_oob;
13135  pvt->use_callerid = pri->ch_cfg.use_callerid;
13136  pvt->use_callingpres = pri->ch_cfg.use_callingpres;
13137  ast_copy_string(pvt->context, pri->ch_cfg.context, sizeof(pvt->context));
13138  ast_copy_string(pvt->mohinterpret, pri->ch_cfg.mohinterpret, sizeof(pvt->mohinterpret));
13139 }
13140 #endif /* defined(HAVE_PRI_CALL_WAITING) */
13141 #endif /* defined(HAVE_PRI) */
13142 
13143 #if defined(HAVE_PRI)
13144 /*!
13145  * \internal
13146  * \brief Create a no B channel interface.
13147  * \since 1.8
13148  *
13149  * \param pri sig_pri span controller to add interface.
13150  *
13151  * \note Assumes the pri->lock is already obtained.
13152  *
13153  * \retval array-index into private pointer array on success.
13154  * \retval -1 on error.
13155  */
13156 static int dahdi_new_pri_nobch_channel(struct sig_pri_span *pri)
13157 {
13158  int pvt_idx;
13159  int res;
13160  unsigned idx;
13161  struct dahdi_pvt *pvt;
13162  struct sig_pri_chan *chan;
13163  struct dahdi_bufferinfo bi;
13164 
13165  static int nobch_channel = CHAN_PSEUDO;
13166 
13167  /* Find spot in the private pointer array for new interface. */
13168  for (pvt_idx = 0; pvt_idx < pri->numchans; ++pvt_idx) {
13169  if (!pri->pvts[pvt_idx]) {
13170  break;
13171  }
13172  }
13173  if (pri->numchans == pvt_idx) {
13174  if (ARRAY_LEN(pri->pvts) <= pvt_idx) {
13175  ast_log(LOG_ERROR, "Unable to add a no-B-channel interface!\n");
13176  return -1;
13177  }
13178 
13179  /* Add new spot to the private pointer array. */
13180  pri->pvts[pvt_idx] = NULL;
13181  ++pri->numchans;
13182  }
13183 
13184  pvt = ast_calloc(1, sizeof(*pvt));
13185  if (!pvt) {
13186  return -1;
13187  }
13189  if (!pvt->cc_params) {
13190  ast_free(pvt);
13191  return -1;
13192  }
13193  ast_mutex_init(&pvt->lock);
13194  for (idx = 0; idx < ARRAY_LEN(pvt->subs); ++idx) {
13195  pvt->subs[idx].dfd = -1;
13196  }
13197  pvt->buf_no = dahdi_pseudo_parms.buf_no;
13198  pvt->buf_policy = dahdi_pseudo_parms.buf_policy;
13199  pvt->faxbuf_no = dahdi_pseudo_parms.faxbuf_no;
13200  pvt->faxbuf_policy = dahdi_pseudo_parms.faxbuf_policy;
13201 
13202  chan = sig_pri_chan_new(pvt, pri, 0, 0, 0);
13203  if (!chan) {
13204  destroy_dahdi_pvt(pvt);
13205  return -1;
13206  }
13207  chan->no_b_channel = 1;
13208 
13209  /*
13210  * Pseudo channel companding law.
13211  * Needed for outgoing call waiting calls.
13212  * XXX May need to make this determined by switchtype or user option.
13213  */
13214  pvt->law_default = DAHDI_LAW_ALAW;
13215 
13216  pvt->sig = pri->sig;
13217  pvt->outsigmod = -1;
13218  pvt->pri = pri;
13219  pvt->sig_pvt = chan;
13220  pri->pvts[pvt_idx] = chan;
13221 
13222  pvt->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo");
13223  if (pvt->subs[SUB_REAL].dfd < 0) {
13224  ast_log(LOG_ERROR, "Unable to open no B channel interface pseudo channel: %s\n",
13225  strerror(errno));
13226  destroy_dahdi_pvt(pvt);
13227  return -1;
13228  }
13229  memset(&bi, 0, sizeof(bi));
13230  res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
13231  if (!res) {
13232  pvt->bufsize = bi.bufsize;
13233  bi.txbufpolicy = pvt->buf_policy;
13234  bi.rxbufpolicy = pvt->buf_policy;
13235  bi.numbufs = pvt->buf_no;
13236  res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
13237  if (res < 0) {
13239  "Unable to set buffer policy on no B channel interface: %s\n",
13240  strerror(errno));
13241  }
13242  } else
13244  "Unable to check buffer policy on no B channel interface: %s\n",
13245  strerror(errno));
13246 
13247  --nobch_channel;
13248  if (CHAN_PSEUDO < nobch_channel) {
13249  nobch_channel = CHAN_PSEUDO - 1;
13250  }
13251  pvt->channel = nobch_channel;
13252  pvt->span = pri->span;
13253  chan->channel = pvt->channel;
13254 
13255  dahdi_nobch_insert(pri, pvt);
13256 
13257  return pvt_idx;
13258 }
13259 #endif /* defined(HAVE_PRI) */
13260 
13261 /* This function can *ONLY* be used for copying pseudo (CHAN_PSEUDO) private
13262  structures; it makes no attempt to safely copy regular channel private
13263  structures that might contain reference-counted object pointers and other
13264  scary bits
13265 */
13266 static struct dahdi_pvt *duplicate_pseudo(struct dahdi_pvt *src)
13267 {
13268  struct dahdi_pvt *p;
13269  struct dahdi_bufferinfo bi;
13270  int res;
13271 
13272  p = ast_malloc(sizeof(*p));
13273  if (!p) {
13274  return NULL;
13275  }
13276  *p = *src;
13277 
13278  /* Must deep copy the cc_params. */
13280  if (!p->cc_params) {
13281  ast_free(p);
13282  return NULL;
13283  }
13285 
13287  p->next = NULL;
13288  p->prev = NULL;
13289  ast_mutex_init(&p->lock);
13290  p->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo");
13291  if (p->subs[SUB_REAL].dfd < 0) {
13292  ast_log(LOG_ERROR, "Unable to dup channel: %s\n", strerror(errno));
13293  destroy_dahdi_pvt(p);
13294  return NULL;
13295  }
13296  res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
13297  if (!res) {
13298  bi.txbufpolicy = src->buf_policy;
13299  bi.rxbufpolicy = src->buf_policy;
13300  bi.numbufs = src->buf_no;
13301  res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
13302  if (res < 0) {
13303  ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel: %s\n", strerror(errno));
13304  }
13305  } else
13306  ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel: %s\n", strerror(errno));
13307  p->destroy = 1;
13309  return p;
13310 }
13311 
13313  /*! Group matching mask. Zero if not specified. */
13315  /*! DAHDI channel to match with. -1 if not specified. */
13317  /*! Round robin saved search location index. (Valid if roundrobin TRUE) */
13319  /*! ISDN span where channels can be picked (Zero if not specified) */
13320  int span;
13321  /*! Analog channel distinctive ring cadance index. */
13322  int cadance;
13323  /*! Dialing option. c/r/d if present and valid. */
13324  char opt;
13325  /*! TRUE if to search the channel list backwards. */
13327  /*! TRUE if search is done with round robin sequence. */
13329 };
13330 static struct dahdi_pvt *determine_starting_point(const char *data, struct dahdi_starting_point *param)
13331 {
13332  char *dest;
13333  char *s;
13334  int x;
13335  int res = 0;
13336  struct dahdi_pvt *p;
13337  char *subdir = NULL;
13339  AST_APP_ARG(group); /* channel/group token */
13340  //AST_APP_ARG(ext); /* extension token */
13341  //AST_APP_ARG(opts); /* options token */
13342  AST_APP_ARG(other); /* Any remining unused arguments */
13343  );
13344 
13345  /*
13346  * data is ---v
13347  * Dial(DAHDI/pseudo[/extension[/options]])
13348  * Dial(DAHDI/<channel#>[c|r<cadance#>|d][/extension[/options]])
13349  * Dial(DAHDI/<subdir>!<channel#>[c|r<cadance#>|d][/extension[/options]])
13350  * Dial(DAHDI/i<span>[/extension[/options]])
13351  * Dial(DAHDI/[i<span>-](g|G|r|R)<group#(0-63)>[c|r<cadance#>|d][/extension[/options]])
13352  *
13353  * i - ISDN span channel restriction.
13354  * Used by CC to ensure that the CC recall goes out the same span.
13355  * Also to make ISDN channel names dialable when the sequence number
13356  * is stripped off. (Used by DTMF attended transfer feature.)
13357  *
13358  * g - channel group allocation search forward
13359  * G - channel group allocation search backward
13360  * r - channel group allocation round robin search forward
13361  * R - channel group allocation round robin search backward
13362  *
13363  * c - Wait for DTMF digit to confirm answer
13364  * r<cadance#> - Set distintive ring cadance number
13365  * d - Force bearer capability for ISDN/SS7 call to digital.
13366  */
13367 
13368  if (data) {
13369  dest = ast_strdupa(data);
13370  } else {
13371  ast_log(LOG_WARNING, "Channel requested with no data\n");
13372  return NULL;
13373  }
13374  AST_NONSTANDARD_APP_ARGS(args, dest, '/');
13375  if (!args.argc || ast_strlen_zero(args.group)) {
13376  ast_log(LOG_WARNING, "No channel/group specified\n");
13377  return NULL;
13378  }
13379 
13380  /* Initialize the output parameters */
13381  memset(param, 0, sizeof(*param));
13382  param->channelmatch = -1;
13383 
13384  if (strchr(args.group, '!') != NULL) {
13385  char *prev = args.group;
13386  while ((s = strchr(prev, '!')) != NULL) {
13387  *s++ = '/';
13388  prev = s;
13389  }
13390  *(prev - 1) = '\0';
13391  subdir = args.group;
13392  args.group = prev;
13393  } else if (args.group[0] == 'i') {
13394  /* Extract the ISDN span channel restriction specifier. */
13395  res = sscanf(args.group + 1, "%30d", &x);
13396  if (res < 1) {
13397  ast_log(LOG_WARNING, "Unable to determine ISDN span for data %s\n", data);
13398  return NULL;
13399  }
13400  param->span = x;
13401 
13402  /* Remove the ISDN span channel restriction specifier. */
13403  s = strchr(args.group, '-');
13404  if (!s) {
13405  /* Search all groups since we are ISDN span restricted. */
13406  return iflist;
13407  }
13408  args.group = s + 1;
13409  res = 0;
13410  }
13411  if (toupper(args.group[0]) == 'G' || toupper(args.group[0])=='R') {
13412  /* Retrieve the group number */
13413  s = args.group + 1;
13414  res = sscanf(s, "%30d%1c%30d", &x, &param->opt, &param->cadance);
13415  if (res < 1) {
13416  ast_log(LOG_WARNING, "Unable to determine group for data %s\n", data);
13417  return NULL;
13418  }
13419  param->groupmatch = ((ast_group_t) 1 << x);
13420 
13421  if (toupper(args.group[0]) == 'G') {
13422  if (args.group[0] == 'G') {
13423  param->backwards = 1;
13424  p = ifend;
13425  } else
13426  p = iflist;
13427  } else {
13428  if (ARRAY_LEN(round_robin) <= x) {
13429  ast_log(LOG_WARNING, "Round robin index %d out of range for data %s\n",
13430  x, data);
13431  return NULL;
13432  }
13433  if (args.group[0] == 'R') {
13434  param->backwards = 1;
13435  p = round_robin[x] ? round_robin[x]->prev : ifend;
13436  if (!p)
13437  p = ifend;
13438  } else {
13439  p = round_robin[x] ? round_robin[x]->next : iflist;
13440  if (!p)
13441  p = iflist;
13442  }
13443  param->roundrobin = 1;
13444  param->rr_starting_point = x;
13445  }
13446  } else {
13447  s = args.group;
13448  if (!strcasecmp(s, "pseudo")) {
13449  /* Special case for pseudo */
13450  x = CHAN_PSEUDO;
13451  param->channelmatch = x;
13452  } else {
13453  res = sscanf(s, "%30d%1c%30d", &x, &param->opt, &param->cadance);
13454  if (res < 1) {
13455  ast_log(LOG_WARNING, "Unable to determine channel for data %s\n", data);
13456  return NULL;
13457  } else {
13458  param->channelmatch = x;
13459  }
13460  }
13461  if (subdir) {
13462  char path[PATH_MAX];
13463  struct stat stbuf;
13464 
13465  snprintf(path, sizeof(path), "/dev/dahdi/%s/%d",
13466  subdir, param->channelmatch);
13467  if (stat(path, &stbuf) < 0) {
13468  ast_log(LOG_WARNING, "stat(%s) failed: %s\n",
13469  path, strerror(errno));
13470  return NULL;
13471  }
13472  if (!S_ISCHR(stbuf.st_mode)) {
13473  ast_log(LOG_ERROR, "%s: Not a character device file\n",
13474  path);
13475  return NULL;
13476  }
13477  param->channelmatch = minor(stbuf.st_rdev);
13478  }
13479 
13480  p = iflist;
13481  }
13482 
13483  if (param->opt == 'r' && res < 3) {
13484  ast_log(LOG_WARNING, "Distinctive ring missing identifier in '%s'\n", data);
13485  param->opt = '\0';
13486  }
13487 
13488  return p;
13489 }
13490 
13491 static struct ast_channel *dahdi_request(const char *type, struct ast_format_cap *cap,
13492  const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor,
13493  const char *data, int *cause)
13494 {
13495  int callwait = 0;
13496  struct dahdi_pvt *p;
13497  struct ast_channel *tmp = NULL;
13498  struct dahdi_pvt *exitpvt;
13499  int channelmatched = 0;
13500  int groupmatched = 0;
13501 #if defined(HAVE_PRI) || defined(HAVE_SS7)
13502  int transcapdigital = 0;
13503 #endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */
13504  struct dahdi_starting_point start;
13505  ast_callid callid = 0;
13506  int callid_created = ast_callid_threadstorage_auto(&callid);
13507 
13509  p = determine_starting_point(data, &start);
13510  if (!p) {
13511  /* We couldn't determine a starting point, which likely means badly-formatted channel name. Abort! */
13513  ast_callid_threadstorage_auto_clean(callid, callid_created);
13514  return NULL;
13515  }
13516 
13517  /* Search for an unowned channel */
13518  exitpvt = p;
13519  while (p && !tmp) {
13520  if (start.roundrobin)
13521  round_robin[start.rr_starting_point] = p;
13522 
13523  if (is_group_or_channel_match(p, start.span, start.groupmatch, &groupmatched, start.channelmatch, &channelmatched)
13524  && available(&p, channelmatched)) {
13525  ast_debug(1, "Using channel %d\n", p->channel);
13526 
13527  callwait = (p->owner != NULL);
13528 #ifdef HAVE_OPENR2
13529  if (p->mfcr2) {
13530  ast_mutex_lock(&p->lock);
13531  if (p->mfcr2call) {
13532  ast_mutex_unlock(&p->lock);
13533  ast_debug(1, "Yay!, someone just beat us in the race for channel %d.\n", p->channel);
13534  goto next;
13535  }
13536  p->mfcr2call = 1;
13537  ast_mutex_unlock(&p->lock);
13538  }
13539 #endif
13540  if (p->channel == CHAN_PSEUDO) {
13541  p = duplicate_pseudo(p);
13542  if (!p) {
13543  break;
13544  }
13545  }
13546 
13547  p->distinctivering = 0;
13548  /* Make special notes */
13549  switch (start.opt) {
13550  case '\0':
13551  /* No option present. */
13552  break;
13553  case 'c':
13554  /* Confirm answer */
13555  p->confirmanswer = 1;
13556  break;
13557  case 'r':
13558  /* Distinctive ring */
13559  p->distinctivering = start.cadance;
13560  break;
13561  case 'd':
13562 #if defined(HAVE_PRI) || defined(HAVE_SS7)
13563  /* If this is an ISDN call, make it digital */
13564  transcapdigital = AST_TRANS_CAP_DIGITAL;
13565 #endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */
13566  break;
13567  default:
13568  ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", start.opt, data);
13569  break;
13570  }
13571 
13572  p->outgoing = 1;
13573  if (dahdi_analog_lib_handles(p->sig, p->radio, p->oprmode)) {
13574  tmp = analog_request(p->sig_pvt, &callwait, requestor);
13575 #ifdef HAVE_PRI
13576  } else if (dahdi_sig_pri_lib_handles(p->sig)) {
13577  /*
13578  * We already have the B channel reserved for this call. We
13579  * just need to make sure that dahdi_hangup() has completed
13580  * cleaning up before continuing.
13581  */
13582  ast_mutex_lock(&p->lock);
13583  ast_mutex_unlock(&p->lock);
13584 
13586  sizeof(p->dnid));
13587  tmp = sig_pri_request(p->sig_pvt, SIG_PRI_DEFLAW, assignedids, requestor, transcapdigital);
13588 #endif
13589 #if defined(HAVE_SS7)
13590  } else if (p->sig == SIG_SS7) {
13591  tmp = sig_ss7_request(p->sig_pvt, SIG_SS7_DEFLAW, assignedids, requestor, transcapdigital);
13592 #endif /* defined(HAVE_SS7) */
13593  } else {
13594  tmp = dahdi_new(p, AST_STATE_RESERVED, 0, p->owner ? SUB_CALLWAIT : SUB_REAL, 0, assignedids, requestor, callid);
13595  }
13596  if (!tmp) {
13597  p->outgoing = 0;
13598 #if defined(HAVE_PRI)
13599  switch (p->sig) {
13601 #if defined(HAVE_PRI_CALL_WAITING)
13602  if (((struct sig_pri_chan *) p->sig_pvt)->is_call_waiting) {
13603  ((struct sig_pri_chan *) p->sig_pvt)->is_call_waiting = 0;
13604  ast_atomic_fetchadd_int(&p->pri->num_call_waiting_calls, -1);
13605  }
13606 #endif /* defined(HAVE_PRI_CALL_WAITING) */
13607  /*
13608  * This should be the last thing to clear when we are done with
13609  * the channel.
13610  */
13611  ((struct sig_pri_chan *) p->sig_pvt)->allocated = 0;
13612  break;
13613  default:
13614  break;
13615  }
13616 #endif /* defined(HAVE_PRI) */
13617  } else {
13618  snprintf(p->dialstring, sizeof(p->dialstring), "DAHDI/%s", data);
13619  }
13620  break;
13621  }
13622 #ifdef HAVE_OPENR2
13623 next:
13624 #endif
13625  if (start.backwards) {
13626  p = p->prev;
13627  if (!p)
13628  p = ifend;
13629  } else {
13630  p = p->next;
13631  if (!p)
13632  p = iflist;
13633  }
13634  /* stop when you roll to the one that we started from */
13635  if (p == exitpvt)
13636  break;
13637  }
13639  restart_monitor();
13640  if (cause && !tmp) {
13641  if (callwait || channelmatched) {
13642  *cause = AST_CAUSE_BUSY;
13643  } else if (groupmatched) {
13644  *cause = AST_CAUSE_CONGESTION;
13645  } else {
13646  /*
13647  * We did not match any channel requested.
13648  * Dialplan error requesting non-existant channel?
13649  */
13650  }
13651  }
13652 
13653  ast_callid_threadstorage_auto_clean(callid, callid_created);
13654  return tmp;
13655 }
13656 
13657 /*!
13658  * \internal
13659  * \brief Determine the device state for a given DAHDI device if we can.
13660  * \since 1.8
13661  *
13662  * \param data DAHDI device name after "DAHDI/".
13663  *
13664  * \retval device_state enum ast_device_state value.
13665  * \retval AST_DEVICE_UNKNOWN if we could not determine the device's state.
13666  */
13667 static int dahdi_devicestate(const char *data)
13668 {
13669 #if defined(HAVE_PRI)
13670  const char *device;
13671  unsigned span;
13672  int res;
13673 
13674  device = data;
13675 
13676  if (*device != 'I') {
13677  /* The request is not for an ISDN span device. */
13678  return AST_DEVICE_UNKNOWN;
13679  }
13680  res = sscanf(device, "I%30u", &span);
13681  if (res != 1 || !span || NUM_SPANS < span) {
13682  /* Bad format for ISDN span device name. */
13683  return AST_DEVICE_UNKNOWN;
13684  }
13685  device = strchr(device, '/');
13686  if (!device) {
13687  /* Bad format for ISDN span device name. */
13688  return AST_DEVICE_UNKNOWN;
13689  }
13690 
13691  /*
13692  * Since there are currently no other span devstate's defined,
13693  * it must be congestion.
13694  */
13695 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
13696  ++device;
13697  if (!strcmp(device, "congestion"))
13698 #endif /* defined(THRESHOLD_DEVSTATE_PLACEHOLDER) */
13699  {
13700  return pris[span - 1].pri.congestion_devstate;
13701  }
13702 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
13703  else if (!strcmp(device, "threshold")) {
13704  return pris[span - 1].pri.threshold_devstate;
13705  }
13706  return AST_DEVICE_UNKNOWN;
13707 #endif /* defined(THRESHOLD_DEVSTATE_PLACEHOLDER) */
13708 #else
13709  return AST_DEVICE_UNKNOWN;
13710 #endif /* defined(HAVE_PRI) */
13711 }
13712 
13713 /*!
13714  * \brief Callback made when dial failed to get a channel out of dahdi_request().
13715  * \since 1.8
13716  *
13717  * \param inbound Incoming asterisk channel.
13718  * \param dest Same dial string passed to dahdi_request().
13719  * \param callback Callback into CC core to announce a busy channel available for CC.
13720  *
13721  * \details
13722  * This callback acts like a forked dial with all prongs of the fork busy.
13723  * Essentially, for each channel that could have taken the call, indicate that
13724  * it is busy.
13725  *
13726  * \retval 0 on success.
13727  * \retval -1 on error.
13728  */
13729 static int dahdi_cc_callback(struct ast_channel *inbound, const char *dest, ast_cc_callback_fn callback)
13730 {
13731  struct dahdi_pvt *p;
13732  struct dahdi_pvt *exitpvt;
13733  struct dahdi_starting_point start;
13734  int groupmatched = 0;
13735  int channelmatched = 0;
13736 
13738  p = determine_starting_point(dest, &start);
13739  if (!p) {
13741  return -1;
13742  }
13743  exitpvt = p;
13744  for (;;) {
13745  if (is_group_or_channel_match(p, start.span, start.groupmatch, &groupmatched, start.channelmatch, &channelmatched)) {
13746  /* We found a potential match. call the callback */
13747  struct ast_str *device_name;
13748  char *dash;
13749  const char *monitor_type;
13750  char dialstring[AST_CHANNEL_NAME];
13751  char full_device_name[AST_CHANNEL_NAME];
13752 
13753  switch (ast_get_cc_monitor_policy(p->cc_params)) {
13754  case AST_CC_MONITOR_NEVER:
13755  break;
13756  case AST_CC_MONITOR_NATIVE:
13757  case AST_CC_MONITOR_ALWAYS:
13759 #if defined(HAVE_PRI)
13760  if (dahdi_sig_pri_lib_handles(p->sig)) {
13761  /*
13762  * ISDN is in a trunk busy condition so we need to monitor
13763  * the span congestion device state.
13764  */
13765  snprintf(full_device_name, sizeof(full_device_name),
13766  "DAHDI/I%d/congestion", p->pri->span);
13767  } else
13768 #endif /* defined(HAVE_PRI) */
13769  {
13770 #if defined(HAVE_PRI)
13771  device_name = create_channel_name(p, 1, "");
13772 #else
13773  device_name = create_channel_name(p);
13774 #endif /* defined(HAVE_PRI) */
13775  snprintf(full_device_name, sizeof(full_device_name), "DAHDI/%s",
13776  device_name ? ast_str_buffer(device_name) : "");
13777  ast_free(device_name);
13778  /*
13779  * The portion after the '-' in the channel name is either a random
13780  * number, a sequence number, or a subchannel number. None are
13781  * necessary so strip them off.
13782  */
13783  dash = strrchr(full_device_name, '-');
13784  if (dash) {
13785  *dash = '\0';
13786  }
13787  }
13788  snprintf(dialstring, sizeof(dialstring), "DAHDI/%s", dest);
13789 
13790  /*
13791  * Analog can only do generic monitoring.
13792  * ISDN is in a trunk busy condition and any "device" is going
13793  * to be busy until a B channel becomes available. The generic
13794  * monitor can do this task.
13795  */
13796  monitor_type = AST_CC_GENERIC_MONITOR_TYPE;
13797  callback(inbound,
13798 #if defined(HAVE_PRI)
13799  p->pri ? p->pri->cc_params : p->cc_params,
13800 #else
13801  p->cc_params,
13802 #endif /* defined(HAVE_PRI) */
13803  monitor_type, full_device_name, dialstring, NULL);
13804  break;
13805  }
13806  }
13807  p = start.backwards ? p->prev : p->next;
13808  if (!p) {
13809  p = start.backwards ? ifend : iflist;
13810  }
13811  if (p == exitpvt) {
13812  break;
13813  }
13814  }
13816  return 0;
13817 }
13818 
13819 #if defined(HAVE_SS7)
13820 static void dahdi_ss7_message(struct ss7 *ss7, char *s)
13821 {
13822  int i;
13823 
13824  if (ss7) {
13825  for (i = 0; i < NUM_SPANS; i++) {
13826  if (linksets[i].ss7.ss7 == ss7) {
13827  ast_verbose_callid(0, "[%d] %s", i + 1, s);
13828  return;
13829  }
13830  }
13831  }
13832  ast_verbose_callid(0, "%s", s);
13833 }
13834 #endif /* defined(HAVE_SS7) */
13835 
13836 #if defined(HAVE_SS7)
13837 static void dahdi_ss7_error(struct ss7 *ss7, char *s)
13838 {
13839  int i;
13840 
13841  if (ss7) {
13842  for (i = 0; i < NUM_SPANS; i++) {
13843  if (linksets[i].ss7.ss7 == ss7) {
13844  ast_log_callid(LOG_ERROR, 0, "[%d] %s", i + 1, s);
13845  return;
13846  }
13847  }
13848  }
13849  ast_log_callid(LOG_ERROR, 0, "%s", s);
13850 }
13851 #endif /* defined(HAVE_SS7) */
13852 
13853 #if defined(HAVE_OPENR2)
13854 static void *mfcr2_monitor(void *data)
13855 {
13856  struct dahdi_mfcr2 *mfcr2 = data;
13857  struct dahdi_pvt *pvt;
13858 
13859  /* we should be using pthread_key_create
13860  and allocate pollers dynamically.
13861  I think do_monitor() could be leaking, since it
13862  could be cancelled at any time and is not
13863  using thread keys, why?, */
13864  struct pollfd pollers[ARRAY_LEN(mfcr2->pvts)];
13865  int res = 0;
13866  int i = 0;
13867  int oldstate = 0;
13868  int quit_loop = 0;
13869  int maxsleep = 20;
13870  int was_idle = 0;
13871  int pollsize = 0;
13872  /* now that we're ready to get calls, unblock our side and
13873  get current line state */
13874  for (i = 0; i < mfcr2->numchans; i++) {
13875  pvt = mfcr2->pvts[i];
13876  if (!pvt) {
13877  continue;
13878  }
13879  openr2_chan_set_idle(pvt->r2chan);
13880  openr2_chan_handle_cas(pvt->r2chan);
13881  }
13882  while (1) {
13883  /* we trust here that the mfcr2 channel list will not ever change once
13884  the module is loaded */
13885  pollsize = 0;
13886  for (i = 0; i < mfcr2->numchans; i++) {
13887  pollers[i].revents = 0;
13888  pollers[i].events = 0;
13889  pvt = mfcr2->pvts[i];
13890  if (!pvt) {
13891  continue;
13892  }
13893  if (pvt->owner) {
13894  continue;
13895  }
13896  if (mfcr2->nodev) {
13897  continue;
13898  }
13899  if (!pvt->r2chan) {
13900  ast_debug(1, "Wow, no r2chan on channel %d\n", pvt->channel);
13901  quit_loop = 1;
13902  break;
13903  }
13904  openr2_chan_enable_read(pvt->r2chan);
13905  pollers[i].events = POLLIN | POLLPRI;
13906  pollers[i].fd = pvt->subs[SUB_REAL].dfd;
13907  pollsize++;
13908  }
13909  if (quit_loop) {
13910  break;
13911  }
13912  if (pollsize == 0) {
13913  if (!was_idle) {
13914  ast_debug(1, "Monitor thread going idle since everybody has an owner\n");
13915  was_idle = 1;
13916  }
13917  poll(NULL, 0, maxsleep);
13918  continue;
13919  }
13920  was_idle = 0;
13921  /* probably poll() is a valid cancel point, lets just be on the safe side
13922  by calling pthread_testcancel */
13923  pthread_testcancel();
13924  res = poll(pollers, mfcr2->numchans, maxsleep);
13925  pthread_testcancel();
13926  if ((res < 0) && (errno != EINTR)) {
13927  ast_log(LOG_ERROR, "going out, poll failed: %s\n", strerror(errno));
13928  break;
13929  }
13930  /* do we want to allow to cancel while processing events? */
13931  pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate);
13932  for (i = 0; i < mfcr2->numchans; i++) {
13933  pvt = mfcr2->pvts[i];
13934  if (!pvt) {
13935  continue;
13936  }
13937  if (pollers[i].revents & POLLPRI || pollers[i].revents & POLLIN) {
13938  openr2_chan_process_event(pvt->r2chan);
13939  }
13940  }
13941  pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
13942  }
13943  ast_log(LOG_NOTICE, "Quitting MFC/R2 monitor thread\n");
13944  return 0;
13945 }
13946 #endif /* HAVE_OPENR2 */
13947 
13948 #if defined(HAVE_PRI)
13949 static void dahdi_pri_message(struct pri *pri, char *s)
13950 {
13951  int x;
13952  int y;
13953  int dchan = -1;
13954  int span = -1;
13955  int dchancount = 0;
13956 
13957  if (pri) {
13958  for (x = 0; x < NUM_SPANS; x++) {
13959  for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
13960  if (pris[x].pri.dchans[y]) {
13961  dchancount++;
13962  }
13963 
13964  if (pris[x].pri.dchans[y] == pri) {
13965  dchan = y;
13966  }
13967  }
13968  if (dchan >= 0) {
13969  span = x;
13970  break;
13971  }
13972  dchancount = 0;
13973  }
13974  if (-1 < span) {
13975  if (1 < dchancount) {
13976  ast_verbose_callid(0, "[PRI Span: %d D-Channel: %d] %s", span + 1, dchan, s);
13977  } else {
13978  ast_verbose_callid(0, "PRI Span: %d %s", span + 1, s);
13979  }
13980  } else {
13981  ast_verbose_callid(0, "PRI Span: ? %s", s);
13982  }
13983  } else {
13984  ast_verbose_callid(0, "PRI Span: ? %s", s);
13985  }
13986 
13987  ast_mutex_lock(&pridebugfdlock);
13988 
13989  if (pridebugfd >= 0) {
13990  if (write(pridebugfd, s, strlen(s)) < 0) {
13991  ast_log_callid(LOG_WARNING, 0, "write() failed: %s\n", strerror(errno));
13992  }
13993  }
13994 
13995  ast_mutex_unlock(&pridebugfdlock);
13996 }
13997 #endif /* defined(HAVE_PRI) */
13998 
13999 #if defined(HAVE_PRI)
14000 static void dahdi_pri_error(struct pri *pri, char *s)
14001 {
14002  int x;
14003  int y;
14004  int dchan = -1;
14005  int span = -1;
14006  int dchancount = 0;
14007 
14008  if (pri) {
14009  for (x = 0; x < NUM_SPANS; x++) {
14010  for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
14011  if (pris[x].pri.dchans[y]) {
14012  dchancount++;
14013  }
14014 
14015  if (pris[x].pri.dchans[y] == pri) {
14016  dchan = y;
14017  }
14018  }
14019  if (dchan >= 0) {
14020  span = x;
14021  break;
14022  }
14023  dchancount = 0;
14024  }
14025  if (-1 < span) {
14026  if (1 < dchancount) {
14027  ast_log_callid(LOG_ERROR, 0, "[PRI Span: %d D-Channel: %d] %s", span + 1, dchan, s);
14028  } else {
14029  ast_log_callid(LOG_ERROR, 0, "PRI Span: %d %s", span + 1, s);
14030  }
14031  } else {
14032  ast_log_callid(LOG_ERROR, 0, "PRI Span: ? %s", s);
14033  }
14034  } else {
14035  ast_log_callid(LOG_ERROR, 0, "PRI Span: ? %s", s);
14036  }
14037 
14038  ast_mutex_lock(&pridebugfdlock);
14039 
14040  if (pridebugfd >= 0) {
14041  if (write(pridebugfd, s, strlen(s)) < 0) {
14042  ast_log_callid(LOG_WARNING, 0, "write() failed: %s\n", strerror(errno));
14043  }
14044  }
14045 
14046  ast_mutex_unlock(&pridebugfdlock);
14047 }
14048 #endif /* defined(HAVE_PRI) */
14049 
14050 #if defined(HAVE_PRI)
14051 static int prepare_pri(struct dahdi_pri *pri)
14052 {
14053  int i, res, x;
14054  struct dahdi_params p;
14055  struct dahdi_bufferinfo bi;
14056  struct dahdi_spaninfo si;
14057 
14058  for (i = 0; i < SIG_PRI_NUM_DCHANS; i++) {
14059  if (!pri->dchannels[i])
14060  break;
14061  if (pri->pri.fds[i] >= 0) {
14062  /* A partial range addition. Not a complete setup. */
14063  break;
14064  }
14065  pri->pri.fds[i] = open("/dev/dahdi/channel", O_RDWR);
14066  if ((pri->pri.fds[i] < 0)) {
14067  ast_log(LOG_ERROR, "Unable to open D-channel (fd=%d) (%s)\n",
14068  pri->pri.fds[i], strerror(errno));
14069  return -1;
14070  }
14071  x = pri->dchannels[i];
14072  res = ioctl(pri->pri.fds[i], DAHDI_SPECIFY, &x);
14073  if (res) {
14074  dahdi_close_pri_fd(pri, i);
14075  ast_log(LOG_ERROR, "Unable to SPECIFY channel %d (%s)\n", x, strerror(errno));
14076  return -1;
14077  }
14078  memset(&p, 0, sizeof(p));
14079  res = ioctl(pri->pri.fds[i], DAHDI_GET_PARAMS, &p);
14080  if (res) {
14081  dahdi_close_pri_fd(pri, i);
14082  ast_log(LOG_ERROR, "Unable to get parameters for D-channel %d (%s)\n", x, strerror(errno));
14083  return -1;
14084  }
14085  if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC)) {
14086  dahdi_close_pri_fd(pri, i);
14087  ast_log(LOG_ERROR, "D-channel %d is not in HDLC/FCS mode.\n", x);
14088  return -1;
14089  }
14090  memset(&si, 0, sizeof(si));
14091  res = ioctl(pri->pri.fds[i], DAHDI_SPANSTAT, &si);
14092  if (res) {
14093  dahdi_close_pri_fd(pri, i);
14094  ast_log(LOG_ERROR, "Unable to get span state for D-channel %d (%s)\n", x, strerror(errno));
14095  }
14096  if (!si.alarms) {
14097  pri_event_noalarm(&pri->pri, i, 1);
14098  } else {
14099  pri_event_alarm(&pri->pri, i, 1);
14100  }
14101  memset(&bi, 0, sizeof(bi));
14102  bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
14103  bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
14104  bi.numbufs = 32;
14105  bi.bufsize = 1024;
14106  if (ioctl(pri->pri.fds[i], DAHDI_SET_BUFINFO, &bi)) {
14107  ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", x, strerror(errno));
14108  dahdi_close_pri_fd(pri, i);
14109  return -1;
14110  }
14111  pri->pri.dchan_logical_span[i] = pris[p.spanno - 1].prilogicalspan;
14112  }
14113  return 0;
14114 }
14115 #endif /* defined(HAVE_PRI) */
14116 
14117 #if defined(HAVE_PRI)
14118 static char *complete_span_helper(const char *line, const char *word, int pos, int state, int rpos)
14119 {
14120  int which, span;
14121  char *ret = NULL;
14122 
14123  if (pos != rpos)
14124  return ret;
14125 
14126  for (which = span = 0; span < NUM_SPANS; span++) {
14127  if (pris[span].pri.pri && ++which > state) {
14128  if (ast_asprintf(&ret, "%d", span + 1) < 0) { /* user indexes start from 1 */
14129  ret = NULL;
14130  }
14131  break;
14132  }
14133  }
14134  return ret;
14135 }
14136 #endif /* defined(HAVE_PRI) */
14137 
14138 #if defined(HAVE_PRI)
14139 static char *complete_span_4(const char *line, const char *word, int pos, int state)
14140 {
14141  return complete_span_helper(line,word,pos,state,3);
14142 }
14143 #endif /* defined(HAVE_PRI) */
14144 
14145 #if defined(HAVE_PRI)
14146 static char *handle_pri_set_debug_file(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14147 {
14148  int myfd;
14149  switch (cmd) {
14150  case CLI_INIT:
14151  e->command = "pri set debug file";
14152  e->usage = "Usage: pri set debug file [output-file]\n"
14153  " Sends PRI debug output to the specified output file\n";
14154  return NULL;
14155  case CLI_GENERATE:
14156  return NULL;
14157  }
14158  if (a->argc < 5)
14159  return CLI_SHOWUSAGE;
14160 
14161  if (ast_strlen_zero(a->argv[4]))
14162  return CLI_SHOWUSAGE;
14163 
14164  myfd = open(a->argv[4], O_CREAT|O_WRONLY, AST_FILE_MODE);
14165  if (myfd < 0) {
14166  ast_cli(a->fd, "Unable to open '%s' for writing\n", a->argv[4]);
14167  return CLI_SUCCESS;
14168  }
14169 
14170  ast_mutex_lock(&pridebugfdlock);
14171 
14172  if (pridebugfd >= 0)
14173  close(pridebugfd);
14174 
14175  pridebugfd = myfd;
14176  ast_copy_string(pridebugfilename,a->argv[4],sizeof(pridebugfilename));
14177  ast_mutex_unlock(&pridebugfdlock);
14178  ast_cli(a->fd, "PRI debug output will be sent to '%s'\n", a->argv[4]);
14179  return CLI_SUCCESS;
14180 }
14181 #endif /* defined(HAVE_PRI) */
14182 
14183 #if defined(HAVE_PRI)
14184 static int action_pri_debug_file_set(struct mansession *s, const struct message *m)
14185 {
14186  const char *output_file = astman_get_header(m, "File");
14187  int myfd;
14188 
14189  if (ast_strlen_zero(output_file)) {
14190  astman_send_error(s, m, "Action must define a 'File'");
14191  }
14192 
14193  myfd = open(output_file, O_CREAT|O_WRONLY, AST_FILE_MODE);
14194  if (myfd < 0) {
14195  astman_send_error(s, m, "Unable to open requested file for writing");
14196  return 0;
14197  }
14198 
14199  ast_mutex_lock(&pridebugfdlock);
14200 
14201  if (pridebugfd >= 0) {
14202  close(pridebugfd);
14203  }
14204 
14205  pridebugfd = myfd;
14206  ast_copy_string(pridebugfilename, output_file, sizeof(pridebugfilename));
14207  ast_mutex_unlock(&pridebugfdlock);
14208  astman_send_ack(s, m, "PRI debug output will now be sent to requested file.");
14209 
14210  return 0;
14211 }
14212 #endif /* defined(HAVE_PRI) */
14213 
14214 #if defined(HAVE_PRI)
14215 static int action_pri_debug_file_unset(struct mansession *s, const struct message *m)
14216 {
14217  ast_mutex_lock(&pridebugfdlock);
14218 
14219  if (pridebugfd >= 0) {
14220  close(pridebugfd);
14221  }
14222 
14223  pridebugfd = -1;
14224 
14225  ast_mutex_unlock(&pridebugfdlock);
14226 
14227  astman_send_ack(s, m, "PRI Debug output to file disabled");
14228  return 0;
14229 }
14230 #endif /* defined(HAVE_PRI) */
14231 
14232 #if defined(HAVE_PRI)
14233 static char *handle_pri_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14234 {
14235  int span;
14236  int x;
14237  int debugmask = 0;
14238  int level = 0;
14239  switch (cmd) {
14240  case CLI_INIT:
14241  e->command = "pri set debug {on|off|hex|intense|0|1|2|3|4|5|6|7|8|9|10|11|12|13|14|15} span";
14242  e->usage =
14243  "Usage: pri set debug {<level>|on|off|hex|intense} span <span>\n"
14244  " Enables debugging on a given PRI span\n"
14245  " Level is a bitmap of the following values:\n"
14246  " 1 General debugging incl. state changes\n"
14247  " 2 Decoded Q.931 messages\n"
14248  " 4 Decoded Q.921 messages\n"
14249  " 8 Raw hex dumps of Q.921 frames\n"
14250  " on - equivalent to 3\n"
14251  " hex - equivalent to 8\n"
14252  " intense - equivalent to 15\n";
14253  return NULL;
14254  case CLI_GENERATE:
14255  return complete_span_4(a->line, a->word, a->pos, a->n);
14256  }
14257  if (a->argc < 6) {
14258  return CLI_SHOWUSAGE;
14259  }
14260 
14261  if (!strcasecmp(a->argv[3], "on")) {
14262  level = 3;
14263  } else if (!strcasecmp(a->argv[3], "off")) {
14264  level = 0;
14265  } else if (!strcasecmp(a->argv[3], "intense")) {
14266  level = 15;
14267  } else if (!strcasecmp(a->argv[3], "hex")) {
14268  level = 8;
14269  } else {
14270  level = atoi(a->argv[3]);
14271  }
14272  span = atoi(a->argv[5]);
14273  if ((span < 1) || (span > NUM_SPANS)) {
14274  ast_cli(a->fd, "Invalid span %s. Should be a number %d to %d\n", a->argv[5], 1, NUM_SPANS);
14275  return CLI_SUCCESS;
14276  }
14277  if (!pris[span-1].pri.pri) {
14278  ast_cli(a->fd, "No PRI running on span %d\n", span);
14279  return CLI_SUCCESS;
14280  }
14281 
14282  if (level & 1) debugmask |= SIG_PRI_DEBUG_NORMAL;
14283  if (level & 2) debugmask |= PRI_DEBUG_Q931_DUMP;
14284  if (level & 4) debugmask |= PRI_DEBUG_Q921_DUMP;
14285  if (level & 8) debugmask |= PRI_DEBUG_Q921_RAW;
14286 
14287  /* Set debug level in libpri */
14288  for (x = 0; x < SIG_PRI_NUM_DCHANS; x++) {
14289  if (pris[span - 1].pri.dchans[x]) {
14290  pri_set_debug(pris[span - 1].pri.dchans[x], debugmask);
14291  }
14292  }
14293  if (level == 0) {
14294  /* Close the debugging file if it's set */
14295  ast_mutex_lock(&pridebugfdlock);
14296  if (0 <= pridebugfd) {
14297  close(pridebugfd);
14298  pridebugfd = -1;
14299  ast_cli(a->fd, "Disabled PRI debug output to file '%s'\n",
14300  pridebugfilename);
14301  }
14302  ast_mutex_unlock(&pridebugfdlock);
14303  }
14304  pris[span - 1].pri.debug = (level) ? 1 : 0;
14305  ast_cli(a->fd, "%s debugging on span %d\n", (level) ? "Enabled" : "Disabled", span);
14306  return CLI_SUCCESS;
14307 }
14308 #endif /* defined(HAVE_PRI) */
14309 
14310 #if defined(HAVE_PRI)
14311 static int action_pri_debug_set(struct mansession *s, const struct message *m)
14312 {
14313  const char *level = astman_get_header(m, "Level");
14314  const char *span = astman_get_header(m, "Span");
14315  int level_val;
14316  int span_val;
14317  int x;
14318  int debugmask = 0;
14319 
14320  if (ast_strlen_zero(level)) {
14321  astman_send_error(s, m, "'Level' was not specified");
14322  return 0;
14323  }
14324 
14325  if (ast_strlen_zero(span)) {
14326  astman_send_error(s, m, "'Span' was not specified");
14327  return 0;
14328  }
14329 
14330  if (!strcasecmp(level, "on")) {
14331  level_val = 3;
14332  } else if (!strcasecmp(level, "off")) {
14333  level_val = 0;
14334  } else if (!strcasecmp(level, "intense")) {
14335  level_val = 15;
14336  } else if (!strcasecmp(level, "hex")) {
14337  level_val = 8;
14338  } else {
14339  if (sscanf(level, "%30d", &level_val) != 1) {
14340  astman_send_error(s, m, "Invalid value for 'Level'");
14341  return 0;
14342  }
14343  }
14344 
14345  if (sscanf(span, "%30d", &span_val) != 1) {
14346  astman_send_error(s, m, "Invalid value for 'Span'");
14347  }
14348 
14349  if ((span_val < 1) || (span_val > NUM_SPANS)) {
14350  const char *id = astman_get_header(m, "ActionID");
14351  char id_text[256] = "";
14352 
14353  if (!ast_strlen_zero(id)) {
14354  snprintf(id_text, sizeof(id_text), "ActionID: %s\r\n", id);
14355  }
14356 
14357  astman_append(s, "Response: Error\r\n"
14358  "%s" /* id_text */
14359  "Message: Invalid span '%s' - Should be a number from 1 to %d\r\n"
14360  "\r\n",
14361  id_text,
14362  span, NUM_SPANS);
14363 
14364  return 0;
14365  }
14366 
14367  if (!pris[span_val-1].pri.pri) {
14368  astman_send_error(s, m, "No PRI running on requested span");
14369  return 0;
14370  }
14371 
14372  if (level_val & 1) {
14373  debugmask |= SIG_PRI_DEBUG_NORMAL;
14374  }
14375  if (level_val & 2) {
14376  debugmask |= PRI_DEBUG_Q931_DUMP;
14377  }
14378  if (level_val & 4) {
14379  debugmask |= PRI_DEBUG_Q921_DUMP;
14380  }
14381  if (level_val & 8) {
14382  debugmask |= PRI_DEBUG_Q921_RAW;
14383  }
14384 
14385  /* Set debug level in libpri */
14386  for (x = 0; x < SIG_PRI_NUM_DCHANS; x++) {
14387  if (pris[span_val - 1].pri.dchans[x]) {
14388  pri_set_debug(pris[span_val - 1].pri.dchans[x], debugmask);
14389  }
14390  }
14391 
14392  pris[span_val - 1].pri.debug = (level_val) ? 1 : 0;
14393  astman_send_ack(s, m, "Debug level set for requested span");
14394 
14395  return 0;
14396 }
14397 #endif /* defined(HAVE_PRI) */
14398 
14399 #if defined(HAVE_PRI)
14400 #if defined(HAVE_PRI_SERVICE_MESSAGES)
14401 static char *handle_pri_service_generic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a, int changestatus)
14402 {
14403  unsigned *why;
14404  int channel;
14405  int trunkgroup;
14406  int x, y, fd = a->fd;
14407  int interfaceid = 0;
14408  char db_chan_name[20], db_answer[15];
14409  struct dahdi_pvt *tmp;
14410  struct dahdi_pri *pri;
14411 
14412  if (a->argc < 5 || a->argc > 6)
14413  return CLI_SHOWUSAGE;
14414  if (strchr(a->argv[4], ':')) {
14415  if (sscanf(a->argv[4], "%30d:%30d", &trunkgroup, &channel) != 2)
14416  return CLI_SHOWUSAGE;
14417  if ((trunkgroup < 1) || (channel < 1))
14418  return CLI_SHOWUSAGE;
14419  pri = NULL;
14420  for (x=0;x<NUM_SPANS;x++) {
14421  if (pris[x].pri.trunkgroup == trunkgroup) {
14422  pri = pris + x;
14423  break;
14424  }
14425  }
14426  if (!pri) {
14427  ast_cli(fd, "No such trunk group %d\n", trunkgroup);
14428  return CLI_FAILURE;
14429  }
14430  } else
14431  channel = atoi(a->argv[4]);
14432 
14433  if (a->argc == 6)
14434  interfaceid = atoi(a->argv[5]);
14435 
14436  /* either servicing a D-Channel */
14437  for (x = 0; x < NUM_SPANS; x++) {
14438  for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
14439  if (pris[x].dchannels[y] == channel) {
14440  pri = pris + x;
14441  if (pri->pri.enable_service_message_support) {
14442  ast_mutex_lock(&pri->pri.lock);
14443  pri_maintenance_service(pri->pri.pri, interfaceid, -1, changestatus);
14444  ast_mutex_unlock(&pri->pri.lock);
14445  } else {
14446  ast_cli(fd,
14447  "\n\tThis operation has not been enabled in chan_dahdi.conf, set 'service_message_support=yes' to use this operation.\n"
14448  "\tNote only 4ESS, 5ESS, and NI2 switch types are supported.\n\n");
14449  }
14450  return CLI_SUCCESS;
14451  }
14452  }
14453  }
14454 
14455  /* or servicing a B-Channel */
14457  for (tmp = iflist; tmp; tmp = tmp->next) {
14458  if (tmp->pri && tmp->channel == channel) {
14460  ast_mutex_lock(&tmp->pri->lock);
14461  if (!tmp->pri->enable_service_message_support) {
14462  ast_mutex_unlock(&tmp->pri->lock);
14463  ast_cli(fd,
14464  "\n\tThis operation has not been enabled in chan_dahdi.conf, set 'service_message_support=yes' to use this operation.\n"
14465  "\tNote only 4ESS, 5ESS, and NI2 switch types are supported.\n\n");
14466  return CLI_SUCCESS;
14467  }
14468  snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, tmp->span, channel);
14469  why = &((struct sig_pri_chan *) tmp->sig_pvt)->service_status;
14470  switch(changestatus) {
14471  case 0: /* enable */
14472  /* Near end wants to be in service now. */
14473  ast_db_del(db_chan_name, SRVST_DBKEY);
14474  *why &= ~SRVST_NEAREND;
14475  if (*why) {
14476  snprintf(db_answer, sizeof(db_answer), "%s:%u", SRVST_TYPE_OOS, *why);
14477  ast_db_put(db_chan_name, SRVST_DBKEY, db_answer);
14478  } else {
14479  dahdi_pri_update_span_devstate(tmp->pri);
14480  }
14481  break;
14482  /* case 1: -- loop */
14483  case 2: /* disable */
14484  /* Near end wants to be out-of-service now. */
14485  ast_db_del(db_chan_name, SRVST_DBKEY);
14486  *why |= SRVST_NEAREND;
14487  snprintf(db_answer, sizeof(db_answer), "%s:%u", SRVST_TYPE_OOS, *why);
14488  ast_db_put(db_chan_name, SRVST_DBKEY, db_answer);
14489  dahdi_pri_update_span_devstate(tmp->pri);
14490  break;
14491  /* case 3: -- continuity */
14492  /* case 4: -- shutdown */
14493  default:
14494  ast_log(LOG_WARNING, "Unsupported changestatus: '%d'\n", changestatus);
14495  break;
14496  }
14497  pri_maintenance_bservice(tmp->pri->pri, tmp->sig_pvt, changestatus);
14498  ast_mutex_unlock(&tmp->pri->lock);
14499  return CLI_SUCCESS;
14500  }
14501  }
14503 
14504  ast_cli(fd, "Unable to find given channel %d, possibly not a PRI\n", channel);
14505  return CLI_FAILURE;
14506 }
14507 
14508 static char *handle_pri_service_enable_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14509 {
14510  switch (cmd) {
14511  case CLI_INIT:
14512  e->command = "pri service enable channel";
14513  e->usage =
14514  "Usage: pri service enable channel <channel> [<interface id>]\n"
14515  " Send an AT&T / NFAS / CCS ANSI T1.607 maintenance message\n"
14516  " to restore a channel to service, with optional interface id\n"
14517  " as agreed upon with remote switch operator\n";
14518  return NULL;
14519  case CLI_GENERATE:
14520  return NULL;
14521  }
14522  return handle_pri_service_generic(e, cmd, a, 0);
14523 }
14524 
14525 static char *handle_pri_service_disable_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14526 {
14527  switch (cmd) {
14528  case CLI_INIT:
14529  e->command = "pri service disable channel";
14530  e->usage =
14531  "Usage: pri service disable channel <chan num> [<interface id>]\n"
14532  " Send an AT&T / NFAS / CCS ANSI T1.607 maintenance message\n"
14533  " to remove a channel from service, with optional interface id\n"
14534  " as agreed upon with remote switch operator\n";
14535  return NULL;
14536  case CLI_GENERATE:
14537  return NULL;
14538  }
14539  return handle_pri_service_generic(e, cmd, a, 2);
14540 }
14541 #endif /* defined(HAVE_PRI_SERVICE_MESSAGES) */
14542 #endif /* defined(HAVE_PRI) */
14543 
14544 #if defined(HAVE_PRI)
14545 static char *handle_pri_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14546 {
14547  int span;
14548 
14549  switch (cmd) {
14550  case CLI_INIT:
14551  e->command = "pri show channels";
14552  e->usage =
14553  "Usage: pri show channels\n"
14554  " Displays PRI channel information such as the current mapping\n"
14555  " of DAHDI B channels to Asterisk channel names and which calls\n"
14556  " are on hold or call-waiting. Calls on hold or call-waiting\n"
14557  " are not associated with any B channel.\n";
14558  return NULL;
14559  case CLI_GENERATE:
14560  return NULL;
14561  }
14562 
14563  if (a->argc != 3)
14564  return CLI_SHOWUSAGE;
14565 
14567  for (span = 0; span < NUM_SPANS; ++span) {
14568  if (pris[span].pri.pri) {
14569  sig_pri_cli_show_channels(a->fd, &pris[span].pri);
14570  }
14571  }
14572  return CLI_SUCCESS;
14573 }
14574 #endif /* defined(HAVE_PRI) */
14575 
14576 #if defined(HAVE_PRI)
14577 static char *handle_pri_show_spans(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14578 {
14579  int span;
14580 
14581  switch (cmd) {
14582  case CLI_INIT:
14583  e->command = "pri show spans";
14584  e->usage =
14585  "Usage: pri show spans\n"
14586  " Displays PRI span information\n";
14587  return NULL;
14588  case CLI_GENERATE:
14589  return NULL;
14590  }
14591 
14592  if (a->argc != 3)
14593  return CLI_SHOWUSAGE;
14594 
14595  for (span = 0; span < NUM_SPANS; span++) {
14596  if (pris[span].pri.pri) {
14597  sig_pri_cli_show_spans(a->fd, span + 1, &pris[span].pri);
14598  }
14599  }
14600  return CLI_SUCCESS;
14601 }
14602 #endif /* defined(HAVE_PRI) */
14603 
14604 #if defined(HAVE_PRI)
14605 #define container_of(ptr, type, member) \
14606  ((type *)((char *)(ptr) - offsetof(type, member)))
14607 /*!
14608  * \internal
14609  * \brief Destroy a D-Channel of a PRI span
14610  * \since 12
14611  *
14612  * \param pri the pri span
14613  *
14614  * Shuts down a span and destroys its D-Channel. Further destruction
14615  * of the B-channels using dahdi_destroy_channel() would probably be required
14616  * for the B-Channels.
14617  */
14618 static void pri_destroy_span(struct sig_pri_span *pri)
14619 {
14620  int i;
14621  int res;
14622  int cancel_code;
14623  struct dahdi_pri* dahdi_pri;
14624  pthread_t master = pri->master;
14625 
14626  if (!master || (master == AST_PTHREADT_NULL)) {
14627  return;
14628  }
14629  ast_debug(2, "About to destroy DAHDI channels of span %d.\n", pri->span);
14630  for (i = 0; i < pri->numchans; i++) {
14631  int channel;
14632  struct sig_pri_chan *pvt = pri->pvts[i];
14633 
14634  if (!pvt) {
14635  continue;
14636  }
14637  channel = pvt->channel;
14638  ast_debug(2, "About to destroy B-channel %d.\n", channel);
14639  dahdi_destroy_channel_range(channel, channel);
14640  }
14641 
14642  cancel_code = pthread_cancel(master);
14643  pthread_kill(master, SIGURG);
14644  ast_debug(4,
14645  "Waiting to join thread of span %d "
14646  "with pid=%p cancel_code=%d\n",
14647  pri->span, (void *)master, cancel_code);
14648  res = pthread_join(master, NULL);
14649  if (res != 0) {
14650  ast_log(LOG_NOTICE, "pthread_join failed: %d\n", res);
14651  }
14652  pri->master = AST_PTHREADT_NULL;
14653 
14654  /* The 'struct dahdi_pri' that contains our 'struct sig_pri_span' */
14655  dahdi_pri = container_of(pri, struct dahdi_pri, pri);
14656  for (i = 0; i < SIG_PRI_NUM_DCHANS; i++) {
14657  ast_debug(4, "closing pri_fd %d\n", i);
14658  dahdi_close_pri_fd(dahdi_pri, i);
14659  dahdi_pri->dchannels[i] = 0;
14660  }
14661  sig_pri_init_pri(pri);
14662  ast_debug(1, "PRI span %d destroyed\n", pri->span);
14663 }
14664 
14665 static char *handle_pri_destroy_span(struct ast_cli_entry *e, int cmd,
14666  struct ast_cli_args *a)
14667 {
14668  int span;
14669  int res;
14670  struct sig_pri_span *pri;
14671 
14672  switch (cmd) {
14673  case CLI_INIT:
14674  e->command = "pri destroy span";
14675  e->usage =
14676  "Usage: pri destroy span <span>\n"
14677  " Destorys D-channel of span and its B-channels.\n"
14678  " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n";
14679  return NULL;
14680  case CLI_GENERATE:
14681  return complete_span_4(a->line, a->word, a->pos, a->n);
14682  }
14683 
14684  if (a->argc < 4) {
14685  return CLI_SHOWUSAGE;
14686  }
14687  res = sscanf(a->argv[3], "%30d", &span);
14688  if ((res != 1) || span < 1 || span > NUM_SPANS) {
14689  ast_cli(a->fd,
14690  "Invalid span '%s'. Should be a number from %d to %d\n",
14691  a->argv[3], 1, NUM_SPANS);
14692  return CLI_SUCCESS;
14693  }
14694  pri = &pris[span - 1].pri;
14695  if (!pri->pri) {
14696  ast_cli(a->fd, "No PRI running on span %d\n", span);
14697  return CLI_SUCCESS;
14698  }
14699 
14700  pri_destroy_span(pri);
14701  return CLI_SUCCESS;
14702 }
14703 
14704 #endif /* defined(HAVE_PRI) */
14705 
14706 #if defined(HAVE_PRI)
14707 static char *handle_pri_show_span(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14708 {
14709  int span;
14710 
14711  switch (cmd) {
14712  case CLI_INIT:
14713  e->command = "pri show span";
14714  e->usage =
14715  "Usage: pri show span <span>\n"
14716  " Displays PRI Information on a given PRI span\n";
14717  return NULL;
14718  case CLI_GENERATE:
14719  return complete_span_4(a->line, a->word, a->pos, a->n);
14720  }
14721 
14722  if (a->argc < 4)
14723  return CLI_SHOWUSAGE;
14724  span = atoi(a->argv[3]);
14725  if ((span < 1) || (span > NUM_SPANS)) {
14726  ast_cli(a->fd, "Invalid span '%s'. Should be a number from %d to %d\n", a->argv[3], 1, NUM_SPANS);
14727  return CLI_SUCCESS;
14728  }
14729  if (!pris[span-1].pri.pri) {
14730  ast_cli(a->fd, "No PRI running on span %d\n", span);
14731  return CLI_SUCCESS;
14732  }
14733 
14734  sig_pri_cli_show_span(a->fd, pris[span-1].dchannels, &pris[span-1].pri);
14735 
14736  return CLI_SUCCESS;
14737 }
14738 #endif /* defined(HAVE_PRI) */
14739 
14740 #if defined(HAVE_PRI)
14741 static char *handle_pri_show_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14742 {
14743  int x;
14744  int span;
14745  int count=0;
14746  int debug;
14747 
14748  switch (cmd) {
14749  case CLI_INIT:
14750  e->command = "pri show debug";
14751  e->usage =
14752  "Usage: pri show debug\n"
14753  " Show the debug state of pri spans\n";
14754  return NULL;
14755  case CLI_GENERATE:
14756  return NULL;
14757  }
14758 
14759  for (span = 0; span < NUM_SPANS; span++) {
14760  if (pris[span].pri.pri) {
14761  for (x = 0; x < SIG_PRI_NUM_DCHANS; x++) {
14762  if (pris[span].pri.dchans[x]) {
14763  debug = pri_get_debug(pris[span].pri.dchans[x]);
14764  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" );
14765  count++;
14766  }
14767  }
14768  }
14769 
14770  }
14771  ast_mutex_lock(&pridebugfdlock);
14772  if (pridebugfd >= 0)
14773  ast_cli(a->fd, "Logging PRI debug to file %s\n", pridebugfilename);
14774  ast_mutex_unlock(&pridebugfdlock);
14775 
14776  if (!count)
14777  ast_cli(a->fd, "No PRI running\n");
14778  return CLI_SUCCESS;
14779 }
14780 #endif /* defined(HAVE_PRI) */
14781 
14782 #if defined(HAVE_PRI)
14783 static char *handle_pri_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14784 {
14785  switch (cmd) {
14786  case CLI_INIT:
14787  e->command = "pri show version";
14788  e->usage =
14789  "Usage: pri show version\n"
14790  "Show libpri version information\n";
14791  return NULL;
14792  case CLI_GENERATE:
14793  return NULL;
14794  }
14795 
14796  ast_cli(a->fd, "libpri version: %s\n", pri_get_version());
14797 
14798  return CLI_SUCCESS;
14799 }
14800 #endif /* defined(HAVE_PRI) */
14801 
14802 #if defined(HAVE_PRI)
14803 static struct ast_cli_entry dahdi_pri_cli[] = {
14804  AST_CLI_DEFINE(handle_pri_debug, "Enables PRI debugging on a span"),
14805 #if defined(HAVE_PRI_SERVICE_MESSAGES)
14806  AST_CLI_DEFINE(handle_pri_service_enable_channel, "Return a channel to service"),
14807  AST_CLI_DEFINE(handle_pri_service_disable_channel, "Remove a channel from service"),
14808 #endif /* defined(HAVE_PRI_SERVICE_MESSAGES) */
14809  AST_CLI_DEFINE(handle_pri_show_channels, "Displays PRI channel information"),
14810  AST_CLI_DEFINE(handle_pri_show_spans, "Displays PRI span information"),
14811  AST_CLI_DEFINE(handle_pri_show_span, "Displays PRI span information"),
14812  AST_CLI_DEFINE(handle_pri_destroy_span, "Destroy a PRI span"),
14813  AST_CLI_DEFINE(handle_pri_show_debug, "Displays current PRI debug settings"),
14814  AST_CLI_DEFINE(handle_pri_set_debug_file, "Sends PRI debug output to the specified file"),
14815  AST_CLI_DEFINE(handle_pri_version, "Displays libpri version"),
14816 };
14817 #endif /* defined(HAVE_PRI) */
14818 
14819 #ifdef HAVE_OPENR2
14820 
14821 static char *handle_mfcr2_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14822 {
14823  switch (cmd) {
14824  case CLI_INIT:
14825  e->command = "mfcr2 show version";
14826  e->usage =
14827  "Usage: mfcr2 show version\n"
14828  " Shows the version of the OpenR2 library being used.\n";
14829  return NULL;
14830  case CLI_GENERATE:
14831  return NULL;
14832  }
14833  ast_cli(a->fd, "OpenR2 version: %s, revision: %s\n", openr2_get_version(), openr2_get_revision());
14834  return CLI_SUCCESS;
14835 }
14836 
14837 static char *handle_mfcr2_show_variants(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14838 {
14839 #define FORMAT "%4s %40s\n"
14840  int i = 0;
14841  int numvariants = 0;
14842  const openr2_variant_entry_t *variants;
14843  switch (cmd) {
14844  case CLI_INIT:
14845  e->command = "mfcr2 show variants";
14846  e->usage =
14847  "Usage: mfcr2 show variants\n"
14848  " Shows the list of MFC/R2 variants supported.\n";
14849  return NULL;
14850  case CLI_GENERATE:
14851  return NULL;
14852  }
14853  if (!(variants = openr2_proto_get_variant_list(&numvariants))) {
14854  ast_cli(a->fd, "Failed to get list of variants.\n");
14855  return CLI_FAILURE;
14856  }
14857  ast_cli(a->fd, FORMAT, "Variant Code", "Country");
14858  for (i = 0; i < numvariants; i++) {
14859  ast_cli(a->fd, FORMAT, variants[i].name, variants[i].country);
14860  }
14861  return CLI_SUCCESS;
14862 #undef FORMAT
14863 }
14864 
14865 static char *handle_mfcr2_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14866 {
14867 #define FORMAT "%4s %4s %-7.7s %-7.7s %-8.8s %-9.9s %-16.16s %-8.8s %-8.8s\n"
14868  int filtertype = 0;
14869  int targetnum = 0;
14870  char channo[5];
14871  char linkno[5];
14872  char anino[5];
14873  char dnisno[5];
14874  struct dahdi_pvt *p;
14875  openr2_context_t *r2context;
14876  openr2_variant_t r2variant;
14877  switch (cmd) {
14878  case CLI_INIT:
14879  e->command = "mfcr2 show channels [group|context]";
14880  e->usage =
14881  "Usage: mfcr2 show channels [group <group> | context <context>]\n"
14882  " Shows the DAHDI channels configured with MFC/R2 signaling.\n";
14883  return NULL;
14884  case CLI_GENERATE:
14885  return NULL;
14886  }
14887  if (!((a->argc == 3) || (a->argc == 5))) {
14888  return CLI_SHOWUSAGE;
14889  }
14890  if (a->argc == 5) {
14891  if (!strcasecmp(a->argv[3], "group")) {
14892  targetnum = atoi(a->argv[4]);
14893  if ((targetnum < 0) || (targetnum > 63))
14894  return CLI_SHOWUSAGE;
14895  targetnum = 1 << targetnum;
14896  filtertype = 1;
14897  } else if (!strcasecmp(a->argv[3], "context")) {
14898  filtertype = 2;
14899  } else {
14900  return CLI_SHOWUSAGE;
14901  }
14902  }
14903  ast_cli(a->fd, FORMAT, "Chan", "Link#", "Variant", "Max ANI", "Max DNIS", "ANI First", "Immediate Accept", "Tx CAS", "Rx CAS");
14905  for (p = iflist; p; p = p->next) {
14906  if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14907  continue;
14908  }
14909  if (filtertype) {
14910  switch(filtertype) {
14911  case 1: /* mfcr2 show channels group <group> */
14912  if (p->group != targetnum) {
14913  continue;
14914  }
14915  break;
14916  case 2: /* mfcr2 show channels context <context> */
14917  if (strcasecmp(p->context, a->argv[4])) {
14918  continue;
14919  }
14920  break;
14921  default:
14922  ;
14923  }
14924  }
14925  r2context = openr2_chan_get_context(p->r2chan);
14926  r2variant = openr2_context_get_variant(r2context);
14927  snprintf(channo, sizeof(channo), "%d", p->channel);
14928  snprintf(linkno, sizeof(linkno), "%d", p->mfcr2->index);
14929  snprintf(anino, sizeof(anino), "%d", openr2_context_get_max_ani(r2context));
14930  snprintf(dnisno, sizeof(dnisno), "%d", openr2_context_get_max_dnis(r2context));
14931  ast_cli(a->fd, FORMAT, channo, linkno, openr2_proto_get_variant_string(r2variant),
14932  anino, dnisno, openr2_context_get_ani_first(r2context) ? "Yes" : "No",
14933  openr2_context_get_immediate_accept(r2context) ? "Yes" : "No",
14934  openr2_chan_get_tx_cas_string(p->r2chan), openr2_chan_get_rx_cas_string(p->r2chan));
14935  }
14937  return CLI_SUCCESS;
14938 #undef FORMAT
14939 }
14940 
14941 static char *handle_mfcr2_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14942 {
14943  struct dahdi_pvt *p = NULL;
14944  int channo = 0;
14945  char *toklevel = NULL;
14946  char *saveptr = NULL;
14947  char *logval = NULL;
14948  openr2_log_level_t loglevel = OR2_LOG_NOTHING;
14949  openr2_log_level_t tmplevel = OR2_LOG_NOTHING;
14950  switch (cmd) {
14951  case CLI_INIT:
14952  e->command = "mfcr2 set debug";
14953  e->usage =
14954  "Usage: mfcr2 set debug <loglevel> <channel>\n"
14955  " Set a new logging level for the specified channel.\n"
14956  " If no channel is specified the logging level will be applied to all channels.\n";
14957  return NULL;
14958  case CLI_GENERATE:
14959  return NULL;
14960  }
14961  if (a->argc < 4) {
14962  return CLI_SHOWUSAGE;
14963  }
14964  channo = (a->argc == 5) ? atoi(a->argv[4]) : -1;
14965  logval = ast_strdupa(a->argv[3]);
14966  toklevel = strtok_r(logval, ",", &saveptr);
14967  if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
14968  ast_cli(a->fd, "Invalid MFC/R2 logging level '%s'.\n", a->argv[3]);
14969  return CLI_FAILURE;
14970  } else if (OR2_LOG_NOTHING == tmplevel) {
14971  loglevel = tmplevel;
14972  } else {
14973  loglevel |= tmplevel;
14974  while ((toklevel = strtok_r(NULL, ",", &saveptr))) {
14975  if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
14976  ast_cli(a->fd, "Ignoring invalid logging level: '%s'.\n", toklevel);
14977  continue;
14978  }
14979  loglevel |= tmplevel;
14980  }
14981  }
14983  for (p = iflist; p; p = p->next) {
14984  if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14985  continue;
14986  }
14987  if ((channo != -1) && (p->channel != channo )) {
14988  continue;
14989  }
14990  openr2_chan_set_log_level(p->r2chan, loglevel);
14991  if (channo != -1) {
14992  ast_cli(a->fd, "MFC/R2 debugging set to '%s' for channel %d.\n", a->argv[3], p->channel);
14993  break;
14994  }
14995  }
14996  if ((channo != -1) && !p) {
14997  ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
14998  }
14999  if (channo == -1) {
15000  ast_cli(a->fd, "MFC/R2 debugging set to '%s' for all channels.\n", a->argv[3]);
15001  }
15003  return CLI_SUCCESS;
15004 }
15005 
15006 static char *handle_mfcr2_call_files(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15007 {
15008  struct dahdi_pvt *p = NULL;
15009  int channo = 0;
15010  switch (cmd) {
15011  case CLI_INIT:
15012  e->command = "mfcr2 call files [on|off]";
15013  e->usage =
15014  "Usage: mfcr2 call files [on|off] <channel>\n"
15015  " Enable call files creation on the specified channel.\n"
15016  " If no channel is specified call files creation policy will be applied to all channels.\n";
15017  return NULL;
15018  case CLI_GENERATE:
15019  return NULL;
15020  }
15021  if (a->argc < 4) {
15022  return CLI_SHOWUSAGE;
15023  }
15024  channo = (a->argc == 5) ? atoi(a->argv[4]) : -1;
15026  for (p = iflist; p; p = p->next) {
15027  if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
15028  continue;
15029  }
15030  if ((channo != -1) && (p->channel != channo )) {
15031  continue;
15032  }
15033  if (ast_true(a->argv[3])) {
15034  openr2_chan_enable_call_files(p->r2chan);
15035  } else {
15036  openr2_chan_disable_call_files(p->r2chan);
15037  }
15038  if (channo != -1) {
15039  if (ast_true(a->argv[3])) {
15040  ast_cli(a->fd, "MFC/R2 call files enabled for channel %d.\n", p->channel);
15041  } else {
15042  ast_cli(a->fd, "MFC/R2 call files disabled for channel %d.\n", p->channel);
15043  }
15044  break;
15045  }
15046  }
15047  if ((channo != -1) && !p) {
15048  ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
15049  }
15050  if (channo == -1) {
15051  if (ast_true(a->argv[3])) {
15052  ast_cli(a->fd, "MFC/R2 Call files enabled for all channels.\n");
15053  } else {
15054  ast_cli(a->fd, "MFC/R2 Call files disabled for all channels.\n");
15055  }
15056  }
15058  return CLI_SUCCESS;
15059 }
15060 
15061 static char *handle_mfcr2_set_idle(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15062 {
15063  struct dahdi_pvt *p = NULL;
15064  int channo = 0;
15065  switch (cmd) {
15066  case CLI_INIT:
15067  e->command = "mfcr2 set idle";
15068  e->usage =
15069  "Usage: mfcr2 set idle <channel>\n"
15070  " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n"
15071  " Force the given channel into IDLE state.\n"
15072  " If no channel is specified, all channels will be set to IDLE.\n";
15073  return NULL;
15074  case CLI_GENERATE:
15075  return NULL;
15076  }
15077  channo = (a->argc == 4) ? atoi(a->argv[3]) : -1;
15079  for (p = iflist; p; p = p->next) {
15080  if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
15081  continue;
15082  }
15083  if ((channo != -1) && (p->channel != channo )) {
15084  continue;
15085  }
15086  openr2_chan_set_idle(p->r2chan);
15087  ast_mutex_lock(&p->lock);
15088  p->locallyblocked = 0;
15089  p->mfcr2call = 0;
15090  ast_mutex_unlock(&p->lock);
15091  if (channo != -1) {
15092  break;
15093  }
15094  }
15095  if ((channo != -1) && !p) {
15096  ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
15097  }
15099  return CLI_SUCCESS;
15100 }
15101 
15102 static char *handle_mfcr2_set_blocked(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15103 {
15104  struct dahdi_pvt *p = NULL;
15105  int channo = 0;
15106  switch (cmd) {
15107  case CLI_INIT:
15108  e->command = "mfcr2 set blocked";
15109  e->usage =
15110  "Usage: mfcr2 set blocked <channel>\n"
15111  " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n"
15112  " Force the given channel into BLOCKED state.\n"
15113  " If no channel is specified, all channels will be set to BLOCKED.\n";
15114  return NULL;
15115  case CLI_GENERATE:
15116  return NULL;
15117  }
15118  channo = (a->argc == 4) ? atoi(a->argv[3]) : -1;
15120  for (p = iflist; p; p = p->next) {
15121  if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
15122  continue;
15123  }
15124  if ((channo != -1) && (p->channel != channo )) {
15125  continue;
15126  }
15127  openr2_chan_set_blocked(p->r2chan);
15128  ast_mutex_lock(&p->lock);
15129  p->locallyblocked = 1;
15130  ast_mutex_unlock(&p->lock);
15131  if (channo != -1) {
15132  break;
15133  }
15134  }
15135  if ((channo != -1) && !p) {
15136  ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
15137  }
15139  return CLI_SUCCESS;
15140 }
15141 
15142 static void mfcr2_show_links_of(struct ast_cli_args *a, struct r2links *list_head, const char *title)
15143 {
15144 #define FORMAT "%-5s %-10s %-15s %-10s %s\n"
15145  AST_LIST_LOCK(list_head);
15146  if (! AST_LIST_EMPTY(list_head)) {
15147  int x = 0;
15148  char index[5];
15149  char live_chans_str[5];
15150  char channel_list[R2_LINK_CAPACITY * 4];
15151  struct r2link_entry *cur;
15152  ast_cli(a->fd, "%s\n", title);
15153  ast_cli(a->fd, FORMAT, "Index", "Thread", "Dahdi-Device", "Channels", "Channel-List");
15154  AST_LIST_TRAVERSE(list_head, cur, list) {
15155  struct dahdi_mfcr2 *mfcr2 = &cur->mfcr2;
15156  const char *thread_status = NULL;
15157  int i;
15158  int len;
15159  int inside_range;
15160  int channo;
15161  int prev_channo;
15162  x++;
15163  if (mfcr2->r2master == 0L) {
15164  thread_status = "zero";
15165  } else if (mfcr2->r2master == AST_PTHREADT_NULL) {
15166  thread_status = "none";
15167  } else {
15168  thread_status = "created";
15169  }
15170  snprintf(index, sizeof(index), "%d", mfcr2->index);
15171  snprintf(live_chans_str, sizeof(live_chans_str), "%d", mfcr2->live_chans);
15172  channo = 0;
15173  prev_channo = 0;
15174  inside_range = 0;
15175  len = 0;
15176  /* Prepare nice string in channel_list[] */
15177  for (i = 0; i < mfcr2->numchans && len < sizeof(channel_list) - 1; i++) {
15178  struct dahdi_pvt *p = mfcr2->pvts[i];
15179  if (!p) {
15180  continue;
15181  }
15182  channo = p->channel;
15183  /* Don't show a range until we know the last channel number */
15184  if (prev_channo && prev_channo == channo - 1) {
15185  prev_channo = channo;
15186  inside_range = 1;
15187  continue;
15188  }
15189  if (inside_range) {
15190  /* Close range */
15191  len += snprintf(channel_list + len, sizeof(channel_list) - len - 1, "-%d,%d", prev_channo, channo);
15192  inside_range = 0;
15193  } else if (prev_channo) {
15194  /* Non-sequential channel numbers */
15195  len += snprintf(channel_list + len, sizeof(channel_list) - len - 1, ",%d", channo);
15196  } else {
15197  /* First channel number */
15198  len += snprintf(channel_list + len, sizeof(channel_list) - len - 1, "%d", channo);
15199  }
15200  prev_channo = channo;
15201  }
15202  /* Handle leftover channels */
15203  if (inside_range) {
15204  /* Close range */
15205  len += snprintf(channel_list + len, sizeof(channel_list) - len - 1, "-%d", channo);
15206  inside_range = 0;
15207  } else if (prev_channo) {
15208  /* Non-sequential channel numbers */
15209  len += snprintf(channel_list + len, sizeof(channel_list) - len - 1, ",%d", channo);
15210  }
15211  // channel_list[len] = '\0';
15212  ast_cli(a->fd, FORMAT,
15213  index,
15214  thread_status,
15215  (mfcr2->nodev) ? "MISSING" : "OK",
15216  live_chans_str,
15217  channel_list);
15218  }
15219  }
15220  AST_LIST_UNLOCK(list_head);
15221 #undef FORMAT
15222 }
15223 
15224 static char *handle_mfcr2_show_links(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15225 {
15226  switch (cmd) {
15227  case CLI_INIT:
15228  e->command = "mfcr2 show links";
15229  e->usage =
15230  "Usage: mfcr2 show links\n"
15231  " Shows the DAHDI MFC/R2 links.\n";
15232  return NULL;
15233  case CLI_GENERATE:
15234  return NULL;
15235  }
15236  if (a->argc != 3) {
15237  return CLI_SHOWUSAGE;
15238  }
15239  mfcr2_show_links_of(a, &r2links, "Live links\n");
15240  mfcr2_show_links_of(a, &nodev_r2links, "Links to be removed (device missing)\n");
15241  return CLI_SUCCESS;
15242 }
15243 
15244 static char *handle_mfcr2_destroy_link(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15245 {
15246  int res;
15247  int wanted_link_index;
15248  int found_link = 0;
15249  struct r2link_entry *cur = NULL;
15250 
15251  switch (cmd) {
15252  case CLI_INIT:
15253  e->command = "mfcr2 destroy link";
15254  e->usage =
15255  "Usage: mfcr2 destroy link <index-number>\n"
15256  " Destorys D-channel of link and its B-channels.\n"
15257  " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n";
15258  return NULL;
15259  case CLI_GENERATE:
15260  return NULL;
15261  }
15262  if (a->argc < 4) {
15263  return CLI_SHOWUSAGE;
15264  }
15265  res = sscanf(a->argv[3], "%30d", &wanted_link_index);
15266  if ((res != 1) || wanted_link_index < 1) {
15267  ast_cli(a->fd,
15268  "Invalid link index '%s'. Should be a positive number\n", a->argv[3]);
15269  return CLI_SUCCESS;
15270  }
15271  AST_LIST_LOCK(&r2links);
15272  AST_LIST_TRAVERSE_SAFE_BEGIN(&r2links, cur, list) {
15273  struct dahdi_mfcr2 *mfcr2 = &cur->mfcr2;
15274  if (wanted_link_index == mfcr2->index) {
15275  AST_LIST_MOVE_CURRENT(&nodev_r2links, list);
15276  r2links_count--;
15277  break;
15278  }
15279  }
15281  AST_LIST_UNLOCK(&r2links);
15282  if (! found_link) {
15283  ast_cli(a->fd, "No link found with index %d.\n", wanted_link_index);
15284  return CLI_FAILURE;
15285  }
15286  return CLI_SUCCESS;
15287 }
15288 
15289 static struct ast_cli_entry dahdi_mfcr2_cli[] = {
15290  AST_CLI_DEFINE(handle_mfcr2_version, "Show OpenR2 library version"),
15291  AST_CLI_DEFINE(handle_mfcr2_show_variants, "Show supported MFC/R2 variants"),
15292  AST_CLI_DEFINE(handle_mfcr2_show_channels, "Show MFC/R2 channels"),
15293  AST_CLI_DEFINE(handle_mfcr2_show_links, "Show MFC/R2 links"),
15294  AST_CLI_DEFINE(handle_mfcr2_set_debug, "Set MFC/R2 channel logging level"),
15295  AST_CLI_DEFINE(handle_mfcr2_call_files, "Enable/Disable MFC/R2 call files"),
15296  AST_CLI_DEFINE(handle_mfcr2_set_idle, "Reset MFC/R2 channel forcing it to IDLE"),
15297  AST_CLI_DEFINE(handle_mfcr2_set_blocked, "Reset MFC/R2 channel forcing it to BLOCKED"),
15298  AST_CLI_DEFINE(handle_mfcr2_destroy_link, "Destroy given MFC/R2 link"),
15299 };
15300 
15301 #endif /* HAVE_OPENR2 */
15302 
15303 static char *dahdi_destroy_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15304 {
15305  int start;
15306  int end;
15307  switch (cmd) {
15308  case CLI_INIT:
15309  e->command = "dahdi destroy channels";
15310  e->usage =
15311  "Usage: dahdi destroy channels <from_channel> [<to_channel>]\n"
15312  " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING. Immediately removes a given channel, whether it is in use or not\n";
15313  return NULL;
15314  case CLI_GENERATE:
15315  return NULL;
15316  }
15317  if ((a->argc < 4) || a->argc > 5) {
15318  return CLI_SHOWUSAGE;
15319  }
15320  start = atoi(a->argv[3]);
15321  if (start < 1) {
15322  ast_cli(a->fd, "Invalid starting channel number %s.\n",
15323  a->argv[4]);
15324  return CLI_FAILURE;
15325  }
15326  if (a->argc == 5) {
15327  end = atoi(a->argv[4]);
15328  if (end < 1) {
15329  ast_cli(a->fd, "Invalid ending channel number %s.\n",
15330  a->argv[4]);
15331  return CLI_FAILURE;
15332  }
15333  } else {
15334  end = start;
15335  }
15336 
15337  if (end < start) {
15338  ast_cli(a->fd,
15339  "range end (%d) is smaller than range start (%d)\n",
15340  end, start);
15341  return CLI_FAILURE;
15342  }
15343  dahdi_destroy_channel_range(start, end);
15344  return CLI_SUCCESS;
15345 }
15346 
15347 static char *dahdi_create_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15348 {
15349  int start;
15350  int end;
15351  int ret;
15352 
15353  switch (cmd) {
15354  case CLI_INIT:
15355  e->command = "dahdi create channels";
15356  e->usage = "Usage: dahdi create channels <from> [<to>] - a range of channels\n"
15357  " dahdi create channels new - add channels not yet created\n"
15358  "For ISDN and SS7 the range should include complete spans.\n";
15359  return NULL;
15360  case CLI_GENERATE:
15361  return NULL;
15362  }
15363  if ((a->argc < 4) || a->argc > 5) {
15364  return CLI_SHOWUSAGE;
15365  }
15366  if (a->argc == 4 && !strcmp(a->argv[3], "new")) {
15367  ret = dahdi_create_channel_range(0, 0);
15368  return (RESULT_SUCCESS == ret) ? CLI_SUCCESS : CLI_FAILURE;
15369  }
15370  start = atoi(a->argv[3]);
15371  if (start <= 0) {
15372  ast_cli(a->fd, "Invalid starting channel number '%s'.\n",
15373  a->argv[3]);
15374  return CLI_FAILURE;
15375  }
15376  if (a->argc == 5) {
15377  end = atoi(a->argv[4]);
15378  if (end <= 0) {
15379  ast_cli(a->fd, "Invalid ending channel number '%s'.\n",
15380  a->argv[4]);
15381  return CLI_FAILURE;
15382  }
15383  } else {
15384  end = start;
15385  }
15386  if (end < start) {
15387  ast_cli(a->fd,
15388  "range end (%d) is smaller than range start (%d)\n",
15389  end, start);
15390  return CLI_FAILURE;
15391  }
15392  ret = dahdi_create_channel_range(start, end);
15393  return (RESULT_SUCCESS == ret) ? CLI_SUCCESS : CLI_FAILURE;
15394 }
15395 
15396 static void dahdi_softhangup_all(void)
15397 {
15398  struct dahdi_pvt *p;
15399 retry:
15401  for (p = iflist; p; p = p->next) {
15402  ast_mutex_lock(&p->lock);
15403  if (p->owner && !p->restartpending) {
15404  if (ast_channel_trylock(p->owner)) {
15405  if (DEBUG_ATLEAST(3))
15406  ast_verbose("Avoiding deadlock\n");
15407  /* Avoid deadlock since you're not supposed to lock iflock or pvt before a channel */
15408  ast_mutex_unlock(&p->lock);
15410  goto retry;
15411  }
15412  if (DEBUG_ATLEAST(3))
15413  ast_verbose("Softhanging up on %s\n", ast_channel_name(p->owner));
15415  p->restartpending = 1;
15418  }
15419  ast_mutex_unlock(&p->lock);
15420  }
15422 }
15423 
15424 static int dahdi_restart(void)
15425 {
15426 #if defined(HAVE_PRI) || defined(HAVE_SS7)
15427  int i, j;
15428 #endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */
15429  int cancel_code;
15430  struct dahdi_pvt *p;
15431 
15433  ast_verb(1, "Destroying channels and reloading DAHDI configuration.\n");
15435  ast_verb(4, "Initial softhangup of all DAHDI channels complete.\n");
15436 #ifdef HAVE_OPENR2
15437  dahdi_r2_destroy_links();
15438 #endif
15439 
15440 #if defined(HAVE_PRI)
15441  for (i = 0; i < NUM_SPANS; i++) {
15442  if (pris[i].pri.master && (pris[i].pri.master != AST_PTHREADT_NULL)) {
15443  cancel_code = pthread_cancel(pris[i].pri.master);
15444  pthread_kill(pris[i].pri.master, SIGURG);
15445  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);
15446  pthread_join(pris[i].pri.master, NULL);
15447  ast_debug(4, "Joined thread of span %d\n", i);
15448  }
15449  }
15450 #endif
15451 
15452 #if defined(HAVE_SS7)
15453  for (i = 0; i < NUM_SPANS; i++) {
15454  if (linksets[i].ss7.master && (linksets[i].ss7.master != AST_PTHREADT_NULL)) {
15455  cancel_code = pthread_cancel(linksets[i].ss7.master);
15456  pthread_kill(linksets[i].ss7.master, SIGURG);
15457  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);
15458  pthread_join(linksets[i].ss7.master, NULL);
15459  ast_debug(4, "Joined thread of span %d\n", i);
15460  }
15461  }
15462 #endif /* defined(HAVE_SS7) */
15463 
15466  cancel_code = pthread_cancel(monitor_thread);
15467  pthread_kill(monitor_thread, SIGURG);
15468  ast_debug(4, "Waiting to join monitor thread with pid=%p, cancel_code=%d\n", (void *) monitor_thread, cancel_code);
15469  pthread_join(monitor_thread, NULL);
15470  ast_debug(4, "Joined monitor thread\n");
15471  }
15472  monitor_thread = AST_PTHREADT_NULL; /* prepare to restart thread in setup_dahdi once channels are reconfigured */
15473 
15475  while (ss_thread_count > 0) { /* let ss_threads finish and run dahdi_hangup before dahvi_pvts are destroyed */
15476  int x = DAHDI_FLASH;
15477  ast_debug(3, "Waiting on %d analog_ss_thread(s) to finish\n", ss_thread_count);
15478 
15480  for (p = iflist; p; p = p->next) {
15481  if (p->owner) {
15482  /* important to create an event for dahdi_wait_event to register so that all analog_ss_threads terminate */
15483  ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
15484  }
15485  }
15488  }
15489 
15490  /* ensure any created channels before monitor threads were stopped are hungup */
15492  ast_verb(4, "Final softhangup of all DAHDI channels complete.\n");
15494  memset(round_robin, 0, sizeof(round_robin));
15495  ast_debug(1, "Channels destroyed. Now re-reading config. %d active channels remaining.\n", ast_active_channels());
15496 
15498 
15499 #ifdef HAVE_PRI
15500  for (i = 0; i < NUM_SPANS; i++) {
15501  for (j = 0; j < SIG_PRI_NUM_DCHANS; j++)
15502  dahdi_close_pri_fd(&(pris[i]), j);
15503  }
15504 
15505  memset(pris, 0, sizeof(pris));
15506  for (i = 0; i < NUM_SPANS; i++) {
15507  sig_pri_init_pri(&pris[i].pri);
15508  }
15509  pri_set_error(dahdi_pri_error);
15510  pri_set_message(dahdi_pri_message);
15511 #endif
15512 #if defined(HAVE_SS7)
15513  for (i = 0; i < NUM_SPANS; i++) {
15514  for (j = 0; j < SIG_SS7_NUM_DCHANS; j++)
15515  dahdi_close_ss7_fd(&(linksets[i]), j);
15516  }
15517 
15518  memset(linksets, 0, sizeof(linksets));
15519  for (i = 0; i < NUM_SPANS; i++) {
15520  sig_ss7_init_linkset(&linksets[i].ss7);
15521  }
15522  ss7_set_error(dahdi_ss7_error);
15523  ss7_set_message(dahdi_ss7_message);
15524  ss7_set_hangup(sig_ss7_cb_hangup);
15525  ss7_set_notinservice(sig_ss7_cb_notinservice);
15526  ss7_set_call_null(sig_ss7_cb_call_null);
15527 #endif /* defined(HAVE_SS7) */
15528 
15529  if (setup_dahdi(2) != 0) {
15530  ast_log(LOG_WARNING, "Reload channels from dahdi config failed!\n");
15532  return 1;
15533  }
15536  return 0;
15537 }
15538 
15539 static char *dahdi_restart_cmd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15540 {
15541  switch (cmd) {
15542  case CLI_INIT:
15543  e->command = "dahdi restart";
15544  e->usage =
15545  "Usage: dahdi restart\n"
15546  " Restarts the DAHDI channels: destroys them all and then\n"
15547  " re-reads them from chan_dahdi.conf.\n"
15548  " Note that this will STOP any running CALL on DAHDI channels.\n"
15549  "";
15550  return NULL;
15551  case CLI_GENERATE:
15552  return NULL;
15553  }
15554  if (a->argc != 2)
15555  return CLI_SHOWUSAGE;
15556 
15557  if (dahdi_restart() != 0)
15558  return CLI_FAILURE;
15559  return CLI_SUCCESS;
15560 }
15561 
15562 static int action_dahdirestart(struct mansession *s, const struct message *m)
15563 {
15564  if (dahdi_restart() != 0) {
15565  astman_send_error(s, m, "Failed rereading DAHDI configuration");
15566  return 1;
15567  }
15568  astman_send_ack(s, m, "DAHDIRestart: Success");
15569  return 0;
15570 }
15571 
15572 static char *dahdi_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15573 {
15574 #define FORMAT "%7s %-15.15s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s %-32.32s\n"
15575 #define FORMAT2 "%7s %-15.15s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s %-32.32s\n"
15576  ast_group_t targetnum = 0;
15577  int filtertype = 0;
15578  struct dahdi_pvt *tmp = NULL;
15579  char tmps[20];
15580  char blockstr[20];
15581 
15582  switch (cmd) {
15583  case CLI_INIT:
15584  e->command = "dahdi show channels [group|context]";
15585  e->usage =
15586  "Usage: dahdi show channels [ group <group> | context <context> ]\n"
15587  " Shows a list of available channels with optional filtering\n"
15588  " <group> must be a number between 0 and 63\n";
15589  return NULL;
15590  case CLI_GENERATE:
15591  return NULL;
15592  }
15593 
15594  /* syntax: dahdi show channels [ group <group> | context <context> ] */
15595 
15596  if (!((a->argc == 3) || (a->argc == 5))) {
15597  return CLI_SHOWUSAGE;
15598  }
15599 
15600  if (a->argc == 5) {
15601  if (!strcasecmp(a->argv[3], "group")) {
15602  targetnum = atoi(a->argv[4]);
15603  if (63 < targetnum) {
15604  return CLI_SHOWUSAGE;
15605  }
15606  targetnum = ((ast_group_t) 1) << targetnum;
15607  filtertype = 1;
15608  } else if (!strcasecmp(a->argv[3], "context")) {
15609  filtertype = 2;
15610  }
15611  }
15612 
15613  ast_cli(a->fd, FORMAT2, "Chan", "Extension", "Context", "Language", "MOH Interpret", "Blocked", "In Service", "Description");
15615  for (tmp = iflist; tmp; tmp = tmp->next) {
15616  if (filtertype) {
15617  switch(filtertype) {
15618  case 1: /* dahdi show channels group <group> */
15619  if (!(tmp->group & targetnum)) {
15620  continue;
15621  }
15622  break;
15623  case 2: /* dahdi show channels context <context> */
15624  if (strcasecmp(tmp->context, a->argv[4])) {
15625  continue;
15626  }
15627  break;
15628  default:
15629  break;
15630  }
15631  }
15632  if (tmp->channel > 0) {
15633  snprintf(tmps, sizeof(tmps), "%d", tmp->channel);
15634  } else {
15635  ast_copy_string(tmps, "pseudo", sizeof(tmps));
15636  }
15637 
15638  blockstr[0] = tmp->locallyblocked ? 'L' : ' ';
15639  blockstr[1] = tmp->remotelyblocked ? 'R' : ' ';
15640  blockstr[2] = '\0';
15641 
15642  ast_cli(a->fd, FORMAT, tmps, tmp->exten, tmp->context, tmp->language, tmp->mohinterpret, blockstr, tmp->inservice ? "Yes" : "No", tmp->description);
15643  }
15645  return CLI_SUCCESS;
15646 #undef FORMAT
15647 #undef FORMAT2
15648 }
15649 
15650 static char *dahdi_show_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15651 {
15652  int channel;
15653  struct dahdi_pvt *tmp = NULL;
15654  struct dahdi_confinfo ci;
15655  struct dahdi_params ps;
15656  int x;
15657  char hwrxgain[15];
15658  char hwtxgain[15];
15659 
15660  switch (cmd) {
15661  case CLI_INIT:
15662  e->command = "dahdi show channel";
15663  e->usage =
15664  "Usage: dahdi show channel <chan num>\n"
15665  " Detailed information about a given channel\n";
15666  return NULL;
15667  case CLI_GENERATE:
15668  return NULL;
15669  }
15670 
15671  if (a->argc != 4)
15672  return CLI_SHOWUSAGE;
15673 
15674  channel = atoi(a->argv[3]);
15675 
15677  for (tmp = iflist; tmp; tmp = tmp->next) {
15678  if (tmp->channel == channel) {
15679  ast_cli(a->fd, "Channel: %d\n", tmp->channel);
15680  ast_cli(a->fd, "Description: %s\n", tmp->description);
15681  ast_cli(a->fd, "File Descriptor: %d\n", tmp->subs[SUB_REAL].dfd);
15682  ast_cli(a->fd, "Span: %d\n", tmp->span);
15683  ast_cli(a->fd, "Extension: %s\n", tmp->exten);
15684  ast_cli(a->fd, "Dialing: %s\n", tmp->dialing ? "yes" : "no");
15685  ast_cli(a->fd, "Context: %s\n", tmp->context);
15686  ast_cli(a->fd, "Caller ID: %s\n", tmp->cid_num);
15687  ast_cli(a->fd, "Calling TON: %d\n", tmp->cid_ton);
15688 #if defined(HAVE_PRI)
15689 #if defined(HAVE_PRI_SUBADDR)
15690  ast_cli(a->fd, "Caller ID subaddress: %s\n", tmp->cid_subaddr);
15691 #endif /* defined(HAVE_PRI_SUBADDR) */
15692 #endif /* defined(HAVE_PRI) */
15693  ast_cli(a->fd, "Caller ID name: %s\n", tmp->cid_name);
15694  ast_cli(a->fd, "Mailbox: %s\n", S_OR(tmp->mailbox, "none"));
15695  if (tmp->vars) {
15696  struct ast_variable *v;
15697  ast_cli(a->fd, "Variables:\n");
15698  for (v = tmp->vars ; v ; v = v->next)
15699  ast_cli(a->fd, " %s = %s\n", v->name, v->value);
15700  }
15701  ast_cli(a->fd, "Destroy: %d\n", tmp->destroy);
15702  ast_cli(a->fd, "InAlarm: %d\n", tmp->inalarm);
15703  ast_cli(a->fd, "Signalling Type: %s\n", sig2str(tmp->sig));
15704  ast_cli(a->fd, "Radio: %d\n", tmp->radio);
15705  ast_cli(a->fd, "Owner: %s\n", tmp->owner ? ast_channel_name(tmp->owner) : "<None>");
15706  ast_cli(a->fd, "Real: %s%s%s\n", tmp->subs[SUB_REAL].owner ? ast_channel_name(tmp->subs[SUB_REAL].owner) : "<None>", tmp->subs[SUB_REAL].inthreeway ? " (Confed)" : "", tmp->subs[SUB_REAL].linear ? " (Linear)" : "");
15707  ast_cli(a->fd, "Callwait: %s%s%s\n", tmp->subs[SUB_CALLWAIT].owner ? ast_channel_name(tmp->subs[SUB_CALLWAIT].owner) : "<None>", tmp->subs[SUB_CALLWAIT].inthreeway ? " (Confed)" : "", tmp->subs[SUB_CALLWAIT].linear ? " (Linear)" : "");
15708  ast_cli(a->fd, "Threeway: %s%s%s\n", tmp->subs[SUB_THREEWAY].owner ? ast_channel_name(tmp->subs[SUB_THREEWAY].owner) : "<None>", tmp->subs[SUB_THREEWAY].inthreeway ? " (Confed)" : "", tmp->subs[SUB_THREEWAY].linear ? " (Linear)" : "");
15709  ast_cli(a->fd, "Confno: %d\n", tmp->confno);
15710  ast_cli(a->fd, "Propagated Conference: %d\n", tmp->propconfno);
15711  ast_cli(a->fd, "Real in conference: %d\n", tmp->inconference);
15712  ast_cli(a->fd, "DSP: %s\n", tmp->dsp ? "yes" : "no");
15713  ast_cli(a->fd, "Busy Detection: %s\n", tmp->busydetect ? "yes" : "no");
15714  if (tmp->busydetect) {
15715 #if defined(BUSYDETECT_TONEONLY)
15716  ast_cli(a->fd, " Busy Detector Helper: BUSYDETECT_TONEONLY\n");
15717 #elif defined(BUSYDETECT_COMPARE_TONE_AND_SILENCE)
15718  ast_cli(a->fd, " Busy Detector Helper: BUSYDETECT_COMPARE_TONE_AND_SILENCE\n");
15719 #endif
15720 #ifdef BUSYDETECT_DEBUG
15721  ast_cli(a->fd, " Busy Detector Debug: Enabled\n");
15722 #endif
15723  ast_cli(a->fd, " Busy Count: %d\n", tmp->busycount);
15724  ast_cli(a->fd, " Busy Pattern: %d,%d,%d,%d\n", tmp->busy_cadence.pattern[0], tmp->busy_cadence.pattern[1], (tmp->busy_cadence.length == 4) ? tmp->busy_cadence.pattern[2] : 0, (tmp->busy_cadence.length == 4) ? tmp->busy_cadence.pattern[3] : 0);
15725  }
15726  ast_cli(a->fd, "TDD: %s\n", tmp->tdd ? "yes" : "no");
15727  ast_cli(a->fd, "Relax DTMF: %s\n", tmp->dtmfrelax ? "yes" : "no");
15728  ast_cli(a->fd, "Dialing/CallwaitCAS: %d/%d\n", tmp->dialing, tmp->callwaitcas);
15729  ast_cli(a->fd, "Default law: %s\n", tmp->law_default == DAHDI_LAW_MULAW ? "ulaw" : tmp->law_default == DAHDI_LAW_ALAW ? "alaw" : "unknown");
15730  ast_cli(a->fd, "Fax Handled: %s\n", tmp->faxhandled ? "yes" : "no");
15731  ast_cli(a->fd, "Pulse phone: %s\n", tmp->pulsedial ? "yes" : "no");
15732  if (tmp->hwrxgain_enabled) {
15733  snprintf(hwrxgain, sizeof(hwrxgain), "%.1f", tmp->hwrxgain);
15734  } else {
15735  ast_copy_string(hwrxgain, "Disabled", sizeof(hwrxgain));
15736  }
15737  if (tmp->hwtxgain_enabled) {
15738  snprintf(hwtxgain, sizeof(hwtxgain), "%.1f", tmp->hwtxgain);
15739  } else {
15740  ast_copy_string(hwtxgain, "Disabled", sizeof(hwtxgain));
15741  }
15742  ast_cli(a->fd, "HW Gains (RX/TX): %s/%s\n", hwrxgain, hwtxgain);
15743  ast_cli(a->fd, "SW Gains (RX/TX): %.2f/%.2f\n", tmp->rxgain, tmp->txgain);
15744  ast_cli(a->fd, "Dynamic Range Compression (RX/TX): %.2f/%.2f\n", tmp->rxdrc, tmp->txdrc);
15745  ast_cli(a->fd, "DND: %s\n", dahdi_dnd(tmp, -1) ? "yes" : "no");
15746  ast_cli(a->fd, "Echo Cancellation:\n");
15747 
15748  if (tmp->echocancel.head.tap_length) {
15749  ast_cli(a->fd, "\t%u taps\n", tmp->echocancel.head.tap_length);
15750  for (x = 0; x < tmp->echocancel.head.param_count; x++) {
15751  ast_cli(a->fd, "\t\t%s: %dd\n", tmp->echocancel.params[x].name, tmp->echocancel.params[x].value);
15752  }
15753  ast_cli(a->fd, "\t%scurrently %s\n", tmp->echocanbridged ? "" : "(unless TDM bridged) ", tmp->echocanon ? "ON" : "OFF");
15754  } else {
15755  ast_cli(a->fd, "\tnone\n");
15756  }
15757  ast_cli(a->fd, "Wait for dialtone: %dms\n", tmp->waitfordialtone);
15758  if (tmp->master)
15759  ast_cli(a->fd, "Master Channel: %d\n", tmp->master->channel);
15760  for (x = 0; x < MAX_SLAVES; x++) {
15761  if (tmp->slaves[x])
15762  ast_cli(a->fd, "Slave Channel: %d\n", tmp->slaves[x]->channel);
15763  }
15764 #ifdef HAVE_OPENR2
15765  if (tmp->mfcr2) {
15766  char calldir[OR2_MAX_PATH];
15767  openr2_context_t *r2context = openr2_chan_get_context(tmp->r2chan);
15768  openr2_variant_t r2variant = openr2_context_get_variant(r2context);
15769  ast_cli(a->fd, "MFC/R2 MF State: %s\n", openr2_chan_get_mf_state_string(tmp->r2chan));
15770  ast_cli(a->fd, "MFC/R2 MF Group: %s\n", openr2_chan_get_mf_group_string(tmp->r2chan));
15771  ast_cli(a->fd, "MFC/R2 State: %s\n", openr2_chan_get_r2_state_string(tmp->r2chan));
15772  ast_cli(a->fd, "MFC/R2 Call State: %s\n", openr2_chan_get_call_state_string(tmp->r2chan));
15773  ast_cli(a->fd, "MFC/R2 Call Files Enabled: %s\n", openr2_chan_get_call_files_enabled(tmp->r2chan) ? "Yes" : "No");
15774  ast_cli(a->fd, "MFC/R2 Variant: %s\n", openr2_proto_get_variant_string(r2variant));
15775  ast_cli(a->fd, "MFC/R2 Max ANI: %d\n", openr2_context_get_max_ani(r2context));
15776  ast_cli(a->fd, "MFC/R2 Max DNIS: %d\n", openr2_context_get_max_dnis(r2context));
15777 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2
15778  ast_cli(a->fd, "MFC/R2 DTMF Dialing: %s\n", openr2_context_get_dtmf_dialing(r2context, NULL, NULL) ? "Yes" : "No");
15779  ast_cli(a->fd, "MFC/R2 DTMF Detection: %s\n", openr2_context_get_dtmf_detection(r2context) ? "Yes" : "No");
15780 #endif
15781  ast_cli(a->fd, "MFC/R2 Get ANI First: %s\n", openr2_context_get_ani_first(r2context) ? "Yes" : "No");
15782 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
15783  ast_cli(a->fd, "MFC/R2 Skip Category Request: %s\n", openr2_context_get_skip_category_request(r2context) ? "Yes" : "No");
15784 #endif
15785  ast_cli(a->fd, "MFC/R2 Immediate Accept: %s\n", openr2_context_get_immediate_accept(r2context) ? "Yes" : "No");
15786  ast_cli(a->fd, "MFC/R2 Accept on Offer: %s\n", tmp->mfcr2_accept_on_offer ? "Yes" : "No");
15787  ast_cli(a->fd, "MFC/R2 Charge Calls: %s\n", tmp->mfcr2_charge_calls ? "Yes" : "No");
15788  ast_cli(a->fd, "MFC/R2 Allow Collect Calls: %s\n", tmp->mfcr2_allow_collect_calls ? "Yes" : "No");
15789  ast_cli(a->fd, "MFC/R2 Forced Release: %s\n", tmp->mfcr2_forced_release ? "Yes" : "No");
15790  ast_cli(a->fd, "MFC/R2 MF Back Timeout: %dms\n", openr2_context_get_mf_back_timeout(r2context));
15791  ast_cli(a->fd, "MFC/R2 R2 Metering Pulse Timeout: %dms\n", openr2_context_get_metering_pulse_timeout(r2context));
15792  ast_cli(a->fd, "MFC/R2 Rx CAS: %s\n", openr2_chan_get_rx_cas_string(tmp->r2chan));
15793  ast_cli(a->fd, "MFC/R2 Tx CAS: %s\n", openr2_chan_get_tx_cas_string(tmp->r2chan));
15794  ast_cli(a->fd, "MFC/R2 MF Tx Signal: %d\n", openr2_chan_get_tx_mf_signal(tmp->r2chan));
15795  ast_cli(a->fd, "MFC/R2 MF Rx Signal: %d\n", openr2_chan_get_rx_mf_signal(tmp->r2chan));
15796  ast_cli(a->fd, "MFC/R2 Call Files Directory: %s\n", openr2_context_get_log_directory(r2context, calldir, sizeof(calldir)));
15797  }
15798 #endif
15799 #if defined(HAVE_SS7)
15800  if (tmp->ss7) {
15801  struct sig_ss7_chan *chan = tmp->sig_pvt;
15802 
15803  ast_cli(a->fd, "CIC: %d\n", chan->cic);
15804  }
15805 #endif /* defined(HAVE_SS7) */
15806 #ifdef HAVE_PRI
15807  if (tmp->pri) {
15808  struct sig_pri_chan *chan = tmp->sig_pvt;
15809 
15810  ast_cli(a->fd, "PRI Flags: ");
15811  if (chan->resetting != SIG_PRI_RESET_IDLE) {
15812  ast_cli(a->fd, "Resetting=%u ", chan->resetting);
15813  }
15814  if (chan->call)
15815  ast_cli(a->fd, "Call ");
15816  if (chan->allocated) {
15817  ast_cli(a->fd, "Allocated ");
15818  }
15819  ast_cli(a->fd, "\n");
15820  if (tmp->logicalspan)
15821  ast_cli(a->fd, "PRI Logical Span: %d\n", tmp->logicalspan);
15822  else
15823  ast_cli(a->fd, "PRI Logical Span: Implicit\n");
15824  }
15825 #endif
15826  memset(&ci, 0, sizeof(ci));
15827  ps.channo = tmp->channel;
15828  if (tmp->subs[SUB_REAL].dfd > -1) {
15829  memset(&ci, 0, sizeof(ci));
15830  if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
15831  ast_cli(a->fd, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci.confno, (unsigned)ci.confmode);
15832  }
15833  if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONFMUTE, &x)) {
15834  ast_cli(a->fd, "Actual Confmute: %s\n", x ? "Yes" : "No");
15835  }
15836  memset(&ps, 0, sizeof(ps));
15837  if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
15838  ast_log(LOG_WARNING, "Failed to get parameters on channel %d: %s\n", tmp->channel, strerror(errno));
15839  } else {
15840  ast_cli(a->fd, "Hookstate (FXS only): %s\n", ps.rxisoffhook ? "Offhook" : "Onhook");
15841  }
15842  }
15844  return CLI_SUCCESS;
15845  }
15846  }
15848 
15849  ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15850  return CLI_FAILURE;
15851 }
15852 
15853 static char *handle_dahdi_show_cadences(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15854 {
15855  int i, j;
15856  switch (cmd) {
15857  case CLI_INIT:
15858  e->command = "dahdi show cadences";
15859  e->usage =
15860  "Usage: dahdi show cadences\n"
15861  " Shows all cadences currently defined\n";
15862  return NULL;
15863  case CLI_GENERATE:
15864  return NULL;
15865  }
15866  for (i = 0; i < num_cadence; i++) {
15867  char output[1024];
15868  char tmp[16], tmp2[64];
15869  snprintf(tmp, sizeof(tmp), "r%d: ", i + 1);
15870  term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output));
15871 
15872  for (j = 0; j < 16; j++) {
15873  if (cadences[i].ringcadence[j] == 0)
15874  break;
15875  snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]);
15876  if (cidrings[i] * 2 - 1 == j)
15877  term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1);
15878  else
15879  term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1);
15880  if (j != 0)
15881  strncat(output, ",", sizeof(output) - strlen(output) - 1);
15882  strncat(output, tmp2, sizeof(output) - strlen(output) - 1);
15883  }
15884  ast_cli(a->fd,"%s\n",output);
15885  }
15886  return CLI_SUCCESS;
15887 }
15888 
15889 /* Based on irqmiss.c */
15890 static char *dahdi_show_status(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15891 {
15892  #define FORMAT "%-40.40s %-7.7s %-6d %-6d %-6d %-3.3s %-4.4s %-8.8s %s\n"
15893  #define FORMAT2 "%-40.40s %-7.7s %-6.6s %-6.6s %-6.6s %-3.3s %-4.4s %-8.8s %s\n"
15894  int span;
15895  int res;
15896  char alarmstr[50];
15897 
15898  int ctl;
15899  struct dahdi_spaninfo s;
15900 
15901  switch (cmd) {
15902  case CLI_INIT:
15903  e->command = "dahdi show status";
15904  e->usage =
15905  "Usage: dahdi show status\n"
15906  " Shows a list of DAHDI cards with status\n";
15907  return NULL;
15908  case CLI_GENERATE:
15909  return NULL;
15910  }
15911  ctl = open("/dev/dahdi/ctl", O_RDWR);
15912  if (ctl < 0) {
15913  ast_cli(a->fd, "No DAHDI found. Unable to open /dev/dahdi/ctl: %s\n", strerror(errno));
15914  return CLI_FAILURE;
15915  }
15916  ast_cli(a->fd, FORMAT2, "Description", "Alarms", "IRQ", "bpviol", "CRC", "Framing", "Coding", "Options", "LBO");
15917 
15918  for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
15919  s.spanno = span;
15920  res = ioctl(ctl, DAHDI_SPANSTAT, &s);
15921  if (res) {
15922  continue;
15923  }
15924  alarmstr[0] = '\0';
15925  if (s.alarms > 0) {
15926  if (s.alarms & DAHDI_ALARM_BLUE)
15927  strcat(alarmstr, "BLU/");
15928  if (s.alarms & DAHDI_ALARM_YELLOW)
15929  strcat(alarmstr, "YEL/");
15930  if (s.alarms & DAHDI_ALARM_RED)
15931  strcat(alarmstr, "RED/");
15932  if (s.alarms & DAHDI_ALARM_LOOPBACK)
15933  strcat(alarmstr, "LB/");
15934  if (s.alarms & DAHDI_ALARM_RECOVER)
15935  strcat(alarmstr, "REC/");
15936  if (s.alarms & DAHDI_ALARM_NOTOPEN)
15937  strcat(alarmstr, "NOP/");
15938  if (!strlen(alarmstr))
15939  strcat(alarmstr, "UUU/");
15940  if (strlen(alarmstr)) {
15941  /* Strip trailing / */
15942  alarmstr[strlen(alarmstr) - 1] = '\0';
15943  }
15944  } else {
15945  if (s.numchans)
15946  strcpy(alarmstr, "OK");
15947  else
15948  strcpy(alarmstr, "UNCONFIGURED");
15949  }
15950 
15951  ast_cli(a->fd, FORMAT, s.desc, alarmstr, s.irqmisses, s.bpvcount, s.crc4count,
15952  s.lineconfig & DAHDI_CONFIG_D4 ? "D4" :
15953  s.lineconfig & DAHDI_CONFIG_ESF ? "ESF" :
15954  s.lineconfig & DAHDI_CONFIG_CCS ? "CCS" :
15955  "CAS",
15956  s.lineconfig & DAHDI_CONFIG_B8ZS ? "B8ZS" :
15957  s.lineconfig & DAHDI_CONFIG_HDB3 ? "HDB3" :
15958  s.lineconfig & DAHDI_CONFIG_AMI ? "AMI" :
15959  "Unk",
15960  s.lineconfig & DAHDI_CONFIG_CRC4 ?
15961  s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" :
15962  s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "YEL" : "",
15963  lbostr[s.lbo]
15964  );
15965  }
15966  close(ctl);
15967 
15968  return CLI_SUCCESS;
15969 #undef FORMAT
15970 #undef FORMAT2
15971 }
15972 
15973 static char *dahdi_show_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15974 {
15975  int pseudo_fd = -1;
15976  struct dahdi_versioninfo vi;
15977 
15978  switch (cmd) {
15979  case CLI_INIT:
15980  e->command = "dahdi show version";
15981  e->usage =
15982  "Usage: dahdi show version\n"
15983  " Shows the DAHDI version in use\n";
15984  return NULL;
15985  case CLI_GENERATE:
15986  return NULL;
15987  }
15988  if ((pseudo_fd = open("/dev/dahdi/ctl", O_RDONLY)) < 0) {
15989  ast_cli(a->fd, "Failed to open control file to get version.\n");
15990  return CLI_SUCCESS;
15991  }
15992 
15993  strcpy(vi.version, "Unknown");
15994  strcpy(vi.echo_canceller, "Unknown");
15995 
15996  if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi))
15997  ast_cli(a->fd, "Failed to get DAHDI version: %s\n", strerror(errno));
15998  else
15999  ast_cli(a->fd, "DAHDI Version: %s Echo Canceller: %s\n", vi.version, vi.echo_canceller);
16000 
16001  close(pseudo_fd);
16002 
16003  return CLI_SUCCESS;
16004 }
16005 
16006 static char *dahdi_set_hwgain(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16007 {
16008  int channel;
16009  float gain;
16010  int tx;
16011  struct dahdi_pvt *tmp = NULL;
16012 
16013  switch (cmd) {
16014  case CLI_INIT:
16015  e->command = "dahdi set hwgain {rx|tx}";
16016  e->usage =
16017  "Usage: dahdi set hwgain <rx|tx> <chan#> <gain>\n"
16018  " Sets the hardware gain on a given channel and overrides the\n"
16019  " value provided at module loadtime. Changes take effect\n"
16020  " immediately whether the channel is in use or not.\n"
16021  "\n"
16022  " <rx|tx> which direction do you want to change (relative to our module)\n"
16023  " <chan num> is the channel number relative to the device\n"
16024  " <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n"
16025  "\n"
16026  " Please note:\n"
16027  " * hwgain is only supportable by hardware with analog ports because\n"
16028  " hwgain works on the analog side of an analog-digital conversion.\n";
16029  return NULL;
16030  case CLI_GENERATE:
16031  return NULL;
16032  }
16033 
16034  if (a->argc != 6)
16035  return CLI_SHOWUSAGE;
16036 
16037  if (!strcasecmp("rx", a->argv[3]))
16038  tx = 0; /* rx */
16039  else if (!strcasecmp("tx", a->argv[3]))
16040  tx = 1; /* tx */
16041  else
16042  return CLI_SHOWUSAGE;
16043 
16044  channel = atoi(a->argv[4]);
16045  gain = atof(a->argv[5]);
16046 
16048 
16049  for (tmp = iflist; tmp; tmp = tmp->next) {
16050 
16051  if (tmp->channel != channel)
16052  continue;
16053 
16054  if (tmp->subs[SUB_REAL].dfd == -1)
16055  break;
16056 
16057  if (set_hwgain(tmp->subs[SUB_REAL].dfd, gain, tx)) {
16058  ast_cli(a->fd, "Unable to set the hardware gain for channel %d: %s\n", channel, strerror(errno));
16060  return CLI_FAILURE;
16061  }
16062  ast_cli(a->fd, "Hardware %s gain set to %.1f dB on channel %d.\n",
16063  tx ? "tx" : "rx", gain, channel);
16064 
16065  if (tx) {
16066  tmp->hwtxgain_enabled = 1;
16067  tmp->hwtxgain = gain;
16068  } else {
16069  tmp->hwrxgain_enabled = 1;
16070  tmp->hwrxgain = gain;
16071  }
16072  break;
16073  }
16074 
16076 
16077  if (tmp)
16078  return CLI_SUCCESS;
16079 
16080  ast_cli(a->fd, "Unable to find given channel %d\n", channel);
16081  return CLI_FAILURE;
16082 
16083 }
16084 
16085 static char *dahdi_set_swgain(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16086 {
16087  int channel;
16088  float gain;
16089  int tx;
16090  int res;
16091  struct dahdi_pvt *tmp = NULL;
16092 
16093  switch (cmd) {
16094  case CLI_INIT:
16095  e->command = "dahdi set swgain {rx|tx}";
16096  e->usage =
16097  "Usage: dahdi set swgain <rx|tx> <chan#> <gain>\n"
16098  " Sets the software gain on a given channel and overrides the\n"
16099  " value provided at module loadtime. Changes take effect\n"
16100  " immediately whether the channel is in use or not.\n"
16101  "\n"
16102  " <rx|tx> which direction do you want to change (relative to our module)\n"
16103  " <chan num> is the channel number relative to the device\n"
16104  " <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
16105  return NULL;
16106  case CLI_GENERATE:
16107  return NULL;
16108  }
16109 
16110  if (a->argc != 6)
16111  return CLI_SHOWUSAGE;
16112 
16113  if (!strcasecmp("rx", a->argv[3]))
16114  tx = 0; /* rx */
16115  else if (!strcasecmp("tx", a->argv[3]))
16116  tx = 1; /* tx */
16117  else
16118  return CLI_SHOWUSAGE;
16119 
16120  channel = atoi(a->argv[4]);
16121  gain = atof(a->argv[5]);
16122 
16124  for (tmp = iflist; tmp; tmp = tmp->next) {
16125 
16126  if (tmp->channel != channel)
16127  continue;
16128 
16129  if (tmp->subs[SUB_REAL].dfd == -1)
16130  break;
16131 
16132  if (tx)
16133  res = set_actual_txgain(tmp->subs[SUB_REAL].dfd, gain, tmp->txdrc, tmp->law);
16134  else
16135  res = set_actual_rxgain(tmp->subs[SUB_REAL].dfd, gain, tmp->rxdrc, tmp->law);
16136 
16137  if (res) {
16138  ast_cli(a->fd, "Unable to set the software gain for channel %d\n", channel);
16140  return CLI_FAILURE;
16141  }
16142 
16143  ast_cli(a->fd, "Software %s gain set to %.2f dB on channel %d.\n",
16144  tx ? "tx" : "rx", gain, channel);
16145 
16146  if (tx) {
16147  tmp->txgain = gain;
16148  } else {
16149  tmp->rxgain = gain;
16150  }
16151  break;
16152  }
16154 
16155  if (tmp)
16156  return CLI_SUCCESS;
16157 
16158  ast_cli(a->fd, "Unable to find given channel %d\n", channel);
16159  return CLI_FAILURE;
16160 
16161 }
16162 
16163 static char *dahdi_set_dnd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16164 {
16165  int channel;
16166  int on;
16167  struct dahdi_pvt *dahdi_chan = NULL;
16168 
16169  switch (cmd) {
16170  case CLI_INIT:
16171  e->command = "dahdi set dnd";
16172  e->usage =
16173  "Usage: dahdi set dnd <chan#> <on|off>\n"
16174  " Sets/resets DND (Do Not Disturb) mode on a channel.\n"
16175  " Changes take effect immediately.\n"
16176  " <chan num> is the channel number\n"
16177  " <on|off> Enable or disable DND mode?\n"
16178  ;
16179  return NULL;
16180  case CLI_GENERATE:
16181  return NULL;
16182  }
16183 
16184  if (a->argc != 5)
16185  return CLI_SHOWUSAGE;
16186 
16187  if ((channel = atoi(a->argv[3])) <= 0) {
16188  ast_cli(a->fd, "Expected channel number, got '%s'\n", a->argv[3]);
16189  return CLI_SHOWUSAGE;
16190  }
16191 
16192  if (ast_true(a->argv[4]))
16193  on = 1;
16194  else if (ast_false(a->argv[4]))
16195  on = 0;
16196  else {
16197  ast_cli(a->fd, "Expected 'on' or 'off', got '%s'\n", a->argv[4]);
16198  return CLI_SHOWUSAGE;
16199  }
16200 
16202  for (dahdi_chan = iflist; dahdi_chan; dahdi_chan = dahdi_chan->next) {
16203  if (dahdi_chan->channel != channel)
16204  continue;
16205 
16206  /* Found the channel. Actually set it */
16207  dahdi_dnd(dahdi_chan, on);
16208  break;
16209  }
16211 
16212  if (!dahdi_chan) {
16213  ast_cli(a->fd, "Unable to find given channel %d\n", channel);
16214  return CLI_FAILURE;
16215  }
16216 
16217  return CLI_SUCCESS;
16218 }
16219 
16220 static struct ast_cli_entry dahdi_cli[] = {
16221  AST_CLI_DEFINE(handle_dahdi_show_cadences, "List cadences"),
16222  AST_CLI_DEFINE(dahdi_show_channels, "Show active DAHDI channels"),
16223  AST_CLI_DEFINE(dahdi_show_channel, "Show information on a channel"),
16224  AST_CLI_DEFINE(dahdi_destroy_channels, "Destroy channels"),
16225  AST_CLI_DEFINE(dahdi_create_channels, "Create channels"),
16226  AST_CLI_DEFINE(dahdi_restart_cmd, "Fully restart DAHDI channels"),
16227  AST_CLI_DEFINE(dahdi_show_status, "Show all DAHDI cards status"),
16228  AST_CLI_DEFINE(dahdi_show_version, "Show the DAHDI version in use"),
16229  AST_CLI_DEFINE(dahdi_set_hwgain, "Set hardware gain on a channel"),
16230  AST_CLI_DEFINE(dahdi_set_swgain, "Set software gain on a channel"),
16231  AST_CLI_DEFINE(dahdi_set_dnd, "Sets/resets DND (Do Not Disturb) mode on a channel"),
16232 };
16233 
16234 #define TRANSFER 0
16235 #define HANGUP 1
16236 
16237 static int dahdi_fake_event(struct dahdi_pvt *p, int mode)
16238 {
16239  if (p) {
16240  switch (mode) {
16241  case TRANSFER:
16242  p->fake_event = DAHDI_EVENT_WINKFLASH;
16243  break;
16244  case HANGUP:
16245  p->fake_event = DAHDI_EVENT_ONHOOK;
16246  break;
16247  default:
16248  ast_log(LOG_WARNING, "I don't know how to handle transfer event with this: %d on channel %s\n",mode, ast_channel_name(p->owner));
16249  }
16250  }
16251  return 0;
16252 }
16253 static struct dahdi_pvt *find_channel(int channel)
16254 {
16255  struct dahdi_pvt *p;
16256 
16258  for (p = iflist; p; p = p->next) {
16259  if (p->channel == channel) {
16260  break;
16261  }
16262  }
16264  return p;
16265 }
16266 
16267 /*!
16268  * \internal
16269  * \brief Get private struct using given numeric channel string.
16270  *
16271  * \param channel Numeric channel number string get private struct.
16272  *
16273  * \retval pvt on success.
16274  * \retval NULL on error.
16275  */
16276 static struct dahdi_pvt *find_channel_from_str(const char *channel)
16277 {
16278  int chan_num;
16279 
16280  if (sscanf(channel, "%30d", &chan_num) != 1) {
16281  /* Not numeric string. */
16282  return NULL;
16283  }
16284 
16285  return find_channel(chan_num);
16286 }
16287 
16288 static int action_dahdidndon(struct mansession *s, const struct message *m)
16289 {
16290  struct dahdi_pvt *p;
16291  const char *channel = astman_get_header(m, "DAHDIChannel");
16292 
16293  if (ast_strlen_zero(channel)) {
16294  astman_send_error(s, m, "No channel specified");
16295  return 0;
16296  }
16297  p = find_channel_from_str(channel);
16298  if (!p) {
16299  astman_send_error(s, m, "No such channel");
16300  return 0;
16301  }
16302  dahdi_dnd(p, 1);
16303  astman_send_ack(s, m, "DND Enabled");
16304  return 0;
16305 }
16306 
16307 static int action_dahdidndoff(struct mansession *s, const struct message *m)
16308 {
16309  struct dahdi_pvt *p;
16310  const char *channel = astman_get_header(m, "DAHDIChannel");
16311 
16312  if (ast_strlen_zero(channel)) {
16313  astman_send_error(s, m, "No channel specified");
16314  return 0;
16315  }
16316  p = find_channel_from_str(channel);
16317  if (!p) {
16318  astman_send_error(s, m, "No such channel");
16319  return 0;
16320  }
16321  dahdi_dnd(p, 0);
16322  astman_send_ack(s, m, "DND Disabled");
16323  return 0;
16324 }
16325 
16326 static int action_transfer(struct mansession *s, const struct message *m)
16327 {
16328  struct dahdi_pvt *p;
16329  const char *channel = astman_get_header(m, "DAHDIChannel");
16330 
16331  if (ast_strlen_zero(channel)) {
16332  astman_send_error(s, m, "No channel specified");
16333  return 0;
16334  }
16335  p = find_channel_from_str(channel);
16336  if (!p) {
16337  astman_send_error(s, m, "No such channel");
16338  return 0;
16339  }
16340  if (!dahdi_analog_lib_handles(p->sig, 0, 0)) {
16341  astman_send_error(s, m, "Channel signaling is not analog");
16342  return 0;
16343  }
16345  astman_send_ack(s, m, "DAHDITransfer");
16346  return 0;
16347 }
16348 
16349 static int action_transferhangup(struct mansession *s, const struct message *m)
16350 {
16351  struct dahdi_pvt *p;
16352  const char *channel = astman_get_header(m, "DAHDIChannel");
16353 
16354  if (ast_strlen_zero(channel)) {
16355  astman_send_error(s, m, "No channel specified");
16356  return 0;
16357  }
16358  p = find_channel_from_str(channel);
16359  if (!p) {
16360  astman_send_error(s, m, "No such channel");
16361  return 0;
16362  }
16363  if (!dahdi_analog_lib_handles(p->sig, 0, 0)) {
16364  astman_send_error(s, m, "Channel signaling is not analog");
16365  return 0;
16366  }
16368  astman_send_ack(s, m, "DAHDIHangup");
16369  return 0;
16370 }
16371 
16372 static int action_dahdidialoffhook(struct mansession *s, const struct message *m)
16373 {
16374  struct dahdi_pvt *p;
16375  const char *channel = astman_get_header(m, "DAHDIChannel");
16376  const char *number = astman_get_header(m, "Number");
16377  int i;
16378 
16379  if (ast_strlen_zero(channel)) {
16380  astman_send_error(s, m, "No channel specified");
16381  return 0;
16382  }
16383  if (ast_strlen_zero(number)) {
16384  astman_send_error(s, m, "No number specified");
16385  return 0;
16386  }
16387  p = find_channel_from_str(channel);
16388  if (!p) {
16389  astman_send_error(s, m, "No such channel");
16390  return 0;
16391  }
16392  if (!p->owner) {
16393  astman_send_error(s, m, "Channel does not have it's owner");
16394  return 0;
16395  }
16396  for (i = 0; i < strlen(number); i++) {
16397  struct ast_frame f = { AST_FRAME_DTMF, .subclass.integer = number[i] };
16398  dahdi_queue_frame(p, &f);
16399  }
16400  astman_send_ack(s, m, "DAHDIDialOffhook");
16401  return 0;
16402 }
16403 
16404 static int action_dahdishowchannels(struct mansession *s, const struct message *m)
16405 {
16406  struct dahdi_pvt *tmp = NULL;
16407  const char *id = astman_get_header(m, "ActionID");
16408  const char *dahdichannel = astman_get_header(m, "DAHDIChannel");
16409  char idText[256];
16410  int channels = 0;
16411  int dahdichanquery;
16412 
16413  if (!dahdichannel || sscanf(dahdichannel, "%30d", &dahdichanquery) != 1) {
16414  /* Not numeric string. */
16415  dahdichanquery = -1;
16416  }
16417 
16418  idText[0] = '\0';
16419  if (!ast_strlen_zero(id)) {
16420  snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
16421  }
16422 
16423  astman_send_listack(s, m, "DAHDI channel status will follow", "start");
16424 
16426 
16427  for (tmp = iflist; tmp; tmp = tmp->next) {
16428  if (tmp->channel > 0) {
16429  int alm;
16430 
16431  /* If a specific channel is queried for, only deliver status for that channel */
16432  if (dahdichanquery > 0 && tmp->channel != dahdichanquery)
16433  continue;
16434 
16435  alm = get_alarms(tmp);
16436  channels++;
16437  if (tmp->owner) {
16438  /* Add data if we have a current call */
16439  astman_append(s,
16440  "Event: DAHDIShowChannels\r\n"
16441  "DAHDIChannel: %d\r\n"
16442  "Channel: %s\r\n"
16443  "Uniqueid: %s\r\n"
16444  "AccountCode: %s\r\n"
16445  "Signalling: %s\r\n"
16446  "SignallingCode: %d\r\n"
16447  "Context: %s\r\n"
16448  "DND: %s\r\n"
16449  "Alarm: %s\r\n"
16450  "Description: %s\r\n"
16451  "%s"
16452  "\r\n",
16453  tmp->channel,
16454  ast_channel_name(tmp->owner),
16457  sig2str(tmp->sig),
16458  tmp->sig,
16459  tmp->context,
16460  dahdi_dnd(tmp, -1) ? "Enabled" : "Disabled",
16461  alarm2str(alm),
16462  tmp->description, idText);
16463  } else {
16464  astman_append(s,
16465  "Event: DAHDIShowChannels\r\n"
16466  "DAHDIChannel: %d\r\n"
16467  "Signalling: %s\r\n"
16468  "SignallingCode: %d\r\n"
16469  "Context: %s\r\n"
16470  "DND: %s\r\n"
16471  "Alarm: %s\r\n"
16472  "Description: %s\r\n"
16473  "%s"
16474  "\r\n",
16475  tmp->channel, sig2str(tmp->sig), tmp->sig,
16476  tmp->context,
16477  dahdi_dnd(tmp, -1) ? "Enabled" : "Disabled",
16478  alarm2str(alm),
16479  tmp->description, idText);
16480  }
16481  }
16482  }
16483 
16485 
16486  astman_send_list_complete_start(s, m, "DAHDIShowChannelsComplete", channels);
16487  astman_append(s, "Items: %d\r\n", channels);
16489  return 0;
16490 }
16491 
16492 #if defined(HAVE_PRI)
16493 static int action_prishowspans(struct mansession *s, const struct message *m)
16494 {
16495  int count;
16496  int idx;
16497  int span_query;
16498  struct dahdi_pri *dspan;
16499  const char *id = astman_get_header(m, "ActionID");
16500  const char *span_str = astman_get_header(m, "Span");
16501  char action_id[256];
16502  const char *show_cmd = "PRIShowSpans";
16503 
16504  /* NOTE: Asking for span 0 gets all spans. */
16505  if (!ast_strlen_zero(span_str)) {
16506  span_query = atoi(span_str);
16507  } else {
16508  span_query = 0;
16509  }
16510 
16511  if (!ast_strlen_zero(id)) {
16512  snprintf(action_id, sizeof(action_id), "ActionID: %s\r\n", id);
16513  } else {
16514  action_id[0] = '\0';
16515  }
16516 
16517  astman_send_listack(s, m, "Span status will follow", "start");
16518 
16519  count = 0;
16520  for (idx = 0; idx < ARRAY_LEN(pris); ++idx) {
16521  dspan = &pris[idx];
16522 
16523  /* If a specific span is asked for, only deliver status for that span. */
16524  if (0 < span_query && dspan->pri.span != span_query) {
16525  continue;
16526  }
16527 
16528  if (dspan->pri.pri) {
16529  count += sig_pri_ami_show_spans(s, show_cmd, &dspan->pri, dspan->dchannels,
16530  action_id);
16531  }
16532  }
16533 
16534  astman_send_list_complete_start(s, m, "PRIShowSpansComplete", count);
16535  astman_append(s, "Items: %d\r\n", count);
16537  return 0;
16538 }
16539 #endif /* defined(HAVE_PRI) */
16540 
16541 #if defined(HAVE_SS7)
16542 static int linkset_addsigchan(int sigchan)
16543 {
16544  struct dahdi_ss7 *link;
16545  int res;
16546  int curfd;
16547  struct dahdi_params params;
16548  struct dahdi_bufferinfo bi;
16549  struct dahdi_spaninfo si;
16550 
16551  if (sigchan < 0) {
16552  ast_log(LOG_ERROR, "Invalid sigchan!\n");
16553  return -1;
16554  }
16555  if (cur_ss7type < 0) {
16556  ast_log(LOG_ERROR, "Unspecified or invalid ss7type\n");
16557  return -1;
16558  }
16559  if (cur_pointcode < 0) {
16560  ast_log(LOG_ERROR, "Unspecified pointcode!\n");
16561  return -1;
16562  }
16563  if (cur_adjpointcode < 0) {
16564  ast_log(LOG_ERROR, "Unspecified adjpointcode!\n");
16565  return -1;
16566  }
16567  if (cur_defaultdpc < 0) {
16568  ast_log(LOG_ERROR, "Unspecified defaultdpc!\n");
16569  return -1;
16570  }
16571  if (cur_networkindicator < 0) {
16572  ast_log(LOG_ERROR, "Invalid networkindicator!\n");
16573  return -1;
16574  }
16575  link = ss7_resolve_linkset(cur_linkset);
16576  if (!link) {
16577  ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
16578  return -1;
16579  }
16580  if (link->ss7.numsigchans >= SIG_SS7_NUM_DCHANS) {
16581  ast_log(LOG_ERROR, "Too many sigchans on linkset %d\n", cur_linkset);
16582  return -1;
16583  }
16584 
16585  curfd = link->ss7.numsigchans;
16586 
16587  /* Open signaling channel */
16588  link->ss7.fds[curfd] = open("/dev/dahdi/channel", O_RDWR, 0600);
16589  if (link->ss7.fds[curfd] < 0) {
16590  ast_log(LOG_ERROR, "Unable to open SS7 sigchan %d (%s)\n", sigchan,
16591  strerror(errno));
16592  return -1;
16593  }
16594  if (ioctl(link->ss7.fds[curfd], DAHDI_SPECIFY, &sigchan) == -1) {
16595  dahdi_close_ss7_fd(link, curfd);
16596  ast_log(LOG_ERROR, "Unable to specify SS7 sigchan %d (%s)\n", sigchan,
16597  strerror(errno));
16598  return -1;
16599  }
16600 
16601  /* Get signaling channel parameters */
16602  memset(&params, 0, sizeof(params));
16603  res = ioctl(link->ss7.fds[curfd], DAHDI_GET_PARAMS, &params);
16604  if (res) {
16605  dahdi_close_ss7_fd(link, curfd);
16606  ast_log(LOG_ERROR, "Unable to get parameters for sigchan %d (%s)\n", sigchan,
16607  strerror(errno));
16608  return -1;
16609  }
16610  if (params.sigtype != DAHDI_SIG_HDLCFCS
16611  && params.sigtype != DAHDI_SIG_HARDHDLC
16612  && params.sigtype != DAHDI_SIG_MTP2) {
16613  dahdi_close_ss7_fd(link, curfd);
16614  ast_log(LOG_ERROR, "sigchan %d is not in HDLC/FCS mode.\n", sigchan);
16615  return -1;
16616  }
16617 
16618  /* Set signaling channel buffer policy. */
16619  memset(&bi, 0, sizeof(bi));
16620  bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
16621  bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
16622  bi.numbufs = 32;
16623  bi.bufsize = 512;
16624  if (ioctl(link->ss7.fds[curfd], DAHDI_SET_BUFINFO, &bi)) {
16625  ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n",
16626  sigchan, strerror(errno));
16627  dahdi_close_ss7_fd(link, curfd);
16628  return -1;
16629  }
16630 
16631  /* Get current signaling channel alarm status. */
16632  memset(&si, 0, sizeof(si));
16633  res = ioctl(link->ss7.fds[curfd], DAHDI_SPANSTAT, &si);
16634  if (res) {
16635  dahdi_close_ss7_fd(link, curfd);
16636  ast_log(LOG_ERROR, "Unable to get span state for sigchan %d (%s)\n", sigchan,
16637  strerror(errno));
16638  }
16639 
16640  res = sig_ss7_add_sigchan(&link->ss7, curfd, cur_ss7type,
16641  (params.sigtype == DAHDI_SIG_MTP2)
16642  ? SS7_TRANSPORT_DAHDIMTP2
16643  : SS7_TRANSPORT_DAHDIDCHAN,
16644  si.alarms, cur_networkindicator, cur_pointcode, cur_adjpointcode, cur_slc);
16645  if (res) {
16646  dahdi_close_ss7_fd(link, curfd);
16647  return -1;
16648  }
16649 
16650  ++link->ss7.numsigchans;
16651 
16652  return 0;
16653 }
16654 #endif /* defined(HAVE_SS7) */
16655 
16656 #if defined(HAVE_SS7)
16657 static char *handle_ss7_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16658 {
16659  int span;
16660  switch (cmd) {
16661  case CLI_INIT:
16662  e->command = "ss7 set debug {on|off} linkset";
16663  e->usage =
16664  "Usage: ss7 set debug {on|off} linkset <linkset>\n"
16665  " Enables debugging on a given SS7 linkset\n";
16666  return NULL;
16667  case CLI_GENERATE:
16668  return NULL;
16669  }
16670 
16671  if (a->argc < 6) {
16672  return CLI_SHOWUSAGE;
16673  }
16674 
16675  span = atoi(a->argv[5]);
16676  if ((span < 1) || (span > NUM_SPANS)) {
16677  ast_cli(a->fd, "Invalid linkset %s. Should be a number from %d to %d\n", a->argv[5], 1, NUM_SPANS);
16678  return CLI_SUCCESS;
16679  }
16680  if (!linksets[span-1].ss7.ss7) {
16681  ast_cli(a->fd, "No SS7 running on linkset %d\n", span);
16682  } else {
16683  if (!strcasecmp(a->argv[3], "on")) {
16684  linksets[span - 1].ss7.debug = 1;
16685  ss7_set_debug(linksets[span-1].ss7.ss7, SIG_SS7_DEBUG);
16686  ast_cli(a->fd, "Enabled debugging on linkset %d\n", span);
16687  } else {
16688  linksets[span - 1].ss7.debug = 0;
16689  ss7_set_debug(linksets[span-1].ss7.ss7, 0);
16690  ast_cli(a->fd, "Disabled debugging on linkset %d\n", span);
16691  }
16692  }
16693 
16694  return CLI_SUCCESS;
16695 }
16696 #endif /* defined(HAVE_SS7) */
16697 
16698 #if defined(HAVE_SS7)
16699 static char *handle_ss7_cic_blocking(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16700 {
16701  int linkset, cic;
16702  int blocked, i;
16703  int do_block = 0;
16704  unsigned int dpc;
16705 
16706  switch (cmd) {
16707  case CLI_INIT:
16708  e->command = "ss7 {block|unblock} cic";
16709  e->usage =
16710  "Usage: ss7 {block|unblock} cic <linkset> <dpc> <CIC>\n"
16711  " Sends a remote {blocking|unblocking} request for the given CIC on the specified linkset\n";
16712  return NULL;
16713  case CLI_GENERATE:
16714  return NULL;
16715  }
16716 
16717  if (a->argc == 6) {
16718  linkset = atoi(a->argv[3]);
16719  } else {
16720  return CLI_SHOWUSAGE;
16721  }
16722 
16723  if (!strcasecmp(a->argv[1], "block")) {
16724  do_block = 1;
16725  } else if (strcasecmp(a->argv[1], "unblock")) {
16726  return CLI_SHOWUSAGE;
16727  }
16728 
16729  if ((linkset < 1) || (linkset > NUM_SPANS)) {
16730  ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16731  return CLI_SUCCESS;
16732  }
16733 
16734  if (!linksets[linkset-1].ss7.ss7) {
16735  ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16736  return CLI_SUCCESS;
16737  }
16738 
16739  cic = atoi(a->argv[5]);
16740  if (cic < 1) {
16741  ast_cli(a->fd, "Invalid CIC specified!\n");
16742  return CLI_SUCCESS;
16743  }
16744 
16745  dpc = atoi(a->argv[4]);
16746  if (dpc < 1) {
16747  ast_cli(a->fd, "Invalid DPC specified!\n");
16748  return CLI_SUCCESS;
16749  }
16750 
16751  for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
16752  if (linksets[linkset-1].ss7.pvts[i] && linksets[linkset-1].ss7.pvts[i]->cic == cic && linksets[linkset-1].ss7.pvts[i]->dpc == dpc) {
16753  blocked = linksets[linkset-1].ss7.pvts[i]->locallyblocked;
16754  if (!do_block ^ !(blocked & SS7_BLOCKED_MAINTENANCE)) {
16755  if (sig_ss7_cic_blocking(&linksets[linkset-1].ss7, do_block, i) < 0) {
16756  ast_cli(a->fd, "Unable to allocate new ss7call\n");
16757  } else {
16758  ast_cli(a->fd, "Sent %sblocking request for linkset %d on CIC %d DPC %d\n", (do_block) ? "" : "un", linkset, cic, dpc);
16759  }
16760  } else if (!do_block && blocked) {
16761  ast_cli(a->fd, "CIC %d is hardware locally blocked!\n", cic);
16762  } else {
16763  ast_cli(a->fd, "CIC %d %s locally blocked\n", cic, do_block ? "already" : "is not");
16764  }
16765  return CLI_SUCCESS;
16766  }
16767  }
16768 
16769  ast_cli(a->fd, "Invalid CIC specified!\n");
16770  return CLI_SUCCESS;
16771 }
16772 #endif /* defined(HAVE_SS7) */
16773 
16774 #if defined(HAVE_SS7)
16775 static char *handle_ss7_linkset_mng(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16776 {
16777  int linkset, i;
16778  enum {
16779  DO_BLOCK,
16780  DO_UNBLOCK,
16781  DO_RESET,
16782  } do_what;
16783 
16784  switch (cmd) {
16785  case CLI_INIT:
16786  e->command = "ss7 {reset|block|unblock} linkset";
16787  e->usage =
16788  "Usage: ss7 {reset|block|unblock} linkset <linkset number>\n"
16789  " Sends a remote {reset|blocking|unblocking} request for all CICs on the given linkset\n";
16790  return NULL;
16791  case CLI_GENERATE:
16792  return NULL;
16793  }
16794 
16795  if (a->argc == 4) {
16796  linkset = atoi(a->argv[3]);
16797  } else {
16798  return CLI_SHOWUSAGE;
16799  }
16800 
16801  if (!strcasecmp(a->argv[1], "block")) {
16802  do_what = DO_BLOCK;
16803  } else if (!strcasecmp(a->argv[1], "unblock")) {
16804  do_what = DO_UNBLOCK;
16805  } else if (!strcasecmp(a->argv[1], "reset")) {
16806  do_what = DO_RESET;
16807  } else {
16808  return CLI_SHOWUSAGE;
16809  }
16810 
16811  if ((linkset < 1) || (linkset > NUM_SPANS)) {
16812  ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16813  return CLI_SUCCESS;
16814  }
16815 
16816  if (!linksets[linkset - 1].ss7.ss7) {
16817  ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16818  return CLI_SUCCESS;
16819  }
16820 
16821  for (i = 0; i < linksets[linkset - 1].ss7.numchans; i++) {
16822  /* XXX Should be done with GRS/CGB/CGU instead - see ss7_reset_linkset() */
16823  if (linksets[linkset - 1].ss7.pvts[i]) {
16824  switch (do_what) {
16825  case DO_BLOCK:
16826  case DO_UNBLOCK:
16827  if (sig_ss7_cic_blocking(&linksets[linkset - 1].ss7, do_what == DO_BLOCK, i)) {
16828  ast_cli(a->fd, "Sent remote %s request on CIC %d\n",
16829  (do_what == DO_BLOCK) ? "blocking" : "unblocking",
16830  linksets[linkset - 1].ss7.pvts[i]->cic);
16831  }
16832  break;
16833  case DO_RESET:
16834  if (sig_ss7_reset_cic(&linksets[linkset - 1].ss7,
16835  linksets[linkset - 1].ss7.pvts[i]->cic,
16836  linksets[linkset - 1].ss7.pvts[i]->dpc)) {
16837  ast_cli(a->fd, "Sent reset request on CIC %d\n",
16838  linksets[linkset - 1].ss7.pvts[i]->cic);
16839  }
16840  break;
16841  }
16842  }
16843  }
16844 
16845  return CLI_SUCCESS;
16846 }
16847 #endif /* defined(HAVE_SS7) */
16848 
16849 #if defined(HAVE_SS7)
16850 static char *handle_ss7_group_blocking(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16851 {
16852  int linkset, cic, range, chanpos;
16853  int i, dpc, orient = 0;
16854  int do_block = 0;
16855  unsigned char state[255];
16856 
16857  switch (cmd) {
16858  case CLI_INIT:
16859  e->command = "ss7 {block|unblock} group";
16860  e->usage =
16861  "Usage: ss7 {block|unblock} group <linkset> <dpc> <1st. CIC> <range> [H]\n"
16862  " Sends a remote {blocking|unblocking} request for CIC range on the specified linkset\n";
16863  return NULL;
16864  case CLI_GENERATE:
16865  return NULL;
16866  }
16867 
16868  if (a->argc == 7 || a->argc == 8) {
16869  linkset = atoi(a->argv[3]);
16870  } else {
16871  return CLI_SHOWUSAGE;
16872  }
16873 
16874  if (!strcasecmp(a->argv[1], "block")) {
16875  do_block = 1;
16876  } else if (strcasecmp(a->argv[1], "unblock")) {
16877  return CLI_SHOWUSAGE;
16878  }
16879 
16880  if (a->argc == 8) {
16881  if (!strcasecmp(a->argv[7], "H")) {
16882  orient = 1;
16883  } else {
16884  return CLI_SHOWUSAGE;
16885  }
16886  }
16887 
16888  if ((linkset < 1) || (linkset > NUM_SPANS)) {
16889  ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[4], 1, NUM_SPANS);
16890  return CLI_SUCCESS;
16891  }
16892 
16893  if (!linksets[linkset-1].ss7.ss7) {
16894  ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16895  return CLI_SUCCESS;
16896  }
16897 
16898  cic = atoi(a->argv[5]);
16899  if (cic < 1) {
16900  ast_cli(a->fd, "Invalid CIC specified!\n");
16901  return CLI_SUCCESS;
16902  }
16903 
16904  range = atoi(a->argv[6]);
16905  /* ITU-T Q.763 3.43 - range 0 is reserved, which makes a range of 2 CICs a minimum group */
16906  if (range < 1 || range > (linksets[linkset - 1].ss7.type == SS7_ANSI ? 24 : 31)) {
16907  ast_cli(a->fd, "Invalid range specified!\n");
16908  return CLI_SUCCESS;
16909  }
16910 
16911  dpc = atoi(a->argv[4]);
16912  if (dpc < 1) {
16913  ast_cli(a->fd, "Invalid DPC specified!\n");
16914  return CLI_SUCCESS;
16915  }
16916 
16917  ast_mutex_lock(&linksets[linkset-1].ss7.lock);
16918  if (!sig_ss7_find_cic_range(&linksets[linkset-1].ss7, cic, cic + range, dpc)) {
16919  ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
16920  ast_cli(a->fd, "Invalid CIC/RANGE\n");
16921  return CLI_SHOWUSAGE;
16922  }
16923 
16924  memset(state, 0, sizeof(state));
16925  for (i = 0; i <= range; ++i) {
16926  state[i] = 1;
16927  }
16928 
16929  /* We are guaranteed to find chanpos because of sig_ss7_find_cic_range() includes it. */
16930  chanpos = sig_ss7_find_cic(&linksets[linkset-1].ss7, cic, dpc);
16931  if (sig_ss7_group_blocking(&linksets[linkset-1].ss7, do_block, chanpos, cic + range, state, orient)) {
16932  ast_cli(a->fd, "Unable allocate new ss7call\n");
16933  } else {
16934  ast_cli(a->fd, "Sending remote%s %sblocking request linkset %d on CIC %d range %d\n",
16935  orient ? " hardware" : "", do_block ? "" : "un", linkset, cic, range);
16936  }
16937 
16938  ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
16939 
16940  /* Break poll on the linkset so it sends our messages */
16941  if (linksets[linkset-1].ss7.master != AST_PTHREADT_NULL) {
16942  pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
16943  }
16944  return CLI_SUCCESS;
16945 }
16946 #endif /* defined(HAVE_SS7) */
16947 
16948 #if defined(HAVE_SS7)
16949 static char *handle_ss7_group_reset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16950 {
16951  int linkset, cic, range;
16952  unsigned int dpc;
16953 
16954  switch (cmd) {
16955  case CLI_INIT:
16956  e->command = "ss7 reset group";
16957  e->usage =
16958  "Usage: ss7 reset group <linkset> <dpc> <1st CIC> <range>\n"
16959  " Send a GRS for the given CIC range on the specified linkset\n";
16960  return NULL;
16961  case CLI_GENERATE:
16962  return NULL;
16963  }
16964 
16965  if (a->argc == 7) {
16966  linkset = atoi(a->argv[3]);
16967  } else {
16968  return CLI_SHOWUSAGE;
16969  }
16970 
16971  if ((linkset < 1) || (linkset > NUM_SPANS)) {
16972  ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[4], 1, NUM_SPANS);
16973  return CLI_SUCCESS;
16974  }
16975 
16976  if (!linksets[linkset-1].ss7.ss7) {
16977  ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16978  return CLI_SUCCESS;
16979  }
16980 
16981  cic = atoi(a->argv[5]);
16982 
16983  if (cic < 1) {
16984  ast_cli(a->fd, "Invalid CIC specified!\n");
16985  return CLI_SUCCESS;
16986  }
16987 
16988  range = atoi(a->argv[6]);
16989  if (range < 1 || range > (linksets[linkset - 1].ss7.type == SS7_ANSI ? 24 : 31)) {
16990  ast_cli(a->fd, "Invalid range specified!\n");
16991  return CLI_SUCCESS;
16992  }
16993 
16994  dpc = atoi(a->argv[4]);
16995  if (dpc < 1) {
16996  ast_cli(a->fd, "Invalid DPC specified!\n");
16997  return CLI_SUCCESS;
16998  }
16999 
17000  ast_mutex_lock(&linksets[linkset-1].ss7.lock);
17001  if (!sig_ss7_find_cic_range(&linksets[linkset-1].ss7, cic, cic + range, dpc)) {
17002  ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
17003  ast_cli(a->fd, "Invalid CIC/RANGE\n");
17004  return CLI_SHOWUSAGE;
17005  }
17006 
17007  if (sig_ss7_reset_group(&linksets[linkset-1].ss7, cic, dpc, range)) {
17008  ast_cli(a->fd, "Unable to allocate new ss7call\n");
17009  } else {
17010  ast_cli(a->fd, "GRS sent ... \n");
17011  }
17012 
17013  ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
17014 
17015  /* Break poll on the linkset so it sends our messages */
17016  if (linksets[linkset-1].ss7.master != AST_PTHREADT_NULL) {
17017  pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
17018  }
17019  return CLI_SUCCESS;
17020 }
17021 #endif /* defined(HAVE_SS7) */
17022 
17023 #if defined(HAVE_SS7)
17024 static char *handle_ss7_show_calls(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
17025 {
17026  int linkset;
17027 
17028  switch (cmd) {
17029  case CLI_INIT:
17030  e->command = "ss7 show calls";
17031  e->usage =
17032  "Usage: ss7 show calls <linkset>\n"
17033  " Show SS7 calls on the specified linkset\n";
17034  return NULL;
17035  case CLI_GENERATE:
17036  return NULL;
17037  }
17038 
17039  if (a->argc == 4) {
17040  linkset = atoi(a->argv[3]);
17041  } else {
17042  return CLI_SHOWUSAGE;
17043  }
17044 
17045  if ((linkset < 1) || (linkset > NUM_SPANS)) {
17046  ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
17047  return CLI_SUCCESS;
17048  }
17049 
17050  if (!linksets[linkset-1].ss7.ss7) {
17051  ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
17052  return CLI_SUCCESS;
17053  }
17054 
17055  ast_mutex_lock(&linksets[linkset-1].ss7.lock);
17056  isup_show_calls(linksets[linkset-1].ss7.ss7, &ast_cli, a->fd);
17057  ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
17058 
17059  return CLI_SUCCESS;
17060 }
17061 #endif /* defined(HAVE_SS7) */
17062 
17063 #if defined(HAVE_SS7)
17064 static char *handle_ss7_reset_cic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
17065 {
17066  int linkset, cic, res;
17067  unsigned int dpc;
17068 
17069  switch (cmd) {
17070  case CLI_INIT:
17071  e->command = "ss7 reset cic";
17072  e->usage =
17073  "Usage: ss7 reset cic <linkset> <dpc> <CIC>\n"
17074  " Send a RSC for the given CIC on the specified linkset\n";
17075  return NULL;
17076  case CLI_GENERATE:
17077  return NULL;
17078  }
17079 
17080  if (a->argc == 6) {
17081  linkset = atoi(a->argv[3]);
17082  } else {
17083  return CLI_SHOWUSAGE;
17084  }
17085 
17086  if ((linkset < 1) || (linkset > NUM_SPANS)) {
17087  ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
17088  return CLI_SUCCESS;
17089  }
17090 
17091  if (!linksets[linkset-1].ss7.ss7) {
17092  ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
17093  return CLI_SUCCESS;
17094  }
17095 
17096  cic = atoi(a->argv[5]);
17097 
17098  if (cic < 1) {
17099  ast_cli(a->fd, "Invalid CIC specified!\n");
17100  return CLI_SUCCESS;
17101  }
17102 
17103  dpc = atoi(a->argv[4]);
17104  if (dpc < 1) {
17105  ast_cli(a->fd, "Invalid DPC specified!\n");
17106  return CLI_SUCCESS;
17107  }
17108 
17109  res = sig_ss7_reset_cic(&linksets[linkset-1].ss7, cic, dpc);
17110 
17111  ast_cli(a->fd, "%s RSC for linkset %d on CIC %d DPC %d\n", res ? "Sent" : "Failed", linkset, cic, dpc);
17112 
17113  return CLI_SUCCESS;
17114 }
17115 #endif /* defined(HAVE_SS7) */
17116 
17117 #if defined(HAVE_SS7)
17118 static char *handle_ss7_net_mng(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
17119 {
17120  int linkset;
17121  unsigned int slc;
17122  unsigned int arg = 0;
17123  const char *res;
17124 
17125  switch (cmd) {
17126  case CLI_INIT:
17127  e->command = "ss7 mtp3";
17128  e->usage =
17129  "Usage: ss7 mtp3 <linkset> <slc> coo|coa|cbd|cba|eco|eca|tfp|tfa|lin|lun|lia|lua|lid|lfu <arg>\n"
17130  " Send a NET MNG message\n"
17131  " WARNING!!! WARNING!!! We are not a STP, just for testing/development purposes\n";
17132  return NULL;
17133  case CLI_GENERATE:
17134  return NULL;
17135  }
17136 
17137  if (a->argc < 5) {
17138  return CLI_SHOWUSAGE;
17139  }
17140 
17141  linkset = atoi(a->argv[2]);
17142  if ((linkset < 1) || (linkset > NUM_SPANS)) {
17143  ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[2], 1, NUM_SPANS);
17144  return CLI_SUCCESS;
17145  }
17146  if (!linksets[linkset-1].ss7.ss7) {
17147  ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
17148  return CLI_SUCCESS;
17149  }
17150 
17151  slc = atoi(a->argv[3]);
17152 
17153  if (a->argc == 6) {
17154  arg = atoi(a->argv[5]);
17155  }
17156 
17157  ast_mutex_lock(&linksets[linkset-1].ss7.lock);
17158  res = mtp3_net_mng(linksets[linkset-1].ss7.ss7, slc, a->argv[4], arg);
17159  ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
17160 
17161  /* Break poll on the linkset so it sends our messages */
17162  if (linksets[linkset-1].ss7.master != AST_PTHREADT_NULL) {
17163  pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
17164  }
17165 
17166  ast_cli(a->fd, "%s", res);
17167 
17168  return CLI_SUCCESS;
17169 }
17170 #endif /* defined(HAVE_SS7) */
17171 
17172 #if defined(HAVE_SS7)
17173 static char *handle_ss7_mtp3_restart(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
17174 {
17175  int linkset;
17176  unsigned int slc = 0;
17177 
17178  switch (cmd) {
17179  case CLI_INIT:
17180  e->command = "ss7 restart mtp3";
17181  e->usage =
17182  "Usage: ss7 restart mtp3 <linkset> <slc>\n"
17183  " Restart link\n";
17184  return NULL;
17185  case CLI_GENERATE:
17186  return NULL;
17187  }
17188 
17189  if (a->argc < 5) {
17190  return CLI_SHOWUSAGE;
17191  }
17192 
17193  linkset = atoi(a->argv[3]);
17194  if ((linkset < 1) || (linkset > NUM_SPANS)) {
17195  ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[2], 1, NUM_SPANS);
17196  return CLI_SUCCESS;
17197  }
17198  if (!linksets[linkset-1].ss7.ss7) {
17199  ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
17200  return CLI_SUCCESS;
17201  }
17202 
17203  slc = atoi(a->argv[4]);
17204 
17205  ast_mutex_lock(&linksets[linkset-1].ss7.lock);
17206  mtp3_init_restart(linksets[linkset-1].ss7.ss7, slc);
17207  ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
17208 
17209  /* Break poll on the linkset so it sends our messages */
17210  if (linksets[linkset-1].ss7.master != AST_PTHREADT_NULL) {
17211  pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
17212  }
17213 
17214  return CLI_SUCCESS;
17215 }
17216 #endif /* defined(HAVE_SS7) */
17217 
17218 #if defined(HAVE_SS7)
17219 static char *handle_ss7_show_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
17220 {
17221  int linkset;
17222  struct sig_ss7_linkset *ss7;
17223  switch (cmd) {
17224  case CLI_INIT:
17225  e->command = "ss7 show linkset";
17226  e->usage =
17227  "Usage: ss7 show linkset <span>\n"
17228  " Shows the status of an SS7 linkset.\n";
17229  return NULL;
17230  case CLI_GENERATE:
17231  return NULL;
17232  }
17233 
17234  if (a->argc < 4) {
17235  return CLI_SHOWUSAGE;
17236  }
17237 
17238  linkset = atoi(a->argv[3]);
17239  if ((linkset < 1) || (linkset > NUM_SPANS)) {
17240  ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
17241  return CLI_SUCCESS;
17242  }
17243  ss7 = &linksets[linkset - 1].ss7;
17244  if (!ss7->ss7) {
17245  ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
17246  return CLI_SUCCESS;
17247  }
17248 
17249  ast_cli(a->fd, "SS7 flags: 0x%x\n", ss7->flags);
17250  ast_cli(a->fd, "SS7 linkset %d status: %s\n", linkset, (ss7->state == LINKSET_STATE_UP) ? "Up" : "Down");
17251  ast_cli(a->fd, "SS7 calling nai: %i\n", ss7->calling_nai);
17252  ast_cli(a->fd, "SS7 called nai: %i\n", ss7->called_nai);
17253  ast_cli(a->fd, "SS7 nationalprefix: %s\n", ss7->nationalprefix);
17254  ast_cli(a->fd, "SS7 internationalprefix: %s\n", ss7->internationalprefix);
17255  ast_cli(a->fd, "SS7 unknownprefix: %s\n", ss7->unknownprefix);
17256  ast_cli(a->fd, "SS7 networkroutedprefix: %s\n", ss7->networkroutedprefix);
17257  ast_cli(a->fd, "SS7 subscriberprefix: %s\n", ss7->subscriberprefix);
17258  ss7_show_linkset(ss7->ss7, &ast_cli, a->fd);
17259 
17260  return CLI_SUCCESS;
17261 }
17262 #endif /* defined(HAVE_SS7) */
17263 
17264 #if defined(HAVE_SS7)
17265 static char *handle_ss7_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
17266 {
17267  int linkset;
17268 
17269  switch (cmd) {
17270  case CLI_INIT:
17271  e->command = "ss7 show channels";
17272  e->usage =
17273  "Usage: ss7 show channels\n"
17274  " Displays SS7 channel information at a glance.\n";
17275  return NULL;
17276  case CLI_GENERATE:
17277  return NULL;
17278  }
17279 
17280  if (a->argc != 3) {
17281  return CLI_SHOWUSAGE;
17282  }
17283 
17285  for (linkset = 0; linkset < NUM_SPANS; ++linkset) {
17286  if (linksets[linkset].ss7.ss7) {
17287  sig_ss7_cli_show_channels(a->fd, &linksets[linkset].ss7);
17288  }
17289  }
17290  return CLI_SUCCESS;
17291 }
17292 #endif /* defined(HAVE_SS7) */
17293 
17294 #if defined(HAVE_SS7)
17295 static char *handle_ss7_show_cics(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
17296 {
17297 #define FORMAT "%5s %5s %6s %12s %-12s\n"
17298 #define FORMAT2 "%5i %5i %6i %12s %-12s\n"
17299  int i, linkset, dpc = 0;
17300  struct sig_ss7_linkset *ss7;
17301  char *state;
17302  char blocking[12];
17303 
17304  switch (cmd) {
17305  case CLI_INIT:
17306  e->command = "ss7 show cics";
17307  e->usage =
17308  "Usage: ss7 show cics <linkset> [dpc]\n"
17309  " Shows the cics of an SS7 linkset.\n";
17310  return NULL;
17311  case CLI_GENERATE:
17312  return NULL;
17313  }
17314 
17315  if (a->argc < 4 || a->argc > 5) {
17316  return CLI_SHOWUSAGE;
17317  }
17318 
17319  linkset = atoi(a->argv[3]);
17320 
17321  if ((linkset < 1) || (linkset > NUM_SPANS)) {
17322  ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
17323  return CLI_SUCCESS;
17324  }
17325 
17326  if (!linksets[linkset-1].ss7.ss7) {
17327  ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
17328  return CLI_SUCCESS;
17329  }
17330  ss7 = &linksets[linkset-1].ss7;
17331 
17332  if (a->argc == 5) {
17333  dpc = atoi(a->argv[4]);
17334  if (dpc < 1) {
17335  ast_cli(a->fd, "Invalid DPC specified!\n");
17336  return CLI_SUCCESS;
17337  }
17338  }
17339 
17340  ast_cli(a->fd, FORMAT, "CIC", "DPC", "DAHDI", "STATE", "BLOCKING");
17341 
17342  for (i = 0; i < ss7->numchans; i++) {
17343  if (!dpc || (ss7->pvts[i] && ss7->pvts[i]->dpc == dpc)) {
17344  struct dahdi_pvt *p = ss7->pvts[i]->chan_pvt;
17345 
17346  if (ss7->pvts[i]->owner) {
17347  state = "Used";
17348  } else if (ss7->pvts[i]->ss7call) {
17349  state = "Pending";
17350  } else if (!p->inservice) {
17351  state = "NotInServ";
17352  } else {
17353  state = "Idle";
17354  }
17355 
17356  if (p->locallyblocked) {
17357  strcpy(blocking, "L:");
17359  strcat(blocking, "M");
17360  } else {
17361  strcat(blocking, " ");
17362  }
17363 
17365  strcat(blocking, "H");
17366  } else {
17367  strcat(blocking, " ");
17368  }
17369  } else {
17370  strcpy(blocking, " ");
17371  }
17372 
17373  if (p->remotelyblocked) {
17374  strcat(blocking, " R:");
17376  strcat(blocking, "M");
17377  } else {
17378  strcat(blocking, " ");
17379  }
17380 
17382  strcat(blocking, "H");
17383  } else {
17384  strcat(blocking, " ");
17385  }
17386  }
17387 
17388  ast_cli(a->fd, FORMAT2, ss7->pvts[i]->cic, ss7->pvts[i]->dpc, ss7->pvts[i]->channel, state, blocking);
17389  }
17390  }
17391 
17392  return CLI_SUCCESS;
17393 #undef FORMAT
17394 #undef FORMAT2
17395 }
17396 #endif /* defined(HAVE_SS7) */
17397 
17398 #if defined(HAVE_SS7)
17399 static char *handle_ss7_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
17400 {
17401  switch (cmd) {
17402  case CLI_INIT:
17403  e->command = "ss7 show version";
17404  e->usage =
17405  "Usage: ss7 show version\n"
17406  " Show the libss7 version\n";
17407  return NULL;
17408  case CLI_GENERATE:
17409  return NULL;
17410  }
17411 
17412  ast_cli(a->fd, "libss7 version: %s\n", ss7_get_version());
17413 
17414  return CLI_SUCCESS;
17415 }
17416 #endif /* defined(HAVE_SS7) */
17417 
17418 #if defined(HAVE_SS7)
17419 static struct ast_cli_entry dahdi_ss7_cli[] = {
17420  AST_CLI_DEFINE(handle_ss7_debug, "Enables SS7 debugging on a linkset"),
17421  AST_CLI_DEFINE(handle_ss7_cic_blocking, "Blocks/Unblocks the given CIC"),
17422  AST_CLI_DEFINE(handle_ss7_linkset_mng, "Resets/Blocks/Unblocks all CICs on a linkset"),
17423  AST_CLI_DEFINE(handle_ss7_group_blocking, "Blocks/Unblocks the given CIC range"),
17424  AST_CLI_DEFINE(handle_ss7_reset_cic, "Resets the given CIC"),
17425  AST_CLI_DEFINE(handle_ss7_group_reset, "Resets the given CIC range"),
17426  AST_CLI_DEFINE(handle_ss7_mtp3_restart, "Restart a link"),
17427  AST_CLI_DEFINE(handle_ss7_net_mng, "Send an NET MNG message"),
17428  AST_CLI_DEFINE(handle_ss7_show_linkset, "Shows the status of a linkset"),
17429  AST_CLI_DEFINE(handle_ss7_show_channels, "Displays SS7 channel information"),
17430  AST_CLI_DEFINE(handle_ss7_show_calls, "Show ss7 calls"),
17431  AST_CLI_DEFINE(handle_ss7_show_cics, "Show cics on a linkset"),
17432  AST_CLI_DEFINE(handle_ss7_version, "Displays libss7 version"),
17433 };
17434 #endif /* defined(HAVE_SS7) */
17435 
17436 #if defined(HAVE_PRI)
17437 #if defined(HAVE_PRI_CCSS)
17438 /*!
17439  * \internal
17440  * \brief CC agent initialization.
17441  * \since 1.8
17442  *
17443  * \param agent CC core agent control.
17444  * \param chan Original channel the agent will attempt to recall.
17445  *
17446  * \details
17447  * This callback is called when the CC core is initialized. Agents should allocate
17448  * any private data necessary for the call and assign it to the private_data
17449  * on the agent. Additionally, if any ast_cc_agent_flags are pertinent to the
17450  * specific agent type, they should be set in this function as well.
17451  *
17452  * \retval 0 on success.
17453  * \retval -1 on error.
17454  */
17455 static int dahdi_pri_cc_agent_init(struct ast_cc_agent *agent, struct ast_channel *chan)
17456 {
17457  struct dahdi_pvt *pvt;
17458  struct sig_pri_chan *pvt_chan;
17459  int res;
17460 
17461  ast_assert(!strcmp(ast_channel_tech(chan)->type, "DAHDI"));
17462 
17463  pvt = ast_channel_tech_pvt(chan);
17464  if (dahdi_sig_pri_lib_handles(pvt->sig)) {
17465  pvt_chan = pvt->sig_pvt;
17466  } else {
17467  pvt_chan = NULL;
17468  }
17469  if (!pvt_chan) {
17470  return -1;
17471  }
17472 
17474 
17475  res = sig_pri_cc_agent_init(agent, pvt_chan);
17476  if (res) {
17478  }
17479  return res;
17480 }
17481 #endif /* defined(HAVE_PRI_CCSS) */
17482 #endif /* defined(HAVE_PRI) */
17483 
17484 #if defined(HAVE_PRI)
17485 #if defined(HAVE_PRI_CCSS)
17486 /*!
17487  * \internal
17488  * \brief Destroy private data on the agent.
17489  * \since 1.8
17490  *
17491  * \param agent CC core agent control.
17492  *
17493  * \details
17494  * The core will call this function upon completion
17495  * or failure of CC.
17496  *
17497  * \return Nothing
17498  */
17499 static void dahdi_pri_cc_agent_destructor(struct ast_cc_agent *agent)
17500 {
17502 
17504 }
17505 #endif /* defined(HAVE_PRI_CCSS) */
17506 #endif /* defined(HAVE_PRI) */
17507 
17508 #if defined(HAVE_PRI)
17509 #if defined(HAVE_PRI_CCSS)
17510 static struct ast_cc_agent_callbacks dahdi_pri_cc_agent_callbacks = {
17511  .type = dahdi_pri_cc_type,
17512  .init = dahdi_pri_cc_agent_init,
17513  .start_offer_timer = sig_pri_cc_agent_start_offer_timer,
17514  .stop_offer_timer = sig_pri_cc_agent_stop_offer_timer,
17515  .respond = sig_pri_cc_agent_req_rsp,
17516  .status_request = sig_pri_cc_agent_status_req,
17517  .stop_ringing = sig_pri_cc_agent_stop_ringing,
17518  .party_b_free = sig_pri_cc_agent_party_b_free,
17519  .start_monitoring = sig_pri_cc_agent_start_monitoring,
17520  .callee_available = sig_pri_cc_agent_callee_available,
17521  .destructor = dahdi_pri_cc_agent_destructor,
17522 };
17523 #endif /* defined(HAVE_PRI_CCSS) */
17524 #endif /* defined(HAVE_PRI) */
17525 
17526 #if defined(HAVE_PRI)
17527 #if defined(HAVE_PRI_CCSS)
17528 static struct ast_cc_monitor_callbacks dahdi_pri_cc_monitor_callbacks = {
17529  .type = dahdi_pri_cc_type,
17530  .request_cc = sig_pri_cc_monitor_req_cc,
17531  .suspend = sig_pri_cc_monitor_suspend,
17532  .unsuspend = sig_pri_cc_monitor_unsuspend,
17533  .status_response = sig_pri_cc_monitor_status_rsp,
17534  .cancel_available_timer = sig_pri_cc_monitor_cancel_available_timer,
17535  .destructor = sig_pri_cc_monitor_destructor,
17536 };
17537 #endif /* defined(HAVE_PRI_CCSS) */
17538 #endif /* defined(HAVE_PRI) */
17539 
17540 static int __unload_module(void)
17541 {
17542  struct dahdi_pvt *p;
17543 #if defined(HAVE_PRI) || defined(HAVE_SS7)
17544  int i, j;
17545 #endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */
17546 
17547 #ifdef HAVE_PRI
17548  for (i = 0; i < NUM_SPANS; i++) {
17549  if (pris[i].pri.master != AST_PTHREADT_NULL) {
17550  pthread_cancel(pris[i].pri.master);
17551  pthread_kill(pris[i].pri.master, SIGURG);
17552  }
17553  }
17554  ast_cli_unregister_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
17555  ast_unregister_application(dahdi_send_keypad_facility_app);
17556 #ifdef HAVE_PRI_PROG_W_CAUSE
17557  ast_unregister_application(dahdi_send_callrerouting_facility_app);
17558 #endif
17559 #endif
17560 #if defined(HAVE_SS7)
17561  for (i = 0; i < NUM_SPANS; i++) {
17562  if (linksets[i].ss7.master != AST_PTHREADT_NULL) {
17563  pthread_cancel(linksets[i].ss7.master);
17564  pthread_kill(linksets[i].ss7.master, SIGURG);
17565  }
17566  }
17567  ast_cli_unregister_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
17568 #endif /* defined(HAVE_SS7) */
17569 #if defined(HAVE_OPENR2)
17570  dahdi_r2_destroy_links();
17571  ast_cli_unregister_multiple(dahdi_mfcr2_cli, ARRAY_LEN(dahdi_mfcr2_cli));
17572  ast_unregister_application(dahdi_accept_r2_call_app);
17573 #endif
17574 
17575  ast_cli_unregister_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli));
17576  ast_manager_unregister("DAHDIDialOffhook");
17577  ast_manager_unregister("DAHDIHangup");
17578  ast_manager_unregister("DAHDITransfer");
17579  ast_manager_unregister("DAHDIDNDoff");
17580  ast_manager_unregister("DAHDIDNDon");
17581  ast_manager_unregister("DAHDIShowChannels");
17582  ast_manager_unregister("DAHDIRestart");
17583 #if defined(HAVE_PRI)
17584  ast_manager_unregister("PRIShowSpans");
17585  ast_manager_unregister("PRIDebugSet");
17586  ast_manager_unregister("PRIDebugFileSet");
17587  ast_manager_unregister("PRIDebugFileUnset");
17588 #endif /* defined(HAVE_PRI) */
17589  ast_channel_unregister(&dahdi_tech);
17590 
17591  /* Hangup all interfaces if they have an owner */
17593  for (p = iflist; p; p = p->next) {
17594  if (p->owner)
17596  }
17598 
17601  pthread_cancel(monitor_thread);
17602  pthread_kill(monitor_thread, SIGURG);
17603  pthread_join(monitor_thread, NULL);
17604  }
17607 
17609 
17610 #if defined(HAVE_PRI)
17611  for (i = 0; i < NUM_SPANS; i++) {
17612  if (pris[i].pri.master && (pris[i].pri.master != AST_PTHREADT_NULL)) {
17613  pthread_join(pris[i].pri.master, NULL);
17614  }
17615  for (j = 0; j < SIG_PRI_NUM_DCHANS; j++) {
17616  dahdi_close_pri_fd(&(pris[i]), j);
17617  }
17618  sig_pri_stop_pri(&pris[i].pri);
17619  }
17620 #if defined(HAVE_PRI_CCSS)
17621  ast_cc_agent_unregister(&dahdi_pri_cc_agent_callbacks);
17622  ast_cc_monitor_unregister(&dahdi_pri_cc_monitor_callbacks);
17623 #endif /* defined(HAVE_PRI_CCSS) */
17624  sig_pri_unload();
17625 #endif
17626 
17627 #if defined(HAVE_SS7)
17628  for (i = 0; i < NUM_SPANS; i++) {
17629  if (linksets[i].ss7.master && (linksets[i].ss7.master != AST_PTHREADT_NULL)) {
17630  pthread_join(linksets[i].ss7.master, NULL);
17631  }
17632  for (j = 0; j < SIG_SS7_NUM_DCHANS; j++) {
17633  dahdi_close_ss7_fd(&(linksets[i]), j);
17634  }
17635  if (linksets[i].ss7.ss7) {
17636  ss7_destroy(linksets[i].ss7.ss7);
17637  linksets[i].ss7.ss7 = NULL;
17638  }
17639  }
17640 #endif /* defined(HAVE_SS7) */
17642 
17644 
17645  ao2_cleanup(dahdi_tech.capabilities);
17646  dahdi_tech.capabilities = NULL;
17647  STASIS_MESSAGE_TYPE_CLEANUP(dahdichannel_type);
17648  return 0;
17649 }
17650 
17651 static int unload_module(void)
17652 {
17653 #if defined(HAVE_PRI) || defined(HAVE_SS7)
17654  int y;
17655 #endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */
17656 #ifdef HAVE_PRI
17657  for (y = 0; y < NUM_SPANS; y++)
17658  ast_mutex_destroy(&pris[y].pri.lock);
17659 #endif
17660 #if defined(HAVE_SS7)
17661  for (y = 0; y < NUM_SPANS; y++)
17662  ast_mutex_destroy(&linksets[y].ss7.lock);
17663 #endif /* defined(HAVE_SS7) */
17664  return __unload_module();
17665 }
17666 
17667 static int build_channels(struct dahdi_chan_conf *conf, const char *value, int reload, int lineno)
17668 {
17669  char *c, *chan;
17670  int x, start, finish;
17671  struct dahdi_pvt *tmp;
17672 
17673  if ((reload == 0) && (conf->chan.sig < 0) && !conf->is_sig_auto) {
17674  ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n");
17675  return -1;
17676  }
17677 
17678  c = ast_strdupa(value);
17679 
17680  while ((chan = strsep(&c, ","))) {
17681  if (sscanf(chan, "%30d-%30d", &start, &finish) == 2) {
17682  /* Range */
17683  } else if (sscanf(chan, "%30d", &start)) {
17684  /* Just one */
17685  finish = start;
17686  } else if (!strcasecmp(chan, "pseudo")) {
17687  finish = start = CHAN_PSEUDO;
17688  } else {
17689  ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan);
17690  return -1;
17691  }
17692  if (finish < start) {
17693  ast_log(LOG_WARNING, "Sillyness: %d < %d\n", start, finish);
17694  x = finish;
17695  finish = start;
17696  start = x;
17697  }
17698 
17699  for (x = start; x <= finish; x++) {
17700  if (conf->wanted_channels_start &&
17701  (x < conf->wanted_channels_start ||
17702  x > conf->wanted_channels_end)
17703  ) {
17704  continue;
17705  }
17706  tmp = mkintf(x, conf, reload);
17707 
17708  if (tmp) {
17709  ast_verb(3, "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", x, sig2str(tmp->sig));
17710  } else {
17711  ast_log(LOG_ERROR, "Unable to %s channel '%s'\n",
17712  (reload == 1) ? "reconfigure" : "register", value);
17713  return -1;
17714  }
17715  if (x == CHAN_PSEUDO) {
17716  has_pseudo = 1;
17717  }
17718  }
17719  }
17720 
17721  return 0;
17722 }
17723 
17724 /** The length of the parameters list of 'dahdichan'.
17725  * \todo Move definition of MAX_CHANLIST_LEN to a proper place. */
17726 #define MAX_CHANLIST_LEN 80
17727 
17728 static void process_echocancel(struct dahdi_chan_conf *confp, const char *data, unsigned int line)
17729 {
17730  char *parse = ast_strdupa(data);
17731  char *params[DAHDI_MAX_ECHOCANPARAMS + 1];
17732  unsigned int param_count;
17733  unsigned int x;
17734 
17735  if (!(param_count = ast_app_separate_args(parse, ',', params, ARRAY_LEN(params))))
17736  return;
17737 
17738  memset(&confp->chan.echocancel, 0, sizeof(confp->chan.echocancel));
17739 
17740  /* first parameter is tap length, process it here */
17741 
17742  x = ast_strlen_zero(params[0]) ? 0 : atoi(params[0]);
17743 
17744  if ((x == 32) || (x == 64) || (x == 128) || (x == 256) || (x == 512) || (x == 1024))
17745  confp->chan.echocancel.head.tap_length = x;
17746  else if ((confp->chan.echocancel.head.tap_length = ast_true(params[0])))
17747  confp->chan.echocancel.head.tap_length = 128;
17748 
17749  /* now process any remaining parameters */
17750 
17751  for (x = 1; x < param_count; x++) {
17752  struct {
17753  char *name;
17754  char *value;
17755  } param;
17756 
17757  if (ast_app_separate_args(params[x], '=', (char **) &param, 2) < 1) {
17758  ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %u: '%s'\n", line, params[x]);
17759  continue;
17760  }
17761 
17762  if (ast_strlen_zero(param.name) || (strlen(param.name) > sizeof(confp->chan.echocancel.params[0].name)-1)) {
17763  ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %u: '%s'\n", line, param.name);
17764  continue;
17765  }
17766 
17767  strcpy(confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].name, param.name);
17768 
17769  if (param.value) {
17770  if (sscanf(param.value, "%30d", &confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].value) != 1) {
17771  ast_log(LOG_WARNING, "Invalid echocancel parameter value supplied at line %u: '%s'\n", line, param.value);
17772  continue;
17773  }
17774  }
17775  confp->chan.echocancel.head.param_count++;
17776  }
17777 }
17778 
17779 #if defined(HAVE_PRI)
17780 #if defined(HAVE_PRI_DISPLAY_TEXT)
17781 /*!
17782  * \internal
17783  * \brief Determine the configured display text options.
17784  * \since 10.0
17785  *
17786  * \param value Configuration value string.
17787  *
17788  * \return Configured display text option flags.
17789  */
17790 static unsigned long dahdi_display_text_option(const char *value)
17791 {
17792  char *val_str;
17793  char *opt_str;
17794  unsigned long options;
17795 
17796  options = 0;
17797  val_str = ast_strdupa(value);
17798 
17799  for (;;) {
17800  opt_str = strsep(&val_str, ",");
17801  if (!opt_str) {
17802  break;
17803  }
17804  opt_str = ast_strip(opt_str);
17805  if (!*opt_str) {
17806  continue;
17807  }
17808 
17809  if (!strcasecmp(opt_str, "block")) {
17810  options |= PRI_DISPLAY_OPTION_BLOCK;
17811  } else if (!strcasecmp(opt_str, "name_initial")) {
17812  options |= PRI_DISPLAY_OPTION_NAME_INITIAL;
17813  } else if (!strcasecmp(opt_str, "name_update")) {
17814  options |= PRI_DISPLAY_OPTION_NAME_UPDATE;
17815  } else if (!strcasecmp(opt_str, "name")) {
17816  options |= (PRI_DISPLAY_OPTION_NAME_INITIAL | PRI_DISPLAY_OPTION_NAME_UPDATE);
17817  } else if (!strcasecmp(opt_str, "text")) {
17818  options |= PRI_DISPLAY_OPTION_TEXT;
17819  }
17820  }
17821  return options;
17822 }
17823 #endif /* defined(HAVE_PRI_DISPLAY_TEXT) */
17824 #endif /* defined(HAVE_PRI) */
17825 
17826 #if defined(HAVE_PRI)
17827 #if defined(HAVE_PRI_DATETIME_SEND)
17828 /*!
17829  * \internal
17830  * \brief Determine the configured date/time send policy option.
17831  * \since 10.0
17832  *
17833  * \param value Configuration value string.
17834  *
17835  * \return Configured date/time send policy option.
17836  */
17837 static int dahdi_datetime_send_option(const char *value)
17838 {
17839  int option;
17840 
17841  option = PRI_DATE_TIME_SEND_DEFAULT;
17842 
17843  if (ast_false(value)) {
17844  option = PRI_DATE_TIME_SEND_NO;
17845  } else if (!strcasecmp(value, "date")) {
17846  option = PRI_DATE_TIME_SEND_DATE;
17847  } else if (!strcasecmp(value, "date_hh")) {
17848  option = PRI_DATE_TIME_SEND_DATE_HH;
17849  } else if (!strcasecmp(value, "date_hhmm")) {
17850  option = PRI_DATE_TIME_SEND_DATE_HHMM;
17851  } else if (!strcasecmp(value, "date_hhmmss")) {
17852  option = PRI_DATE_TIME_SEND_DATE_HHMMSS;
17853  }
17854 
17855  return option;
17856 }
17857 #endif /* defined(HAVE_PRI_DATETIME_SEND) */
17858 #endif /* defined(HAVE_PRI) */
17859 
17860 /*! process_dahdi() - ignore keyword 'channel' and similar */
17861 #define PROC_DAHDI_OPT_NOCHAN (1 << 0)
17862 /*! process_dahdi() - No warnings on non-existing cofiguration keywords */
17863 #define PROC_DAHDI_OPT_NOWARN (1 << 1)
17864 
17865 static void parse_busy_pattern(struct ast_variable *v, struct ast_dsp_busy_pattern *busy_cadence)
17866 {
17867  int count_pattern = 0;
17868  int norval = 0;
17869  char *temp = NULL;
17870 
17871  for (; ;) {
17872  /* Scans the string for the next value in the pattern. If none, it checks to see if any have been entered so far. */
17873  if (!sscanf(v->value, "%30d", &norval) && count_pattern == 0) {
17874  ast_log(LOG_ERROR, "busypattern= expects either busypattern=tonelength,quietlength or busypattern=t1length, q1length, t2length, q2length at line %d.\n", v->lineno);
17875  break;
17876  }
17877 
17878  busy_cadence->pattern[count_pattern] = norval;
17879 
17880  count_pattern++;
17881  if (count_pattern == 4) {
17882  break;
17883  }
17884 
17885  temp = strchr(v->value, ',');
17886  if (temp == NULL) {
17887  break;
17888  }
17889  v->value = temp + 1;
17890  }
17891  busy_cadence->length = count_pattern;
17892 
17893  if (count_pattern % 2 != 0) {
17894  /* The pattern length must be divisible by two */
17895  ast_log(LOG_ERROR, "busypattern= expects either busypattern=tonelength,quietlength or busypattern=t1length, q1length, t2length, q2length at line %d.\n", v->lineno);
17896  }
17897 
17898 }
17899 
17900 static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct ast_variable *v, int reload, int options)
17901 {
17902  struct dahdi_pvt *tmp;
17903  int y;
17904  struct ast_variable *dahdichan = NULL;
17905 
17906  for (; v; v = v->next) {
17907  if (!ast_jb_read_conf(&global_jbconf, v->name, v->value))
17908  continue;
17909 
17910  /* Create the interface list */
17911  if (!strcasecmp(v->name, "channel") || !strcasecmp(v->name, "channels")) {
17912  if (options & PROC_DAHDI_OPT_NOCHAN) {
17913  ast_log(LOG_WARNING, "Channel '%s' ignored.\n", v->value);
17914  continue;
17915  }
17916  if (build_channels(confp, v->value, reload, v->lineno)) {
17917  if (confp->ignore_failed_channels) {
17918  ast_log(LOG_WARNING, "Channel '%s' failure ignored: ignore_failed_channels.\n", v->value);
17919  continue;
17920  } else {
17921  return -1;
17922  }
17923  }
17924  ast_debug(1, "Channel '%s' configured.\n", v->value);
17925  } else if (!strcasecmp(v->name, "ignore_failed_channels")) {
17926  confp->ignore_failed_channels = ast_true(v->value);
17927  } else if (!strcasecmp(v->name, "buffers")) {
17928  if (parse_buffers_policy(v->value, &confp->chan.buf_no, &confp->chan.buf_policy)) {
17929  ast_log(LOG_WARNING, "Using default buffer policy.\n");
17930  confp->chan.buf_no = numbufs;
17931  confp->chan.buf_policy = DAHDI_POLICY_IMMEDIATE;
17932  }
17933  } else if (!strcasecmp(v->name, "faxbuffers")) {
17934  if (!parse_buffers_policy(v->value, &confp->chan.faxbuf_no, &confp->chan.faxbuf_policy)) {
17935  confp->chan.usefaxbuffers = 1;
17936  }
17937  } else if (!strcasecmp(v->name, "dahdichan")) {
17938  /* Only process the last dahdichan value. */
17939  dahdichan = v;
17940  } else if (!strcasecmp(v->name, "usedistinctiveringdetection")) {
17942  } else if (!strcasecmp(v->name, "distinctiveringaftercid")) {
17944  } else if (!strcasecmp(v->name, "dring1context")) {
17946  } else if (!strcasecmp(v->name, "dring2context")) {
17948  } else if (!strcasecmp(v->name, "dring3context")) {
17950  } else if (!strcasecmp(v->name, "dring1range")) {
17951  confp->chan.drings.ringnum[0].range = atoi(v->value);
17952  } else if (!strcasecmp(v->name, "dring2range")) {
17953  confp->chan.drings.ringnum[1].range = atoi(v->value);
17954  } else if (!strcasecmp(v->name, "dring3range")) {
17955  confp->chan.drings.ringnum[2].range = atoi(v->value);
17956  } else if (!strcasecmp(v->name, "dring1")) {
17957  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]);
17958  } else if (!strcasecmp(v->name, "dring2")) {
17959  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]);
17960  } else if (!strcasecmp(v->name, "dring3")) {
17961  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]);
17962  } else if (!strcasecmp(v->name, "usecallerid")) {
17963  confp->chan.use_callerid = ast_true(v->value);
17964  } else if (!strcasecmp(v->name, "cidsignalling")) {
17965  if (!strcasecmp(v->value, "bell"))
17966  confp->chan.cid_signalling = CID_SIG_BELL;
17967  else if (!strcasecmp(v->value, "v23"))
17968  confp->chan.cid_signalling = CID_SIG_V23;
17969  else if (!strcasecmp(v->value, "dtmf"))
17970  confp->chan.cid_signalling = CID_SIG_DTMF;
17971  else if (!strcasecmp(v->value, "smdi"))
17972  confp->chan.cid_signalling = CID_SIG_SMDI;
17973  else if (!strcasecmp(v->value, "v23_jp"))
17975  else if (ast_true(v->value))
17976  confp->chan.cid_signalling = CID_SIG_BELL;
17977  } else if (!strcasecmp(v->name, "cidstart")) {
17978  if (!strcasecmp(v->value, "ring"))
17979  confp->chan.cid_start = CID_START_RING;
17980  else if (!strcasecmp(v->value, "polarity_in"))
17982  else if (!strcasecmp(v->value, "polarity"))
17984  else if (!strcasecmp(v->value, "dtmf"))
17986  else if (ast_true(v->value))
17987  confp->chan.cid_start = CID_START_RING;
17988  } else if (!strcasecmp(v->name, "threewaycalling")) {
17989  confp->chan.threewaycalling = ast_true(v->value);
17990  } else if (!strcasecmp(v->name, "cancallforward")) {
17991  confp->chan.cancallforward = ast_true(v->value);
17992  } else if (!strcasecmp(v->name, "relaxdtmf")) {
17993  if (ast_true(v->value))
17995  else
17996  confp->chan.dtmfrelax = 0;
17997  } else if (!strcasecmp(v->name, "mailbox")) {
17998  ast_copy_string(confp->chan.mailbox, v->value, sizeof(confp->chan.mailbox));
17999  } else if (!strcasecmp(v->name, "description")) {
18000  ast_copy_string(confp->chan.description, v->value, sizeof(confp->chan.description));
18001  } else if (!strcasecmp(v->name, "hasvoicemail")) {
18002  if (ast_true(v->value) && ast_strlen_zero(confp->chan.mailbox)) {
18003  /*
18004  * hasvoicemail is a users.conf legacy voicemail enable method.
18005  * hasvoicemail is only going to work for app_voicemail mailboxes.
18006  */
18007  if (strchr(cat, '@')) {
18008  ast_copy_string(confp->chan.mailbox, cat, sizeof(confp->chan.mailbox));
18009  } else {
18010  snprintf(confp->chan.mailbox, sizeof(confp->chan.mailbox),
18011  "%s@default", cat);
18012  }
18013  }
18014  } else if (!strcasecmp(v->name, "adsi")) {
18015  confp->chan.adsi = ast_true(v->value);
18016  } else if (!strcasecmp(v->name, "usesmdi")) {
18017  confp->chan.use_smdi = ast_true(v->value);
18018  } else if (!strcasecmp(v->name, "smdiport")) {
18019  ast_copy_string(confp->smdi_port, v->value, sizeof(confp->smdi_port));
18020  } else if (!strcasecmp(v->name, "transfer")) {
18021  confp->chan.transfer = ast_true(v->value);
18022  } else if (!strcasecmp(v->name, "canpark")) {
18023  confp->chan.canpark = ast_true(v->value);
18024  } else if (!strcasecmp(v->name, "echocancelwhenbridged")) {
18025  confp->chan.echocanbridged = ast_true(v->value);
18026  } else if (!strcasecmp(v->name, "busydetect")) {
18027  confp->chan.busydetect = ast_true(v->value);
18028  } else if (!strcasecmp(v->name, "busycount")) {
18029  confp->chan.busycount = atoi(v->value);
18030  } else if (!strcasecmp(v->name, "busypattern")) {
18031  parse_busy_pattern(v, &confp->chan.busy_cadence);
18032  } else if (!strcasecmp(v->name, "callprogress")) {
18034  if (ast_true(v->value))
18036  } else if (!strcasecmp(v->name, "waitfordialtone")) {
18037  confp->chan.waitfordialtone = atoi(v->value);
18038  } else if (!strcasecmp(v->name, "dialtone_detect")) {
18039  if (!strcasecmp(v->value, "always")) {
18040  confp->chan.dialtone_detect = -1;
18041  } else if (ast_true(v->value)) {
18043  } else if (ast_false(v->value)) {
18044  confp->chan.dialtone_detect = 0;
18045  } else {
18046  confp->chan.dialtone_detect = ast_strlen_zero(v->value) ? 0 : (8 * atoi(v->value)) / READ_SIZE;
18047  }
18048  } else if (!strcasecmp(v->name, "faxdetect")) {
18049  confp->chan.callprogress &= ~CALLPROGRESS_FAX;
18050  if (!strcasecmp(v->value, "incoming")) {
18052  } else if (!strcasecmp(v->value, "outgoing")) {
18054  } else if (!strcasecmp(v->value, "both") || ast_true(v->value))
18056  } else if (!strcasecmp(v->name, "faxdetect_timeout")) {
18057  if (sscanf(v->value, "%30u", &confp->chan.faxdetect_timeout) != 1) {
18058  confp->chan.faxdetect_timeout = 0;
18059  }
18060  } else if (!strcasecmp(v->name, "firstdigit_timeout")) {
18061  if (sscanf(v->value, "%30d", &confp->chan.firstdigit_timeout) != 1
18062  || confp->chan.firstdigit_timeout <= 0) {
18064  }
18065  } else if (!strcasecmp(v->name, "interdigit_timeout")) {
18066  if (sscanf(v->value, "%30d", &confp->chan.interdigit_timeout) != 1
18067  || confp->chan.interdigit_timeout <= 0) {
18069  }
18070  } else if (!strcasecmp(v->name, "matchdigit_timeout")) {
18071  if (sscanf(v->value, "%30d", &confp->chan.matchdigit_timeout) != 1
18072  || confp->chan.matchdigit_timeout <= 0) {
18074  }
18075  } else if (!strcasecmp(v->name, "echocancel")) {
18076  process_echocancel(confp, v->value, v->lineno);
18077  } else if (!strcasecmp(v->name, "echotraining")) {
18078  if (sscanf(v->value, "%30d", &y) == 1) {
18079  if ((y < 10) || (y > 4000)) {
18080  ast_log(LOG_WARNING, "Echo training time must be within the range of 10 to 4000 ms at line %d.\n", v->lineno);
18081  } else {
18082  confp->chan.echotraining = y;
18083  }
18084  } else if (ast_true(v->value)) {
18085  confp->chan.echotraining = 400;
18086  } else
18087  confp->chan.echotraining = 0;
18088  } else if (!strcasecmp(v->name, "hidecallerid")) {
18089  confp->chan.hidecallerid = ast_true(v->value);
18090  } else if (!strcasecmp(v->name, "hidecalleridname")) {
18091  confp->chan.hidecalleridname = ast_true(v->value);
18092  } else if (!strcasecmp(v->name, "pulsedial")) {
18093  confp->chan.pulse = ast_true(v->value);
18094  } else if (!strcasecmp(v->name, "callreturn")) {
18095  confp->chan.callreturn = ast_true(v->value);
18096  } else if (!strcasecmp(v->name, "callwaiting")) {
18097  confp->chan.callwaiting = ast_true(v->value);
18098  } else if (!strcasecmp(v->name, "callwaitingcallerid")) {
18099  confp->chan.callwaitingcallerid = ast_true(v->value);
18100  } else if (!strcasecmp(v->name, "context")) {
18101  ast_copy_string(confp->chan.context, v->value, sizeof(confp->chan.context));
18102  } else if (!strcasecmp(v->name, "language")) {
18103  ast_copy_string(confp->chan.language, v->value, sizeof(confp->chan.language));
18104  } else if (!strcasecmp(v->name, "progzone")) {
18105  ast_copy_string(progzone, v->value, sizeof(progzone));
18106  } else if (!strcasecmp(v->name, "mohinterpret")
18107  ||!strcasecmp(v->name, "musiconhold") || !strcasecmp(v->name, "musicclass")) {
18108  ast_copy_string(confp->chan.mohinterpret, v->value, sizeof(confp->chan.mohinterpret));
18109  } else if (!strcasecmp(v->name, "mohsuggest")) {
18110  ast_copy_string(confp->chan.mohsuggest, v->value, sizeof(confp->chan.mohsuggest));
18111  } else if (!strcasecmp(v->name, "parkinglot")) {
18112  ast_copy_string(confp->chan.parkinglot, v->value, sizeof(confp->chan.parkinglot));
18113  } else if (!strcasecmp(v->name, "stripmsd")) {
18114  ast_log(LOG_NOTICE, "Configuration option \"%s\" has been deprecated. Please use dialplan instead\n", v->name);
18115  confp->chan.stripmsd = atoi(v->value);
18116  } else if (!strcasecmp(v->name, "jitterbuffers")) {
18117  numbufs = atoi(v->value);
18118  } else if (!strcasecmp(v->name, "group")) {
18119  confp->chan.group = ast_get_group(v->value);
18120  } else if (!strcasecmp(v->name, "callgroup")) {
18121  if (!strcasecmp(v->value, "none"))
18122  confp->chan.callgroup = 0;
18123  else
18124  confp->chan.callgroup = ast_get_group(v->value);
18125  } else if (!strcasecmp(v->name, "pickupgroup")) {
18126  if (!strcasecmp(v->value, "none"))
18127  confp->chan.pickupgroup = 0;
18128  else
18129  confp->chan.pickupgroup = ast_get_group(v->value);
18130  } else if (!strcasecmp(v->name, "namedcallgroup")) {
18132  } else if (!strcasecmp(v->name, "namedpickupgroup")) {
18134  } else if (!strcasecmp(v->name, "setvar")) {
18135  if (v->value) {
18136  char *varval = NULL;
18137  struct ast_variable *tmpvar;
18138  char varname[strlen(v->value) + 1];
18139  strcpy(varname, v->value); /* safe */
18140  if ((varval = strchr(varname, '='))) {
18141  *varval++ = '\0';
18142  if ((tmpvar = ast_variable_new(varname, varval, ""))) {
18143  if (ast_variable_list_replace(&confp->chan.vars, tmpvar)) {
18144  tmpvar->next = confp->chan.vars;
18145  confp->chan.vars = tmpvar;
18146  }
18147  }
18148  }
18149  }
18150  } else if (!strcasecmp(v->name, "immediate")) {
18151  confp->chan.immediate = ast_true(v->value);
18152  } else if (!strcasecmp(v->name, "transfertobusy")) {
18153  confp->chan.transfertobusy = ast_true(v->value);
18154  } else if (!strcasecmp(v->name, "mwimonitor")) {
18155  confp->chan.mwimonitor_neon = 0;
18156  confp->chan.mwimonitor_fsk = 0;
18157  confp->chan.mwimonitor_rpas = 0;
18158  if (strcasestr(v->value, "fsk")) {
18159  confp->chan.mwimonitor_fsk = 1;
18160  }
18161  if (strcasestr(v->value, "rpas")) {
18162  confp->chan.mwimonitor_rpas = 1;
18163  }
18164  if (strcasestr(v->value, "neon")) {
18165  confp->chan.mwimonitor_neon = 1;
18166  }
18167  /* If set to true or yes, assume that simple fsk is desired */
18168  if (ast_true(v->value)) {
18169  confp->chan.mwimonitor_fsk = 1;
18170  }
18171  } else if (!strcasecmp(v->name, "hwrxgain")) {
18172  confp->chan.hwrxgain_enabled = 0;
18173  if (strcasecmp(v->value, "disabled")) {
18174  if (sscanf(v->value, "%30f", &confp->chan.hwrxgain) == 1) {
18175  confp->chan.hwrxgain_enabled = 1;
18176  } else {
18177  ast_log(LOG_WARNING, "Invalid hwrxgain: %s at line %d.\n", v->value, v->lineno);
18178  }
18179  }
18180  } else if (!strcasecmp(v->name, "hwtxgain")) {
18181  confp->chan.hwtxgain_enabled = 0;
18182  if (strcasecmp(v->value, "disabled")) {
18183  if (sscanf(v->value, "%30f", &confp->chan.hwtxgain) == 1) {
18184  confp->chan.hwtxgain_enabled = 1;
18185  } else {
18186  ast_log(LOG_WARNING, "Invalid hwtxgain: %s at line %d.\n", v->value, v->lineno);
18187  }
18188  }
18189  } else if (!strcasecmp(v->name, "cid_rxgain")) {
18190  if (sscanf(v->value, "%30f", &confp->chan.cid_rxgain) != 1) {
18191  ast_log(LOG_WARNING, "Invalid cid_rxgain: %s at line %d.\n", v->value, v->lineno);
18192  }
18193  } else if (!strcasecmp(v->name, "rxgain")) {
18194  if (sscanf(v->value, "%30f", &confp->chan.rxgain) != 1) {
18195  ast_log(LOG_WARNING, "Invalid rxgain: %s at line %d.\n", v->value, v->lineno);
18196  }
18197  } else if (!strcasecmp(v->name, "txgain")) {
18198  if (sscanf(v->value, "%30f", &confp->chan.txgain) != 1) {
18199  ast_log(LOG_WARNING, "Invalid txgain: %s at line %d.\n", v->value, v->lineno);
18200  }
18201  } else if (!strcasecmp(v->name, "txdrc")) {
18202  if (sscanf(v->value, "%f", &confp->chan.txdrc) != 1) {
18203  ast_log(LOG_WARNING, "Invalid txdrc: %s\n", v->value);
18204  }
18205  } else if (!strcasecmp(v->name, "rxdrc")) {
18206  if (sscanf(v->value, "%f", &confp->chan.rxdrc) != 1) {
18207  ast_log(LOG_WARNING, "Invalid rxdrc: %s\n", v->value);
18208  }
18209  } else if (!strcasecmp(v->name, "tonezone")) {
18210  if (sscanf(v->value, "%30d", &confp->chan.tonezone) != 1) {
18211  ast_log(LOG_WARNING, "Invalid tonezone: %s at line %d.\n", v->value, v->lineno);
18212  }
18213  } else if (!strcasecmp(v->name, "callerid")) {
18214  if (!strcasecmp(v->value, "asreceived")) {
18215  confp->chan.cid_num[0] = '\0';
18216  confp->chan.cid_name[0] = '\0';
18217  } else {
18218  ast_callerid_split(v->value, confp->chan.cid_name, sizeof(confp->chan.cid_name), confp->chan.cid_num, sizeof(confp->chan.cid_num));
18219  }
18220  } else if (!strcasecmp(v->name, "fullname")) {
18221  ast_copy_string(confp->chan.cid_name, v->value, sizeof(confp->chan.cid_name));
18222  } else if (!strcasecmp(v->name, "cid_number")) {
18223  ast_copy_string(confp->chan.cid_num, v->value, sizeof(confp->chan.cid_num));
18224  } else if (!strcasecmp(v->name, "cid_tag")) {
18225  ast_copy_string(confp->chan.cid_tag, v->value, sizeof(confp->chan.cid_tag));
18226  } else if (!strcasecmp(v->name, "useincomingcalleridondahditransfer")) {
18227  confp->chan.dahditrcallerid = ast_true(v->value);
18228  } else if (!strcasecmp(v->name, "restrictcid")) {
18229  confp->chan.restrictcid = ast_true(v->value);
18230  } else if (!strcasecmp(v->name, "usecallingpres")) {
18231  confp->chan.use_callingpres = ast_true(v->value);
18232  } else if (!strcasecmp(v->name, "accountcode")) {
18233  ast_copy_string(confp->chan.accountcode, v->value, sizeof(confp->chan.accountcode));
18234  } else if (!strcasecmp(v->name, "amaflags")) {
18236  if (y < 0)
18237  ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d.\n", v->value, v->lineno);
18238  else
18239  confp->chan.amaflags = y;
18240  } else if (!strcasecmp(v->name, "polarityonanswerdelay")) {
18241  confp->chan.polarityonanswerdelay = atoi(v->value);
18242  } else if (!strcasecmp(v->name, "answeronpolarityswitch")) {
18244  } else if (!strcasecmp(v->name, "hanguponpolarityswitch")) {
18246  } else if (!strcasecmp(v->name, "sendcalleridafter")) {
18247  confp->chan.sendcalleridafter = atoi(v->value);
18248  } else if (!strcasecmp(v->name, "mwimonitornotify")) {
18250  } else if (ast_cc_is_config_param(v->name)) {
18251  ast_cc_set_param(confp->chan.cc_params, v->name, v->value);
18252  } else if (!strcasecmp(v->name, "mwisendtype")) {
18253 #ifndef HAVE_DAHDI_LINEREVERSE_VMWI /* backward compatibility for older dahdi VMWI implementation */
18254  if (!strcasecmp(v->value, "rpas")) { /* Ring Pulse Alert Signal */
18255  mwisend_rpas = 1;
18256  } else {
18257  mwisend_rpas = 0;
18258  }
18259 #else
18260  /* Default is fsk, to turn it off you must specify nofsk */
18261  memset(&confp->chan.mwisend_setting, 0, sizeof(confp->chan.mwisend_setting));
18262  if (strcasestr(v->value, "nofsk")) { /* NoFSK */
18263  confp->chan.mwisend_fsk = 0;
18264  } else { /* Default FSK */
18265  confp->chan.mwisend_fsk = 1;
18266  }
18267  if (strcasestr(v->value, "rpas")) { /* Ring Pulse Alert Signal, normally followed by FSK */
18268  confp->chan.mwisend_rpas = 1;
18269  } else {
18270  confp->chan.mwisend_rpas = 0;
18271  }
18272  if (strcasestr(v->value, "lrev")) { /* Line Reversal */
18273  confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_LREV;
18274  }
18275  if (strcasestr(v->value, "hvdc")) { /* HV 90VDC */
18276  confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_HVDC;
18277  }
18278  if ( (strcasestr(v->value, "neon")) || (strcasestr(v->value, "hvac")) ) { /* 90V DC pulses */
18279  confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_HVAC;
18280  }
18281 #endif
18282  } else if (reload != 1) {
18283  if (!strcasecmp(v->name, "signalling") || !strcasecmp(v->name, "signaling")) {
18284  int orig_radio = confp->chan.radio;
18285  int orig_outsigmod = confp->chan.outsigmod;
18286  int orig_auto = confp->is_sig_auto;
18287 
18288  confp->chan.radio = 0;
18289  confp->chan.outsigmod = -1;
18290  confp->is_sig_auto = 0;
18291  if (!strcasecmp(v->value, "em")) {
18292  confp->chan.sig = SIG_EM;
18293  } else if (!strcasecmp(v->value, "em_e1")) {
18294  confp->chan.sig = SIG_EM_E1;
18295  } else if (!strcasecmp(v->value, "em_w")) {
18296  confp->chan.sig = SIG_EMWINK;
18297  } else if (!strcasecmp(v->value, "fxs_ls")) {
18298  confp->chan.sig = SIG_FXSLS;
18299  } else if (!strcasecmp(v->value, "fxs_gs")) {
18300  confp->chan.sig = SIG_FXSGS;
18301  } else if (!strcasecmp(v->value, "fxs_ks")) {
18302  confp->chan.sig = SIG_FXSKS;
18303  } else if (!strcasecmp(v->value, "fxo_ls")) {
18304  confp->chan.sig = SIG_FXOLS;
18305  } else if (!strcasecmp(v->value, "fxo_gs")) {
18306  confp->chan.sig = SIG_FXOGS;
18307  } else if (!strcasecmp(v->value, "fxo_ks")) {
18308  confp->chan.sig = SIG_FXOKS;
18309  } else if (!strcasecmp(v->value, "fxs_rx")) {
18310  confp->chan.sig = SIG_FXSKS;
18311  confp->chan.radio = 1;
18312  } else if (!strcasecmp(v->value, "fxo_rx")) {
18313  confp->chan.sig = SIG_FXOLS;
18314  confp->chan.radio = 1;
18315  } else if (!strcasecmp(v->value, "fxs_tx")) {
18316  confp->chan.sig = SIG_FXSLS;
18317  confp->chan.radio = 1;
18318  } else if (!strcasecmp(v->value, "fxo_tx")) {
18319  confp->chan.sig = SIG_FXOGS;
18320  confp->chan.radio = 1;
18321  } else if (!strcasecmp(v->value, "em_rx")) {
18322  confp->chan.sig = SIG_EM;
18323  confp->chan.radio = 1;
18324  } else if (!strcasecmp(v->value, "em_tx")) {
18325  confp->chan.sig = SIG_EM;
18326  confp->chan.radio = 1;
18327  } else if (!strcasecmp(v->value, "em_rxtx")) {
18328  confp->chan.sig = SIG_EM;
18329  confp->chan.radio = 2;
18330  } else if (!strcasecmp(v->value, "em_txrx")) {
18331  confp->chan.sig = SIG_EM;
18332  confp->chan.radio = 2;
18333  } else if (!strcasecmp(v->value, "sf")) {
18334  confp->chan.sig = SIG_SF;
18335  } else if (!strcasecmp(v->value, "sf_w")) {
18336  confp->chan.sig = SIG_SFWINK;
18337  } else if (!strcasecmp(v->value, "sf_featd")) {
18338  confp->chan.sig = SIG_FEATD;
18339  } else if (!strcasecmp(v->value, "sf_featdmf")) {
18340  confp->chan.sig = SIG_FEATDMF;
18341  } else if (!strcasecmp(v->value, "sf_featb")) {
18342  confp->chan.sig = SIG_SF_FEATB;
18343  } else if (!strcasecmp(v->value, "sf")) {
18344  confp->chan.sig = SIG_SF;
18345  } else if (!strcasecmp(v->value, "sf_rx")) {
18346  confp->chan.sig = SIG_SF;
18347  confp->chan.radio = 1;
18348  } else if (!strcasecmp(v->value, "sf_tx")) {
18349  confp->chan.sig = SIG_SF;
18350  confp->chan.radio = 1;
18351  } else if (!strcasecmp(v->value, "sf_rxtx")) {
18352  confp->chan.sig = SIG_SF;
18353  confp->chan.radio = 2;
18354  } else if (!strcasecmp(v->value, "sf_txrx")) {
18355  confp->chan.sig = SIG_SF;
18356  confp->chan.radio = 2;
18357  } else if (!strcasecmp(v->value, "featd")) {
18358  confp->chan.sig = SIG_FEATD;
18359  } else if (!strcasecmp(v->value, "featdmf")) {
18360  confp->chan.sig = SIG_FEATDMF;
18361  } else if (!strcasecmp(v->value, "featdmf_ta")) {
18362  confp->chan.sig = SIG_FEATDMF_TA;
18363  } else if (!strcasecmp(v->value, "e911")) {
18364  confp->chan.sig = SIG_E911;
18365  } else if (!strcasecmp(v->value, "fgccama")) {
18366  confp->chan.sig = SIG_FGC_CAMA;
18367  } else if (!strcasecmp(v->value, "fgccamamf")) {
18368  confp->chan.sig = SIG_FGC_CAMAMF;
18369  } else if (!strcasecmp(v->value, "featb")) {
18370  confp->chan.sig = SIG_FEATB;
18371 #ifdef HAVE_PRI
18372  } else if (!strcasecmp(v->value, "pri_net")) {
18373  confp->chan.sig = SIG_PRI;
18374  confp->pri.pri.nodetype = PRI_NETWORK;
18375  } else if (!strcasecmp(v->value, "pri_cpe")) {
18376  confp->chan.sig = SIG_PRI;
18377  confp->pri.pri.nodetype = PRI_CPE;
18378  } else if (!strcasecmp(v->value, "bri_cpe")) {
18379  confp->chan.sig = SIG_BRI;
18380  confp->pri.pri.nodetype = PRI_CPE;
18381  } else if (!strcasecmp(v->value, "bri_net")) {
18382  confp->chan.sig = SIG_BRI;
18383  confp->pri.pri.nodetype = PRI_NETWORK;
18384  } else if (!strcasecmp(v->value, "bri_cpe_ptmp")) {
18385  confp->chan.sig = SIG_BRI_PTMP;
18386  confp->pri.pri.nodetype = PRI_CPE;
18387  } else if (!strcasecmp(v->value, "bri_net_ptmp")) {
18388 #if defined(HAVE_PRI_CALL_HOLD)
18389  confp->chan.sig = SIG_BRI_PTMP;
18390  confp->pri.pri.nodetype = PRI_NETWORK;
18391 #else
18392  ast_log(LOG_WARNING, "How cool would it be if someone implemented this mode! For now, sucks for you. (line %d)\n", v->lineno);
18393 #endif /* !defined(HAVE_PRI_CALL_HOLD) */
18394 #endif
18395 #if defined(HAVE_SS7)
18396  } else if (!strcasecmp(v->value, "ss7")) {
18397  confp->chan.sig = SIG_SS7;
18398 #endif /* defined(HAVE_SS7) */
18399 #ifdef HAVE_OPENR2
18400  } else if (!strcasecmp(v->value, "mfcr2")) {
18401  confp->chan.sig = SIG_MFCR2;
18402 #endif
18403  } else if (!strcasecmp(v->value, "auto")) {
18404  confp->is_sig_auto = 1;
18405  } else {
18406  confp->chan.outsigmod = orig_outsigmod;
18407  confp->chan.radio = orig_radio;
18408  confp->is_sig_auto = orig_auto;
18409  ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
18410  }
18411  } else if (!strcasecmp(v->name, "outsignalling") || !strcasecmp(v->name, "outsignaling")) {
18412  if (!strcasecmp(v->value, "em")) {
18413  confp->chan.outsigmod = SIG_EM;
18414  } else if (!strcasecmp(v->value, "em_e1")) {
18415  confp->chan.outsigmod = SIG_EM_E1;
18416  } else if (!strcasecmp(v->value, "em_w")) {
18417  confp->chan.outsigmod = SIG_EMWINK;
18418  } else if (!strcasecmp(v->value, "sf")) {
18419  confp->chan.outsigmod = SIG_SF;
18420  } else if (!strcasecmp(v->value, "sf_w")) {
18421  confp->chan.outsigmod = SIG_SFWINK;
18422  } else if (!strcasecmp(v->value, "sf_featd")) {
18423  confp->chan.outsigmod = SIG_FEATD;
18424  } else if (!strcasecmp(v->value, "sf_featdmf")) {
18425  confp->chan.outsigmod = SIG_FEATDMF;
18426  } else if (!strcasecmp(v->value, "sf_featb")) {
18427  confp->chan.outsigmod = SIG_SF_FEATB;
18428  } else if (!strcasecmp(v->value, "sf")) {
18429  confp->chan.outsigmod = SIG_SF;
18430  } else if (!strcasecmp(v->value, "featd")) {
18431  confp->chan.outsigmod = SIG_FEATD;
18432  } else if (!strcasecmp(v->value, "featdmf")) {
18433  confp->chan.outsigmod = SIG_FEATDMF;
18434  } else if (!strcasecmp(v->value, "featdmf_ta")) {
18435  confp->chan.outsigmod = SIG_FEATDMF_TA;
18436  } else if (!strcasecmp(v->value, "e911")) {
18437  confp->chan.outsigmod = SIG_E911;
18438  } else if (!strcasecmp(v->value, "fgccama")) {
18439  confp->chan.outsigmod = SIG_FGC_CAMA;
18440  } else if (!strcasecmp(v->value, "fgccamamf")) {
18441  confp->chan.outsigmod = SIG_FGC_CAMAMF;
18442  } else if (!strcasecmp(v->value, "featb")) {
18443  confp->chan.outsigmod = SIG_FEATB;
18444  } else {
18445  ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
18446  }
18447 #ifdef HAVE_PRI
18448  } else if (!strcasecmp(v->name, "pridialplan")) {
18449  if (!strcasecmp(v->value, "national")) {
18450  confp->pri.pri.dialplan = PRI_NATIONAL_ISDN + 1;
18451  } else if (!strcasecmp(v->value, "unknown")) {
18452  confp->pri.pri.dialplan = PRI_UNKNOWN + 1;
18453  } else if (!strcasecmp(v->value, "private")) {
18454  confp->pri.pri.dialplan = PRI_PRIVATE + 1;
18455  } else if (!strcasecmp(v->value, "international")) {
18456  confp->pri.pri.dialplan = PRI_INTERNATIONAL_ISDN + 1;
18457  } else if (!strcasecmp(v->value, "local")) {
18458  confp->pri.pri.dialplan = PRI_LOCAL_ISDN + 1;
18459  } else if (!strcasecmp(v->value, "dynamic")) {
18460  confp->pri.pri.dialplan = -1;
18461  } else if (!strcasecmp(v->value, "redundant")) {
18462  confp->pri.pri.dialplan = -2;
18463  } else {
18464  ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno);
18465  }
18466  } else if (!strcasecmp(v->name, "prilocaldialplan")) {
18467  if (!strcasecmp(v->value, "national")) {
18468  confp->pri.pri.localdialplan = PRI_NATIONAL_ISDN + 1;
18469  } else if (!strcasecmp(v->value, "unknown")) {
18470  confp->pri.pri.localdialplan = PRI_UNKNOWN + 1;
18471  } else if (!strcasecmp(v->value, "private")) {
18472  confp->pri.pri.localdialplan = PRI_PRIVATE + 1;
18473  } else if (!strcasecmp(v->value, "international")) {
18474  confp->pri.pri.localdialplan = PRI_INTERNATIONAL_ISDN + 1;
18475  } else if (!strcasecmp(v->value, "local")) {
18476  confp->pri.pri.localdialplan = PRI_LOCAL_ISDN + 1;
18477  } else if (!strcasecmp(v->value, "from_channel")) {
18478  confp->pri.pri.localdialplan = 0;
18479  } else if (!strcasecmp(v->value, "dynamic")) {
18480  confp->pri.pri.localdialplan = -1;
18481  } else if (!strcasecmp(v->value, "redundant")) {
18482  confp->pri.pri.localdialplan = -2;
18483  } else {
18484  ast_log(LOG_WARNING, "Unknown PRI localdialplan '%s' at line %d.\n", v->value, v->lineno);
18485  }
18486  } else if (!strcasecmp(v->name, "pricpndialplan")) {
18487  if (!strcasecmp(v->value, "national")) {
18488  confp->pri.pri.cpndialplan = PRI_NATIONAL_ISDN + 1;
18489  } else if (!strcasecmp(v->value, "unknown")) {
18490  confp->pri.pri.cpndialplan = PRI_UNKNOWN + 1;
18491  } else if (!strcasecmp(v->value, "private")) {
18492  confp->pri.pri.cpndialplan = PRI_PRIVATE + 1;
18493  } else if (!strcasecmp(v->value, "international")) {
18494  confp->pri.pri.cpndialplan = PRI_INTERNATIONAL_ISDN + 1;
18495  } else if (!strcasecmp(v->value, "local")) {
18496  confp->pri.pri.cpndialplan = PRI_LOCAL_ISDN + 1;
18497  } else if (!strcasecmp(v->value, "from_channel")) {
18498  confp->pri.pri.cpndialplan = 0;
18499  } else if (!strcasecmp(v->value, "dynamic")) {
18500  confp->pri.pri.cpndialplan = -1;
18501  } else if (!strcasecmp(v->value, "redundant")) {
18502  confp->pri.pri.cpndialplan = -2;
18503  } else {
18504  ast_log(LOG_WARNING, "Unknown PRI cpndialplan '%s' at line %d.\n", v->value, v->lineno);
18505  }
18506  } else if (!strcasecmp(v->name, "switchtype")) {
18507  if (!strcasecmp(v->value, "national"))
18508  confp->pri.pri.switchtype = PRI_SWITCH_NI2;
18509  else if (!strcasecmp(v->value, "ni1"))
18510  confp->pri.pri.switchtype = PRI_SWITCH_NI1;
18511  else if (!strcasecmp(v->value, "dms100"))
18512  confp->pri.pri.switchtype = PRI_SWITCH_DMS100;
18513  else if (!strcasecmp(v->value, "4ess"))
18514  confp->pri.pri.switchtype = PRI_SWITCH_ATT4ESS;
18515  else if (!strcasecmp(v->value, "5ess"))
18516  confp->pri.pri.switchtype = PRI_SWITCH_LUCENT5E;
18517  else if (!strcasecmp(v->value, "euroisdn"))
18518  confp->pri.pri.switchtype = PRI_SWITCH_EUROISDN_E1;
18519  else if (!strcasecmp(v->value, "qsig"))
18520  confp->pri.pri.switchtype = PRI_SWITCH_QSIG;
18521  else {
18522  ast_log(LOG_ERROR, "Unknown switchtype '%s' at line %d.\n", v->value, v->lineno);
18523  return -1;
18524  }
18525  } else if (!strcasecmp(v->name, "msn")) {
18526  ast_copy_string(confp->pri.pri.msn_list, v->value,
18527  sizeof(confp->pri.pri.msn_list));
18528  } else if (!strcasecmp(v->name, "nsf")) {
18529  if (!strcasecmp(v->value, "sdn"))
18530  confp->pri.pri.nsf = PRI_NSF_SDN;
18531  else if (!strcasecmp(v->value, "megacom"))
18532  confp->pri.pri.nsf = PRI_NSF_MEGACOM;
18533  else if (!strcasecmp(v->value, "tollfreemegacom"))
18534  confp->pri.pri.nsf = PRI_NSF_TOLL_FREE_MEGACOM;
18535  else if (!strcasecmp(v->value, "accunet"))
18536  confp->pri.pri.nsf = PRI_NSF_ACCUNET;
18537  else if (!strcasecmp(v->value, "none"))
18538  confp->pri.pri.nsf = PRI_NSF_NONE;
18539  else {
18540  ast_log(LOG_WARNING, "Unknown network-specific facility '%s' at line %d.\n", v->value, v->lineno);
18541  confp->pri.pri.nsf = PRI_NSF_NONE;
18542  }
18543  } else if (!strcasecmp(v->name, "priindication")) {
18544  if (!strcasecmp(v->value, "outofband"))
18545  confp->chan.priindication_oob = 1;
18546  else if (!strcasecmp(v->value, "inband"))
18547  confp->chan.priindication_oob = 0;
18548  else
18549  ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d.\n",
18550  v->value, v->lineno);
18551  } else if (!strcasecmp(v->name, "priexclusive")) {
18552  confp->chan.priexclusive = ast_true(v->value);
18553  } else if (!strcasecmp(v->name, "internationalprefix")) {
18554  ast_copy_string(confp->pri.pri.internationalprefix, v->value, sizeof(confp->pri.pri.internationalprefix));
18555  } else if (!strcasecmp(v->name, "nationalprefix")) {
18556  ast_copy_string(confp->pri.pri.nationalprefix, v->value, sizeof(confp->pri.pri.nationalprefix));
18557  } else if (!strcasecmp(v->name, "localprefix")) {
18558  ast_copy_string(confp->pri.pri.localprefix, v->value, sizeof(confp->pri.pri.localprefix));
18559  } else if (!strcasecmp(v->name, "privateprefix")) {
18560  ast_copy_string(confp->pri.pri.privateprefix, v->value, sizeof(confp->pri.pri.privateprefix));
18561  } else if (!strcasecmp(v->name, "unknownprefix")) {
18562  ast_copy_string(confp->pri.pri.unknownprefix, v->value, sizeof(confp->pri.pri.unknownprefix));
18563  } else if (!strcasecmp(v->name, "resetinterval")) {
18564  if (!strcasecmp(v->value, "never"))
18565  confp->pri.pri.resetinterval = -1;
18566  else if (atoi(v->value) >= 60)
18567  confp->pri.pri.resetinterval = atoi(v->value);
18568  else
18569  ast_log(LOG_WARNING, "'%s' is not a valid reset interval, should be >= 60 seconds or 'never' at line %d.\n",
18570  v->value, v->lineno);
18571  } else if (!strcasecmp(v->name, "force_restart_unavailable_chans")) {
18572  confp->pri.pri.force_restart_unavailable_chans = ast_true(v->value);
18573  } else if (!strcasecmp(v->name, "minunused")) {
18574  confp->pri.pri.minunused = atoi(v->value);
18575  } else if (!strcasecmp(v->name, "minidle")) {
18576  confp->pri.pri.minidle = atoi(v->value);
18577  } else if (!strcasecmp(v->name, "idleext")) {
18578  ast_copy_string(confp->pri.pri.idleext, v->value, sizeof(confp->pri.pri.idleext));
18579  } else if (!strcasecmp(v->name, "idledial")) {
18580  ast_copy_string(confp->pri.pri.idledial, v->value, sizeof(confp->pri.pri.idledial));
18581  } else if (!strcasecmp(v->name, "overlapdial")) {
18582  if (ast_true(v->value)) {
18583  confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
18584  } else if (!strcasecmp(v->value, "incoming")) {
18585  confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_INCOMING;
18586  } else if (!strcasecmp(v->value, "outgoing")) {
18587  confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_OUTGOING;
18588  } else if (!strcasecmp(v->value, "both") || ast_true(v->value)) {
18589  confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
18590  } else {
18591  confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_NONE;
18592  }
18593 #ifdef HAVE_PRI_PROG_W_CAUSE
18594  } else if (!strcasecmp(v->name, "qsigchannelmapping")) {
18595  if (!strcasecmp(v->value, "logical")) {
18596  confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_LOGICAL;
18597  } else if (!strcasecmp(v->value, "physical")) {
18598  confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL;
18599  } else {
18600  confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL;
18601  }
18602 #endif
18603  } else if (!strcasecmp(v->name, "discardremoteholdretrieval")) {
18604  confp->pri.pri.discardremoteholdretrieval = ast_true(v->value);
18605 #if defined(HAVE_PRI_SERVICE_MESSAGES)
18606  } else if (!strcasecmp(v->name, "service_message_support")) {
18607  /* assuming switchtype for this channel group has been configured already */
18608  if ((confp->pri.pri.switchtype == PRI_SWITCH_ATT4ESS
18609  || confp->pri.pri.switchtype == PRI_SWITCH_LUCENT5E
18610  || confp->pri.pri.switchtype == PRI_SWITCH_NI2) && ast_true(v->value)) {
18611  confp->pri.pri.enable_service_message_support = 1;
18612  } else {
18613  confp->pri.pri.enable_service_message_support = 0;
18614  }
18615 #endif /* defined(HAVE_PRI_SERVICE_MESSAGES) */
18616 #ifdef HAVE_PRI_INBANDDISCONNECT
18617  } else if (!strcasecmp(v->name, "inbanddisconnect")) {
18618  confp->pri.pri.inbanddisconnect = ast_true(v->value);
18619 #endif
18620  } else if (!strcasecmp(v->name, "pritimer")) {
18621 #ifdef PRI_GETSET_TIMERS
18622  char tmp[20];
18623  char *timerc;
18624  char *c;
18625  int timer;
18626  int timeridx;
18627 
18628  ast_copy_string(tmp, v->value, sizeof(tmp));
18629  c = tmp;
18630  timerc = strsep(&c, ",");
18631  if (!ast_strlen_zero(timerc) && !ast_strlen_zero(c)) {
18632  timeridx = pri_timer2idx(timerc);
18633  timer = atoi(c);
18634  if (timeridx < 0 || PRI_MAX_TIMERS <= timeridx) {
18636  "'%s' is not a valid ISDN timer at line %d.\n", timerc,
18637  v->lineno);
18638  } else if (!timer) {
18640  "'%s' is not a valid value for ISDN timer '%s' at line %d.\n",
18641  c, timerc, v->lineno);
18642  } else {
18643  confp->pri.pri.pritimers[timeridx] = timer;
18644  }
18645  } else {
18647  "'%s' is not a valid ISDN timer configuration string at line %d.\n",
18648  v->value, v->lineno);
18649  }
18650 #endif /* PRI_GETSET_TIMERS */
18651  } else if (!strcasecmp(v->name, "facilityenable")) {
18652  confp->pri.pri.facilityenable = ast_true(v->value);
18653 #if defined(HAVE_PRI_AOC_EVENTS)
18654  } else if (!strcasecmp(v->name, "aoc_enable")) {
18655  confp->pri.pri.aoc_passthrough_flag = 0;
18656  if (strchr(v->value, 's') || strchr(v->value, 'S')) {
18657  confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_S;
18658  }
18659  if (strchr(v->value, 'd') || strchr(v->value, 'D')) {
18660  confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_D;
18661  }
18662  if (strchr(v->value, 'e') || strchr(v->value, 'E')) {
18663  confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_E;
18664  }
18665  } else if (!strcasecmp(v->name, "aoce_delayhangup")) {
18666  confp->pri.pri.aoce_delayhangup = ast_true(v->value);
18667 #endif /* defined(HAVE_PRI_AOC_EVENTS) */
18668 #if defined(HAVE_PRI_CALL_HOLD)
18669  } else if (!strcasecmp(v->name, "hold_disconnect_transfer")) {
18670  confp->pri.pri.hold_disconnect_transfer = ast_true(v->value);
18671 #endif /* defined(HAVE_PRI_CALL_HOLD) */
18672  } else if (!strcasecmp(v->name, "moh_signaling")
18673  || !strcasecmp(v->name, "moh_signalling")) {
18674  if (!strcasecmp(v->value, "moh")) {
18675  confp->pri.pri.moh_signaling = SIG_PRI_MOH_SIGNALING_MOH;
18676  } else if (!strcasecmp(v->value, "notify")) {
18677  confp->pri.pri.moh_signaling = SIG_PRI_MOH_SIGNALING_NOTIFY;
18678 #if defined(HAVE_PRI_CALL_HOLD)
18679  } else if (!strcasecmp(v->value, "hold")) {
18680  confp->pri.pri.moh_signaling = SIG_PRI_MOH_SIGNALING_HOLD;
18681 #endif /* defined(HAVE_PRI_CALL_HOLD) */
18682  } else {
18683  confp->pri.pri.moh_signaling = SIG_PRI_MOH_SIGNALING_MOH;
18684  }
18685 #if defined(HAVE_PRI_CCSS)
18686  } else if (!strcasecmp(v->name, "cc_ptmp_recall_mode")) {
18687  if (!strcasecmp(v->value, "global")) {
18688  confp->pri.pri.cc_ptmp_recall_mode = 0;/* globalRecall */
18689  } else if (!strcasecmp(v->value, "specific")) {
18690  confp->pri.pri.cc_ptmp_recall_mode = 1;/* specificRecall */
18691  } else {
18692  confp->pri.pri.cc_ptmp_recall_mode = 1;/* specificRecall */
18693  }
18694  } else if (!strcasecmp(v->name, "cc_qsig_signaling_link_req")) {
18695  if (!strcasecmp(v->value, "release")) {
18696  confp->pri.pri.cc_qsig_signaling_link_req = 0;/* release */
18697  } else if (!strcasecmp(v->value, "retain")) {
18698  confp->pri.pri.cc_qsig_signaling_link_req = 1;/* retain */
18699  } else if (!strcasecmp(v->value, "do_not_care")) {
18700  confp->pri.pri.cc_qsig_signaling_link_req = 2;/* do-not-care */
18701  } else {
18702  confp->pri.pri.cc_qsig_signaling_link_req = 1;/* retain */
18703  }
18704  } else if (!strcasecmp(v->name, "cc_qsig_signaling_link_rsp")) {
18705  if (!strcasecmp(v->value, "release")) {
18706  confp->pri.pri.cc_qsig_signaling_link_rsp = 0;/* release */
18707  } else if (!strcasecmp(v->value, "retain")) {
18708  confp->pri.pri.cc_qsig_signaling_link_rsp = 1;/* retain */
18709  } else {
18710  confp->pri.pri.cc_qsig_signaling_link_rsp = 1;/* retain */
18711  }
18712 #endif /* defined(HAVE_PRI_CCSS) */
18713 #if defined(HAVE_PRI_CALL_WAITING)
18714  } else if (!strcasecmp(v->name, "max_call_waiting_calls")) {
18715  confp->pri.pri.max_call_waiting_calls = atoi(v->value);
18716  if (confp->pri.pri.max_call_waiting_calls < 0) {
18717  /* Negative values are not allowed. */
18718  confp->pri.pri.max_call_waiting_calls = 0;
18719  }
18720  } else if (!strcasecmp(v->name, "allow_call_waiting_calls")) {
18721  confp->pri.pri.allow_call_waiting_calls = ast_true(v->value);
18722 #endif /* defined(HAVE_PRI_CALL_WAITING) */
18723 #if defined(HAVE_PRI_MWI)
18724  } else if (!strcasecmp(v->name, "mwi_mailboxes")) {
18725  ast_copy_string(confp->pri.pri.mwi_mailboxes, v->value,
18726  sizeof(confp->pri.pri.mwi_mailboxes));
18727  } else if (!strcasecmp(v->name, "mwi_vm_boxes")) {
18728  ast_copy_string(confp->pri.pri.mwi_vm_boxes, v->value,
18729  sizeof(confp->pri.pri.mwi_vm_boxes));
18730  } else if (!strcasecmp(v->name, "mwi_vm_numbers")) {
18731  ast_copy_string(confp->pri.pri.mwi_vm_numbers, v->value,
18732  sizeof(confp->pri.pri.mwi_vm_numbers));
18733 #endif /* defined(HAVE_PRI_MWI) */
18734  } else if (!strcasecmp(v->name, "append_msn_to_cid_tag")) {
18735  confp->pri.pri.append_msn_to_user_tag = ast_true(v->value);
18736  } else if (!strcasecmp(v->name, "inband_on_setup_ack")) {
18737  confp->pri.pri.inband_on_setup_ack = ast_true(v->value);
18738  } else if (!strcasecmp(v->name, "inband_on_proceeding")) {
18739  confp->pri.pri.inband_on_proceeding = ast_true(v->value);
18740 #if defined(HAVE_PRI_DISPLAY_TEXT)
18741  } else if (!strcasecmp(v->name, "display_send")) {
18742  confp->pri.pri.display_flags_send = dahdi_display_text_option(v->value);
18743  } else if (!strcasecmp(v->name, "display_receive")) {
18744  confp->pri.pri.display_flags_receive = dahdi_display_text_option(v->value);
18745 #endif /* defined(HAVE_PRI_DISPLAY_TEXT) */
18746 #if defined(HAVE_PRI_MCID)
18747  } else if (!strcasecmp(v->name, "mcid_send")) {
18748  confp->pri.pri.mcid_send = ast_true(v->value);
18749 #endif /* defined(HAVE_PRI_MCID) */
18750 #if defined(HAVE_PRI_DATETIME_SEND)
18751  } else if (!strcasecmp(v->name, "datetime_send")) {
18752  confp->pri.pri.datetime_send = dahdi_datetime_send_option(v->value);
18753 #endif /* defined(HAVE_PRI_DATETIME_SEND) */
18754  } else if (!strcasecmp(v->name, "layer1_presence")) {
18755  if (!strcasecmp(v->value, "required")) {
18756  confp->pri.pri.layer1_ignored = 0;
18757  } else if (!strcasecmp(v->value, "ignore")) {
18758  confp->pri.pri.layer1_ignored = 1;
18759  } else {
18760  /* Default */
18761  confp->pri.pri.layer1_ignored = 0;
18762  }
18763 #if defined(HAVE_PRI_L2_PERSISTENCE)
18764  } else if (!strcasecmp(v->name, "layer2_persistence")) {
18765  if (!strcasecmp(v->value, "keep_up")) {
18766  confp->pri.pri.l2_persistence = PRI_L2_PERSISTENCE_KEEP_UP;
18767  } else if (!strcasecmp(v->value, "leave_down")) {
18768  confp->pri.pri.l2_persistence = PRI_L2_PERSISTENCE_LEAVE_DOWN;
18769  } else {
18770  confp->pri.pri.l2_persistence = PRI_L2_PERSISTENCE_DEFAULT;
18771  }
18772 #endif /* defined(HAVE_PRI_L2_PERSISTENCE) */
18773  } else if (!strcasecmp(v->name, "colp_send")) {
18774  if (!strcasecmp(v->value, "block")) {
18775  confp->pri.pri.colp_send = SIG_PRI_COLP_BLOCK;
18776  } else if (!strcasecmp(v->value, "connect")) {
18777  confp->pri.pri.colp_send = SIG_PRI_COLP_CONNECT;
18778  } else if (!strcasecmp(v->value, "update")) {
18779  confp->pri.pri.colp_send = SIG_PRI_COLP_UPDATE;
18780  } else {
18781  confp->pri.pri.colp_send = SIG_PRI_COLP_UPDATE;
18782  }
18783 #endif /* HAVE_PRI */
18784 #if defined(HAVE_SS7)
18785  } else if (!strcasecmp(v->name, "ss7type")) {
18786  if (!strcasecmp(v->value, "itu")) {
18787  cur_ss7type = SS7_ITU;
18788  } else if (!strcasecmp(v->value, "ansi")) {
18789  cur_ss7type = SS7_ANSI;
18790  } else {
18791  ast_log(LOG_WARNING, "'%s' is an unknown ss7 switch type at line %d.!\n", v->value, v->lineno);
18792  }
18793  } else if (!strcasecmp(v->name, "slc")) {
18794  cur_slc = atoi(v->value);
18795  } else if (!strcasecmp(v->name, "linkset")) {
18796  cur_linkset = atoi(v->value);
18797  } else if (!strcasecmp(v->name, "pointcode")) {
18798  cur_pointcode = parse_pointcode(v->value);
18799  } else if (!strcasecmp(v->name, "adjpointcode")) {
18800  cur_adjpointcode = parse_pointcode(v->value);
18801  } else if (!strcasecmp(v->name, "defaultdpc")) {
18802  cur_defaultdpc = parse_pointcode(v->value);
18803  } else if (!strcasecmp(v->name, "cicbeginswith")) {
18804  cur_cicbeginswith = atoi(v->value);
18805  } else if (!strcasecmp(v->name, "networkindicator")) {
18806  if (!strcasecmp(v->value, "national")) {
18807  cur_networkindicator = SS7_NI_NAT;
18808  } else if (!strcasecmp(v->value, "national_spare")) {
18809  cur_networkindicator = SS7_NI_NAT_SPARE;
18810  } else if (!strcasecmp(v->value, "international")) {
18811  cur_networkindicator = SS7_NI_INT;
18812  } else if (!strcasecmp(v->value, "international_spare")) {
18813  cur_networkindicator = SS7_NI_INT_SPARE;
18814  } else {
18815  cur_networkindicator = -1;
18816  }
18817  } else if (!strcasecmp(v->name, "ss7_internationalprefix")) {
18818  ast_copy_string(confp->ss7.ss7.internationalprefix, v->value, sizeof(confp->ss7.ss7.internationalprefix));
18819  } else if (!strcasecmp(v->name, "ss7_nationalprefix")) {
18820  ast_copy_string(confp->ss7.ss7.nationalprefix, v->value, sizeof(confp->ss7.ss7.nationalprefix));
18821  } else if (!strcasecmp(v->name, "ss7_subscriberprefix")) {
18822  ast_copy_string(confp->ss7.ss7.subscriberprefix, v->value, sizeof(confp->ss7.ss7.subscriberprefix));
18823  } else if (!strcasecmp(v->name, "ss7_unknownprefix")) {
18824  ast_copy_string(confp->ss7.ss7.unknownprefix, v->value, sizeof(confp->ss7.ss7.unknownprefix));
18825  } else if (!strcasecmp(v->name, "ss7_networkroutedprefix")) {
18826  ast_copy_string(confp->ss7.ss7.networkroutedprefix, v->value, sizeof(confp->ss7.ss7.networkroutedprefix));
18827  } else if (!strcasecmp(v->name, "ss7_called_nai")) {
18828  if (!strcasecmp(v->value, "national")) {
18829  confp->ss7.ss7.called_nai = SS7_NAI_NATIONAL;
18830  } else if (!strcasecmp(v->value, "international")) {
18831  confp->ss7.ss7.called_nai = SS7_NAI_INTERNATIONAL;
18832  } else if (!strcasecmp(v->value, "subscriber")) {
18833  confp->ss7.ss7.called_nai = SS7_NAI_SUBSCRIBER;
18834  } else if (!strcasecmp(v->value, "unknown")) {
18835  confp->ss7.ss7.called_nai = SS7_NAI_UNKNOWN;
18836  } else if (!strcasecmp(v->value, "dynamic")) {
18837  confp->ss7.ss7.called_nai = SS7_NAI_DYNAMIC;
18838  } else {
18839  ast_log(LOG_WARNING, "Unknown SS7 called_nai '%s' at line %d.\n", v->value, v->lineno);
18840  }
18841  } else if (!strcasecmp(v->name, "ss7_calling_nai")) {
18842  if (!strcasecmp(v->value, "national")) {
18843  confp->ss7.ss7.calling_nai = SS7_NAI_NATIONAL;
18844  } else if (!strcasecmp(v->value, "international")) {
18845  confp->ss7.ss7.calling_nai = SS7_NAI_INTERNATIONAL;
18846  } else if (!strcasecmp(v->value, "subscriber")) {
18847  confp->ss7.ss7.calling_nai = SS7_NAI_SUBSCRIBER;
18848  } else if (!strcasecmp(v->value, "unknown")) {
18849  confp->ss7.ss7.calling_nai = SS7_NAI_UNKNOWN;
18850  } else if (!strcasecmp(v->value, "dynamic")) {
18851  confp->ss7.ss7.calling_nai = SS7_NAI_DYNAMIC;
18852  } else {
18853  ast_log(LOG_WARNING, "Unknown SS7 calling_nai '%s' at line %d.\n", v->value, v->lineno);
18854  }
18855  } else if (!strcasecmp(v->name, "sigchan")) {
18856  int sigchan, res;
18857  sigchan = atoi(v->value);
18858  res = linkset_addsigchan(sigchan);
18859  if (res < 0) {
18860  return -1;
18861  }
18862  } else if (!strcasecmp(v->name, "ss7_explicitacm")) {
18863  struct dahdi_ss7 *link;
18864  link = ss7_resolve_linkset(cur_linkset);
18865  if (!link) {
18866  ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
18867  return -1;
18868  }
18869  if (ast_true(v->value)) {
18870  link->ss7.flags |= LINKSET_FLAG_EXPLICITACM;
18871  } else {
18872  link->ss7.flags &= ~LINKSET_FLAG_EXPLICITACM;
18873  }
18874  } else if (!strcasecmp(v->name, "ss7_autoacm")) {
18875  struct dahdi_ss7 *link;
18876  link = ss7_resolve_linkset(cur_linkset);
18877  if (!link) {
18878  ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
18879  return -1;
18880  }
18881  if (ast_true(v->value)) {
18882  link->ss7.flags |= LINKSET_FLAG_AUTOACM;
18883  } else {
18884  link->ss7.flags &= ~LINKSET_FLAG_AUTOACM;
18885  }
18886  } else if (!strcasecmp(v->name, "ss7_initialhwblo")) {
18887  struct dahdi_ss7 *link;
18888  link = ss7_resolve_linkset(cur_linkset);
18889  if (!link) {
18890  ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
18891  return -1;
18892  }
18893  if (ast_true(v->value)) {
18894  link->ss7.flags |= LINKSET_FLAG_INITIALHWBLO;
18895  } else {
18896  link->ss7.flags &= ~LINKSET_FLAG_INITIALHWBLO;
18897  }
18898  } else if (!strcasecmp(v->name, "ss7_use_echocontrol")) {
18899  struct dahdi_ss7 *link;
18900  link = ss7_resolve_linkset(cur_linkset);
18901  if (!link) {
18902  ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
18903  return -1;
18904  }
18905  if (ast_true(v->value)) {
18906  link->ss7.flags |= LINKSET_FLAG_USEECHOCONTROL;
18907  } else {
18908  link->ss7.flags &= ~LINKSET_FLAG_USEECHOCONTROL;
18909  }
18910  } else if (!strcasecmp(v->name, "ss7_default_echocontrol")) {
18911  struct dahdi_ss7 *link;
18912  link = ss7_resolve_linkset(cur_linkset);
18913  if (!link) {
18914  ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
18915  return -1;
18916  }
18917  if (ast_true(v->value)) {
18918  link->ss7.flags |= LINKSET_FLAG_DEFAULTECHOCONTROL;
18919  } else {
18920  link->ss7.flags &= ~LINKSET_FLAG_DEFAULTECHOCONTROL;
18921  }
18922  } else if (!strncasecmp(v->name, "isup_timer.", 11)) {
18923  struct dahdi_ss7 *link;
18924  link = ss7_resolve_linkset(cur_linkset);
18925  if (!link) {
18926  ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
18927  return -1;
18928  }
18929  if (!link->ss7.ss7) {
18930  ast_log(LOG_ERROR, "Please specify isup timers after sigchan!\n");
18931  } else if (!ss7_set_isup_timer(link->ss7.ss7, strstr(v->name, ".") + 1, atoi(v->value))) {
18932  ast_log(LOG_ERROR, "Invalid isup timer %s\n", v->name);
18933  }
18934  } else if (!strncasecmp(v->name, "mtp3_timer.", 11)) {
18935  struct dahdi_ss7 *link;
18936  link = ss7_resolve_linkset(cur_linkset);
18937  if (!link) {
18938  ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
18939  return -1;
18940  }
18941  if (!link->ss7.ss7) {
18942  ast_log(LOG_ERROR, "Please specify mtp3 timers after sigchan!\n");
18943  } else if (!ss7_set_mtp3_timer(link->ss7.ss7, strstr(v->name, ".") + 1, atoi(v->value))) {
18944  ast_log(LOG_ERROR, "Invalid mtp3 timer %s\n", v->name);
18945  }
18946  } else if (!strcasecmp(v->name, "inr_if_no_calling")) {
18947  struct dahdi_ss7 *link;
18948  link = ss7_resolve_linkset(cur_linkset);
18949  if (!link) {
18950  ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
18951  return -1;
18952  }
18953  if (!link->ss7.ss7) {
18954  ast_log(LOG_ERROR, "Please specify inr_if_no_calling after sigchan!\n");
18955  } else if (ast_true(v->value)) {
18956  ss7_set_flags(link->ss7.ss7, SS7_INR_IF_NO_CALLING);
18957  } else {
18958  ss7_clear_flags(link->ss7.ss7, SS7_INR_IF_NO_CALLING);
18959  }
18960  } else if (!strcasecmp(v->name, "non_isdn_access")) {
18961  struct dahdi_ss7 *link;
18962  link = ss7_resolve_linkset(cur_linkset);
18963  if (!link) {
18964  ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
18965  return -1;
18966  }
18967  if (!link->ss7.ss7) {
18968  ast_log(LOG_ERROR, "Please specify non_isdn_access after sigchan!\n");
18969  } else if (ast_true(v->value)) {
18970  ss7_clear_flags(link->ss7.ss7, SS7_ISDN_ACCESS_INDICATOR);
18971  } else {
18972  ss7_set_flags(link->ss7.ss7, SS7_ISDN_ACCESS_INDICATOR);
18973  }
18974  } else if (!strcasecmp(v->name, "sls_shift")) {
18975  struct dahdi_ss7 *link;
18976  int sls_shift = atoi(v->value);
18977 
18978  if (sls_shift < 0 || sls_shift > 7) {
18979  ast_log(LOG_ERROR, "Invalid sls_shift value. Must be between 0 and 7\n");
18980  return -1;
18981  }
18982 
18983  link = ss7_resolve_linkset(cur_linkset);
18984  if (!link) {
18985  ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
18986  return -1;
18987  }
18988  if (!link->ss7.ss7) {
18989  ast_log(LOG_ERROR, "Please specify sls_shift after sigchan!\n");
18990  } else {
18991  ss7_set_sls_shift(link->ss7.ss7, sls_shift);
18992  }
18993  } else if (!strcasecmp(v->name, "cause_location")) {
18994  struct dahdi_ss7 *link;
18995  int cause_location = atoi(v->value);
18996 
18997  if (cause_location < 0 || cause_location > 15) {
18998  ast_log(LOG_ERROR, "Invalid cause_location value. Must be between 0 and 15\n");
18999  return -1;
19000  }
19001  link = ss7_resolve_linkset(cur_linkset);
19002  if (!link) {
19003  ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
19004  return -1;
19005  }
19006  if (!link->ss7.ss7) {
19007  ast_log(LOG_ERROR, "Please specify cause_location after sigchan!\n");
19008  } else {
19009  ss7_set_cause_location(link->ss7.ss7, cause_location);
19010  }
19011 #endif /* defined(HAVE_SS7) */
19012 #ifdef HAVE_OPENR2
19013  } else if (!strcasecmp(v->name, "mfcr2_advanced_protocol_file")) {
19014  ast_copy_string(confp->mfcr2.r2proto_file, v->value, sizeof(confp->mfcr2.r2proto_file));
19015  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);
19016  } else if (!strcasecmp(v->name, "mfcr2_logdir")) {
19017  ast_copy_string(confp->mfcr2.logdir, v->value, sizeof(confp->mfcr2.logdir));
19018  } else if (!strcasecmp(v->name, "mfcr2_variant")) {
19019  confp->mfcr2.variant = openr2_proto_get_variant(v->value);
19020  if (OR2_VAR_UNKNOWN == confp->mfcr2.variant) {
19021  ast_log(LOG_WARNING, "Unknown MFC/R2 variant '%s' at line %d, defaulting to ITU.\n", v->value, v->lineno);
19022  confp->mfcr2.variant = OR2_VAR_ITU;
19023  }
19024  } else if (!strcasecmp(v->name, "mfcr2_mfback_timeout")) {
19025  confp->mfcr2.mfback_timeout = atoi(v->value);
19026  if (!confp->mfcr2.mfback_timeout) {
19027  ast_log(LOG_WARNING, "MF timeout of 0? hum, I will protect you from your ignorance. Setting default.\n");
19028  confp->mfcr2.mfback_timeout = -1;
19029  } else if (confp->mfcr2.mfback_timeout > 0 && confp->mfcr2.mfback_timeout < 500) {
19030  ast_log(LOG_WARNING, "MF timeout less than 500ms is not recommended, you have been warned!\n");
19031  }
19032  } else if (!strcasecmp(v->name, "mfcr2_metering_pulse_timeout")) {
19033  confp->mfcr2.metering_pulse_timeout = atoi(v->value);
19034  if (confp->mfcr2.metering_pulse_timeout > 500) {
19035  ast_log(LOG_WARNING, "Metering pulse timeout greater than 500ms is not recommended, you have been warned!\n");
19036  }
19037 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2
19038  } else if (!strcasecmp(v->name, "mfcr2_dtmf_detection")) {
19039  confp->mfcr2.dtmf_detection = ast_true(v->value) ? 1 : 0;
19040  } else if (!strcasecmp(v->name, "mfcr2_dtmf_dialing")) {
19041  confp->mfcr2.dtmf_dialing = ast_true(v->value) ? 1 : 0;
19042  } else if (!strcasecmp(v->name, "mfcr2_dtmf_time_on")) {
19043  confp->mfcr2.dtmf_time_on = atoi(v->value);
19044  } else if (!strcasecmp(v->name, "mfcr2_dtmf_time_off")) {
19045  confp->mfcr2.dtmf_time_off = atoi(v->value);
19046 #endif
19047 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 3
19048  } else if (!strcasecmp(v->name, "mfcr2_dtmf_end_timeout")) {
19049  confp->mfcr2.dtmf_end_timeout = atoi(v->value);
19050 #endif
19051  } else if (!strcasecmp(v->name, "mfcr2_get_ani_first")) {
19052  confp->mfcr2.get_ani_first = ast_true(v->value) ? 1 : 0;
19053  } else if (!strcasecmp(v->name, "mfcr2_double_answer")) {
19054  confp->mfcr2.double_answer = ast_true(v->value) ? 1 : 0;
19055  } else if (!strcasecmp(v->name, "mfcr2_charge_calls")) {
19056  confp->mfcr2.charge_calls = ast_true(v->value) ? 1 : 0;
19057  } else if (!strcasecmp(v->name, "mfcr2_accept_on_offer")) {
19058  confp->mfcr2.accept_on_offer = ast_true(v->value) ? 1 : 0;
19059  } else if (!strcasecmp(v->name, "mfcr2_allow_collect_calls")) {
19060  confp->mfcr2.allow_collect_calls = ast_true(v->value) ? 1 : 0;
19061  } else if (!strcasecmp(v->name, "mfcr2_forced_release")) {
19062  confp->mfcr2.forced_release = ast_true(v->value) ? 1 : 0;
19063  } else if (!strcasecmp(v->name, "mfcr2_immediate_accept")) {
19064  confp->mfcr2.immediate_accept = ast_true(v->value) ? 1 : 0;
19065 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
19066  } else if (!strcasecmp(v->name, "mfcr2_skip_category")) {
19067  confp->mfcr2.skip_category_request = ast_true(v->value) ? 1 : 0;
19068 #endif
19069  } else if (!strcasecmp(v->name, "mfcr2_call_files")) {
19070  confp->mfcr2.call_files = ast_true(v->value) ? 1 : 0;
19071  } else if (!strcasecmp(v->name, "mfcr2_max_ani")) {
19072  confp->mfcr2.max_ani = atoi(v->value);
19073  if (confp->mfcr2.max_ani >= AST_MAX_EXTENSION) {
19074  confp->mfcr2.max_ani = AST_MAX_EXTENSION - 1;
19075  }
19076  } else if (!strcasecmp(v->name, "mfcr2_max_dnis")) {
19077  confp->mfcr2.max_dnis = atoi(v->value);
19078  if (confp->mfcr2.max_dnis >= AST_MAX_EXTENSION) {
19079  confp->mfcr2.max_dnis = AST_MAX_EXTENSION - 1;
19080  }
19081  } else if (!strcasecmp(v->name, "mfcr2_category")) {
19082  confp->mfcr2.category = openr2_proto_get_category(v->value);
19083  if (OR2_CALLING_PARTY_CATEGORY_UNKNOWN == confp->mfcr2.category) {
19084  confp->mfcr2.category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER;
19085  ast_log(LOG_WARNING, "Invalid MFC/R2 caller category '%s' at line %d. Using national subscriber as default.\n",
19086  v->value, v->lineno);
19087  }
19088  } else if (!strcasecmp(v->name, "mfcr2_logging")) {
19089  openr2_log_level_t tmplevel;
19090  char *clevel;
19091  char *logval;
19092  char copy[strlen(v->value) + 1];
19093  strcpy(copy, v->value); /* safe */
19094  logval = copy;
19095  while (logval) {
19096  clevel = strsep(&logval,",");
19097  if (-1 == (tmplevel = openr2_log_get_level(clevel))) {
19098  ast_log(LOG_WARNING, "Ignoring invalid logging level: '%s' at line %d.\n", clevel, v->lineno);
19099  continue;
19100  }
19101  confp->mfcr2.loglevel |= tmplevel;
19102  }
19103 #endif /* HAVE_OPENR2 */
19104  } else if (!strcasecmp(v->name, "cadence")) {
19105  /* setup to scan our argument */
19106  int element_count, c[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
19107  int i;
19108  struct dahdi_ring_cadence new_cadence;
19109  int cid_location = -1;
19110  int firstcadencepos = 0;
19111  char original_args[80];
19112  int cadence_is_ok = 1;
19113 
19114  ast_copy_string(original_args, v->value, sizeof(original_args));
19115  /* 16 cadences allowed (8 pairs) */
19116  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]);
19117 
19118  /* Cadence must be even (on/off) */
19119  if (element_count % 2 == 1) {
19120  ast_log(LOG_ERROR, "Must be a silence duration for each ring duration: %s at line %d.\n", original_args, v->lineno);
19121  cadence_is_ok = 0;
19122  }
19123 
19124  /* This check is only needed to satisfy the compiler that element_count can't cause an out of bounds */
19125  if (element_count > ARRAY_LEN(c)) {
19126  element_count = ARRAY_LEN(c);
19127  }
19128 
19129  /* Ring cadences cannot be negative */
19130  for (i = 0; i < element_count; i++) {
19131  if (c[i] == 0) {
19132  ast_log(LOG_ERROR, "Ring or silence duration cannot be zero: %s at line %d.\n", original_args, v->lineno);
19133  cadence_is_ok = 0;
19134  break;
19135  } else if (c[i] < 0) {
19136  if (i % 2 == 1) {
19137  /* Silence duration, negative possibly okay */
19138  if (cid_location == -1) {
19139  cid_location = i;
19140  c[i] *= -1;
19141  } else {
19142  ast_log(LOG_ERROR, "CID location specified twice: %s at line %d.\n", original_args, v->lineno);
19143  cadence_is_ok = 0;
19144  break;
19145  }
19146  } else {
19147  if (firstcadencepos == 0) {
19148  firstcadencepos = i; /* only recorded to avoid duplicate specification */
19149  /* duration will be passed negative to the DAHDI driver */
19150  } else {
19151  ast_log(LOG_ERROR, "First cadence position specified twice: %s at line %d.\n", original_args, v->lineno);
19152  cadence_is_ok = 0;
19153  break;
19154  }
19155  }
19156  }
19157  }
19158 
19159  /* Substitute our scanned cadence */
19160  for (i = 0; i < 16; i++) {
19161  new_cadence.ringcadence[i] = c[i];
19162  }
19163 
19164  if (cadence_is_ok) {
19165  /* ---we scanned it without getting annoyed; now some sanity checks--- */
19166  if (element_count < 2) {
19167  ast_log(LOG_ERROR, "Minimum cadence is ring,pause: %s at line %d.\n", original_args, v->lineno);
19168  } else {
19169  if (cid_location == -1) {
19170  /* user didn't say; default to first pause */
19171  cid_location = 1;
19172  } else {
19173  /* convert element_index to cidrings value */
19174  cid_location = (cid_location + 1) / 2;
19175  }
19176  /* ---we like their cadence; try to install it--- */
19178  /* this is the first user-defined cadence; clear the default user cadences */
19179  num_cadence = 0;
19180  if ((num_cadence+1) >= NUM_CADENCE_MAX)
19181  ast_log(LOG_ERROR, "Already %d cadences; can't add another: %s at line %d.\n", NUM_CADENCE_MAX, original_args, v->lineno);
19182  else {
19183  cadences[num_cadence] = new_cadence;
19184  cidrings[num_cadence++] = cid_location;
19185  ast_verb(3, "cadence 'r%d' added: %s\n",num_cadence,original_args);
19186  }
19187  }
19188  }
19189  } else if (!strcasecmp(v->name, "ringtimeout")) {
19190  ringt_base = (atoi(v->value) * 8) / READ_SIZE;
19191  } else if (!strcasecmp(v->name, "prewink")) {
19192  confp->timing.prewinktime = atoi(v->value);
19193  } else if (!strcasecmp(v->name, "preflash")) {
19194  confp->timing.preflashtime = atoi(v->value);
19195  } else if (!strcasecmp(v->name, "wink")) {
19196  confp->timing.winktime = atoi(v->value);
19197  } else if (!strcasecmp(v->name, "flash")) {
19198  confp->timing.flashtime = atoi(v->value);
19199  } else if (!strcasecmp(v->name, "start")) {
19200  confp->timing.starttime = atoi(v->value);
19201  } else if (!strcasecmp(v->name, "rxwink")) {
19202  confp->timing.rxwinktime = atoi(v->value);
19203  } else if (!strcasecmp(v->name, "rxflash")) {
19204  confp->timing.rxflashtime = atoi(v->value);
19205  } else if (!strcasecmp(v->name, "debounce")) {
19206  confp->timing.debouncetime = atoi(v->value);
19207  } else if (!strcasecmp(v->name, "toneduration")) {
19208  int toneduration;
19209  int ctlfd;
19210  int res;
19211  struct dahdi_dialparams dps;
19212 
19213  ctlfd = open("/dev/dahdi/ctl", O_RDWR);
19214  if (ctlfd == -1) {
19215  ast_log(LOG_ERROR, "Unable to open /dev/dahdi/ctl to set toneduration at line %d.\n", v->lineno);
19216  return -1;
19217  }
19218 
19219  toneduration = atoi(v->value);
19220  if (toneduration > -1) {
19221  memset(&dps, 0, sizeof(dps));
19222 
19223  dps.dtmf_tonelen = dps.mfv1_tonelen = toneduration;
19224  res = ioctl(ctlfd, DAHDI_SET_DIALPARAMS, &dps);
19225  if (res < 0) {
19226  ast_log(LOG_ERROR, "Invalid tone duration: %d ms at line %d: %s\n", toneduration, v->lineno, strerror(errno));
19227  close(ctlfd);
19228  return -1;
19229  }
19230  }
19231  close(ctlfd);
19232  } else if (!strcasecmp(v->name, "defaultcic")) {
19234  } else if (!strcasecmp(v->name, "defaultozz")) {
19236  } else if (!strcasecmp(v->name, "mwilevel")) {
19237  mwilevel = atoi(v->value);
19238  } else if (!strcasecmp(v->name, "dtmfcidlevel")) {
19239  dtmfcid_level = atoi(v->value);
19240  } else if (!strcasecmp(v->name, "reportalarms")) {
19241  if (!strcasecmp(v->value, "all"))
19243  if (!strcasecmp(v->value, "none"))
19244  report_alarms = 0;
19245  else if (!strcasecmp(v->value, "channels"))
19247  else if (!strcasecmp(v->value, "spans"))
19249  }
19250  } else if (!(options & PROC_DAHDI_OPT_NOWARN) )
19251  ast_log(LOG_WARNING, "Ignoring any changes to '%s' (on reload) at line %d.\n", v->name, v->lineno);
19252  }
19253 
19254  if (dahdichan) {
19255  /* Process the deferred dahdichan value. */
19256  if (build_channels(confp, dahdichan->value, reload, dahdichan->lineno)) {
19257  if (confp->ignore_failed_channels) {
19259  "Dahdichan '%s' failure ignored: ignore_failed_channels.\n",
19260  dahdichan->value);
19261  } else {
19262  return -1;
19263  }
19264  }
19265  }
19266 
19267  /*
19268  * Since confp has already filled individual dahdi_pvt objects with channels
19269  * at this point, clear the variables in confp's pvt.
19270  */
19271  if (confp->chan.vars) {
19273  confp->chan.vars = NULL;
19274  }
19275 
19276  /* mark the first channels of each DAHDI span to watch for their span alarms */
19277  for (tmp = iflist, y=-1; tmp; tmp = tmp->next) {
19278  if (!tmp->destroy && tmp->span != y) {
19279  tmp->manages_span_alarms = 1;
19280  y = tmp->span;
19281  } else {
19282  tmp->manages_span_alarms = 0;
19283  }
19284  }
19285 
19286  /*< \todo why check for the pseudo in the per-channel section.
19287  * Any actual use for manual setup of the pseudo channel? */
19288  if (!has_pseudo && reload != 1 && !(options & PROC_DAHDI_OPT_NOCHAN)) {
19289  /* use the default configuration for a channel, so
19290  that any settings from real configured channels
19291  don't "leak" into the pseudo channel config
19292  */
19293  struct dahdi_chan_conf conf = dahdi_chan_conf_default();
19294 
19295  if (conf.chan.cc_params) {
19296  tmp = mkintf(CHAN_PSEUDO, &conf, reload);
19297  } else {
19298  tmp = NULL;
19299  }
19300  if (tmp) {
19301  ast_verb(3, "Automatically generated pseudo channel\n");
19302  has_pseudo = 1;
19303  } else {
19304  ast_log(LOG_WARNING, "Unable to register pseudo channel!\n");
19305  }
19307  }
19308 
19309  /* Since named callgroup and named pickup group are ref'd to dahdi_pvt at this point, unref container in confp's pvt. */
19312 
19313  return 0;
19314 }
19315 
19316 /*!
19317  * \internal
19318  * \brief Deep copy struct dahdi_chan_conf.
19319  * \since 1.8
19320  *
19321  * \param dest Destination.
19322  * \param src Source.
19323  *
19324  * \return Nothing
19325  */
19326 static void deep_copy_dahdi_chan_conf(struct dahdi_chan_conf *dest, const struct dahdi_chan_conf *src)
19327 {
19328  struct ast_cc_config_params *cc_params;
19329 
19330  cc_params = dest->chan.cc_params;
19331  *dest = *src;
19332  dest->chan.cc_params = cc_params;
19334 }
19335 
19336 /*!
19337  * \internal
19338  * \brief Setup DAHDI channel driver.
19339  *
19340  * \param reload enum: load_module(0), reload(1), restart(2).
19341  * \param default_conf Default config parameters. So cc_params can be properly destroyed.
19342  * \param base_conf Default config parameters per section. So cc_params can be properly destroyed.
19343  * \param conf Local config parameters. So cc_params can be properly destroyed.
19344  *
19345  * \retval 0 on success.
19346  * \retval -1 on error.
19347  */
19348 static int setup_dahdi_int(int reload, struct dahdi_chan_conf *default_conf, struct dahdi_chan_conf *base_conf, struct dahdi_chan_conf *conf)
19349 {
19350  struct ast_config *cfg;
19351  struct ast_config *ucfg;
19352  struct ast_variable *v;
19353  struct ast_flags config_flags = { reload == 1 ? CONFIG_FLAG_FILEUNCHANGED : 0 };
19354  const char *chans;
19355  const char *cat;
19356  int res;
19357 
19358 #ifdef HAVE_PRI
19359  char *c;
19360  int spanno;
19361  int i;
19362  int logicalspan;
19363  int trunkgroup;
19364  int dchannels[SIG_PRI_NUM_DCHANS];
19365 #endif
19366  int have_cfg_now;
19367  static int had_cfg_before = 1;/* So initial load will complain if we don't have cfg. */
19368 
19369  cfg = ast_config_load(config, config_flags);
19370  have_cfg_now = !!cfg;
19371  if (!cfg) {
19372  /* Error if we have no config file */
19373  if (had_cfg_before) {
19374  ast_log(LOG_ERROR, "Unable to load config %s\n", config);
19375  ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
19376  }
19377  cfg = ast_config_new();/* Dummy config */
19378  if (!cfg) {
19379  return 0;
19380  }
19381  ucfg = ast_config_load("users.conf", config_flags);
19382  if (ucfg == CONFIG_STATUS_FILEUNCHANGED) {
19383  ast_config_destroy(cfg);
19384  return 0;
19385  }
19386  if (ucfg == CONFIG_STATUS_FILEINVALID) {
19387  ast_log(LOG_ERROR, "File users.conf cannot be parsed. Aborting.\n");
19388  ast_config_destroy(cfg);
19389  return 0;
19390  }
19391  } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
19392  ucfg = ast_config_load("users.conf", config_flags);
19393  if (ucfg == CONFIG_STATUS_FILEUNCHANGED) {
19394  return 0;
19395  }
19396  if (ucfg == CONFIG_STATUS_FILEINVALID) {
19397  ast_log(LOG_ERROR, "File users.conf cannot be parsed. Aborting.\n");
19398  return 0;
19399  }
19400  ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
19401  cfg = ast_config_load(config, config_flags);
19402  have_cfg_now = !!cfg;
19403  if (!cfg) {
19404  if (had_cfg_before) {
19405  /* We should have been able to load the config. */
19406  ast_log(LOG_ERROR, "Bad. Unable to load config %s\n", config);
19407  ast_config_destroy(ucfg);
19408  return 0;
19409  }
19410  cfg = ast_config_new();/* Dummy config */
19411  if (!cfg) {
19412  ast_config_destroy(ucfg);
19413  return 0;
19414  }
19415  } else if (cfg == CONFIG_STATUS_FILEINVALID) {
19416  ast_log(LOG_ERROR, "File %s cannot be parsed. Aborting.\n", config);
19417  ast_config_destroy(ucfg);
19418  return 0;
19419  }
19420  } else if (cfg == CONFIG_STATUS_FILEINVALID) {
19421  ast_log(LOG_ERROR, "File %s cannot be parsed. Aborting.\n", config);
19422  return 0;
19423  } else {
19424  ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
19425  ucfg = ast_config_load("users.conf", config_flags);
19426  if (ucfg == CONFIG_STATUS_FILEINVALID) {
19427  ast_log(LOG_ERROR, "File users.conf cannot be parsed. Aborting.\n");
19428  ast_config_destroy(cfg);
19429  return 0;
19430  }
19431  }
19432  had_cfg_before = have_cfg_now;
19433 
19434  /* It's a little silly to lock it, but we might as well just to be sure */
19436 #ifdef HAVE_PRI
19437  if (reload != 1) {
19438  /* Process trunkgroups first */
19439  v = ast_variable_browse(cfg, "trunkgroups");
19440  while (v) {
19441  if (!strcasecmp(v->name, "trunkgroup")) {
19442  trunkgroup = atoi(v->value);
19443  if (trunkgroup > 0) {
19444  if ((c = strchr(v->value, ','))) {
19445  i = 0;
19446  memset(dchannels, 0, sizeof(dchannels));
19447  while (c && (i < SIG_PRI_NUM_DCHANS)) {
19448  dchannels[i] = atoi(c + 1);
19449  if (dchannels[i] < 0) {
19450  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);
19451  } else
19452  i++;
19453  c = strchr(c + 1, ',');
19454  }
19455  if (i) {
19456  if (pri_create_trunkgroup(trunkgroup, dchannels)) {
19457  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);
19458  } else
19459  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");
19460  } else
19461  ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
19462  } else
19463  ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
19464  } else
19465  ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of chan_dahdi.conf\n", v->lineno);
19466  } else if (!strcasecmp(v->name, "spanmap")) {
19467  spanno = atoi(v->value);
19468  if (spanno > 0) {
19469  if ((c = strchr(v->value, ','))) {
19470  trunkgroup = atoi(c + 1);
19471  if (trunkgroup > 0) {
19472  if ((c = strchr(c + 1, ',')))
19473  logicalspan = atoi(c + 1);
19474  else
19475  logicalspan = 0;
19476  if (logicalspan >= 0) {
19477  if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) {
19478  ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
19479  } else
19480  ast_verb(2, "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
19481  } else
19482  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);
19483  } else
19484  ast_log(LOG_WARNING, "Trunk group must be a postive number at line %d of chan_dahdi.conf\n", v->lineno);
19485  } else
19486  ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of chan_dahdi.conf\n", v->lineno);
19487  } else
19488  ast_log(LOG_WARNING, "Span number must be a postive integer at line %d of chan_dahdi.conf\n", v->lineno);
19489  } else {
19490  ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name);
19491  }
19492  v = v->next;
19493  }
19494  }
19495 #endif
19496 
19497  /* Copy the default jb config over global_jbconf */
19498  memcpy(&global_jbconf, &default_jbconf, sizeof(global_jbconf));
19499 
19500  mwimonitornotify[0] = '\0';
19501 
19502  v = ast_variable_browse(cfg, "channels");
19503  if ((res = process_dahdi(base_conf,
19504  "" /* Must be empty for the channels category. Silly voicemail mailbox. */,
19505  v, reload, 0))) {
19507  ast_config_destroy(cfg);
19508  if (ucfg) {
19509  ast_config_destroy(ucfg);
19510  }
19511  return res;
19512  }
19513 
19514  /* Now get configuration from all normal sections in chan_dahdi.conf: */
19515  for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) {
19516  /* [channels] and [trunkgroups] are used. Let's also reserve
19517  * [globals] and [general] for future use
19518  */
19519  if (!strcasecmp(cat, "general") ||
19520  !strcasecmp(cat, "trunkgroups") ||
19521  !strcasecmp(cat, "globals") ||
19522  !strcasecmp(cat, "channels")) {
19523  continue;
19524  }
19525 
19526  chans = ast_variable_retrieve(cfg, cat, "dahdichan");
19527  if (ast_strlen_zero(chans)) {
19528  /* Section is useless without a dahdichan value present. */
19529  continue;
19530  }
19531 
19532  /* Copy base_conf to conf. */
19533  deep_copy_dahdi_chan_conf(conf, base_conf);
19534 
19535  if ((res = process_dahdi(conf, cat, ast_variable_browse(cfg, cat), reload, PROC_DAHDI_OPT_NOCHAN))) {
19537  ast_config_destroy(cfg);
19538  if (ucfg) {
19539  ast_config_destroy(ucfg);
19540  }
19541  return res;
19542  }
19543  }
19544 
19545  ast_config_destroy(cfg);
19546 
19547  if (ucfg) {
19548  /* Reset base_conf, so things don't leak from chan_dahdi.conf */
19549  deep_copy_dahdi_chan_conf(base_conf, default_conf);
19550  process_dahdi(base_conf,
19551  "" /* Must be empty for the general category. Silly voicemail mailbox. */,
19552  ast_variable_browse(ucfg, "general"), 1, 0);
19553 
19554  for (cat = ast_category_browse(ucfg, NULL); cat ; cat = ast_category_browse(ucfg, cat)) {
19555  if (!strcasecmp(cat, "general")) {
19556  continue;
19557  }
19558 
19559  chans = ast_variable_retrieve(ucfg, cat, "dahdichan");
19560  if (ast_strlen_zero(chans)) {
19561  /* Section is useless without a dahdichan value present. */
19562  continue;
19563  }
19564 
19565  /* Copy base_conf to conf. */
19566  deep_copy_dahdi_chan_conf(conf, base_conf);
19567 
19568  if ((res = process_dahdi(conf, cat, ast_variable_browse(ucfg, cat), reload, PROC_DAHDI_OPT_NOCHAN | PROC_DAHDI_OPT_NOWARN))) {
19569  ast_config_destroy(ucfg);
19571  return res;
19572  }
19573  }
19574  ast_config_destroy(ucfg);
19575  }
19577 
19578 #ifdef HAVE_PRI
19579  if (reload != 1) {
19580  int x;
19581  for (x = 0; x < NUM_SPANS; x++) {
19582  if (pris[x].pri.pvts[0] &&
19583  pris[x].pri.master == AST_PTHREADT_NULL) {
19584  prepare_pri(pris + x);
19585  if (sig_pri_start_pri(&pris[x].pri)) {
19586  ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1);
19587  return -1;
19588  } else
19589  ast_verb(2, "Starting D-Channel on span %d\n", x + 1);
19590  }
19591  }
19592  }
19593 #endif
19594 #if defined(HAVE_SS7)
19595  if (reload != 1) {
19596  int x;
19597  for (x = 0; x < NUM_SPANS; x++) {
19598  if (linksets[x].ss7.ss7) {
19599  if (ast_pthread_create(&linksets[x].ss7.master, NULL, ss7_linkset, &linksets[x].ss7)) {
19600  ast_log(LOG_ERROR, "Unable to start SS7 linkset on span %d\n", x + 1);
19601  return -1;
19602  } else
19603  ast_verb(2, "Starting SS7 linkset on span %d\n", x + 1);
19604  }
19605  }
19606  }
19607 #endif /* defined(HAVE_SS7) */
19608 #ifdef HAVE_OPENR2
19609  if (reload != 1) {
19610  struct r2link_entry *cur;
19611  int x = 0;
19612  AST_LIST_LOCK(&r2links);
19613  AST_LIST_TRAVERSE(&r2links, cur, list) {
19614  struct dahdi_mfcr2 *r2 = &cur->mfcr2;
19615  if (r2->r2master == AST_PTHREADT_NULL) {
19616  if (ast_pthread_create(&r2->r2master, NULL, mfcr2_monitor, r2)) {
19617  ast_log(LOG_ERROR, "Unable to start R2 monitor on channel group %d\n", x + 1);
19618  return -1;
19619  } else {
19620  ast_verb(2, "Starting R2 monitor on channel group %d\n", x + 1);
19621  }
19622  x++;
19623  }
19624  }
19625  AST_LIST_UNLOCK(&r2links);
19626  }
19627 #endif
19628  /* And start the monitor for the first time */
19629  restart_monitor();
19630  return 0;
19631 }
19632 
19633 /*!
19634  * \internal
19635  * \brief Setup DAHDI channel driver.
19636  *
19637  * \param reload enum: load_module(0), reload(1), restart(2).
19638  *
19639  * \retval 0 on success.
19640  * \retval -1 on error.
19641  */
19642 static int setup_dahdi(int reload)
19643 {
19644  int res;
19645  struct dahdi_chan_conf default_conf = dahdi_chan_conf_default();
19646  struct dahdi_chan_conf base_conf = dahdi_chan_conf_default();
19647  struct dahdi_chan_conf conf = dahdi_chan_conf_default();
19648 
19649  if (default_conf.chan.cc_params && base_conf.chan.cc_params && conf.chan.cc_params) {
19650  res = setup_dahdi_int(reload, &default_conf, &base_conf, &conf);
19651  } else {
19652  res = -1;
19653  }
19657 
19658  return res;
19659 }
19660 
19661 /*!
19662  * \brief Load the module
19663  *
19664  * Module loading including tests for configuration or dependencies.
19665  * This function can return AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_DECLINE,
19666  * or AST_MODULE_LOAD_SUCCESS. If a dependency or environment variable fails
19667  * tests return AST_MODULE_LOAD_FAILURE. If the module can not load the
19668  * configuration file or other non-critical problem return
19669  * AST_MODULE_LOAD_DECLINE. On success return AST_MODULE_LOAD_SUCCESS.
19670  */
19671 static int load_module(void)
19672 {
19673  int res;
19674 #if defined(HAVE_PRI) || defined(HAVE_SS7)
19675  int y;
19676 #endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */
19677 
19678  if (STASIS_MESSAGE_TYPE_INIT(dahdichannel_type)) {
19679  return AST_MODULE_LOAD_DECLINE;
19680  }
19681 
19683  return AST_MODULE_LOAD_DECLINE;
19684  }
19688 
19689  if (dahdi_native_load(&dahdi_tech)) {
19690  ao2_ref(dahdi_tech.capabilities, -1);
19691  return AST_MODULE_LOAD_DECLINE;
19692  }
19693 
19694 #ifdef HAVE_PRI
19695  memset(pris, 0, sizeof(pris));
19696  for (y = 0; y < NUM_SPANS; y++) {
19697  sig_pri_init_pri(&pris[y].pri);
19698  }
19699  pri_set_error(dahdi_pri_error);
19700  pri_set_message(dahdi_pri_message);
19701  ast_register_application_xml(dahdi_send_keypad_facility_app, dahdi_send_keypad_facility_exec);
19702 #ifdef HAVE_PRI_PROG_W_CAUSE
19703  ast_register_application_xml(dahdi_send_callrerouting_facility_app, dahdi_send_callrerouting_facility_exec);
19704 #endif
19705 #if defined(HAVE_PRI_CCSS)
19706  if (ast_cc_agent_register(&dahdi_pri_cc_agent_callbacks)
19707  || ast_cc_monitor_register(&dahdi_pri_cc_monitor_callbacks)) {
19708  __unload_module();
19709  return AST_MODULE_LOAD_DECLINE;
19710  }
19711 #endif /* defined(HAVE_PRI_CCSS) */
19712  if (sig_pri_load(
19713 #if defined(HAVE_PRI_CCSS)
19714  dahdi_pri_cc_type
19715 #else
19716  NULL
19717 #endif /* defined(HAVE_PRI_CCSS) */
19718  )) {
19719  __unload_module();
19720  return AST_MODULE_LOAD_DECLINE;
19721  }
19722 #endif
19723 #if defined(HAVE_SS7)
19724  memset(linksets, 0, sizeof(linksets));
19725  for (y = 0; y < NUM_SPANS; y++) {
19726  sig_ss7_init_linkset(&linksets[y].ss7);
19727  }
19728  ss7_set_error(dahdi_ss7_error);
19729  ss7_set_message(dahdi_ss7_message);
19730  ss7_set_hangup(sig_ss7_cb_hangup);
19731  ss7_set_notinservice(sig_ss7_cb_notinservice);
19732  ss7_set_call_null(sig_ss7_cb_call_null);
19733 #endif /* defined(HAVE_SS7) */
19734  res = setup_dahdi(0);
19735  /* Make sure we can register our DAHDI channel type */
19736  if (res) {
19737  __unload_module();
19738  return AST_MODULE_LOAD_DECLINE;
19739  }
19740  if (ast_channel_register(&dahdi_tech)) {
19741  ast_log(LOG_ERROR, "Unable to register channel class 'DAHDI'\n");
19742  __unload_module();
19743  return AST_MODULE_LOAD_DECLINE;
19744  }
19745 #ifdef HAVE_PRI
19746  ast_cli_register_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
19747 #endif
19748 #if defined(HAVE_SS7)
19749  ast_cli_register_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
19750 #endif /* defined(HAVE_SS7) */
19751 #ifdef HAVE_OPENR2
19752  ast_cli_register_multiple(dahdi_mfcr2_cli, ARRAY_LEN(dahdi_mfcr2_cli));
19753  ast_register_application_xml(dahdi_accept_r2_call_app, dahdi_accept_r2_call_exec);
19754 #endif
19755 
19756  ast_cli_register_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli));
19757  memset(round_robin, 0, sizeof(round_robin));
19758  ast_manager_register_xml("DAHDITransfer", 0, action_transfer);
19760  ast_manager_register_xml("DAHDIDialOffhook", 0, action_dahdidialoffhook);
19761  ast_manager_register_xml("DAHDIDNDon", 0, action_dahdidndon);
19762  ast_manager_register_xml("DAHDIDNDoff", 0, action_dahdidndoff);
19763  ast_manager_register_xml("DAHDIShowChannels", 0, action_dahdishowchannels);
19764  ast_manager_register_xml("DAHDIRestart", 0, action_dahdirestart);
19765 #if defined(HAVE_PRI)
19766  ast_manager_register_xml("PRIShowSpans", 0, action_prishowspans);
19767  ast_manager_register_xml("PRIDebugSet", 0, action_pri_debug_set);
19768  ast_manager_register_xml("PRIDebugFileSet", EVENT_FLAG_SYSTEM, action_pri_debug_file_set);
19769  ast_manager_register_xml("PRIDebugFileUnset", 0, action_pri_debug_file_unset);
19770 #endif /* defined(HAVE_PRI) */
19771 
19773 
19774  return res;
19775 }
19776 
19777 static int dahdi_sendtext(struct ast_channel *c, const char *text)
19778 {
19779 #define END_SILENCE_LEN 400
19780 #define HEADER_MS 50
19781 #define TRAILER_MS 5
19782 #define HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8)
19783 #define ASCII_BYTES_PER_CHAR 80
19784 
19785  unsigned char *buf,*mybuf;
19786  struct dahdi_pvt *p = ast_channel_tech_pvt(c);
19787  struct pollfd fds[1];
19788  int size,res,fd,len,x;
19789  int bytes=0;
19790  int idx;
19791 
19792  /*
19793  * Initial carrier (imaginary)
19794  *
19795  * Note: The following float variables are used by the
19796  * PUT_CLID_MARKMS and PUT_CLID() macros.
19797  */
19798  float cr = 1.0;
19799  float ci = 0.0;
19800  float scont = 0.0;
19801 
19802  if (!text[0]) {
19803  return(0); /* if nothing to send, don't */
19804  }
19805  idx = dahdi_get_index(c, p, 0);
19806  if (idx < 0) {
19807  ast_log(LOG_WARNING, "Huh? I don't exist?\n");
19808  return -1;
19809  }
19810  if ((!p->tdd) && (!p->mate)) {
19811 #if defined(HAVE_PRI)
19812 #if defined(HAVE_PRI_DISPLAY_TEXT)
19813  ast_mutex_lock(&p->lock);
19814  if (dahdi_sig_pri_lib_handles(p->sig)) {
19815  sig_pri_sendtext(p->sig_pvt, text);
19816  }
19817  ast_mutex_unlock(&p->lock);
19818 #endif /* defined(HAVE_PRI_DISPLAY_TEXT) */
19819 #endif /* defined(HAVE_PRI) */
19820  return(0); /* if not in TDD mode, just return */
19821  }
19822  if (p->mate)
19823  buf = ast_malloc(((strlen(text) + 1) * ASCII_BYTES_PER_CHAR) + END_SILENCE_LEN + HEADER_LEN);
19824  else
19825  buf = ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN);
19826  if (!buf)
19827  return -1;
19828  mybuf = buf;
19829  if (p->mate) {
19830  /* PUT_CLI_MARKMS is a macro and requires a format ptr called codec to be present */
19831  struct ast_format *codec = AST_LAW(p);
19832 
19833  for (x = 0; x < HEADER_MS; x++) { /* 50 ms of Mark */
19835  }
19836  /* Put actual message */
19837  for (x = 0; text[x]; x++) {
19838  PUT_CLID(text[x]);
19839  }
19840  for (x = 0; x < TRAILER_MS; x++) { /* 5 ms of Mark */
19842  }
19843  len = bytes;
19844  buf = mybuf;
19845  } else {
19846  len = tdd_generate(p->tdd, buf, text);
19847  if (len < 1) {
19848  ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text));
19849  ast_free(mybuf);
19850  return -1;
19851  }
19852  }
19853  memset(buf + len, 0x7f, END_SILENCE_LEN);
19854  len += END_SILENCE_LEN;
19855  fd = p->subs[idx].dfd;
19856  while (len) {
19857  if (ast_check_hangup(c)) {
19858  ast_free(mybuf);
19859  return -1;
19860  }
19861  size = len;
19862  if (size > READ_SIZE)
19863  size = READ_SIZE;
19864  fds[0].fd = fd;
19865  fds[0].events = POLLOUT | POLLPRI;
19866  fds[0].revents = 0;
19867  res = poll(fds, 1, -1);
19868  if (!res) {
19869  ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
19870  continue;
19871  }
19872  /* if got exception */
19873  if (fds[0].revents & POLLPRI) {
19874  ast_free(mybuf);
19875  return -1;
19876  }
19877  if (!(fds[0].revents & POLLOUT)) {
19878  ast_debug(1, "write fd not ready on channel %d\n", p->channel);
19879  continue;
19880  }
19881  res = write(fd, buf, size);
19882  if (res != size) {
19883  if (res == -1) {
19884  ast_free(mybuf);
19885  return -1;
19886  }
19887  ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
19888  break;
19889  }
19890  len -= size;
19891  buf += size;
19892  }
19893  ast_free(mybuf);
19894  return(0);
19895 }
19896 
19897 
19898 static int reload(void)
19899 {
19900  int res = 0;
19901 
19902  res = setup_dahdi(1);
19903  if (res) {
19904  ast_log(LOG_WARNING, "Reload of chan_dahdi.so is unsuccessful!\n");
19905  return -1;
19906  }
19907  return 0;
19908 }
19909 
19910 /* This is a workaround so that menuselect displays a proper description
19911  * AST_MODULE_INFO(, , "DAHDI Telephony"
19912  */
19913 
19915  .support_level = AST_MODULE_SUPPORT_CORE,
19916  .load = load_module,
19917  .unload = unload_module,
19918  .reload = reload,
19919  .load_pri = AST_MODPRI_CHANNEL_DRIVER,
19920  .requires = "ccss",
19921  .optional_modules = "res_smdi",
19922 );
static void my_set_outgoing(void *pvt, int is_outgoing)
Definition: chan_dahdi.c:1922
int cidpos
Position in the cidspill buffer to send out next.
Definition: chan_dahdi.h:552
static void publish_span_alarm(int span, const char *alarm_txt)
Definition: chan_dahdi.c:7331
void(* ast_cc_callback_fn)(struct ast_channel *chan, struct ast_cc_config_params *cc_params, const char *monitor_type, const char *const device_name, const char *const dialstring, void *private_data)
Callback made from ast_cc_callback for certain channel types.
Definition: ccss.h:1602
struct ast_party_caller * ast_channel_caller(struct ast_channel *chan)
A-Law to Signed linear conversion.
char defcontext[AST_MAX_CONTEXT]
Default distinctive ring context.
Definition: chan_dahdi.h:453
unsigned int outgoing
TRUE if we originated the call leg.
Definition: chan_dahdi.h:290
int outsigmod
Definition: chan_dahdi.h:149
static struct ast_frame * dahdi_exception(struct ast_channel *ast)
Definition: chan_dahdi.c:8403
unsigned int digital
TRUE if the transfer capability of the call is digital.
Definition: chan_dahdi.h:236
#define AST_CAUSE_PROTOCOL_ERROR
Definition: causes.h:144
static void swap_subs(struct dahdi_pvt *p, int a, int b)
Definition: chan_dahdi.c:4058
int ast_cc_agent_register(const struct ast_cc_agent_callbacks *callbacks)
Register a set of agent callbacks with the core.
Definition: ccss.c:1239
struct ast_variable * next
int dialtone_scanning_time_elapsed
Definition: chan_dahdi.h:615
int ast_safe_sleep(struct ast_channel *chan, int ms)
Wait for a specified amount of time, looking for hangups.
Definition: channel.c:1574
analog_sigtype
Definition: sig_analog.h:45
static int conf_del(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index)
Definition: chan_dahdi.c:4506
struct ringContextData ringContext[3]
Definition: chan_dahdi.h:71
unsigned long long ast_group_t
Definition: channel.h:214
#define dahdi_get_index(ast, p, nullok)
Definition: chan_dahdi.h:827
int matchdigit_timeout
Time (ms) to wait, in case of ambiguous match (in an analog phone)
Definition: chan_dahdi.h:635
static const char type[]
Definition: chan_ooh323.c:109
static void dahdi_handle_dtmf(struct ast_channel *ast, int idx, struct ast_frame **dest)
Definition: chan_dahdi.c:7231
void sig_pri_unload(void)
char description[32]
A description for the channel configuration.
Definition: chan_dahdi.h:449
Struct containing info for an AMI event to send out.
Definition: manager.h:491
enum sip_cc_notify_state state
Definition: chan_sip.c:959
#define MAX_SLAVES
Definition: chan_dahdi.h:95
struct ast_channel * sig_ss7_request(struct sig_ss7_chan *p, enum sig_ss7_law law, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, int transfercapability)
int dtmfrelax
Definition: chan_dahdi.h:665
unsigned int priexclusive
TRUE if PRI B channels are always exclusively selected.
Definition: chan_dahdi.h:311
int presentation
Q.931 encoded presentation-indicator encoded field.
Definition: channel.h:278
void ast_channel_pickupgroup_set(struct ast_channel *chan, ast_group_t value)
char cid_name[AST_MAX_EXTENSION]
Definition: sig_analog.h:314
int sig_pri_cc_monitor_unsuspend(struct ast_cc_monitor *monitor)
int nodetype
Definition: sig_pri.h:557
static struct ast_frame * dahdi_handle_event(struct ast_channel *ast)
Definition: chan_dahdi.c:7386
struct dahdi_pvt * pvt
Definition: chan_dahdi.c:10707
void sig_pri_chan_alarm_notify(struct sig_pri_chan *p, int noalarm)
char digit
static int __unload_module(void)
Definition: chan_dahdi.c:17540
void ast_set_callerid(struct ast_channel *chan, const char *cid_num, const char *cid_name, const char *cid_ani)
Set caller ID number, name and ANI and generate AMI event.
Definition: channel.c:7434
unsigned int threewaycalling
Definition: sig_analog.h:290
int faxbuf_no
Definition: chan_dahdi.h:141
int ast_matchmore_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
Looks to see if adding anything to this extension might match something. (exists ^ canmatch) ...
Definition: pbx.c:4199
#define ast_channel_lock(chan)
Definition: channel.h:2945
analog_event
Definition: sig_analog.h:79
#define DAHDI_OVERLAPDIAL_INCOMING
Definition: sig_pri.h:255
unsigned int use_callerid
Definition: sig_analog.h:293
struct ast_frame * ast_dsp_process(struct ast_channel *chan, struct ast_dsp *dsp, struct ast_frame *inf)
Return AST_FRAME_NULL frames when there is silence, AST_FRAME_BUSY on busies, and call progress...
Definition: dsp.c:1494
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:118
Main Channel structure associated with a channel.
struct ast_party_dialed::@246 number
Dialed/Called number.
static const char * my_get_orig_dialstring(void *pvt)
Definition: chan_dahdi.c:2044
#define CID_MSGWAITING
Definition: callerid.h:56
static void handle_clear_alarms(struct dahdi_pvt *p)
Definition: chan_dahdi.c:3537
Music on hold handling.
#define FORMAT
char calling_nai
Definition: sig_ss7.h:338
#define AST_CLI_DEFINE(fn, txt,...)
Definition: cli.h:197
int sig_pri_cc_agent_party_b_free(struct ast_cc_agent *agent)
ast_device_state
Device States.
Definition: devicestate.h:52
struct dahdi_dialoperation dop
DAHDI dial operation command struct for ioctl() call.
Definition: chan_dahdi.h:641
struct ast_smdi_interface * smdi_iface
The SMDI interface to get SMDI messages from.
Definition: sig_analog.h:301
static void my_unlock_private(void *pvt)
Definition: chan_dahdi.c:1728
void dahdi_dtmf_detect_disable(struct dahdi_pvt *p)
Definition: chan_dahdi.c:6473
int sig_pri_available(struct sig_pri_chan **pvt, int is_specific_channel)
char cid_subaddr[AST_MAX_EXTENSION]
Caller ID subaddress from an incoming call.
Definition: chan_dahdi.h:490
const char * type
Type of monitor the callbacks belong to.
Definition: ccss.h:583
char * str
Subscriber phone number (Malloced)
Definition: channel.h:292
#define CIDCW_EXPIRE_SAMPLES
Definition: chan_dahdi.c:681
General Asterisk channel transcoding definitions.
#define PROC_DAHDI_OPT_NOWARN
Definition: chan_dahdi.c:17863
void ast_cc_agent_unregister(const struct ast_cc_agent_callbacks *callbacks)
Unregister a set of agent callbacks with the core.
Definition: ccss.c:1254
static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen)
Definition: chan_dahdi.c:8975
static int analogsub_to_dahdisub(enum analog_sub analogsub)
Definition: chan_dahdi.c:1126
char fwd_st[SMDI_MAX_STATION_NUM_LEN+1]
Definition: smdi.h:69
int ast_streamfile(struct ast_channel *c, const char *filename, const char *preflang)
Streams a file.
Definition: file.c:1250
unsigned int permhidecallerid
TRUE if the outgoing caller ID is blocked/restricted/hidden.
Definition: chan_dahdi.h:301
unsigned int cancallforward
TRUE if support for call forwarding enabled. Dial *72 to enable call forwarding. Dial *73 to disable ...
Definition: chan_dahdi.h:214
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
unsigned int priexclusive
Definition: sig_pri.h:285
static struct ast_jb_conf default_jbconf
Definition: chan_dahdi.c:497
const char *const type
Definition: channel.h:630
Asterisk locking-related definitions:
unsigned int needflash
Definition: chan_dahdi.h:87
static int num_restart_pending
Definition: chan_dahdi.c:645
void astman_append(struct mansession *s, const char *fmt,...)
Definition: manager.c:3080
int cid_ton
Caller ID Q.931 TON/NPI field values. Set by PRI. Zero otherwise.
Definition: chan_dahdi.h:486
Asterisk main include file. File version handling, generic pbx functions.
struct ast_namedgroups * named_pickupgroups
Named pickup groups this belongs to.
Definition: chan_dahdi.h:532
int sig_pri_indicate(struct sig_pri_chan *p, struct ast_channel *chan, int condition, const void *data, size_t datalen)
static int dahdi_sig_pri_lib_handles(int signaling)
Definition: chan_dahdi.h:770
int tonezone
Definition: chan_dahdi.h:166
int sig_ss7_available(struct sig_ss7_chan *p)
void * ast_mwi_unsubscribe(struct ast_mwi_subscriber *sub)
Unsubscribe from the stasis topic and MWI.
Definition: mwi.c:249
unsigned int callwaiting
TRUE if busy extensions will hear the call-waiting tone and can use hook-flash to switch between call...
Definition: chan_dahdi.h:202
int congestion_devstate
Congestion device state of the span.
Definition: sig_pri.h:629
static void my_deadlock_avoidance_private(void *pvt)
Definition: chan_dahdi.c:1734
enum ast_transfer_result ast_bridge_transfer_attended(struct ast_channel *to_transferee, struct ast_channel *to_transfer_target)
Attended transfer.
Definition: bridge.c:4729
#define REPORT_CHANNEL_ALARMS
Definition: chan_dahdi.c:615
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
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)
Definition: chan_dahdi.c:2182
struct ast_features_pickup_config * ast_get_chan_features_pickup_config(struct ast_channel *chan)
Get the pickup configuration options for a channel.
char * str
Subscriber phone number (Malloced)
Definition: channel.h:387
char chan_name[AST_CHANNEL_NAME]
#define IS_DIGITAL(cap)
Definition: transcap.h:43
int callwaitcas
TRUE if Call Waiting (CW) CPE Alert Signal (CAS) is being sent.
Definition: chan_dahdi.h:575
static void dahdi_iflist_extract(struct dahdi_pvt *pvt)
Definition: chan_dahdi.c:5332
#define POLARITY_IDLE
Definition: chan_dahdi.c:792
static int my_on_hook(void *pvt)
Definition: chan_dahdi.c:2700
int firstdigit_timeout
Time (ms) to detect first digit (in an analog phone)
Definition: chan_dahdi.h:625
struct ast_json * ast_json_pack(char const *format,...)
Helper for creating complex JSON values.
Definition: json.c:591
static ast_mutex_t restart_lock
Definition: chan_dahdi.c:643
int sig_ss7_reset_cic(struct sig_ss7_linkset *linkset, int cic, unsigned int dpc)
static int dahdi_dial_str(struct dahdi_pvt *pvt, int operation, const char *dial_str)
Definition: chan_dahdi.c:1223
unsigned int dialing
TRUE if in the process of dialing digits or sending something.
Definition: chan_dahdi.h:234
unsigned short ast_channel_transfercapability(const struct ast_channel *chan)
#define AST_OPTION_TXGAIN
static int is_group_or_channel_match(struct dahdi_pvt *p, int span, ast_group_t groupmatch, int *groupmatched, int channelmatch, int *channelmatched)
Definition: chan_dahdi.c:13025
int ast_callerid_split(const char *src, char *name, int namelen, char *num, int numlen)
Definition: callerid.c:1092
static int drc_sample(int sample, float drc)
Definition: chan_dahdi.c:4738
struct dahdi_subchannel subs[3]
Definition: chan_dahdi.h:131
unsigned int immediate
Definition: sig_analog.h:286
unsigned int use_callingpres
Definition: sig_pri.h:288
static void monitor_pfds_clean(void *arg)
Definition: chan_dahdi.c:11477
void dahdi_master_slave_unlink(struct dahdi_pvt *slave, struct dahdi_pvt *master, int needlock)
Definition: chan_dahdi.c:6981
void sig_pri_cli_show_span(int fd, int *dchannels, struct sig_pri_span *pri)
static char * dahdi_restart_cmd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: chan_dahdi.c:15539
int presentation
Q.931 presentation-indicator and screening-indicator encoded fields.
Definition: channel.h:296
int callwaitrings
Number of call waiting rings.
Definition: chan_dahdi.h:577
void(*const lock_private)(void *pvt)
Definition: sig_ss7.h:157
void ast_cc_config_params_destroy(struct ast_cc_config_params *params)
Free memory from CCSS configuration params.
Definition: ccss.c:693
analog_tone
Definition: sig_analog.h:70
unsigned int dpc
Definition: sig_ss7.h:202
static struct ast_cli_entry dahdi_cli[]
Definition: chan_dahdi.c:16220
CallerID (and other GR30) management and generation Includes code and algorithms from the Zapata libr...
void ast_channel_set_writeformat(struct ast_channel *chan, struct ast_format *format)
void ast_variables_destroy(struct ast_variable *var)
Free variable list.
Definition: extconf.c:1263
static int my_is_off_hook(void *pvt)
Definition: chan_dahdi.c:2530
void sig_pri_cli_show_spans(int fd, int span, struct sig_pri_span *pri)
static struct ast_manager_event_blob * dahdichannel_to_ami(struct stasis_message *msg)
Definition: chan_dahdi.c:1741
Definition: ast_expr2.c:325
static int my_stop_callwait(void *pvt)
Definition: chan_dahdi.c:1499
void * analog_handle_init_event(struct analog_pvt *i, int event)
Definition: sig_analog.c:3675
int sig_ss7_indicate(struct sig_ss7_chan *p, struct ast_channel *chan, int condition, const void *data, size_t datalen)
Call Parking API.
#define SIG_FXOGS
Definition: chan_dahdi.h:735
#define ast_pthread_create_detached(a, b, c, d)
Definition: utils.h:563
static enum analog_event dahdievent_to_analogevent(int event)
Definition: chan_dahdi.c:2412
struct ast_party_id id
Connected party ID.
Definition: channel.h:459
short int16_t
Definition: db.h:59
void sig_pri_cli_show_channels(int fd, struct sig_pri_span *pri)
#define SIG_SF_FEATDMF
Definition: chan_dahdi.h:740
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Definition: clicompat.c:30
void sig_pri_cli_show_channels_header(int fd)
void ast_log_callid(int level, const char *file, int line, const char *function, ast_callid callid, const char *fmt,...)
Used for sending a log message with a known call_id This is a modified logger function which is funct...
Definition: logger.c:2149
void * ast_channel_tech_pvt(const struct ast_channel *chan)
static int dahdi_confmute(struct dahdi_pvt *p, int muted)
Definition: chan_dahdi.c:4939
static int report_alarms
Definition: chan_dahdi.c:617
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2981
static ast_mutex_t ss_thread_lock
Definition: chan_dahdi.c:642
#define SIG_PRI_DEBUG_NORMAL
Definition: sig_pri.h:41
static void * my_get_sigpvt_bridged_channel(struct ast_channel *chan)
Definition: chan_dahdi.c:1871
char parkinglot[AST_MAX_EXTENSION]
Definition: chan_dahdi.h:471
int cid_signalling
Definition: chan_dahdi.h:541
unsigned int callwaitingcallerid
TRUE if send caller ID for Call Waiting.
Definition: chan_dahdi.h:207
static int dtmfcid_level
Definition: chan_dahdi.c:613
#define AST_CAUSE_SWITCH_CONGESTION
Definition: causes.h:122
struct ast_variable * ast_variable_browse(const struct ast_config *config, const char *category_name)
Definition: extconf.c:1216
void sig_ss7_cli_show_channels(int fd, struct sig_ss7_linkset *linkset)
Device state management.
unsigned int priindication_oob
Definition: sig_pri.h:286
unsigned int use_callerid
Definition: sig_pri.h:287
static int analog_tone_to_dahditone(enum analog_tone tone)
Definition: chan_dahdi.c:1106
#define HEADER_MS
unsigned int hidecallerid
TRUE if the outgoing caller ID is blocked/hidden.
Definition: sig_ss7.h:213
struct dahdi_pvt * next
Definition: chan_dahdi.h:168
unsigned int hardwaredtmf
TRUE if DTMF detection needs to be done by hardware.
Definition: chan_dahdi.h:263
static int digit_to_dtmfindex(char digit)
Definition: chan_dahdi.c:4221
char idleext[AST_MAX_EXTENSION]
Definition: sig_pri.h:552
void ast_json_unref(struct ast_json *value)
Decrease refcount on value. If refcount reaches zero, value is freed.
Definition: json.c:73
struct ast_party_name name
Subscriber name.
Definition: channel.h:341
#define DSP_DIGITMODE_DTMF
Definition: dsp.h:31
char * address
Definition: f2c.h:59
void ast_channel_unregister(const struct ast_channel_tech *tech)
Unregister a channel technology.
Definition: channel.c:570
struct ast_party_id from
Who is redirecting the call (Sent to the party the call is redirected toward)
Definition: channel.h:528
int interdigit_timeout
Time (ms) to detect following digits (in an analog phone)
Definition: chan_dahdi.h:630
void ast_dsp_free(struct ast_dsp *dsp)
Definition: dsp.c:1770
int ast_dsp_get_tcount(struct ast_dsp *dsp)
Get tcount (Threshold counter)
Definition: dsp.c:1903
#define DSP_FEATURE_DIGIT_DETECT
Definition: dsp.h:28
int analog_hangup(struct analog_pvt *p, struct ast_channel *ast)
Definition: sig_analog.c:1251
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
#define AST_CAUSE_UNALLOCATED
Definition: causes.h:97
static int dahdi_analog_lib_handles(int signalling, int radio, int oprmode)
Definition: chan_dahdi.h:786
static void parse_busy_pattern(struct ast_variable *v, struct ast_dsp_busy_pattern *busy_cadence)
Definition: chan_dahdi.c:17865
void ast_channel_hangupcause_set(struct ast_channel *chan, int value)
void dahdi_ec_enable(struct dahdi_pvt *p)
Definition: chan_dahdi.c:4638
struct ast_json * blob
void pri_event_alarm(struct sig_pri_span *pri, int index, int before_start_pri)
int cid_start
Definition: chan_dahdi.h:542
unsigned int needanswer
Definition: chan_dahdi.h:86
static struct ast_channel_tech dahdi_tech
Definition: chan_dahdi.c:1030
#define CID_SIG_SMDI
Definition: callerid.h:63
struct stasis_cache * ast_mwi_state_cache(void)
Backend cache for ast_mwi_topic_cached().
Definition: mwi.c:90
static void my_set_pulsedial(void *pvt, int flag)
Definition: chan_dahdi.c:2031
char unknownprefix[20]
Definition: sig_ss7.h:342
int ringt
Ring timeout timer??
Definition: chan_dahdi.h:556
#define STASIS_MESSAGE_TYPE_INIT(name)
Boiler-plate messaging macro for initializing message types.
Definition: stasis.h:1501
static struct ast_frame * dahdi_read(struct ast_channel *ast)
Definition: chan_dahdi.c:8418
int ast_queue_unhold(struct ast_channel *chan)
Queue an unhold frame.
Definition: channel.c:1216
char mohsuggest[MAX_MUSICCLASS]
Definition: sig_analog.h:312
char dnid[AST_MAX_EXTENSION]
Dialed Number Identifier.
Definition: chan_dahdi.h:500
struct ast_channel_snapshot * snapshot
Convenient Signal Processing routines.
unsigned int firstradio
TRUE if over a radio and dahdi_read() has been called.
Definition: chan_dahdi.h:256
#define CALLWAITING_SUPPRESS_SAMPLES
Definition: chan_dahdi.c:680
int sig_pri_cc_agent_stop_offer_timer(struct ast_cc_agent *agent)
enum sig_ss7_linkset::@164 state
static int my_start_cid_detect(void *pvt, int cid_signalling)
Definition: chan_dahdi.c:1269
#define AST_CAUSE_NETWORK_OUT_OF_ORDER
Definition: causes.h:120
int pattern[4]
Definition: dsp.h:68
void ast_channel_set_rawwriteformat(struct ast_channel *chan, struct ast_format *format)
static void my_start_polarityswitch(void *pvt)
Definition: chan_dahdi.c:2612
#define DSP_DIGITMODE_MF
Definition: dsp.h:32
#define ast_set_flag(p, flag)
Definition: utils.h:70
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the &#39;standard&#39; argument separation process for an application.
#define SUB_THREEWAY
Definition: chan_dahdi.h:59
#define DSP_DIGITMODE_MUTECONF
Definition: dsp.h:35
static struct dahdi_chan_conf dahdi_chan_conf_default(void)
Definition: chan_dahdi.c:869
static int parse_buffers_policy(const char *parse, int *num_buffers, int *policy)
Definition: chan_dahdi.c:6878
Call Pickup API.
void astman_send_list_complete_start(struct mansession *s, const struct message *m, const char *event_name, int count)
Start the list complete event.
Definition: manager.c:3237
struct ast_format * ast_format_ulaw
Built-in cached ulaw format.
Definition: format_cache.c:86
int echotraining
Definition: sig_analog.h:307
#define TDD_BYTES_PER_CHAR
Definition: tdd.h:27
int ringt_base
Definition: sig_analog.h:357
#define DEADLOCK_AVOIDANCE(lock)
Definition: lock.h:374
char calling_st[SMDI_MAX_STATION_NUM_LEN+1]
Definition: smdi.h:70
struct dahdi_pvt * master
Definition: chan_dahdi.h:135
static const char tdesc[]
Definition: chan_dahdi.c:527
int ast_cc_is_config_param(const char *const name)
Is this a CCSS configuration parameter?
Definition: ccss.c:846
descriptor for a cli entry.
Definition: cli.h:171
const int argc
Definition: cli.h:160
static sqlite3 * db
#define AST_OPTION_OPRMODE
Interface header for PRI signaling module.
#define LOG_WARNING
Definition: logger.h:274
enum ast_pbx_result ast_pbx_start(struct ast_channel *c)
Create a new thread and start the PBX.
Definition: pbx.c:4712
#define ASCII_BYTES_PER_CHAR
static int ast_fdisset(struct pollfd *pfds, int fd, int maximum, int *start)
Helper function for migrating select to poll.
Definition: channel.h:2850
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
struct ast_mwi_subscriber * mwi_event_sub
Opaque event subscription parameters for message waiting indication support.
Definition: chan_dahdi.h:656
char * name
Definition: chan_dahdi.c:4361
void ast_callid_threadstorage_auto_clean(ast_callid callid, int callid_created)
Use in conjunction with ast_callid_threadstorage_auto. Cleans up the references and if the callid was...
Definition: logger.c:2042
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:714
static void * analog_ss_thread(void *data)
Definition: chan_dahdi.c:9512
unsigned int locallyblocked
Bitmask for the channel being locally blocked.
Definition: chan_dahdi.h:404
#define AST_ALAW(a)
Definition: alaw.h:84
static int muted
Definition: muted.c:82
static int debug
Global debug status.
Definition: res_xmpp.c:435
AST_JSON_INT_T ast_json_int_t
Primarily used to cast when packing to an "I" type.
Definition: json.h:87
static int my_play_tone(void *pvt, enum analog_sub sub, enum analog_tone tone)
Definition: chan_dahdi.c:2402
static void my_set_callwaiting(void *pvt, int callwaiting_enable)
Definition: chan_dahdi.c:2009
int sig_pri_cc_monitor_req_cc(struct ast_cc_monitor *monitor, int *available_timer_id)
q931_call * call
Definition: sig_pri.h:358
static int usedistinctiveringdetection
Definition: chan_dahdi.c:607
#define DSP_PROGRESS_TALK
Definition: dsp.h:39
char callwait_name[AST_MAX_EXTENSION]
Call waiting name.
Definition: chan_dahdi.h:496
float txdrc
Definition: chan_dahdi.h:163
int ast_party_id_presentation(const struct ast_party_id *id)
Determine the overall presentation value for the given party.
Definition: channel.c:1821
int ast_jb_read_conf(struct ast_jb_conf *conf, const char *varname, const char *value)
Sets jitterbuffer configuration property.
Definition: abstract_jb.c:545
#define CONFIG_STATUS_FILEINVALID
Native DAHDI bridging support.
#define DSP_FEATURE_CALL_PROGRESS
Definition: dsp.h:43
struct ast_dsp * ast_dsp_new(void)
Allocates a new dsp, assumes 8khz for internal sample rate.
Definition: dsp.c:1745
unsigned int inservice
TRUE if channel is out of reset and ready.
Definition: chan_dahdi.h:395
#define SIG_EM
Definition: chan_dahdi.h:722
static int my_is_dialing(void *pvt, enum analog_sub sub)
Definition: chan_dahdi.c:2684
struct ast_channel * owner
Definition: chan_dahdi.h:127
struct ast_smdi_interface * ast_smdi_interface_find(const char *iface_name)
Find an SMDI interface with the specified name.
Definition: res_smdi.c:563
#define LINKSET_FLAG_INITIALHWBLO
Definition: sig_ss7.h:69
static int my_set_echocanceller(void *pvt, int enable)
Definition: chan_dahdi.c:2559
static int timeout
Definition: cdr_mysql.c:86
int sig_pri_cc_monitor_suspend(struct ast_cc_monitor *monitor)
static int tmp()
Definition: bt_open.c:389
#define DSP_TONE_STATE_DIALTONE
Definition: dsp.h:54
static struct ast_frame * __dahdi_exception(struct ast_channel *ast)
Definition: chan_dahdi.c:8281
int channel
Definition: sig_ss7.h:200
#define NUM_CADENCE_MAX
Definition: chan_dahdi.c:563
static struct dahdi_pvt * determine_starting_point(const char *data, struct dahdi_starting_point *param)
Definition: chan_dahdi.c:13330
#define LINKSET_FLAG_USEECHOCONTROL
Definition: sig_ss7.h:70
unsigned int callreturn
Definition: sig_analog.h:281
static ast_cond_t ss_thread_complete
Definition: chan_dahdi.c:641
Structure for variables, used for configurations and for channel variables.
static int my_allocate_sub(void *pvt, enum analog_sub analogsub)
Definition: chan_dahdi.c:2386
static void release_doomed_pris(void)
Definition: chan_dahdi.c:1156
int buf_no
Definition: chan_dahdi.h:139
int dsp_features
DSP feature flags: DSP_FEATURE_xxx.
Definition: chan_dahdi.h:683
mwisend_states mwisend_current
Definition: chan_dahdi.h:112
unsigned int dahditrcallerid
TRUE if we should use the callerid from incoming call on dahdi transfer.
Definition: chan_dahdi.h:365
struct ast_channel * owner
Definition: sig_analog.h:257
static int my_flash(void *pvt)
Definition: chan_dahdi.c:2580
unsigned int dnd
TRUE if Do-Not-Disturb is enabled, present only for non sig_analog.
Definition: chan_dahdi.h:238
unsigned int usefaxbuffers
Definition: chan_dahdi.h:252
int law_default
Default call PCM encoding format: DAHDI_LAW_ALAW or DAHDI_LAW_MULAW.
Definition: chan_dahdi.h:507
struct ast_frame * ast_read(struct ast_channel *chan)
Reads a frame.
Definition: channel.c:4302
static int my_dahdi_write(struct dahdi_pvt *p, unsigned char *buf, int len, int idx, int linear)
Definition: chan_dahdi.c:8872
int minidle
Definition: sig_pri.h:556
#define STASIS_MESSAGE_TYPE_CLEANUP(name)
Boiler-plate messaging macro for cleaning up message types.
Definition: stasis.h:1523
struct analog_callback analog_callbacks
Definition: chan_dahdi.c:3355
#define EVENT_FLAG_CALL
Definition: manager.h:72
void ast_dsp_digitreset(struct ast_dsp *dsp)
Reset DTMF detector.
Definition: dsp.c:1797
Definition: cli.h:152
int ast_dsp_was_muted(struct ast_dsp *dsp)
Returns true if DSP code was muting any fragment of the last processed frame. Muting (squelching) hap...
Definition: dsp.c:1893
static void destroy_channel(struct dahdi_pvt *cur, int now)
Definition: chan_dahdi.c:5649
int ast_callerid_callwaiting_generate(unsigned char *buf, const char *name, const char *number, struct ast_format *codec)
Generate Caller-ID spill but in a format suitable for Call Waiting(tm)&#39;s Caller*ID(tm) ...
Definition: callerid.c:1068
#define CID_START_POLARITY
Definition: callerid.h:66
unsigned int immediate
TRUE if the channel should be answered immediately without attempting to gather any digits...
Definition: chan_dahdi.h:284
#define SMDI_MAX_FILENAME_LEN
Definition: smdi.h:42
Structure to pass both assignedid values to channel drivers.
Definition: channel.h:605
static int dahdi_func_write(struct ast_channel *chan, const char *function, char *data, const char *value)
Definition: chan_dahdi.c:6907
Interface header for SS7 signaling module.
static int dahdi_call(struct ast_channel *ast, const char *rdest, int timeout)
Definition: chan_dahdi.c:5121
int ast_ignore_pattern(const char *context, const char *pattern)
Checks to see if a number should be ignored.
Definition: pbx.c:6921
int cid_signalling
Definition: sig_analog.h:308
void ast_channel_callgroup_set(struct ast_channel *chan, ast_group_t value)
#define SIG_FXOKS
Definition: chan_dahdi.h:736
#define HEADER_LEN
ast_channel_state
ast_channel states
Definition: channelstate.h:35
static char * alarm2str(int alm)
Definition: chan_dahdi.c:4372
#define SIG_FEATB
Definition: chan_dahdi.h:726
void analog_handle_dtmf(struct analog_pvt *p, struct ast_channel *ast, enum analog_sub idx, struct ast_frame **dest)
Definition: sig_analog.c:1564
void * sig_pvt
Definition: chan_dahdi.h:709
char * str
Subscriber name (Malloced)
Definition: channel.h:265
static void my_hangup_polarityswitch(void *pvt)
Definition: chan_dahdi.c:2632
static int dahdi_wink(struct dahdi_pvt *p, int index)
Definition: chan_dahdi.c:9419
float cid_rxgain
Amount of gain to increase during caller id.
Definition: chan_dahdi.h:157
Definition: astman.c:222
#define ANALOG_MATCH_DIGIT_TIMEOUT
Default time (ms) to wait, in case of ambiguous match.
Definition: sig_analog.h:42
enum sig_pri_reset_state resetting
Channel reset/restart state.
Definition: sig_pri.h:363
#define CHAN_PSEUDO
Definition: chan_dahdi.c:556
int callingpres
Definition: chan_dahdi.h:545
Definition of a media format.
Definition: format.c:43
#define TRAILER_MS
#define DAHDI_OVERLAPDIAL_OUTGOING
Definition: sig_pri.h:254
#define ast_cond_wait(cond, mutex)
Definition: lock.h:203
static int my_get_callerid(void *pvt, char *namebuf, char *numbuf, enum analog_event *ev, size_t timeout)
Definition: chan_dahdi.c:1302
static struct @109 alarms[]
#define SIG_BRI_PTMP
Definition: chan_dahdi.h:747
struct ast_dsp_busy_pattern busy_cadence
Busy cadence pattern description.
Definition: chan_dahdi.h:599
#define ast_cond_init(cond, attr)
Definition: lock.h:199
static int unalloc_sub(struct dahdi_pvt *p, int x)
Definition: chan_dahdi.c:4204
#define ast_cli_register_multiple(e, len)
Register multiple commands.
Definition: cli.h:265
void ast_channel_named_pickupgroups_set(struct ast_channel *chan, struct ast_namedgroups *value)
static void dahdi_iflist_insert(struct dahdi_pvt *pvt)
Definition: chan_dahdi.c:5282
int bufsize
Definition: chan_dahdi.h:138
unsigned char valid
TRUE if the subaddress information is valid/present.
Definition: channel.h:329
unsigned int no_b_channel
TRUE if this interface has no B channel. (call hold and call waiting)
Definition: sig_pri.h:345
static void dahdi_destroy_channel_range(int start, int end)
Definition: chan_dahdi.c:11068
unsigned int inalarm
TRUE if channel is associated with a link that is down.
Definition: sig_ss7.h:288
#define CID_SIG_BELL
Definition: callerid.h:59
unsigned int transfertobusy
TRUE if allowed to flash-transfer to busy channels.
Definition: chan_dahdi.h:370
int ast_parking_blind_transfer_park(struct ast_bridge_channel *parker, const char *context, const char *exten, transfer_channel_cb parked_channel_cb, struct transfer_channel_data *parked_channel_data)
Perform a blind transfer to a parking extension.
Definition: parking.c:143
static int my_wait_event(void *pvt)
Definition: chan_dahdi.c:2509
#define AST_OPTION_CC_AGENT_TYPE
The channel is not being RESTARTed.
Definition: sig_pri.h:154
static int copy(char *infile, char *outfile)
Utility function to copy a file.
static int my_have_progressdetect(void *pvt)
Definition: chan_dahdi.c:3329
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:150
#define CANBUSYDETECT(p)
Definition: chan_dahdi.c:593
unsigned int usedistinctiveringdetection
Definition: sig_analog.h:294
int sig_pri_ami_show_spans(struct mansession *s, const char *show_cmd, struct sig_pri_span *pri, const int *dchannels, const char *action_id)
unsigned int ast_callid
Definition: logger.h:87
static int my_conf_add(void *pvt, enum analog_sub sub)
Definition: chan_dahdi.c:2116
#define COLOR_GREEN
Definition: term.h:51
int ast_channel_get_up_time(struct ast_channel *chan)
Obtain how long it has been since the channel was answered.
Definition: channel.c:2854
#define SIG_FEATDMF_TA
Definition: chan_dahdi.h:728
unsigned int transfertobusy
Definition: sig_analog.h:292
void dahdi_ec_disable(struct dahdi_pvt *p)
Definition: chan_dahdi.c:4710
static int my_get_sub_fd(void *pvt, enum analog_sub sub)
Definition: chan_dahdi.c:1885
static int calc_energy(const unsigned char *buf, int len, struct ast_format *law)
Definition: chan_dahdi.c:10712
#define AST_LIST_EMPTY(head)
Checks whether the specified list contains any entries.
Definition: linkedlists.h:449
static int attempt_transfer(struct dahdi_pvt *p)
Definition: chan_dahdi.c:7145
#define ast_assert(a)
Definition: utils.h:695
#define RING_PATTERNS
Definition: sig_analog.h:35
#define CID_MWI_TYPE_MDMF_FULL
Definition: callerid.h:76
void astman_send_ack(struct mansession *s, const struct message *m, char *msg)
Send ack in manager transaction.
Definition: manager.c:3191
#define ast_mutex_lock(a)
Definition: lock.h:187
int whichwink
Definition: chan_dahdi.h:642
int dialplan
Definition: sig_pri.h:506
char * origcid_num
Definition: chan_dahdi.h:491
static struct test_val c
int ast_channel_register(const struct ast_channel_tech *tech)
Register a channel technology (a new channel driver) Called by a channel module to register the kind ...
Definition: channel.c:539
Definition: muted.c:95
char * text
Definition: app_queue.c:1508
static int conf_add(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index, int slavechannel)
Definition: chan_dahdi.c:4457
const char * ast_format_get_name(const struct ast_format *format)
Get the name associated with a format.
Definition: format.c:334
int64_t ast_tvdiff_ms(struct timeval end, struct timeval start)
Computes the difference (in milliseconds) between two struct timeval instances.
Definition: time.h:98
void ast_verbose(const char *fmt,...)
Definition: extconf.c:2207
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:243
static int setup_dahdi(int reload)
Definition: chan_dahdi.c:19642
void sig_ss7_cb_notinservice(struct ss7 *ss7, int cic, unsigned int dpc)
#define AST_OPTION_TDD
DAHDI internal API definitions.
static char * dahdi_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: chan_dahdi.c:15572
const char * str
Definition: app_jack.c:147
Generic File Format Support. Should be included by clients of the file handling routines. File service providers should instead include mod_format.h.
static int alloc_sub(struct dahdi_pvt *p, int x)
Definition: chan_dahdi.c:4167
int switchtype
Definition: sig_pri.h:558
static void * mwi_thread(void *data)
Definition: chan_dahdi.c:10726
char * ast_category_browse(struct ast_config *config, const char *prev_name)
Browse categories.
Definition: extconf.c:3328
unsigned int inalarm
Definition: sig_pri.h:326
#define SIG_PRI_AOC_GRANT_S
Definition: sig_pri.h:53
#define CALLPROGRESS_PROGRESS
Definition: chan_dahdi.c:558
const char * args
#define CID_START_POLARITY_IN
Definition: callerid.h:67
int law
Active PCM encoding format: DAHDI_LAW_ALAW or DAHDI_LAW_MULAW.
Definition: chan_dahdi.h:509
static int my_wink(void *pvt, enum analog_sub sub)
Definition: chan_dahdi.c:1632
char * str
Malloced subaddress string.
Definition: channel.h:314
static int ifcount
Definition: chan_dahdi.c:628
#define NULL
Definition: resample.c:96
int callwaitingrepeat
Definition: chan_dahdi.h:546
const char * data
#define AST_CAUSE_NO_USER_RESPONSE
Definition: causes.h:107
static struct dahdi_pvt * find_channel_from_str(const char *channel)
Definition: chan_dahdi.c:16276
void dahdi_conf_update(struct dahdi_pvt *p)
Definition: chan_dahdi.c:4583
static int isourconf(struct dahdi_pvt *p, struct dahdi_subchannel *c)
Definition: chan_dahdi.c:4495
static void dahdi_close_sub(struct dahdi_pvt *chan_pvt, int sub_num)
Definition: chan_dahdi.c:4139
char * end
Definition: eagi_proxy.c:73
unsigned int adsi
TRUE if ADSI (Analog Display Services Interface) available.
Definition: chan_dahdi.h:177
#define AST_CAUSE_NORMAL_CIRCUIT_CONGESTION
Definition: causes.h:119
Common implementation-independent jitterbuffer stuff.
int value
Definition: syslog.c:37
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
static const char config[]
Definition: chan_dahdi.c:548
ast_transfer_result
Definition: bridge.h:1115
#define ast_cc_config_params_init()
Allocate and initialize an ast_cc_config_params structure.
Definition: ccss.h:135
ADSI Support (built upon Caller*ID)
#define AST_LIST_REMOVE(head, elm, field)
Removes a specific entry from a list.
Definition: linkedlists.h:855
int sig_ss7_cic_blocking(struct sig_ss7_linkset *linkset, int do_block, int cic)
struct ast_frame f
Definition: chan_dahdi.h:82
#define AST_FRAME_DTMF
int ast_channel_setoption(struct ast_channel *channel, int option, void *data, int datalen, int block)
Sets an option on a channel.
Definition: channel.c:7522
unsigned int restartpending
Definition: chan_dahdi.h:319
static int action_dahdidndon(struct mansession *s, const struct message *m)
Definition: chan_dahdi.c:16288
static char * dahdi_set_hwgain(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: chan_dahdi.c:16006
void * chan_pvt
Definition: sig_pri.h:376
const char * ext
Definition: http.c:147
struct dahdi_pvt * oprpeer
Definition: chan_dahdi.h:151
int ast_unregister_application(const char *app)
Unregister an application.
Definition: pbx_app.c:392
int ringt_base
Ring timeout base.
Definition: chan_dahdi.h:561
#define AST_FILE_MODE
Definition: asterisk.h:32
struct timeval pause
Definition: chan_dahdi.h:111
void ast_moh_stop(struct ast_channel *chan)
Turn off music on hold on a given channel.
Definition: channel.c:7876
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
Definition: linkedlists.h:614
float txgain
Software Tx gain set by chan_dahdi.conf.
Definition: chan_dahdi.h:161
static char cid_num[AST_MAX_EXTENSION]
Definition: chan_mgcp.c:164
#define ast_cond_signal(cond)
Definition: lock.h:201
static struct dahdi_pvt * ifend
Definition: chan_dahdi.c:802
int polarityonanswerdelay
Definition: sig_analog.h:309
struct timeval dtmfcid_delay
Definition: chan_dahdi.h:544
#define SS7_BLOCKED_HARDWARE
Definition: sig_ss7.h:75
unsigned int hidecalleridname
TRUE if hide just the name not the number for legacy PBX use.
Definition: chan_dahdi.h:276
int analog_fixup(struct ast_channel *oldchan, struct ast_channel *newchan, void *newp)
Definition: sig_analog.c:3981
int inconference
Definition: chan_dahdi.h:136
static struct dahdi_ring_cadence AS_RP_cadence
Definition: chan_dahdi.c:588
#define SS7_NAI_DYNAMIC
Definition: sig_ss7.h:66
#define ast_verb(level,...)
Definition: logger.h:463
#define DAHDI_OVERLAPDIAL_NONE
Definition: sig_pri.h:253
struct ast_smdi_md_message * ast_smdi_md_message_wait(struct ast_smdi_interface *iface, int timeout)
Get the next SMDI message from the queue.
Definition: res_smdi.c:539
unsigned int needhold
Definition: chan_dahdi.h:88
#define REPORT_SPAN_ALARMS
Definition: chan_dahdi.c:616
struct ast_manager_event_blob * ast_manager_event_blob_create(int event_flags, const char *manager_event, const char *extra_fields_fmt,...)
Construct a ast_manager_event_blob.
Definition: manager.c:9727
static char defaultozz[64]
Definition: chan_dahdi.c:597
void sig_pri_extract_called_num_subaddr(struct sig_pri_chan *p, const char *rdest, char *called, size_t called_buff_size)
int ast_atomic_fetchadd_int(volatile int *p, int v)
Atomically add v to *p and return the previous value of *p.
Definition: lock.h:755
#define MAX_CALLERID_SIZE
Definition: callerid.h:50
const char * line
Definition: cli.h:162
const char *const subnames[]
Definition: chan_dahdi.c:795
static const char *const lbostr[]
Definition: chan_dahdi.c:484
static int mwilevel
Definition: chan_dahdi.c:612
int ast_canmatch_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
Looks for a valid matching extension.
Definition: pbx.c:4194
static char * dahdi_show_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: chan_dahdi.c:15650
#define ast_publish_mwi_state(mailbox, context, new_msgs, old_msgs)
Publish a MWI state update via stasis.
Definition: mwi.h:380
static void my_increase_ss_count(void)
Definition: chan_dahdi.c:2051
const char * pbx_builtin_getvar_helper(struct ast_channel *chan, const char *name)
Return a pointer to the value of the corresponding channel variable.
void callerid_get(struct callerid_state *cid, char **number, char **name, int *flags)
Extract info out of callerID state machine. Flags are listed above.
Definition: callerid.c:188
struct ast_frame_subclass subclass
unsigned int use_smdi
TRUE if SMDI (Simplified Message Desk Interface) is enabled.
Definition: sig_analog.h:299
#define SIG_SF
Definition: chan_dahdi.h:737
struct analog_pvt * analog_new(enum analog_sigtype signallingtype, void *private_data)
Definition: sig_analog.c:3928
static int mute
Definition: chan_alsa.c:144
unsigned int pulse
TRUE if we will pulse dial.
Definition: chan_dahdi.h:316
static int dahdi_callwait(struct ast_channel *ast)
Definition: chan_dahdi.c:5087
ast_mutex_t lock
Definition: sig_pri.h:618
char * bs
Definition: eagi_proxy.c:73
int sig_ss7_reset_group(struct sig_ss7_linkset *linkset, int cic, unsigned int dpc, int range)
static void dahdi_queue_frame(struct dahdi_pvt *p, struct ast_frame *f)
Definition: chan_dahdi.c:3490
int oprmode
Definition: chan_dahdi.h:150
Utility functions.
int(*const play_tone)(void *pvt, enum analog_sub sub, enum analog_tone tone)
Definition: sig_analog.h:175
#define ast_asprintf(ret, fmt,...)
A wrapper for asprintf()
Definition: astmm.h:269
int ast_queue_hangup_with_cause(struct ast_channel *chan, int cause)
Queue a hangup frame with hangupcause set.
Definition: channel.c:1166
Blob of data associated with a channel.
unsigned int cancallforward
Definition: sig_analog.h:282
threshold
Definition: dsp.h:71
const char * astman_get_header(const struct message *m, char *var)
Get header from mananger transaction.
Definition: manager.c:2820
int sig_pri_hangup(struct sig_pri_chan *p, struct ast_channel *ast)
#define ast_module_unref(mod)
Release a reference to the module.
Definition: module.h:469
static void my_set_needringing(void *pvt, int value)
Definition: chan_dahdi.c:2595
pthread_cond_t ast_cond_t
Definition: lock.h:176
#define ast_strlen_zero(foo)
Definition: strings.h:52
enum ast_cc_monitor_policies ast_get_cc_monitor_policy(struct ast_cc_config_params *config)
Get the cc_monitor_policy.
Definition: ccss.c:883
ast_group_t pickupgroup
Bitmapped pickup groups this belongs to.
Definition: chan_dahdi.h:522
static void my_decrease_ss_count(void)
Definition: chan_dahdi.c:2058
char cid_name[AST_MAX_EXTENSION]
Caller ID name from an incoming call.
Definition: chan_dahdi.h:488
int pri_send_keypad_facility_exec(struct sig_pri_chan *p, const char *digits)
struct ast_channel * owner
Definition: sig_analog.h:270
char finaldial[64]
Second part of SIG_FEATDMF_TA wink operation.
Definition: chan_dahdi.h:644
#define ast_pthread_create_background(a, b, c, d)
Definition: utils.h:567
void ast_dsp_set_busy_count(struct ast_dsp *dsp, int cadences)
Set number of required cadences for busy.
Definition: dsp.c:1780
static void fill_rxgain(struct dahdi_gains *g, float gain, float drc, int law)
Definition: chan_dahdi.c:4808
void ast_channel_tech_set(struct ast_channel *chan, const struct ast_channel_tech *value)
#define TRANSFER
Definition: chan_dahdi.c:16234
static void my_get_and_handle_alarms(void *pvt)
Definition: chan_dahdi.c:1862
#define DAHDI_CHAN_MAPPING_PHYSICAL
Definition: sig_pri.h:249
unsigned int hwtxgain_enabled
TRUE if hardware Tx gain set by Asterisk.
Definition: chan_dahdi.h:422
struct dahdi_params timing
Definition: chan_dahdi.c:844
unsigned int use_callingpres
TRUE if we will use the calling presentation setting from the Asterisk channel for outgoing calls...
Definition: sig_ss7.h:220
struct ss7 * ss7
Definition: sig_ss7.h:321
Number structure.
Definition: app_followme.c:154
static int my_conf_del(void *pvt, enum analog_sub sub)
Definition: chan_dahdi.c:2106
static int mwisend_rpas
Definition: chan_dahdi.c:602
int _dahdi_get_index(struct ast_channel *ast, struct dahdi_pvt *p, int nullok, const char *fname, unsigned long line)
Definition: chan_dahdi.c:3431
enum ama_flags ast_channel_string2amaflag(const char *flag)
Convert a string to a detail record AMA flag.
Definition: channel.c:4405
static int set_hwgain(int fd, float gain, int tx_direction)
Definition: chan_dahdi.c:4728
static void wakeup_sub(struct dahdi_pvt *p, int a)
Definition: chan_dahdi.c:3481
int callerid_feed_jp(struct callerid_state *cid, unsigned char *ubuf, int samples, struct ast_format *codec)
Read samples into the state machine.
Definition: callerid.c:306
#define ANALOG_MAX_CID
Definition: sig_analog.h:33
#define SIG_EMWINK
Definition: chan_dahdi.h:723
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
Definition: strings.h:1065
static int dahdi_wait_event(int fd)
Avoid the silly dahdi_waitevent which ignores a bunch of events.
Definition: chan_dahdi.c:661
struct ast_party_id id
Caller party ID.
Definition: channel.h:421
static char progzone[10]
Definition: chan_dahdi.c:605
#define CALLPROGRESS_FAX_OUTGOING
Definition: chan_dahdi.c:559
void sig_pri_init_pri(struct sig_pri_span *pri)
unsigned int remotelyblocked
Bitmask for the channel being remotely blocked.
Definition: sig_ss7.h:235
int ast_cc_monitor_register(const struct ast_cc_monitor_callbacks *callbacks)
Register a set of monitor callbacks with the core.
Definition: ccss.c:1184
static void handle_alarms(struct dahdi_pvt *p, int alms)
Definition: chan_dahdi.c:7364
static enum analog_sigtype dahdisig_to_analogsig(int sig)
Definition: chan_dahdi.c:1055
unsigned int answeronpolarityswitch
TRUE if we can use a polarity reversal to mark when an outgoing call is answered by the remote party...
Definition: chan_dahdi.h:183
int stripmsd
Definition: sig_analog.h:310
Configuration File Parser.
static void destroy_all_channels(void)
Definition: chan_dahdi.c:5667
#define NEED_MFDETECT(p)
Signaling types that need to use MF detection should be placed in this macro.
Definition: chan_dahdi.c:525
int dahdi_native_load(const struct ast_channel_tech *tech)
#define DSP_DIGITMODE_RELAXDTMF
Definition: dsp.h:37
enum analog_sigtype sigtype
Definition: sig_analog.c:69
ast_mutex_t lock
Definition: sig_ss7.h:320
static char mailbox[AST_MAX_MAILBOX_UNIQUEID]
Definition: chan_mgcp.c:204
static int restart_monitor(void)
Definition: chan_dahdi.c:11770
char context[AST_MAX_CONTEXT]
Definition: sig_ss7.h:237
static int has_voicemail(struct dahdi_pvt *p)
Definition: chan_dahdi.c:5033
int dtmfcid_holdoff_state
Definition: chan_dahdi.h:543
#define SIG_FGC_CAMAMF
Definition: chan_dahdi.h:730
#define EVENT_FLAG_SYSTEM
Definition: manager.h:71
unsigned int didtdd
Definition: chan_dahdi.h:227
unsigned int bufferoverrideinuse
Definition: chan_dahdi.h:254
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
static ast_mutex_t monlock
Protect the monitoring thread, so only one process can kill or start it, and not when it&#39;s doing some...
Definition: chan_dahdi.c:636
#define ast_log
Definition: astobj2.c:42
char smdi_port[SMDI_MAX_FILENAME_LEN]
The serial port to listen for SMDI data on.
Definition: chan_dahdi.c:853
int polarity
Current line interface polarity. POLARITY_IDLE, POLARITY_REV.
Definition: chan_dahdi.h:681
unsigned int hanguponpolarityswitch
TRUE if the call will be considered "hung up" on a polarity reversal.
Definition: chan_dahdi.h:261
static int user_has_defined_cadences
Definition: chan_dahdi.c:565
unsigned int callreturn
TRUE if call return is enabled. (*69, if your dialplan doesn&#39;t catch this first)
Definition: chan_dahdi.h:195
void ast_channel_set_rawreadformat(struct ast_channel *chan, struct ast_format *format)
int sig_pri_cc_monitor_cancel_available_timer(struct ast_cc_monitor *monitor, int *sched_id)
u-Law to Signed linear conversion
#define ISTRUNK(p)
Definition: chan_dahdi.c:590
unsigned int transfer
TRUE if call transfer is enabled.
Definition: chan_dahdi.h:339
#define ast_config_load(filename, flags)
Load a config file.
unsigned int use_callerid
TRUE if caller ID is used on this channel.
Definition: sig_ss7.h:215
static int dahdi_devicestate(const char *data)
Definition: chan_dahdi.c:13667
static int my_stop_cid_detect(void *pvt)
Definition: chan_dahdi.c:1286
#define SIG_BRI
Definition: chan_dahdi.h:746
enum ast_format_cmp_res ast_format_cmp(const struct ast_format *format1, const struct ast_format *format2)
Compare two formats.
Definition: format.c:201
unsigned int echobreak
XXX BOOLEAN Purpose???
Definition: chan_dahdi.h:240
static int dahdi_dnd(struct dahdi_pvt *dahdichan, int flag)
enable or disable the chan_dahdi Do-Not-Disturb mode for a DAHDI channel
Definition: chan_dahdi.c:9466
struct ast_cc_config_params * cc_params
Definition: chan_dahdi.h:710
Definition: logger.c:165
int ast_devstate_changed(enum ast_device_state state, enum ast_devstate_cache cachable, const char *fmt,...)
Tells Asterisk the State for Device is changed.
Definition: devicestate.c:510
static int dahdi_ring_phone(struct dahdi_pvt *p)
Definition: chan_dahdi.c:7101
static int dahdi_cc_callback(struct ast_channel *inbound, const char *dest, ast_cc_callback_fn callback)
Callback made when dial failed to get a channel out of dahdi_request().
Definition: chan_dahdi.c:13729
struct ast_module * self
Definition: module.h:342
struct ast_party_id ani
Automatic Number Identification (ANI)
Definition: channel.h:428
static int my_has_voicemail(void *pvt)
Definition: chan_dahdi.c:2395
int amaflags
Definition: chan_dahdi.h:646
static int my_get_event(void *pvt)
Definition: chan_dahdi.c:2516
General Asterisk PBX channel definitions.
int stripmsd
Number of most significant digits/characters to strip from the dialed number.
Definition: sig_ss7.h:209
int onhooktime
Definition: sig_analog.h:274
int ast_tdd_gen_ecdisa(unsigned char *outbuf, int len)
Definition: tdd.c:148
struct dahdi_pvt * slaves[MAX_SLAVES]
Definition: chan_dahdi.h:134
static void my_set_confirmanswer(void *pvt, int flag)
Definition: chan_dahdi.c:1993
sig_pri_law
Definition: sig_pri.h:67
void ast_channel_rings_set(struct ast_channel *chan, int value)
struct mwisend_info mwisend_data
Definition: chan_dahdi.h:433
const char * ast_channel_accountcode(const struct ast_channel *chan)
static pthread_t monitor_thread
This is the thread for the monitor which checks for input on the channels which are not currently in ...
Definition: chan_dahdi.c:640
void ast_set_hangupsource(struct ast_channel *chan, const char *source, int force)
Set the source of the hangup in this channel and it&#39;s bridge.
Definition: channel.c:2504
Asterisk file paths, configured in asterisk.conf.
#define AST_FRIENDLY_OFFSET
Offset into a frame&#39;s data buffer.
const char * src
void astman_send_list_complete_end(struct mansession *s)
End the list complete event.
Definition: manager.c:3245
#define ast_mutex_trylock(a)
Definition: lock.h:189
static int my_send_callerid(void *pvt, int cwcid, struct ast_party_caller *caller)
Definition: chan_dahdi.c:1547
unsigned int needunhold
Definition: chan_dahdi.h:89
char mailbox[AST_MAX_MAILBOX_UNIQUEID]
Voice mailbox location.
Definition: chan_dahdi.h:654
static int my_dsp_set_digitmode(void *pvt, enum analog_dsp_digitmode mode)
Definition: chan_dahdi.c:1591
static int dahdi_fake_event(struct dahdi_pvt *p, int mode)
Definition: chan_dahdi.c:16237
#define CID_NOMSGWAITING
Definition: callerid.h:57
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:911
#define DSP_TONE_STATE_RINGING
Definition: dsp.h:53
#define AST_OPTION_RELAXDTMF
int ast_variable_list_replace(struct ast_variable **head, struct ast_variable *replacement)
Replace a variable in the given list with a new value.
Definition: main/config.c:668
char echorest[20]
Filled with &#39;w&#39;. XXX Purpose??
Definition: chan_dahdi.h:589
int cidlen
Length of the cidspill buffer containing samples.
Definition: chan_dahdi.h:554
const int fd
Definition: cli.h:159
struct sig_ss7_chan * sig_ss7_chan_new(void *pvt_data, struct sig_ss7_linkset *ss7)
void ast_channel_nativeformats_set(struct ast_channel *chan, struct ast_format_cap *value)
void ast_channel_stage_snapshot_done(struct ast_channel *chan)
Clear flag to indicate channel snapshot is being staged, and publish snapshot.
static int ss_thread_count
Definition: chan_dahdi.c:644
struct timeval flashtime
Definition: chan_dahdi.h:637
struct ast_party_connected_line * ast_channel_connected(struct ast_channel *chan)
#define SIG_SS7_DEBUG
Definition: sig_ss7.h:43
int sig_pri_cc_agent_stop_ringing(struct ast_cc_agent *agent)
#define AST_PTHREADT_NULL
Definition: lock.h:66
int stripmsd
Definition: sig_pri.h:291
struct dahdi_confinfo saveconf
Definition: chan_dahdi.h:132
const int n
Definition: cli.h:165
struct ast_pbx * ast_channel_pbx(const struct ast_channel *chan)
struct sla_ringing_trunk * last
Definition: app_meetme.c:1092
#define SIG_FEATD
Definition: chan_dahdi.h:724
unsigned int mwimonitoractive
TRUE if an MWI monitor thread is currently active.
Definition: chan_dahdi.h:388
#define AST_MULAW(a)
Definition: ulaw.h:85
int echotraining
Echo training time. 0 = disabled.
Definition: chan_dahdi.h:587
void sig_ss7_link_noalarm(struct sig_ss7_linkset *linkset, int which)
#define LINKSET_FLAG_EXPLICITACM
Definition: sig_ss7.h:68
static int my_callwait(void *pvt)
Definition: chan_dahdi.c:1513
void(*const handle_dchan_exception)(struct sig_pri_span *pri, int index)
Definition: sig_pri.h:202
int sig_ss7_find_cic(struct sig_ss7_linkset *linkset, int cic, unsigned int dpc)
#define AST_MAX_EXTENSION
Definition: channel.h:135
static int reset_conf(struct dahdi_pvt *p)
Definition: chan_dahdi.c:4569
char * ast_strip(char *s)
Strip leading/trailing whitespace from a string.
Definition: strings.h:219
#define AST_CAUSE_NORMAL_CLEARING
Definition: causes.h:105
static int my_ring(void *pvt)
Definition: chan_dahdi.c:2573
void sig_ss7_cli_show_channels_header(int fd)
void ast_party_number_init(struct ast_party_number *init)
Initialize the given number structure.
Definition: channel.c:1644
static int sigtype_to_signalling(int sigtype)
Definition: chan_dahdi.c:12076
#define ast_verbose_callid(callid,...)
Definition: logger.h:178
Caller Party information.
Definition: channel.h:419
#define ast_channel_cleanup(c)
Cleanup a channel reference.
Definition: channel.h:2992
int cid_ani2
Automatic Number Identification code from PRI.
Definition: chan_dahdi.h:477
#define ao2_ref(o, delta)
Definition: astobj2.h:464
void ast_channel_set_readformat(struct ast_channel *chan, struct ast_format *format)
static int cidrings[NUM_CADENCE_MAX]
cidrings says in which pause to transmit the cid information, where the first pause is 1...
Definition: chan_dahdi.c:580
ast_mutex_t lock
Definition: chan_dahdi.h:125
static int action_dahdidndoff(struct mansession *s, const struct message *m)
Definition: chan_dahdi.c:16307
#define S_COR(a, b, c)
returns the equivalent of logic or for strings, with an additional boolean check: second one if not e...
Definition: strings.h:85
int ast_softhangup(struct ast_channel *chan, int reason)
Softly hangup up a channel.
Definition: channel.c:2476
static int ringt_base
Configured ring timeout base.
Definition: chan_dahdi.c:690
void ast_config_destroy(struct ast_config *config)
Destroys a config.
Definition: extconf.c:1290
In case you didn&#39;t read that giant block of text above the mansession_session struct, the struct mansession is named this solely to keep the API the same in Asterisk. This structure really represents data that is different from Manager action to Manager action. The mansession_session pointer contained within points to session-specific data.
Definition: manager.c:1625
#define DSP_FEATURE_FAX_DETECT
Definition: dsp.h:29
#define MIN_MS_SINCE_FLASH
Definition: chan_dahdi.c:682
static void my_handle_dtmf(void *pvt, struct ast_channel *ast, enum analog_sub analog_index, struct ast_frame **dest)
Definition: chan_dahdi.c:1648
long int ast_random(void)
Definition: main/utils.c:2064
float rxdrc
Definition: chan_dahdi.h:164
char contextData[AST_MAX_CONTEXT]
Definition: chan_dahdi.h:67
static ast_mutex_t iflock
Protect the interface list (of dahdi_pvt&#39;s)
Definition: chan_dahdi.c:625
unsigned char * cidspill
Analog caller ID waveform sample buffer.
Definition: chan_dahdi.h:550
static int mwi_send_init(struct dahdi_pvt *pvt)
Definition: chan_dahdi.c:10883
unsigned int permcallwaiting
TRUE if busy extensions will hear the call-waiting tone and can use hook-flash to switch between call...
Definition: chan_dahdi.h:296
static int dahdi_open(char *fn)
Definition: chan_dahdi.c:4086
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
void sig_ss7_set_alarm(struct sig_ss7_chan *p, int in_alarm)
int ring[3]
Definition: chan_dahdi.h:63
static int my_unallocate_sub(void *pvt, enum analog_sub analogsub)
Definition: chan_dahdi.c:2377
struct ast_channel * owner
Definition: chan_dahdi.h:79
int ast_cc_set_param(struct ast_cc_config_params *params, const char *const name, const char *value)
set a CCSS configuration parameter, given its name
Definition: ccss.c:804
#define ast_format_cap_append(cap, format, framing)
Definition: format_cap.h:103
const char * ast_json_string_get(const struct ast_json *string)
Get the value of a JSON string.
Definition: json.c:273
void ast_channel_amaflags_set(struct ast_channel *chan, enum ama_flags value)
int analog_available(struct analog_pvt *p)
Definition: sig_analog.c:795
unsigned int busydetect
TRUE if busy detection is enabled. (Listens for the beep-beep busy pattern.)
Definition: chan_dahdi.h:189
void * chan_pvt
Definition: sig_ss7.h:190
#define AST_LAW(p)
Definition: chan_dahdi.c:521
static int restore_gains(struct dahdi_pvt *p)
Definition: chan_dahdi.c:4909
unsigned int mwimonitor_fsk
TRUE if the FXO port monitors for fsk type MWI indications from the other end.
Definition: chan_dahdi.h:380
#define ast_malloc(len)
A wrapper for malloc()
Definition: astmm.h:193
char mohinterpret[MAX_MUSICCLASS]
Definition: sig_ss7.h:238
static void publish_channel_alarm_clear(int channel)
Definition: chan_dahdi.c:3506
static struct ao2_container * pvts
Definition: chan_console.c:174
static struct channel_usage channels
static void my_set_alarm(void *pvt, int in_alarm)
Definition: chan_dahdi.c:1908
#define ast_variable_new(name, value, filename)
ast_group_t ast_get_group(const char *s)
Definition: channel.c:7718
unsigned int inservice
TRUE if channel is in service.
Definition: sig_ss7.h:290
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:832
#define AST_CAUSE_NO_ANSWER
Definition: causes.h:108
#define gen_pvt_field_callback(type, field)
Definition: chan_dahdi.c:3342
analog_sub
Definition: sig_analog.h:108
int ast_dsp_get_tstate(struct ast_dsp *dsp)
Get tstate (Tone State)
Definition: dsp.c:1898
unsigned int linear
Definition: chan_dahdi.h:90
static void dahdi_softhangup_all(void)
Definition: chan_dahdi.c:15396
struct ast_frame * analog_exception(struct analog_pvt *p, struct ast_channel *ast)
Definition: sig_analog.c:3555
void * no_b_chan_end
Definition: sig_pri.h:614
static void dahdi_train_ec(struct dahdi_pvt *p)
Definition: chan_dahdi.c:4693
int ast_exists_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
Determine whether an extension exists.
Definition: pbx.c:4179
short buffer[AST_FRIENDLY_OFFSET/2+READ_SIZE]
Definition: chan_dahdi.h:81
static int action_dahdirestart(struct mansession *s, const struct message *m)
Definition: chan_dahdi.c:15562
#define ast_format_cap_alloc(flags)
Definition: format_cap.h:52
analog_dsp_digitmode
Definition: sig_analog.h:114
unsigned int use_callingpres
TRUE if we will use the calling presentation setting from the Asterisk channel for outgoing calls...
Definition: chan_dahdi.h:354
struct ast_str * ast_manager_build_channel_state_string(const struct ast_channel_snapshot *snapshot)
Generate the AMI message body from a channel snapshot.
#define SMDI_MD_WAIT_TIMEOUT
Definition: chan_dahdi.c:482
An SMDI message desk message.
Definition: smdi.h:65
int ast_queue_hold(struct ast_channel *chan, const char *musicclass)
Queue a hold frame.
Definition: channel.c:1191
char cid_tag[AST_MAX_EXTENSION]
Caller ID tag from incoming call.
Definition: chan_dahdi.h:484
struct ast_config * ast_config_new(void)
Create a new base configuration structure.
Definition: extconf.c:3276
char subscriberprefix[20]
Definition: sig_ss7.h:341
#define AST_CAUSE_NOTDEFINED
Definition: causes.h:154
Structure to describe a channel "technology", ie a channel driver See for examples: ...
Definition: channel.h:629
#define AST_LIST_MOVE_CURRENT(newhead, field)
Move the current list entry to another list.
Definition: linkedlists.h:581
void ast_channel_adsicpe_set(struct ast_channel *chan, enum ast_channel_adsicpe value)
const char * ast_channel_exten(const struct ast_channel *chan)
static int my_check_for_conference(void *pvt)
Definition: chan_dahdi.c:2176
Core PBX routines and definitions.
int ast_channel_cc_params_init(struct ast_channel *chan, const struct ast_cc_config_params *base_params)
Set up datastore with CCSS parameters for a channel.
Definition: channel.c:10652
int ast_queue_frame(struct ast_channel *chan, struct ast_frame *f)
Queue one or more frames to a channel&#39;s frame queue.
Definition: channel.c:1139
void ast_party_number_free(struct ast_party_number *doomed)
Destroy the party number contents.
Definition: channel.c:1691
int ast_check_hangup(struct ast_channel *chan)
Check to see if a channel is needing hang up.
Definition: channel.c:445
#define SIG_PRI
Definition: chan_dahdi.h:745
static void my_cancel_cidspill(void *pvt)
Definition: chan_dahdi.c:2016
static char * dahdi_set_dnd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: chan_dahdi.c:16163
#define AST_CAUSE_DESTINATION_OUT_OF_ORDER
Definition: causes.h:114
static int bump_gains(struct dahdi_pvt *p)
Definition: chan_dahdi.c:4895
#define AST_CC_GENERIC_MONITOR_TYPE
Definition: ccss.h:489
#define CONFIG_STATUS_FILEUNCHANGED
void sig_pri_chan_delete(struct sig_pri_chan *doomed)
static int load_module(void)
Load the module.
Definition: chan_dahdi.c:19671
#define AST_LIST_HEAD_STATIC(name, type)
Defines a structure to be used to hold a list of specified type, statically initialized.
Definition: linkedlists.h:290
char cid_num[AST_MAX_EXTENSION]
Definition: sig_analog.h:313
#define GET_CHANNEL(p)
Definition: chan_dahdi.c:1053
char * term_color(char *outbuf, const char *inbuf, int fgcolor, int bgcolor, int maxout)
Colorize a specified string by adding terminal color codes.
Definition: term.c:184
unsigned int use_smdi
TRUE if SMDI (Simplified Message Desk Interface) is enabled.
Definition: chan_dahdi.h:432
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition: astmm.h:290
const char * ast_channel_uniqueid(const struct ast_channel *chan)
const char *const * argv
Definition: cli.h:161
#define AST_OPTION_ECHOCAN
static int my_train_echocanceller(void *pvt)
Definition: chan_dahdi.c:2675
#define DEFAULT_DIALTONE_DETECT_TIMEOUT
Definition: chan_dahdi.c:684
#define SIG_SS7
Definition: chan_dahdi.h:750
#define SIG_E911
Definition: chan_dahdi.h:727
static void * do_monitor(void *data)
Definition: chan_dahdi.c:11482
static int my_off_hook(void *pvt)
Definition: chan_dahdi.c:2589
int ast_manager_unregister(const char *action)
Unregister a registered manager command.
Definition: manager.c:7258
The AMI - Asterisk Manager Interface - is a TCP protocol created to manage Asterisk with third-party ...
static int numbufs
Definition: chan_dahdi.c:610
unsigned int inthreeway
Definition: chan_dahdi.h:91
int sig_pri_cc_agent_init(struct ast_cc_agent *agent, struct sig_pri_chan *pvt_chan)
static int my_start(void *pvt)
Definition: chan_dahdi.c:2647
struct dahdi_pvt * prev
Definition: chan_dahdi.h:169
struct ast_party_subaddress subaddress
Subscriber subaddress.
Definition: channel.h:345
void ast_channel_stage_snapshot(struct ast_channel *chan)
Set flag to indicate channel snapshot is being staged.
struct timeval waitingfordt
Definition: chan_dahdi.h:636
#define COLOR_BLACK
Definition: term.h:47
const char * type
Type of agent the callbacks belong to.
Definition: ccss.h:894
#define AST_OPTION_DIGIT_DETECT
static struct ast_channel * my_new_analog_ast_channel(void *pvt, int state, int startpbx, enum analog_sub sub, const struct ast_channel *requestor)
Definition: chan_dahdi.c:2225
#define DSP_DIGITMODE_MUTEMAX
Definition: dsp.h:36
static int reload(void)
Definition: chan_dahdi.c:19898
#define CID_SIG_V23_JP
Definition: callerid.h:62
struct ast_format * ast_channel_rawreadformat(struct ast_channel *chan)
static void notify_message(char *mailbox, int thereornot)
Send MWI state change.
Definition: chan_dahdi.c:3292
struct sig_ss7_chan * pvts[SIG_SS7_MAX_CHANNELS]
Definition: sig_ss7.h:322
struct ast_dsp * dsp
Opaque DSP configuration structure.
Definition: chan_dahdi.h:639
int sig_pri_cc_monitor_status_rsp(struct ast_cc_monitor *monitor, enum ast_device_state devstate)
int analog_ss_thread_start(struct analog_pvt *p, struct ast_channel *chan)
Definition: sig_analog.c:2665
int busycount
Number of times to see "busy" tone before hanging up.
Definition: chan_dahdi.h:594
static int dahdi_sendtext(struct ast_channel *c, const char *text)
Definition: chan_dahdi.c:19777
unsigned int destroy
TRUE if the channel is to be destroyed on hangup. (Used by pseudo channels.)
Definition: chan_dahdi.h:226
struct ast_namedgroups * ast_get_namedgroups(const char *s)
Create an ast_namedgroups set with group names from comma separated string.
Definition: channel.c:7775
static int dahdi_restart(void)
Definition: chan_dahdi.c:15424
enum analog_cid_start cid_start
Definition: sig_analog.h:311
#define LOG_ERROR
Definition: logger.h:285
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:730
unsigned int faxhandled
TRUE if a fax tone has already been handled.
Definition: chan_dahdi.h:250
int sig_ss7_call(struct sig_ss7_chan *p, struct ast_channel *ast, const char *rdest)
int analog_call(struct analog_pvt *p, struct ast_channel *ast, const char *rdest, int timeout)
Definition: sig_analog.c:987
int ast_pickup_call(struct ast_channel *chan)
Pickup a call.
Definition: pickup.c:200
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true". This function checks to see whether a string passed to it is an indication of an "true" value. It checks to see if the string is "yes", "true", "y", "t", "on" or "1".
Definition: main/utils.c:1951
#define PROC_DAHDI_OPT_NOCHAN
Definition: chan_dahdi.c:17861
struct dahdi_pvt::@110 echocancel
Echo cancel parameters.
char mohinterpret[MAX_MUSICCLASS]
The configured music-on-hold class to use for calls.
Definition: chan_dahdi.h:465
int fds[SIG_SS7_NUM_DCHANS]
Definition: sig_ss7.h:323
pthread_t master
Definition: sig_pri.h:617
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:584
enum DAHDI_IFLIST which_iflist
Definition: chan_dahdi.h:167
char cid_num[AST_MAX_EXTENSION]
Caller ID number from an incoming call.
Definition: chan_dahdi.h:479
int analog_config_complete(struct analog_pvt *p)
Definition: sig_analog.c:3963
Format capabilities structure, holds formats + preference order + etc.
Definition: format_cap.c:54
int ast_safe_system(const char *s)
Safely spawn an OS shell command while closing file descriptors.
Definition: extconf.c:829
static int send_cwcidspill(struct dahdi_pvt *p)
Definition: chan_dahdi.c:5017
#define AST_OPTION_RXGAIN
struct tdd_state * tdd_new(void)
Definition: tdd.c:103
int ast_parking_is_exten_park(const char *context, const char *exten)
Determine if the context/exten is a "parking" extension.
Definition: parking.c:179
int minunused
Definition: sig_pri.h:555
static char * handle_dahdi_show_cadences(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: chan_dahdi.c:15853
#define CLI_SHOWUSAGE
Definition: cli.h:45
static int mwi_send_process_event(struct dahdi_pvt *pvt, int event)
Definition: chan_dahdi.c:11024
static int my_dial_digits(void *pvt, enum analog_sub sub, struct analog_dialoperation *dop)
Definition: chan_dahdi.c:2655
static int my_distinctive_ring(struct ast_channel *chan, void *pvt, int idx, int *ringdata)
Definition: chan_dahdi.c:1375
#define HANGUP
Definition: chan_dahdi.c:16235
int plan
Q.931 Type-Of-Number and Numbering-Plan encoded fields.
Definition: channel.h:294
void ast_channel_named_callgroups_set(struct ast_channel *chan, struct ast_namedgroups *value)
void * stasis_message_data(const struct stasis_message *msg)
Get the data contained in a message.
static char * dahdi_sig2str(int sig)
Definition: chan_dahdi.c:4391
static struct dahdi_pvt * duplicate_pseudo(struct dahdi_pvt *src)
Definition: chan_dahdi.c:13266
TTY/TDD Generation support.
int ast_remaining_ms(struct timeval start, int max_ms)
Calculate remaining milliseconds given a starting timestamp and upper bound.
Definition: main/utils.c:2033
static int dahdi_create_channel_range(int start, int end)
Definition: chan_dahdi.c:11150
static void deep_copy_dahdi_chan_conf(struct dahdi_chan_conf *dest, const struct dahdi_chan_conf *src)
Definition: chan_dahdi.c:19326
#define POLARITY_REV
Definition: chan_dahdi.c:793
#define AST_NONSTANDARD_APP_ARGS(args, parse, sep)
Performs the &#39;nonstandard&#39; argument separation process for an application.
int analog_answer(struct analog_pvt *p, struct ast_channel *ast)
Definition: sig_analog.c:1461
#define SIG_SS7_NUM_DCHANS
Definition: sig_ss7.h:56
static int my_check_waitingfordt(void *pvt)
Definition: chan_dahdi.c:1982
void ast_party_name_init(struct ast_party_name *init)
Initialize the given name structure.
Definition: channel.c:1591
#define DAHDI_OVERLAPDIAL_BOTH
Definition: sig_pri.h:256
int sig_ss7_find_cic_range(struct sig_ss7_linkset *linkset, int startcic, int endcic, unsigned int dpc)
unsigned int use_callerid
TRUE if caller ID is used on this channel.
Definition: chan_dahdi.h:347
static char * dahdi_destroy_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: chan_dahdi.c:15303
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
int ani2
Automatic Number Identification 2 (Info Digits)
Definition: channel.h:434
int errno
unsigned int needringing
Definition: chan_dahdi.h:83
#define SUB_REAL
Definition: chan_dahdi.h:57
char dialstring[AST_CHANNEL_NAME]
Definition: chan_dahdi.h:717
static void my_set_waitingfordt(void *pvt, struct ast_channel *ast)
Definition: chan_dahdi.c:1971
int confno
Definition: chan_dahdi.h:510
static void dahdi_ami_channel_event(struct dahdi_pvt *p, struct ast_channel *chan)
Definition: chan_dahdi.c:1801
static int has_pseudo
Definition: chan_dahdi.c:567
#define CID_SIG_DTMF
Definition: callerid.h:61
void ast_dsp_set_busy_pattern(struct ast_dsp *dsp, const struct ast_dsp_busy_pattern *cadence)
Set expected lengths of the busy tone.
Definition: dsp.c:1791
static struct dahdi_pvt * find_next_iface_in_span(struct dahdi_pvt *cur)
Definition: chan_dahdi.c:5558
struct ast_codec * codec
Pointer to the codec in use for this format.
Definition: format.c:47
#define SIG_PRI_NUM_DCHANS
Definition: sig_pri.h:241
int propconfno
Definition: chan_dahdi.h:512
const ast_string_field name
struct ast_party_dialed * ast_channel_dialed(struct ast_channel *chan)
static void process_echocancel(struct dahdi_chan_conf *confp, const char *data, unsigned int line)
Definition: chan_dahdi.c:17728
int ast_moh_start(struct ast_channel *chan, const char *mclass, const char *interpclass)
Turn on music on hold on a given channel.
Definition: channel.c:7866
struct sig_pri_chan * pvts[SIG_PRI_MAX_CHANNELS]
Definition: sig_pri.h:616
static void my_handle_notify_message(struct ast_channel *chan, void *pvt, int cid_flags, int neon_mwievent)
Definition: chan_dahdi.c:3307
void analog_delete(struct analog_pvt *doomed)
Delete the analog private structure.
Definition: sig_analog.c:3958
void ast_party_name_free(struct ast_party_name *doomed)
Destroy the party name contents.
Definition: channel.c:1638
static struct dahdi_pvt * find_channel(int channel)
Definition: chan_dahdi.c:16253
#define READ_SIZE
Definition: chan_dahdi.c:673
#define SIG_FXSGS
Definition: chan_dahdi.h:732
static void my_set_cadence(void *pvt, int *cid_rings, struct ast_channel *ast)
Definition: chan_dahdi.c:1892
#define ast_cond_destroy(cond)
Definition: lock.h:200
char idledial[AST_MAX_EXTENSION]
Definition: sig_pri.h:554
unsigned int immediate
Definition: sig_pri.h:284
#define AST_LIST_LAST(head)
Returns the last entry contained in a list.
Definition: linkedlists.h:428
static struct ast_channel * dahdi_new_callid_clean(struct dahdi_pvt *i, int state, int startpbx, int idx, int law, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, ast_callid callid, int callid_created)
Definition: chan_dahdi.c:9144
#define LOG_NOTICE
Definition: logger.h:263
sig_ss7_tone
Definition: sig_ss7.h:78
#define DEFAULT_CIDRINGS
Typically, how many rings before we should send Caller*ID.
Definition: chan_dahdi.c:519
char * strcasestr(const char *, const char *)
const char * ast_config_AST_LOG_DIR
Definition: options.c:159
struct ast_format_cap * capabilities
Definition: channel.h:633
static void my_set_inthreeway(void *pvt, enum analog_sub sub, int inthreeway)
Definition: chan_dahdi.c:1852
int ast_softhangup_nolock(struct ast_channel *chan, int reason)
Softly hangup up a channel (no channel lock)
Definition: channel.c:2463
char * origcid_name
Definition: chan_dahdi.h:492
char exten[AST_MAX_EXTENSION]
Extension to use in the dialplan.
Definition: chan_dahdi.h:455
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
#define AST_LIST_ENTRY(type)
Declare a forward link structure inside a list entry.
Definition: linkedlists.h:409
void sig_ss7_init_linkset(struct sig_ss7_linkset *ss7)
static int set_actual_txgain(int fd, float gain, float drc, int law)
Definition: chan_dahdi.c:4856
long int flag
Definition: f2c.h:83
static int restore_conference(struct dahdi_pvt *p)
Definition: chan_dahdi.c:5002
#define SIG_PRI_LIB_HANDLE_CASES
Definition: chan_dahdi.h:756
struct ast_namedgroups * ast_ref_namedgroups(struct ast_namedgroups *groups)
Definition: channel.c:7838
int muting
TRUE if confrence is muted.
Definition: chan_dahdi.h:708
int distinctivering
Definition: chan_dahdi.h:664
int ast_parking_provider_registered(void)
Check whether a parking provider is registered.
Definition: parking.c:241
#define ast_channel_unlock(chan)
Definition: channel.h:2946
void sig_pri_fixup(struct ast_channel *oldchan, struct ast_channel *newchan, struct sig_pri_chan *pchan)
#define CLI_FAILURE
Definition: cli.h:46
void stasis_subscription_cb_noop(void *data, struct stasis_subscription *sub, struct stasis_message *message)
Stasis subscription callback function that does nothing.
Definition: stasis.c:811
int sig_ss7_group_blocking(struct sig_ss7_linkset *linkset, int do_block, int startcic, int endcic, unsigned char state[], int type)
static void parse(struct mgcp_request *req)
Definition: chan_mgcp.c:1872
void ast_dsp_set_features(struct ast_dsp *dsp, int features)
Select feature set.
Definition: dsp.c:1755
#define SIG_SF_FEATD
Definition: chan_dahdi.h:739
static void publish_dnd_state(int channel, const char *status)
Definition: chan_dahdi.c:9437
unsigned int usedistinctiveringdetection
TRUE if distinctive rings are to be detected.
Definition: chan_dahdi.h:360
static int dahdi_queryoption(struct ast_channel *chan, int option, void *data, int *datalen)
Definition: chan_dahdi.c:6504
#define AST_CAUSE_UNREGISTERED
Definition: causes.h:153
char call_forward[AST_MAX_EXTENSION]
Accumulated call forwarding number.
Definition: chan_dahdi.h:649
#define ast_free(a)
Definition: astmm.h:182
char * command
Definition: cli.h:186
static struct ast_jb_conf global_jbconf
Definition: chan_dahdi.c:505
unsigned int hidecalleridname
Definition: sig_pri.h:283
#define container_of(ptr, type, member)
Definition: codec_dahdi.c:277
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204
#define ast_pthread_create(a, b, c, d)
Definition: utils.h:559
static int dahdi_set_hook(int fd, int hs)
Definition: chan_dahdi.c:4922
void sig_pri_set_alarm(struct sig_pri_chan *p, int in_alarm)
#define AST_CHANNEL_NAME
Definition: channel.h:172
unsigned int faxdetect_timeout
The number of seconds into call to disable fax detection. (0 = disabled)
Definition: chan_dahdi.h:620
unsigned int restrictcid
TRUE if caller ID is restricted.
Definition: chan_dahdi.h:325
static int dahdi_answer(struct ast_channel *ast)
Definition: chan_dahdi.c:6409
char called_nai
Definition: sig_ss7.h:337
static int get_alarms(struct dahdi_pvt *p)
Definition: chan_dahdi.c:7204
unsigned int dahditrcallerid
Definition: sig_analog.h:284
static int dahdi_get_event(int fd)
Avoid the silly dahdi_getevent which ignores a bunch of events.
Definition: chan_dahdi.c:652
#define AST_OPTION_AUDIO_MODE
Call Completion Supplementary Services API.
#define CHANNEL_DEADLOCK_AVOIDANCE(chan)
Definition: lock.h:352
void ast_hangup(struct ast_channel *chan)
Hang up a channel.
Definition: channel.c:2548
static void my_lock_private(void *pvt)
Definition: chan_dahdi.c:1722
static void my_set_polarity(void *pvt, int value)
Definition: chan_dahdi.c:2601
char context[AST_MAX_CONTEXT]
The configured context for incoming calls.
Definition: chan_dahdi.h:444
unsigned int remotelyblocked
Bitmask for the channel being remotely blocked. 1 maintenance, 2 blocked in hardware.
Definition: chan_dahdi.h:413
struct callerid_state * cs
Definition: chan_dahdi.h:126
Channel configuration from chan_dahdi.conf . This struct is used for parsing the [channels] section o...
Definition: chan_dahdi.c:831
static void to_ami(struct ast_sip_subscription *sub, struct ast_str **buf)
void dahdi_master_slave_link(struct dahdi_pvt *slave, struct dahdi_pvt *master)
Definition: chan_dahdi.c:7037
unsigned int threewaycalling
TRUE if three way calling is enabled.
Definition: chan_dahdi.h:330
int msgstate
-1 = unknown, 0 = no messages, 1 = new messages available
Definition: sig_analog.h:277
SMDI support for Asterisk.
const char * word
Definition: cli.h:163
#define DSP_FEATURE_BUSY_DETECT
Definition: dsp.h:27
struct stasis_message_type * ast_mwi_state_type(void)
Get the Stasis Message Bus API message type for MWI messages.
unsigned int permhidecallerid
Definition: sig_analog.h:288
Module has failed to load, may be in an inconsistent state.
Definition: module.h:78
static void fill_txgain(struct dahdi_gains *g, float gain, float drc, int law)
Definition: chan_dahdi.c:4758
static char * dahdi_show_status(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: chan_dahdi.c:15890
void dahdi_dtmf_detect_enable(struct dahdi_pvt *p)
Definition: chan_dahdi.c:6487
int pri_send_callrerouting_facility_exec(struct sig_pri_chan *p, enum ast_channel_state chanstate, const char *destination, const char *original, const char *reason)
int wanted_channels_start
Don&#39;t create channels below this number.
Definition: chan_dahdi.c:859
static const char * event2str(int event)
Definition: chan_dahdi.c:4382
int alarm
Definition: chan_dahdi.c:4360
#define SIG_SFWINK
Definition: chan_dahdi.h:738
struct dahdi_echocanparam params[DAHDI_MAX_ECHOCANPARAMS]
Definition: chan_dahdi.h:581
unsigned int flags
Combination of the AST_JB_ENABLED, AST_JB_FORCED and AST_JB_LOG flags.
Definition: abstract_jb.h:72
void ast_cc_copy_config_params(struct ast_cc_config_params *dest, const struct ast_cc_config_params *src)
copy CCSS configuration parameters from one structure to another
Definition: ccss.c:861
int ast_db_get(const char *family, const char *key, char *value, int valuelen)
Get key value specified by family/key.
Definition: main/db.c:412
int stripmsd
Number of most significant digits/characters to strip from the dialed number.
Definition: chan_dahdi.h:568
void sig_pri_cc_monitor_destructor(void *monitor_pvt)
static void publish_dahdichannel(struct ast_channel *chan, ast_group_t group, int span, const char *dahdi_channel)
Sends a DAHDIChannel channel blob used to produce DAHDIChannel AMI messages.
Definition: chan_dahdi.c:1772
int sig_pri_start_pri(struct sig_pri_span *pri)
#define AST_CAUSE_INTERWORKING
Definition: causes.h:145
struct ast_namedgroups * named_callgroups
Named call groups this belongs to.
Definition: chan_dahdi.h:527
static int mwi_send_process_buffer(struct dahdi_pvt *pvt, int num_read)
Definition: chan_dahdi.c:10936
void sig_ss7_link_alarm(struct sig_ss7_linkset *linkset, int which)
int sig_pri_cc_agent_start_monitoring(struct ast_cc_agent *agent)
struct ast_smdi_interface * smdi_iface
The SMDI interface to get SMDI messages from.
Definition: chan_dahdi.h:435
#define END_SILENCE_LEN
Structure used to handle boolean flags.
Definition: utils.h:199
static int send_callerid(struct dahdi_pvt *p)
Definition: chan_dahdi.c:5051
int ast_callerid_generate(unsigned char *buf, const char *name, const char *number, struct ast_format *codec)
Generate Caller-ID spill from the "callerid" field of asterisk (in e-mail address like format) ...
Definition: callerid.c:1063
#define SIG_FGC_CAMA
Definition: chan_dahdi.h:729
static int dahdi_func_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len)
Definition: chan_dahdi.c:6764
#define FORMAT2
int ast_app_has_voicemail(const char *mailboxes, const char *folder)
Determine if a given mailbox has any voicemail If folder is NULL, defaults to "INBOX". If folder is "INBOX", includes the number of messages in the "Urgent" folder.
Definition: main/app.c:655
char networkroutedprefix[20]
Definition: sig_ss7.h:343
#define ast_clear_flag(p, flag)
Definition: utils.h:77
struct ast_channel * peer
void ast_channel_set_fd(struct ast_channel *chan, int which, int fd)
Definition: channel.c:2431
struct ast_party_redirecting * ast_channel_redirecting(struct ast_channel *chan)
char nationalprefix[10]
Definition: sig_ss7.h:340
#define SIG_SF_FEATB
Definition: chan_dahdi.h:741
#define SIG_MFCR2
Definition: chan_dahdi.h:753
static char cid_name[AST_MAX_EXTENSION]
Definition: chan_mgcp.c:165
struct ast_bridge_channel * ast_channel_get_bridge_channel(struct ast_channel *chan)
Get a reference to the channel&#39;s bridge pointer.
Definition: channel.c:10783
AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS|AST_MODFLAG_LOAD_ORDER, "HTTP Phone Provisioning",.support_level=AST_MODULE_SUPPORT_EXTENDED,.load=load_module,.unload=unload_module,.reload=reload,.load_pri=AST_MODPRI_CHANNEL_DEPEND,.requires="http",)
struct timeval delivery
int buf_policy
Definition: chan_dahdi.h:140
void ast_channel_callid_set(struct ast_channel *chan, ast_callid value)
static int set_actual_rxgain(int fd, float gain, float drc, int law)
Definition: chan_dahdi.c:4873
static int action_dahdishowchannels(struct mansession *s, const struct message *m)
Definition: chan_dahdi.c:16404
void ast_jb_configure(struct ast_channel *chan, const struct ast_jb_conf *conf)
Configures a jitterbuffer on a channel.
Definition: abstract_jb.c:593
unsigned int ignoredtmf
TRUE if DTMF detection is disabled.
Definition: chan_dahdi.h:278
int numchans
Definition: sig_pri.h:615
#define CHECK_BLOCKING(c)
Set the blocking indication on the channel.
Definition: channel.h:2894
#define SIG_FXSKS
Definition: chan_dahdi.h:733
#define CALLWAITING_REPEAT_SAMPLES
Definition: chan_dahdi.c:679
int fake_event
Holding place for event injected from outside normal operation.
Definition: chan_dahdi.h:667
struct dahdi_echocanparams head
Definition: chan_dahdi.h:580
#define CID_START_RING
Definition: callerid.h:65
const char * usage
Definition: cli.h:177
void ast_channel_exten_set(struct ast_channel *chan, const char *value)
int pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
Add a variable to the channel variable stack, removing the most recently set value for the same name...
static int my_set_linear_mode(void *pvt, enum analog_sub sub, int linear_mode)
Definition: chan_dahdi.c:1840
static int dahdi_setlinear(int dfd, int linear)
Definition: chan_dahdi.c:4161
struct ast_frame ast_null_frame
Definition: main/frame.c:79
unsigned int confirmanswer
TRUE if to wait for a DTMF digit to confirm answer.
Definition: chan_dahdi.h:221
int ast_waitfordigit(struct ast_channel *c, int ms)
Waits for a digit.
Definition: channel.c:3184
void callerid_free(struct callerid_state *cid)
This function frees callerid_state cid.
Definition: callerid.c:734
int wanted_channels_end
Don&#39;t create channels above this number (infinity by default)
Definition: chan_dahdi.c:865
static int available(struct dahdi_pvt **pvt, int is_specific_channel)
Definition: chan_dahdi.c:13058
int sig_pri_call(struct sig_pri_chan *p, struct ast_channel *ast, const char *rdest, int timeout, int layer1)
#define CLI_SUCCESS
Definition: cli.h:44
const char * ast_variable_retrieve(struct ast_config *config, const char *category, const char *variable)
Definition: main/config.c:694
void dahdi_native_unload(void)
char * tag
User-set "tag".
Definition: channel.h:355
STASIS_MESSAGE_TYPE_DEFN_LOCAL(dahdichannel_type,.to_ami=dahdichannel_to_ami,)
static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
Definition: chan_dahdi.c:7061
#define PUT_CLID(byte)
Definition: callerid.h:304
int ast_channel_fd(const struct ast_channel *chan, int which)
unsigned int mwimonitor_neon
TRUE if the FXO port monitors for neon type MWI indications from the other end.
Definition: chan_dahdi.h:375
#define ANALOG_FIRST_DIGIT_TIMEOUT
Default time (ms) to detect first digit.
Definition: sig_analog.h:38
unsigned int hidecallerid
Definition: sig_pri.h:282
static int my_complete_conference_update(void *pvt, int needconference)
Definition: chan_dahdi.c:2126
static struct dahdi_ring_cadence cadences[NUM_CADENCE_MAX]
Definition: chan_dahdi.c:569
int waitfordialtone
Number of milliseconds to wait for dialtone.
Definition: chan_dahdi.h:609
struct tdd_state * tdd
Definition: chan_dahdi.h:647
#define CALLPROGRESS_FAX_INCOMING
Definition: chan_dahdi.c:560
unsigned int locallyblocked
Bitmask for the channel being locally blocked.
Definition: sig_ss7.h:228
unsigned int immediate
Definition: sig_ss7.h:221
static int my_getsigstr(struct ast_channel *chan, char *str, const char *term, int ms)
Definition: chan_dahdi.c:9400
float hwtxgain
Hardware Tx gain set by chan_dahdi.conf.
Definition: chan_dahdi.h:155
Structure that contains information regarding a channel in a bridge.
void sig_ss7_chan_delete(struct sig_ss7_chan *doomed)
int sig_pri_answer(struct sig_pri_chan *p, struct ast_channel *ast)
char * strsep(char **str, const char *delims)
#define AST_OPTION_FAX_DETECT
static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen)
Definition: chan_dahdi.c:6545
static int distinctiveringaftercid
Definition: chan_dahdi.c:608
FILE * out
Definition: utils/frame.c:33
static int save_conference(struct dahdi_pvt *p)
Definition: chan_dahdi.c:4976
#define PUT_CLID_MARKMS
Definition: callerid.h:289
#define ast_channel_ref(c)
Increase channel reference count.
Definition: channel.h:2970
int sig_ss7_hangup(struct sig_ss7_chan *p, struct ast_channel *ast)
sig_pri_tone
Definition: sig_pri.h:57
int ast_waitfor(struct ast_channel *chan, int ms)
Wait for input on a channel.
Definition: channel.c:3171
#define abs(x)
Definition: f2c.h:195
static const char *const events[]
Definition: chan_dahdi.c:4337
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
Standard Command Line Interface.
struct ast_json * ast_json_object_get(struct ast_json *object, const char *key)
Get a field from a JSON object.
Definition: json.c:397
struct ast_channel * sig_pri_request(struct sig_pri_chan *p, enum sig_pri_law law, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, int transfercapability)
int sig_ss7_add_sigchan(struct sig_ss7_linkset *linkset, int which, int ss7type, int transport, int inalarm, int networkindicator, int pointcode, int adjpointcode, int cur_slc)
void sig_pri_stop_pri(struct sig_pri_span *pri)
int ast_channel_hangupcause(const struct ast_channel *chan)
int ast_db_del(const char *family, const char *key)
Delete entry in astdb.
Definition: main/db.c:429
void ast_channel_context_set(struct ast_channel *chan, const char *value)
struct dahdi_distRings drings
Distinctive Ring data.
Definition: chan_dahdi.h:438
static int dahdi_hangup(struct ast_channel *ast)
Definition: chan_dahdi.c:5992
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
unsigned int echocanon
TRUE if echo cancellation is turned on.
Definition: chan_dahdi.h:248
static struct ast_channel * dahdi_request(const char *type, struct ast_format_cap *cap, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, const char *data, int *cause)
Definition: chan_dahdi.c:13491
unsigned int needcongestion
Definition: chan_dahdi.h:85
static void publish_span_alarm_clear(int span)
Definition: chan_dahdi.c:3524
static void my_set_ringtimeout(void *pvt, int ringt)
Definition: chan_dahdi.c:1965
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:79
struct ast_format * ast_format_alaw
Built-in cached alaw format.
Definition: format_cache.c:91
unsigned int callwaitingcallerid
Definition: sig_analog.h:295
struct timeval ast_tv(ast_time_t sec, ast_suseconds_t usec)
Returns a timeval from sec, usec.
Definition: time.h:226
static struct dahdi_pvt * iflist
Definition: chan_dahdi.c:801
struct ast_channel * ast_channel_bridge_peer(struct ast_channel *chan)
Get the channel&#39;s bridge peer only if the bridge is two-party.
Definition: channel.c:10765
const char * ast_channel_name(const struct ast_channel *chan)
int sig_pri_digit_begin(struct sig_pri_chan *pvt, struct ast_channel *ast, char digit)
int attribute_pure ast_false(const char *val)
Make sure something is false. Determine if a string containing a boolean value is "false"...
Definition: main/utils.c:1968
unsigned int needbusy
Definition: chan_dahdi.h:84
const int pos
Definition: cli.h:164
int new_msgs
Definition: mwi.h:461
#define AST_CAUSE_USER_BUSY
Definition: causes.h:106
static int check_for_conference(struct dahdi_pvt *p)
Definition: chan_dahdi.c:7178
int cidcwexpire
Definition: chan_dahdi.h:547
int ast_waitstream(struct ast_channel *c, const char *breakon)
Waits for a stream to stop or digit to be pressed.
Definition: file.c:1776
int ignore_failed_channels
Definition: chan_dahdi.c:847
int ast_callid_threadstorage_auto(ast_callid *callid)
Checks thread storage for a callid and stores a reference if it exists. If not, then a new one will b...
Definition: logger.c:2020
int ast_callerid_vmwi_generate(unsigned char *buf, int active, int type, struct ast_format *codec, const char *name, const char *number, int flags)
Generate message waiting indicator.
Definition: callerid.c:810
void sig_pri_cc_agent_destructor(struct ast_cc_agent *agent)
struct dahdi_pvt chan
Definition: chan_dahdi.c:832
int ast_setstate(struct ast_channel *chan, enum ast_channel_state)
Change the state of a channel.
Definition: channel.c:7486
Asterisk MWI API.
#define AST_PTHREADT_STOP
Definition: lock.h:67
#define ast_frfree(fr)
int ast_async_goto(struct ast_channel *chan, const char *context, const char *exten, int priority)
Set the channel to next execute the specified dialplan location.
Definition: pbx.c:7011
int cid_suppress_expire
Definition: chan_dahdi.h:548
static PGresult * result
Definition: cel_pgsql.c:88
void sig_pri_dial_complete(struct sig_pri_chan *pvt, struct ast_channel *ast)
int ast_queue_control_data(struct ast_channel *chan, enum ast_control_frame_type control, const void *data, size_t datalen)
Queue a control frame with payload.
Definition: channel.c:1238
Interface header for analog signaling module.
#define SIG_FXSLS
Definition: chan_dahdi.h:731
static struct ast_str * create_channel_name(struct dahdi_pvt *i)
Definition: chan_dahdi.c:9099
#define AST_CAUSE_BUSY
Definition: causes.h:148
static void my_set_dialing(void *pvt, int is_dialing)
Definition: chan_dahdi.c:1915
static int dahdi_digit_end(struct ast_channel *ast, char digit, unsigned int duration)
Definition: chan_dahdi.c:4299
enum ast_pbx_result ast_pbx_run(struct ast_channel *c)
Execute the PBX in the current thread.
Definition: pbx.c:4759
ast_group_t groupmatch
Definition: chan_dahdi.c:13314
struct ast_variable * vars
Channel variable list with associated values to set when a channel is created.
Definition: chan_dahdi.h:537
unsigned int dialednone
TRUE if analog type line dialed no digits in Dial()
Definition: chan_dahdi.h:229
struct stasis_forward * sub
Definition: res_corosync.c:240
Data structure associated with a single frame of data.
static char * dahdi_create_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: chan_dahdi.c:15347
unsigned int manages_span_alarms
TRUE if the channel alarms will be managed also as Span ones.
Definition: chan_dahdi.h:418
Internal Asterisk hangup causes.
unsigned int priindication_oob
TRUE if PRI congestion/busy indications are sent out-of-band.
Definition: chan_dahdi.h:306
struct ast_channel * owner
Definition: sig_ss7.h:192
void ast_channel_softhangup_internal_flag_add(struct ast_channel *chan, int value)
const char * ast_channel_language(const struct ast_channel *chan)
#define ANALOG_INTER_DIGIT_TIMEOUT
Default time (ms) to detect following digits.
Definition: sig_analog.h:40
struct stasis_message * stasis_cache_get(struct stasis_cache *cache, struct stasis_message_type *type, const char *id)
Retrieve an item from the cache for the ast_eid_default entity.
Definition: stasis_cache.c:686
static int set_actual_gain(int fd, float rxgain, float txgain, float rxdrc, float txdrc, int law)
Definition: chan_dahdi.c:4890
char internationalprefix[10]
Definition: sig_ss7.h:339
enum analog_sigtype outsigmod
Definition: sig_analog.h:306
struct timeval polaritydelaytv
Start delay time if polarityonanswerdelay is nonzero.
Definition: chan_dahdi.h:674
unsigned int inalarm
Definition: sig_analog.h:325
Abstract JSON element (object, array, string, int, ...).
unsigned int hidecallerid
TRUE if the outgoing caller ID is blocked/hidden.
Definition: chan_dahdi.h:270
char callwait_num[AST_MAX_EXTENSION]
Call waiting number.
Definition: chan_dahdi.h:494
int fxsoffhookstate
Definition: sig_analog.h:275
struct isup_call * ss7call
Opaque libss7 call control structure.
Definition: sig_ss7.h:195
static void my_all_subchannels_hungup(void *pvt)
Definition: chan_dahdi.c:2066
int faxbuf_policy
Definition: chan_dahdi.h:142
#define AST_OPTION_TONE_VERIFY
static int my_confmute(void *pvt, int mute)
Definition: chan_dahdi.c:2025
static struct dahdi_pvt * round_robin[32]
Definition: chan_dahdi.c:3429
int sig_ss7_answer(struct sig_ss7_chan *p, struct ast_channel *ast)
static struct test_val b
static int setup_dahdi_int(int reload, struct dahdi_chan_conf *default_conf, struct dahdi_chan_conf *base_conf, struct dahdi_chan_conf *conf)
Definition: chan_dahdi.c:19348
#define DLA_UNLOCK(lock)
Deadlock avoidance unlock.
Definition: lock.h:408
Definition: search.h:40
const char * ast_channel_context(const struct ast_channel *chan)
Handy terminal functions for vt* terms.
int ast_db_put(const char *family, const char *key, const char *value)
Store value addressed by family/key.
Definition: main/db.c:327
void ast_cc_monitor_unregister(const struct ast_cc_monitor_callbacks *callbacks)
Unregister a set of monitor callbacks with the core.
Definition: ccss.c:1217
union ast_frame::@263 data
void * no_b_chan_iflist
Definition: sig_pri.h:609
unsigned int echocanbridged
TRUE if echo cancellation enabled when bridged.
Definition: chan_dahdi.h:246
int polarityonanswerdelay
Minimal time period (ms) between the answer polarity switch and hangup polarity switch.
Definition: chan_dahdi.h:672
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
Definition: linkedlists.h:528
int sig_pri_is_chan_available(struct sig_pri_chan *pvt)
static int isslavenative(struct dahdi_pvt *p, struct dahdi_pvt **out)
Definition: chan_dahdi.c:4525
enum ast_frame_type frametype
#define PATH_MAX
Definition: asterisk.h:40
float rxgain
Software Rx gain set by chan_dahdi.conf.
Definition: chan_dahdi.h:159
unsigned int pulse
Definition: sig_analog.h:289
static void destroy_dahdi_pvt(struct dahdi_pvt *pvt)
Definition: chan_dahdi.c:5569
static char * dahdi_show_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: chan_dahdi.c:15973
#define DAHDI_CHAN_MAPPING_LOGICAL
Definition: sig_pri.h:250
char x
Definition: extconf.c:81
#define NUM_SPANS
Definition: chan_dahdi.c:553
#define ast_mutex_init(pmutex)
Definition: lock.h:184
static int my_check_confirmanswer(void *pvt)
Definition: chan_dahdi.c:1999
#define SIG_PRI_AOC_GRANT_E
Definition: sig_pri.h:55
#define ast_channel_trylock(chan)
Definition: channel.h:2947
Callbacks defined by CC monitors.
Definition: ccss.h:576
unsigned char valid
TRUE if the name information is valid/present.
Definition: channel.h:280
int tdd_generate(struct tdd_state *tdd, unsigned char *buf, const char *string)
Definition: tdd.c:297
struct ast_namedgroups * ast_unref_namedgroups(struct ast_namedgroups *groups)
Definition: channel.c:7832
static struct test_options options
void ast_channel_publish_blob(struct ast_channel *chan, struct stasis_message_type *type, struct ast_json *blob)
Publish a channel blob message.
static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame)
Definition: chan_dahdi.c:8894
Call Parking and Pickup API Includes code and algorithms from the Zapata library. ...
struct ast_flags * ast_channel_flags(struct ast_channel *chan)
int sig_pri_cc_agent_start_offer_timer(struct ast_cc_agent *agent)
#define ast_mutex_destroy(a)
Definition: lock.h:186
unsigned int transfer
Definition: sig_analog.h:291
struct analog_subchannel subs[3]
Definition: sig_analog.h:272
void tdd_free(struct tdd_state *tdd)
Definition: tdd.c:218
static struct dahdi_pvt * mkintf(int channel, const struct dahdi_chan_conf *conf, int reloading)
Definition: chan_dahdi.c:12095
void ast_channel_internal_fd_set(struct ast_channel *chan, int which, int value)
struct ast_format * format
static char defaultcic[64]
Definition: chan_dahdi.c:596
#define LINKSET_FLAG_DEFAULTECHOCONTROL
Definition: sig_ss7.h:71
#define SIG_FXOLS
Definition: chan_dahdi.h:734
int sig_pri_load(const char *cc_type_name)
void sig_ss7_fixup(struct ast_channel *oldchan, struct ast_channel *newchan, struct sig_ss7_chan *pchan)
void callerid_get_dtmf(char *cidstring, char *number, int *flags)
Get and parse DTMF-based callerid.
Definition: callerid.c:201
#define sig2str
Definition: chan_dahdi.c:4455
int ast_devstate_changed_literal(enum ast_device_state state, enum ast_devstate_cache cachable, const char *device)
Tells Asterisk the State for Device is changed.
Definition: devicestate.c:471
#define DSP_FEATURE_WAITDIALTONE
Definition: dsp.h:44
unsigned int hanguponpolarityswitch
Definition: sig_analog.h:285
struct sig_pri_chan * sig_pri_chan_new(void *pvt_data, struct sig_pri_span *pri, int logicalspan, int channo, int trunkgroup)
#define AST_LIST_HEAD_INIT_VALUE
Defines initial values for a declaration of AST_LIST_HEAD.
Definition: linkedlists.h:233
static int my_dsp_reset_and_flush_digits(void *pvt)
Definition: chan_dahdi.c:1582
const char * ast_channel_macrocontext(const struct ast_channel *chan)
void ast_shrink_phone_number(char *n)
Shrink a phone number in place to just digits (more accurately it just removes ()&#39;s, .&#39;s, and -&#39;s...
Definition: callerid.c:947
struct callerid_state * callerid_new(int cid_signalling)
Create a callerID state machine.
Definition: callerid.c:129
The structure that contains MWI state.
Definition: mwi.h:457
static void my_set_new_owner(void *pvt, struct ast_channel *new_owner)
Definition: chan_dahdi.c:2037
int radio
Nonzero if the signaling type is sent over a radio.
Definition: chan_dahdi.h:148
#define ast_manager_register_xml(action, authority, func)
Register a manager callback using XML documentation to describe the manager.
Definition: manager.h:186
#define CID_START_DTMF_NOALERT
Definition: callerid.h:68
Say numbers and dates (maybe words one day too)
#define SIG_FEATDMF
Definition: chan_dahdi.h:725
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition: module.h:46
#define DEBUG_ATLEAST(level)
Definition: logger.h:441
#define AST_CAUSE_CALL_REJECTED
Definition: causes.h:110
unsigned int allocated
TRUE when this channel is allocated.
Definition: sig_pri.h:341
int sig_ss7_cb_hangup(struct ss7 *ss7, int cic, unsigned int dpc, int cause, int do_hangup)
char rdnis[AST_MAX_EXTENSION]
Redirecting Directory Number Information Service (RDNIS) number.
Definition: chan_dahdi.h:498
Bridging API.
static struct ast_timer * timer
Definition: chan_iax2.c:360
#define RESULT_SUCCESS
Definition: cli.h:40
#define ast_channel_alloc(needqueue, state, cid_num, cid_name, acctcode, exten, context, assignedids, requestor, amaflag,...)
Create a channel structure.
Definition: channel.h:1259
struct ast_format * ast_format_slin
Built-in cached signed linear 8kHz format.
Definition: format_cache.c:41
struct pri * dchans[SIG_PRI_NUM_DCHANS]
Definition: sig_pri.h:603
void astman_send_error(struct mansession *s, const struct message *m, char *error)
Send error in manager transaction.
Definition: manager.c:3159
char context[AST_MAX_CONTEXT]
Definition: sig_pri.h:289
unsigned int canpark
Definition: sig_analog.h:283
Asterisk module definitions.
static int num_cadence
Definition: chan_dahdi.c:564
static struct dahdi_pvt * handle_init_event(struct dahdi_pvt *i, int event)
Definition: chan_dahdi.c:11218
int callprogress
Bitmapped call progress detection flags. CALLPROGRESS_xxx values.
Definition: chan_dahdi.h:604
float hwrxgain
Hardware Rx gain set by chan_dahdi.conf.
Definition: chan_dahdi.h:153
#define DEFAULT_RINGT
Definition: chan_dahdi.c:683
intmax_t ast_json_integer_get(const struct ast_json *integer)
Get the value from a JSON integer.
Definition: json.c:322
static int canmatch_featurecode(const char *pickupexten, const char *exten)
Definition: chan_dahdi.c:9485
char language[MAX_LANGUAGE]
Language configured for calls.
Definition: chan_dahdi.h:460
unsigned int hwrxgain_enabled
TRUE if hardware Rx gain set by Asterisk.
Definition: chan_dahdi.h:420
static int build_channels(struct dahdi_chan_conf *conf, const char *value, int reload, int lineno)
Definition: chan_dahdi.c:17667
static int action_transfer(struct mansession *s, const struct message *m)
Definition: chan_dahdi.c:16326
ast_group_t group
Bitmapped groups this belongs to.
Definition: chan_dahdi.h:505
struct ast_mwi_subscriber * ast_mwi_subscribe_pool(const char *mailbox, stasis_subscription_cb callback, void *data)
Add an MWI state subscriber, and stasis subscription to the mailbox.
Definition: mwi.c:230
int dialtone_detect
Number of frames to watch for dialtone in incoming calls.
Definition: chan_dahdi.h:614
time_t guardtime
Definition: chan_dahdi.h:540
static snd_pcm_format_t format
Definition: chan_alsa.c:102
#define SS7_BLOCKED_MAINTENANCE
Definition: sig_ss7.h:74
int ast_active_channels(void)
returns number of active/allocated channels
Definition: channel.c:499
static int revert_fax_buffers(struct dahdi_pvt *p, struct ast_channel *ast)
Definition: chan_dahdi.c:5970
unsigned int inalarm
TRUE if in an alarm condition.
Definition: chan_dahdi.h:286
Persistant data storage (akin to *doze registry)
void ast_channel_tech_pvt_set(struct ast_channel *chan, void *value)
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application&#39;s arguments.
void sig_pri_cc_agent_req_rsp(struct ast_cc_agent *agent, enum ast_cc_agent_response_reason reason)
#define SIG_PRI_AOC_GRANT_D
Definition: sig_pri.h:54
int channel
Definition: chan_dahdi.h:538
static char mwimonitornotify[PATH_MAX]
Definition: chan_dahdi.c:600
static int unload_module(void)
Definition: chan_dahdi.c:17651
#define DLA_LOCK(lock)
Deadlock avoidance lock.
Definition: lock.h:427
unsigned char valid
TRUE if the number information is valid/present.
Definition: channel.h:298
int analog_dnd(struct analog_pvt *p, int flag)
Definition: sig_analog.c:4019
int sendcalleridafter
Send caller ID on FXS after this many rings. Set to 1 for US.
Definition: chan_dahdi.h:679
struct pri * pri
Definition: sig_pri.h:604
const struct ast_channel_tech * ast_channel_tech(const struct ast_channel *chan)
char number[64]
Definition: callerid.c:54
int sig_pri_is_alarm_ignored(struct sig_pri_span *pri)
sig_ss7_law
Definition: sig_ss7.h:88
General jitterbuffer configuration.
Definition: abstract_jb.h:69
int sig_pri_cc_agent_callee_available(struct ast_cc_agent *agent)
int ast_dsp_set_call_progress_zone(struct ast_dsp *dsp, char *zone)
Set zone for doing progress detection.
Definition: dsp.c:1879
void ast_channel_hangupcause_hash_set(struct ast_channel *chan, const struct ast_control_pvt_cause_code *cause_code, int datalen)
Sets the HANGUPCAUSE hash and optionally the SIP_CAUSE hash on the given channel. ...
Definition: channel.c:4391
static void my_answer_polarityswitch(void *pvt)
Definition: chan_dahdi.c:2621
ast_group_t callgroup
Bitmapped call groups this belongs to.
Definition: chan_dahdi.h:517
struct ast_channel * analog_request(struct analog_pvt *p, int *callwait, const struct ast_channel *requestor)
Definition: sig_analog.c:772
#define AST_LIN2MU(a)
Definition: ulaw.h:49
char dialdest[256]
Delayed dialing for E911. Overlap digits for ISDN.
Definition: chan_dahdi.h:658
unsigned int permcallwaiting
Definition: sig_analog.h:287
char mohinterpret[MAX_MUSICCLASS]
Definition: sig_pri.h:290
static void publish_channel_alarm(int channel, const char *alarm_txt)
Definition: chan_dahdi.c:7345
static void dahdi_close(int fd)
Definition: chan_dahdi.c:4133
static struct ast_channel * dahdi_new(struct dahdi_pvt *i, int state, int startpbx, int idx, int law, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, ast_callid callid)
Definition: chan_dahdi.c:9153
#define AST_CAUSE_CONGESTION
Definition: causes.h:152
void * ss7_linkset(void *data)
#define AST_TRANS_CAP_DIGITAL
Definition: transcap.h:35
#define LINKSET_FLAG_AUTOACM
Definition: sig_ss7.h:72
unsigned int mate
TRUE if TDD in MATE mode.
Definition: chan_dahdi.h:288
#define CANPROGRESSDETECT(p)
Definition: chan_dahdi.c:594
static int dahdi_digit_begin(struct ast_channel *ast, char digit)
Definition: chan_dahdi.c:4237
#define AST_MUTEX_DEFINE_STATIC(mutex)
Definition: lock.h:518
#define ast_register_application_xml(app, execute)
Register an application using XML documentation.
Definition: module.h:626
static int action_dahdidialoffhook(struct mansession *s, const struct message *m)
Definition: chan_dahdi.c:16372
unsigned char buf[READ_SIZE]
Definition: chan_dahdi.c:10708
unsigned int canpark
TRUE if support for call parking is enabled.
Definition: chan_dahdi.h:219
#define SIG_EM_E1
Definition: chan_dahdi.h:742
static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct ast_variable *v, int reload, int options)
Definition: chan_dahdi.c:17900
int ast_dsp_set_digitmode(struct ast_dsp *dsp, int digitmode)
Set digit mode.
Definition: dsp.c:1844
int channel
Definition: sig_pri.h:292
int fds[SIG_PRI_NUM_DCHANS]
Definition: sig_pri.h:459
int trunkgroup
Definition: sig_pri.h:560
#define RESULT_FAILURE
Definition: cli.h:42
struct distRingData ringnum[3]
Definition: chan_dahdi.h:70
static char * dahdi_set_swgain(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: chan_dahdi.c:16085
static void dahdi_lock_sub_owner(struct dahdi_pvt *pvt, int sub_idx)
Definition: chan_dahdi.c:3465
unsigned int pulsedial
TRUE if a pulsed digit was detected. (Pulse dial phone detected)
Definition: chan_dahdi.h:318
void pri_event_noalarm(struct sig_pri_span *pri, int index, int before_start_pri)
jack_status_t status
Definition: app_jack.c:146
struct dahdi_confinfo curconf
Definition: chan_dahdi.h:92
void ast_manager_publish_event(const char *type, int class_type, struct ast_json *obj)
Publish an event to AMI.
Definition: manager.c:1903
#define ast_app_separate_args(a, b, c, d)
char mohsuggest[MAX_MUSICCLASS]
Suggested music-on-hold class for peer channel to use for calls.
Definition: chan_dahdi.h:470
#define COLOR_MAGENTA
Definition: term.h:57
static int action_transferhangup(struct mansession *s, const struct message *m)
Definition: chan_dahdi.c:16349
#define CALLPROGRESS_FAX
Definition: chan_dahdi.c:561
Media Format Cache API.
#define ast_str_create(init_len)
Create a malloc&#39;ed dynamic length string.
Definition: strings.h:620
short word
unsigned int answeronpolarityswitch
Definition: sig_analog.h:280
#define ast_mutex_unlock(a)
Definition: lock.h:188
int callerid_feed(struct callerid_state *cid, unsigned char *ubuf, int samples, struct ast_format *codec)
Read samples into the state machine.
Definition: callerid.c:545
char begindigit
DTMF digit in progress. 0 when no digit in progress.
Definition: chan_dahdi.h:706
Configuration relating to call pickup.
static struct chans chans
#define AST_LIN2A(a)
Definition: alaw.h:50
#define AST_APP_ARG(name)
Define an application argument.
int ast_gen_cas(unsigned char *outbuf, int sas, int len, struct ast_format *codec)
Generate a CAS (CPE Alert Signal) tone for &#39;n&#39; samples.
Definition: callerid.c:261
char accountcode[AST_MAX_ACCOUNT_CODE]
Definition: chan_dahdi.h:645
#define CID_SIG_V23
Definition: callerid.h:60
int sig_pri_cc_agent_status_req(struct ast_cc_agent *agent)
void astman_send_listack(struct mansession *s, const struct message *m, char *msg, char *listflag)
Send ack in manager transaction to begin a list.
Definition: manager.c:3201
#define SUB_CALLWAIT
Definition: chan_dahdi.h:58
static struct test_val a
struct ast_party_number number
Subscriber phone number.
Definition: channel.h:343
int tdd_feed(struct tdd_state *tdd, unsigned char *ubuf, int samples)
Definition: tdd.c:161
#define ast_module_ref(mod)
Hold a reference to the module.
Definition: module.h:443
unsigned int mwimonitor_rpas
TRUE if the FXO port monitors for rpas precursor to fsk MWI indications from the other end...
Definition: chan_dahdi.h:386
void sig_ss7_cb_call_null(struct ss7 *ss7, struct isup_call *c, int lock)
unsigned int mwisendactive
TRUE if a MWI message sending thread is active.
Definition: chan_dahdi.h:390
#define max(a, b)
Definition: f2c.h:198